summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Isdale <keith.isdale@nokia.com>2010-07-26 14:56:53 +1000
committerKeith Isdale <keith.isdale@nokia.com>2010-07-26 14:56:53 +1000
commit9f034793bcfc51c2b7c1dd14db806f7258f9a9eb (patch)
tree63bd0f50ce5b77828ad8205eafd7b9412810499e
parent619d92cfef29e653bfdf852e83888e50cfc4348f (diff)
parent65271649dbc90f3af1184ad1b23bdb64c0c07d07 (diff)
Merge branch 'master' of git://git-nokia.trolltech.com.au/qtsoftware/research/qtuitest
-rw-r--r--botan/Makefile148
-rw-r--r--botan/botan.pri2
-rw-r--r--botan/botan.pro4
-rw-r--r--botan/build/botan/adler32.h35
-rw-r--r--botan/build/botan/aes.h81
-rw-r--r--botan/build/botan/alg_id.h49
-rw-r--r--botan/build/botan/algo_cache.h224
-rw-r--r--botan/build/botan/algo_factory.h132
-rw-r--r--botan/build/botan/allocate.h37
-rw-r--r--botan/build/botan/arc4.h41
-rw-r--r--botan/build/botan/asn1_int.h108
-rw-r--r--botan/build/botan/asn1_obj.h160
-rw-r--r--botan/build/botan/asn1_oid.h96
-rw-r--r--botan/build/botan/auto_rng.h44
-rw-r--r--botan/build/botan/base64.h94
-rw-r--r--botan/build/botan/basefilt.h99
-rw-r--r--botan/build/botan/benchmark.h59
-rw-r--r--botan/build/botan/ber_dec.h122
-rw-r--r--botan/build/botan/bigint.h534
-rw-r--r--botan/build/botan/bit_ops.h91
-rw-r--r--botan/build/botan/blinding.h34
-rw-r--r--botan/build/botan/block_cipher.h100
-rw-r--r--botan/build/botan/blowfish.h40
-rw-r--r--botan/build/botan/botan.h18
-rw-r--r--botan/build/botan/bswap.h62
-rw-r--r--botan/build/botan/buf_comp.h126
-rw-r--r--botan/build/botan/buf_filt.h39
-rw-r--r--botan/build/botan/build.h41
-rw-r--r--botan/build/botan/build_unix.h353
-rw-r--r--botan/build/botan/build_windows.h335
-rw-r--r--botan/build/botan/cast128.h47
-rw-r--r--botan/build/botan/cast256.h44
-rw-r--r--botan/build/botan/cbc.h55
-rw-r--r--botan/build/botan/cbc_mac.h40
-rw-r--r--botan/build/botan/certstor.h39
-rw-r--r--botan/build/botan/cfb.h47
-rw-r--r--botan/build/botan/charset.h44
-rw-r--r--botan/build/botan/cmac.h44
-rw-r--r--botan/build/botan/cms_dec.h65
-rw-r--r--botan/build/botan/cms_enc.h92
-rw-r--r--botan/build/botan/crc24.h34
-rw-r--r--botan/build/botan/crc32.h34
-rw-r--r--botan/build/botan/crl_ent.h78
-rw-r--r--botan/build/botan/cryptobox.h42
-rw-r--r--botan/build/botan/ctr.h31
-rw-r--r--botan/build/botan/cts.h60
-rw-r--r--botan/build/botan/curve_gfp.h177
-rw-r--r--botan/build/botan/cvc_ado.h101
-rw-r--r--botan/build/botan/cvc_ca.h51
-rw-r--r--botan/build/botan/cvc_cert.h94
-rw-r--r--botan/build/botan/cvc_gen_cert.h177
-rw-r--r--botan/build/botan/cvc_key.h54
-rw-r--r--botan/build/botan/cvc_req.h63
-rw-r--r--botan/build/botan/cvc_self.h167
-rw-r--r--botan/build/botan/data_snk.h65
-rw-r--r--botan/build/botan/data_src.h150
-rw-r--r--botan/build/botan/datastor.h61
-rw-r--r--botan/build/botan/def_eng.h83
-rw-r--r--botan/build/botan/def_powm.h64
-rw-r--r--botan/build/botan/defalloc.h43
-rw-r--r--botan/build/botan/der_enc.h91
-rw-r--r--botan/build/botan/des.h70
-rw-r--r--botan/build/botan/desx.h35
-rw-r--r--botan/build/botan/dh.h80
-rw-r--r--botan/build/botan/dh_core.h38
-rw-r--r--botan/build/botan/dh_op.h45
-rw-r--r--botan/build/botan/divide.h19
-rw-r--r--botan/build/botan/dl_algo.h116
-rw-r--r--botan/build/botan/dl_group.h162
-rw-r--r--botan/build/botan/dlies.h69
-rw-r--r--botan/build/botan/dsa.h62
-rw-r--r--botan/build/botan/dsa_core.h37
-rw-r--r--botan/build/botan/dsa_op.h53
-rw-r--r--botan/build/botan/eac_asn_obj.h244
-rw-r--r--botan/build/botan/eac_obj.h131
-rw-r--r--botan/build/botan/eax.h85
-rw-r--r--botan/build/botan/ec_dompar.h121
-rw-r--r--botan/build/botan/ecb.h73
-rw-r--r--botan/build/botan/ecc_key.h154
-rw-r--r--botan/build/botan/ecdsa.h145
-rw-r--r--botan/build/botan/ecdsa_core.h47
-rw-r--r--botan/build/botan/ecdsa_op.h64
-rw-r--r--botan/build/botan/ecdsa_sig.h88
-rw-r--r--botan/build/botan/eckaeg.h137
-rw-r--r--botan/build/botan/eckaeg_core.h44
-rw-r--r--botan/build/botan/eckaeg_op.h49
-rw-r--r--botan/build/botan/elg_core.h44
-rw-r--r--botan/build/botan/elg_op.h52
-rw-r--r--botan/build/botan/elgamal.h59
-rw-r--r--botan/build/botan/eme.h42
-rw-r--r--botan/build/botan/eme1.h45
-rw-r--r--botan/build/botan/eme_pkcs.h30
-rw-r--r--botan/build/botan/emsa.h36
-rw-r--r--botan/build/botan/emsa1.h41
-rw-r--r--botan/build/botan/emsa1_bsi.h32
-rw-r--r--botan/build/botan/emsa2.h41
-rw-r--r--botan/build/botan/emsa3.h65
-rw-r--r--botan/build/botan/emsa4.h43
-rw-r--r--botan/build/botan/emsa_raw.h34
-rw-r--r--botan/build/botan/engine.h140
-rw-r--r--botan/build/botan/entropy_src.h95
-rw-r--r--botan/build/botan/es_capi.h33
-rw-r--r--botan/build/botan/es_dev.h53
-rw-r--r--botan/build/botan/es_egd.h49
-rw-r--r--botan/build/botan/es_ftw.h42
-rw-r--r--botan/build/botan/es_unix.h39
-rw-r--r--botan/build/botan/es_win32.h27
-rw-r--r--botan/build/botan/exceptn.h197
-rw-r--r--botan/build/botan/fd_unix.h23
-rw-r--r--botan/build/botan/filter.h113
-rw-r--r--botan/build/botan/filters.h189
-rw-r--r--botan/build/botan/fork256.h35
-rw-r--r--botan/build/botan/freestore.h85
-rw-r--r--botan/build/botan/get_pbe.h33
-rw-r--r--botan/build/botan/gfp_element.h311
-rw-r--r--botan/build/botan/gfp_modulus.h127
-rw-r--r--botan/build/botan/gost_28147.h67
-rw-r--r--botan/build/botan/gost_3411.h41
-rw-r--r--botan/build/botan/has160.h35
-rw-r--r--botan/build/botan/hash.h52
-rw-r--r--botan/build/botan/hash_id.h24
-rw-r--r--botan/build/botan/hex.h90
-rw-r--r--botan/build/botan/hmac.h38
-rw-r--r--botan/build/botan/hmac_rng.h59
-rw-r--r--botan/build/botan/idea.h34
-rw-r--r--botan/build/botan/if_algo.h85
-rw-r--r--botan/build/botan/if_core.h45
-rw-r--r--botan/build/botan/if_op.h52
-rw-r--r--botan/build/botan/init.h41
-rw-r--r--botan/build/botan/kasumi.h36
-rw-r--r--botan/build/botan/kdf.h60
-rw-r--r--botan/build/botan/kdf1.h36
-rw-r--r--botan/build/botan/kdf2.h34
-rw-r--r--botan/build/botan/keypair.h47
-rw-r--r--botan/build/botan/libstate.h125
-rw-r--r--botan/build/botan/lion.h43
-rw-r--r--botan/build/botan/loadstor.h281
-rw-r--r--botan/build/botan/look_pk.h78
-rw-r--r--botan/build/botan/lookup.h239
-rw-r--r--botan/build/botan/lubyrack.h38
-rw-r--r--botan/build/botan/mac.h60
-rw-r--r--botan/build/botan/mars.h38
-rw-r--r--botan/build/botan/md2.h37
-rw-r--r--botan/build/botan/md4.h36
-rw-r--r--botan/build/botan/md5.h35
-rw-r--r--botan/build/botan/mdx_hash.h42
-rw-r--r--botan/build/botan/mem_ops.h40
-rw-r--r--botan/build/botan/mem_pool.h74
-rw-r--r--botan/build/botan/mgf1.h36
-rw-r--r--botan/build/botan/misty1.h35
-rw-r--r--botan/build/botan/mmap_mem.h30
-rw-r--r--botan/build/botan/mode_pad.h120
-rw-r--r--botan/build/botan/modebase.h39
-rw-r--r--botan/build/botan/mp_asm.h54
-rw-r--r--botan/build/botan/mp_asmi.h191
-rw-r--r--botan/build/botan/mp_core.h98
-rw-r--r--botan/build/botan/mp_types.h33
-rw-r--r--botan/build/botan/mutex.h56
-rw-r--r--botan/build/botan/mux_noop.h26
-rw-r--r--botan/build/botan/mux_pthr.h26
-rw-r--r--botan/build/botan/mux_win32.h26
-rw-r--r--botan/build/botan/noekeon.h37
-rw-r--r--botan/build/botan/nr.h63
-rw-r--r--botan/build/botan/nr_core.h37
-rw-r--r--botan/build/botan/nr_op.h53
-rw-r--r--botan/build/botan/numthry.h120
-rw-r--r--botan/build/botan/ofb.h33
-rw-r--r--botan/build/botan/oids.h58
-rw-r--r--botan/build/botan/openpgp.h34
-rw-r--r--botan/build/botan/out_buf.h43
-rw-r--r--botan/build/botan/par_hash.h36
-rw-r--r--botan/build/botan/parsing.h41
-rw-r--r--botan/build/botan/pbe.h56
-rw-r--r--botan/build/botan/pbes1.h53
-rw-r--r--botan/build/botan/pbes2.h53
-rw-r--r--botan/build/botan/pbkdf1.h44
-rw-r--r--botan/build/botan/pbkdf2.h40
-rw-r--r--botan/build/botan/pem.h35
-rw-r--r--botan/build/botan/pgp_s2k.h36
-rw-r--r--botan/build/botan/pipe.h275
-rw-r--r--botan/build/botan/pk_algs.h31
-rw-r--r--botan/build/botan/pk_engine.h95
-rw-r--r--botan/build/botan/pk_filts.h91
-rw-r--r--botan/build/botan/pk_keys.h180
-rw-r--r--botan/build/botan/pkcs10.h101
-rw-r--r--botan/build/botan/pkcs8.h177
-rw-r--r--botan/build/botan/point_gfp.h315
-rw-r--r--botan/build/botan/pow_mod.h93
-rw-r--r--botan/build/botan/prf_ssl3.h27
-rw-r--r--botan/build/botan/prf_tls.h34
-rw-r--r--botan/build/botan/prf_x942.h31
-rw-r--r--botan/build/botan/pubkey.h392
-rw-r--r--botan/build/botan/pubkey_enums.h77
-rw-r--r--botan/build/botan/randpool.h53
-rw-r--r--botan/build/botan/rc2.h37
-rw-r--r--botan/build/botan/rc5.h35
-rw-r--r--botan/build/botan/rc6.h35
-rw-r--r--botan/build/botan/reducer.h36
-rw-r--r--botan/build/botan/rmd128.h35
-rw-r--r--botan/build/botan/rmd160.h35
-rw-r--r--botan/build/botan/rng.h103
-rw-r--r--botan/build/botan/rotate.h30
-rw-r--r--botan/build/botan/rsa.h88
-rw-r--r--botan/build/botan/rw.h56
-rw-r--r--botan/build/botan/s2k.h102
-rw-r--r--botan/build/botan/safer_sk.h40
-rw-r--r--botan/build/botan/salsa20.h41
-rw-r--r--botan/build/botan/scan_name.h77
-rw-r--r--botan/build/botan/secmem.h438
-rw-r--r--botan/build/botan/secqueue.h43
-rw-r--r--botan/build/botan/seed.h43
-rw-r--r--botan/build/botan/selftest.h22
-rw-r--r--botan/build/botan/serpent.h35
-rw-r--r--botan/build/botan/sha160.h38
-rw-r--r--botan/build/botan/sha2_32.h59
-rw-r--r--botan/build/botan/sha2_64.h60
-rw-r--r--botan/build/botan/signed_obj.h93
-rw-r--r--botan/build/botan/skein_512.h41
-rw-r--r--botan/build/botan/skipjack.h38
-rw-r--r--botan/build/botan/square.h52
-rw-r--r--botan/build/botan/ssl3_mac.h39
-rw-r--r--botan/build/botan/stl_util.h86
-rw-r--r--botan/build/botan/stream_cipher.h92
-rw-r--r--botan/build/botan/sym_algo.h101
-rw-r--r--botan/build/botan/symkey.h62
-rw-r--r--botan/build/botan/tea.h34
-rw-r--r--botan/build/botan/tiger.h44
-rw-r--r--botan/build/botan/timer.h45
-rw-r--r--botan/build/botan/tm_posix.h27
-rw-r--r--botan/build/botan/tm_unix.h27
-rw-r--r--botan/build/botan/tm_win32.h27
-rw-r--r--botan/build/botan/turing.h47
-rw-r--r--botan/build/botan/twofish.h48
-rw-r--r--botan/build/botan/types.h42
-rw-r--r--botan/build/botan/ui.h36
-rw-r--r--botan/build/botan/unix_cmd.h59
-rw-r--r--botan/build/botan/util.h39
-rw-r--r--botan/build/botan/version.h61
-rw-r--r--botan/build/botan/whrlpool.h42
-rw-r--r--botan/build/botan/wid_wake.h41
-rw-r--r--botan/build/botan/x509_ca.h108
-rw-r--r--botan/build/botan/x509_crl.h90
-rw-r--r--botan/build/botan/x509_ext.h317
-rw-r--r--botan/build/botan/x509_key.h110
-rw-r--r--botan/build/botan/x509_obj.h67
-rw-r--r--botan/build/botan/x509cert.h185
-rw-r--r--botan/build/botan/x509find.h60
-rw-r--r--botan/build/botan/x509self.h198
-rw-r--r--botan/build/botan/x509stor.h143
-rw-r--r--botan/build/botan/x919_mac.h41
-rw-r--r--botan/build/botan/x931_rng.h45
-rw-r--r--botan/build/botan/xor_buf.h74
-rw-r--r--botan/build/botan/xtea.h34
-rw-r--r--botan/build/botan/xts.h76
-rw-r--r--botan/checks/algos.cpp105
-rw-r--r--botan/checks/bench.cpp198
-rw-r--r--botan/checks/bench.h37
-rw-r--r--botan/checks/bigint.cpp353
-rw-r--r--botan/checks/block.cpp98
-rw-r--r--botan/checks/check.cpp240
-rw-r--r--botan/checks/clock.cpp82
-rw-r--r--botan/checks/common.h100
-rw-r--r--botan/checks/cvc_tests.cpp600
-rw-r--r--botan/checks/dolook.cpp130
-rw-r--r--botan/checks/dolook2.cpp212
-rw-r--r--botan/checks/ec_tests.cpp1223
-rw-r--r--botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.crtbin0 -> 862 bytes
-rw-r--r--botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.pem20
-rw-r--r--botan/checks/ecc_testdata/DE1_flen_chars_cvcRequest_ECDSA.derbin0 -> 158 bytes
-rw-r--r--botan/checks/ecc_testdata/Lidia.cerbin0 -> 985 bytes
-rw-r--r--botan/checks/ecc_testdata/Lidia.pem23
-rw-r--r--botan/checks/ecc_testdata/adobin0 -> 353 bytes
-rw-r--r--botan/checks/ecc_testdata/ado.cvcreqbin0 -> 238 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_cvca.cerbin0 -> 392 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_dvca_ado2.cerbin0 -> 238 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_dvca_cert1.cerbin0 -> 212 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_dvca_req.cerbin0 -> 158 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_dvca_req2.cerbin0 -> 158 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_dvca_req2b.cerbin0 -> 158 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_is_cert.cerbin0 -> 210 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_is_req.cerbin0 -> 151 bytes
-rw-r--r--botan/checks/ecc_testdata/cvc_chain_link12.cerbin0 -> 392 bytes
-rw-r--r--botan/checks/ecc_testdata/cvca01.cv.crtbin0 -> 402 bytes
-rw-r--r--botan/checks/ecc_testdata/cvca_illegal_chars.cv.crtbin0 -> 402 bytes
-rw-r--r--botan/checks/ecc_testdata/cvca_illegal_chars2.cv.crtbin0 -> 402 bytes
-rw-r--r--botan/checks/ecc_testdata/ec_for_flex_mes.sig1
-rw-r--r--botan/checks/ecc_testdata/ec_oid_not_in_reg_private_2.pkcs8.pem7
-rw-r--r--botan/checks/ecc_testdata/flex_cert.crtbin0 -> 412 bytes
-rw-r--r--botan/checks/ecc_testdata/flex_mes1
-rw-r--r--botan/checks/ecc_testdata/flex_mes.sigbin0 -> 64 bytes
-rw-r--r--botan/checks/ecc_testdata/insito_expl_ec.pem19
-rw-r--r--botan/checks/ecc_testdata/insito_oid_ec.pem13
-rw-r--r--botan/checks/ecc_testdata/link_SHA1.166.crtbin0 -> 858 bytes
-rw-r--r--botan/checks/ecc_testdata/link_SHA256.cerbin0 -> 1790 bytes
-rw-r--r--botan/checks/ecc_testdata/my_cv_cert.berbin0 -> 286 bytes
-rw-r--r--botan/checks/ecc_testdata/my_cv_cert2.berbin0 -> 286 bytes
-rw-r--r--botan/checks/ecc_testdata/my_cv_req.berbin0 -> 238 bytes
-rw-r--r--botan/checks/ecc_testdata/nodompar_private.pkcs8.pem12
-rw-r--r--botan/checks/ecc_testdata/private.pem11
-rw-r--r--botan/checks/ecc_testdata/root1_SHA256.cerbin0 -> 1790 bytes
-rw-r--r--botan/checks/ecc_testdata/root2_SHA256.cerbin0 -> 1790 bytes
-rw-r--r--botan/checks/ecc_testdata/root_SHA1.163.crtbin0 -> 860 bytes
-rw-r--r--botan/checks/ecc_testdata/withdompar_private.pkcs8.pem5
-rw-r--r--botan/checks/ecc_testdata/x509_req_test_expl.pem19
-rw-r--r--botan/checks/ecc_testdata/x509_req_test_oid.pem12
-rw-r--r--botan/checks/ecc_testdata/x509_test_privkey_expl_pw123456.pem13
-rw-r--r--botan/checks/ecc_testdata/x509_test_privkey_oid_pw123456.pem13
-rw-r--r--botan/checks/ecdsa.cpp556
-rw-r--r--botan/checks/eckaeg.cpp286
-rw-r--r--botan/checks/fail.dat100
-rw-r--r--botan/checks/getopt.cpp85
-rw-r--r--botan/checks/getopt.h45
-rw-r--r--botan/checks/gfpmath.cpp818
-rw-r--r--botan/checks/misc.cpp77
-rw-r--r--botan/checks/mp_valid.dat2983
-rw-r--r--botan/checks/nist_tests/failure.txt12
-rw-r--r--botan/checks/nist_tests/readme.txt26
-rw-r--r--botan/checks/nist_tests/tests/test01/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test01/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test01/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test02/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test02/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test02/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test02/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test02/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test03/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test03/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test03/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test03/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test03/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/int1.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test04/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test05/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test05/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test05/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test05/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test05/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test06/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test06/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test06/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test06/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test06/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test07/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test07/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test07/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test07/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test07/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test08/end.crtbin0 -> 652 bytes
-rw-r--r--botan/checks/nist_tests/tests/test08/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test08/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test08/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test08/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test09/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test09/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test09/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test09/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test09/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test10/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test10/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test10/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test10/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test10/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test11/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test11/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test11/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test11/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test11/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test12/end.crtbin0 -> 652 bytes
-rw-r--r--botan/checks/nist_tests/tests/test12/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test12/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test12/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test12/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test13/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test13/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test13/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test13/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test13/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test14/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test14/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test14/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test14/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test14/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test15/end.crtbin0 -> 654 bytes
-rw-r--r--botan/checks/nist_tests/tests/test15/int.crlbin0 -> 341 bytes
-rw-r--r--botan/checks/nist_tests/tests/test15/int.crtbin0 -> 671 bytes
-rw-r--r--botan/checks/nist_tests/tests/test15/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test15/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test16/end.crtbin0 -> 657 bytes
-rw-r--r--botan/checks/nist_tests/tests/test16/int.crlbin0 -> 337 bytes
-rw-r--r--botan/checks/nist_tests/tests/test16/int.crtbin0 -> 667 bytes
-rw-r--r--botan/checks/nist_tests/tests/test16/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test16/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test17/end.crtbin0 -> 652 bytes
-rw-r--r--botan/checks/nist_tests/tests/test17/int.crlbin0 -> 337 bytes
-rw-r--r--botan/checks/nist_tests/tests/test17/int.crtbin0 -> 667 bytes
-rw-r--r--botan/checks/nist_tests/tests/test17/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test17/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test18/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test18/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test18/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test18/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test18/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test19/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test19/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test19/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test19/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test20/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test20/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test20/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test20/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test20/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test21/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test21/int.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test21/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test21/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test21/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test22/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test22/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test22/int.crtbin0 -> 648 bytes
-rw-r--r--botan/checks/nist_tests/tests/test22/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test22/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test23/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test23/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test23/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test23/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test23/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test24/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test24/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test24/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test24/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test24/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test25/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test25/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test25/int.crtbin0 -> 659 bytes
-rw-r--r--botan/checks/nist_tests/tests/test25/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test25/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test26/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test26/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test26/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test26/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test26/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test27/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test27/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test27/int.crtbin0 -> 659 bytes
-rw-r--r--botan/checks/nist_tests/tests/test27/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test27/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test28/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test28/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test28/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test28/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test28/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test29/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test29/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test29/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test29/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test29/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test30/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test30/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test30/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test30/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test30/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test31/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test31/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test31/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test31/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test31/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test32/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test32/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test32/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test32/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test32/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test33/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test33/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test33/int.crtbin0 -> 662 bytes
-rw-r--r--botan/checks/nist_tests/tests/test33/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test33/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test34/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test34/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test34/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test34/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test34/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test35/end.crtbin0 -> 626 bytes
-rw-r--r--botan/checks/nist_tests/tests/test35/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test35/int.crtbin0 -> 641 bytes
-rw-r--r--botan/checks/nist_tests/tests/test35/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test35/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/int1.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test36/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/int1.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test37/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/int1.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test38/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/end.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int1.crtbin0 -> 706 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int2.crtbin0 -> 691 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/int3.crtbin0 -> 678 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test39/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/end.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int1.crtbin0 -> 691 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int2.crtbin0 -> 678 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test40/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/end.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int1.crtbin0 -> 678 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test41/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int1.crtbin0 -> 691 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int2.crtbin0 -> 678 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test42/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/end.crtbin0 -> 626 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int1.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test43/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/end.crtbin0 -> 626 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int1.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test44/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/end.crtbin0 -> 626 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int1.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test45/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int1.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int2.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int3.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test46/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/end.crtbin0 -> 626 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int1.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int2.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int3.crtbin0 -> 679 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/int4.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test47/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test48/end.crtbin0 -> 650 bytes
-rw-r--r--botan/checks/nist_tests/tests/test48/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test48/int.crtbin0 -> 665 bytes
-rw-r--r--botan/checks/nist_tests/tests/test48/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test48/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test49/end.crtbin0 -> 663 bytes
-rw-r--r--botan/checks/nist_tests/tests/test49/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test49/int.crtbin0 -> 678 bytes
-rw-r--r--botan/checks/nist_tests/tests/test49/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test49/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test50/end.crtbin0 -> 645 bytes
-rw-r--r--botan/checks/nist_tests/tests/test50/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test50/int.crtbin0 -> 660 bytes
-rw-r--r--botan/checks/nist_tests/tests/test50/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test50/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test51/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test51/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test51/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test51/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test51/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test52/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test52/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test52/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test52/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test52/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test53/end.crtbin0 -> 677 bytes
-rw-r--r--botan/checks/nist_tests/tests/test53/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test53/int.crtbin0 -> 692 bytes
-rw-r--r--botan/checks/nist_tests/tests/test53/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test53/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/int2.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test54/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/end.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/int2.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test55/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test56/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test56/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test56/int.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test56/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test56/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test57/end.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test57/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test57/int.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test57/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test57/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test58/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/end.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test59/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/int4.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test60/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/end.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/int4.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test61/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/int4.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test62/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/end.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int1.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int1.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int2.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int3.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int3.crtbin0 -> 669 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int4.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/int4.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test63/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test64/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test64/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test64/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test64/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test64/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/int1.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/int2.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test65/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test66/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test66/int.crlbin0 -> 372 bytes
-rw-r--r--botan/checks/nist_tests/tests/test66/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test66/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test66/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/int1.crlbin0 -> 372 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test67/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/int1.crlbin0 -> 393 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/int1.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/int2.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test68/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test69/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test69/int.crlbin0 -> 393 bytes
-rw-r--r--botan/checks/nist_tests/tests/test69/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test69/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test69/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/int1.crlbin0 -> 393 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/int1.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/int2.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/int2.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test70/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test71/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test71/int.crlbin0 -> 393 bytes
-rw-r--r--botan/checks/nist_tests/tests/test71/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test71/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test71/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test72/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test72/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test72/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test72/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test72/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test73/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test73/int.crlbin0 -> 335 bytes
-rw-r--r--botan/checks/nist_tests/tests/test73/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test73/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test73/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test74/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test74/int.crlbin0 -> 337 bytes
-rw-r--r--botan/checks/nist_tests/tests/test74/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test74/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test74/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test75/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test75/int.crlbin0 -> 350 bytes
-rw-r--r--botan/checks/nist_tests/tests/test75/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test75/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test75/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/tests/test76/end.crtbin0 -> 651 bytes
-rw-r--r--botan/checks/nist_tests/tests/test76/int.crlbin0 -> 352 bytes
-rw-r--r--botan/checks/nist_tests/tests/test76/int.crtbin0 -> 666 bytes
-rw-r--r--botan/checks/nist_tests/tests/test76/root.crlbin0 -> 371 bytes
-rw-r--r--botan/checks/nist_tests/tests/test76/root.crtbin0 -> 624 bytes
-rw-r--r--botan/checks/nist_tests/x509test.cpp411
-rw-r--r--botan/checks/pk.cpp775
-rw-r--r--botan/checks/pk_bench.cpp682
-rw-r--r--botan/checks/pk_valid.dat4808
-rw-r--r--botan/checks/timer.cpp51
-rw-r--r--botan/checks/timer.h50
-rw-r--r--botan/checks/validate.cpp310
-rw-r--r--botan/checks/validate.dat45951
-rw-r--r--botan/checks/validate.h34
-rw-r--r--botan/checks/x509.cpp224
-rw-r--r--botan/configure.pl2340
-rw-r--r--botan/configure.py1122
-rw-r--r--botan/doc/api.pdfbin0 -> 254607 bytes
-rw-r--r--botan/doc/api.tex3103
-rw-r--r--botan/doc/architecture.pdfbin0 -> 463402 bytes
-rw-r--r--botan/doc/building.pdfbin0 -> 84582 bytes
-rw-r--r--botan/doc/building.tex398
-rw-r--r--botan/doc/credits.txt78
-rw-r--r--botan/doc/examples/GNUmakefile21
-rw-r--r--botan/doc/examples/asn1.cpp312
-rw-r--r--botan/doc/examples/base.cpp44
-rw-r--r--botan/doc/examples/base64.cpp82
-rw-r--r--botan/doc/examples/bench.cpp98
-rw-r--r--botan/doc/examples/benchmark.cpp41
-rw-r--r--botan/doc/examples/bzip.cpp108
-rw-r--r--botan/doc/examples/ca.cpp74
-rw-r--r--botan/doc/examples/checksum.cpp31
-rw-r--r--botan/doc/examples/cms_dec.cpp116
-rw-r--r--botan/doc/examples/cms_enc.cpp53
-rw-r--r--botan/doc/examples/cryptobox.cpp50
-rw-r--r--botan/doc/examples/decrypt.cpp158
-rw-r--r--botan/doc/examples/dh.cpp59
-rw-r--r--botan/doc/examples/dsa_kgen.cpp66
-rw-r--r--botan/doc/examples/dsa_sign.cpp83
-rw-r--r--botan/doc/examples/dsa_ver.cpp92
-rw-r--r--botan/doc/examples/eax_test.cpp241
-rw-r--r--botan/doc/examples/eax_tv.txt461
-rw-r--r--botan/doc/examples/ecdsa.cpp57
-rw-r--r--botan/doc/examples/encrypt.cpp179
-rw-r--r--botan/doc/examples/encrypt2.cpp55
-rw-r--r--botan/doc/examples/factor.cpp144
-rw-r--r--botan/doc/examples/gen_certs.cpp124
-rw-r--r--botan/doc/examples/gtk/dsa.cpp556
-rw-r--r--botan/doc/examples/gtk/gtk_ui.cpp78
-rw-r--r--botan/doc/examples/gtk/gtk_ui.h25
-rw-r--r--botan/doc/examples/gtk/readme.txt18
-rw-r--r--botan/doc/examples/hash.cpp64
-rw-r--r--botan/doc/examples/hash_fd.cpp71
-rw-r--r--botan/doc/examples/hash_quickly.cpp90
-rw-r--r--botan/doc/examples/hasher.cpp58
-rw-r--r--botan/doc/examples/hasher2.cpp72
-rw-r--r--botan/doc/examples/make_prime.cpp73
-rw-r--r--botan/doc/examples/passhash.cpp86
-rw-r--r--botan/doc/examples/pkcs10.cpp73
-rw-r--r--botan/doc/examples/pqg_gen.cpp116
-rw-r--r--botan/doc/examples/readme.txt77
-rw-r--r--botan/doc/examples/ressol.cpp80
-rw-r--r--botan/doc/examples/rng_test.cpp143
-rw-r--r--botan/doc/examples/row_encryptor.cpp143
-rw-r--r--botan/doc/examples/rsa_dec.cpp127
-rw-r--r--botan/doc/examples/rsa_enc.cpp151
-rw-r--r--botan/doc/examples/rsa_kgen.cpp65
-rw-r--r--botan/doc/examples/rsa_manykey.cpp36
-rw-r--r--botan/doc/examples/self_sig.cpp79
-rw-r--r--botan/doc/examples/sig_gen.cpp90
-rw-r--r--botan/doc/examples/stack.cpp86
-rw-r--r--botan/doc/examples/test_es.cpp115
-rw-r--r--botan/doc/examples/x509info.cpp154
-rw-r--r--botan/doc/examples/xor_ciph.cpp96
-rw-r--r--botan/doc/fips140.tex156
-rw-r--r--botan/doc/indent.el57
-rw-r--r--botan/doc/insito_manual.pdfbin0 -> 150405 bytes
-rw-r--r--botan/doc/internals.tex179
-rw-r--r--botan/doc/license.txt40
-rw-r--r--botan/doc/log.txt1323
-rw-r--r--botan/doc/pgpkeys.asc83
-rw-r--r--botan/doc/scripts/comba.py65
-rw-r--r--botan/doc/scripts/combine_bmarks.pl120
-rw-r--r--botan/doc/scripts/dist.sh64
-rw-r--r--botan/doc/scripts/primes.py63
-rw-r--r--botan/doc/scripts/print_deps.py70
-rw-r--r--botan/doc/scripts/update_deps.py41
-rw-r--r--botan/doc/thanks.txt49
-rw-r--r--botan/doc/tutorial.pdfbin0 -> 115992 bytes
-rw-r--r--botan/doc/tutorial.tex883
-rw-r--r--botan/readme.txt44
-rw-r--r--botan/src/Makefile1628
-rw-r--r--botan/src/algo_factory/algo_cache.h224
-rw-r--r--botan/src/algo_factory/algo_factory.cpp286
-rw-r--r--botan/src/algo_factory/algo_factory.h132
-rw-r--r--botan/src/algo_factory/info.txt21
-rw-r--r--botan/src/algo_factory/prov_weight.cpp33
-rw-r--r--botan/src/alloc/alloc_mmap/info.txt30
-rw-r--r--botan/src/alloc/alloc_mmap/mmap_mem.cpp124
-rw-r--r--botan/src/alloc/alloc_mmap/mmap_mem.h30
-rw-r--r--botan/src/alloc/allocate.h37
-rw-r--r--botan/src/alloc/info.txt8
-rw-r--r--botan/src/alloc/mem_pool/info.txt12
-rw-r--r--botan/src/alloc/mem_pool/mem_pool.cpp265
-rw-r--r--botan/src/alloc/mem_pool/mem_pool.h74
-rw-r--r--botan/src/alloc/secmem.h438
-rw-r--r--botan/src/alloc/system_alloc/defalloc.cpp100
-rw-r--r--botan/src/alloc/system_alloc/defalloc.h43
-rw-r--r--botan/src/alloc/system_alloc/info.txt13
-rw-r--r--botan/src/asn1/alg_id.cpp103
-rw-r--r--botan/src/asn1/alg_id.h49
-rw-r--r--botan/src/asn1/asn1_alt.cpp228
-rw-r--r--botan/src/asn1/asn1_att.cpp60
-rw-r--r--botan/src/asn1/asn1_dn.cpp304
-rw-r--r--botan/src/asn1/asn1_int.cpp68
-rw-r--r--botan/src/asn1/asn1_int.h108
-rw-r--r--botan/src/asn1/asn1_obj.h160
-rw-r--r--botan/src/asn1/asn1_oid.cpp176
-rw-r--r--botan/src/asn1/asn1_oid.h96
-rw-r--r--botan/src/asn1/asn1_str.cpp160
-rw-r--r--botan/src/asn1/asn1_tm.cpp297
-rw-r--r--botan/src/asn1/ber_dec.cpp471
-rw-r--r--botan/src/asn1/ber_dec.h122
-rw-r--r--botan/src/asn1/der_enc.cpp393
-rw-r--r--botan/src/asn1/der_enc.h91
-rw-r--r--botan/src/asn1/info.txt31
-rw-r--r--botan/src/benchmark/benchmark.cpp189
-rw-r--r--botan/src/benchmark/benchmark.h59
-rw-r--r--botan/src/benchmark/info.txt21
-rw-r--r--botan/src/block/aes/aes.cpp257
-rw-r--r--botan/src/block/aes/aes.h81
-rw-r--r--botan/src/block/aes/aes_tab.cpp406
-rw-r--r--botan/src/block/aes/info.txt11
-rw-r--r--botan/src/block/block_cipher.h100
-rw-r--r--botan/src/block/blowfish/blfs_tab.cpp190
-rw-r--r--botan/src/block/blowfish/blowfish.cpp125
-rw-r--r--botan/src/block/blowfish/blowfish.h40
-rw-r--r--botan/src/block/blowfish/info.txt11
-rw-r--r--botan/src/block/cast/cast128.cpp172
-rw-r--r--botan/src/block/cast/cast128.h47
-rw-r--r--botan/src/block/cast/cast256.cpp165
-rw-r--r--botan/src/block/cast/cast256.h44
-rw-r--r--botan/src/block/cast/cast_tab.cpp412
-rw-r--r--botan/src/block/cast/info.txt13
-rw-r--r--botan/src/block/des/des.cpp265
-rw-r--r--botan/src/block/des/des.h70
-rw-r--r--botan/src/block/des/des_tab.cpp636
-rw-r--r--botan/src/block/des/desx.cpp43
-rw-r--r--botan/src/block/des/desx.h35
-rw-r--r--botan/src/block/des/info.txt13
-rw-r--r--botan/src/block/gost_28147/gost_28147.cpp139
-rw-r--r--botan/src/block/gost_28147/gost_28147.h67
-rw-r--r--botan/src/block/gost_28147/info.txt10
-rw-r--r--botan/src/block/idea/idea.cpp174
-rw-r--r--botan/src/block/idea/idea.h34
-rw-r--r--botan/src/block/idea/info.txt10
-rw-r--r--botan/src/block/info.txt13
-rw-r--r--botan/src/block/kasumi/info.txt10
-rw-r--r--botan/src/block/kasumi/kasumi.cpp215
-rw-r--r--botan/src/block/kasumi/kasumi.h36
-rw-r--r--botan/src/block/lion/info.txt15
-rw-r--r--botan/src/block/lion/lion.cpp114
-rw-r--r--botan/src/block/lion/lion.h43
-rw-r--r--botan/src/block/lubyrack/info.txt14
-rw-r--r--botan/src/block/lubyrack/lubyrack.cpp116
-rw-r--r--botan/src/block/lubyrack/lubyrack.h38
-rw-r--r--botan/src/block/mars/info.txt11
-rw-r--r--botan/src/block/mars/mars.cpp276
-rw-r--r--botan/src/block/mars/mars.h38
-rw-r--r--botan/src/block/mars/mars_tab.cpp100
-rw-r--r--botan/src/block/misty1/info.txt10
-rw-r--r--botan/src/block/misty1/misty1.cpp249
-rw-r--r--botan/src/block/misty1/misty1.h35
-rw-r--r--botan/src/block/noekeon/info.txt10
-rw-r--r--botan/src/block/noekeon/noekeon.cpp198
-rw-r--r--botan/src/block/noekeon/noekeon.h37
-rw-r--r--botan/src/block/rc2/info.txt10
-rw-r--r--botan/src/block/rc2/rc2.cpp163
-rw-r--r--botan/src/block/rc2/rc2.h37
-rw-r--r--botan/src/block/rc5/info.txt10
-rw-r--r--botan/src/block/rc5/rc5.cpp103
-rw-r--r--botan/src/block/rc5/rc5.h35
-rw-r--r--botan/src/block/rc6/info.txt10
-rw-r--r--botan/src/block/rc6/rc6.cpp122
-rw-r--r--botan/src/block/rc6/rc6.h35
-rw-r--r--botan/src/block/safer/info.txt11
-rw-r--r--botan/src/block/safer/safe_tab.cpp121
-rw-r--r--botan/src/block/safer/safer_sk.cpp115
-rw-r--r--botan/src/block/safer/safer_sk.h40
-rw-r--r--botan/src/block/seed/info.txt11
-rw-r--r--botan/src/block/seed/seed.cpp127
-rw-r--r--botan/src/block/seed/seed.h43
-rw-r--r--botan/src/block/seed/seed_tab.cpp192
-rw-r--r--botan/src/block/serpent/info.txt10
-rw-r--r--botan/src/block/serpent/serpent.cpp369
-rw-r--r--botan/src/block/serpent/serpent.h35
-rw-r--r--botan/src/block/serpent_ia32/info.txt35
-rw-r--r--botan/src/block/serpent_ia32/serp_ia32.cpp51
-rw-r--r--botan/src/block/serpent_ia32/serp_ia32.h30
-rw-r--r--botan/src/block/serpent_ia32/serp_ia32_imp.S669
-rw-r--r--botan/src/block/skipjack/info.txt10
-rw-r--r--botan/src/block/skipjack/skipjack.cpp162
-rw-r--r--botan/src/block/skipjack/skipjack.h38
-rw-r--r--botan/src/block/square/info.txt11
-rw-r--r--botan/src/block/square/sqr_tab.cpp460
-rw-r--r--botan/src/block/square/square.cpp187
-rw-r--r--botan/src/block/square/square.h52
-rw-r--r--botan/src/block/tea/info.txt10
-rw-r--r--botan/src/block/tea/tea.cpp58
-rw-r--r--botan/src/block/tea/tea.h34
-rw-r--r--botan/src/block/twofish/info.txt11
-rw-r--r--botan/src/block/twofish/two_tab.cpp293
-rw-r--r--botan/src/block/twofish/twofish.cpp218
-rw-r--r--botan/src/block/twofish/twofish.h48
-rw-r--r--botan/src/block/xtea/info.txt10
-rw-r--r--botan/src/block/xtea/xtea.cpp64
-rw-r--r--botan/src/block/xtea/xtea.h34
-rw-r--r--botan/src/build-data/arch/alpha.txt31
-rw-r--r--botan/src/build-data/arch/amd64.txt27
-rw-r--r--botan/src/build-data/arch/arm.txt23
-rw-r--r--botan/src/build-data/arch/hitachi-sh.txt11
-rw-r--r--botan/src/build-data/arch/hppa.txt17
-rw-r--r--botan/src/build-data/arch/ia32.txt60
-rw-r--r--botan/src/build-data/arch/ia64.txt15
-rw-r--r--botan/src/build-data/arch/m68k.txt15
-rw-r--r--botan/src/build-data/arch/mips32.txt22
-rw-r--r--botan/src/build-data/arch/mips64.txt22
-rw-r--r--botan/src/build-data/arch/ppc.txt24
-rw-r--r--botan/src/build-data/arch/ppc64.txt26
-rw-r--r--botan/src/build-data/arch/s390.txt7
-rw-r--r--botan/src/build-data/arch/s390x.txt7
-rw-r--r--botan/src/build-data/arch/sparc32.txt34
-rw-r--r--botan/src/build-data/arch/sparc64.txt15
-rw-r--r--botan/src/build-data/botan-config.in69
-rw-r--r--botan/src/build-data/botan.doxy.in233
-rw-r--r--botan/src/build-data/botan.pc.in12
-rw-r--r--botan/src/build-data/buildh.in66
-rw-r--r--botan/src/build-data/cc/bcc.txt31
-rw-r--r--botan/src/build-data/cc/compaq.txt29
-rw-r--r--botan/src/build-data/cc/ekopath.txt40
-rw-r--r--botan/src/build-data/cc/gcc.txt89
-rw-r--r--botan/src/build-data/cc/hpcc.txt32
-rw-r--r--botan/src/build-data/cc/icc.txt35
-rw-r--r--botan/src/build-data/cc/kai.txt30
-rw-r--r--botan/src/build-data/cc/mipspro.txt42
-rw-r--r--botan/src/build-data/cc/msvc.txt27
-rw-r--r--botan/src/build-data/cc/open64.txt30
-rw-r--r--botan/src/build-data/cc/pgi.txt31
-rw-r--r--botan/src/build-data/cc/sgipro64.txt30
-rw-r--r--botan/src/build-data/cc/sunwspro.txt47
-rw-r--r--botan/src/build-data/cc/xlc.txt29
-rw-r--r--botan/src/build-data/makefile/nmake.in107
-rw-r--r--botan/src/build-data/makefile/unix.in121
-rw-r--r--botan/src/build-data/makefile/unix_shr.in137
-rw-r--r--botan/src/build-data/os/aix.txt7
-rw-r--r--botan/src/build-data/os/beos.txt16
-rw-r--r--botan/src/build-data/os/cygwin.txt13
-rw-r--r--botan/src/build-data/os/darwin.txt19
-rw-r--r--botan/src/build-data/os/defaults.txt19
-rw-r--r--botan/src/build-data/os/dragonfly.txt11
-rw-r--r--botan/src/build-data/os/freebsd.txt11
-rw-r--r--botan/src/build-data/os/hpux.txt13
-rw-r--r--botan/src/build-data/os/irix.txt7
-rw-r--r--botan/src/build-data/os/linux.txt12
-rw-r--r--botan/src/build-data/os/mingw.txt22
-rw-r--r--botan/src/build-data/os/netbsd.txt7
-rw-r--r--botan/src/build-data/os/openbsd.txt7
-rw-r--r--botan/src/build-data/os/qnx.txt7
-rw-r--r--botan/src/build-data/os/solaris.txt15
-rw-r--r--botan/src/build-data/os/tru64.txt11
-rw-r--r--botan/src/build-data/os/windows.txt26
-rw-r--r--botan/src/cert/cvc/asn1_eac_str.cpp130
-rw-r--r--botan/src/cert/cvc/asn1_eac_tm.cpp361
-rw-r--r--botan/src/cert/cvc/cvc_ado.cpp135
-rw-r--r--botan/src/cert/cvc/cvc_ado.h101
-rw-r--r--botan/src/cert/cvc/cvc_ca.cpp46
-rw-r--r--botan/src/cert/cvc/cvc_ca.h51
-rw-r--r--botan/src/cert/cvc/cvc_cert.cpp102
-rw-r--r--botan/src/cert/cvc/cvc_cert.h94
-rw-r--r--botan/src/cert/cvc/cvc_gen_cert.h177
-rw-r--r--botan/src/cert/cvc/cvc_key.h54
-rw-r--r--botan/src/cert/cvc/cvc_req.cpp68
-rw-r--r--botan/src/cert/cvc/cvc_req.h62
-rw-r--r--botan/src/cert/cvc/cvc_self.cpp327
-rw-r--r--botan/src/cert/cvc/cvc_self.h167
-rw-r--r--botan/src/cert/cvc/eac_asn_obj.h244
-rw-r--r--botan/src/cert/cvc/eac_obj.h131
-rw-r--r--botan/src/cert/cvc/ecdsa_sig.cpp64
-rw-r--r--botan/src/cert/cvc/ecdsa_sig.h88
-rw-r--r--botan/src/cert/cvc/freestore.h85
-rw-r--r--botan/src/cert/cvc/info.txt44
-rw-r--r--botan/src/cert/cvc/signed_obj.cpp67
-rw-r--r--botan/src/cert/cvc/signed_obj.h93
-rw-r--r--botan/src/cert/x509/certstor.cpp48
-rw-r--r--botan/src/cert/x509/certstor.h39
-rw-r--r--botan/src/cert/x509/crl_ent.cpp107
-rw-r--r--botan/src/cert/x509/crl_ent.h78
-rw-r--r--botan/src/cert/x509/info.txt45
-rw-r--r--botan/src/cert/x509/pkcs10.cpp200
-rw-r--r--botan/src/cert/x509/pkcs10.h101
-rw-r--r--botan/src/cert/x509/x509_ca.cpp284
-rw-r--r--botan/src/cert/x509/x509_ca.h108
-rw-r--r--botan/src/cert/x509/x509_crl.cpp147
-rw-r--r--botan/src/cert/x509/x509_crl.h90
-rw-r--r--botan/src/cert/x509/x509_ext.cpp581
-rw-r--r--botan/src/cert/x509/x509_ext.h317
-rw-r--r--botan/src/cert/x509/x509_obj.cpp235
-rw-r--r--botan/src/cert/x509/x509_obj.h67
-rw-r--r--botan/src/cert/x509/x509cert.cpp366
-rw-r--r--botan/src/cert/x509/x509cert.h185
-rw-r--r--botan/src/cert/x509/x509find.cpp111
-rw-r--r--botan/src/cert/x509/x509find.h60
-rw-r--r--botan/src/cert/x509/x509opt.cpp108
-rw-r--r--botan/src/cert/x509/x509self.cpp176
-rw-r--r--botan/src/cert/x509/x509self.h198
-rw-r--r--botan/src/cert/x509/x509stor.cpp695
-rw-r--r--botan/src/cert/x509/x509stor.h143
-rw-r--r--botan/src/checksum/adler32/adler32.cpp74
-rw-r--r--botan/src/checksum/adler32/adler32.h35
-rw-r--r--botan/src/checksum/adler32/info.txt14
-rw-r--r--botan/src/checksum/crc24/crc24.cpp100
-rw-r--r--botan/src/checksum/crc24/crc24.h34
-rw-r--r--botan/src/checksum/crc24/info.txt14
-rw-r--r--botan/src/checksum/crc32/crc32.cpp102
-rw-r--r--botan/src/checksum/crc32/crc32.h34
-rw-r--r--botan/src/checksum/crc32/info.txt14
-rw-r--r--botan/src/cms/cms_algo.cpp164
-rw-r--r--botan/src/cms/cms_comp.cpp107
-rw-r--r--botan/src/cms/cms_dalg.cpp276
-rw-r--r--botan/src/cms/cms_dec.cpp127
-rw-r--r--botan/src/cms/cms_dec.h65
-rw-r--r--botan/src/cms/cms_ealg.cpp401
-rw-r--r--botan/src/cms/cms_enc.cpp86
-rw-r--r--botan/src/cms/cms_enc.h92
-rw-r--r--botan/src/cms/info.txt31
-rw-r--r--botan/src/codec/base64/b64_char.cpp47
-rw-r--r--botan/src/codec/base64/base64.cpp228
-rw-r--r--botan/src/codec/base64/base64.h94
-rw-r--r--botan/src/codec/base64/info.txt15
-rw-r--r--botan/src/codec/bzip2/bzip2.cpp275
-rw-r--r--botan/src/codec/bzip2/bzip2.h61
-rw-r--r--botan/src/codec/bzip2/info.txt21
-rw-r--r--botan/src/codec/hex/hex.cpp191
-rw-r--r--botan/src/codec/hex/hex.h90
-rw-r--r--botan/src/codec/hex/hex_char.cpp48
-rw-r--r--botan/src/codec/hex/info.txt15
-rw-r--r--botan/src/codec/openpgp/info.txt15
-rw-r--r--botan/src/codec/openpgp/openpgp.cpp197
-rw-r--r--botan/src/codec/openpgp/openpgp.h34
-rw-r--r--botan/src/codec/pem/info.txt15
-rw-r--r--botan/src/codec/pem/pem.cpp143
-rw-r--r--botan/src/codec/pem/pem.h35
-rw-r--r--botan/src/codec/zlib/info.txt23
-rw-r--r--botan/src/codec/zlib/zlib.cpp287
-rw-r--r--botan/src/codec/zlib/zlib.h58
-rw-r--r--botan/src/cryptobox/cryptobox.cpp146
-rw-r--r--botan/src/cryptobox/cryptobox.h42
-rw-r--r--botan/src/cryptobox/info.txt22
-rw-r--r--botan/src/engine/amd64_eng/eng_amd64.cpp27
-rw-r--r--botan/src/engine/amd64_eng/eng_amd64.h26
-rw-r--r--botan/src/engine/amd64_eng/info.txt10
-rw-r--r--botan/src/engine/def_engine/def_eng.h83
-rw-r--r--botan/src/engine/def_engine/def_mode.cpp209
-rw-r--r--botan/src/engine/def_engine/def_pk_ops.cpp121
-rw-r--r--botan/src/engine/def_engine/def_powm.cpp24
-rw-r--r--botan/src/engine/def_engine/info.txt24
-rw-r--r--botan/src/engine/def_engine/lookup_block.cpp264
-rw-r--r--botan/src/engine/def_engine/lookup_hash.cpp209
-rw-r--r--botan/src/engine/def_engine/lookup_mac.cpp70
-rw-r--r--botan/src/engine/def_engine/lookup_stream.cpp61
-rw-r--r--botan/src/engine/engine.h140
-rw-r--r--botan/src/engine/gnump/eng_gmp.h57
-rw-r--r--botan/src/engine/gnump/gmp_dh.cpp53
-rw-r--r--botan/src/engine/gnump/gmp_dsa.cpp124
-rw-r--r--botan/src/engine/gnump/gmp_elg.cpp92
-rw-r--r--botan/src/engine/gnump/gmp_if.cpp81
-rw-r--r--botan/src/engine/gnump/gmp_mem.cpp70
-rw-r--r--botan/src/engine/gnump/gmp_nr.cpp107
-rw-r--r--botan/src/engine/gnump/gmp_powm.cpp53
-rw-r--r--botan/src/engine/gnump/gmp_wrap.cpp98
-rw-r--r--botan/src/engine/gnump/gmp_wrap.h38
-rw-r--r--botan/src/engine/gnump/info.txt26
-rw-r--r--botan/src/engine/ia32_eng/eng_ia32.cpp62
-rw-r--r--botan/src/engine/ia32_eng/eng_ia32.h29
-rw-r--r--botan/src/engine/ia32_eng/info.txt10
-rw-r--r--botan/src/engine/info.txt18
-rw-r--r--botan/src/engine/openssl/arc4_openssl.cpp82
-rw-r--r--botan/src/engine/openssl/bn_powm.cpp54
-rw-r--r--botan/src/engine/openssl/bn_wrap.cpp116
-rw-r--r--botan/src/engine/openssl/bn_wrap.h53
-rw-r--r--botan/src/engine/openssl/eng_ossl.h64
-rw-r--r--botan/src/engine/openssl/info.txt28
-rw-r--r--botan/src/engine/openssl/ossl_bc.cpp200
-rw-r--r--botan/src/engine/openssl/ossl_dh.cpp60
-rw-r--r--botan/src/engine/openssl/ossl_dsa.cpp126
-rw-r--r--botan/src/engine/openssl/ossl_elg.cpp95
-rw-r--r--botan/src/engine/openssl/ossl_if.cpp85
-rw-r--r--botan/src/engine/openssl/ossl_md.cpp126
-rw-r--r--botan/src/engine/openssl/ossl_nr.cpp113
-rw-r--r--botan/src/engine/sse2_eng/eng_sse2.cpp27
-rw-r--r--botan/src/engine/sse2_eng/eng_sse2.h26
-rw-r--r--botan/src/engine/sse2_eng/info.txt15
-rw-r--r--botan/src/entropy/beos_stats/es_beos.cpp65
-rw-r--r--botan/src/entropy/beos_stats/es_beos.h28
-rw-r--r--botan/src/entropy/beos_stats/info.txt19
-rw-r--r--botan/src/entropy/cryptoapi_rng/es_capi.cpp93
-rw-r--r--botan/src/entropy/cryptoapi_rng/es_capi.h33
-rw-r--r--botan/src/entropy/cryptoapi_rng/info.txt21
-rw-r--r--botan/src/entropy/dev_random/es_dev.cpp125
-rw-r--r--botan/src/entropy/dev_random/es_dev.h53
-rw-r--r--botan/src/entropy/dev_random/info.txt28
-rw-r--r--botan/src/entropy/egd/es_egd.cpp156
-rw-r--r--botan/src/entropy/egd/es_egd.h49
-rw-r--r--botan/src/entropy/egd/info.txt32
-rw-r--r--botan/src/entropy/entropy_src.h95
-rw-r--r--botan/src/entropy/info.txt11
-rw-r--r--botan/src/entropy/proc_walk/es_ftw.cpp146
-rw-r--r--botan/src/entropy/proc_walk/es_ftw.h42
-rw-r--r--botan/src/entropy/proc_walk/info.txt34
-rw-r--r--botan/src/entropy/unix_procs/es_unix.cpp114
-rw-r--r--botan/src/entropy/unix_procs/es_unix.h39
-rw-r--r--botan/src/entropy/unix_procs/info.txt33
-rw-r--r--botan/src/entropy/unix_procs/unix_cmd.cpp236
-rw-r--r--botan/src/entropy/unix_procs/unix_cmd.h59
-rw-r--r--botan/src/entropy/unix_procs/unix_src.cpp61
-rw-r--r--botan/src/entropy/win32_stats/es_win32.cpp118
-rw-r--r--botan/src/entropy/win32_stats/es_win32.h27
-rw-r--r--botan/src/entropy/win32_stats/info.txt24
-rw-r--r--botan/src/filters/algo_filt.cpp124
-rw-r--r--botan/src/filters/basefilt.cpp74
-rw-r--r--botan/src/filters/basefilt.h99
-rw-r--r--botan/src/filters/buf_filt.cpp71
-rw-r--r--botan/src/filters/buf_filt.h39
-rw-r--r--botan/src/filters/data_snk.cpp62
-rw-r--r--botan/src/filters/data_snk.h65
-rw-r--r--botan/src/filters/data_src.cpp207
-rw-r--r--botan/src/filters/data_src.h150
-rw-r--r--botan/src/filters/fd_unix/fd_unix.cpp53
-rw-r--r--botan/src/filters/fd_unix/fd_unix.h23
-rw-r--r--botan/src/filters/fd_unix/info.txt28
-rw-r--r--botan/src/filters/filter.cpp127
-rw-r--r--botan/src/filters/filter.h113
-rw-r--r--botan/src/filters/filters.h189
-rw-r--r--botan/src/filters/info.txt41
-rw-r--r--botan/src/filters/out_buf.cpp119
-rw-r--r--botan/src/filters/out_buf.h43
-rw-r--r--botan/src/filters/pbe.h56
-rw-r--r--botan/src/filters/pipe.cpp306
-rw-r--r--botan/src/filters/pipe.h275
-rw-r--r--botan/src/filters/pipe_io.cpp45
-rw-r--r--botan/src/filters/pipe_rw.cpp167
-rw-r--r--botan/src/filters/secqueue.cpp205
-rw-r--r--botan/src/filters/secqueue.h43
-rw-r--r--botan/src/hash/fork256/fork256.cpp149
-rw-r--r--botan/src/hash/fork256/fork256.h35
-rw-r--r--botan/src/hash/fork256/info.txt14
-rw-r--r--botan/src/hash/gost_3411/gost_3411.cpp236
-rw-r--r--botan/src/hash/gost_3411/gost_3411.h41
-rw-r--r--botan/src/hash/gost_3411/info.txt14
-rw-r--r--botan/src/hash/has160/has160.cpp159
-rw-r--r--botan/src/hash/has160/has160.h35
-rw-r--r--botan/src/hash/has160/info.txt14
-rw-r--r--botan/src/hash/hash.h52
-rw-r--r--botan/src/hash/info.txt11
-rw-r--r--botan/src/hash/md2/info.txt10
-rw-r--r--botan/src/hash/md2/md2.cpp108
-rw-r--r--botan/src/hash/md2/md2.h37
-rw-r--r--botan/src/hash/md4/info.txt14
-rw-r--r--botan/src/hash/md4/md4.cpp108
-rw-r--r--botan/src/hash/md4/md4.h36
-rw-r--r--botan/src/hash/md4_ia32/info.txt35
-rw-r--r--botan/src/hash/md4_ia32/md4_ia32.cpp27
-rw-r--r--botan/src/hash/md4_ia32/md4_ia32.h28
-rw-r--r--botan/src/hash/md4_ia32/md4_ia32_imp.S137
-rw-r--r--botan/src/hash/md5/info.txt14
-rw-r--r--botan/src/hash/md5/md5.cpp136
-rw-r--r--botan/src/hash/md5/md5.h35
-rw-r--r--botan/src/hash/md5_ia32/info.txt35
-rw-r--r--botan/src/hash/md5_ia32/md5_ia32.cpp32
-rw-r--r--botan/src/hash/md5_ia32/md5_ia32.h28
-rw-r--r--botan/src/hash/md5_ia32/md5_ia32_imp.S166
-rw-r--r--botan/src/hash/mdx_hash/info.txt10
-rw-r--r--botan/src/hash/mdx_hash/mdx_hash.cpp105
-rw-r--r--botan/src/hash/mdx_hash/mdx_hash.h42
-rw-r--r--botan/src/hash/par_hash/info.txt10
-rw-r--r--botan/src/hash/par_hash/par_hash.cpp103
-rw-r--r--botan/src/hash/par_hash/par_hash.h36
-rw-r--r--botan/src/hash/rmd128/info.txt14
-rw-r--r--botan/src/hash/rmd128/rmd128.cpp172
-rw-r--r--botan/src/hash/rmd128/rmd128.h35
-rw-r--r--botan/src/hash/rmd160/info.txt14
-rw-r--r--botan/src/hash/rmd160/rmd160.cpp210
-rw-r--r--botan/src/hash/rmd160/rmd160.h35
-rw-r--r--botan/src/hash/sha1/info.txt14
-rw-r--r--botan/src/hash/sha1/sha160.cpp162
-rw-r--r--botan/src/hash/sha1/sha160.h38
-rw-r--r--botan/src/hash/sha1_amd64/info.txt34
-rw-r--r--botan/src/hash/sha1_amd64/sha1_amd64.cpp31
-rw-r--r--botan/src/hash/sha1_amd64/sha1_amd64.h28
-rw-r--r--botan/src/hash/sha1_amd64/sha1_amd64_imp.S260
-rw-r--r--botan/src/hash/sha1_ia32/info.txt35
-rw-r--r--botan/src/hash/sha1_ia32/sha1_ia32.cpp32
-rw-r--r--botan/src/hash/sha1_ia32/sha1_ia32.h31
-rw-r--r--botan/src/hash/sha1_ia32/sha1_ia32_imp.S244
-rw-r--r--botan/src/hash/sha1_sse2/info.txt28
-rw-r--r--botan/src/hash/sha1_sse2/sha1_sse2.cpp24
-rw-r--r--botan/src/hash/sha1_sse2/sha1_sse2.h31
-rw-r--r--botan/src/hash/sha1_sse2/sha1_sse2_imp.cpp331
-rw-r--r--botan/src/hash/sha2/info.txt16
-rw-r--r--botan/src/hash/sha2/sha2_32.cpp193
-rw-r--r--botan/src/hash/sha2/sha2_32.h59
-rw-r--r--botan/src/hash/sha2/sha2_64.cpp208
-rw-r--r--botan/src/hash/sha2/sha2_64.h60
-rw-r--r--botan/src/hash/skein/info.txt14
-rw-r--r--botan/src/hash/skein/skein_512.cpp262
-rw-r--r--botan/src/hash/skein/skein_512.h41
-rw-r--r--botan/src/hash/tiger/info.txt15
-rw-r--r--botan/src/hash/tiger/tig_tab.cpp364
-rw-r--r--botan/src/hash/tiger/tiger.cpp164
-rw-r--r--botan/src/hash/tiger/tiger.h44
-rw-r--r--botan/src/hash/whirlpool/info.txt15
-rw-r--r--botan/src/hash/whirlpool/whrl_tab.cpp540
-rw-r--r--botan/src/hash/whirlpool/whrlpool.cpp146
-rw-r--r--botan/src/hash/whirlpool/whrlpool.h42
-rw-r--r--botan/src/kdf/info.txt14
-rw-r--r--botan/src/kdf/kdf.cpp68
-rw-r--r--botan/src/kdf/kdf.h60
-rw-r--r--botan/src/kdf/kdf1/info.txt14
-rw-r--r--botan/src/kdf/kdf1/kdf1.cpp24
-rw-r--r--botan/src/kdf/kdf1/kdf1.h36
-rw-r--r--botan/src/kdf/kdf2/info.txt14
-rw-r--r--botan/src/kdf/kdf2/kdf2.cpp41
-rw-r--r--botan/src/kdf/kdf2/kdf2.h34
-rw-r--r--botan/src/kdf/mgf1/info.txt14
-rw-r--r--botan/src/kdf/mgf1/mgf1.cpp58
-rw-r--r--botan/src/kdf/mgf1/mgf1.h36
-rw-r--r--botan/src/kdf/ssl_prf/info.txt16
-rw-r--r--botan/src/kdf/ssl_prf/prf_ssl3.cpp76
-rw-r--r--botan/src/kdf/ssl_prf/prf_ssl3.h27
-rw-r--r--botan/src/kdf/tls_prf/info.txt17
-rw-r--r--botan/src/kdf/tls_prf/prf_tls.cpp85
-rw-r--r--botan/src/kdf/tls_prf/prf_tls.h34
-rw-r--r--botan/src/kdf/x942_prf/info.txt16
-rw-r--r--botan/src/kdf/x942_prf/prf_x942.cpp91
-rw-r--r--botan/src/kdf/x942_prf/prf_x942.h31
-rw-r--r--botan/src/libstate/botan.h18
-rw-r--r--botan/src/libstate/get_enc.cpp238
-rw-r--r--botan/src/libstate/info.txt45
-rw-r--r--botan/src/libstate/init.cpp75
-rw-r--r--botan/src/libstate/init.h41
-rw-r--r--botan/src/libstate/libstate.cpp338
-rw-r--r--botan/src/libstate/libstate.h125
-rw-r--r--botan/src/libstate/look_pk.cpp76
-rw-r--r--botan/src/libstate/look_pk.h78
-rw-r--r--botan/src/libstate/lookup.cpp296
-rw-r--r--botan/src/libstate/lookup.h239
-rw-r--r--botan/src/libstate/oid_lookup/info.txt14
-rw-r--r--botan/src/libstate/oid_lookup/oids.cpp76
-rw-r--r--botan/src/libstate/oid_lookup/oids.h58
-rw-r--r--botan/src/libstate/pk_engine.cpp175
-rw-r--r--botan/src/libstate/pk_engine.h95
-rw-r--r--botan/src/libstate/policy.cpp511
-rw-r--r--botan/src/libstate/scan_name.cpp74
-rw-r--r--botan/src/libstate/scan_name.h77
-rw-r--r--botan/src/mac/cbc_mac/cbc_mac.cpp109
-rw-r--r--botan/src/mac/cbc_mac/cbc_mac.h40
-rw-r--r--botan/src/mac/cbc_mac/info.txt14
-rw-r--r--botan/src/mac/cmac/cmac.cpp162
-rw-r--r--botan/src/mac/cmac/cmac.h44
-rw-r--r--botan/src/mac/cmac/info.txt14
-rw-r--r--botan/src/mac/hmac/hmac.cpp99
-rw-r--r--botan/src/mac/hmac/hmac.h38
-rw-r--r--botan/src/mac/hmac/info.txt14
-rw-r--r--botan/src/mac/info.txt13
-rw-r--r--botan/src/mac/mac.cpp26
-rw-r--r--botan/src/mac/mac.h60
-rw-r--r--botan/src/mac/ssl3mac/info.txt14
-rw-r--r--botan/src/mac/ssl3mac/ssl3_mac.cpp90
-rw-r--r--botan/src/mac/ssl3mac/ssl3_mac.h39
-rw-r--r--botan/src/mac/x919_mac/info.txt14
-rw-r--r--botan/src/mac/x919_mac/x919_mac.cpp107
-rw-r--r--botan/src/mac/x919_mac/x919_mac.h41
-rw-r--r--botan/src/math/bigint/big_code.cpp154
-rw-r--r--botan/src/math/bigint/big_io.cpp55
-rw-r--r--botan/src/math/bigint/big_ops2.cpp224
-rw-r--r--botan/src/math/bigint/big_ops3.cpp190
-rw-r--r--botan/src/math/bigint/big_rand.cpp61
-rw-r--r--botan/src/math/bigint/bigint.cpp369
-rw-r--r--botan/src/math/bigint/bigint.h534
-rw-r--r--botan/src/math/bigint/divide.cpp106
-rw-r--r--botan/src/math/bigint/divide.h19
-rw-r--r--botan/src/math/bigint/info.txt33
-rw-r--r--botan/src/math/bigint/monty_amd64/info.txt32
-rw-r--r--botan/src/math/bigint/monty_amd64/mp_monty.S399
-rw-r--r--botan/src/math/bigint/monty_generic/info.txt7
-rw-r--r--botan/src/math/bigint/monty_generic/mp_monty.cpp78
-rw-r--r--botan/src/math/bigint/mp_amd64/info.txt19
-rw-r--r--botan/src/math/bigint/mp_amd64/mp_asm.h69
-rw-r--r--botan/src/math/bigint/mp_amd64/mp_asmi.h243
-rw-r--r--botan/src/math/bigint/mp_asm.cpp179
-rw-r--r--botan/src/math/bigint/mp_asm64/info.txt27
-rw-r--r--botan/src/math/bigint/mp_asm64/mp_asm.h119
-rw-r--r--botan/src/math/bigint/mp_comba.cpp920
-rw-r--r--botan/src/math/bigint/mp_core.h98
-rw-r--r--botan/src/math/bigint/mp_generic/info.txt8
-rw-r--r--botan/src/math/bigint/mp_generic/mp_asm.h54
-rw-r--r--botan/src/math/bigint/mp_generic/mp_asmi.h191
-rw-r--r--botan/src/math/bigint/mp_ia32/info.txt19
-rw-r--r--botan/src/math/bigint/mp_ia32/mp_asm.h67
-rw-r--r--botan/src/math/bigint/mp_ia32/mp_asmi.h235
-rw-r--r--botan/src/math/bigint/mp_ia32_msvc/info.txt18
-rw-r--r--botan/src/math/bigint/mp_ia32_msvc/mp_asmi.h528
-rw-r--r--botan/src/math/bigint/mp_karat.cpp336
-rw-r--r--botan/src/math/bigint/mp_misc.cpp94
-rw-r--r--botan/src/math/bigint/mp_shift.cpp138
-rw-r--r--botan/src/math/bigint/mp_types.h33
-rw-r--r--botan/src/math/bigint/mulop_amd64/info.txt32
-rw-r--r--botan/src/math/bigint/mulop_amd64/mp_mulop.cpp96
-rw-r--r--botan/src/math/bigint/mulop_amd64/mp_mulop_amd64.S130
-rw-r--r--botan/src/math/bigint/mulop_generic/info.txt7
-rw-r--r--botan/src/math/bigint/mulop_generic/mp_mulop.cpp77
-rw-r--r--botan/src/math/bigint/mulop_ia32/info.txt34
-rw-r--r--botan/src/math/bigint/mulop_ia32/mp_mulop.S64
-rw-r--r--botan/src/math/gfpmath/curve_gfp.cpp165
-rw-r--r--botan/src/math/gfpmath/curve_gfp.h177
-rw-r--r--botan/src/math/gfpmath/gfp_element.cpp699
-rw-r--r--botan/src/math/gfpmath/gfp_element.h311
-rw-r--r--botan/src/math/gfpmath/gfp_modulus.h127
-rw-r--r--botan/src/math/gfpmath/info.txt22
-rw-r--r--botan/src/math/gfpmath/point_gfp.cpp1154
-rw-r--r--botan/src/math/gfpmath/point_gfp.h315
-rw-r--r--botan/src/math/numbertheory/blinding.cpp49
-rw-r--r--botan/src/math/numbertheory/blinding.h34
-rw-r--r--botan/src/math/numbertheory/def_powm.h64
-rw-r--r--botan/src/math/numbertheory/dsa_gen.cpp135
-rw-r--r--botan/src/math/numbertheory/info.txt33
-rw-r--r--botan/src/math/numbertheory/jacobi.cpp53
-rw-r--r--botan/src/math/numbertheory/make_prm.cpp97
-rw-r--r--botan/src/math/numbertheory/mp_numth.cpp71
-rw-r--r--botan/src/math/numbertheory/numthry.cpp346
-rw-r--r--botan/src/math/numbertheory/numthry.h120
-rw-r--r--botan/src/math/numbertheory/pow_mod.cpp157
-rw-r--r--botan/src/math/numbertheory/pow_mod.h93
-rw-r--r--botan/src/math/numbertheory/powm_fw.cpp104
-rw-r--r--botan/src/math/numbertheory/powm_mnt.cpp180
-rw-r--r--botan/src/math/numbertheory/primes.cpp676
-rw-r--r--botan/src/math/numbertheory/reducer.cpp97
-rw-r--r--botan/src/math/numbertheory/reducer.h36
-rw-r--r--botan/src/math/numbertheory/ressol.cpp82
-rw-r--r--botan/src/modes/cbc/cbc.cpp158
-rw-r--r--botan/src/modes/cbc/cbc.h55
-rw-r--r--botan/src/modes/cbc/info.txt14
-rw-r--r--botan/src/modes/cfb/cfb.cpp143
-rw-r--r--botan/src/modes/cfb/cfb.h47
-rw-r--r--botan/src/modes/cfb/info.txt15
-rw-r--r--botan/src/modes/ctr/ctr.cpp75
-rw-r--r--botan/src/modes/ctr/ctr.h31
-rw-r--r--botan/src/modes/ctr/info.txt15
-rw-r--r--botan/src/modes/cts/cts.cpp134
-rw-r--r--botan/src/modes/cts/cts.h60
-rw-r--r--botan/src/modes/cts/info.txt14
-rw-r--r--botan/src/modes/eax/eax.cpp172
-rw-r--r--botan/src/modes/eax/eax.h85
-rw-r--r--botan/src/modes/eax/eax_dec.cpp127
-rw-r--r--botan/src/modes/eax/info.txt18
-rw-r--r--botan/src/modes/ecb/ecb.cpp105
-rw-r--r--botan/src/modes/ecb/ecb.h73
-rw-r--r--botan/src/modes/ecb/info.txt15
-rw-r--r--botan/src/modes/info.txt15
-rw-r--r--botan/src/modes/mode_pad/info.txt10
-rw-r--r--botan/src/modes/mode_pad/mode_pad.cpp128
-rw-r--r--botan/src/modes/mode_pad/mode_pad.h120
-rw-r--r--botan/src/modes/modebase.cpp54
-rw-r--r--botan/src/modes/modebase.h39
-rw-r--r--botan/src/modes/ofb/info.txt14
-rw-r--r--botan/src/modes/ofb/ofb.cpp66
-rw-r--r--botan/src/modes/ofb/ofb.h33
-rw-r--r--botan/src/modes/xts/info.txt15
-rw-r--r--botan/src/modes/xts/xts.cpp344
-rw-r--r--botan/src/modes/xts/xts.h76
-rw-r--r--botan/src/mutex/info.txt9
-rw-r--r--botan/src/mutex/mutex.h56
-rw-r--r--botan/src/mutex/noop_mutex/info.txt10
-rw-r--r--botan/src/mutex/noop_mutex/mux_noop.cpp50
-rw-r--r--botan/src/mutex/noop_mutex/mux_noop.h26
-rw-r--r--botan/src/mutex/pthreads/info.txt30
-rw-r--r--botan/src/mutex/pthreads/mux_pthr.cpp58
-rw-r--r--botan/src/mutex/pthreads/mux_pthr.h26
-rw-r--r--botan/src/mutex/qt_mutex/info.txt18
-rw-r--r--botan/src/mutex/qt_mutex/mux_qt.cpp35
-rw-r--r--botan/src/mutex/qt_mutex/mux_qt.h27
-rw-r--r--botan/src/mutex/win32_crit_section/info.txt17
-rw-r--r--botan/src/mutex/win32_crit_section/mux_win32.cpp34
-rw-r--r--botan/src/mutex/win32_crit_section/mux_win32.h26
-rw-r--r--botan/src/pbe/get_pbe.cpp130
-rw-r--r--botan/src/pbe/get_pbe.h33
-rw-r--r--botan/src/pbe/info.txt16
-rw-r--r--botan/src/pbe/pbes1/info.txt19
-rw-r--r--botan/src/pbe/pbes1/pbes1.cpp184
-rw-r--r--botan/src/pbe/pbes1/pbes1.h53
-rw-r--r--botan/src/pbe/pbes2/info.txt23
-rw-r--r--botan/src/pbe/pbes2/pbes2.cpp239
-rw-r--r--botan/src/pbe/pbes2/pbes2.h53
-rw-r--r--botan/src/pk_pad/eme.cpp50
-rw-r--r--botan/src/pk_pad/eme.h42
-rw-r--r--botan/src/pk_pad/eme1/eme1.cpp103
-rw-r--r--botan/src/pk_pad/eme1/eme1.h45
-rw-r--r--botan/src/pk_pad/eme1/info.txt16
-rw-r--r--botan/src/pk_pad/eme_pkcs/eme_pkcs.cpp70
-rw-r--r--botan/src/pk_pad/eme_pkcs/eme_pkcs.h30
-rw-r--r--botan/src/pk_pad/eme_pkcs/info.txt10
-rw-r--r--botan/src/pk_pad/emsa.h36
-rw-r--r--botan/src/pk_pad/emsa1/emsa1.cpp105
-rw-r--r--botan/src/pk_pad/emsa1/emsa1.h41
-rw-r--r--botan/src/pk_pad/emsa1/info.txt14
-rw-r--r--botan/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp29
-rw-r--r--botan/src/pk_pad/emsa1_bsi/emsa1_bsi.h32
-rw-r--r--botan/src/pk_pad/emsa1_bsi/info.txt14
-rw-r--r--botan/src/pk_pad/emsa2/emsa2.cpp112
-rw-r--r--botan/src/pk_pad/emsa2/emsa2.h41
-rw-r--r--botan/src/pk_pad/emsa2/info.txt15
-rw-r--r--botan/src/pk_pad/emsa3/emsa3.cpp152
-rw-r--r--botan/src/pk_pad/emsa3/emsa3.h65
-rw-r--r--botan/src/pk_pad/emsa3/info.txt15
-rw-r--r--botan/src/pk_pad/emsa4/emsa4.cpp143
-rw-r--r--botan/src/pk_pad/emsa4/emsa4.h43
-rw-r--r--botan/src/pk_pad/emsa4/info.txt16
-rw-r--r--botan/src/pk_pad/emsa_raw/emsa_raw.cpp50
-rw-r--r--botan/src/pk_pad/emsa_raw/emsa_raw.h34
-rw-r--r--botan/src/pk_pad/emsa_raw/info.txt10
-rw-r--r--botan/src/pk_pad/hash_id/hash_id.cpp116
-rw-r--r--botan/src/pk_pad/hash_id/hash_id.h24
-rw-r--r--botan/src/pk_pad/hash_id/info.txt14
-rw-r--r--botan/src/pk_pad/info.txt16
-rw-r--r--botan/src/pubkey/dh/dh.cpp119
-rw-r--r--botan/src/pubkey/dh/dh.h80
-rw-r--r--botan/src/pubkey/dh/dh_core.cpp69
-rw-r--r--botan/src/pubkey/dh/dh_core.h38
-rw-r--r--botan/src/pubkey/dh/dh_op.h45
-rw-r--r--botan/src/pubkey/dh/info.txt20
-rw-r--r--botan/src/pubkey/dl_algo/dl_algo.cpp167
-rw-r--r--botan/src/pubkey/dl_algo/dl_algo.h116
-rw-r--r--botan/src/pubkey/dl_algo/info.txt18
-rw-r--r--botan/src/pubkey/dl_group/dl_group.cpp333
-rw-r--r--botan/src/pubkey/dl_group/dl_group.h162
-rw-r--r--botan/src/pubkey/dl_group/info.txt19
-rw-r--r--botan/src/pubkey/dlies/dlies.cpp137
-rw-r--r--botan/src/pubkey/dlies/dlies.h69
-rw-r--r--botan/src/pubkey/dlies/info.txt16
-rw-r--r--botan/src/pubkey/dsa/dsa.cpp134
-rw-r--r--botan/src/pubkey/dsa/dsa.h62
-rw-r--r--botan/src/pubkey/dsa/dsa_core.cpp63
-rw-r--r--botan/src/pubkey/dsa/dsa_core.h37
-rw-r--r--botan/src/pubkey/dsa/dsa_op.cpp73
-rw-r--r--botan/src/pubkey/dsa/dsa_op.h53
-rw-r--r--botan/src/pubkey/dsa/info.txt22
-rw-r--r--botan/src/pubkey/ec_dompar/ec_dompar.cpp573
-rw-r--r--botan/src/pubkey/ec_dompar/ec_dompar.h121
-rw-r--r--botan/src/pubkey/ec_dompar/info.txt18
-rw-r--r--botan/src/pubkey/ecc_key/ecc_key.cpp269
-rw-r--r--botan/src/pubkey/ecc_key/ecc_key.h154
-rw-r--r--botan/src/pubkey/ecc_key/info.txt20
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa.cpp230
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa.h145
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa_core.cpp55
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa_core.h47
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa_op.cpp129
-rw-r--r--botan/src/pubkey/ecdsa/ecdsa_op.h64
-rw-r--r--botan/src/pubkey/ecdsa/info.txt25
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg.cpp152
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg.h137
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg_core.cpp59
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg_core.h44
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg_op.cpp36
-rw-r--r--botan/src/pubkey/eckaeg/eckaeg_op.h49
-rw-r--r--botan/src/pubkey/eckaeg/info.txt24
-rw-r--r--botan/src/pubkey/elgamal/elg_core.cpp97
-rw-r--r--botan/src/pubkey/elgamal/elg_core.h44
-rw-r--r--botan/src/pubkey/elgamal/elg_op.cpp56
-rw-r--r--botan/src/pubkey/elgamal/elg_op.h52
-rw-r--r--botan/src/pubkey/elgamal/elgamal.cpp124
-rw-r--r--botan/src/pubkey/elgamal/elgamal.h59
-rw-r--r--botan/src/pubkey/elgamal/info.txt22
-rw-r--r--botan/src/pubkey/if_algo/if_algo.cpp215
-rw-r--r--botan/src/pubkey/if_algo/if_algo.h85
-rw-r--r--botan/src/pubkey/if_algo/if_core.cpp87
-rw-r--r--botan/src/pubkey/if_algo/if_core.h45
-rw-r--r--botan/src/pubkey/if_algo/if_op.cpp47
-rw-r--r--botan/src/pubkey/if_algo/if_op.h52
-rw-r--r--botan/src/pubkey/if_algo/info.txt22
-rw-r--r--botan/src/pubkey/info.txt30
-rw-r--r--botan/src/pubkey/keypair/info.txt14
-rw-r--r--botan/src/pubkey/keypair/keypair.cpp73
-rw-r--r--botan/src/pubkey/keypair/keypair.h47
-rw-r--r--botan/src/pubkey/nr/info.txt22
-rw-r--r--botan/src/pubkey/nr/nr.cpp134
-rw-r--r--botan/src/pubkey/nr/nr.h63
-rw-r--r--botan/src/pubkey/nr/nr_core.cpp62
-rw-r--r--botan/src/pubkey/nr/nr_core.h37
-rw-r--r--botan/src/pubkey/nr/nr_op.cpp71
-rw-r--r--botan/src/pubkey/nr/nr_op.h53
-rw-r--r--botan/src/pubkey/pk_algs.cpp112
-rw-r--r--botan/src/pubkey/pk_algs.h31
-rw-r--r--botan/src/pubkey/pk_codecs/info.txt18
-rw-r--r--botan/src/pubkey/pk_codecs/pkcs8.cpp313
-rw-r--r--botan/src/pubkey/pk_codecs/pkcs8.h177
-rw-r--r--botan/src/pubkey/pk_codecs/x509_key.cpp176
-rw-r--r--botan/src/pubkey/pk_codecs/x509_key.h110
-rw-r--r--botan/src/pubkey/pk_filts.cpp115
-rw-r--r--botan/src/pubkey/pk_filts.h91
-rw-r--r--botan/src/pubkey/pk_keys.cpp54
-rw-r--r--botan/src/pubkey/pk_keys.h180
-rw-r--r--botan/src/pubkey/pubkey.cpp396
-rw-r--r--botan/src/pubkey/pubkey.h392
-rw-r--r--botan/src/pubkey/pubkey_enums.cpp42
-rw-r--r--botan/src/pubkey/pubkey_enums.h77
-rw-r--r--botan/src/pubkey/rsa/info.txt17
-rw-r--r--botan/src/pubkey/rsa/rsa.cpp164
-rw-r--r--botan/src/pubkey/rsa/rsa.h88
-rw-r--r--botan/src/pubkey/rw/info.txt17
-rw-r--r--botan/src/pubkey/rw/rw.cpp148
-rw-r--r--botan/src/pubkey/rw/rw.h56
-rw-r--r--botan/src/rng/auto_rng/auto_rng.cpp158
-rw-r--r--botan/src/rng/auto_rng/auto_rng.h44
-rw-r--r--botan/src/rng/auto_rng/info.txt16
-rw-r--r--botan/src/rng/hmac_rng/hmac_rng.cpp223
-rw-r--r--botan/src/rng/hmac_rng/hmac_rng.h59
-rw-r--r--botan/src/rng/hmac_rng/info.txt14
-rw-r--r--botan/src/rng/info.txt12
-rw-r--r--botan/src/rng/randpool/info.txt15
-rw-r--r--botan/src/rng/randpool/randpool.cpp214
-rw-r--r--botan/src/rng/randpool/randpool.h53
-rw-r--r--botan/src/rng/rng.cpp38
-rw-r--r--botan/src/rng/rng.h103
-rw-r--r--botan/src/rng/x931_rng/info.txt14
-rw-r--r--botan/src/rng/x931_rng/x931_rng.cpp154
-rw-r--r--botan/src/rng/x931_rng/x931_rng.h45
-rw-r--r--botan/src/s2k/info.txt13
-rw-r--r--botan/src/s2k/pbkdf1/info.txt14
-rw-r--r--botan/src/s2k/pbkdf1/pbkdf1.cpp55
-rw-r--r--botan/src/s2k/pbkdf1/pbkdf1.h44
-rw-r--r--botan/src/s2k/pbkdf2/info.txt14
-rw-r--r--botan/src/s2k/pbkdf2/pbkdf2.cpp82
-rw-r--r--botan/src/s2k/pbkdf2/pbkdf2.h40
-rw-r--r--botan/src/s2k/pgps2k/info.txt14
-rw-r--r--botan/src/s2k/pgps2k/pgp_s2k.cpp74
-rw-r--r--botan/src/s2k/pgps2k/pgp_s2k.h36
-rw-r--r--botan/src/s2k/s2k.cpp55
-rw-r--r--botan/src/s2k/s2k.h102
-rw-r--r--botan/src/selftest/info.txt21
-rw-r--r--botan/src/selftest/selftest.cpp184
-rw-r--r--botan/src/selftest/selftest.h22
-rw-r--r--botan/src/src.pro573
-rw-r--r--botan/src/stream/arc4/arc4.cpp105
-rw-r--r--botan/src/stream/arc4/arc4.h41
-rw-r--r--botan/src/stream/arc4/info.txt14
-rw-r--r--botan/src/stream/info.txt14
-rw-r--r--botan/src/stream/salsa20/info.txt14
-rw-r--r--botan/src/stream/salsa20/salsa20.cpp217
-rw-r--r--botan/src/stream/salsa20/salsa20.h41
-rw-r--r--botan/src/stream/stream_cipher.cpp30
-rw-r--r--botan/src/stream/stream_cipher.h92
-rw-r--r--botan/src/stream/turing/info.txt15
-rw-r--r--botan/src/stream/turing/tur_tab.cpp81
-rw-r--r--botan/src/stream/turing/turing.cpp307
-rw-r--r--botan/src/stream/turing/turing.h47
-rw-r--r--botan/src/stream/wid_wake/info.txt14
-rw-r--r--botan/src/stream/wid_wake/wid_wake.cpp147
-rw-r--r--botan/src/stream/wid_wake/wid_wake.h41
-rw-r--r--botan/src/sym_algo/info.txt16
-rw-r--r--botan/src/sym_algo/sym_algo.h101
-rw-r--r--botan/src/sym_algo/symkey.cpp141
-rw-r--r--botan/src/sym_algo/symkey.h62
-rw-r--r--botan/src/timer/cpu_counter/info.txt36
-rw-r--r--botan/src/timer/cpu_counter/tm_hard.cpp51
-rw-r--r--botan/src/timer/cpu_counter/tm_hard.h33
-rw-r--r--botan/src/timer/gettimeofday/info.txt33
-rw-r--r--botan/src/timer/gettimeofday/tm_unix.cpp24
-rw-r--r--botan/src/timer/gettimeofday/tm_unix.h27
-rw-r--r--botan/src/timer/info.txt14
-rw-r--r--botan/src/timer/posix_rt/info.txt29
-rw-r--r--botan/src/timer/posix_rt/tm_posix.cpp33
-rw-r--r--botan/src/timer/posix_rt/tm_posix.h27
-rw-r--r--botan/src/timer/timer.cpp52
-rw-r--r--botan/src/timer/timer.h45
-rw-r--r--botan/src/timer/win32_query_perf_ctr/info.txt26
-rw-r--r--botan/src/timer/win32_query_perf_ctr/tm_win32.cpp23
-rw-r--r--botan/src/timer/win32_query_perf_ctr/tm_win32.h27
-rw-r--r--botan/src/utils/asm_amd64/asm_macr.h127
-rw-r--r--botan/src/utils/asm_amd64/info.txt16
-rw-r--r--botan/src/utils/asm_ia32/asm_macr.h128
-rw-r--r--botan/src/utils/asm_ia32/info.txt16
-rw-r--r--botan/src/utils/bit_ops.h91
-rw-r--r--botan/src/utils/bswap.h62
-rw-r--r--botan/src/utils/buf_comp/buf_comp.h126
-rw-r--r--botan/src/utils/buf_comp/info.txt11
-rw-r--r--botan/src/utils/charset.cpp201
-rw-r--r--botan/src/utils/charset.h44
-rw-r--r--botan/src/utils/datastor/datastor.cpp172
-rw-r--r--botan/src/utils/datastor/datastor.h61
-rw-r--r--botan/src/utils/datastor/info.txt13
-rw-r--r--botan/src/utils/exceptn.cpp62
-rw-r--r--botan/src/utils/exceptn.h197
-rw-r--r--botan/src/utils/info.txt33
-rw-r--r--botan/src/utils/loadstor.h281
-rw-r--r--botan/src/utils/mem_ops.h40
-rw-r--r--botan/src/utils/mlock.cpp55
-rw-r--r--botan/src/utils/parsing.cpp288
-rw-r--r--botan/src/utils/parsing.h41
-rw-r--r--botan/src/utils/rotate.h30
-rw-r--r--botan/src/utils/stl_util.h86
-rw-r--r--botan/src/utils/types.h42
-rw-r--r--botan/src/utils/ui.cpp36
-rw-r--r--botan/src/utils/ui.h36
-rw-r--r--botan/src/utils/util.cpp68
-rw-r--r--botan/src/utils/util.h39
-rw-r--r--botan/src/utils/version.cpp36
-rw-r--r--botan/src/utils/version.h61
-rw-r--r--botan/src/utils/xor_buf.h74
-rw-r--r--botan/wrappers/boost-python/botan/__init__.py27
-rw-r--r--botan/wrappers/boost-python/nisttest.py61
-rw-r--r--botan/wrappers/boost-python/results.txt60
-rw-r--r--botan/wrappers/boost-python/rng_test.py22
-rw-r--r--botan/wrappers/boost-python/src/block.cpp152
-rw-r--r--botan/wrappers/boost-python/src/core.cpp73
-rw-r--r--botan/wrappers/boost-python/src/filter.cpp176
-rw-r--r--botan/wrappers/boost-python/src/hash.cpp108
-rw-r--r--botan/wrappers/boost-python/src/macs.cpp59
-rw-r--r--botan/wrappers/boost-python/src/pk.cpp125
-rw-r--r--botan/wrappers/boost-python/src/python_botan.h54
-rw-r--r--botan/wrappers/boost-python/src/stream.cpp54
-rw-r--r--botan/wrappers/boost-python/src/x509.cpp140
-rw-r--r--botan/wrappers/perl-xs/Botan.pm117
-rw-r--r--botan/wrappers/perl-xs/Botan.xs829
-rw-r--r--botan/wrappers/perl-xs/Changes4
-rw-r--r--botan/wrappers/perl-xs/MANIFEST15
-rw-r--r--botan/wrappers/perl-xs/data/ca.cert.derbin0 -> 712 bytes
-rw-r--r--botan/wrappers/perl-xs/data/ca.cert.pem17
-rw-r--r--botan/wrappers/perl-xs/t/base64.t273
-rw-r--r--botan/wrappers/perl-xs/t/filt.t56
-rw-r--r--botan/wrappers/perl-xs/t/hex.t256
-rw-r--r--botan/wrappers/perl-xs/t/oid.t45
-rw-r--r--botan/wrappers/perl-xs/t/pipe.t98
-rw-r--r--botan/wrappers/perl-xs/t/testutl.pl26
-rw-r--r--botan/wrappers/perl-xs/t/x509cert.t42
-rw-r--r--botan/wrappers/perl-xs/typemap62
-rw-r--r--botan/wrappers/swig/base.cpp61
-rw-r--r--botan/wrappers/swig/base.h102
-rw-r--r--botan/wrappers/swig/botan.swg26
-rw-r--r--botan/wrappers/swig/doit.py49
-rw-r--r--botan/wrappers/swig/filter.cpp39
-rw-r--r--botan/wrappers/swig/pipe.cpp89
-rw-r--r--botan/wrappers/swig/pk.swg8
-rw-r--r--botan/wrappers/swig/readme.txt34
-rw-r--r--botan/wrappers/swig/tests/block.py52
-rw-r--r--botan/wrappers/swig/tests/block2.py44
-rw-r--r--botan/wrappers/swig/tests/encrypt.py37
-rw-r--r--botan/wrappers/swig/tests/filter.py27
-rw-r--r--botan/wrappers/swig/tests/hash.py30
-rw-r--r--botan/wrappers/swig/tests/mac.py12
-rw-r--r--botan/wrappers/swig/tests/pubkey.py10
-rw-r--r--botan/wrappers/swig/tests/stream.py17
-rw-r--r--botan/wrappers/swig/x509.swg9
-rw-r--r--coreplugin/core_global.h41
-rw-r--r--coreplugin/ssh/sftpchannel.cpp899
-rw-r--r--coreplugin/ssh/sftpchannel.h122
-rw-r--r--coreplugin/ssh/sftpchannel_p.h132
-rw-r--r--coreplugin/ssh/sftpdefs.cpp32
-rw-r--r--coreplugin/ssh/sftpdefs.h48
-rw-r--r--coreplugin/ssh/sftpincomingpacket.cpp230
-rw-r--r--coreplugin/ssh/sftpincomingpacket_p.h111
-rw-r--r--coreplugin/ssh/sftpoperation.cpp183
-rw-r--r--coreplugin/ssh/sftpoperation_p.h228
-rw-r--r--coreplugin/ssh/sftpoutgoingpacket.cpp202
-rw-r--r--coreplugin/ssh/sftpoutgoingpacket_p.h83
-rw-r--r--coreplugin/ssh/sftppacket.cpp54
-rw-r--r--coreplugin/ssh/sftppacket_p.h108
-rw-r--r--coreplugin/ssh/sshbotanconversions_p.h97
-rw-r--r--coreplugin/ssh/sshcapabilities.cpp103
-rw-r--r--coreplugin/ssh/sshcapabilities_p.h72
-rw-r--r--coreplugin/ssh/sshchannel.cpp244
-rw-r--r--coreplugin/ssh/sshchannel_p.h111
-rw-r--r--coreplugin/ssh/sshchannelmanager.cpp188
-rw-r--r--coreplugin/ssh/sshchannelmanager_p.h89
-rw-r--r--coreplugin/ssh/sshconnection.cpp561
-rw-r--r--coreplugin/ssh/sshconnection.h111
-rw-r--r--coreplugin/ssh/sshconnection_p.h157
-rw-r--r--coreplugin/ssh/sshcryptofacility.cpp369
-rw-r--r--coreplugin/ssh/sshcryptofacility_p.h154
-rw-r--r--coreplugin/ssh/sshdelayedsignal.cpp165
-rw-r--r--coreplugin/ssh/sshdelayedsignal_p.h190
-rw-r--r--coreplugin/ssh/ssherrors.h43
-rw-r--r--coreplugin/ssh/sshexception_p.h89
-rw-r--r--coreplugin/ssh/sshincomingpacket.cpp442
-rw-r--r--coreplugin/ssh/sshincomingpacket_p.h186
-rw-r--r--coreplugin/ssh/sshkeyexchange.cpp197
-rw-r--r--coreplugin/ssh/sshkeyexchange_p.h87
-rw-r--r--coreplugin/ssh/sshkeygenerator.cpp139
-rw-r--r--coreplugin/ssh/sshkeygenerator.h75
-rw-r--r--coreplugin/ssh/sshoutgoingpacket.cpp284
-rw-r--r--coreplugin/ssh/sshoutgoingpacket_p.h98
-rw-r--r--coreplugin/ssh/sshpacket.cpp167
-rw-r--r--coreplugin/ssh/sshpacket_p.h137
-rw-r--r--coreplugin/ssh/sshpacketparser.cpp153
-rw-r--r--coreplugin/ssh/sshpacketparser_p.h81
-rw-r--r--coreplugin/ssh/sshremoteprocess.cpp270
-rw-r--r--coreplugin/ssh/sshremoteprocess.h130
-rw-r--r--coreplugin/ssh/sshremoteprocess_p.h96
-rw-r--r--coreplugin/ssh/sshsendfacility.cpp191
-rw-r--r--coreplugin/ssh/sshsendfacility_p.h90
-rw-r--r--examples/cppsystemtest/cppsystemtest.pro1
-rw-r--r--interpreter/interpreter.pro1
-rw-r--r--interpreter/qscriptsystemtest.cpp2
-rw-r--r--libqsystemtest/libqsystemtest.pro61
-rw-r--r--libqsystemtest/qabstracttest.cpp2
-rw-r--r--libqsystemtest/qsystemtest.cpp19
-rw-r--r--libqsystemtest/qsystemtest.h2
-rw-r--r--libqsystemtest/testdevicecontrol.cpp272
-rw-r--r--libqsystemtest/testdevicecontrol.h98
-rwxr-xr-xmk_src_package15
-rw-r--r--qtuitest-for-creator.pro3
-rw-r--r--qtuitest-host.pri7
-rw-r--r--qtuitest.pro9
1810 files changed, 188865 insertions, 18 deletions
diff --git a/botan/Makefile b/botan/Makefile
new file mode 100644
index 0000000..9d78dcc
--- /dev/null
+++ b/botan/Makefile
@@ -0,0 +1,148 @@
+#############################################################################
+# Makefile for building: botan
+# Generated by qmake (2.01a) (Qt 4.7.0) on: Sat Jun 26 13:13:55 2010
+# Project: botan.pro
+# Template: subdirs
+# Command: /opt/Qt/4.7/bin/qmake -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile botan.pro
+#############################################################################
+
+first: make_default
+MAKEFILE = Makefile
+QMAKE = /opt/Qt/4.7/bin/qmake
+DEL_FILE = rm -f
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+COPY = cp -f
+COPY_FILE = cp -f
+COPY_DIR = cp -f -R
+INSTALL_FILE = $(COPY_FILE)
+INSTALL_PROGRAM = $(COPY_FILE)
+INSTALL_DIR = $(COPY_DIR)
+DEL_FILE = rm -f
+SYMLINK = ln -f -s
+DEL_DIR = rmdir
+MOVE = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+SUBTARGETS = \
+ sub-src
+
+src/$(MAKEFILE):
+ @$(CHK_DIR_EXISTS) src/ || $(MKDIR) src/
+ cd src/ && $(QMAKE) /Users/ebaak/depot/creator-qtest/src/libs/3rdparty/botan/src/src.pro -spec /opt/Qt/4.7/mkspecs/macx-g++ -o $(MAKEFILE)
+sub-src-qmake_all: FORCE
+ @$(CHK_DIR_EXISTS) src/ || $(MKDIR) src/
+ cd src/ && $(QMAKE) /Users/ebaak/depot/creator-qtest/src/libs/3rdparty/botan/src/src.pro -spec /opt/Qt/4.7/mkspecs/macx-g++ -o $(MAKEFILE)
+sub-src: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE)
+sub-src-make_default-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE)
+sub-src-make_default: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE)
+sub-src-make_first-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) first
+sub-src-make_first: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) first
+sub-src-all-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) all
+sub-src-all: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) all
+sub-src-clean-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) clean
+sub-src-clean: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) clean
+sub-src-distclean-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) distclean
+sub-src-distclean: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) distclean
+sub-src-install_subtargets-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) install
+sub-src-install_subtargets: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) install
+sub-src-uninstall_subtargets-ordered: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) uninstall
+sub-src-uninstall_subtargets: src/$(MAKEFILE) FORCE
+ cd src/ && $(MAKE) -f $(MAKEFILE) uninstall
+
+Makefile: botan.pro /opt/Qt/4.7/mkspecs/macx-g++/qmake.conf /opt/Qt/4.7/mkspecs/common/unix.conf \
+ /opt/Qt/4.7/mkspecs/common/mac.conf \
+ /opt/Qt/4.7/mkspecs/common/mac-g++.conf \
+ /opt/Qt/4.7/mkspecs/qconfig.pri \
+ /opt/Qt/4.7/mkspecs/features/qt_functions.prf \
+ /opt/Qt/4.7/mkspecs/features/qt_config.prf \
+ /opt/Qt/4.7/mkspecs/features/exclusive_builds.prf \
+ /opt/Qt/4.7/mkspecs/features/default_pre.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_pre.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/dwarf2.prf \
+ /opt/Qt/4.7/mkspecs/features/debug.prf \
+ /opt/Qt/4.7/mkspecs/features/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/x86_64.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/objective_c.prf \
+ /opt/Qt/4.7/mkspecs/features/warn_on.prf \
+ /opt/Qt/4.7/mkspecs/modules/qt_webkit_version.pri \
+ /opt/Qt/4.7/mkspecs/features/qt.prf \
+ /opt/Qt/4.7/mkspecs/features/unix/thread.prf \
+ /opt/Qt/4.7/mkspecs/features/moc.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/rez.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/sdk.prf \
+ /opt/Qt/4.7/mkspecs/features/resources.prf \
+ /opt/Qt/4.7/mkspecs/features/uic.prf \
+ /opt/Qt/4.7/mkspecs/features/yacc.prf \
+ /opt/Qt/4.7/mkspecs/features/lex.prf \
+ /opt/Qt/4.7/mkspecs/features/include_source_dir.prf
+ $(QMAKE) -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile botan.pro
+/opt/Qt/4.7/mkspecs/common/unix.conf:
+/opt/Qt/4.7/mkspecs/common/mac.conf:
+/opt/Qt/4.7/mkspecs/common/mac-g++.conf:
+/opt/Qt/4.7/mkspecs/qconfig.pri:
+/opt/Qt/4.7/mkspecs/features/qt_functions.prf:
+/opt/Qt/4.7/mkspecs/features/qt_config.prf:
+/opt/Qt/4.7/mkspecs/features/exclusive_builds.prf:
+/opt/Qt/4.7/mkspecs/features/default_pre.prf:
+/opt/Qt/4.7/mkspecs/features/mac/default_pre.prf:
+/opt/Qt/4.7/mkspecs/features/mac/dwarf2.prf:
+/opt/Qt/4.7/mkspecs/features/debug.prf:
+/opt/Qt/4.7/mkspecs/features/default_post.prf:
+/opt/Qt/4.7/mkspecs/features/mac/default_post.prf:
+/opt/Qt/4.7/mkspecs/features/mac/x86_64.prf:
+/opt/Qt/4.7/mkspecs/features/mac/objective_c.prf:
+/opt/Qt/4.7/mkspecs/features/warn_on.prf:
+/opt/Qt/4.7/mkspecs/modules/qt_webkit_version.pri:
+/opt/Qt/4.7/mkspecs/features/qt.prf:
+/opt/Qt/4.7/mkspecs/features/unix/thread.prf:
+/opt/Qt/4.7/mkspecs/features/moc.prf:
+/opt/Qt/4.7/mkspecs/features/mac/rez.prf:
+/opt/Qt/4.7/mkspecs/features/mac/sdk.prf:
+/opt/Qt/4.7/mkspecs/features/resources.prf:
+/opt/Qt/4.7/mkspecs/features/uic.prf:
+/opt/Qt/4.7/mkspecs/features/yacc.prf:
+/opt/Qt/4.7/mkspecs/features/lex.prf:
+/opt/Qt/4.7/mkspecs/features/include_source_dir.prf:
+qmake: qmake_all FORCE
+ @$(QMAKE) -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile botan.pro
+
+qmake_all: sub-src-qmake_all FORCE
+
+make_default: sub-src-make_default-ordered FORCE
+make_first: sub-src-make_first-ordered FORCE
+all: sub-src-all-ordered FORCE
+clean: sub-src-clean-ordered FORCE
+distclean: sub-src-distclean-ordered FORCE
+ -$(DEL_FILE) Makefile
+install_subtargets: sub-src-install_subtargets-ordered FORCE
+uninstall_subtargets: sub-src-uninstall_subtargets-ordered FORCE
+
+sub-src-check_ordered: src/$(MAKEFILE)
+ cd src/ && $(MAKE) check
+check: sub-src-check_ordered
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+install: install_subtargets FORCE
+
+uninstall: uninstall_subtargets FORCE
+
+FORCE:
+
diff --git a/botan/botan.pri b/botan/botan.pri
new file mode 100644
index 0000000..b1c924d
--- /dev/null
+++ b/botan/botan.pri
@@ -0,0 +1,2 @@
+INCLUDEPATH *= $$PWD/build
+LIBS *= -l$$qtLibraryTarget(Botan)
diff --git a/botan/botan.pro b/botan/botan.pro
new file mode 100644
index 0000000..5712a1b
--- /dev/null
+++ b/botan/botan.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += src \ No newline at end of file
diff --git a/botan/build/botan/adler32.h b/botan/build/botan/adler32.h
new file mode 100644
index 0000000..98a28bc
--- /dev/null
+++ b/botan/build/botan/adler32.h
@@ -0,0 +1,35 @@
+/*
+* Adler32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ADLER32_H__
+#define BOTAN_ADLER32_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Adler32
+*/
+class BOTAN_DLL Adler32 : public HashFunction
+ {
+ public:
+ void clear() throw() { S1 = 1; S2 = 0; }
+ std::string name() const { return "Adler32"; }
+ HashFunction* clone() const { return new Adler32; }
+ Adler32() : HashFunction(4) { clear(); }
+ ~Adler32() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void hash(const byte[], u32bit);
+ u16bit S1, S2;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/aes.h b/botan/build/botan/aes.h
new file mode 100644
index 0000000..05e2e31
--- /dev/null
+++ b/botan/build/botan/aes.h
@@ -0,0 +1,81 @@
+/**
+* AES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AES_H__
+#define BOTAN_AES_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* Rijndael aka AES
+*/
+class BOTAN_DLL AES : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "AES"; }
+ BlockCipher* clone() const { return new AES; }
+ AES() : BlockCipher(16, 16, 32, 8) { ROUNDS = 14; }
+ AES(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ static u32bit S(u32bit);
+
+ static const byte SE[256];
+ static const byte SD[256];
+ static const u32bit TE[1024];
+ static const u32bit TD[1024];
+
+ u32bit ROUNDS;
+
+ SecureBuffer<u32bit, 56> EK;
+ SecureBuffer<byte, 16> ME;
+
+ SecureBuffer<u32bit, 56> DK;
+ SecureBuffer<byte, 16> MD;
+ };
+
+/**
+* AES-128
+*/
+class BOTAN_DLL AES_128 : public AES
+ {
+ public:
+ std::string name() const { return "AES-128"; }
+ BlockCipher* clone() const { return new AES_128; }
+ AES_128() : AES(16) {}
+ };
+
+/**
+* AES-192
+*/
+class BOTAN_DLL AES_192 : public AES
+ {
+ public:
+ std::string name() const { return "AES-192"; }
+ BlockCipher* clone() const { return new AES_192; }
+ AES_192() : AES(24) {}
+ };
+
+/**
+* AES-256
+*/
+class BOTAN_DLL AES_256 : public AES
+ {
+ public:
+ std::string name() const { return "AES-256"; }
+ BlockCipher* clone() const { return new AES_256; }
+ AES_256() : AES(32) {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/alg_id.h b/botan/build/botan/alg_id.h
new file mode 100644
index 0000000..4a1ad2f
--- /dev/null
+++ b/botan/build/botan/alg_id.h
@@ -0,0 +1,49 @@
+/*
+* Algorithm Identifier
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALGORITHM_IDENTIFIER_H__
+#define BOTAN_ALGORITHM_IDENTIFIER_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Algorithm Identifier
+*/
+class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object
+ {
+ public:
+ enum Encoding_Option { USE_NULL_PARAM };
+
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ AlgorithmIdentifier() {}
+ AlgorithmIdentifier(const OID&, Encoding_Option);
+ AlgorithmIdentifier(const std::string&, Encoding_Option);
+
+ AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&);
+ AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&);
+
+ OID oid;
+ SecureVector<byte> parameters;
+ };
+
+/*
+* Comparison Operations
+*/
+bool BOTAN_DLL operator==(const AlgorithmIdentifier&,
+ const AlgorithmIdentifier&);
+bool BOTAN_DLL operator!=(const AlgorithmIdentifier&,
+ const AlgorithmIdentifier&);
+
+}
+
+#endif
diff --git a/botan/build/botan/algo_cache.h b/botan/build/botan/algo_cache.h
new file mode 100644
index 0000000..17ea996
--- /dev/null
+++ b/botan/build/botan/algo_cache.h
@@ -0,0 +1,224 @@
+/**
+* An algorithm cache (used by Algorithm_Factory)
+*/
+
+#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
+#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
+
+#include <botan/mutex.h>
+#include <botan/stl_util.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* @param prov_name a provider name
+* @return weight for this provider
+*/
+u32bit static_provider_weight(const std::string& prov_name);
+
+/**
+* Algorithm_Cache (used by Algorithm_Factory)
+*/
+template<typename T>
+class Algorithm_Cache
+ {
+ public:
+ const T* get(const std::string& algo_spec,
+ const std::string& pref_provider);
+
+ /**
+ * Add a new algorithm implementation to the cache
+ */
+ void add(T* algo,
+ const std::string& requested_name,
+ const std::string& provider_name);
+
+ /**
+ * Set the preferred provider
+ */
+ void set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider);
+
+ /**
+ * Return the list of providers of this algorithm
+ */
+ std::vector<std::string> providers_of(const std::string& algo_name);
+
+ Algorithm_Cache(Mutex* m) : mutex(m) {}
+ ~Algorithm_Cache();
+ private:
+ typedef typename std::map<std::string, std::map<std::string, T*> >::iterator
+ algorithms_iterator;
+
+ typedef typename std::map<std::string, T*>::iterator provider_iterator;
+
+ algorithms_iterator find_algorithm(const std::string& algo_spec);
+
+ Mutex* mutex;
+ std::map<std::string, std::string> aliases;
+ std::map<std::string, std::string> pref_providers;
+ std::map<std::string, std::map<std::string, T*> > algorithms;
+ };
+
+/**
+* Look for an algorithm implementation in the cache, also checking aliases
+* Assumes object lock is held
+*/
+template<typename T>
+typename Algorithm_Cache<T>::algorithms_iterator
+Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
+ {
+ algorithms_iterator algo = algorithms.find(algo_spec);
+
+ // Not found? Check if a known alias
+ if(algo == algorithms.end())
+ {
+ std::map<std::string, std::string>::const_iterator alias =
+ aliases.find(algo_spec);
+
+ if(alias != aliases.end())
+ algo = algorithms.find(alias->second);
+ }
+
+ return algo;
+ }
+
+/**
+* Look for an algorithm implementation by a particular provider
+*/
+template<typename T>
+const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
+ const std::string& requested_provider)
+ {
+ Mutex_Holder lock(mutex);
+
+ algorithms_iterator algo = find_algorithm(algo_spec);
+ if(algo == algorithms.end()) // algo not found at all (no providers)
+ return 0;
+
+ // If a provider is requested specifically, return it or fail entirely
+ if(requested_provider != "")
+ {
+ provider_iterator prov = algo->second.find(requested_provider);
+ if(prov != algo->second.end())
+ return prov->second;
+ return 0;
+ }
+
+ const T* prototype = 0;
+ std::string prototype_provider;
+ u32bit prototype_prov_weight = 0;
+
+ const std::string pref_provider = search_map(pref_providers, algo_spec);
+
+ for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
+ {
+ const std::string prov_name = i->first;
+ const u32bit prov_weight = static_provider_weight(prov_name);
+
+ // preferred prov exists, return immediately
+ if(prov_name == pref_provider)
+ return i->second;
+
+ if(prototype == 0 || prov_weight > prototype_prov_weight)
+ {
+ prototype = i->second;
+ prototype_provider = i->first;
+ prototype_prov_weight = prov_weight;
+ }
+ }
+
+ return prototype;
+ }
+
+/**
+* Add an implementation to the cache
+*/
+template<typename T>
+void Algorithm_Cache<T>::add(T* algo,
+ const std::string& requested_name,
+ const std::string& provider)
+ {
+ if(!algo)
+ return;
+
+ Mutex_Holder lock(mutex);
+
+ delete algorithms[algo->name()][provider];
+ algorithms[algo->name()][provider] = algo;
+
+ if(algo->name() != requested_name &&
+ aliases.find(requested_name) == aliases.end())
+ {
+ aliases[requested_name] = algo->name();
+ }
+ }
+
+/**
+* Find the providers of this algo (if any)
+*/
+template<typename T> std::vector<std::string>
+Algorithm_Cache<T>::providers_of(const std::string& algo_name)
+ {
+ Mutex_Holder lock(mutex);
+
+ std::vector<std::string> providers;
+
+ algorithms_iterator algo = find_algorithm(algo_name);
+
+ if(algo != algorithms.end())
+ {
+ provider_iterator provider = algo->second.begin();
+
+ while(provider != algo->second.end())
+ {
+ providers.push_back(provider->first);
+ ++provider;
+ }
+ }
+
+ return providers;
+ }
+
+/**
+* Set the preferred provider for an algorithm
+*/
+template<typename T>
+void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ Mutex_Holder lock(mutex);
+
+ pref_providers[algo_spec] = provider;
+ }
+
+/**
+* Algorithm_Cache<T> Destructor
+*/
+template<typename T>
+Algorithm_Cache<T>::~Algorithm_Cache()
+ {
+ algorithms_iterator algo = algorithms.begin();
+
+ while(algo != algorithms.end())
+ {
+ provider_iterator provider = algo->second.begin();
+
+ while(provider != algo->second.end())
+ {
+ delete provider->second;
+ ++provider;
+ }
+
+ ++algo;
+ }
+
+ delete mutex;
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/algo_factory.h b/botan/build/botan/algo_factory.h
new file mode 100644
index 0000000..73e5920
--- /dev/null
+++ b/botan/build/botan/algo_factory.h
@@ -0,0 +1,132 @@
+/**
+* Algorithm Factory
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALGORITHM_FACTORY_H__
+#define BOTAN_ALGORITHM_FACTORY_H__
+
+#include <botan/mutex.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Forward declarations (don't need full definitions here)
+*/
+class BlockCipher;
+class StreamCipher;
+class HashFunction;
+class MessageAuthenticationCode;
+
+template<typename T> class Algorithm_Cache;
+
+class Engine;
+
+/**
+* Algorithm Factory
+*/
+class BOTAN_DLL Algorithm_Factory
+ {
+ public:
+ /**
+ * Constructor
+ * @param engines_in the list of engines to use
+ * @param mf a mutex factory
+ */
+ Algorithm_Factory(const std::vector<Engine*>& engines_in,
+ Mutex_Factory& mf);
+
+ /**
+ * Destructor
+ */
+ ~Algorithm_Factory();
+
+ /*
+ * Provider management
+ */
+ std::vector<std::string> providers_of(const std::string& algo_spec);
+
+ void set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider);
+
+ /*
+ * Block cipher operations
+ */
+ const BlockCipher*
+ prototype_block_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ BlockCipher* make_block_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_block_cipher(BlockCipher* hash, const std::string& provider);
+
+ /*
+ * Stream cipher operations
+ */
+ const StreamCipher*
+ prototype_stream_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ StreamCipher* make_stream_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_stream_cipher(StreamCipher* hash, const std::string& provider);
+
+ /*
+ * Hash function operations
+ */
+ const HashFunction*
+ prototype_hash_function(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ HashFunction* make_hash_function(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_hash_function(HashFunction* hash, const std::string& provider);
+
+ /*
+ * MAC operations
+ */
+ const MessageAuthenticationCode*
+ prototype_mac(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ MessageAuthenticationCode* make_mac(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_mac(MessageAuthenticationCode* mac,
+ const std::string& provider);
+
+ /*
+ * Deprecated
+ */
+ class BOTAN_DLL Engine_Iterator
+ {
+ public:
+ class Engine* next() { return af.get_engine_n(n++); }
+ Engine_Iterator(const Algorithm_Factory& a) : af(a) { n = 0; }
+ private:
+ const Algorithm_Factory& af;
+ u32bit n;
+ };
+ friend class Engine_Iterator;
+
+ private:
+ class Engine* get_engine_n(u32bit) const;
+
+ std::vector<class Engine*> engines;
+
+ Algorithm_Cache<BlockCipher>* block_cipher_cache;
+ Algorithm_Cache<StreamCipher>* stream_cipher_cache;
+ Algorithm_Cache<HashFunction>* hash_cache;
+ Algorithm_Cache<MessageAuthenticationCode>* mac_cache;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/allocate.h b/botan/build/botan/allocate.h
new file mode 100644
index 0000000..180f2c0
--- /dev/null
+++ b/botan/build/botan/allocate.h
@@ -0,0 +1,37 @@
+/*
+* Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALLOCATOR_H__
+#define BOTAN_ALLOCATOR_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Allocator Interface
+*/
+class BOTAN_DLL Allocator
+ {
+ public:
+ static Allocator* get(bool);
+
+ virtual void* allocate(u32bit) = 0;
+ virtual void deallocate(void*, u32bit) = 0;
+
+ virtual std::string type() const = 0;
+
+ virtual void init() {}
+ virtual void destroy() {}
+
+ virtual ~Allocator() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/arc4.h b/botan/build/botan/arc4.h
new file mode 100644
index 0000000..aa2cea7
--- /dev/null
+++ b/botan/build/botan/arc4.h
@@ -0,0 +1,41 @@
+/*
+* ARC4
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ARC4_H__
+#define BOTAN_ARC4_H__
+
+#include <botan/stream_cipher.h>
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* ARC4
+*/
+class BOTAN_DLL ARC4 : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ StreamCipher* clone() const { return new ARC4(SKIP); }
+ ARC4(u32bit = 0);
+ ~ARC4() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void generate();
+
+ const u32bit SKIP;
+
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ SecureBuffer<u32bit, 256> state;
+ u32bit X, Y, position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/asn1_int.h b/botan/build/botan/asn1_int.h
new file mode 100644
index 0000000..619f45b
--- /dev/null
+++ b/botan/build/botan/asn1_int.h
@@ -0,0 +1,108 @@
+/*
+* ASN.1 Internals
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_H__
+#define BOTAN_ASN1_H__
+
+#include <botan/secmem.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* ASN.1 Type and Class Tags
+*/
+enum ASN1_Tag {
+ UNIVERSAL = 0x00,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xC0,
+
+ CONSTRUCTED = 0x20,
+
+ EOC = 0x00,
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ NULL_TAG = 0x05,
+ OBJECT_ID = 0x06,
+ ENUMERATED = 0x0A,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+
+ UTF8_STRING = 0x0C,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ IA5_STRING = 0x16,
+ VISIBLE_STRING = 0x1A,
+ BMP_STRING = 0x1E,
+
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+
+ NO_OBJECT = 0xFF00,
+ DIRECTORY_STRING = 0xFF01
+};
+
+/*
+* Basic ASN.1 Object Interface
+*/
+class BOTAN_DLL ASN1_Object
+ {
+ public:
+ virtual void encode_into(class DER_Encoder&) const = 0;
+ virtual void decode_from(class BER_Decoder&) = 0;
+ virtual ~ASN1_Object() {}
+ };
+
+/*
+* BER Encoded Object
+*/
+class BOTAN_DLL BER_Object
+ {
+ public:
+ void assert_is_a(ASN1_Tag, ASN1_Tag);
+
+ ASN1_Tag type_tag, class_tag;
+ SecureVector<byte> value;
+ };
+
+/*
+* ASN.1 Utility Functions
+*/
+class DataSource;
+
+namespace ASN1 {
+
+SecureVector<byte> put_in_sequence(const MemoryRegion<byte>&);
+std::string to_string(const BER_Object&);
+bool maybe_BER(DataSource&);
+
+}
+
+/*
+* General BER Decoding Error Exception
+*/
+struct BER_Decoding_Error : public Decoding_Error
+ {
+ BER_Decoding_Error(const std::string&);
+ };
+
+/*
+* Exception For Incorrect BER Taggings
+*/
+struct BER_Bad_Tag : public BER_Decoding_Error
+ {
+ BER_Bad_Tag(const std::string&, ASN1_Tag);
+ BER_Bad_Tag(const std::string&, ASN1_Tag, ASN1_Tag);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/asn1_obj.h b/botan/build/botan/asn1_obj.h
new file mode 100644
index 0000000..ea21c47
--- /dev/null
+++ b/botan/build/botan/asn1_obj.h
@@ -0,0 +1,160 @@
+/*
+* Common ASN.1 Objects
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_OBJ_H__
+#define BOTAN_ASN1_OBJ_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <botan/alg_id.h>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*
+* Attribute
+*/
+class BOTAN_DLL Attribute : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ OID oid;
+ MemoryVector<byte> parameters;
+
+ Attribute() {}
+ Attribute(const OID&, const MemoryRegion<byte>&);
+ Attribute(const std::string&, const MemoryRegion<byte>&);
+ };
+
+/*
+* X.509 Time
+*/
+class BOTAN_DLL X509_Time : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::string as_string() const;
+ std::string readable_string() const;
+ bool time_is_set() const;
+
+ s32bit cmp(const X509_Time&) const;
+
+ void set_to(const std::string&);
+ void set_to(const std::string&, ASN1_Tag);
+
+ X509_Time(u64bit);
+ X509_Time(const std::string& = "");
+ X509_Time(const std::string&, ASN1_Tag);
+ private:
+ bool passes_sanity_check() const;
+ u32bit year, month, day, hour, minute, second;
+ ASN1_Tag tag;
+ };
+
+/*
+* Simple String
+*/
+class BOTAN_DLL ASN1_String : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::string value() const;
+ std::string iso_8859() const;
+
+ ASN1_Tag tagging() const;
+
+ ASN1_String(const std::string& = "");
+ ASN1_String(const std::string&, ASN1_Tag);
+ private:
+ std::string iso_8859_str;
+ ASN1_Tag tag;
+ };
+
+/*
+* Distinguished Name
+*/
+class BOTAN_DLL X509_DN : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::multimap<OID, std::string> get_attributes() const;
+ std::vector<std::string> get_attribute(const std::string&) const;
+
+ std::multimap<std::string, std::string> contents() const;
+
+ void add_attribute(const std::string&, const std::string&);
+ void add_attribute(const OID&, const std::string&);
+
+ static std::string deref_info_field(const std::string&);
+
+ void do_decode(const MemoryRegion<byte>&);
+ MemoryVector<byte> get_bits() const;
+
+ X509_DN();
+ X509_DN(const std::multimap<OID, std::string>&);
+ X509_DN(const std::multimap<std::string, std::string>&);
+ private:
+ std::multimap<OID, ASN1_String> dn_info;
+ MemoryVector<byte> dn_bits;
+ };
+
+/*
+* Alternative Name
+*/
+class BOTAN_DLL AlternativeName : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::multimap<std::string, std::string> contents() const;
+
+ void add_attribute(const std::string&, const std::string&);
+ std::multimap<std::string, std::string> get_attributes() const;
+
+ void add_othername(const OID&, const std::string&, ASN1_Tag);
+ std::multimap<OID, ASN1_String> get_othernames() const;
+
+ bool has_items() const;
+
+ AlternativeName(const std::string& = "", const std::string& = "",
+ const std::string& = "", const std::string& = "");
+ private:
+ std::multimap<std::string, std::string> alt_info;
+ std::multimap<OID, ASN1_String> othernames;
+ };
+
+/*
+* Comparison Operations
+*/
+bool BOTAN_DLL operator==(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator!=(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator<=(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator>=(const X509_Time&, const X509_Time&);
+
+bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&);
+bool BOTAN_DLL operator!=(const X509_DN&, const X509_DN&);
+bool BOTAN_DLL operator<(const X509_DN&, const X509_DN&);
+
+/*
+* Helper Functions
+*/
+bool BOTAN_DLL is_string_type(ASN1_Tag);
+
+}
+
+#endif
diff --git a/botan/build/botan/asn1_oid.h b/botan/build/botan/asn1_oid.h
new file mode 100644
index 0000000..e6d077b
--- /dev/null
+++ b/botan/build/botan/asn1_oid.h
@@ -0,0 +1,96 @@
+/*
+* ASN.1 OID
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_OID_H__
+#define BOTAN_ASN1_OID_H__
+
+#include <botan/asn1_int.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents ASN.1 object identifiers.
+*/
+class BOTAN_DLL OID : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Find out whether this OID is empty
+ * @return true is no OID value is set
+ */
+ bool is_empty() const { return id.size() == 0; }
+
+ /**
+ * Get this OID as list (vector) of its components.
+ * @return a vector representing this OID
+ */
+ std::vector<u32bit> get_id() const { return id; }
+
+ /**
+ * Get this OID as a string
+ * @return a string representing this OID
+ */
+ std::string as_string() const;
+
+ /**
+ * Compare two OIDs.
+ * @return true if they are equal, false otherwise
+ */
+ bool operator==(const OID&) const;
+
+ /**
+ * Reset this instance to an empty OID.
+ */
+ void clear();
+
+ /**
+ * Add a component to this OID.
+ * @param new_comp the new component to add to the end of this OID
+ * @return a reference to *this
+ */
+ OID& operator+=(u32bit new_comp);
+
+ /**
+ * Construct an OID from a string.
+ * @param str a string in the form "a.b.c" etc., where a,b,c are numbers
+ */
+ OID(const std::string& str = "");
+ private:
+ std::vector<u32bit> id;
+ };
+
+/**
+* Append another component onto the OID.
+* @param oid the OID to add the new component to
+* @param new_comp the new component to add
+*/
+OID operator+(const OID& oid, u32bit new_comp);
+
+/**
+* Compare two OIDs.
+* @param a the first OID
+* @param b the second OID
+* @return true if a is not equal to b
+*/
+bool operator!=(const OID& a, const OID& b);
+
+/**
+* Compare two OIDs.
+* @param a the first OID
+* @param b the second OID
+* @return true if a is lexicographically smaller than b
+*/
+bool operator<(const OID& a, const OID& b);
+
+}
+
+#endif
diff --git a/botan/build/botan/auto_rng.h b/botan/build/botan/auto_rng.h
new file mode 100644
index 0000000..f18f8e5
--- /dev/null
+++ b/botan/build/botan/auto_rng.h
@@ -0,0 +1,44 @@
+/*
+* Auto Seeded RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AUTO_SEEDING_RNG_H__
+#define BOTAN_AUTO_SEEDING_RNG_H__
+
+#include <botan/rng.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* RNG that attempts to seed itself
+*/
+class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte out[], u32bit len)
+ { rng->randomize(out, len); }
+ bool is_seeded() const
+ { return rng->is_seeded(); }
+ void clear() throw() { rng->clear(); }
+ std::string name() const
+ { return "AutoSeeded(" + rng->name() + ")"; }
+
+ void reseed(u32bit poll_bits = 256) { rng->reseed(poll_bits); }
+ void add_entropy_source(EntropySource* es)
+ { rng->add_entropy_source(es); }
+ void add_entropy(const byte in[], u32bit len)
+ { rng->add_entropy(in, len); }
+
+ AutoSeeded_RNG(u32bit poll_bits = 256);
+ ~AutoSeeded_RNG() { delete rng; }
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/base64.h b/botan/build/botan/base64.h
new file mode 100644
index 0000000..aca02da
--- /dev/null
+++ b/botan/build/botan/base64.h
@@ -0,0 +1,94 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASE64_H__
+#define BOTAN_BASE64_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a Base64 encoder.
+*/
+class BOTAN_DLL Base64_Encoder : public Filter
+ {
+ public:
+ static void encode(const byte in[3], byte out[4]);
+
+ /**
+ * Input a part of a message to the encoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param breaks whether to use line breaks in the Streamcipheroutput
+ * @param length the length of the lines of the output
+ * @param t_n whether to use a trailing newline
+ */
+ Base64_Encoder(bool breaks = false, u32bit length = 72,
+ bool t_n = false);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ void do_output(const byte[], u32bit);
+ static const byte BIN_TO_BASE64[64];
+
+ const u32bit line_length;
+ const bool trailing_newline;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This object represents a Base64 decoder.
+*/
+class BOTAN_DLL Base64_Decoder : public Filter
+ {
+ public:
+ static void decode(const byte input[4], byte output[3]);
+
+ static bool is_valid(byte);
+
+ /**
+ * Input a part of a message to the decoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param checking the type of checking that shall be performed by
+ * the decoder
+ */
+ Base64_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte BASE64_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/basefilt.h b/botan/build/botan/basefilt.h
new file mode 100644
index 0000000..75625ab
--- /dev/null
+++ b/botan/build/botan/basefilt.h
@@ -0,0 +1,99 @@
+/*
+* Basic Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASEFILT_H__
+#define BOTAN_BASEFILT_H__
+
+#include <botan/filter.h>
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents Filter chains. A Filter chain is an ordered
+* concatenation of Filters, the input to a Chain sequentially passes
+* through all the Filters contained in the Chain.
+*/
+
+class BOTAN_DLL Chain : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+
+ /**
+ * Construct a chain of up to four filters. The filters are set
+ * up in the same order as the arguments.
+ */
+ Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a chain from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Chain(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents a fork filter, whose purpose is to fork the
+* flow of data. It causes an input message to result in n messages at
+* the end of the filter, where n is the number of forks.
+*/
+class BOTAN_DLL Fork : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+ void set_port(u32bit n) { Fanout_Filter::set_port(n); }
+
+ /**
+ * Construct a Fork filter with up to four forks.
+ */
+ Fork(Filter*, Filter*, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Fork from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Fork(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents keyed filters, i.e. filters that have to be
+* fed with a key in order to function.
+*/
+class BOTAN_DLL Keyed_Filter : public Filter
+ {
+ public:
+
+ /**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ virtual void set_key(const SymmetricKey& key);
+
+ /**
+ * Set the initialization vector of this filter.
+ * @param iv the initialization vector to set
+ */
+ virtual void set_iv(const InitializationVector&) {}
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ virtual bool valid_keylength(u32bit length) const;
+
+ Keyed_Filter() { base_ptr = 0; }
+ protected:
+ SymmetricAlgorithm* base_ptr;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/benchmark.h b/botan/build/botan/benchmark.h
new file mode 100644
index 0000000..272cfdf
--- /dev/null
+++ b/botan/build/botan/benchmark.h
@@ -0,0 +1,59 @@
+/**
+* Runtime benchmarking
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RUNTIME_BENCHMARK_H__
+#define BOTAN_RUNTIME_BENCHMARK_H__
+
+#include <botan/algo_factory.h>
+#include <botan/timer.h>
+#include <botan/rng.h>
+#include <map>
+#include <string>
+
+/**
+* Choose some sort of default timer implementation to use, since some
+* (like hardware tick counters and current Win32 timer) are not
+* reliable for benchmarking.
+*/
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ #include <botan/tm_posix.h>
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ #include <botan/tm_unix.h>
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ typedef POSIX_Timer Default_Benchmark_Timer;
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ typedef Unix_Timer Default_Benchmark_Timer;
+#else
+ /* I have not had good success using clock(), the results seem
+ * pretty bogus, but as a last resort it works.
+ */
+ typedef ANSI_Clock_Timer Default_Benchmark_Timer;
+#endif
+
+/**
+* Algorithm benchmark
+* @param name the name of the algorithm to test (cipher, hash, or MAC)
+* @param milliseconds total time for the benchmark to run
+* @param timer the timer to use
+* @param rng the rng to use to generate random inputs
+* @param af the algorithm factory used to create objects
+* @return results a map from provider to speed in mebibytes per second
+*/
+std::map<std::string, double>
+algorithm_benchmark(const std::string& name,
+ u32bit milliseconds,
+ Timer& timer,
+ RandomNumberGenerator& rng,
+ Algorithm_Factory& af);
+
+}
+
+#endif
diff --git a/botan/build/botan/ber_dec.h b/botan/build/botan/ber_dec.h
new file mode 100644
index 0000000..2e38af3
--- /dev/null
+++ b/botan/build/botan/ber_dec.h
@@ -0,0 +1,122 @@
+/*
+* BER Decoder
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BER_DECODER_H__
+#define BOTAN_BER_DECODER_H__
+
+#include <botan/asn1_oid.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/*
+* BER Decoding Object
+*/
+class BOTAN_DLL BER_Decoder
+ {
+ public:
+ BER_Object get_next_object();
+ void push_back(const BER_Object&);
+
+ bool more_items() const;
+ BER_Decoder& verify_end();
+ BER_Decoder& discard_remaining();
+
+ BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
+ BER_Decoder& end_cons();
+
+ BER_Decoder& raw_bytes(MemoryRegion<byte>&);
+
+ BER_Decoder& decode_null();
+ BER_Decoder& decode(bool&);
+ BER_Decoder& decode(u32bit&);
+ BER_Decoder& decode(class BigInt&);
+ BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag);
+
+ BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(u32bit&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(class BigInt&,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+
+ BER_Decoder& decode(class ASN1_Object&);
+
+ template<typename T>
+ BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T());
+
+ template<typename T>
+ BER_Decoder& decode_list(std::vector<T>&, bool = true);
+
+ BER_Decoder& decode_optional_string(MemoryRegion<byte>&,
+ ASN1_Tag, u16bit);
+
+ BER_Decoder(DataSource&);
+ BER_Decoder(const byte[], u32bit);
+ BER_Decoder(const MemoryRegion<byte>&);
+ BER_Decoder(const BER_Decoder&);
+ ~BER_Decoder();
+ private:
+ BER_Decoder& operator=(const BER_Decoder&) { return (*this); }
+
+ BER_Decoder* parent;
+ DataSource* source;
+ BER_Object pushed;
+ mutable bool owns;
+ };
+
+/*
+* Decode an OPTIONAL or DEFAULT element
+*/
+template<typename T>
+BER_Decoder& BER_Decoder::decode_optional(T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ const T& default_value)
+ {
+ BER_Object obj = get_next_object();
+
+ if(obj.type_tag == type_tag && obj.class_tag == class_tag)
+ {
+ if(class_tag & CONSTRUCTED)
+ BER_Decoder(obj.value).decode(out).verify_end();
+ else
+ {
+ push_back(obj);
+ decode(out, type_tag, class_tag);
+ }
+ }
+ else
+ {
+ out = default_value;
+ push_back(obj);
+ }
+
+ return (*this);
+ }
+
+/*
+* Decode a list of homogenously typed values
+*/
+template<typename T>
+BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec, bool clear_it)
+ {
+ if(clear_it)
+ vec.clear();
+
+ while(more_items())
+ {
+ T value;
+ decode(value);
+ vec.push_back(value);
+ }
+ return (*this);
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/bigint.h b/botan/build/botan/bigint.h
new file mode 100644
index 0000000..16a1bba
--- /dev/null
+++ b/botan/build/botan/bigint.h
@@ -0,0 +1,534 @@
+/*
+* BigInt
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BIGINT_H__
+#define BOTAN_BIGINT_H__
+
+#include <botan/rng.h>
+#include <botan/secmem.h>
+#include <botan/mp_types.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+ * Big Integer representation. This class defines an integer type,
+ * that can be very big. Additionally some helper functions are
+ * defined to work more comfortably.
+
+ */
+class BOTAN_DLL BigInt
+ {
+ public:
+ /**
+ * Base-Enumerator (currently 8,10,16 and 256 are defined)
+ */
+ enum Base { Octal = 8, Decimal = 10, Hexadecimal = 16, Binary = 256 };
+
+ /**
+ * Sign symbol definitions for positive and negative numbers
+ */
+ enum Sign { Negative = 0, Positive = 1 };
+
+ /**
+ * Number types (Powers of 2)
+ */
+ enum NumberType { Power2 };
+
+ /**
+ * DivideByZero Exception
+ */
+ struct DivideByZero : public Exception
+ { DivideByZero() : Exception("BigInt divide by zero") {} };
+
+ /*************
+ * operators
+ *************/
+
+ /**
+ * += Operator
+ * @param y the BigInt to add to the local value
+ */
+ BigInt& operator+=(const BigInt& y);
+
+ /**
+ * -= Operator
+ * @param y the BigInt to subtract from the local value
+ */
+ BigInt& operator-=(const BigInt& y);
+
+ /**
+ * *= Operator
+ * @param y the BigInt to multiply with the local value
+ */
+ BigInt& operator*=(const BigInt& y);
+
+ /**
+ * /= Operator
+ * @param y the BigInt to divide the local value by
+ */
+ BigInt& operator/=(const BigInt& y);
+
+ /**
+ * %= Operator, modulo operator.
+ * @param y the modulus to reduce the local value by
+ */
+ BigInt& operator%=(const BigInt& y);
+
+ /**
+ * %= Operator
+ * @param y the modulus (word) to reduce the local value by
+ */
+ word operator%=(word y);
+
+ /**
+ * <<= Operator
+ * @param y the amount of bits to shift the local value left
+ */
+ BigInt& operator<<=(u32bit y);
+
+ /**
+ * >>= Operator
+ * @param y the amount of bits to shift the local value right
+ */
+ BigInt& operator>>=(u32bit y);
+
+ /**
+ * ++ Operator
+ */
+ BigInt& operator++() { return (*this += 1); }
+
+ /**
+ * -- Operator
+ */
+ BigInt& operator--() { return (*this -= 1); }
+
+ /**
+ * ++ Operator (postfix)
+ */
+ BigInt operator++(int) { BigInt x = (*this); ++(*this); return x; }
+
+ /**
+ * -- Operator (postfix)
+ */
+ BigInt operator--(int) { BigInt x = (*this); --(*this); return x; }
+
+ /**
+ * - Operator
+ */
+ BigInt operator-() const;
+
+ /**
+ * ! Operator
+ */
+ bool operator !() const { return (!is_nonzero()); }
+
+ /**
+ * [] Operator (array access)
+ */
+ word& operator[](u32bit i) { return reg[i]; }
+
+ /**
+ * [] Operator (array access)
+ */
+ word operator[](u32bit i) const { return reg[i]; }
+
+ /**
+ * Zeroize the BigInt
+ */
+ void clear() { get_reg().clear(); }
+
+ /*************
+ * functions
+ ************/
+
+ /**
+ * Compare *this to another BigInt.
+ * @param n the BigInt value to compare to the local value.
+ * @param check_signs Include sign in comparison?
+ * @result if (this<n) return -1, if (this>n) return 1, if both
+ * values are identical return 0.
+ */
+ s32bit cmp(const BigInt& n, bool check_signs = true) const;
+
+ /**
+ * Test if the integer has an even value
+ * @result true, if the integer an even value, false otherwise
+ */
+ bool is_even() const { return (get_bit(0) == 0); }
+
+ /**
+ * Test if the integer has an odd value
+ * @result true, if the integer an odd value, false otherwise
+ */
+ bool is_odd() const { return (get_bit(0) == 1); }
+
+ /**
+ * Test if the integer is not zero.
+ * @result true, if the integer has a non-zero value, false otherwise
+ */
+ bool is_nonzero() const { return (!is_zero()); }
+
+ /**
+ * Test if the integer is zero.
+ * @result true, if the integer has the value zero, false otherwise
+ */
+ bool is_zero() const
+ {
+ const u32bit sw = sig_words();
+
+ for(u32bit i = 0; i != sw; ++i)
+ if(reg[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Set bit at specified position
+ * @param n bit position to set
+ */
+ void set_bit(u32bit n);
+
+ /**
+ * Clear bit at specified position
+ * @param n bit position to clear
+ */
+ void clear_bit(u32bit n);
+
+ /**
+ * Clear all but the lowest n bits
+ * @param n amount of bits to keep
+ */
+ void mask_bits(u32bit n);
+
+ /**
+ * Return bit value at specified position
+ * @param n the bit offset to test
+ * @result true, if the bit at position n is set, false otherwise
+ */
+ bool get_bit(u32bit n) const;
+
+ /**
+ * Return (a maximum of) 32 bits of the complete value
+ * @param offset the offset to start extracting
+ * @param length amount of bits to extract (starting at offset)
+ * @result the integer extracted from the register starting at
+ * offset with specified length
+ */
+ u32bit get_substring(u32bit offset, u32bit length) const;
+
+ byte byte_at(u32bit) const;
+
+ /**
+ * Return the word at a specified position of the internal register
+ * @param n position in the register
+ * @return the value at position n
+ */
+ word word_at(u32bit n) const
+ { return ((n < size()) ? reg[n] : 0); }
+
+ /**
+ * Return the integer as an unsigned 32bit-integer-value. If the
+ * value is negative OR to big to be stored in 32bits, this
+ * function will throw an exception.
+ * @result a 32bit-integer
+ */
+ u32bit to_u32bit() const;
+
+ /**
+ * Tests if the sign of the integer is negative.
+ * @result true, if the integer has a negative sign,
+ */
+ bool is_negative() const { return (sign() == Negative); }
+
+ /**
+ * Tests if the sign of the integer is positive.
+ * @result true, if the integer has a positive sign,
+ */
+ bool is_positive() const { return (sign() == Positive); }
+
+ /**
+ * Return the sign of the integer
+ * @result the sign of the integer
+ */
+ Sign sign() const { return (signedness); }
+
+ /**
+ * Return the opposite sign of the represented integer value
+ * @result the opposite sign of the represented integer value
+ */
+ Sign reverse_sign() const;
+
+ /**
+ * Flip (change!) the sign of the integer to its opposite value
+ */
+ void flip_sign();
+
+ /**
+ * Set sign of the integer
+ * @param sign new Sign to set
+ */
+ void set_sign(Sign sign);
+
+ /**
+ * Give absolute (positive) value of the integer
+ * @result absolute (positive) value of the integer
+ */
+ BigInt abs() const;
+
+ /**
+ * Give size of internal register
+ * @result size of internal register in words
+ */
+ u32bit size() const { return get_reg().size(); }
+
+ /**
+ * Give significant words of the represented integer value
+ * @result significant words of the represented integer value
+ */
+ u32bit sig_words() const
+ {
+ const word* x = reg.begin();
+ u32bit sig = reg.size();
+
+ while(sig && (x[sig-1] == 0))
+ sig--;
+ return sig;
+ }
+
+ /**
+ * Give byte-length of the integer
+ * @result byte-length of the represented integer value
+ */
+ u32bit bytes() const;
+
+ /**
+ * Get the bit-length of the integer.
+ * @result bit-length of the represented integer value
+ */
+ u32bit bits() const;
+
+ /**
+ * Return a pointer to the big integer word register.
+ * @result a pointer to the start of the internal register of
+ * the integer value
+ */
+ const word* data() const { return reg.begin(); }
+
+ /**
+ * return a reference to the internal register containing the value
+ * @result a reference to the word-array (SecureVector<word>)
+ * with the internal register value (containing the integer
+ * value)
+ */
+ SecureVector<word>& get_reg() { return reg; }
+
+ /**
+ * return a const reference to the internal register containing the value
+ * @result a const reference to the word-array (SecureVector<word>)
+ * with the internal register value (containing the integer
+ * value)
+ */
+ const SecureVector<word>& get_reg() const { return reg; }
+
+ /**
+ * Increase internal register buffer by n words
+ * @param n increase by n words
+ */
+ void grow_reg(u32bit n);
+
+ void grow_to(u32bit n);
+
+ /**
+ * Fill BigInt with a random number with size of bitsize
+ * @param rng the random number generator to use
+ * @param bitsize number of bits the created random value should have
+ */
+ void randomize(RandomNumberGenerator& rng, u32bit bitsize = 0);
+
+ /**
+ * Store BigInt-value in a given byte array
+ * @param buf destination byte array for the integer value
+ */
+ void binary_encode(byte buf[]) const;
+
+ /**
+ * Read integer value from a byte array with given size
+ * @param buf byte array buffer containing the integer
+ * @param length size of buf
+ */
+ void binary_decode(const byte buf[], u32bit length);
+
+ /**
+ * Read integer value from a byte array (MemoryRegion<byte>)
+ * @param buf the BigInt value to compare to the local value.
+ */
+ void binary_decode(const MemoryRegion<byte>& buf);
+
+ u32bit encoded_size(Base = Binary) const;
+
+ /**
+ @param rng a random number generator
+ @result a random integer between min and max
+ */
+ static BigInt random_integer(RandomNumberGenerator& rng,
+ const BigInt& min, const BigInt& max);
+
+ /**
+ * Encode the integer value from a BigInt to a SecureVector of bytes
+ * @param n the BigInt to use as integer source
+ * @param base number-base of resulting byte array representation
+ * @result SecureVector of bytes containing the integer with given base
+ */
+ static SecureVector<byte> encode(const BigInt& n, Base base = Binary);
+
+ /**
+ * Encode the integer value from a BigInt to a byte array
+ * @param buf destination byte array for the encoded integer
+ * value with given base
+ * @param n the BigInt to use as integer source
+ * @param base number-base of resulting byte array representation
+ */
+ static void encode(byte buf[], const BigInt& n, Base base = Binary);
+
+ /**
+ * Create a BigInt from an integer in a byte array
+ * @param buf the BigInt value to compare to the local value.
+ * @param length size of buf
+ * @param base number-base of the integer in buf
+ * @result BigInt-representing the given integer read from the byte array
+ */
+ static BigInt decode(const byte buf[], u32bit length,
+ Base base = Binary);
+
+ static BigInt decode(const MemoryRegion<byte>&, Base = Binary);
+
+ /**
+ * Encode a Big Integer to a byte array according to IEEE1363.
+ * @param n the Big Integer to encode
+ * @param bytes the length of the resulting SecureVector<byte>
+ * @result a SecureVector<byte> containing the encoded Big Integer
+ */
+ static SecureVector<byte> encode_1363(const BigInt& n, u32bit bytes);
+
+ /**
+ * Swap BigInt-value with given BigInt.
+ * @param bigint the BigInt to swap values with
+ */
+ void swap(BigInt& bigint);
+
+ /**
+ * constructors
+ */
+
+ /**
+ * Create empty BigInt
+ */
+ BigInt() { signedness = Positive; }
+
+ /**
+ * Create BigInt from 64bit-Integer value
+ * @param n 64bit-integer
+ */
+ BigInt(u64bit n);
+
+ /**
+ * Copy-Constructor: clone given BigInt
+ * @param bigint the BigInt to clone
+ */
+ BigInt(const BigInt& bigint);
+
+ /**
+ * Create BigInt from a string.
+ * If the string starts with 0x the rest of the string will be
+ * interpreted as hexadecimal digits.
+ * If the string starts with 0 and the second character is NOT
+ * an 'x' the string will be interpreted as octal digits.
+ * If the string starts with non-zero digit, it will be
+ * interpreted as a decimal number.
+ * @param str the string to parse for an integer value
+ */
+ BigInt(const std::string& str);
+
+ /**
+ * Create a BigInt from an integer in a byte array
+ * @param buf the BigInt value to compare to the local value.
+ * @param length size of buf
+ * @param base number-base of the integer in buf
+ */
+ BigInt(const byte buf[], u32bit length, Base base = Binary);
+
+ /**
+ * Create a random BigInt of the specified size
+ * @param rng random number generator
+ * @param bits size in bits
+ */
+ BigInt(RandomNumberGenerator& rng, u32bit bits);
+
+ /**
+ * Create BigInt from unsigned 32 bit integer value and an
+ * also specify the sign of the value
+ * @param n integer value
+ */
+ BigInt(Sign, u32bit n);
+
+ /**
+ * Create a number of the specified type and size
+ * @param type the type of number to create
+ * @param n the size
+ */
+ BigInt(NumberType type, u32bit n);
+
+ private:
+ SecureVector<word> reg;
+ Sign signedness;
+ };
+
+/*
+* Arithmetic Operators
+*/
+BigInt BOTAN_DLL operator+(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator-(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator*(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator/(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator%(const BigInt&, const BigInt&);
+word BOTAN_DLL operator%(const BigInt&, word);
+BigInt BOTAN_DLL operator<<(const BigInt&, u32bit);
+BigInt BOTAN_DLL operator>>(const BigInt&, u32bit);
+
+/*
+* Comparison Operators
+*/
+inline bool operator==(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) == 0); }
+inline bool operator!=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) != 0); }
+inline bool operator<=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) <= 0); }
+inline bool operator>=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) >= 0); }
+inline bool operator<(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) < 0); }
+inline bool operator>(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) > 0); }
+
+/*
+* I/O Operators
+*/
+BOTAN_DLL std::ostream& operator<<(std::ostream&, const BigInt&);
+BOTAN_DLL std::istream& operator>>(std::istream&, BigInt&);
+
+}
+
+namespace std {
+
+inline void swap(Botan::BigInt& a, Botan::BigInt& b) { a.swap(b); }
+
+}
+
+#endif
diff --git a/botan/build/botan/bit_ops.h b/botan/build/botan/bit_ops.h
new file mode 100644
index 0000000..c02ec53
--- /dev/null
+++ b/botan/build/botan/bit_ops.h
@@ -0,0 +1,91 @@
+/*
+* Bit/Word Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BIT_OPS_H__
+#define BOTAN_BIT_OPS_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Return true iff arg is 2**n for some n > 0
+* T should be an unsigned integer type
+*/
+template<typename T>
+inline bool power_of_2(T arg)
+ {
+ return ((arg != 0 && arg != 1) && ((arg & (arg-1)) == 0));
+ }
+
+/*
+* Return the index of the highest set bit
+* T is an unsigned integer type
+*/
+template<typename T>
+inline u32bit high_bit(T n)
+ {
+ for(u32bit i = 8*sizeof(T); i > 0; --i)
+ if((n >> (i - 1)) & 0x01)
+ return i;
+ return 0;
+ }
+
+/*
+* Return the index of the lowest set bit
+*/
+template<typename T>
+inline u32bit low_bit(T n)
+ {
+ for(u32bit i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return (i + 1);
+ return 0;
+ }
+
+/*
+* Return the number of significant bytes in n
+*/
+template<typename T>
+inline u32bit significant_bytes(T n)
+ {
+ for(u32bit j = 0; j != sizeof(T); ++j)
+ if(get_byte(j, n))
+ return sizeof(T)-j;
+ return 0;
+ }
+
+/*
+* Return the Hamming weight of n
+*/
+template<typename T>
+inline u32bit hamming_weight(T n)
+ {
+ const byte NIBBLE_WEIGHTS[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+ u32bit weight = 0;
+ for(u32bit i = 0; i != 2*sizeof(T); ++i)
+ weight += NIBBLE_WEIGHTS[(n >> (4*i)) & 0x0F];
+ return weight;
+ }
+
+/*
+* Count the trailing zero bits in n
+*/
+template<typename T>
+inline u32bit ctz(T n)
+ {
+ for(u32bit i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return i;
+ return 8*sizeof(T);
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/blinding.h b/botan/build/botan/blinding.h
new file mode 100644
index 0000000..5f7f9e6
--- /dev/null
+++ b/botan/build/botan/blinding.h
@@ -0,0 +1,34 @@
+/*
+* Blinder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLINDER_H__
+#define BOTAN_BLINDER_H__
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/*
+* Blinding Function Object
+*/
+class BOTAN_DLL Blinder
+ {
+ public:
+ BigInt blind(const BigInt&) const;
+ BigInt unblind(const BigInt&) const;
+
+ Blinder() {}
+ Blinder(const BigInt&, const BigInt&, const BigInt&);
+ private:
+ Modular_Reducer reducer;
+ mutable BigInt e, d;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/block_cipher.h b/botan/build/botan/block_cipher.h
new file mode 100644
index 0000000..01c45af
--- /dev/null
+++ b/botan/build/botan/block_cipher.h
@@ -0,0 +1,100 @@
+/**
+* Block Cipher Base Class
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLOCK_CIPHER_H__
+#define BOTAN_BLOCK_CIPHER_H__
+
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents a block cipher object.
+*
+* It would be very useful to extend this interface to support the
+* encryption of multiple blocks at a time. This could help
+* performance, wrt cache effects in the software implementations, and
+* could be a big deal when supporting block ciphers implemented as
+* hardware devices. It could be used by implementations of ECB, and
+* more importantly counter mode (which most designs are moving to, due
+* to the parallelism possible in counter mode which is not the case
+* with feedback-based modes like CBC).
+*
+* Probable future API here:
+* virtual void encrypt_n(const byte in[], byte out[],
+* u32bit blocks) const = 0;
+* virtual void decrypt_n(const byte in[], byte out[],
+* u32bit blocks) const = 0;
+*/
+class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * The block size of this algorithm.
+ */
+ const u32bit BLOCK_SIZE;
+
+ /**
+ * Encrypt a block.
+ * @param in The plaintext block to be encrypted as a byte array.
+ * Must be of length BLOCK_SIZE.
+ * @param out The byte array designated to hold the encrypted block.
+ * Must be of length BLOCK_SIZE.
+ */
+ void encrypt(const byte in[], byte out[]) const { enc(in, out); }
+
+ /**
+ * Decrypt a block.
+ * @param in The ciphertext block to be decypted as a byte array.
+ * Must be of length BLOCK_SIZE.
+ * @param out The byte array designated to hold the decrypted block.
+ * Must be of length BLOCK_SIZE.
+ */
+ void decrypt(const byte in[], byte out[]) const { dec(in, out); }
+
+ /**
+ * Encrypt a block.
+ * @param in The plaintext block to be encrypted as a byte array.
+ * Must be of length BLOCK_SIZE. Will hold the result when the function
+ * has finished.
+ */
+ void encrypt(byte block[]) const { enc(block, block); }
+
+ /**
+ * Decrypt a block.
+ * @param in The ciphertext block to be decrypted as a byte array.
+ * Must be of length BLOCK_SIZE. Will hold the result when the function
+ * has finished.
+ */
+ void decrypt(byte block[]) const { dec(block, block); }
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual BlockCipher* clone() const = 0;
+
+ /**
+ * Zeroize internal state
+ */
+ virtual void clear() throw() = 0;
+
+ BlockCipher(u32bit block_size,
+ u32bit key_min,
+ u32bit key_max = 0,
+ u32bit key_mod = 1) :
+ SymmetricAlgorithm(key_min, key_max, key_mod),
+ BLOCK_SIZE(block_size) {}
+
+ virtual ~BlockCipher() {}
+ private:
+ virtual void enc(const byte[], byte[]) const = 0;
+ virtual void dec(const byte[], byte[]) const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/blowfish.h b/botan/build/botan/blowfish.h
new file mode 100644
index 0000000..f0f2641
--- /dev/null
+++ b/botan/build/botan/blowfish.h
@@ -0,0 +1,40 @@
+/*
+* Blowfish
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLOWFISH_H__
+#define BOTAN_BLOWFISH_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Blowfish
+*/
+class BOTAN_DLL Blowfish : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Blowfish"; }
+ BlockCipher* clone() const { return new Blowfish; }
+ Blowfish() : BlockCipher(8, 1, 56) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ void generate_sbox(u32bit[], u32bit, u32bit&, u32bit&) const;
+
+ static const u32bit P_INIT[18];
+ static const u32bit S_INIT[1024];
+
+ SecureBuffer<u32bit, 1024> S;
+ SecureBuffer<u32bit, 18> P;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/botan.h b/botan/build/botan/botan.h
new file mode 100644
index 0000000..3fa1312
--- /dev/null
+++ b/botan/build/botan/botan.h
@@ -0,0 +1,18 @@
+/**
+* A vague catch all include file for Botan
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/init.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/version.h>
+#include <botan/parsing.h>
+
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ #include <botan/auto_rng.h>
+#endif
diff --git a/botan/build/botan/bswap.h b/botan/build/botan/bswap.h
new file mode 100644
index 0000000..ec1e814
--- /dev/null
+++ b/botan/build/botan/bswap.h
@@ -0,0 +1,62 @@
+/*
+* Byte Swapping Operations
+* (C) 1999-2008 Jack Lloyd
+* (C) 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BYTE_SWAP_H__
+#define BOTAN_BYTE_SWAP_H__
+
+#include <botan/types.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* Byte Swapping Functions
+*/
+inline u16bit reverse_bytes(u16bit input)
+ {
+ return rotate_left(input, 8);
+ }
+
+inline u32bit reverse_bytes(u32bit input)
+ {
+#if BOTAN_USE_GCC_INLINE_ASM && \
+ (defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64))
+
+ /* GCC-style inline assembly for x86 or x86-64 */
+ asm("bswapl %0" : "=r" (input) : "0" (input));
+ return input;
+
+#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32)
+ /* Visual C++ inline asm for 32-bit x86, by Yves Jerschow */
+ __asm mov eax, input;
+ __asm bswap eax;
+
+#else
+ /* Generic implementation */
+ input = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8);
+ return rotate_left(input, 16);
+#endif
+ }
+
+inline u64bit reverse_bytes(u64bit input)
+ {
+#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64)
+ asm("bswapq %0" : "=r" (input) : "0" (input));
+ return input;
+#else
+ u32bit hi = ((input >> 40) & 0x00FF00FF) | ((input >> 24) & 0xFF00FF00);
+ u32bit lo = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8);
+ hi = (hi << 16) | (hi >> 16);
+ lo = (lo << 16) | (lo >> 16);
+ return (static_cast<u64bit>(lo) << 32) | hi;
+#endif
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/buf_comp.h b/botan/build/botan/buf_comp.h
new file mode 100644
index 0000000..3f1e90b
--- /dev/null
+++ b/botan/build/botan/buf_comp.h
@@ -0,0 +1,126 @@
+/**
+* BufferedComputation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BUFFERED_COMPUTATION_H__
+#define BOTAN_BUFFERED_COMPUTATION_H__
+
+#include <botan/secmem.h>
+
+namespace Botan {
+
+/**
+* This class represents any kind of computation which
+* uses an internal state,
+* such as hash functions.
+*/
+class BOTAN_DLL BufferedComputation
+ {
+ public:
+
+ /**
+ * The length of the output of this function in bytes.
+ */
+ const u32bit OUTPUT_LENGTH;
+
+ /**
+ * Add new input to process.
+ * @param in the input to process as a byte array
+ * @param the length of the byte array
+ */
+ void update(const byte in[], u32bit length) { add_data(in, length); }
+
+ /**
+ * Add new input to process.
+ * @param in the input to process as a MemoryRegion
+ */
+ void update(const MemoryRegion<byte>& in) { add_data(in, in.size()); }
+
+ /**
+ * Add new input to process.
+ * @param str the input to process as a std::string. Will be interpreted
+ * as a byte array based on
+ * the strings encoding.
+ */
+ void update(const std::string& str)
+ {
+ add_data(reinterpret_cast<const byte*>(str.data()), str.size());
+ }
+
+ /**
+ * Process a single byte.
+ * @param in the byte to process
+ */
+ void update(byte in) { add_data(&in, 1); }
+
+ /**
+ * Complete the computation and retrieve the
+ * final result.
+ * @param out The byte array to be filled with the result.
+ * Must be of length OUTPUT_LENGTH.
+ */
+ void final(byte out[]) { final_result(out); }
+
+ /**
+ * Complete the computation and retrieve the
+ * final result.
+ * @return a SecureVector holding the result
+ */
+ SecureVector<byte> final()
+ {
+ SecureVector<byte> output(OUTPUT_LENGTH);
+ final_result(output);
+ return output;
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process as a byte array
+ * @param length the length of the byte array
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const byte in[], u32bit length)
+ {
+ add_data(in, length);
+ return final();
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const MemoryRegion<byte>& in)
+ {
+ add_data(in, in.size());
+ return final();
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process as a string
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const std::string& in)
+ {
+ update(in);
+ return final();
+ }
+
+ BufferedComputation(u32bit out_len) : OUTPUT_LENGTH(out_len) {}
+ virtual ~BufferedComputation() {}
+ private:
+ BufferedComputation& operator=(const BufferedComputation&);
+ virtual void add_data(const byte[], u32bit) = 0;
+ virtual void final_result(byte[]) = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/buf_filt.h b/botan/build/botan/buf_filt.h
new file mode 100644
index 0000000..ce3dbc9
--- /dev/null
+++ b/botan/build/botan/buf_filt.h
@@ -0,0 +1,39 @@
+/*
+* Buffering Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BUFFERING_FILTER_H__
+#define BOTAN_BUFFERING_FILTER_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* Buffering_Filter: This class represents filters for operations that
+* maintain an internal state.
+*/
+
+class BOTAN_DLL Buffering_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ virtual void end_msg();
+ Buffering_Filter(u32bit, u32bit = 0);
+ virtual ~Buffering_Filter() {}
+ protected:
+ virtual void initial_block(const byte[]) {}
+ virtual void main_block(const byte[]) = 0;
+ virtual void final_block(const byte[], u32bit) = 0;
+ private:
+ const u32bit INITIAL_BLOCK_SIZE, BLOCK_SIZE;
+ SecureVector<byte> initial, block;
+ u32bit initial_block_pos, block_pos;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/build.h b/botan/build/botan/build.h
new file mode 100644
index 0000000..e23eb82
--- /dev/null
+++ b/botan/build/botan/build.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BOTAN_BUILD_CONFIG_H_QT
+#define BOTAN_BUILD_CONFIG_H_QT
+
+#include <qglobal.h>
+
+#if defined(Q_OS_WIN)
+# include "build_windows.h"
+#elif defined(Q_OS_UNIX)
+# include "build_unix.h"
+#endif
+
+#endif
diff --git a/botan/build/botan/build_unix.h b/botan/build/botan/build_unix.h
new file mode 100644
index 0000000..a49de5d
--- /dev/null
+++ b/botan/build/botan/build_unix.h
@@ -0,0 +1,353 @@
+
+#ifndef BOTAN_BUILD_CONFIG_H__
+#define BOTAN_BUILD_CONFIG_H__
+
+/* This file was automatically generated Tue Jan 12 09:38:57 2010 UTC */
+
+#define BOTAN_VERSION_MAJOR 1
+#define BOTAN_VERSION_MINOR 8
+#define BOTAN_VERSION_PATCH 8
+
+#ifndef BOTAN_DLL
+ #define BOTAN_DLL __attribute__ ((visibility("default")))
+#endif
+
+/* Chunk sizes */
+#define BOTAN_DEFAULT_BUFFER_SIZE 4096
+#define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024
+
+/* BigInt toggles */
+#define BOTAN_MP_WORD_BITS 32
+#define BOTAN_KARAT_MUL_THRESHOLD 32
+#define BOTAN_KARAT_SQR_THRESHOLD 32
+#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64
+
+/* PK key consistency checking toggles */
+#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1
+
+/* Should we use GCC-style inline assembler? */
+#if !defined(BOTAN_USE_GCC_INLINE_ASM) && defined(__GNUG__)
+ #define BOTAN_USE_GCC_INLINE_ASM 1
+#endif
+
+#ifndef BOTAN_USE_GCC_INLINE_ASM
+ #define BOTAN_USE_GCC_INLINE_ASM 0
+#endif
+
+
+#define BOTAN_USE_STD_TR1
+
+/* Module definitions */
+#define BOTAN_HAS_ADLER32
+#define BOTAN_HAS_AES
+#define BOTAN_HAS_ALGORITHM_FACTORY
+#define BOTAN_HAS_ALLOC_MMAP
+#define BOTAN_HAS_ANSI_X919_MAC
+#define BOTAN_HAS_ARC4
+#define BOTAN_HAS_ASN1
+#define BOTAN_HAS_AUTO_SEEDING_RNG
+#define BOTAN_HAS_BASE64_CODEC
+#define BOTAN_HAS_BIGINT
+#define BOTAN_HAS_BIGINT_GFP
+#define BOTAN_HAS_BIGINT_MATH
+#define BOTAN_HAS_BLOCK_CIPHER
+#define BOTAN_HAS_BLOWFISH
+#define BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES
+#define BOTAN_HAS_CAST
+#define BOTAN_HAS_CBC
+#define BOTAN_HAS_CBC_MAC
+#define BOTAN_HAS_CFB
+#define BOTAN_HAS_CIPHER_MODEBASE
+#define BOTAN_HAS_CIPHER_MODE_PADDING
+#define BOTAN_HAS_CMAC
+#define BOTAN_HAS_CMS
+#define BOTAN_HAS_CRC24
+#define BOTAN_HAS_CRC32
+#define BOTAN_HAS_CRYPTO_BOX
+#define BOTAN_HAS_CTR
+#define BOTAN_HAS_CTS
+#define BOTAN_HAS_DEFAULT_ENGINE
+#define BOTAN_HAS_DES
+#define BOTAN_HAS_DIFFIE_HELLMAN
+#define BOTAN_HAS_DLIES
+#define BOTAN_HAS_DL_GROUP
+#define BOTAN_HAS_DL_PUBLIC_KEY_FAMILY
+#define BOTAN_HAS_DSA
+#define BOTAN_HAS_EAX
+#define BOTAN_HAS_ECB
+#define BOTAN_HAS_ECC_DOMAIN_PARAMATERS
+#define BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO
+#define BOTAN_HAS_ECDSA
+#define BOTAN_HAS_ECKAEG
+#define BOTAN_HAS_ELGAMAL
+#define BOTAN_HAS_EME1
+#define BOTAN_HAS_EME_PKCS1v15
+#define BOTAN_HAS_EMSA1
+#define BOTAN_HAS_EMSA1_BSI
+#define BOTAN_HAS_EMSA2
+#define BOTAN_HAS_EMSA3
+#define BOTAN_HAS_EMSA4
+#define BOTAN_HAS_EMSA_RAW
+#define BOTAN_HAS_ENGINES
+#define BOTAN_HAS_ENTROPY_SRC_DEVICE
+#define BOTAN_HAS_ENTROPY_SRC_EGD
+#define BOTAN_HAS_ENTROPY_SRC_FTW
+#define BOTAN_HAS_ENTROPY_SRC_UNIX
+#define BOTAN_HAS_FILTERS
+#define BOTAN_HAS_FORK_256
+#define BOTAN_HAS_GOST_28147_89
+#define BOTAN_HAS_GOST_34_11
+#define BOTAN_HAS_HASH_ID
+#define BOTAN_HAS_HAS_160
+#define BOTAN_HAS_HEX_CODEC
+#define BOTAN_HAS_HMAC
+#define BOTAN_HAS_HMAC_RNG
+#define BOTAN_HAS_IDEA
+#define BOTAN_HAS_IF_PUBLIC_KEY_FAMILY
+#define BOTAN_HAS_KASUMI
+#define BOTAN_HAS_KDF1
+#define BOTAN_HAS_KDF2
+#define BOTAN_HAS_KDF_BASE
+#define BOTAN_HAS_KEYPAIR_TESTING
+#define BOTAN_HAS_LIBSTATE_MODULE
+#define BOTAN_HAS_LION
+#define BOTAN_HAS_LUBY_RACKOFF
+#define BOTAN_HAS_MARS
+#define BOTAN_HAS_MD2
+#define BOTAN_HAS_MD4
+#define BOTAN_HAS_MD5
+#define BOTAN_HAS_MDX_HASH_FUNCTION
+#define BOTAN_HAS_MGF1
+#define BOTAN_HAS_MISTY1
+#define BOTAN_HAS_MUTEX_NOOP
+#define BOTAN_HAS_MUTEX_PTHREAD
+#define BOTAN_HAS_MUTEX_WRAPPERS
+#define BOTAN_HAS_NOEKEON
+#define BOTAN_HAS_NYBERG_RUEPPEL
+#define BOTAN_HAS_OFB
+#define BOTAN_HAS_OID_LOOKUP
+#define BOTAN_HAS_OPENPGP_CODEC
+#define BOTAN_HAS_PARALLEL_HASH
+#define BOTAN_HAS_PASSWORD_BASED_ENCRYPTION
+#define BOTAN_HAS_PBE_PKCS_V15
+#define BOTAN_HAS_PBE_PKCS_V20
+#define BOTAN_HAS_PBKDF1
+#define BOTAN_HAS_PBKDF2
+#define BOTAN_HAS_PEM_CODEC
+#define BOTAN_HAS_PGPS2K
+#define BOTAN_HAS_PIPE_UNIXFD_IO
+#define BOTAN_HAS_PK_PADDING
+#define BOTAN_HAS_PUBLIC_KEY_CRYPTO
+#define BOTAN_HAS_RANDPOOL
+#define BOTAN_HAS_RC2
+#define BOTAN_HAS_RC5
+#define BOTAN_HAS_RC6
+#define BOTAN_HAS_RIPEMD_128
+#define BOTAN_HAS_RIPEMD_160
+#define BOTAN_HAS_RSA
+#define BOTAN_HAS_RUNTIME_BENCHMARKING
+#define BOTAN_HAS_RW
+#define BOTAN_HAS_SAFER
+#define BOTAN_HAS_SALSA20
+#define BOTAN_HAS_SEED
+#define BOTAN_HAS_SELFTESTS
+#define BOTAN_HAS_SERPENT
+#define BOTAN_HAS_SHA1
+#define BOTAN_HAS_SHA2
+#define BOTAN_HAS_SKEIN_512
+#define BOTAN_HAS_SKIPJACK
+#define BOTAN_HAS_SQUARE
+#define BOTAN_HAS_SSL3_MAC
+#define BOTAN_HAS_SSL_V3_PRF
+#define BOTAN_HAS_STREAM_CIPHER
+#define BOTAN_HAS_TEA
+#define BOTAN_HAS_TIGER
+#define BOTAN_HAS_TIMER
+#ifndef Q_OS_MAC
+#define BOTAN_HAS_TIMER_POSIX
+#endif
+#define BOTAN_HAS_TIMER_UNIX
+#define BOTAN_HAS_TLS_V10_PRF
+#define BOTAN_HAS_TURING
+#define BOTAN_HAS_TWOFISH
+#define BOTAN_HAS_UTIL_FUNCTIONS
+#define BOTAN_HAS_WHIRLPOOL
+#define BOTAN_HAS_WID_WAKE
+#define BOTAN_HAS_X509
+#define BOTAN_HAS_X931_RNG
+#define BOTAN_HAS_X942_PRF
+#define BOTAN_HAS_XTEA
+#define BOTAN_HAS_XTS
+
+/* Local configuration options */
+
+
+/*
+christian@christian-linux ran 'configure.py --os=linux --cpu=ia32 --cc=gcc --disable-asm'
+
+Target
+-------
+Compiler: g++ -O2 -finline-functions
+Arch: ia32/ia32
+OS: linux
+
+Modules
+-------
+adler32 (Adler32)
+aes (AES)
+algo_factory (Algorithm Factory)
+alloc (Allocator)
+alloc_mmap (Disk Based Allocation System)
+arc4 (ARC4)
+asn1 (ASN.1/BER/DER module)
+auto_rng (Auto-seeded Random Number Generator)
+base64 (Base64 Codec)
+benchmark (Benchmarking)
+bigint (BigInt)
+block (Block Ciphers)
+blowfish (Blowfish)
+buf_comp (Buffered Computation)
+cast (CAST)
+cbc (CBC block cipher mode)
+cbc_mac (CBC-MAC)
+cfb (CFB block cipher mode)
+cmac (CMAC)
+cms (CMS)
+crc24 (CRC-24)
+crc32 (CRC-32)
+cryptobox (Crypto Box)
+ctr (CTR block cipher mode)
+cts (CTS block cipher mode)
+cvc (Card Verifiable Certificates)
+datastor (Datastore)
+def_engine (Default Engine)
+des (DES)
+dev_random (RNG Device Reader)
+dh (Diffie-Hellman Key Agreement)
+dl_algo (Discrete Logarithm PK Algorithms)
+dl_group (DL Group)
+dlies (DLIES)
+dsa (DSA)
+eax (EAX block cipher mode)
+ec_dompar (ECC Domain Parameters)
+ecb (ECB block cipher mode)
+ecc_key (ECC Public Key)
+ecdsa (ECDSA)
+eckaeg (ECKAEG)
+egd (EGD Entropy Source)
+elgamal (ElGamal)
+eme1 (EME1)
+eme_pkcs (PKCSv1 v1.5 EME)
+emsa1 (EMSA1)
+emsa1_bsi (EMSA1 (BSI variant))
+emsa2 (EMSA2)
+emsa3 (EMSA3)
+emsa4 (EMSA4)
+emsa_raw (EMSA-Raw)
+engine (Engines)
+entropy (Entropy Sources)
+fd_unix (Unix I/O support for Pipe)
+filters (Pipe/Filter)
+fork256 (FORK-256)
+gettimeofday (Unix Timer)
+gfpmath (GF(p) Math)
+gost_28147 (GOST 28147-89)
+gost_3411 (GOST 34.11)
+has160 (HAS-160)
+hash (Hash Functions)
+hash_id (Hash Function Identifiers)
+hex (Hex Codec)
+hmac (HMAC)
+hmac_rng (HMAC RNG)
+idea (IDEA)
+if_algo (Integer Factorization Algorithms)
+kasumi (Kasumi)
+kdf (KDF Base Class)
+kdf1 (KDF1)
+kdf2 (KDF2)
+keypair (Keypair Testing)
+libstate (Botan Libstate Module)
+lion (Lion)
+lubyrack (Luby-Rackoff)
+mac (Message Authentication Codes)
+mars (MARS)
+md2 (MD2)
+md4 (MD4)
+md5 (MD5)
+mdx_hash (MDx Hash Base)
+mem_pool (Memory Pool Allocator)
+mgf1 (MGF1)
+misty1 (MISTY-1)
+mode_pad (Cipher Mode Padding Method)
+modes (Cipher Mode Base Class)
+monty_generic (Montgomery Reduction)
+mp_generic (MPI Core (C++))
+mulop_generic (BigInt Multiply-Add)
+mutex (Mutex Wrappers)
+noekeon (Noekeon)
+noop_mutex (No-Op Mutex)
+nr (Nyberg-Rueppel)
+numbertheory (Math Functions)
+ofb (OFB block cipher mode)
+oid_lookup (OID Lookup)
+openpgp (OpenPGP Codec)
+par_hash (Parallel Hash)
+pbe (PBE Base)
+pbes1 (PKCS5 v1.5 PBE)
+pbes2 (PKCS5 v2.0 PBE)
+pbkdf1 (Pbkdf1)
+pbkdf2 (Pbkdf2)
+pem (PEM Codec)
+pgps2k (Pgps2k)
+pk_codecs (PK codecs (PKCS8, X.509))
+pk_pad (Public Key EME/EMSA Padding Modes)
+posix_rt (POSIX Timer)
+proc_walk (File Tree Walking Entropy Source)
+pthreads (Pthread Mutex)
+pubkey (Public Key Base)
+randpool (Randpool RNG)
+rc2 (RC2)
+rc5 (RC5)
+rc6 (RC6)
+rmd128 (RIPEMD-128)
+rmd160 (RIPEMD-160)
+rng (Random Number Generators)
+rsa (RSA)
+rw (Rabin-Williams)
+s2k (String to Key Functions)
+safer (SAFER)
+salsa20 (Salsa20)
+seed (SEED)
+selftest (Selftests)
+serpent (Serpent)
+sha1 (SHA-1)
+sha2 (SHA-2 (224, 256, 384, 512))
+skein (Skein)
+skipjack (Skipjack)
+square (Square)
+ssl3mac (SSLv3 MAC)
+ssl_prf (SSLv3 PRF)
+stream (Stream Ciphers)
+sym_algo (Symmetric Algorithms)
+system_alloc (Default (Malloc) Allocators)
+tea (TEA)
+tiger (Tiger)
+timer (Timer Base Class)
+tls_prf (TLS v1.0 PRF)
+turing (Turing)
+twofish (Twofish)
+unix_procs (Generic Unix Entropy Source)
+utils (Utility Functions)
+whirlpool (Whirlpool)
+wid_wake (WiderWake)
+x509 (X.509)
+x919_mac (ANSI X9.19 MAC)
+x931_rng (ANSI X9.31 PRNG)
+x942_prf (X942 PRF)
+xtea (XTEA)
+xts (XTS block cipher mode)
+*/
+
+#endif
diff --git a/botan/build/botan/build_windows.h b/botan/build/botan/build_windows.h
new file mode 100644
index 0000000..8e9bc03
--- /dev/null
+++ b/botan/build/botan/build_windows.h
@@ -0,0 +1,335 @@
+
+#ifndef BOTAN_BUILD_CONFIG_H__
+#define BOTAN_BUILD_CONFIG_H__
+
+/* This file was automatically generated Mon Jan 11 14:51:24 2010 UTC */
+
+#define BOTAN_VERSION_MAJOR 1
+#define BOTAN_VERSION_MINOR 8
+#define BOTAN_VERSION_PATCH 8
+
+#ifndef BOTAN_DLL
+# if !defined(Q_CC_MINGW)
+# define BOTAN_DLL __declspec(dllexport)
+# else
+# define BOTAN_DLL
+# endif
+#endif
+
+/* Chunk sizes */
+#define BOTAN_DEFAULT_BUFFER_SIZE 4096
+#define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024
+
+/* BigInt toggles */
+#define BOTAN_MP_WORD_BITS 32
+#define BOTAN_KARAT_MUL_THRESHOLD 32
+#define BOTAN_KARAT_SQR_THRESHOLD 32
+#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64
+
+/* PK key consistency checking toggles */
+#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1
+
+/* Should we use GCC-style inline assembler? */
+#if !defined(BOTAN_USE_GCC_INLINE_ASM) && defined(__GNUG__)
+ #define BOTAN_USE_GCC_INLINE_ASM 1
+#endif
+
+#ifndef BOTAN_USE_GCC_INLINE_ASM
+ #define BOTAN_USE_GCC_INLINE_ASM 0
+#endif
+
+/* Target identification and feature test macros */
+#define BOTAN_TARGET_OS_IS_WINDOWS
+#define BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK
+
+/* Module definitions */
+#if defined(Q_CC_MINGW)
+# define BOTAN_USE_STD_TR1
+# define BOTAN_HAS_BIGINT_GFP
+# define BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES
+# define BOTAN_HAS_ECC_DOMAIN_PARAMATERS
+# define BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO
+#endif
+
+#define BOTAN_HAS_ADLER32
+#define BOTAN_HAS_AES
+#define BOTAN_HAS_ALGORITHM_FACTORY
+#define BOTAN_HAS_ANSI_X919_MAC
+#define BOTAN_HAS_ARC4
+#define BOTAN_HAS_ASN1
+#define BOTAN_HAS_AUTO_SEEDING_RNG
+#define BOTAN_HAS_BASE64_CODEC
+#define BOTAN_HAS_BIGINT
+#define BOTAN_HAS_BIGINT_MATH
+#define BOTAN_HAS_BLOCK_CIPHER
+#define BOTAN_HAS_BLOWFISH
+#define BOTAN_HAS_CAST
+#define BOTAN_HAS_CBC
+#define BOTAN_HAS_CBC_MAC
+#define BOTAN_HAS_CFB
+#define BOTAN_HAS_CIPHER_MODEBASE
+#define BOTAN_HAS_CIPHER_MODE_PADDING
+#define BOTAN_HAS_CMAC
+#define BOTAN_HAS_CMS
+#define BOTAN_HAS_CRC24
+#define BOTAN_HAS_CRC32
+#define BOTAN_HAS_CRYPTO_BOX
+#define BOTAN_HAS_CTR
+#define BOTAN_HAS_CTS
+#define BOTAN_HAS_DEFAULT_ENGINE
+#define BOTAN_HAS_DES
+#define BOTAN_HAS_DIFFIE_HELLMAN
+#define BOTAN_HAS_DLIES
+#define BOTAN_HAS_DL_GROUP
+#define BOTAN_HAS_DL_PUBLIC_KEY_FAMILY
+#define BOTAN_HAS_DSA
+#define BOTAN_HAS_EAX
+#define BOTAN_HAS_ECB
+#define BOTAN_HAS_ELGAMAL
+#define BOTAN_HAS_EME1
+#define BOTAN_HAS_EME_PKCS1v15
+#define BOTAN_HAS_EMSA1
+#define BOTAN_HAS_EMSA1_BSI
+#define BOTAN_HAS_EMSA2
+#define BOTAN_HAS_EMSA3
+#define BOTAN_HAS_EMSA4
+#define BOTAN_HAS_EMSA_RAW
+#define BOTAN_HAS_ENGINES
+#define BOTAN_HAS_ENTROPY_SRC_CAPI
+#define BOTAN_HAS_ENTROPY_SRC_WIN32
+#define BOTAN_HAS_FILTERS
+#define BOTAN_HAS_FORK_256
+#define BOTAN_HAS_GOST_28147_89
+#define BOTAN_HAS_GOST_34_11
+#define BOTAN_HAS_HASH_ID
+#define BOTAN_HAS_HAS_160
+#define BOTAN_HAS_HEX_CODEC
+#define BOTAN_HAS_HMAC
+#define BOTAN_HAS_HMAC_RNG
+#define BOTAN_HAS_IDEA
+#define BOTAN_HAS_IF_PUBLIC_KEY_FAMILY
+#define BOTAN_HAS_KASUMI
+#define BOTAN_HAS_KDF1
+#define BOTAN_HAS_KDF2
+#define BOTAN_HAS_KDF_BASE
+#define BOTAN_HAS_KEYPAIR_TESTING
+#define BOTAN_HAS_LIBSTATE_MODULE
+#define BOTAN_HAS_LION
+#define BOTAN_HAS_LUBY_RACKOFF
+#define BOTAN_HAS_MARS
+#define BOTAN_HAS_MD2
+#define BOTAN_HAS_MD4
+#define BOTAN_HAS_MD5
+#define BOTAN_HAS_MDX_HASH_FUNCTION
+#define BOTAN_HAS_MGF1
+#define BOTAN_HAS_MISTY1
+#define BOTAN_HAS_MUTEX_NOOP
+#define BOTAN_HAS_MUTEX_WIN32
+#define BOTAN_HAS_MUTEX_WRAPPERS
+#define BOTAN_HAS_NOEKEON
+#define BOTAN_HAS_NYBERG_RUEPPEL
+#define BOTAN_HAS_OFB
+#define BOTAN_HAS_OID_LOOKUP
+#define BOTAN_HAS_OPENPGP_CODEC
+#define BOTAN_HAS_PARALLEL_HASH
+#define BOTAN_HAS_PASSWORD_BASED_ENCRYPTION
+#define BOTAN_HAS_PBE_PKCS_V15
+#define BOTAN_HAS_PBE_PKCS_V20
+#define BOTAN_HAS_PBKDF1
+#define BOTAN_HAS_PBKDF2
+#define BOTAN_HAS_PEM_CODEC
+#define BOTAN_HAS_PGPS2K
+#define BOTAN_HAS_PK_PADDING
+#define BOTAN_HAS_PUBLIC_KEY_CRYPTO
+#define BOTAN_HAS_RANDPOOL
+#define BOTAN_HAS_RC2
+#define BOTAN_HAS_RC5
+#define BOTAN_HAS_RC6
+#define BOTAN_HAS_RIPEMD_128
+#define BOTAN_HAS_RIPEMD_160
+#define BOTAN_HAS_RSA
+#define BOTAN_HAS_RUNTIME_BENCHMARKING
+#define BOTAN_HAS_RW
+#define BOTAN_HAS_SAFER
+#define BOTAN_HAS_SALSA20
+#define BOTAN_HAS_SEED
+#define BOTAN_HAS_SELFTESTS
+#define BOTAN_HAS_SERPENT
+#define BOTAN_HAS_SHA1
+#define BOTAN_HAS_SHA2
+#define BOTAN_HAS_SKEIN_512
+#define BOTAN_HAS_SKIPJACK
+#define BOTAN_HAS_SQUARE
+#define BOTAN_HAS_SSL3_MAC
+#define BOTAN_HAS_SSL_V3_PRF
+#define BOTAN_HAS_STREAM_CIPHER
+#define BOTAN_HAS_TEA
+#define BOTAN_HAS_TIGER
+#define BOTAN_HAS_TIMER
+#define BOTAN_HAS_TIMER_WIN32
+#define BOTAN_HAS_TLS_V10_PRF
+#define BOTAN_HAS_TURING
+#define BOTAN_HAS_TWOFISH
+#define BOTAN_HAS_UTIL_FUNCTIONS
+#define BOTAN_HAS_WHIRLPOOL
+#define BOTAN_HAS_WID_WAKE
+#define BOTAN_HAS_X509
+#define BOTAN_HAS_X931_RNG
+#define BOTAN_HAS_X942_PRF
+#define BOTAN_HAS_XTEA
+#define BOTAN_HAS_XTS
+
+
+/* Local configuration options */
+
+
+/*
+Modules
+-------
+adler32 (Adler32)
+aes (AES)
+algo_factory (Algorithm Factory)
+alloc (Allocator)
+arc4 (ARC4)
+asn1 (ASN.1/BER/DER module)
+auto_rng (Auto-seeded Random Number Generator)
+base64 (Base64 Codec)
+benchmark (Benchmarking)
+bigint (BigInt)
+block (Block Ciphers)
+blowfish (Blowfish)
+buf_comp (Buffered Computation)
+cast (CAST)
+cbc (CBC block cipher mode)
+cbc_mac (CBC-MAC)
+cfb (CFB block cipher mode)
+cmac (CMAC)
+cms (CMS)
+crc24 (CRC-24)
+crc32 (CRC-32)
+cryptoapi_rng (Win32 CryptoAPI Entropy Source)
+cryptobox (Crypto Box)
+ctr (CTR block cipher mode)
+cts (CTS block cipher mode)
+datastor (Datastore)
+def_engine (Default Engine)
+des (DES)
+dh (Diffie-Hellman Key Agreement)
+dl_algo (Discrete Logarithm PK Algorithms)
+dl_group (DL Group)
+dlies (DLIES)
+dsa (DSA)
+eax (EAX block cipher mode)
+ecb (ECB block cipher mode)
+elgamal (ElGamal)
+eme1 (EME1)
+eme_pkcs (PKCSv1 v1.5 EME)
+emsa1 (EMSA1)
+emsa1_bsi (EMSA1 (BSI variant))
+emsa2 (EMSA2)
+emsa3 (EMSA3)
+emsa4 (EMSA4)
+emsa_raw (EMSA-Raw)
+engine (Engines)
+entropy (Entropy Sources)
+filters (Pipe/Filter)
+fork256 (FORK-256)
+gost_28147 (GOST 28147-89)
+gost_3411 (GOST 34.11)
+has160 (HAS-160)
+hash (Hash Functions)
+hash_id (Hash Function Identifiers)
+hex (Hex Codec)
+hmac (HMAC)
+hmac_rng (HMAC RNG)
+idea (IDEA)
+if_algo (Integer Factorization Algorithms)
+kasumi (Kasumi)
+kdf (KDF Base Class)
+kdf1 (KDF1)
+kdf2 (KDF2)
+keypair (Keypair Testing)
+libstate (Botan Libstate Module)
+lion (Lion)
+lubyrack (Luby-Rackoff)
+mac (Message Authentication Codes)
+mars (MARS)
+md2 (MD2)
+md4 (MD4)
+md5 (MD5)
+mdx_hash (MDx Hash Base)
+mem_pool (Memory Pool Allocator)
+mgf1 (MGF1)
+misty1 (MISTY-1)
+mode_pad (Cipher Mode Padding Method)
+modes (Cipher Mode Base Class)
+monty_generic (Montgomery Reduction)
+mp_generic (MPI Core (C++))
+mulop_generic (BigInt Multiply-Add)
+mutex (Mutex Wrappers)
+noekeon (Noekeon)
+noop_mutex (No-Op Mutex)
+nr (Nyberg-Rueppel)
+numbertheory (Math Functions)
+ofb (OFB block cipher mode)
+oid_lookup (OID Lookup)
+openpgp (OpenPGP Codec)
+par_hash (Parallel Hash)
+pbe (PBE Base)
+pbes1 (PKCS5 v1.5 PBE)
+pbes2 (PKCS5 v2.0 PBE)
+pbkdf1 (Pbkdf1)
+pbkdf2 (Pbkdf2)
+pem (PEM Codec)
+pgps2k (Pgps2k)
+pk_codecs (PK codecs (PKCS8, X.509))
+pk_pad (Public Key EME/EMSA Padding Modes)
+pubkey (Public Key Base)
+randpool (Randpool RNG)
+rc2 (RC2)
+rc5 (RC5)
+rc6 (RC6)
+rmd128 (RIPEMD-128)
+rmd160 (RIPEMD-160)
+rng (Random Number Generators)
+rsa (RSA)
+rw (Rabin-Williams)
+s2k (String to Key Functions)
+safer (SAFER)
+salsa20 (Salsa20)
+seed (SEED)
+selftest (Selftests)
+serpent (Serpent)
+sha1 (SHA-1)
+sha2 (SHA-2 (224, 256, 384, 512))
+skein (Skein)
+skipjack (Skipjack)
+square (Square)
+ssl3mac (SSLv3 MAC)
+ssl_prf (SSLv3 PRF)
+stream (Stream Ciphers)
+sym_algo (Symmetric Algorithms)
+system_alloc (Default (Malloc) Allocators)
+tea (TEA)
+tiger (Tiger)
+timer (Timer Base Class)
+tls_prf (TLS v1.0 PRF)
+turing (Turing)
+twofish (Twofish)
+utils (Utility Functions)
+whirlpool (Whirlpool)
+wid_wake (WiderWake)
+win32_crit_section (Win32 Mutex)
+win32_query_perf_ctr (Win32 Timer)
+win32_stats (Win32 Entropy Source)
+x509 (X.509)
+x919_mac (ANSI X9.19 MAC)
+x931_rng (ANSI X9.31 PRNG)
+x942_prf (X942 PRF)
+xtea (XTEA)
+xts (XTS block cipher mode)
+*/
+
+#endif
diff --git a/botan/build/botan/cast128.h b/botan/build/botan/cast128.h
new file mode 100644
index 0000000..6804814
--- /dev/null
+++ b/botan/build/botan/cast128.h
@@ -0,0 +1,47 @@
+/*
+* CAST-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CAST128_H__
+#define BOTAN_CAST128_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CAST-128
+*/
+class BOTAN_DLL CAST_128 : public BlockCipher
+ {
+ public:
+ void clear() throw() { MK.clear(); RK.clear(); }
+ std::string name() const { return "CAST-128"; }
+ BlockCipher* clone() const { return new CAST_128; }
+ CAST_128() : BlockCipher(8, 11, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void key_schedule(u32bit[16], u32bit[4]);
+
+ static const u32bit S5[256];
+ static const u32bit S6[256];
+ static const u32bit S7[256];
+ static const u32bit S8[256];
+
+ SecureBuffer<u32bit, 16> MK, RK;
+ };
+
+extern const u32bit CAST_SBOX1[256];
+extern const u32bit CAST_SBOX2[256];
+extern const u32bit CAST_SBOX3[256];
+extern const u32bit CAST_SBOX4[256];
+
+}
+
+#endif
diff --git a/botan/build/botan/cast256.h b/botan/build/botan/cast256.h
new file mode 100644
index 0000000..cd48edd
--- /dev/null
+++ b/botan/build/botan/cast256.h
@@ -0,0 +1,44 @@
+/*
+* CAST-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CAST256_H__
+#define BOTAN_CAST256_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CAST-256
+*/
+class BOTAN_DLL CAST_256 : public BlockCipher
+ {
+ public:
+ void clear() throw() { MK.clear(); RK.clear(); }
+ std::string name() const { return "CAST-256"; }
+ BlockCipher* clone() const { return new CAST_256; }
+ CAST_256() : BlockCipher(16, 4, 32, 4) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const u32bit KEY_MASK[192];
+ static const byte KEY_ROT[32];
+
+ SecureBuffer<u32bit, 48> MK;
+ SecureBuffer<byte, 48> RK;
+ };
+
+extern const u32bit CAST_SBOX1[256];
+extern const u32bit CAST_SBOX2[256];
+extern const u32bit CAST_SBOX3[256];
+extern const u32bit CAST_SBOX4[256];
+
+}
+
+#endif
diff --git a/botan/build/botan/cbc.h b/botan/build/botan/cbc.h
new file mode 100644
index 0000000..a926ac1
--- /dev/null
+++ b/botan/build/botan/cbc.h
@@ -0,0 +1,55 @@
+/*
+* CBC Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_H__
+#define BOTAN_CBC_H__
+
+#include <botan/modebase.h>
+#include <botan/mode_pad.h>
+
+namespace Botan {
+
+/*
+* CBC Encryption
+*/
+class BOTAN_DLL CBC_Encryption : public BlockCipherMode
+ {
+ public:
+ CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*);
+ CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*,
+ const SymmetricKey&, const InitializationVector&);
+
+ ~CBC_Encryption() { delete padder; }
+ private:
+ std::string name() const;
+ void write(const byte[], u32bit);
+ void end_msg();
+ const BlockCipherModePaddingMethod* padder;
+ };
+
+/*
+* CBC Decryption
+*/
+class BOTAN_DLL CBC_Decryption : public BlockCipherMode
+ {
+ public:
+ CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*);
+ CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*,
+ const SymmetricKey&, const InitializationVector&);
+
+ ~CBC_Decryption() { delete padder; }
+ private:
+ std::string name() const;
+ void write(const byte[], u32bit);
+ void end_msg();
+ const BlockCipherModePaddingMethod* padder;
+ SecureVector<byte> temp;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cbc_mac.h b/botan/build/botan/cbc_mac.h
new file mode 100644
index 0000000..d17d792
--- /dev/null
+++ b/botan/build/botan/cbc_mac.h
@@ -0,0 +1,40 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_MAC_H__
+#define BOTAN_CBC_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CBC-MAC
+*/
+class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ CBC_MAC(BlockCipher* e);
+ ~CBC_MAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ SecureVector<byte> state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/certstor.h b/botan/build/botan/certstor.h
new file mode 100644
index 0000000..d5004e3
--- /dev/null
+++ b/botan/build/botan/certstor.h
@@ -0,0 +1,39 @@
+/*
+* Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CERT_STORE_H__
+#define BOTAN_CERT_STORE_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+
+namespace Botan {
+
+/*
+* Certificate Store Interface
+*/
+class BOTAN_DLL Certificate_Store
+ {
+ public:
+ virtual std::vector<X509_Certificate>
+ by_SKID(const MemoryRegion<byte>&) const = 0;
+
+ virtual std::vector<X509_Certificate> by_name(const std::string&) const;
+ virtual std::vector<X509_Certificate> by_email(const std::string&) const;
+ virtual std::vector<X509_Certificate> by_dn(const X509_DN&) const;
+
+ virtual std::vector<X509_CRL>
+ get_crls_for(const X509_Certificate&) const;
+
+ virtual Certificate_Store* clone() const = 0;
+
+ virtual ~Certificate_Store() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cfb.h b/botan/build/botan/cfb.h
new file mode 100644
index 0000000..7810c00
--- /dev/null
+++ b/botan/build/botan/cfb.h
@@ -0,0 +1,47 @@
+/*
+* CFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CFB_H__
+#define BOTAN_CFB_H__
+
+#include <botan/modebase.h>
+
+namespace Botan {
+
+/*
+* CFB Encryption
+*/
+class BOTAN_DLL CFB_Encryption : public BlockCipherMode
+ {
+ public:
+ CFB_Encryption(BlockCipher*, u32bit = 0);
+ CFB_Encryption(BlockCipher*, const SymmetricKey&,
+ const InitializationVector&, u32bit = 0);
+ private:
+ void write(const byte[], u32bit);
+ void feedback();
+ const u32bit FEEDBACK_SIZE;
+ };
+
+/*
+* CFB Decryption
+*/
+class BOTAN_DLL CFB_Decryption : public BlockCipherMode
+ {
+ public:
+ CFB_Decryption(BlockCipher*, u32bit = 0);
+ CFB_Decryption(BlockCipher*, const SymmetricKey&,
+ const InitializationVector&, u32bit = 0);
+ private:
+ void write(const byte[], u32bit);
+ void feedback();
+ const u32bit FEEDBACK_SIZE;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/charset.h b/botan/build/botan/charset.h
new file mode 100644
index 0000000..eebb199
--- /dev/null
+++ b/botan/build/botan/charset.h
@@ -0,0 +1,44 @@
+/*
+* Character Set Handling
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CHARSET_H__
+#define BOTAN_CHARSET_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* The different charsets (nominally) supported by Botan.
+*/
+enum Character_Set {
+ LOCAL_CHARSET,
+ UCS2_CHARSET,
+ UTF8_CHARSET,
+ LATIN1_CHARSET
+};
+
+namespace Charset {
+
+/*
+* Character Set Handling
+*/
+std::string transcode(const std::string&, Character_Set, Character_Set);
+
+bool is_digit(char);
+bool is_space(char);
+bool caseless_cmp(char, char);
+
+byte char2digit(char);
+char digit2char(byte);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/cmac.h b/botan/build/botan/cmac.h
new file mode 100644
index 0000000..5a6deb7
--- /dev/null
+++ b/botan/build/botan/cmac.h
@@ -0,0 +1,44 @@
+/*
+* CMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMAC_H__
+#define BOTAN_CMAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CMAC
+*/
+class BOTAN_DLL CMAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ static SecureVector<byte> poly_double(const MemoryRegion<byte>& in,
+ byte polynomial);
+
+ CMAC(BlockCipher* e);
+ ~CMAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ SecureVector<byte> buffer, state, B, P;
+ u32bit position;
+ byte polynomial;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cms_dec.h b/botan/build/botan/cms_dec.h
new file mode 100644
index 0000000..75b61c9
--- /dev/null
+++ b/botan/build/botan/cms_dec.h
@@ -0,0 +1,65 @@
+/*
+* CMS Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMS_DECODER_H__
+#define BOTAN_CMS_DECODER_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509stor.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/ui.h>
+
+namespace Botan {
+
+/*
+* CMS Decoding Operation
+*/
+class BOTAN_DLL CMS_Decoder
+ {
+ public:
+ enum Status { GOOD, BAD, NO_KEY, FAILURE };
+
+ enum Content_Type { DATA, UNKNOWN, COMPRESSED, ENVELOPED, SIGNED,
+ AUTHENTICATED, DIGESTED };
+
+ Status layer_status() const;
+ Content_Type layer_type() const;
+ std::string layer_info() const;
+ std::string layer_algo() const;
+ std::string get_data() const;
+ std::vector<X509_Certificate> get_certs() const;
+ std::vector<X509_CRL> get_crls() const;
+
+ void next_layer() { decode_layer(); }
+
+ void add_key(PKCS8_PrivateKey*);
+
+ CMS_Decoder(DataSource&, const X509_Store&, User_Interface&,
+ PKCS8_PrivateKey* = 0);
+ private:
+ std::string get_passphrase(const std::string&);
+ void read_econtent(BER_Decoder&);
+ void initial_read(DataSource&);
+ void decode_layer();
+ void decompress(BER_Decoder&);
+
+ User_Interface& ui;
+
+ X509_Store store;
+ std::vector<std::string> passphrases;
+ std::vector<PKCS8_PrivateKey*> keys;
+
+ OID type, next_type;
+ SecureVector<byte> data;
+ Status status;
+ std::string info;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cms_enc.h b/botan/build/botan/cms_enc.h
new file mode 100644
index 0000000..6fdd2b7
--- /dev/null
+++ b/botan/build/botan/cms_enc.h
@@ -0,0 +1,92 @@
+/*
+* CMS Encoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMS_ENCODER_H__
+#define BOTAN_CMS_ENCODER_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509stor.h>
+#include <botan/pkcs8.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+/*
+* CMS Encoding Operation
+*/
+class BOTAN_DLL CMS_Encoder
+ {
+ public:
+
+ void encrypt(RandomNumberGenerator&,
+ const X509_Certificate&, const std::string = "");
+
+ void encrypt(RandomNumberGenerator& rng,
+ const std::string&, const std::string& = "");
+
+ void encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey&, const std::string& = "");
+
+ void authenticate(const X509_Certificate&, const std::string& = "");
+ void authenticate(const std::string&, const std::string& = "");
+ void authenticate(const SymmetricKey&, const std::string& = "");
+
+ void sign(const X509_Certificate& cert,
+ const PKCS8_PrivateKey& key,
+ RandomNumberGenerator& rng,
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::string& hash,
+ const std::string& padding);
+
+ void digest(const std::string& = "");
+
+ void compress(const std::string&);
+ static bool can_compress_with(const std::string&);
+
+ SecureVector<byte> get_contents();
+ std::string PEM_contents();
+
+ void set_data(const std::string&);
+ void set_data(const byte[], u32bit);
+
+ CMS_Encoder(const std::string& str) { set_data(str); }
+ CMS_Encoder(const byte buf[], u32bit length) { set_data(buf, length); }
+ private:
+ void add_layer(const std::string&, DER_Encoder&);
+
+ void encrypt_ktri(RandomNumberGenerator&,
+ const X509_Certificate&, PK_Encrypting_Key*,
+ const std::string&);
+ void encrypt_kari(RandomNumberGenerator&,
+ const X509_Certificate&, X509_PublicKey*,
+ const std::string&);
+
+ SecureVector<byte> do_encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey&, const std::string&);
+
+ static SecureVector<byte> make_econtent(const SecureVector<byte>&,
+ const std::string&);
+
+ static SymmetricKey setup_key(RandomNumberGenerator& rng,
+ const std::string&);
+
+ static SecureVector<byte> wrap_key(RandomNumberGenerator& rng,
+ const std::string&,
+ const SymmetricKey&,
+ const SymmetricKey&);
+
+ static SecureVector<byte> encode_params(const std::string&,
+ const SymmetricKey&,
+ const InitializationVector&);
+
+ SecureVector<byte> data;
+ std::string type;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/crc24.h b/botan/build/botan/crc24.h
new file mode 100644
index 0000000..bca4d0e
--- /dev/null
+++ b/botan/build/botan/crc24.h
@@ -0,0 +1,34 @@
+/*
+* CRC24
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRC24_H__
+#define BOTAN_CRC24_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* CRC24
+*/
+class BOTAN_DLL CRC24 : public HashFunction
+ {
+ public:
+ void clear() throw() { crc = 0xB704CE; }
+ std::string name() const { return "CRC24"; }
+ HashFunction* clone() const { return new CRC24; }
+ CRC24() : HashFunction(3) { clear(); }
+ ~CRC24() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ u32bit crc;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/crc32.h b/botan/build/botan/crc32.h
new file mode 100644
index 0000000..390fb10
--- /dev/null
+++ b/botan/build/botan/crc32.h
@@ -0,0 +1,34 @@
+/*
+* CRC32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRC32_H__
+#define BOTAN_CRC32_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* CRC32
+*/
+class BOTAN_DLL CRC32 : public HashFunction
+ {
+ public:
+ void clear() throw() { crc = 0xFFFFFFFF; }
+ std::string name() const { return "CRC32"; }
+ HashFunction* clone() const { return new CRC32; }
+ CRC32() : HashFunction(4) { clear(); }
+ ~CRC32() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ u32bit crc;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/crl_ent.h b/botan/build/botan/crl_ent.h
new file mode 100644
index 0000000..050356c
--- /dev/null
+++ b/botan/build/botan/crl_ent.h
@@ -0,0 +1,78 @@
+/*
+* CRL Entry
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRL_ENTRY_H__
+#define BOTAN_CRL_ENTRY_H__
+
+#include <botan/x509cert.h>
+
+namespace Botan {
+
+/**
+* This class represents CRL entries
+*/
+class BOTAN_DLL CRL_Entry : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get the serial number of the certificate associated with this entry.
+ * @return the certificate's serial number
+ */
+ MemoryVector<byte> serial_number() const { return serial; }
+
+ /**
+ * Get the revocation date of the certificate associated with this entry
+ * @return the certificate's revocation date
+ */
+ X509_Time expire_time() const { return time; }
+
+ /**
+ * Get the entries reason code
+ * @return the reason code
+ */
+ CRL_Code reason_code() const { return reason; }
+
+ /**
+ * Construct an empty CRL entry.
+ */
+ CRL_Entry(bool throw_on_unknown_critical_extension = false);
+
+ /**
+ * Construct an CRL entry.
+ * @param cert the certificate to revoke
+ * @param reason the reason code to set in the entry
+ */
+ CRL_Entry(const X509_Certificate&, CRL_Code = UNSPECIFIED);
+
+ private:
+ bool throw_on_unknown_critical;
+ MemoryVector<byte> serial;
+ X509_Time time;
+ CRL_Code reason;
+ };
+
+/**
+* Test two CRL entries for equality in all fields.
+*/
+BOTAN_DLL bool operator==(const CRL_Entry&, const CRL_Entry&);
+
+/**
+* Test two CRL entries for inequality in at least one field.
+*/
+BOTAN_DLL bool operator!=(const CRL_Entry&, const CRL_Entry&);
+
+/**
+* Order two entries based on the revocation date.
+*/
+BOTAN_DLL bool operator<(const CRL_Entry&, const CRL_Entry&);
+
+}
+
+#endif
diff --git a/botan/build/botan/cryptobox.h b/botan/build/botan/cryptobox.h
new file mode 100644
index 0000000..a30cb24
--- /dev/null
+++ b/botan/build/botan/cryptobox.h
@@ -0,0 +1,42 @@
+/*
+* Cryptobox Message Routines
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRYPTOBOX_H__
+#define BOTAN_CRYPTOBOX_H__
+
+#include <string>
+#include <botan/rng.h>
+
+namespace Botan {
+
+namespace CryptoBox {
+
+/**
+* Encrypt a message
+* @param input the input data
+* @param input_len the length of input in bytes
+* @param passphrase the passphrase used to encrypt the message
+* @param rng a ref to a random number generator, such as AutoSeeded_RNG
+*/
+BOTAN_DLL std::string encrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase,
+ RandomNumberGenerator& rng);
+
+/**
+* Decrypt a message encrypted with CryptoBox::encrypt
+* @param input the input data
+* @param input_len the length of input in bytes
+* @param passphrase the passphrase used to encrypt the message
+*/
+BOTAN_DLL std::string decrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/ctr.h b/botan/build/botan/ctr.h
new file mode 100644
index 0000000..aa0db57
--- /dev/null
+++ b/botan/build/botan/ctr.h
@@ -0,0 +1,31 @@
+/*
+* CTR Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_COUNTER_MODE_H__
+#define BOTAN_COUNTER_MODE_H__
+
+#include <botan/modebase.h>
+#include <botan/modebase.h>
+
+namespace Botan {
+
+/*
+* CTR-BE Mode
+*/
+class BOTAN_DLL CTR_BE : public BlockCipherMode
+ {
+ public:
+ CTR_BE(BlockCipher*);
+ CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&);
+ private:
+ void write(const byte[], u32bit);
+ void increment_counter();
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cts.h b/botan/build/botan/cts.h
new file mode 100644
index 0000000..9b17203
--- /dev/null
+++ b/botan/build/botan/cts.h
@@ -0,0 +1,60 @@
+/*
+* CTS Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CTS_H__
+#define BOTAN_CTS_H__
+
+#include <botan/modebase.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CTS Encryption
+*/
+class BOTAN_DLL CTS_Encryption : public BlockCipherMode
+ {
+ public:
+ CTS_Encryption(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) {}
+
+ CTS_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { set_key(key); set_iv(iv); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void encrypt(const byte[]);
+ };
+
+/*
+* CTS Decryption
+*/
+class BOTAN_DLL CTS_Decryption : public BlockCipherMode
+ {
+ public:
+ CTS_Decryption(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { temp.create(BLOCK_SIZE); }
+
+ CTS_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { set_key(key); set_iv(iv); temp.create(BLOCK_SIZE); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void decrypt(const byte[]);
+ SecureVector<byte> temp;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/curve_gfp.h b/botan/build/botan/curve_gfp.h
new file mode 100644
index 0000000..81cf6ce
--- /dev/null
+++ b/botan/build/botan/curve_gfp.h
@@ -0,0 +1,177 @@
+/******
+ * Elliptic curves over GF(p) (header file)
+ *
+ * (C) 2007 Martin Doering
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_CURVE_H__
+#define BOTAN_GFP_CURVE_H__
+
+#include <botan/bigint.h>
+#include <botan/gfp_element.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents an elliptic curve over GF(p)
+*
+* Distributed under the terms of the Botan license
+*/
+class BOTAN_DLL CurveGFp
+ {
+ public:
+
+ /**
+ * Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
+ * @param a first coefficient
+ * @param b second coefficient
+ * @param p prime number of the field
+ */
+ CurveGFp(const GFpElement& a, const GFpElement& b,
+ const BigInt& p);
+
+ /**
+ * Copy constructor
+ * @param other The curve to clone
+ */
+ CurveGFp(const CurveGFp& other);
+
+ /**
+ * Assignment operator
+ * @param other The curve to use as source for the assignment
+ */
+ const CurveGFp& operator=(const CurveGFp& other);
+
+ /**
+ * Set the shared GFpModulus object.
+ * Warning: do not use this function unless you know in detail how
+ * the sharing of values
+ * in the various EC related objects works.
+ * Do NOT spread pointers to a GFpModulus over different threads!
+ * @param mod a shared pointer to a GFpModulus object suitable for
+ * *this.
+ */
+ void set_shrd_mod(const std::tr1::shared_ptr<GFpModulus> mod);
+
+ // getters
+
+ /**
+ * Get coefficient a
+ * @result coefficient a
+ */
+ const GFpElement& get_a() const;
+
+ /**
+ * Get coefficient b
+ * @result coefficient b
+ */
+ const GFpElement& get_b() const;
+
+ /**
+ * Get the GFpElement coefficient a transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the coefficient a, transformed to its m-residue
+ */
+ GFpElement const get_mres_a() const;
+
+ /**
+ * Get the GFpElement coefficient b transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the coefficient b, transformed to its m-residue
+ */
+ GFpElement const get_mres_b() const;
+
+
+ /**
+ * Get the GFpElement 1 transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the GFpElement 1, transformed to its m-residue
+ */
+ std::tr1::shared_ptr<GFpElement const> const get_mres_one() const;
+
+ /**
+ * Get prime modulus of the field of the curve
+ * @result prime modulus of the field of the curve
+ */
+ BigInt const get_p() const;
+ /*inline std::tr1::shared_ptr<BigInt> const get_ptr_p() const
+ {
+ return mp_p;
+ }*/
+
+ /**
+ * Retrieve a shared pointer to the curves GFpModulus object for efficient storage
+ * and computation of montgomery multiplication related data members and functions.
+ * Warning: do not use this function unless you know in detail how the sharing of values
+ * in the various EC related objects works.
+ * Do NOT spread pointers to a GFpModulus over different threads!
+ * @result a shared pointer to a GFpModulus object
+ */
+ inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
+ {
+ return mp_mod;
+ }
+
+ /**
+ * swaps the states of *this and other, does not throw
+ * @param other The curve to swap values with
+ */
+ void swap(CurveGFp& other);
+
+ private:
+ std::tr1::shared_ptr<GFpModulus> mp_mod;
+ GFpElement mA;
+ GFpElement mB;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_a;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_b;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_one;
+ };
+
+// relational operators
+bool operator==(const CurveGFp& lhs, const CurveGFp& rhs);
+
+inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+// io operators
+std::ostream& operator<<(std::ostream& output, const CurveGFp& elem);
+
+// swaps the states of curve1 and curve2, does not throw!
+// cf. Meyers, Item 25
+inline
+void swap(CurveGFp& curve1, CurveGFp& curve2)
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace Botan
+
+
+namespace std {
+
+// swaps the states of curve1 and curve2, does not throw!
+// cf. Meyers, Item 25
+template<> inline
+void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
+ Botan::CurveGFp& curve2)
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace std
+
+#endif
diff --git a/botan/build/botan/cvc_ado.h b/botan/build/botan/cvc_ado.h
new file mode 100644
index 0000000..2c4f3ce
--- /dev/null
+++ b/botan/build/botan/cvc_ado.h
@@ -0,0 +1,101 @@
+/*
+* EAC1_1 CVC ADO
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_ADO_H__
+#define BOTAN_EAC_CVC_ADO_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_req.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a TR03110 (EAC) v1.1 CVC ADO request
+*/
+
+ // CRTP continuation from EAC1_1_obj
+class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
+ {
+ public:
+ friend class EAC1_1_obj<EAC1_1_ADO>;
+
+ /**
+ * Construct a CVC ADO request from a DER encoded CVC ADO request file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_ADO(const std::string& str);
+
+ /**
+ * Construct a CVC ADO request from a data source
+ * @param source the data source
+ */
+ EAC1_1_ADO(std::tr1::shared_ptr<DataSource> source);
+
+ /**
+ * Create a signed CVC ADO request from to be signed (TBS) data
+ * @param signer the signer used to sign the CVC ADO request
+ * @param tbs_bits the TBS data to sign
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Get the CAR of this CVC ADO request
+ * @result the CAR of this CVC ADO request
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CVC request contained in this object.
+ * @result the CVC request inside this CVC ADO request
+ */
+ EAC1_1_Req get_request() const;
+
+ /**
+ * Encode this object into a pipe. Only DER is supported.
+ * @param out the pipe to encode this object into
+ * @param encoding the encoding type to use, must be DER
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ bool operator==(EAC1_1_ADO const& rhs) const;
+
+ /**
+ * Get the TBS data of this CVC ADO request.
+ * @result the TBS data
+ */
+ SecureVector<byte> tbs_data() const;
+
+ virtual ~EAC1_1_ADO() {}
+ private:
+ ASN1_Car m_car;
+ EAC1_1_Req m_req;
+
+ void force_decode();
+ static void decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig);
+ };
+
+inline bool operator!=(EAC1_1_ADO const& lhs, EAC1_1_ADO const& rhs)
+ {
+ return (!(lhs == rhs));
+ }
+
+}
+
+#endif
+
+
diff --git a/botan/build/botan/cvc_ca.h b/botan/build/botan/cvc_ca.h
new file mode 100644
index 0000000..3ec307b
--- /dev/null
+++ b/botan/build/botan/cvc_ca.h
@@ -0,0 +1,51 @@
+/*
+* EAC1.1 CVC Certificate Authority
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_CA_H__
+#define BOTAN_CVC_CA_H__
+
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/pubkey.h>
+#include <botan/cvc_cert.h>
+
+namespace Botan {
+
+/**
+* This class represents a CVC CA.
+*/
+class BOTAN_DLL EAC1_1_CVC_CA
+ {
+ public:
+
+ /**
+ * Create an arbitrary EAC 1.1 CVC.
+ * The desired key encoding must be set within the key (if applicable).
+ * @param signer the signer used to sign the certificate
+ * @param public_key the DER encoded public key to appear in
+ * the certificate
+ * @param car the CAR of the certificate
+ * @param chr the CHR of the certificate
+ * @param holder_auth_templ the holder authorization value byte to
+ * appear in the CHAT of the certificate
+ * @param ced the CED to appear in the certificate
+ * @param ced the CEX to appear in the certificate
+ */
+ static EAC1_1_CVC make_cert(std::auto_ptr<PK_Signer> signer,
+ MemoryRegion<byte> const& public_key,
+ ASN1_Car const& car,
+ ASN1_Chr const& chr,
+ byte holder_auth_templ,
+ ASN1_Ced ced,
+ ASN1_Cex cex,
+ RandomNumberGenerator& rng);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/cvc_cert.h b/botan/build/botan/cvc_cert.h
new file mode 100644
index 0000000..17671d3
--- /dev/null
+++ b/botan/build/botan/cvc_cert.h
@@ -0,0 +1,94 @@
+/*
+* EAC1_1 CVC
+* (C) 2008 Falko Strenzke
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_EAC_H__
+#define BOTAN_CVC_EAC_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/signed_obj.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/ecdsa_sig.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_gen_cert.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 (EAC) v1.1 CV Certificates
+*/
+class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object
+ {
+ public:
+ friend class EAC1_1_obj<EAC1_1_CVC>;
+
+ /**
+ * Get the CAR of the certificate.
+ * @result the CAR of the certificate
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CED of this certificate.
+ * @result the CED this certificate
+ */
+ ASN1_Ced get_ced() const;
+
+ /**
+ * Get the CEX of this certificate.
+ * @result the CEX this certificate
+ */
+ ASN1_Cex get_cex() const;
+
+ /**
+ * Get the CHAT value.
+ * @result the CHAT value
+ */
+ u32bit get_chat_value() const;
+
+ bool operator==(const EAC1_1_CVC&) const;
+
+ /**
+ * Construct a CVC from a data source
+ * @param source the data source
+ */
+ EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& source);
+
+ /**
+ * Construct a CVC from a file
+ * @param str the path to the certificate file
+ */
+ EAC1_1_CVC(const std::string& str);
+
+ virtual ~EAC1_1_CVC() {}
+ private:
+ void force_decode();
+ friend class EAC1_1_CVC_CA;
+ EAC1_1_CVC() {}
+
+ ASN1_Car m_car;
+ ASN1_Ced m_ced;
+ ASN1_Cex m_cex;
+ byte m_chat_val;
+ OID m_chat_oid;
+ };
+
+/*
+* Comparison
+*/
+inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
+
diff --git a/botan/build/botan/cvc_gen_cert.h b/botan/build/botan/cvc_gen_cert.h
new file mode 100644
index 0000000..4a78802
--- /dev/null
+++ b/botan/build/botan/cvc_gen_cert.h
@@ -0,0 +1,177 @@
+/*
+* EAC1_1 general CVC
+* (C) 2008 Falko Strenzke
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_GEN_CERT_H__
+#define BOTAN_EAC_CVC_GEN_CERT_H__
+
+#include <botan/x509_key.h>
+#include <botan/eac_asn_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa_sig.h>
+#include <string>
+#include <assert.h>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 (EAC) v1.1 generalized CV Certificates
+*/
+template<typename Derived>
+class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj
+ {
+ friend class EAC1_1_obj<EAC1_1_gen_CVC>;
+
+ public:
+
+ /**
+ * Get this certificates public key.
+ * @result this certificates public key
+ */
+ std::auto_ptr<Public_Key> subject_public_key() const;
+
+ /**
+ * Find out whether this object is self signed.
+ * @result true if this object is self signed
+ */
+ bool is_self_signed() const;
+
+ /**
+ * Get the CHR of the certificate.
+ * @result the CHR of the certificate
+ */
+ ASN1_Chr get_chr() const;
+
+ /**
+ * Put the DER encoded version of this object into a pipe. PEM
+ * is not supported.
+ * @param out the pipe to push the DER encoded version into
+ * @param encoding the encoding to use. Must be DER.
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ /**
+ * Get the to-be-signed (TBS) data of this object.
+ * @result the TBS data of this object
+ */
+ SecureVector<byte> tbs_data() const;
+
+ /**
+ * Build the DER encoded certifcate body of an object
+ * @param tbs the data to be signed
+ * @result the correctly encoded body of the object
+ */
+ static SecureVector<byte> build_cert_body(MemoryRegion<byte> const& tbs);
+
+ /**
+ * Create a signed generalized CVC object.
+ * @param signer the signer used to sign this object
+ * @param tbs_bits the body the generalized CVC object to be signed
+ * @result the DER encoded signed generalized CVC object
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+ virtual ~EAC1_1_gen_CVC<Derived>()
+ {}
+
+ protected:
+ ECDSA_PublicKey m_pk; // public key
+ ASN1_Chr m_chr;
+ bool self_signed;
+
+ static void decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig);
+
+ };
+
+template<typename Derived> ASN1_Chr EAC1_1_gen_CVC<Derived>::get_chr() const
+ {
+ return m_chr;
+ }
+
+template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const
+ {
+ return self_signed;
+ }
+
+template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng) // static
+ {
+ SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer.get(), tbs_bits, rng);
+ assert(concat_sig.size() % 2 == 0);
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+ }
+
+template<typename Derived> std::auto_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const
+ {
+ return std::auto_ptr<Public_Key>(new ECDSA_PublicKey(m_pk));
+ }
+
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs)
+ {
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(tbs)
+ .end_cons().get_contents();
+ }
+
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const
+ {
+ return build_cert_body(EAC1_1_obj<Derived>::tbs_bits);
+ }
+
+template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const
+ {
+ SecureVector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation());
+ SecureVector<byte> der = DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(EAC1_1_obj<Derived>::tbs_bits)
+ .end_cons()
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+
+ if (encoding == PEM)
+ throw Invalid_Argument("EAC1_1_gen_CVC::encode() cannot PEM encode an EAC object");
+ else
+ out.write(der);
+ }
+
+template<typename Derived>
+void EAC1_1_gen_CVC<Derived>::decode_info(
+ SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig)
+ {
+ SecureVector<byte> concat_sig;
+ BER_Decoder(*source.get_shared().get())
+ .start_cons(ASN1_Tag(33))
+ .start_cons(ASN1_Tag(78))
+ .raw_bytes(res_tbs_bits)
+ .end_cons()
+ .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons();
+ res_sig = decode_concatenation(concat_sig);
+ }
+
+}
+
+#endif
+
+
diff --git a/botan/build/botan/cvc_key.h b/botan/build/botan/cvc_key.h
new file mode 100644
index 0000000..67b6cef
--- /dev/null
+++ b/botan/build/botan/cvc_key.h
@@ -0,0 +1,54 @@
+/*
+* EAC CVC Public Key
+* (C) 2008 FlexSecure Gmbh
+* Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+#define BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+
+namespace Botan {
+
+/**
+* This class represents EAC 1.1 CVC public key encoders.
+*/
+class BOTAN_DLL EAC1_1_CVC_Encoder
+ {
+ public:
+ /**
+ * Get the DER encoded CVC public key.
+ * @param alg_id the algorithm identifier to use in the encoding
+ * @return the DER encoded public key
+ */
+ virtual MemoryVector<byte>
+ public_key(const AlgorithmIdentifier& enc) const = 0;
+
+ virtual ~EAC1_1_CVC_Encoder() {}
+ };
+
+/**
+* This class represents EAC 1.1 CVC public key decoders.
+*/
+class BOTAN_DLL EAC1_1_CVC_Decoder
+ {
+ public:
+ /**
+ * Decode a CVC public key.
+ * @param enc the DER encoded public key to decode
+ * @return the algorithm identifier found in the encoded public key
+ */
+ virtual AlgorithmIdentifier const
+ public_key(const MemoryRegion<byte>& enc) = 0;
+
+ virtual ~EAC1_1_CVC_Decoder() {}
+ };
+}
+
+#endif
diff --git a/botan/build/botan/cvc_req.h b/botan/build/botan/cvc_req.h
new file mode 100644
index 0000000..8599f53
--- /dev/null
+++ b/botan/build/botan/cvc_req.h
@@ -0,0 +1,63 @@
+/*
+* EAC1_1 CVC Request
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_REQ_H__
+#define BOTAN_EAC_CVC_REQ_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/cvc_gen_cert.h>
+#include <botan/cvc_req.h>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 v1.1 EAC CV Certificate Requests.
+*/
+class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req>
+ {
+ public:
+ friend class EAC1_1_Req_CA;
+ friend class EAC1_1_ADO;
+ friend class EAC1_1_obj<EAC1_1_Req>;
+
+ /**
+ * Compare for equality with other
+ * @param other compare for equality with this object
+ */
+ bool operator==(const EAC1_1_Req& other) const;
+
+ /**
+ * Construct a CVC request from a data source.
+ * @param source the data source
+ */
+ EAC1_1_Req(std::tr1::shared_ptr<DataSource> source);
+
+ /**
+ * Construct a CVC request from a DER encoded CVC reqeust file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_Req(const std::string& str);
+
+ virtual ~EAC1_1_Req(){}
+ private:
+ void force_decode();
+ EAC1_1_Req() {}
+ };
+
+/*
+* Comparison Operator
+*/
+inline bool operator!=(EAC1_1_Req const& lhs, EAC1_1_Req const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/cvc_self.h b/botan/build/botan/cvc_self.h
new file mode 100644
index 0000000..db23547
--- /dev/null
+++ b/botan/build/botan/cvc_self.h
@@ -0,0 +1,167 @@
+/*
+* CVC Self-Signed Certificate
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_EAC_SELF_H__
+#define BOTAN_CVC_EAC_SELF_H__
+
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/cvc_cert.h>
+#include <botan/ecdsa.h>
+#include <botan/asn1_obj.h>
+#include <botan/cvc_req.h>
+#include <botan/cvc_ado.h>
+
+namespace Botan {
+
+/**
+* This class represents a set of options used for the creation of CVC certificates
+*/
+class BOTAN_DLL EAC1_1_CVC_Options
+ {
+ public:
+
+ ASN1_Car car;
+ ASN1_Chr chr;
+ byte holder_auth_templ;
+ ASN1_Ced ced;
+ ASN1_Cex cex;
+ std::string hash_alg;
+ };
+
+/**
+* This namespace represents general EAC 1.1 convenience functions.
+*/
+namespace CVC_EAC {
+
+/**
+* Create a selfsigned CVCA
+* @param rng the rng to use
+* @param key the ECDSA private key to be used to sign the certificate
+* @param opts used to set several parameters. Necessary are:
+* car, holder_auth_templ, hash_alg, ced, cex and hash_alg
+* @result the self signed certificate
+*/
+
+EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
+ EAC1_1_CVC_Options const& opts,
+ RandomNumberGenerator& rng);
+/**
+* Create a CVC request. The key encoding will be according to the provided private key.
+* @param priv_key the private key associated with the requesting entity
+* @param chr the chr to appear in the certificate (to be provided without
+* sequence number)
+* @param hash_alg the string defining the hash algorithm to be used for the creation
+* of the signature
+* @param rng the rng to use
+* @result the new request
+*/
+EAC1_1_Req create_cvc_req(Private_Key const& priv_key,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng);
+
+/**
+* Create an ADO from a request object.
+* @param priv_key the private key used to sign the ADO
+* @param req the request forming the body of the ADO
+* @param car the CAR forming the body of the ADO, i.e. the
+* CHR of the entity associated with the provided private key
+* @param rng the rng to use
+*/
+EAC1_1_ADO create_ado_req(Private_Key const& priv_key,
+ EAC1_1_Req const& req,
+ ASN1_Car const& car,
+ RandomNumberGenerator& rng);
+}
+/**
+* This namespace represents EAC 1.1 CVC convenience functions following the specific german
+* requirements.
+*/
+namespace DE_EAC {
+
+/**
+* Create a CVCA certificate.
+* @param priv_key the private key associated with the CVCA certificate
+* to be created
+* @param hash the string identifying the hash algorithm to be used
+* for signing the certificate to be created
+* @param car the CAR of the certificate to be created
+* @param iris indicates whether the entity associated with the certificate
+* shall be entitled to read the biometrical iris image
+* @param fingerpr indicates whether the entity associated with the certificate
+* shall be entitled to read the biometrical fingerprint image
+* @param rng the rng to use
+* @result the CVCA certificate created
+*/
+EAC1_1_CVC create_cvca(Private_Key const& priv_key,
+ std::string const& hash,
+ ASN1_Car const& car,
+ bool iris,
+ bool fingerpr,
+ u32bit cvca_validity_months,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a link certificate between two CVCA certificates. The key
+* encoding will be implicitCA.
+* @param signer the cvca certificate associated with the signing
+* entity
+* @param priv_key the private key associated with the signer
+* @param to_be_signed the certificate which whose CAR/CHR will be
+* the holder of the link certificate
+* @param rng a random number generator
+*/
+EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
+ Private_Key const& priv_key,
+ EAC1_1_CVC const& to_be_signed,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a CVC request. The key encoding will be implicitCA.
+* @param priv_key the private key associated with the requesting entity
+* @param chr the chr to appear in the certificate (to be provided without
+* sequence number)
+* @param hash_alg the string defining the hash algorithm to be used for the creation
+* of the signature
+* @param rng a random number generator
+* @result the new request
+*/
+EAC1_1_Req create_cvc_req(Private_Key const& priv_key,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng);
+
+/**
+* Sign a CVC request.
+* @param signer_cert the certificate of the signing entity
+* @param priv_key the private key of the signing entity
+* @param req the request to be signed
+* @param seqnr the sequence number of the certificate to be created
+* @param seqnr_len the number of digits the sequence number will be
+* encoded in
+* @param domestic indicates whether to sign a domestic or a foreign certificate:
+* set to true for domestic
+* @param rng a random number generator
+* @result the new certificate
+*
+**/
+EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
+ Private_Key const& priv_key,
+ EAC1_1_Req const& req,
+ u32bit seqnr,
+ u32bit seqnr_len,
+ bool domestic,
+ u32bit dvca_validity_months,
+ u32bit ca_is_validity_months,
+ RandomNumberGenerator& rng);
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/data_snk.h b/botan/build/botan/data_snk.h
new file mode 100644
index 0000000..61ddf6e
--- /dev/null
+++ b/botan/build/botan/data_snk.h
@@ -0,0 +1,65 @@
+/*
+* DataSink
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_SINK_H__
+#define BOTAN_DATA_SINK_H__
+
+#include <botan/filter.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents abstract data sink objects.
+*/
+class BOTAN_DLL DataSink : public Filter
+ {
+ public:
+ bool attachable() { return false; }
+ DataSink() {}
+ virtual ~DataSink() {}
+ private:
+ DataSink& operator=(const DataSink&) { return (*this); }
+ DataSink(const DataSink&);
+ };
+
+/**
+* This class represents a data sink which writes its output to a stream.
+*/
+class BOTAN_DLL DataSink_Stream : public DataSink
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param stream the stream to write to
+ * @param name identifier
+ */
+ DataSink_Stream(std::ostream& stream,
+ const std::string& name = "");
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param file the name of the file to open a stream to
+ * @param use_binary indicates whether to treat the file
+ * as a binary file or not
+ */
+ DataSink_Stream(const std::string& filename,
+ bool use_binary = false);
+
+ ~DataSink_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::ostream* sink;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/data_src.h b/botan/build/botan/data_src.h
new file mode 100644
index 0000000..e16217e
--- /dev/null
+++ b/botan/build/botan/data_src.h
@@ -0,0 +1,150 @@
+/*
+* DataSource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_SRC_H__
+#define BOTAN_DATA_SRC_H__
+
+#include <botan/secmem.h>
+#include <string>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents an abstract data source object.
+*/
+class BOTAN_DLL DataSource
+ {
+ public:
+ /**
+ * Read from the source. Moves the internal offset so that
+ * every call to read will return a new portion of the source.
+ * @param out the byte array to write the result to
+ * @param length the length of the byte array out
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ virtual u32bit read(byte out[], u32bit length) = 0;
+
+ /**
+ * Read from the source but do not modify the internal offset. Consecutive
+ * calls to peek() will return portions of the source starting at the same
+ * position.
+ * @param out the byte array to write the output to
+ * @param length the length of the byte array out
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ virtual u32bit peek(byte out[], u32bit length,
+ u32bit peek_offset) const = 0;
+
+ /**
+ * Test whether the source still has data that can be read.
+ * @return true if there is still data to read, false otherwise
+ */
+ virtual bool end_of_data() const = 0;
+ /**
+ * return the id of this data source
+ * @return the std::string representing the id of this data source
+ */
+ virtual std::string id() const { return ""; }
+
+ /**
+ * Read one byte.
+ * @param the byte to read to
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ u32bit read_byte(byte& out);
+
+ /**
+ * Peek at one byte.
+ * @param the byte to read to
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ u32bit peek_byte(byte& out) const;
+
+ /**
+ * Discard the next N bytes of the data
+ * @param N the number of bytes to discard
+ * @return the number of bytes actually discarded
+ */
+ u32bit discard_next(u32bit N);
+
+ DataSource() {}
+ virtual ~DataSource() {}
+ private:
+ DataSource& operator=(const DataSource&) { return (*this); }
+ DataSource(const DataSource&);
+ };
+
+/**
+* This class represents a Memory-Based DataSource
+*/
+class BOTAN_DLL DataSource_Memory : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+
+ /**
+ * Construct a memory source that reads from a string
+ * @param in the string to read from
+ */
+ DataSource_Memory(const std::string& in);
+
+ /**
+ * Construct a memory source that reads from a byte array
+ * @param in the byte array to read from
+ * @param length the length of the byte array
+ */
+ DataSource_Memory(const byte in[], u32bit length);
+
+ /**
+ * Construct a memory source that reads from a MemoryRegion
+ * @param in the MemoryRegion to read from
+ */
+ DataSource_Memory(const MemoryRegion<byte>& in);
+ private:
+ SecureVector<byte> source;
+ u32bit offset;
+ };
+
+/**
+* This class represents a Stream-Based DataSource.
+*/
+class BOTAN_DLL DataSource_Stream : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+ std::string id() const;
+
+ DataSource_Stream(std::istream&, const std::string& id = "");
+
+ /**
+ * Construct a Stream-Based DataSource from file
+ * @param file the name of the file
+ * @param use_binary whether to treat the file as binary or not
+ */
+ DataSource_Stream(const std::string& file, bool use_binary = false);
+
+ ~DataSource_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::istream* source;
+ u32bit total_read;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/datastor.h b/botan/build/botan/datastor.h
new file mode 100644
index 0000000..7ee626f
--- /dev/null
+++ b/botan/build/botan/datastor.h
@@ -0,0 +1,61 @@
+/*
+* Data Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_STORE_H__
+#define BOTAN_DATA_STORE_H__
+
+#include <botan/secmem.h>
+#include <utility>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* Data Store
+*/
+class BOTAN_DLL Data_Store
+ {
+ public:
+ class BOTAN_DLL Matcher
+ {
+ public:
+ virtual bool operator()(const std::string&,
+ const std::string&) const = 0;
+
+ virtual std::pair<std::string, std::string>
+ transform(const std::string&, const std::string&) const;
+
+ virtual ~Matcher() {}
+ };
+
+ bool operator==(const Data_Store&) const;
+
+ std::multimap<std::string, std::string>
+ search_with(const Matcher&) const;
+
+ std::vector<std::string> get(const std::string&) const;
+
+ std::string get1(const std::string&) const;
+
+ MemoryVector<byte> get1_memvec(const std::string&) const;
+ u32bit get1_u32bit(const std::string&, u32bit = 0) const;
+
+ bool has_value(const std::string&) const;
+
+ void add(const std::multimap<std::string, std::string>&);
+ void add(const std::string&, const std::string&);
+ void add(const std::string&, u32bit);
+ void add(const std::string&, const MemoryRegion<byte>&);
+ private:
+ std::multimap<std::string, std::string> contents;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/def_eng.h b/botan/build/botan/def_eng.h
new file mode 100644
index 0000000..2d71454
--- /dev/null
+++ b/botan/build/botan/def_eng.h
@@ -0,0 +1,83 @@
+/*
+* Default Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DEFAULT_ENGINE_H__
+#define BOTAN_DEFAULT_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*
+* Default Engine
+*/
+class BOTAN_DLL Default_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "core"; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ virtual bool can_add_algorithms() { return true; }
+
+ Keyed_Filter* get_cipher(const std::string&, Cipher_Dir,
+ Algorithm_Factory&);
+
+ private:
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ StreamCipher* find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+
+ MessageAuthenticationCode* find_mac(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/def_powm.h b/botan/build/botan/def_powm.h
new file mode 100644
index 0000000..472c865
--- /dev/null
+++ b/botan/build/botan/def_powm.h
@@ -0,0 +1,64 @@
+/*
+* Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DEFAULT_MODEXP_H__
+#define BOTAN_DEFAULT_MODEXP_H__
+
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Fixed Window Exponentiator
+*/
+class BOTAN_DLL Fixed_Window_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_exponent(const BigInt&);
+ void set_base(const BigInt&);
+ BigInt execute() const;
+
+ Modular_Exponentiator* copy() const
+ { return new Fixed_Window_Exponentiator(*this); }
+
+ Fixed_Window_Exponentiator(const BigInt&, Power_Mod::Usage_Hints);
+ private:
+ Modular_Reducer reducer;
+ BigInt exp;
+ u32bit window_bits;
+ std::vector<BigInt> g;
+ Power_Mod::Usage_Hints hints;
+ };
+
+/*
+* Montgomery Exponentiator
+*/
+class BOTAN_DLL Montgomery_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_exponent(const BigInt&);
+ void set_base(const BigInt&);
+ BigInt execute() const;
+
+ Modular_Exponentiator* copy() const
+ { return new Montgomery_Exponentiator(*this); }
+
+ Montgomery_Exponentiator(const BigInt&, Power_Mod::Usage_Hints);
+ private:
+ BigInt exp, modulus;
+ BigInt R2, R_mod;
+ std::vector<BigInt> g;
+ word mod_prime;
+ u32bit mod_words, exp_bits, window_bits;
+ Power_Mod::Usage_Hints hints;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/defalloc.h b/botan/build/botan/defalloc.h
new file mode 100644
index 0000000..627e8df
--- /dev/null
+++ b/botan/build/botan/defalloc.h
@@ -0,0 +1,43 @@
+/*
+* Basic Allocators
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASIC_ALLOC_H__
+#define BOTAN_BASIC_ALLOC_H__
+
+#include <botan/mem_pool.h>
+
+namespace Botan {
+
+/*
+* Malloc Allocator
+*/
+class BOTAN_DLL Malloc_Allocator : public Allocator
+ {
+ public:
+ void* allocate(u32bit);
+ void deallocate(void*, u32bit);
+
+ std::string type() const { return "malloc"; }
+ };
+
+/*
+* Locking Allocator
+*/
+class BOTAN_DLL Locking_Allocator : public Pooling_Allocator
+ {
+ public:
+ Locking_Allocator(Mutex* m) : Pooling_Allocator(m) {}
+
+ std::string type() const { return "locking"; }
+ private:
+ void* alloc_block(u32bit);
+ void dealloc_block(void*, u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/der_enc.h b/botan/build/botan/der_enc.h
new file mode 100644
index 0000000..23b5297
--- /dev/null
+++ b/botan/build/botan/der_enc.h
@@ -0,0 +1,91 @@
+/*
+* DER Encoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DER_ENCODER_H__
+#define BOTAN_DER_ENCODER_H__
+
+#include <botan/asn1_int.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* General DER Encoding Object
+*/
+class BOTAN_DLL DER_Encoder
+ {
+ public:
+ SecureVector<byte> get_contents();
+
+ DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
+ DER_Encoder& end_cons();
+
+ DER_Encoder& start_explicit(u16bit);
+ DER_Encoder& end_explicit();
+
+ DER_Encoder& raw_bytes(const byte[], u32bit);
+ DER_Encoder& raw_bytes(const MemoryRegion<byte>&);
+
+ DER_Encoder& encode_null();
+ DER_Encoder& encode(bool);
+ DER_Encoder& encode(u32bit);
+ DER_Encoder& encode(const class BigInt&);
+ DER_Encoder& encode(const MemoryRegion<byte>&, ASN1_Tag);
+ DER_Encoder& encode(const byte[], u32bit, ASN1_Tag);
+
+ DER_Encoder& encode(bool, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(u32bit, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const class BigInt&, ASN1_Tag,
+ ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const MemoryRegion<byte>&, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const byte[], u32bit, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+
+ template<typename T>
+ DER_Encoder& encode_optional(const T& value, const T& default_value)
+ {
+ if(value != default_value)
+ encode(value);
+ return (*this);
+ }
+
+ template<typename T>
+ DER_Encoder& encode_list(const std::vector<T>& values)
+ {
+ for(u32bit j = 0; j != values.size(); ++j)
+ encode(values[j]);
+ return (*this);
+ }
+
+ DER_Encoder& encode(const class ASN1_Object&);
+ DER_Encoder& encode_if(bool, DER_Encoder&);
+
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const byte[], u32bit);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const MemoryRegion<byte>&);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const std::string&);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, byte);
+ private:
+ class DER_Sequence
+ {
+ public:
+ ASN1_Tag tag_of() const;
+ SecureVector<byte> get_contents();
+ void add_bytes(const byte[], u32bit);
+ DER_Sequence(ASN1_Tag, ASN1_Tag);
+ private:
+ ASN1_Tag type_tag, class_tag;
+ SecureVector<byte> contents;
+ std::vector< SecureVector<byte> > set_contents;
+ };
+ SecureVector<byte> contents;
+ std::vector<DER_Sequence> subsequences;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/des.h b/botan/build/botan/des.h
new file mode 100644
index 0000000..6fa59de
--- /dev/null
+++ b/botan/build/botan/des.h
@@ -0,0 +1,70 @@
+/*
+* DES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DES_H__
+#define BOTAN_DES_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* DES
+*/
+class BOTAN_DLL DES : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "DES"; }
+ BlockCipher* clone() const { return new DES; }
+ DES() : BlockCipher(8, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 32> round_key;
+ };
+
+/*
+* Triple DES
+*/
+class BOTAN_DLL TripleDES : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "TripleDES"; }
+ BlockCipher* clone() const { return new TripleDES; }
+ TripleDES() : BlockCipher(8, 16, 24, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 96> round_key;
+ };
+
+/*
+* DES Tables
+*/
+extern const u32bit DES_SPBOX1[256];
+extern const u32bit DES_SPBOX2[256];
+extern const u32bit DES_SPBOX3[256];
+extern const u32bit DES_SPBOX4[256];
+extern const u32bit DES_SPBOX5[256];
+extern const u32bit DES_SPBOX6[256];
+extern const u32bit DES_SPBOX7[256];
+extern const u32bit DES_SPBOX8[256];
+
+extern const u64bit DES_IPTAB1[256];
+extern const u64bit DES_IPTAB2[256];
+extern const u64bit DES_FPTAB1[256];
+extern const u64bit DES_FPTAB2[256];
+
+}
+
+#endif
diff --git a/botan/build/botan/desx.h b/botan/build/botan/desx.h
new file mode 100644
index 0000000..49ecc24
--- /dev/null
+++ b/botan/build/botan/desx.h
@@ -0,0 +1,35 @@
+/*
+* DESX
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DESX_H__
+#define BOTAN_DESX_H__
+
+#include <botan/des.h>
+
+namespace Botan {
+
+/*
+* DESX
+*/
+class BOTAN_DLL DESX : public BlockCipher
+ {
+ public:
+ void clear() throw() { des.clear(); K1.clear(); K2.clear(); }
+ std::string name() const { return "DESX"; }
+ BlockCipher* clone() const { return new DESX; }
+ DESX() : BlockCipher(8, 24) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<byte, 8> K1, K2;
+ DES des;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dh.h b/botan/build/botan/dh.h
new file mode 100644
index 0000000..fa558bc
--- /dev/null
+++ b/botan/build/botan/dh.h
@@ -0,0 +1,80 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DIFFIE_HELLMAN_H__
+#define BOTAN_DIFFIE_HELLMAN_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dh_core.h>
+
+namespace Botan {
+
+/**
+* This class represents Diffie-Hellman public keys.
+*/
+class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DH"; }
+
+ MemoryVector<byte> public_value() const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ /**
+ * Construct an uninitialized key. Use this constructor if you wish
+ * to decode an encoded key into the new instance.
+ */
+ DH_PublicKey() {}
+
+ /**
+ * Construct a public key with the specified parameters.
+ * @param grp the DL group to use in the key
+ * @param y the public value y
+ */
+ DH_PublicKey(const DL_Group& grp, const BigInt& y);
+ private:
+ void X509_load_hook();
+ };
+
+/**
+* This class represents Diffie-Hellman private keys.
+*/
+class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
+ public PK_Key_Agreement_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> derive_key(const byte other[], u32bit length) const;
+ SecureVector<byte> derive_key(const DH_PublicKey& other) const;
+ SecureVector<byte> derive_key(const BigInt& other) const;
+
+ MemoryVector<byte> public_value() const;
+
+ /**
+ * Construct an uninitialized key. Use this constructor if you wish
+ * to decode an encoded key into the new instance.
+ */
+ DH_PrivateKey() {}
+
+ /**
+ * Construct a private key with predetermined value.
+ * @param rng random number generator to use
+ * @param grp the group to be used in the key
+ * @param x the key's secret value (or if zero, generate a new key)
+ */
+ DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp,
+ const BigInt& x = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false);
+ DH_Core core;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dh_core.h b/botan/build/botan/dh_core.h
new file mode 100644
index 0000000..91b50a2
--- /dev/null
+++ b/botan/build/botan/dh_core.h
@@ -0,0 +1,38 @@
+/*
+* DH Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DH_CORE_H__
+#define BOTAN_DH_CORE_H__
+
+#include <botan/dh_op.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/*
+* DH Core
+*/
+class BOTAN_DLL DH_Core
+ {
+ public:
+ BigInt agree(const BigInt&) const;
+
+ DH_Core& operator=(const DH_Core&);
+
+ DH_Core() { op = 0; }
+ DH_Core(const DH_Core&);
+ DH_Core(RandomNumberGenerator& rng,
+ const DL_Group&, const BigInt&);
+ ~DH_Core() { delete op; }
+ private:
+ DH_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dh_op.h b/botan/build/botan/dh_op.h
new file mode 100644
index 0000000..50f3d78
--- /dev/null
+++ b/botan/build/botan/dh_op.h
@@ -0,0 +1,45 @@
+/*
+* DH Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DH_OPS_H__
+#define BOTAN_DH_OPS_H__
+
+#include <botan/dl_group.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+
+namespace Botan {
+
+/*
+* DH Operation Interface
+*/
+class BOTAN_DLL DH_Operation
+ {
+ public:
+ virtual BigInt agree(const BigInt&) const = 0;
+ virtual DH_Operation* clone() const = 0;
+ virtual ~DH_Operation() {}
+ };
+
+/*
+* Botan's Default DH Operation
+*/
+class BOTAN_DLL Default_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const { return powermod_x_p(i); }
+ DH_Operation* clone() const { return new Default_DH_Op(*this); }
+
+ Default_DH_Op(const DL_Group& group, const BigInt& x) :
+ powermod_x_p(x, group.get_p()) {}
+ private:
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/divide.h b/botan/build/botan/divide.h
new file mode 100644
index 0000000..9445b13
--- /dev/null
+++ b/botan/build/botan/divide.h
@@ -0,0 +1,19 @@
+/*
+* Division
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DIVISON_ALGORITHM_H__
+#define BOTAN_DIVISON_ALGORITHM_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+void BOTAN_DLL divide(const BigInt&, const BigInt&, BigInt&, BigInt&);
+
+}
+
+#endif
diff --git a/botan/build/botan/dl_algo.h b/botan/build/botan/dl_algo.h
new file mode 100644
index 0000000..256ce96
--- /dev/null
+++ b/botan/build/botan/dl_algo.h
@@ -0,0 +1,116 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_ALGO_H__
+#define BOTAN_DL_ALGO_H__
+
+#include <botan/dl_group.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm (DL) public keys.
+*/
+class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the DL domain parameters of this key.
+ * @return the DL domain parameters of this key
+ */
+ const DL_Group& get_domain() const { return group; }
+
+ /**
+ * Get the public value y with y = g^x mod p where x is the secret key.
+ */
+ const BigInt& get_y() const { return y; }
+
+ /**
+ * Get the prime p of the underlying DL group.
+ * @return the prime p
+ */
+ const BigInt& group_p() const { return group.get_p(); }
+
+ /**
+ * Get the prime q of the underlying DL group.
+ * @return the prime q
+ */
+ const BigInt& group_q() const { return group.get_q(); }
+
+ /**
+ * Get the generator g of the underlying DL group.
+ * @return the generator g
+ */
+ const BigInt& group_g() const { return group.get_g(); }
+
+ /**
+ * Get the underlying groups encoding format.
+ * @return the encoding format
+ */
+ virtual DL_Group::Format group_format() const = 0;
+
+ /**
+ * Get an X509 encoder for this key.
+ * @return an encoder usable to encode this key.
+ */
+ X509_Encoder* x509_encoder() const;
+
+ /**
+ * Get an X509 decoder for this key.
+ * @return an decoder usable to decode a DL key and store the
+ * values in this instance.
+ */
+ X509_Decoder* x509_decoder();
+ protected:
+ BigInt y;
+ DL_Group group;
+ private:
+ virtual void X509_load_hook() {}
+ };
+
+/**
+* This class represents discrete logarithm (DL) private keys.
+*/
+class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the secret key x.
+ * @return the secret key
+ */
+ const BigInt& get_x() const { return x; }
+
+ /**
+ * Get an PKCS#8 encoder for this key.
+ * @return an encoder usable to encode this key.
+ */
+ PKCS8_Encoder* pkcs8_encoder() const;
+
+ /**
+ * Get an PKCS#8 decoder for this key.
+ * @param rng the rng to use
+ * @return an decoder usable to decode a DL key and store the
+ * values in this instance.
+ */
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator& rng);
+ protected:
+ BigInt x;
+ private:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false) {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dl_group.h b/botan/build/botan/dl_group.h
new file mode 100644
index 0000000..a84a85f
--- /dev/null
+++ b/botan/build/botan/dl_group.h
@@ -0,0 +1,162 @@
+/*
+* Discrete Logarithm Group
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_PARAM_H__
+#define BOTAN_DL_PARAM_H__
+
+#include <botan/bigint.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm groups. It holds a prime p,
+* a prime q = (p-1)/2 and g = x^((p-1)/q) mod p.
+*/
+class BOTAN_DLL DL_Group
+ {
+ public:
+ /**
+ * Get the prime p.
+ * @return the prime p
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Get the prime q.
+ * @return the prime q
+ */
+ const BigInt& get_q() const;
+
+ /**
+ * Get the base g.
+ * @return the base g
+ */
+ const BigInt& get_g() const;
+
+ /**
+ * The DL group encoding format variants.
+ */
+ enum Format {
+ ANSI_X9_42,
+ ANSI_X9_57,
+ PKCS_3,
+
+ DSA_PARAMETERS = ANSI_X9_57,
+ DH_PARAMETERS = ANSI_X9_42,
+ X942_DH_PARAMETERS = ANSI_X9_42,
+ PKCS3_DH_PARAMETERS = PKCS_3
+ };
+
+ /**
+ * Determine the prime creation for DL groups.
+ */
+ enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
+
+ /**
+ * Perform validity checks on the group.
+ * @param rng the rng to use
+ * @param strong whether to perform stronger by lengthier tests
+ * @return true if the object is consistent, false otherwise
+ */
+ bool verify_group(RandomNumberGenerator& rng, bool strong) const;
+
+ /**
+ * Encode this group into a string using PEM encoding.
+ * @param format the encoding format
+ * @return the string holding the PEM encoded group
+ */
+ std::string PEM_encode(Format format) const;
+
+ /**
+ * Encode this group into a string using DER encoding.
+ * @param format the encoding format
+ * @return the string holding the DER encoded group
+ */
+ SecureVector<byte> DER_encode(Format format) const;
+
+ /**
+ * Decode a DER/BER encoded group into this instance.
+ * @param src a DataSource providing the encoded group
+ * @param format the format of the encoded group
+ */
+ void BER_decode(DataSource& src, Format format);
+
+ /**
+ * Decode a PEM encoded group into this instance.
+ * @param src a DataSource providing the encoded group
+ */
+ void PEM_decode(DataSource& src);
+
+ /**
+ * Construct a DL group with uninitialized internal value.
+ * Use this constructor is you wish to set the groups values
+ * from a DER or PEM encoded group.
+ */
+ DL_Group();
+
+ /**
+ * Construct a DL group that is registered in the configuration.
+ * @param name the name that is configured in the global configuration
+ * for the desired group. If no configuration file is specified,
+ * the default values from the file policy.cpp will be used. For instance,
+ * use "modp/ietf/768" as name.
+ */
+ DL_Group(const std::string& name);
+
+ /**
+ * Create a new group randomly.
+ * @param rng the random number generator to use
+ * @param type specifies how the creation of primes p and q shall
+ * be performed. If type=Strong, then p will be determined as a
+ * safe prime, and q will be chosen as (p-1)/2. If
+ * type=Prime_Subgroup and qbits = 0, then the size of q will be
+ * determined according to the estimated difficulty of the DL
+ * problem. If type=DSA_Kosherizer, DSA primes will be created.
+ * @param pbits the number of bits of p
+ * @param qbits the number of bits of q. Leave it as 0 to have
+ * the value determined according to pbits.
+ */
+ DL_Group(RandomNumberGenerator& rng, PrimeType type,
+ u32bit pbits, u32bit qbits = 0);
+
+ /**
+ * Create a DSA group with a given seed.
+ * @param rng the random number generator to use
+ * @param seed the seed to use to create the random primes
+ * @param pbits the desired bit size of the prime p
+ * @param qbits the desired bit size of the prime q.
+ */
+ DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed,
+ u32bit pbits = 1024, u32bit qbits = 0);
+
+ /**
+ * Create a DL group. The prime q will be determined according to p.
+ * @param p the prime p
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& g);
+
+ /**
+ * Create a DL group.
+ * @param p the prime p
+ * @param q the prime q
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& q, const BigInt& g);
+ private:
+ static BigInt make_dsa_generator(const BigInt&, const BigInt&);
+
+ void init_check() const;
+ void initialize(const BigInt&, const BigInt&, const BigInt&);
+ bool initialized;
+ BigInt p, q, g;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dlies.h b/botan/build/botan/dlies.h
new file mode 100644
index 0000000..88a22b9
--- /dev/null
+++ b/botan/build/botan/dlies.h
@@ -0,0 +1,69 @@
+/*
+* DLIES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DLIES_H__
+#define BOTAN_DLIES_H__
+
+#include <botan/pubkey.h>
+#include <botan/mac.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* DLIES Encryption
+*/
+class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
+ {
+ public:
+ DLIES_Encryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ u32bit mac_key_len = 20);
+
+ ~DLIES_Encryptor();
+
+ void set_other_key(const MemoryRegion<byte>&);
+ private:
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+ u32bit maximum_input_size() const;
+
+ const PK_Key_Agreement_Key& key;
+ SecureVector<byte> other_key;
+
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ u32bit mac_keylen;
+ };
+
+/*
+* DLIES Decryption
+*/
+class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
+ {
+ public:
+ DLIES_Decryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ u32bit mac_key_len = 20);
+
+ ~DLIES_Decryptor();
+
+ private:
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Key_Agreement_Key& key;
+
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ u32bit mac_keylen;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dsa.h b/botan/build/botan/dsa.h
new file mode 100644
index 0000000..4c9b708
--- /dev/null
+++ b/botan/build/botan/dsa.h
@@ -0,0 +1,62 @@
+/*
+* DSA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_H__
+#define BOTAN_DSA_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dsa_core.h>
+
+namespace Botan {
+
+/*
+* DSA Public Key
+*/
+class BOTAN_DLL DSA_PublicKey : public PK_Verifying_wo_MR_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DSA"; }
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DSA_PublicKey() {}
+ DSA_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ DSA_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* DSA Private Key
+*/
+class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ DSA_PrivateKey() {}
+ DSA_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dsa_core.h b/botan/build/botan/dsa_core.h
new file mode 100644
index 0000000..8bb1621
--- /dev/null
+++ b/botan/build/botan/dsa_core.h
@@ -0,0 +1,37 @@
+/*
+* DSA Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_CORE_H__
+#define BOTAN_DSA_CORE_H__
+
+#include <botan/dsa_op.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* DSA Core
+*/
+class BOTAN_DLL DSA_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+
+ DSA_Core& operator=(const DSA_Core&);
+
+ DSA_Core() { op = 0; }
+ DSA_Core(const DSA_Core&);
+ DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~DSA_Core() { delete op; }
+ private:
+ DSA_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/dsa_op.h b/botan/build/botan/dsa_op.h
new file mode 100644
index 0000000..0b112c6
--- /dev/null
+++ b/botan/build/botan/dsa_op.h
@@ -0,0 +1,53 @@
+/*
+* DSA Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_OPS_H__
+#define BOTAN_DSA_OPS_H__
+
+#include <botan/numthry.h>
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* DSA Operation
+*/
+class BOTAN_DLL DSA_Operation
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual DSA_Operation* clone() const = 0;
+ virtual ~DSA_Operation() {}
+ };
+
+/*
+* Botan's Default DSA Operation
+*/
+class BOTAN_DLL Default_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new Default_DSA_Op(*this); }
+
+ Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eac_asn_obj.h b/botan/build/botan/eac_asn_obj.h
new file mode 100644
index 0000000..3e70f6b
--- /dev/null
+++ b/botan/build/botan/eac_asn_obj.h
@@ -0,0 +1,244 @@
+/*
+* EAC ASN.1 Objects
+* (C) 2007-2008 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_ASN1_OBJ_H__
+#define BOTAN_EAC_ASN1_OBJ_H__
+
+#include <botan/asn1_obj.h>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* This class represents CVC EAC Time objects.
+* It only models year, month and day. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL EAC_Time : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get a this objects value as a string.
+ * @return the date string
+ */
+ std::string as_string() const;
+
+ /**
+ * Get a this objects value as a readable formatted string.
+ * @return the date string
+ */
+ std::string readable_string() const;
+
+ /**
+ * Find out whether this object's values have been set.
+ * @return true if this object's internal values are set
+ */
+ bool time_is_set() const;
+
+ /**
+ * Compare this to another EAC_Time object.
+ * @return -1 if this object's date is earlier than
+ * other, +1 in the opposite case, and 0 if both dates are
+ * equal.
+ */
+ s32bit cmp(const EAC_Time& other) const;
+
+ /**
+ * Set this' value by a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ void set_to(const std::string& str);
+ //void set_to(const std::string&, ASN1_Tag);
+
+ /**
+ * Add the specified number of years to this.
+ * @param years the number of years to add
+ */
+ void add_years(u32bit years);
+
+ /**
+ * Add the specified number of months to this.
+ * @param months the number of months to add
+ */
+ void add_months(u32bit months);
+
+ /**
+ * Get the year value of this objects.
+ * @return the year value
+ */
+ u32bit get_year() const;
+
+ /**
+ * Get the month value of this objects.
+ * @return the month value
+ */
+ u32bit get_month() const;
+
+ /**
+ * Get the day value of this objects.
+ * @return the day value
+ */
+ u32bit get_day() const;
+
+ EAC_Time(u64bit, ASN1_Tag t = ASN1_Tag(0));
+ //EAC_Time(const std::string& = "");
+ EAC_Time(const std::string&, ASN1_Tag = ASN1_Tag(0));
+ EAC_Time(u32bit year, u32bit month, u32bit day, ASN1_Tag = ASN1_Tag(0));
+
+ virtual ~EAC_Time() {}
+ private:
+ SecureVector<byte> encoded_eac_time() const;
+ bool passes_sanity_check() const;
+ u32bit year, month, day;
+ ASN1_Tag tag;
+ };
+
+/**
+* This class represents CVC CEDs. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL ASN1_Ced : public EAC_Time
+ {
+ public:
+ /**
+ * Construct a CED from a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ ASN1_Ced(std::string const& str = "");
+
+ /**
+ * Construct a CED from a timer value.
+ * @param time the number of seconds elapsed midnight, 1st
+ * January 1970 GMT (or 7pm, 31st December 1969 EST) up to the
+ * desired date
+ */
+ ASN1_Ced(u64bit time);
+
+ /**
+ * Copy constructor (for general EAC_Time objects).
+ * @param other the object to copy from
+ */
+ ASN1_Ced(EAC_Time const& other);
+ //ASN1_Ced(ASN1_Cex const& cex);
+ };
+
+
+/**
+* This class represents CVC CEXs. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL ASN1_Cex : public EAC_Time
+ {
+ public:
+ /**
+ * Construct a CED from a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ ASN1_Cex(std::string const& str="");
+
+ /**
+ * Construct a CED from a timer value.
+ * @param time the number of seconds elapsed
+ * midnight, 1st
+ * January 1970 GMT (or 7pm, 31st December 1969 EST)
+ * up to the desired date
+ */
+ ASN1_Cex(u64bit time);
+
+ /**
+ * Copy constructor (for general EAC_Time objects).
+ * @param other the object to copy from
+ */
+ ASN1_Cex(EAC_Time const& other);
+ //ASN1_Cex(ASN1_Ced const& ced);
+ };
+
+/**
+* Base class for car/chr of cv certificates.
+*/
+class BOTAN_DLL ASN1_EAC_String: public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get this objects string value.
+ * @return the string value
+ */
+ std::string value() const;
+
+ /**
+ * Get this objects string value.
+ * @return the string value in iso8859 encoding
+ */
+ std::string iso_8859() const;
+
+ ASN1_Tag tagging() const;
+ ASN1_EAC_String(const std::string& str, ASN1_Tag the_tag);
+
+ virtual ~ASN1_EAC_String() {}
+ protected:
+ bool sanity_check() const;
+ private:
+ std::string iso_8859_str;
+ ASN1_Tag tag;
+ };
+
+/**
+* This class represents CARs of CVCs. (String tagged with 2)
+*/
+class BOTAN_DLL ASN1_Car : public ASN1_EAC_String
+ {
+ public:
+ /**
+ * Create a CAR with the specified content.
+ * @param str the CAR value
+ */
+ ASN1_Car(std::string const& str = "");
+ };
+
+/**
+* This class represents CHRs of CVCs (tag 32)
+*/
+class BOTAN_DLL ASN1_Chr : public ASN1_EAC_String
+ {
+ public:
+ /**
+ * Create a CHR with the specified content.
+ * @param str the CHR value
+ */
+ ASN1_Chr(std::string const& str = "");
+ };
+
+/*
+* Comparison Operations
+*/
+bool operator==(const EAC_Time&, const EAC_Time&);
+bool operator!=(const EAC_Time&, const EAC_Time&);
+bool operator<=(const EAC_Time&, const EAC_Time&);
+bool operator>=(const EAC_Time&, const EAC_Time&);
+bool operator>(const EAC_Time&, const EAC_Time&);
+bool operator<(const EAC_Time&, const EAC_Time&);
+
+bool operator==(const ASN1_EAC_String&, const ASN1_EAC_String&);
+inline bool operator!=(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/eac_obj.h b/botan/build/botan/eac_obj.h
new file mode 100644
index 0000000..04afd7e
--- /dev/null
+++ b/botan/build/botan/eac_obj.h
@@ -0,0 +1,131 @@
+/*
+* EAC1_1 objects
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_OBJ_H__
+#define BOTAN_EAC_OBJ_H__
+
+#include <botan/pubkey.h>
+#include <botan/x509_key.h>
+#include <botan/signed_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/parsing.h>
+#include <botan/pem.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/ecdsa_sig.h>
+#include <string>
+
+namespace Botan {
+
+const std::string eac_cvc_emsa("EMSA1_BSI");
+
+/*
+* TR03110 v1.1 EAC CV Certificate
+*/
+template<typename Derived> // CRTP is used enable the call sequence:
+class BOTAN_DLL EAC1_1_obj : public EAC_Signed_Object
+ {
+ // data members first:
+ protected:
+
+ ECDSA_Signature m_sig;
+
+ // member functions here:
+ public:
+ /**
+ * Return the signature as a concatenation of the encoded parts.
+ * @result the concatenated signature
+ */
+ SecureVector<byte> get_concat_sig() const;
+
+ /**
+ * Verify the signature of this objects.
+ * @param pub_key the public key to verify the signature with
+ * @result true if the verification succeeded
+ */
+ virtual bool check_signature(Public_Key& pub_key) const;
+
+ protected:
+ void init(SharedPtrConverter<DataSource> in);
+
+ static SecureVector<byte> make_signature(PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+
+ virtual ~EAC1_1_obj<Derived>(){}
+
+ };
+
+template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_sig() const
+ {
+ return m_sig.get_concatenation();
+ }
+
+template<typename Derived> SecureVector<byte>
+EAC1_1_obj<Derived>::make_signature(PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng)
+ {
+ // this is the signature as a der sequence
+ SecureVector<byte> seq_sig = signer->sign_message(tbs_bits, rng);
+
+ ECDSA_Signature sig(decode_seq(seq_sig));
+ SecureVector<byte> concat_sig(sig.get_concatenation());
+ return concat_sig;
+ }
+
+template<typename Derived> void EAC1_1_obj<Derived>::init(SharedPtrConverter<DataSource> in)
+ {
+ try
+ {
+ Derived::decode_info(in.get_shared(), tbs_bits, m_sig);
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error(PEM_label_pref + " decoding failed");
+ }
+ }
+
+template<typename Derived>
+bool EAC1_1_obj<Derived>::check_signature(Public_Key& pub_key) const
+ {
+ try
+ {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ {
+ return false;
+ }
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ if(!dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key))
+ return false;
+
+ std::auto_ptr<ECDSA_Signature_Encoder> enc(new ECDSA_Signature_Encoder(&m_sig));
+ SecureVector<byte> seq_sig = enc->signature_bits();
+ SecureVector<byte> to_sign = tbs_data();
+
+ PK_Verifying_wo_MR_Key& sig_key = dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key);
+ std::auto_ptr<PK_Verifier> verifier(get_pk_verifier(sig_key, padding, format));
+ return verifier->verify_message(to_sign, seq_sig);
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/eax.h b/botan/build/botan/eax.h
new file mode 100644
index 0000000..1bb2e51
--- /dev/null
+++ b/botan/build/botan/eax.h
@@ -0,0 +1,85 @@
+/*
+* EAX Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAX_H__
+#define BOTAN_EAX_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* EAX Base Class
+*/
+class BOTAN_DLL EAX_Base : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey&);
+ void set_iv(const InitializationVector&);
+ void set_header(const byte[], u32bit);
+ std::string name() const;
+
+ bool valid_keylength(u32bit) const;
+
+ ~EAX_Base() { delete cipher; delete mac; }
+ protected:
+ EAX_Base(BlockCipher*, u32bit);
+ void start_msg();
+ void increment_counter();
+
+ const u32bit TAG_SIZE, BLOCK_SIZE;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+ SecureVector<byte> nonce_mac, header_mac, state, buffer;
+ u32bit position;
+ };
+
+/*
+* EAX Encryption
+*/
+class BOTAN_DLL EAX_Encryption : public EAX_Base
+ {
+ public:
+ EAX_Encryption(BlockCipher* ciph, u32bit tag_size = 0) :
+ EAX_Base(ciph, tag_size) {}
+
+ EAX_Encryption(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit tag_size) : EAX_Base(ciph, tag_size)
+ {
+ set_key(key);
+ set_iv(iv);
+ }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+/*
+* EAX Decryption
+*/
+class BOTAN_DLL EAX_Decryption : public EAX_Base
+ {
+ public:
+ EAX_Decryption(BlockCipher* ciph, u32bit tag_size = 0);
+
+ EAX_Decryption(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit tag_size = 0);
+ private:
+ void write(const byte[], u32bit);
+ void do_write(const byte[], u32bit);
+ void end_msg();
+ SecureVector<byte> queue;
+ u32bit queue_start, queue_end;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ec_dompar.h b/botan/build/botan/ec_dompar.h
new file mode 100644
index 0000000..47971d8
--- /dev/null
+++ b/botan/build/botan/ec_dompar.h
@@ -0,0 +1,121 @@
+/*
+* ECDSA Domain Parameters
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_DOMAIN_PARAMETERS_H__
+#define BOTAN_ECC_DOMAIN_PARAMETERS_H__
+
+#include <botan/point_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/curve_gfp.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/alg_id.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/**
+* This class represents elliptic curce domain parameters
+*/
+class BOTAN_DLL EC_Domain_Params
+ {
+ public:
+
+ /**
+ * Construct Domain paramers from specified parameters
+ * @param curve elliptic curve
+ * @param base_point a base point
+ * @param order the order of the base point
+ * @param cofactor the cofactor
+ */
+ EC_Domain_Params(const CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor);
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const CurveGFp& get_curve() const
+ {
+ return m_curve;
+ }
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const PointGFp& get_base_point() const
+ {
+ return m_base_point;
+ }
+
+ /**
+ * Return the order of the base point
+ * @result order of the base point
+ */
+ const BigInt& get_order() const
+ {
+ return m_order;
+ }
+
+ /**
+ * Return the cofactor
+ * @result the cofactor
+ */
+ const BigInt& get_cofactor() const
+ {
+ return m_cofactor;
+ }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ std::string get_oid() const { return m_oid; }
+
+ private:
+ friend EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+ CurveGFp m_curve;
+ PointGFp m_base_point;
+ BigInt m_order;
+ BigInt m_cofactor;
+ std::string m_oid;
+ };
+
+bool operator==(EC_Domain_Params const& lhs, EC_Domain_Params const& rhs);
+
+inline bool operator!=(const EC_Domain_Params& lhs,
+ const EC_Domain_Params& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+enum EC_dompar_enc { ENC_EXPLICIT = 0, ENC_IMPLICITCA = 1, ENC_OID = 2 };
+
+SecureVector<byte> encode_der_ec_dompar(EC_Domain_Params const& dom_pars,
+ EC_dompar_enc enc_type);
+
+EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded);
+
+/**
+* Factory function, the only way to obtain EC domain parameters with
+* an OID. The demanded OID has to be registered in the InSiTo
+* configuration. Consult the file ec_dompar.cpp for the default
+* configuration.
+* @param oid the oid of the demanded EC domain parameters
+* @result the EC domain parameters associated with the OID
+*/
+EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+}
+
+#endif
diff --git a/botan/build/botan/ecb.h b/botan/build/botan/ecb.h
new file mode 100644
index 0000000..5230f9b
--- /dev/null
+++ b/botan/build/botan/ecb.h
@@ -0,0 +1,73 @@
+/*
+* ECB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECB_H__
+#define BOTAN_ECB_H__
+
+#include <botan/modebase.h>
+#include <botan/mode_pad.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* ECB
+*/
+class BOTAN_DLL ECB : public BlockCipherMode
+ {
+ protected:
+ ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) :
+ BlockCipherMode(ciph, "ECB", 0), padder(pad) {}
+ ~ECB() { delete padder; }
+
+ std::string name() const;
+ BlockCipherModePaddingMethod* padder;
+ private:
+ bool valid_iv_size(u32bit) const;
+ };
+
+/*
+* ECB Encryption
+*/
+class BOTAN_DLL ECB_Encryption : public ECB
+ {
+ public:
+ ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ ECB(ciph, pad) {}
+
+ ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key) :
+ ECB(ciph, pad) { set_key(key); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+/*
+* ECB Decryption
+*/
+class BOTAN_DLL ECB_Decryption : public ECB
+ {
+ public:
+ ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ ECB(ciph, pad) {}
+
+ ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key) :
+ ECB(ciph, pad) { set_key(key); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ecc_key.h b/botan/build/botan/ecc_key.h
new file mode 100644
index 0000000..0ca9a0e
--- /dev/null
+++ b/botan/build/botan/ecc_key.h
@@ -0,0 +1,154 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H__
+#define BOTAN_ECC_PUBLIC_KEY_BASE_H__
+
+#include <botan/bigint.h>
+#include <botan/curve_gfp.h>
+#include <botan/pk_keys.h>
+#include <botan/ec_dompar.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract EC Public Keys. When encoding a key
+* via an encoder that can be accessed via the corresponding member
+* functions, the key will decide upon its internally stored encoding
+* information whether to encode itself with or without domain
+* parameters, or using the domain parameter oid. Furthermore, a public
+* key without domain parameters can be decoded. In that case, it
+* cannot be used for verification until its domain parameters are set
+* by calling the corresponding member function.
+*/
+class BOTAN_DLL EC_PublicKey : public virtual Public_Key
+ {
+ public:
+
+ /**
+ * Tells whether this key knows his own domain parameters.
+ * @result true if the domain parameters are set, false otherwise
+ */
+ bool domain_parameters_set();
+
+ /**
+ * Get the public point of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the public point of this key
+ */
+ const PointGFp& public_point() const;
+
+ /**
+ * Get the domain parameters of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the domain parameters of this key
+ */
+ const EC_Domain_Params& domain_parameters() const;
+
+ /**
+ * Set the domain parameter encoding to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_parameter_encoding(EC_dompar_enc enc);
+
+ /**
+ * Get the domain parameter encoding to be used when encoding this key.
+ * @result the encoding to use
+ */
+ inline int get_parameter_encoding() const
+ {
+ return m_param_enc;
+ }
+
+ //ctors
+ EC_PublicKey()
+ : m_param_enc(ENC_EXPLICIT)
+ {
+ //assert(mp_dom_pars.get() == 0);
+ //assert(mp_public_point.get() == 0);
+ }
+
+ /**
+ * Get an x509_encoder that can be used to encode this key.
+ * @result an x509_encoder for this key
+ */
+ X509_Encoder* x509_encoder() const;
+
+ /**
+ * Get an x509_decoder that can be used to decode a stored key into
+ * this key.
+ * @result an x509_decoder for this key
+ */
+ X509_Decoder* x509_decoder();
+
+ /**
+ * Make sure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ virtual ~EC_PublicKey() {}
+ protected:
+ virtual void X509_load_hook();
+
+ SecureVector<byte> m_enc_public_point; // stores the public point
+
+ std::auto_ptr<EC_Domain_Params> mp_dom_pars;
+ std::auto_ptr<PointGFp> mp_public_point;
+ EC_dompar_enc m_param_enc;
+ };
+
+/**
+* This abstract class represents general EC Private Keys
+*/
+class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key
+ {
+ public:
+
+ /**
+ * Get an PKCS#8 encoder that can be used to encoded this key.
+ * @result an PKCS#8 encoder for this key
+ */
+ PKCS8_Encoder* pkcs8_encoder() const;
+
+ /**
+ * Get an PKCS#8 decoder that can be used to decoded a stored key into
+ * this key.
+ * @result an PKCS#8 decoder for this key
+ */
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+
+ /**
+ * Get the private key value of this key object.
+ * @result the private key value of this key object
+ */
+ const BigInt& private_value() const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ virtual ~EC_PrivateKey() {}
+ protected:
+ virtual void PKCS8_load_hook(bool = false);
+ void generate_private_key(RandomNumberGenerator&);
+ BigInt m_private_value;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ecdsa.h b/botan/build/botan/ecdsa.h
new file mode 100644
index 0000000..3794457
--- /dev/null
+++ b/botan/build/botan/ecdsa.h
@@ -0,0 +1,145 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_KEY_H__
+#define BOTAN_ECDSA_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/ecdsa_core.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDSA Public Keys.
+*/
+class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey,
+ public PK_Verifying_wo_MR_Key
+ {
+ public:
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name ("ECDSA")
+ */
+ std::string algo_name() const { return "ECDSA"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @result the maximum number of input bits
+ */
+ u32bit max_input_bits() const;
+
+ /**
+ * Verify a message with this key.
+ * @param message the byte array containing the message
+ * @param mess_len the number of bytes in the message byte array
+ * @param signature the byte array containing the signature
+ * @param sig_len the number of bytes in the signature byte array
+ */
+ bool verify(const byte message[], u32bit mess_len,
+ const byte signature[], u32bit sig_len) const;
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECDSA_PublicKey() {}
+
+ /**
+ * Construct a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECDSA_PublicKey(const EC_Domain_Params& dom_par,
+ const PointGFp& public_point); // sets core
+
+ ECDSA_PublicKey const& operator=(const ECDSA_PublicKey& rhs);
+
+ ECDSA_PublicKey(const ECDSA_PublicKey& other);
+
+ /**
+ * Set the domain parameters of this key. This function has to be
+ * used when a key encoded without domain parameters was decoded into
+ * this key. Otherwise it will not be able to verify a signature.
+ * @param dom_pars the domain_parameters associated with this key
+ * @throw Invalid_Argument if the point was found not to be satisfying the
+ * curve equation of the provided domain parameters
+ * or if this key already has domain parameters set
+ * and these are differing from those given as the parameter
+ */
+ void set_domain_parameters(const EC_Domain_Params& dom_pars);
+
+ /**
+ * Ensure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values(const ECDSA_PublicKey& other);
+
+ ECDSA_Core m_ecdsa_core;
+ };
+
+/**
+* This class represents ECDSA Private Keys
+*/
+class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
+ public EC_PrivateKey,
+ public PK_Signing_Key
+ {
+ public:
+ //ctors
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECDSA_PrivateKey() {}
+
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& domain);
+
+ ECDSA_PrivateKey(const ECDSA_PrivateKey& other);
+ ECDSA_PrivateKey const& operator=(const ECDSA_PrivateKey& rhs);
+
+ /**
+ * Sign a message with this key.
+ * @param message the byte array representing the message to be signed
+ * @param mess_len the length of the message byte array
+ * @result the signature
+ */
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ virtual void set_all_values(const ECDSA_PrivateKey& other);
+ private:
+ void PKCS8_load_hook(bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ecdsa_core.h b/botan/build/botan/ecdsa_core.h
new file mode 100644
index 0000000..ceccc94
--- /dev/null
+++ b/botan/build/botan/ecdsa_core.h
@@ -0,0 +1,47 @@
+/*
+* ECDSA Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_CORE_H__
+#define BOTAN_ECDSA_CORE_H__
+
+#include <botan/ecdsa_op.h>
+#include <botan/blinding.h>
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECDSA Core
+*/
+class BOTAN_DLL ECDSA_Core
+ {
+ public:
+ bool verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const;
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ ECDSA_Core& operator=(const ECDSA_Core&);
+
+ ECDSA_Core() { op = 0; }
+
+ ECDSA_Core(const ECDSA_Core&);
+
+ ECDSA_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+
+ ~ECDSA_Core() { delete op; }
+ private:
+ ECDSA_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ecdsa_op.h b/botan/build/botan/ecdsa_op.h
new file mode 100644
index 0000000..25831a9
--- /dev/null
+++ b/botan/build/botan/ecdsa_op.h
@@ -0,0 +1,64 @@
+/*
+* ECDSA Operations
+* (C) 1999-2008 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_OPERATIONS_H__
+#define BOTAN_ECDSA_OPERATIONS_H__
+
+#include <botan/ec_dompar.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* ECDSA Operation
+*/
+class BOTAN_DLL ECDSA_Operation
+ {
+ public:
+ virtual bool verify(const byte sig[], u32bit sig_len,
+ const byte msg[], u32bit msg_len) const = 0;
+
+ virtual SecureVector<byte> sign(const byte message[],
+ u32bit mess_len,
+ RandomNumberGenerator&) const = 0;
+
+ virtual ECDSA_Operation* clone() const = 0;
+
+ virtual ~ECDSA_Operation() {}
+ };
+
+
+/*
+* Default ECDSA operation
+*/
+class BOTAN_DLL Default_ECDSA_Op : public ECDSA_Operation
+ {
+ public:
+ bool verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const;
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ ECDSA_Operation* clone() const
+ {
+ return new Default_ECDSA_Op(*this);
+ }
+
+ Default_ECDSA_Op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+ private:
+ EC_Domain_Params m_dom_pars;
+ PointGFp m_pub_key;
+ BigInt m_priv_key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ecdsa_sig.h b/botan/build/botan/ecdsa_sig.h
new file mode 100644
index 0000000..15015c7
--- /dev/null
+++ b/botan/build/botan/ecdsa_sig.h
@@ -0,0 +1,88 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_SIGNATURE_H__
+#define BOTAN_ECDSA_SIGNATURE_H__
+
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+class BOTAN_DLL ECDSA_Signature
+ {
+ public:
+ friend class ECDSA_Signature_Decoder;
+
+ ECDSA_Signature() {}
+ ECDSA_Signature(const BigInt& r, const BigInt& s);
+ ECDSA_Signature(ECDSA_Signature const& other);
+ ECDSA_Signature const& operator=(ECDSA_Signature const& other);
+
+ const BigInt& get_r() const { return m_r; }
+ const BigInt& get_s() const { return m_s; }
+
+ /**
+ * return the r||s
+ */
+ SecureVector<byte> const get_concatenation() const;
+ private:
+ BigInt m_r;
+ BigInt m_s;
+ };
+
+/* Equality of ECDSA_Signature */
+bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs);
+inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+class BOTAN_DLL ECDSA_Signature_Decoder
+ {
+ public:
+ void signature_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(m_signature->m_r)
+ .decode(m_signature->m_s)
+ .verify_end()
+ .end_cons();
+ }
+ ECDSA_Signature_Decoder(ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ ECDSA_Signature* m_signature;
+ };
+
+class BOTAN_DLL ECDSA_Signature_Encoder
+ {
+ public:
+ MemoryVector<byte> signature_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(m_signature->get_r())
+ .encode(m_signature->get_s())
+ .end_cons()
+ .get_contents();
+ }
+ ECDSA_Signature_Encoder(const ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ const ECDSA_Signature* m_signature;
+ };
+
+ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq);
+ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation);
+
+}
+
+#endif
diff --git a/botan/build/botan/eckaeg.h b/botan/build/botan/eckaeg.h
new file mode 100644
index 0000000..31b6574
--- /dev/null
+++ b/botan/build/botan/eckaeg.h
@@ -0,0 +1,137 @@
+/*
+* ECKAEG
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_KEY_H__
+#define BOTAN_ECKAEG_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/eckaeg_core.h>
+
+namespace Botan {
+
+/**
+* This class represents ECKAEG Public Keys.
+*/
+class BOTAN_DLL ECKAEG_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECKAEG_PublicKey() {}
+
+ /**
+ * Construct a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECKAEG_PublicKey(const EC_Domain_Params& dom_par,
+ const PointGFp& public_point);
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name
+ */
+ std::string algo_name() const { return "ECKAEG"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @result the maximum number of input bits
+ */
+ u32bit max_input_bits() const
+ {
+ if(!mp_dom_pars.get())
+ throw Invalid_State("ECKAEG_PublicKey::max_input_bits(): domain parameters not set");
+
+ return mp_dom_pars->get_order().bits();
+ }
+
+ ECKAEG_PublicKey(ECKAEG_PublicKey const& other);
+ ECKAEG_PublicKey const& operator= (ECKAEG_PublicKey const& rhs);
+
+ /**
+ * Make sure that the public point and domain parameters of this
+ * key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values(const ECKAEG_PublicKey& other);
+
+ ECKAEG_Core m_eckaeg_core;
+ };
+
+/**
+* This class represents ECKAEG Private Keys.
+*/
+class BOTAN_DLL ECKAEG_PrivateKey : public ECKAEG_PublicKey,
+ public EC_PrivateKey,
+ public PK_Key_Agreement_Key
+ {
+ public:
+
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECKAEG_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& dom_pars)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_pars));
+ generate_private_key(rng);
+ mp_public_point->check_invariants();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECKAEG_PrivateKey() {}
+ ECKAEG_PrivateKey(ECKAEG_PrivateKey const& other);
+ ECKAEG_PrivateKey const& operator=(ECKAEG_PrivateKey const& rhs);
+
+ MemoryVector<byte> public_value() const;
+
+ void PKCS8_load_hook(bool = false);
+
+ /**
+ * Derive a shared key with the other partys public key.
+ * @param key the other partys public key
+ * @param key_len the other partys public key
+ */
+ SecureVector<byte> derive_key(const byte key[], u32bit key_len) const;
+
+ /**
+ * Derive a shared key with the other partys public key.
+ * @param other the other partys public key
+ */
+ SecureVector<byte> derive_key(const ECKAEG_PublicKey& other) const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ virtual void set_all_values(const ECKAEG_PrivateKey& other);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eckaeg_core.h b/botan/build/botan/eckaeg_core.h
new file mode 100644
index 0000000..d632c94
--- /dev/null
+++ b/botan/build/botan/eckaeg_core.h
@@ -0,0 +1,44 @@
+/*
+* ECKAEG Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_CORE_H__
+#define BOTAN_ECKAEG_CORE_H__
+
+#include <botan/eckaeg_op.h>
+#include <botan/blinding.h>
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECKAEG Core
+*/
+class BOTAN_DLL ECKAEG_Core
+ {
+ public:
+ SecureVector<byte> agree(const PointGFp&) const;
+
+ ECKAEG_Core& operator=(const ECKAEG_Core&);
+
+ ECKAEG_Core() { op = 0; }
+
+ ECKAEG_Core(const ECKAEG_Core&);
+
+ ECKAEG_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ PointGFp const& pub_key);
+
+ ~ECKAEG_Core() { delete op; }
+ private:
+ ECKAEG_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eckaeg_op.h b/botan/build/botan/eckaeg_op.h
new file mode 100644
index 0000000..27cf4f3
--- /dev/null
+++ b/botan/build/botan/eckaeg_op.h
@@ -0,0 +1,49 @@
+/*
+* ECKAEG Operations
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_OPERATIONS_H__
+#define BOTAN_ECKAEG_OPERATIONS_H__
+
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECKAEG Operation
+*/
+class BOTAN_DLL ECKAEG_Operation
+ {
+ public:
+ virtual SecureVector<byte> agree(const PointGFp&) const = 0;
+ virtual ECKAEG_Operation* clone() const = 0;
+ virtual ~ECKAEG_Operation() {}
+ };
+
+/*
+* Default ECKAEG operation
+*/
+class BOTAN_DLL Default_ECKAEG_Op : public ECKAEG_Operation
+ {
+ public:
+ SecureVector<byte> agree(const PointGFp& i) const;
+
+ ECKAEG_Operation* clone() const { return new Default_ECKAEG_Op(*this); }
+
+ Default_ECKAEG_Op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+ private:
+ EC_Domain_Params m_dom_pars;
+ PointGFp m_pub_key;
+ BigInt m_priv_key;
+ };
+
+
+}
+
+#endif
diff --git a/botan/build/botan/elg_core.h b/botan/build/botan/elg_core.h
new file mode 100644
index 0000000..a7768a6
--- /dev/null
+++ b/botan/build/botan/elg_core.h
@@ -0,0 +1,44 @@
+/*
+* ElGamal Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_CORE_H__
+#define BOTAN_ELGAMAL_CORE_H__
+
+#include <botan/elg_op.h>
+#include <botan/blinding.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* ElGamal Core
+*/
+class BOTAN_DLL ELG_Core
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ ELG_Core& operator=(const ELG_Core&);
+
+ ELG_Core() { op = 0; }
+ ELG_Core(const ELG_Core&);
+
+ ELG_Core(const DL_Group&, const BigInt&);
+ ELG_Core(RandomNumberGenerator&, const DL_Group&,
+ const BigInt&, const BigInt&);
+
+ ~ELG_Core() { delete op; }
+ private:
+ ELG_Operation* op;
+ Blinder blinder;
+ u32bit p_bytes;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/elg_op.h b/botan/build/botan/elg_op.h
new file mode 100644
index 0000000..39ed897
--- /dev/null
+++ b/botan/build/botan/elg_op.h
@@ -0,0 +1,52 @@
+/*
+* ElGamal Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_OPS_H__
+#define BOTAN_ELGAMAL_OPS_H__
+
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* ElGamal Operation
+*/
+class BOTAN_DLL ELG_Operation
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0;
+ virtual ELG_Operation* clone() const = 0;
+ virtual ~ELG_Operation() {}
+ };
+
+/*
+* Botan's Default ElGamal Operation
+*/
+class BOTAN_DLL Default_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new Default_ELG_Op(*this); }
+
+ Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt p;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Modular_Reducer mod_p;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/elgamal.h b/botan/build/botan/elgamal.h
new file mode 100644
index 0000000..93e640f
--- /dev/null
+++ b/botan/build/botan/elgamal.h
@@ -0,0 +1,59 @@
+/*
+* ElGamal
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_H__
+#define BOTAN_ELGAMAL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/elg_core.h>
+
+namespace Botan {
+
+/*
+* ElGamal Public Key
+*/
+class BOTAN_DLL ElGamal_PublicKey : public PK_Encrypting_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "ElGamal"; }
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+ u32bit max_input_bits() const;
+
+ ElGamal_PublicKey() {}
+ ElGamal_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ ELG_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* ElGamal Private Key
+*/
+class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
+ public PK_Decrypting_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ ElGamal_PrivateKey() {}
+ ElGamal_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eme.h b/botan/build/botan/eme.h
new file mode 100644
index 0000000..321c1d0
--- /dev/null
+++ b/botan/build/botan/eme.h
@@ -0,0 +1,42 @@
+/*
+* EME Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__
+#define BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Encoding Method for Encryption
+*/
+class BOTAN_DLL EME
+ {
+ public:
+ virtual u32bit maximum_input_size(u32bit) const = 0;
+
+ SecureVector<byte> encode(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encode(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decode(const byte[], u32bit, u32bit) const;
+ SecureVector<byte> decode(const MemoryRegion<byte>&, u32bit) const;
+
+ virtual ~EME() {}
+ private:
+ virtual SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const = 0;
+
+ virtual SecureVector<byte> unpad(const byte[], u32bit, u32bit) const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eme1.h b/botan/build/botan/eme1.h
new file mode 100644
index 0000000..4df5c5f
--- /dev/null
+++ b/botan/build/botan/eme1.h
@@ -0,0 +1,45 @@
+/*
+* EME1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EME1_H__
+#define BOTAN_EME1_H__
+
+#include <botan/eme.h>
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EME1
+*/
+class BOTAN_DLL EME1 : public EME
+ {
+ public:
+ u32bit maximum_input_size(u32bit) const;
+
+ /**
+ EME1 constructor. Hash will be deleted by ~EME1 (when mgf is deleted)
+
+ P is an optional label. Normally empty.
+ */
+ EME1(HashFunction* hash, const std::string& P = "");
+
+ ~EME1() { delete mgf; }
+ private:
+ SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> unpad(const byte[], u32bit, u32bit) const;
+
+ const u32bit HASH_LENGTH;
+ SecureVector<byte> Phash;
+ MGF* mgf;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/eme_pkcs.h b/botan/build/botan/eme_pkcs.h
new file mode 100644
index 0000000..1aeedf5
--- /dev/null
+++ b/botan/build/botan/eme_pkcs.h
@@ -0,0 +1,30 @@
+/*
+* EME PKCS#1 v1.5
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EME_PKCS1_H__
+#define BOTAN_EME_PKCS1_H__
+
+#include <botan/eme.h>
+
+namespace Botan {
+
+/*
+* EME_PKCS1v15
+*/
+class BOTAN_DLL EME_PKCS1v15 : public EME
+ {
+ public:
+ u32bit maximum_input_size(u32bit) const;
+ private:
+ SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> unpad(const byte[], u32bit, u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa.h b/botan/build/botan/emsa.h
new file mode 100644
index 0000000..e2491e4
--- /dev/null
+++ b/botan/build/botan/emsa.h
@@ -0,0 +1,36 @@
+/*
+* EMSA Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_EMSA_H__
+#define BOTAN_PUBKEY_EMSA_H__
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Encoding Method for Signatures, Appendix
+*/
+class BOTAN_DLL EMSA
+ {
+ public:
+ virtual void update(const byte[], u32bit) = 0;
+ virtual SecureVector<byte> raw_data() = 0;
+
+ virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>&,
+ u32bit,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw() = 0;
+ virtual ~EMSA() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa1.h b/botan/build/botan/emsa1.h
new file mode 100644
index 0000000..a5dac07
--- /dev/null
+++ b/botan/build/botan/emsa1.h
@@ -0,0 +1,41 @@
+/*
+* EMSA1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA1_H__
+#define BOTAN_EMSA1_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EMSA1
+*/
+class BOTAN_DLL EMSA1 : public EMSA
+ {
+ public:
+ EMSA1(HashFunction* h) : hash(h) {}
+ ~EMSA1() { delete hash; }
+ protected:
+ const HashFunction* hash_ptr() const { return hash; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa1_bsi.h b/botan/build/botan/emsa1_bsi.h
new file mode 100644
index 0000000..ec86d40
--- /dev/null
+++ b/botan/build/botan/emsa1_bsi.h
@@ -0,0 +1,32 @@
+/*
+* EMSA1 BSI Variant
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA1_BSI_H__
+#define BOTAN_EMSA1_BSI_H__
+
+#include <botan/emsa1.h>
+
+namespace Botan {
+
+/**
+EMSA1_BSI is a variant of EMSA1 specified by the BSI. It accepts only
+hash values which are less or equal than the maximum key length. The
+implementation comes from InSiTo
+*/
+class BOTAN_DLL EMSA1_BSI : public EMSA1
+ {
+ public:
+ EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {}
+ private:
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa2.h b/botan/build/botan/emsa2.h
new file mode 100644
index 0000000..76888d1
--- /dev/null
+++ b/botan/build/botan/emsa2.h
@@ -0,0 +1,41 @@
+/*
+* EMSA2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA2_H__
+#define BOTAN_EMSA2_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EMSA2
+*/
+class BOTAN_DLL EMSA2 : public EMSA
+ {
+ public:
+ EMSA2(HashFunction* hash);
+ ~EMSA2() { delete hash; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ SecureVector<byte> empty_hash;
+ HashFunction* hash;
+ byte hash_id;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa3.h b/botan/build/botan/emsa3.h
new file mode 100644
index 0000000..301f214
--- /dev/null
+++ b/botan/build/botan/emsa3.h
@@ -0,0 +1,65 @@
+/*
+* EMSA3 and EMSA3_Raw
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA3_H__
+#define BOTAN_EMSA3_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* EMSA3
+* aka PKCS #1 v1.5 signature padding
+* aka PKCS #1 block type 1
+*/
+class BOTAN_DLL EMSA3 : public EMSA
+ {
+ public:
+ EMSA3(HashFunction*);
+ ~EMSA3();
+
+ void update(const byte[], u32bit);
+
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+ private:
+ HashFunction* hash;
+ SecureVector<byte> hash_id;
+ };
+
+/**
+* EMSA3_Raw which is EMSA3 without a hash or digest id (which
+* according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS
+* mechanism", something I have not confirmed)
+*/
+class BOTAN_DLL EMSA3_Raw : public EMSA
+ {
+ public:
+ void update(const byte[], u32bit);
+
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ private:
+ SecureVector<byte> message;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa4.h b/botan/build/botan/emsa4.h
new file mode 100644
index 0000000..b716178
--- /dev/null
+++ b/botan/build/botan/emsa4.h
@@ -0,0 +1,43 @@
+/*
+* EMSA4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA4_H__
+#define BOTAN_EMSA4_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* EMSA4
+*/
+class BOTAN_DLL EMSA4 : public EMSA
+ {
+ public:
+ EMSA4(HashFunction*);
+ EMSA4(HashFunction*, u32bit);
+
+ ~EMSA4() { delete hash; delete mgf; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ u32bit SALT_SIZE;
+ HashFunction* hash;
+ const MGF* mgf;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/emsa_raw.h b/botan/build/botan/emsa_raw.h
new file mode 100644
index 0000000..1b0ad51
--- /dev/null
+++ b/botan/build/botan/emsa_raw.h
@@ -0,0 +1,34 @@
+/*
+* EMSA-Raw
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA_RAW_H__
+#define BOTAN_EMSA_RAW_H__
+
+#include <botan/emsa.h>
+
+namespace Botan {
+
+/*
+* EMSA-Raw
+*/
+class BOTAN_DLL EMSA_Raw : public EMSA
+ {
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&);
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ SecureVector<byte> message;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/engine.h b/botan/build/botan/engine.h
new file mode 100644
index 0000000..66a159e
--- /dev/null
+++ b/botan/build/botan/engine.h
@@ -0,0 +1,140 @@
+/*
+* Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_H__
+#define BOTAN_ENGINE_H__
+
+#include <botan/scan_name.h>
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/pow_mod.h>
+
+#include <utility>
+#include <map>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+namespace Botan {
+
+class Algorithm_Factory;
+class Keyed_Filter;
+
+/*
+* Engine Base Class
+*/
+class BOTAN_DLL Engine
+ {
+ public:
+ virtual ~Engine() {}
+
+ virtual std::string provider_name() const = 0;
+
+ // Lookup functions
+ virtual BlockCipher*
+ find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual StreamCipher*
+ find_stream_cipher(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual HashFunction*
+ find_hash(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual MessageAuthenticationCode*
+ find_mac(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual Modular_Exponentiator*
+ mod_exp(const BigInt&, Power_Mod::Usage_Hints) const
+ { return 0; }
+
+ virtual Keyed_Filter* get_cipher(const std::string&,
+ Cipher_Dir,
+ Algorithm_Factory&)
+ { return 0; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ virtual NR_Operation* nr_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/entropy_src.h b/botan/build/botan/entropy_src.h
new file mode 100644
index 0000000..a1a53fa
--- /dev/null
+++ b/botan/build/botan/entropy_src.h
@@ -0,0 +1,95 @@
+/**
+* EntropySource
+* (C) 2008-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SOURCE_BASE_H__
+#define BOTAN_ENTROPY_SOURCE_BASE_H__
+
+#include <botan/buf_comp.h>
+#include <string>
+#include <utility>
+
+namespace Botan {
+
+/**
+* Class used to accumulate the poll results of EntropySources
+*/
+class Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator(u32bit goal) :
+ entropy_goal(goal), collected_bits(0) {}
+
+ virtual ~Entropy_Accumulator() {}
+
+ /**
+ @return cached I/O buffer for repeated polls
+ */
+ MemoryRegion<byte>& get_io_buffer(u32bit size)
+ { io_buffer.create(size); return io_buffer; }
+
+ u32bit bits_collected() const
+ { return static_cast<u32bit>(collected_bits); }
+
+ bool polling_goal_achieved() const
+ { return (collected_bits >= entropy_goal); }
+
+ u32bit desired_remaining_bits() const
+ {
+ if(collected_bits >= entropy_goal)
+ return 0;
+ return static_cast<u32bit>(entropy_goal - collected_bits);
+ }
+
+ void add(const void* bytes, u32bit length, double entropy_bits_per_byte)
+ {
+ add_bytes(reinterpret_cast<const byte*>(bytes), length);
+ collected_bits += entropy_bits_per_byte * length;
+ }
+
+ template<typename T>
+ void add(const T& v, double entropy_bits_per_byte)
+ {
+ add(&v, sizeof(T), entropy_bits_per_byte);
+ }
+ private:
+ virtual void add_bytes(const byte bytes[], u32bit length) = 0;
+
+ SecureVector<byte> io_buffer;
+ u32bit entropy_goal;
+ double collected_bits;
+ };
+
+class Entropy_Accumulator_BufferedComputation : public Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator_BufferedComputation(BufferedComputation& sink,
+ u32bit goal) :
+ Entropy_Accumulator(goal), entropy_sink(sink) {}
+
+ private:
+ virtual void add_bytes(const byte bytes[], u32bit length)
+ {
+ entropy_sink.update(bytes, length);
+ }
+
+ BufferedComputation& entropy_sink;
+ };
+
+/**
+* Abstract interface to a source of (hopefully unpredictable) system entropy
+*/
+class BOTAN_DLL EntropySource
+ {
+ public:
+ virtual std::string name() const = 0;
+ virtual void poll(Entropy_Accumulator& accum) = 0;
+ virtual ~EntropySource() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_capi.h b/botan/build/botan/es_capi.h
new file mode 100644
index 0000000..55966d7
--- /dev/null
+++ b/botan/build/botan/es_capi.h
@@ -0,0 +1,33 @@
+/*
+* Win32 CAPI EntropySource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_WIN32_CAPI_H__
+#define BOTAN_ENTROPY_SRC_WIN32_CAPI_H__
+
+#include <botan/entropy_src.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Win32 CAPI Entropy Source
+*/
+class BOTAN_DLL Win32_CAPI_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Win32 CryptoGenRandom"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ Win32_CAPI_EntropySource(const std::string& = "");
+ private:
+ std::vector<u64bit> prov_types;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_dev.h b/botan/build/botan/es_dev.h
new file mode 100644
index 0000000..df9dbe1
--- /dev/null
+++ b/botan/build/botan/es_dev.h
@@ -0,0 +1,53 @@
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_DEVICE_H__
+#define BOTAN_ENTROPY_SRC_DEVICE_H__
+
+#include <botan/entropy_src.h>
+#include <vector>
+#include <string>
+
+namespace Botan {
+
+class BOTAN_DLL Device_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "RNG Device Reader"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ Device_EntropySource(const std::vector<std::string>& fsnames);
+ ~Device_EntropySource();
+ private:
+
+ /**
+ A class handling reading from a Unix character device
+ */
+ class Device_Reader
+ {
+ public:
+ typedef int fd_type;
+
+ // Does not own fd, a transient class
+ Device_Reader(fd_type device_fd) : fd(device_fd) {}
+
+ void close();
+
+ u32bit get(byte out[], u32bit length, u32bit ms_wait_time);
+
+ static fd_type open(const std::string& pathname);
+ private:
+ fd_type fd;
+ };
+
+ std::vector<Device_Reader> devices;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_egd.h b/botan/build/botan/es_egd.h
new file mode 100644
index 0000000..5db6565
--- /dev/null
+++ b/botan/build/botan/es_egd.h
@@ -0,0 +1,49 @@
+/**
+* EGD EntropySource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_EGD_H__
+#define BOTAN_ENTROPY_SRC_EGD_H__
+
+#include <botan/entropy_src.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* EGD Entropy Source
+*/
+class BOTAN_DLL EGD_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "EGD/PRNGD"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ EGD_EntropySource(const std::vector<std::string>&);
+ ~EGD_EntropySource();
+ private:
+ class EGD_Socket
+ {
+ public:
+ EGD_Socket(const std::string& path);
+
+ void close();
+ u32bit read(byte outbuf[], u32bit length);
+ private:
+ static int open_socket(const std::string& path);
+
+ std::string socket_path;
+ int m_fd; // cached fd
+ };
+
+ std::vector<EGD_Socket> sockets;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_ftw.h b/botan/build/botan/es_ftw.h
new file mode 100644
index 0000000..928a7b1
--- /dev/null
+++ b/botan/build/botan/es_ftw.h
@@ -0,0 +1,42 @@
+/*
+* File Tree Walking EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_FTW_H__
+#define BOTAN_ENTROPY_SRC_FTW_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* File Tree Walking Entropy Source
+*/
+class BOTAN_DLL FTW_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Proc Walker"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ FTW_EntropySource(const std::string& root_dir);
+ ~FTW_EntropySource();
+
+ class File_Descriptor_Source
+ {
+ public:
+ virtual int next_fd() = 0;
+ virtual ~File_Descriptor_Source() {}
+ };
+ private:
+
+ std::string path;
+ File_Descriptor_Source* dir;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_unix.h b/botan/build/botan/es_unix.h
new file mode 100644
index 0000000..1f8abb7
--- /dev/null
+++ b/botan/build/botan/es_unix.h
@@ -0,0 +1,39 @@
+/*
+* Unix EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_UNIX_H__
+#define BOTAN_ENTROPY_SRC_UNIX_H__
+
+#include <botan/entropy_src.h>
+#include <botan/unix_cmd.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Unix Entropy Source
+*/
+class BOTAN_DLL Unix_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Unix Entropy Source"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ void add_sources(const Unix_Program[], u32bit);
+ Unix_EntropySource(const std::vector<std::string>& path);
+ private:
+ static void add_default_sources(std::vector<Unix_Program>&);
+ void fast_poll(Entropy_Accumulator& accum);
+
+ const std::vector<std::string> PATH;
+ std::vector<Unix_Program> sources;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/es_win32.h b/botan/build/botan/es_win32.h
new file mode 100644
index 0000000..0aa9054
--- /dev/null
+++ b/botan/build/botan/es_win32.h
@@ -0,0 +1,27 @@
+/**
+* Win32 EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_WIN32_H__
+#define BOTAN_ENTROPY_SRC_WIN32_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Win32 Entropy Source
+*/
+class BOTAN_DLL Win32_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Win32 Statistics"; }
+ void poll(Entropy_Accumulator& accum);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/exceptn.h b/botan/build/botan/exceptn.h
new file mode 100644
index 0000000..a55d842
--- /dev/null
+++ b/botan/build/botan/exceptn.h
@@ -0,0 +1,197 @@
+/*
+* Exceptions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EXCEPTION_H__
+#define BOTAN_EXCEPTION_H__
+
+#include <botan/types.h>
+#include <exception>
+#include <string>
+
+namespace Botan {
+
+/*
+* Exception Base Class
+*/
+class BOTAN_DLL Exception : public std::exception
+ {
+ public:
+ const char* what() const throw() { return msg.c_str(); }
+ Exception(const std::string& m = "Unknown error") { set_msg(m); }
+ virtual ~Exception() throw() {}
+ protected:
+ void set_msg(const std::string& m) { msg = "Botan: " + m; }
+ private:
+ std::string msg;
+ };
+
+/*
+* Invalid_Argument Exception
+*/
+struct BOTAN_DLL Invalid_Argument : public Exception
+ {
+ Invalid_Argument(const std::string& err = "") : Exception(err) {}
+ };
+
+/*
+* Invalid_Key_Length Exception
+*/
+struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
+ {
+ Invalid_Key_Length(const std::string&, u32bit);
+ };
+
+/*
+* Invalid_Block_Size Exception
+*/
+struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
+ {
+ Invalid_Block_Size(const std::string&, const std::string&);
+ };
+
+/*
+* Invalid_IV_Length Exception
+*/
+struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
+ {
+ Invalid_IV_Length(const std::string&, u32bit);
+ };
+
+/*
+* Invalid_State Exception
+*/
+struct BOTAN_DLL Invalid_State : public Exception
+ {
+ Invalid_State(const std::string& err) : Exception(err) {}
+ };
+
+/*
+* PRNG_Unseeded Exception
+*/
+struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
+ {
+ PRNG_Unseeded(const std::string& algo) :
+ Invalid_State("PRNG not seeded: " + algo) {}
+ };
+
+/*
+* Policy_Violation Exception
+*/
+struct BOTAN_DLL Policy_Violation : public Invalid_State
+ {
+ Policy_Violation(const std::string& err) :
+ Invalid_State("Policy violation: " + err) {}
+ };
+
+/*
+* Lookup_Error Exception
+*/
+struct BOTAN_DLL Lookup_Error : public Exception
+ {
+ Lookup_Error(const std::string& err) : Exception(err) {}
+ };
+
+/*
+* Algorithm_Not_Found Exception
+*/
+struct BOTAN_DLL Algorithm_Not_Found : public Exception
+ {
+ Algorithm_Not_Found(const std::string&);
+ };
+
+/*
+* Format_Error Exception
+*/
+struct BOTAN_DLL Format_Error : public Exception
+ {
+ Format_Error(const std::string& err = "") : Exception(err) {}
+ };
+
+/*
+* Invalid_Algorithm_Name Exception
+*/
+struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error
+ {
+ Invalid_Algorithm_Name(const std::string&);
+ };
+
+/*
+* Encoding_Error Exception
+*/
+struct BOTAN_DLL Encoding_Error : public Format_Error
+ {
+ Encoding_Error(const std::string& name) :
+ Format_Error("Encoding error: " + name) {}
+ };
+
+/*
+* Decoding_Error Exception
+*/
+struct BOTAN_DLL Decoding_Error : public Format_Error
+ {
+ Decoding_Error(const std::string& name) :
+ Format_Error("Decoding error: " + name) {}
+ };
+
+/*
+* Invalid_OID Exception
+*/
+struct BOTAN_DLL Invalid_OID : public Decoding_Error
+ {
+ Invalid_OID(const std::string& oid) :
+ Decoding_Error("Invalid ASN.1 OID: " + oid) {}
+ };
+
+/*
+* Stream_IO_Error Exception
+*/
+struct BOTAN_DLL Stream_IO_Error : public Exception
+ {
+ Stream_IO_Error(const std::string& err) :
+ Exception("I/O error: " + err) {}
+ };
+
+/*
+* Configuration Error Exception
+*/
+struct BOTAN_DLL Config_Error : public Format_Error
+ {
+ Config_Error(const std::string& err) :
+ Format_Error("Config error: " + err) {}
+ Config_Error(const std::string&, u32bit);
+ };
+
+/*
+* Integrity Failure Exception
+*/
+struct BOTAN_DLL Integrity_Failure : public Exception
+ {
+ Integrity_Failure(const std::string& err) :
+ Exception("Integrity failure: " + err) {}
+ };
+
+/*
+* Internal_Error Exception
+*/
+struct BOTAN_DLL Internal_Error : public Exception
+ {
+ Internal_Error(const std::string& err) :
+ Exception("Internal error: " + err) {}
+ };
+
+/*
+* Self Test Failure Exception
+*/
+struct BOTAN_DLL Self_Test_Failure : public Internal_Error
+ {
+ Self_Test_Failure(const std::string& err) :
+ Internal_Error("Self test failed: " + err) {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/fd_unix.h b/botan/build/botan/fd_unix.h
new file mode 100644
index 0000000..0aed009
--- /dev/null
+++ b/botan/build/botan/fd_unix.h
@@ -0,0 +1,23 @@
+/*
+* Pipe I/O for Unix
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_UNIXFD_H__
+#define BOTAN_PIPE_UNIXFD_H__
+
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* Unix I/O Operators for Pipe
+*/
+int operator<<(int, Pipe&);
+int operator>>(int, Pipe&);
+
+}
+
+#endif
diff --git a/botan/build/botan/filter.h b/botan/build/botan/filter.h
new file mode 100644
index 0000000..b13a366
--- /dev/null
+++ b/botan/build/botan/filter.h
@@ -0,0 +1,113 @@
+/*
+* Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTER_H__
+#define BOTAN_FILTER_H__
+
+#include <botan/secmem.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents general abstract filter objects.
+*/
+class BOTAN_DLL Filter
+ {
+ public:
+
+ /**
+ * Write a portion of a message to this filter.
+ * @param input the input as a byte array
+ * @param length the length of the byte array input
+ */
+ virtual void write(const byte input[], u32bit length) = 0;
+
+ /**
+ * Start a new message. Must be closed by end_msg() before another
+ * message can be startet.
+ */
+ virtual void start_msg() {}
+
+ /**
+ * Tell the Filter that the current message shall be ended.
+ */
+ virtual void end_msg() {}
+
+ /**
+ * Check whether this filter is an attachable filter.
+ * @return true if this filter is attachable, false otherwise
+ */
+ virtual bool attachable() { return true; }
+
+ /**
+ * Start a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void new_msg();
+
+ /**
+ * End a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void finish_msg();
+
+ virtual ~Filter() {}
+ protected:
+ void send(const byte[], u32bit);
+ void send(byte input) { send(&input, 1); }
+ void send(const MemoryRegion<byte>& in) { send(in.begin(), in.size()); }
+ Filter();
+ private:
+ Filter(const Filter&) {}
+ Filter& operator=(const Filter&) { return (*this); }
+
+ friend class Pipe;
+ friend class Fanout_Filter;
+
+ u32bit total_ports() const;
+ u32bit current_port() const { return port_num; }
+ void set_port(u32bit);
+
+ u32bit owns() const { return filter_owns; }
+
+ void attach(Filter*);
+ void set_next(Filter*[], u32bit);
+ Filter* get_next() const;
+
+ SecureVector<byte> write_queue;
+ std::vector<Filter*> next;
+ u32bit port_num, filter_owns;
+
+ // true if filter belongs to a pipe --> prohibit filter sharing!
+ bool owned;
+ };
+
+/**
+* This is the abstract Fanout_Filter base class.
+**/
+class BOTAN_DLL Fanout_Filter : public Filter
+ {
+ protected:
+ void incr_owns() { ++filter_owns; }
+
+ void set_port(u32bit n) { Filter::set_port(n); }
+ void set_next(Filter* f[], u32bit n) { Filter::set_next(f, n); }
+ void attach(Filter* f) { Filter::attach(f); }
+ };
+
+/**
+* The type of checking to be performed by decoders:
+* NONE - no checks, IGNORE_WS - perform checks, but ignore
+* whitespaces, FULL_CHECK - perform checks, also complain
+* about white spaces.
+*/
+enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
+
+}
+
+#endif
diff --git a/botan/build/botan/filters.h b/botan/build/botan/filters.h
new file mode 100644
index 0000000..725651f
--- /dev/null
+++ b/botan/build/botan/filters.h
@@ -0,0 +1,189 @@
+/*
+* Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTERS_H__
+#define BOTAN_FILTERS_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+#include <botan/pipe.h>
+#include <botan/basefilt.h>
+#include <botan/data_snk.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_BASE64_CODEC)
+ #include <botan/base64.h>
+#endif
+
+#if defined(BOTAN_HAS_HEX_CODEC)
+ #include <botan/hex.h>
+#endif
+
+namespace Botan {
+
+/**
+* Stream Cipher Filter.
+*/
+class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
+ {
+ public:
+
+ /**
+ * Seek in the stream.
+ * @param position the position to seek ahead
+ */
+ void seek(u32bit position) { cipher->seek(position); }
+
+ /**
+ * Find out whether the cipher underlying this filter supports
+ * resyncing.
+ * @return true if the cipher supports resyncing
+ */
+ bool supports_resync() const { return (cipher->IV_LENGTH != 0); }
+
+ /**
+ * Set the initialization vector for this filter.
+ * @param iv the initialization vector to set
+ */
+ void set_iv(const InitializationVector& iv);
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher_obj a cipher object to use
+ */
+ StreamCipher_Filter(StreamCipher* cipher_obj);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ */
+ StreamCipher_Filter(const std::string& cipher);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ * @param key the key to use inside this filter
+ */
+ StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key);
+
+ ~StreamCipher_Filter() { delete cipher; }
+ private:
+ SecureVector<byte> buffer;
+ StreamCipher* cipher;
+ };
+
+/**
+* Hash Filter.
+*/
+class BOTAN_DLL Hash_Filter : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { hash->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a hash filter.
+ * @param hash_fun the hash function to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(HashFunction* hash_fun, u32bit len = 0) :
+ OUTPUT_LENGTH(len), hash(hash_fun) {}
+
+ /**
+ * Construct a hash filter.
+ * @param request the name of the hash algorithm to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(const std::string& request, u32bit len = 0);
+
+ ~Hash_Filter() { delete hash; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ HashFunction* hash;
+ };
+
+/**
+* MessageAuthenticationCode Filter.
+*/
+class BOTAN_DLL MAC_Filter : public Keyed_Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { mac->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ }
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ const SymmetricKey& key,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ mac->set_key(key);
+ }
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the name of the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, u32bit len = 0);
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the name of the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, const SymmetricKey& key,
+ u32bit len = 0);
+
+ ~MAC_Filter() { delete mac; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ MessageAuthenticationCode* mac;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/fork256.h b/botan/build/botan/fork256.h
new file mode 100644
index 0000000..70d336c
--- /dev/null
+++ b/botan/build/botan/fork256.h
@@ -0,0 +1,35 @@
+/*
+* FORK-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FORK_256_H__
+#define BOTAN_FORK_256_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* FORK-256
+*/
+class BOTAN_DLL FORK_256 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "FORK-256"; }
+ HashFunction* clone() const { return new FORK_256; }
+ FORK_256() : MDx_HashFunction(32, 64, true, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 8> digest;
+ SecureBuffer<u32bit, 16> M;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/freestore.h b/botan/build/botan/freestore.h
new file mode 100644
index 0000000..f95afa8
--- /dev/null
+++ b/botan/build/botan/freestore.h
@@ -0,0 +1,85 @@
+/**
+* (C) 2007 Christoph Ludwig
+* ludwig@fh-worms.de
+**/
+
+#ifndef BOTAN_FREESTORE_H__
+#define BOTAN_FREESTORE_H__
+
+#include <botan/build.h>
+
+#if defined(BOTAN_USE_STD_TR1)
+ #include <tr1/memory>
+#elif defined(BOTAN_USE_BOOST_TR1)
+ #include <boost/tr1/memory.hpp>
+#else
+ #error "Please choose a TR1 implementation in build.h"
+#endif
+
+namespace Botan {
+
+/**
+* This class is intended as an function call parameter type and
+* enables convenient automatic conversions between plain and smart
+* pointer types. It internally stores a SharedPointer which can be
+* accessed.
+*
+* Distributed under the terms of the Botan license
+*/
+template<typename T>
+class BOTAN_DLL SharedPtrConverter
+ {
+ public:
+ typedef std::tr1::shared_ptr<T> SharedPtr;
+
+ /**
+ * Construct a null pointer equivalent object.
+ */
+ SharedPtrConverter() : ptr() {}
+
+ /**
+ * Copy constructor.
+ */
+ SharedPtrConverter(SharedPtrConverter const& other) :
+ ptr(other.ptr) {}
+
+ /**
+ * Construct a converter object from another pointer type.
+ * @param p the pointer which shall be set as the internally stored
+ * pointer value of this converter.
+ */
+ template<typename Ptr>
+ SharedPtrConverter(Ptr p)
+ : ptr(p) {}
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr const& get_ptr() const { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr get_ptr() { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr const& get_shared() const { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr get_shared() { return this->ptr; }
+
+ private:
+ SharedPtr ptr;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/get_pbe.h b/botan/build/botan/get_pbe.h
new file mode 100644
index 0000000..04eda66
--- /dev/null
+++ b/botan/build/botan/get_pbe.h
@@ -0,0 +1,33 @@
+/*
+* PBE Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOOKUP_PBE_H__
+#define BOTAN_LOOKUP_PBE_H__
+
+#include <botan/pbe.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Factory function for PBEs.
+* @param algo_spec the name of the PBE algorithm to retrieve
+* @return a pointer to a PBE with randomly created parameters
+*/
+BOTAN_DLL PBE* get_pbe(const std::string&);
+
+/**
+* Factory function for PBEs.
+* @param pbe_oid the oid of the desired PBE
+* @param params a DataSource providing the DER encoded parameters to use
+* @return a pointer to the PBE with the specified parameters
+*/
+BOTAN_DLL PBE* get_pbe(const OID&, DataSource&);
+
+}
+
+#endif
diff --git a/botan/build/botan/gfp_element.h b/botan/build/botan/gfp_element.h
new file mode 100644
index 0000000..4e0ee98
--- /dev/null
+++ b/botan/build/botan/gfp_element.h
@@ -0,0 +1,311 @@
+/******
+ * Arithmetic for prime fields GF(p) (header file)
+ *
+ * (C) 2007 Martin Doering
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_ELEMENT_H__
+#define BOTAN_GFP_ELEMENT_H__
+
+#include <botan/bigint.h>
+#include <botan/gfp_modulus.h>
+#include <iosfwd>
+
+#if defined(BOTAN_USE_STD_TR1)
+ #include <tr1/memory>
+#elif defined(BOTAN_USE_BOOST_TR1)
+ #include <boost/tr1/memory.hpp>
+#else
+ #error "Please choose a TR1 implementation in build.h"
+#endif
+
+namespace Botan {
+
+struct Illegal_Transformation : public Exception
+ {
+ Illegal_Transformation(const std::string& err =
+ "Requested transformation is not possible")
+ : Exception(err) {}
+ };
+
+/**
+ * This class represents one element in GF(p). Enables the convenient,
+ * transparent use of the montgomery multiplication.
+ */
+class BOTAN_DLL GFpElement
+ {
+ private:
+ std::tr1::shared_ptr<GFpModulus> mp_mod;
+ mutable BigInt m_value; // ordinary residue or m-residue respectively
+ mutable BigInt workspace;
+
+ // *****************************************
+ // data members for montgomery multiplication
+ mutable bool m_use_montgm;
+ //mutable BigInt m_mres;
+ // this bool tells use whether the m_mres carries
+ // the actual value (in this case mValue doesn´t)
+ mutable bool m_is_trf;
+
+ void ensure_montgm_precomp() const;
+ void trf_to_mres() const;
+ void trf_to_ordres() const;
+
+ public:
+
+ /** construct an element of GF(p) with the given value.
+ * use_montg defaults to false and determines wether Montgomery
+ * multiplications will be use when applying operators *, *=
+ * @param p the prime number of the field
+ * @param value the element value
+ * @param use_montgm whether this object will use Montgomery multiplication
+ */
+ explicit GFpElement (const BigInt& p, const BigInt& value, bool use_montgm = false);
+
+
+ /** construct an element of GF(p) with the given value (defaults
+ * to 0). use_montg defaults to false and determines wether
+ * montgomery multiplications will be use when applying operators
+ * '*' , '*='. Use this constructor for efficient use of
+ * Montgomery multiplication in a context with a fixed a modulus.
+ * Warning: do not use this function unless you know in detail
+ * about the implications of using the shared GFpModulus objects!
+ * @param mod shared pointer to the GFpModulus to be shared
+ * @param value the element value
+ * @param use_montgm whether this object will use Montgomery multiplication
+ */
+ explicit GFpElement(std::tr1::shared_ptr<GFpModulus> const mod,
+ const BigInt& value, bool use_mongm = false);
+
+ /**
+ * Copy constructor
+ * @param other The element to clone
+ */
+ GFpElement(const GFpElement& other);
+
+ /**
+ * Assignment operator.
+ * makes *this a totally independent object
+ * (gives *this independent modulus specific values).
+
+ * @param other The element to assign to our object
+ */
+ const GFpElement& operator=(const GFpElement& other);
+
+ /**
+ * Works like the assignment operator, but lets
+ * *this share the modulus dependend value with other.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @param other The element to assign to our object
+ */
+ void share_assign(const GFpElement& other);
+
+ /**
+ * Switch Montgomery multiplcation optimizations ON
+ */
+ void turn_on_sp_red_mul() const;
+
+ /**
+ * Switch Montgomery multiplcation optimizations OFF
+ */
+ void turn_off_sp_red_mul() const;
+
+ /**
+ * += Operator
+ * @param rhs the GFpElement to add to the local value
+ * @result *this
+ */
+ GFpElement& operator+=(const GFpElement& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the GFpElement to subtract from the local value
+ * @result *this
+ */
+ GFpElement& operator-=(const GFpElement& rhs);
+
+ /**
+ * *= Operator
+ * @param rhs the GFpElement to multiply with the local value
+ * @result *this
+ */
+ GFpElement& operator*=(const GFpElement& rhs);
+ /**
+ * /= Operator
+ * @param rhs the GFpElement to divide the local value by
+ * @result *this
+ */
+ GFpElement& operator/=(const GFpElement& rhs);
+
+ /**
+ * *= Operator
+ * @param rhs the value to multiply with the local value
+ * @result *this
+ */
+ GFpElement& operator*= (u32bit rhs);
+
+ /**
+ * Negate internal value(*this *= -1 )
+ * @return *this
+ */
+ GFpElement& negate();
+
+ /**
+ * Assigns the inverse of *this to *this, i.e.
+ * *this = (*this)^(-1)
+ * @result *this
+ */
+ GFpElement& inverse_in_place();
+
+ /**
+ * checks whether the value is zero (without provoking
+ * a backtransformation to the ordinary-residue)
+ * @result true, if the value is zero, false otherwise.
+ */
+ bool is_zero();
+
+ /**
+ * return prime number of GF(p)
+ * @result a prime number
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Return the represented value in GF(p)
+ * @result The value in GF(p)
+ */
+ const BigInt& get_value() const;
+
+ /**
+ * Returns the shared pointer to the GFpModulus of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @result the shared pointer to the GFpModulus of *this
+ */
+ inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
+ {
+ return mp_mod;
+ }
+
+
+ /**
+ * Sets the shared pointer to the GFpModulus of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @param mod a shared pointer to a GFpModulus that will be held in *this
+ */
+ void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> const mod);
+
+ /**
+ * Tells whether this GFpElement is currently transformed to it´ m-residue,
+ * i.e. in the form x_bar = x * r mod m.
+ * @result true if it is currently transformed to it´s m-residue.
+ */
+ bool is_trf_to_mres() const;
+
+ /**
+ * Transforms this to x_bar = x * r mod m
+ * @result return the value x_bar.
+ */
+ const BigInt& get_mres() const;
+
+ /**
+ * Check, if montgomery multiplication is used.
+ * @result true, if montgomery multiplication is used, false otherwise
+ */
+ bool is_use_montgm() const
+ {
+ return m_use_montgm;
+ }
+
+ /**
+ * Transforms the arguments in such way that either both
+ * are in m-residue representation (returns true) or both are
+ * in ordinary residue representation (returns false).
+ * m-residue is prefered in case of ambiguity.
+ * does not toggle m_use_montgm of the arguments.
+ * Don´t be confused about the constness of the arguments:
+ * the transformation between normal residue and m-residue is
+ * considered as leaving the object const.
+ * @param lhs the first operand to be aligned
+ * @param rhs the second operand to be aligned
+ * @result true if both are transformed to their m-residue,
+ * false it both are transformed to their normal residue.
+ */
+ static bool align_operands_res(const GFpElement& lhs, const GFpElement& rhs);
+
+ //friend declarations for non-member functions
+
+ /**
+ * write a GFpElement to an output stream.
+ * @param output the output stream to write to
+ * @param elem the object to write
+ * @result the output stream
+ */
+ friend std::ostream& operator<<(std::ostream& output, const GFpElement& elem);
+
+ friend class Point_Coords_GFp;
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other The value to swap with
+ */
+ void swap(GFpElement& other);
+
+ };
+
+// relational operators
+bool operator==(const GFpElement& lhs, const GFpElement& rhs);
+inline bool operator!=(const GFpElement& lhs, const GFpElement& rhs )
+ {
+ return !operator==(lhs, rhs);
+ }
+
+// arithmetic operators
+GFpElement operator+(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator-(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator-(const GFpElement& lhs);
+
+GFpElement operator*(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator/(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator* (const GFpElement& lhs, u32bit rhs);
+GFpElement operator* (u32bit rhs, const GFpElement& lhs);
+
+// io operators
+std::ostream& operator<<(std::ostream& output, const GFpElement& elem);
+
+// return (*this)^(-1)
+GFpElement inverse(const GFpElement& elem);
+
+// encoding and decoding
+SecureVector<byte> FE2OSP(const GFpElement& elem);
+GFpElement OS2FEP(MemoryRegion<byte> const& os, BigInt p);
+
+inline void swap(GFpElement& x, GFpElement& y)
+ {
+ x.swap(y);
+ }
+
+}
+
+namespace std {
+
+template<> inline
+void swap<Botan::GFpElement>(Botan::GFpElement& x,
+ Botan::GFpElement& y)
+ {
+ x.swap(y);
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/gfp_modulus.h b/botan/build/botan/gfp_modulus.h
new file mode 100644
index 0000000..b5c0857
--- /dev/null
+++ b/botan/build/botan/gfp_modulus.h
@@ -0,0 +1,127 @@
+/******
+ * Modulus and related data for a specific
+ * implementation of GF(p) (header file)
+ *
+ * (C) 2008 Martin Döring
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_MODULUS_H__
+#define BOTAN_GFP_MODULUS_H__
+
+#include <botan/bigint.h>
+
+namespace Botan
+{
+
+class BOTAN_DLL GFpElement;
+/**
+* This class represents a GFpElement modulus including the modulus related
+* values necessary for the montgomery multiplication.
+*
+* Distributed under the terms of the Botan license
+*/
+class BOTAN_DLL GFpModulus
+ {
+ friend class GFpElement;
+ private:
+ BigInt m_p; // the modulus itself
+ mutable BigInt m_p_dash;
+ mutable BigInt m_r;
+ mutable BigInt m_r_inv;
+ public:
+
+ /**
+ * Construct a GF(P)-Modulus from a BigInt
+ */
+ GFpModulus(BigInt p)
+ : m_p(p),
+ m_p_dash(),
+ m_r(),
+ m_r_inv()
+ {}
+
+ /**
+ * Tells whether the precomputations necessary for the use of the
+ * montgomery multiplication have yet been established.
+ * @result true if the precomputated value are already available.
+ */
+ inline bool has_precomputations() const
+ {
+ return(!m_p_dash.is_zero() && !m_r.is_zero() && !m_r_inv.is_zero());
+ }
+
+ /**
+ * Swaps this with another GFpModulus, does not throw.
+ * @param other the GFpModulus to swap *this with.
+ */
+ inline void swap(GFpModulus& other)
+ {
+ m_p.swap(other.m_p);
+ m_p_dash.swap(other.m_p_dash);
+ m_r.swap(other.m_r);
+ m_r_inv.swap(other.m_r_inv);
+ }
+
+ /**
+ * Tells whether the modulus of *this is equal to the argument.
+ * @param mod the modulus to compare this with
+ * @result true if the modulus of *this and the argument are equal.
+ */
+ inline bool p_equal_to(const BigInt& mod) const
+ {
+ return (m_p == mod);
+ }
+
+ /**
+ * Return the modulus of this GFpModulus.
+ * @result the modulus of *this.
+ */
+ inline const BigInt& get_p() const
+ {
+ return m_p;
+ }
+
+ /**
+ * returns the montgomery multiplication related value r.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result r
+ */
+ inline const BigInt& get_r() const
+ {
+ return m_r;
+ }
+
+ /**
+ * returns the montgomery multiplication related value r^{-1}.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result r^{-1}
+ */
+ inline const BigInt& get_r_inv() const
+ {
+ return m_r_inv;
+ }
+
+ /**
+ * returns the montgomery multiplication related value p'.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result p'
+ */
+ inline const BigInt& get_p_dash() const
+ {
+ return m_p_dash;
+ }
+ // default cp-ctor, op= are fine
+ };
+
+}
+
+#endif
+
diff --git a/botan/build/botan/gost_28147.h b/botan/build/botan/gost_28147.h
new file mode 100644
index 0000000..96d24c6
--- /dev/null
+++ b/botan/build/botan/gost_28147.h
@@ -0,0 +1,67 @@
+/*
+* GOST 28147-89
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GOST_28147_89_H__
+#define BOTAN_GOST_28147_89_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+class GOST_28147_89_Params;
+
+/**
+* The GOST 28147-89 block cipher uses a set of 4 bit Sboxes, however
+* the standard does not actually define these Sboxes; they are
+* considered a local configuration issue. Several different sets are
+* used.
+*/
+class GOST_28147_89_Params
+ {
+ public:
+ byte sbox_entry(u32bit row, u32bit col) const;
+
+ std::string param_name() const { return name; }
+
+ /**
+ * Default GOST parameters are the ones given in GOST R 34.11 for
+ * testing purposes; these sboxes are also used by Crypto++, and,
+ * at least according to Wikipedia, the Central Bank of Russian Federation
+ */
+ GOST_28147_89_Params(const std::string& name = "R3411_94_TestParam");
+ private:
+ const byte* sboxes;
+ std::string name;
+ };
+
+/**
+* GOST 28147-89
+*/
+class BOTAN_DLL GOST_28147_89 : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+
+ std::string name() const { return "GOST-28147-89"; }
+ BlockCipher* clone() const { return new GOST_28147_89(SBOX); }
+
+ GOST_28147_89(const GOST_28147_89_Params& params);
+ private:
+ GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) :
+ BlockCipher(8, 32), SBOX(other_SBOX) {}
+
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 1024> SBOX;
+ SecureBuffer<u32bit, 8> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/gost_3411.h b/botan/build/botan/gost_3411.h
new file mode 100644
index 0000000..c695550
--- /dev/null
+++ b/botan/build/botan/gost_3411.h
@@ -0,0 +1,41 @@
+/**
+* GOST 34.11
+* (C) 2009 Jack Lloyd
+*/
+
+#ifndef BOTAN_GOST_3411_H__
+#define BOTAN_GOST_3411_H__
+
+#include <botan/hash.h>
+#include <botan/gost_28147.h>
+
+namespace Botan {
+
+/**
+* GOST 34.11
+*/
+class BOTAN_DLL GOST_34_11 : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "GOST-R-34.11-94" ; }
+ HashFunction* clone() const { return new GOST_34_11; }
+
+ GOST_34_11();
+ protected:
+ void compress_n(const byte input[], u32bit blocks);
+
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+
+ GOST_28147_89 cipher;
+ SecureBuffer<byte, 32> buffer;
+ SecureBuffer<byte, 32> sum;
+ SecureBuffer<byte, 32> hash;
+ u64bit count;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/has160.h b/botan/build/botan/has160.h
new file mode 100644
index 0000000..44bb63b
--- /dev/null
+++ b/botan/build/botan/has160.h
@@ -0,0 +1,35 @@
+/*
+* HAS-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HAS_160_H__
+#define BOTAN_HAS_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* HAS-160
+*/
+class BOTAN_DLL HAS_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "HAS-160"; }
+ HashFunction* clone() const { return new HAS_160; }
+ HAS_160() : MDx_HashFunction(20, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 20> X;
+ SecureBuffer<u32bit, 5> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/hash.h b/botan/build/botan/hash.h
new file mode 100644
index 0000000..a30234b
--- /dev/null
+++ b/botan/build/botan/hash.h
@@ -0,0 +1,52 @@
+/**
+* Hash Function Base Class
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HASH_FUNCTION_BASE_CLASS_H__
+#define BOTAN_HASH_FUNCTION_BASE_CLASS_H__
+
+#include <botan/buf_comp.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents hash function (message digest) objects.
+*/
+class BOTAN_DLL HashFunction : public BufferedComputation
+ {
+ public:
+ /**
+ * The hash block size as defined for this algorithm.
+ */
+ const u32bit HASH_BLOCK_SIZE;
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual HashFunction* clone() const = 0;
+
+ /**
+ * Get the name of this algorithm.
+ * @return the name of this algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Reset the internal state of this object.
+ */
+ virtual void clear() throw() = 0;
+
+ HashFunction(u32bit hash_len, u32bit block_len = 0) :
+ BufferedComputation(hash_len), HASH_BLOCK_SIZE(block_len) {}
+ virtual ~HashFunction() {}
+ private:
+ HashFunction& operator=(const HashFunction&);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/hash_id.h b/botan/build/botan/hash_id.h
new file mode 100644
index 0000000..847d910
--- /dev/null
+++ b/botan/build/botan/hash_id.h
@@ -0,0 +1,24 @@
+/*
+* Hash Function Identification
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HASHID_H__
+#define BOTAN_HASHID_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Return the values of various defined HashIDs
+*/
+BOTAN_DLL MemoryVector<byte> pkcs_hash_id(const std::string&);
+BOTAN_DLL byte ieee1363_hash_id(const std::string&);
+
+}
+
+#endif
diff --git a/botan/build/botan/hex.h b/botan/build/botan/hex.h
new file mode 100644
index 0000000..035bf4e
--- /dev/null
+++ b/botan/build/botan/hex.h
@@ -0,0 +1,90 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HEX_H__
+#define BOTAN_HEX_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a hex encoder. It encodes byte arrays to hex strings.
+*/
+class BOTAN_DLL Hex_Encoder : public Filter
+ {
+ public:
+ /**
+ * Whether to use uppercase or lowercase letters for the encoded string.
+ */
+ enum Case { Uppercase, Lowercase };
+
+ /**
+ Encode a single byte into two hex characters
+ */
+ static void encode(byte in, byte out[2], Case the_case = Uppercase);
+
+ void write(const byte in[], u32bit length);
+ void end_msg();
+
+ /**
+ * Create a hex encoder.
+ * @param the_case the case to use in the encoded strings.
+ */
+ Hex_Encoder(Case the_case);
+
+ /**
+ * Create a hex encoder.
+ * @param newlines should newlines be used
+ * @param line_length if newlines are used, how long are lines
+ * @param the_case the case to use in the encoded strings
+ */
+ Hex_Encoder(bool newlines = false,
+ u32bit line_length = 72,
+ Case the_case = Uppercase);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ static const byte BIN_TO_HEX_UPPER[16];
+ static const byte BIN_TO_HEX_LOWER[16];
+
+ const Case casing;
+ const u32bit line_length;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This class represents a hex decoder. It converts hex strings to byte arrays.
+*/
+class BOTAN_DLL Hex_Decoder : public Filter
+ {
+ public:
+ static byte decode(const byte[2]);
+ static bool is_valid(byte);
+
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ /**
+ * Construct a Hex Decoder using the specified
+ * character checking.
+ * @param checking the checking to use during decoding.
+ */
+ Hex_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte HEX_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/hmac.h b/botan/build/botan/hmac.h
new file mode 100644
index 0000000..932af71
--- /dev/null
+++ b/botan/build/botan/hmac.h
@@ -0,0 +1,38 @@
+/*
+* HMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_H__
+#define BOTAN_HMAC_H__
+
+#include <botan/mac.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* HMAC
+*/
+class BOTAN_DLL HMAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ HMAC(HashFunction* hash);
+ ~HMAC() { delete hash; }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+ HashFunction* hash;
+ SecureVector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/hmac_rng.h b/botan/build/botan/hmac_rng.h
new file mode 100644
index 0000000..318e2a9
--- /dev/null
+++ b/botan/build/botan/hmac_rng.h
@@ -0,0 +1,59 @@
+/*
+* HMAC RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_RNG_H__
+#define BOTAN_HMAC_RNG_H__
+
+#include <botan/mac.h>
+#include <botan/rng.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+HMAC_RNG - based on the design described in "On Extract-then-Expand
+Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk
+(henceforce, 'E-t-E')
+
+However it actually can be parameterized with any two MAC functions,
+not restricted to HMAC (this variation is also described in Krawczyk's
+paper), for instance one could use HMAC(SHA-512) as the extractor
+and CMAC(AES-256) as the PRF.
+*/
+class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte buf[], u32bit len);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte[], u32bit);
+
+ HMAC_RNG(MessageAuthenticationCode* extractor,
+ MessageAuthenticationCode* prf);
+
+ ~HMAC_RNG();
+ private:
+ void reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit length);
+
+ MessageAuthenticationCode* extractor;
+ MessageAuthenticationCode* prf;
+
+ std::vector<EntropySource*> entropy_sources;
+ bool seeded;
+
+ SecureVector<byte> K, io_buffer;
+ u32bit counter, source_index;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/idea.h b/botan/build/botan/idea.h
new file mode 100644
index 0000000..2c53cd0
--- /dev/null
+++ b/botan/build/botan/idea.h
@@ -0,0 +1,34 @@
+/*
+* IDEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IDEA_H__
+#define BOTAN_IDEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* IDEA
+*/
+class BOTAN_DLL IDEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); DK.clear(); }
+ std::string name() const { return "IDEA"; }
+ BlockCipher* clone() const { return new IDEA; }
+ IDEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u16bit, 52> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/if_algo.h b/botan/build/botan/if_algo.h
new file mode 100644
index 0000000..32a29be
--- /dev/null
+++ b/botan/build/botan/if_algo.h
@@ -0,0 +1,85 @@
+/*
+* IF Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_ALGO_H__
+#define BOTAN_IF_ALGO_H__
+
+#include <botan/if_core.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get n = p * q.
+ * @return n
+ */
+ const BigInt& get_n() const { return n; }
+
+ /**
+ * Get the public exponent used by the key.
+ * @return the public exponent
+ */
+ const BigInt& get_e() const { return e; }
+
+ u32bit max_input_bits() const { return (n.bits() - 1); }
+
+ X509_Encoder* x509_encoder() const;
+ X509_Decoder* x509_decoder();
+ protected:
+ virtual void X509_load_hook();
+ BigInt n, e;
+ IF_Core core;
+ };
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the first prime p.
+ * @return the prime p
+ */
+ const BigInt& get_p() const { return p; }
+
+ /**
+ * Get the second prime q.
+ * @return the prime q
+ */
+ const BigInt& get_q() const { return q; }
+
+ /**
+ * Get d with exp * d = 1 mod (p - 1, q - 1).
+ * @return d
+ */
+ const BigInt& get_d() const { return d; }
+
+ PKCS8_Encoder* pkcs8_encoder() const;
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+ protected:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ BigInt d, p, q, d1, d2, c;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/if_core.h b/botan/build/botan/if_core.h
new file mode 100644
index 0000000..b7f4877
--- /dev/null
+++ b/botan/build/botan/if_core.h
@@ -0,0 +1,45 @@
+/*
+* IF Algorithm Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_CORE_H__
+#define BOTAN_IF_CORE_H__
+
+#include <botan/if_op.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/*
+* IF Core
+*/
+class BOTAN_DLL IF_Core
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Core& operator=(const IF_Core&);
+
+ IF_Core() { op = 0; }
+ IF_Core(const IF_Core&);
+
+ IF_Core(const BigInt&, const BigInt&);
+
+ IF_Core(RandomNumberGenerator& rng,
+ const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&);
+
+ ~IF_Core() { delete op; }
+ private:
+ IF_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/if_op.h b/botan/build/botan/if_op.h
new file mode 100644
index 0000000..516902f
--- /dev/null
+++ b/botan/build/botan/if_op.h
@@ -0,0 +1,52 @@
+/*
+* IF Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_OP_H__
+#define BOTAN_IF_OP_H__
+
+#include <botan/bigint.h>
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/*
+* IF Operation
+*/
+class BOTAN_DLL IF_Operation
+ {
+ public:
+ virtual BigInt public_op(const BigInt&) const = 0;
+ virtual BigInt private_op(const BigInt&) const = 0;
+ virtual IF_Operation* clone() const = 0;
+ virtual ~IF_Operation() {}
+ };
+
+/*
+* Default IF Operation
+*/
+class BOTAN_DLL Default_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt& i) const
+ { return powermod_e_n(i); }
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new Default_IF_Op(*this); }
+
+ Default_IF_Op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+ private:
+ Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
+ Modular_Reducer reducer;
+ BigInt c, q;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/init.h b/botan/build/botan/init.h
new file mode 100644
index 0000000..254f945
--- /dev/null
+++ b/botan/build/botan/init.h
@@ -0,0 +1,41 @@
+/**
+* Library Initialization
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LIBRARY_INITIALIZER_H__
+#define BOTAN_LIBRARY_INITIALIZER_H__
+
+#include <botan/build.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents the Library Initialization/Shutdown Object. It
+* has to exceed the lifetime of any Botan object used in an
+* application. You can call initialize/deinitialize or use
+* LibraryInitializer in the RAII style.
+*/
+class BOTAN_DLL LibraryInitializer
+ {
+ public:
+ static void initialize(const std::string& options = "");
+
+ static void deinitialize();
+
+ /**
+ * Initialize the library
+ * @param thread_safe if the library should use a thread-safe mutex
+ */
+ LibraryInitializer(const std::string& options = "")
+ { LibraryInitializer::initialize(options); }
+
+ ~LibraryInitializer() { LibraryInitializer::deinitialize(); }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/kasumi.h b/botan/build/botan/kasumi.h
new file mode 100644
index 0000000..df49fa9
--- /dev/null
+++ b/botan/build/botan/kasumi.h
@@ -0,0 +1,36 @@
+/*
+* KASUMI
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KASUMI_H__
+#define BOTAN_KASUMI_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* KASUMI
+*/
+class BOTAN_DLL KASUMI : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "KASUMI"; }
+ BlockCipher* clone() const { return new KASUMI; }
+
+ KASUMI() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 64> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/kdf.h b/botan/build/botan/kdf.h
new file mode 100644
index 0000000..70f636b
--- /dev/null
+++ b/botan/build/botan/kdf.h
@@ -0,0 +1,60 @@
+/*
+* KDF/MGF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF_BASE_H__
+#define BOTAN_KDF_BASE_H__
+
+#include <botan/secmem.h>
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Key Derivation Function
+*/
+class BOTAN_DLL KDF
+ {
+ public:
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const std::string& salt = "") const;
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const MemoryRegion<byte>& salt) const;
+
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const byte salt[], u32bit salt_len) const;
+
+ SecureVector<byte> derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const std::string& salt = "") const;
+ SecureVector<byte> derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const;
+
+ virtual ~KDF() {}
+ private:
+ virtual SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ };
+
+/*
+* Mask Generation Function
+*/
+class BOTAN_DLL MGF
+ {
+ public:
+ virtual void mask(const byte in[], u32bit in_len,
+ byte out[], u32bit out_len) const = 0;
+
+ virtual ~MGF() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/kdf1.h b/botan/build/botan/kdf1.h
new file mode 100644
index 0000000..d657ccc
--- /dev/null
+++ b/botan/build/botan/kdf1.h
@@ -0,0 +1,36 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF1_H__
+#define BOTAN_KDF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* KDF1
+*/
+class BOTAN_DLL KDF1 : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit,
+ const byte secret[], u32bit secret_len,
+ const byte P[], u32bit P_len) const;
+
+ KDF1(HashFunction* h) : hash(h) {}
+ KDF1(const KDF1& other) : KDF(), hash(other.hash->clone()) {}
+
+ ~KDF1() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/kdf2.h b/botan/build/botan/kdf2.h
new file mode 100644
index 0000000..f748bed
--- /dev/null
+++ b/botan/build/botan/kdf2.h
@@ -0,0 +1,34 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF2_H__
+#define BOTAN_KDF2_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* KDF2
+*/
+class BOTAN_DLL KDF2 : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ KDF2(HashFunction* h) : hash(h) {}
+ KDF2(const KDF2& other) : KDF(), hash(other.hash->clone()) {}
+ ~KDF2() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/keypair.h b/botan/build/botan/keypair.h
new file mode 100644
index 0000000..b1d5c2d
--- /dev/null
+++ b/botan/build/botan/keypair.h
@@ -0,0 +1,47 @@
+/*
+* Keypair Checks
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KEYPAIR_H__
+#define BOTAN_KEYPAIR_H__
+
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/**
+* Tests whether the specified encryptor and decryptor are related to each other,
+* i.e. whether encrypting with the encryptor and consecutive decryption leads to
+* the original plaintext.
+* @param rng the rng to use
+* @param enc the encryptor to test
+* @param dec the decryptor to test
+* @throw Self_Test_Failure if the arguments are not related to each other
+*/
+BOTAN_DLL void check_key(RandomNumberGenerator& rng,
+ PK_Encryptor* enc,
+ PK_Decryptor* dec);
+
+/**
+* Tests whether the specified signer and verifier are related to each other,
+* i.e. whether a signature created with the signer and can be
+* successfully verified with the verifier.
+* @param rng the rng to use
+* @param sig the signer to test
+* @param ver the verifier to test
+* @throw Self_Test_Failure if the arguments are not related to each other
+*/
+BOTAN_DLL void check_key(RandomNumberGenerator& rng,
+ PK_Signer* sig,
+ PK_Verifier* ver);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/libstate.h b/botan/build/botan/libstate.h
new file mode 100644
index 0000000..2493863
--- /dev/null
+++ b/botan/build/botan/libstate.h
@@ -0,0 +1,125 @@
+/*
+* Library Internal/Global State
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LIB_STATE_H__
+#define BOTAN_LIB_STATE_H__
+
+#include <botan/types.h>
+#include <botan/allocate.h>
+#include <botan/algo_factory.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*
+* Global State Container Base
+*/
+class BOTAN_DLL Library_State
+ {
+ public:
+ Library_State();
+ ~Library_State();
+
+ void initialize(bool thread_safe);
+
+ Algorithm_Factory& algorithm_factory();
+
+ Allocator* get_allocator(const std::string& = "") const;
+ void add_allocator(Allocator*);
+ void set_default_allocator(const std::string&);
+
+ /**
+ * Get a parameter value as std::string.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @result the value of the parameter
+ */
+ std::string get(const std::string& section,
+ const std::string& key) const;
+
+ /**
+ * Check whether a certain parameter is set
+ * or not.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @result true if the parameters value is set,
+ * false otherwise
+ */
+ bool is_set(const std::string& section, const std::string& key) const;
+
+ /**
+ * Set a configuration parameter.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @param overwrite if set to true, the parameters value
+ * will be overwritten even if it is already set, otherwise
+ * no existing values will be overwritten.
+ */
+ void set(const std::string& section, const std::string& key,
+ const std::string& value, bool overwrite = true);
+
+ /**
+ * Get a parameters value out of the "conf" section (
+ * referred to as option).
+ * @param key the desired keys name
+ */
+ std::string option(const std::string& key) const;
+
+ /**
+ * Set an option.
+ * @param key the key of the option to set
+ * @param value the value to set
+ */
+ void set_option(const std::string key, const std::string& value);
+
+ /**
+ * Add a parameter value to the "alias" section.
+ * @param key the name of the parameter which shall have a new alias
+ * @param value the new alias
+ */
+ void add_alias(const std::string&, const std::string&);
+
+ /**
+ * Resolve an alias.
+ * @param alias the alias to resolve.
+ * @return what the alias stands for
+ */
+ std::string deref_alias(const std::string&) const;
+
+ class Mutex* get_mutex() const;
+ private:
+ void load_default_config();
+
+ Library_State(const Library_State&) {}
+ Library_State& operator=(const Library_State&) { return (*this); }
+
+ class Mutex_Factory* mutex_factory;
+
+ std::map<std::string, std::string> config;
+ class Mutex* config_lock;
+
+ class Mutex* allocator_lock;
+ std::map<std::string, Allocator*> alloc_factory;
+ mutable Allocator* cached_default_allocator;
+ std::vector<Allocator*> allocators;
+
+ Algorithm_Factory* m_algorithm_factory;
+ };
+
+/*
+* Global State
+*/
+BOTAN_DLL Library_State& global_state();
+BOTAN_DLL void set_global_state(Library_State*);
+BOTAN_DLL Library_State* swap_global_state(Library_State*);
+
+}
+
+#endif
diff --git a/botan/build/botan/lion.h b/botan/build/botan/lion.h
new file mode 100644
index 0000000..5bc4e72
--- /dev/null
+++ b/botan/build/botan/lion.h
@@ -0,0 +1,43 @@
+/*
+* Lion
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LION_H__
+#define BOTAN_LION_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Lion
+*/
+class BOTAN_DLL Lion : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ BlockCipher* clone() const;
+
+ Lion(HashFunction*, StreamCipher*, u32bit);
+ ~Lion() { delete hash; delete cipher; }
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ const u32bit LEFT_SIZE, RIGHT_SIZE;
+
+ HashFunction* hash;
+ StreamCipher* cipher;
+ SecureVector<byte> key1, key2;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/loadstor.h b/botan/build/botan/loadstor.h
new file mode 100644
index 0000000..77ed155
--- /dev/null
+++ b/botan/build/botan/loadstor.h
@@ -0,0 +1,281 @@
+/*
+* Load/Store Operators
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOAD_STORE_H__
+#define BOTAN_LOAD_STORE_H__
+
+#include <botan/types.h>
+#include <botan/bswap.h>
+#include <botan/rotate.h>
+
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+
+#define BOTAN_ENDIAN_N2B(x) (x)
+#define BOTAN_ENDIAN_B2N(x) (x)
+
+#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
+
+#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+
+#define BOTAN_ENDIAN_N2L(x) (x)
+#define BOTAN_ENDIAN_L2N(x) (x)
+
+#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
+
+#endif
+
+#endif
+
+namespace Botan {
+
+/*
+* Byte Extraction Function
+*/
+template<typename T> inline byte get_byte(u32bit byte_num, T input)
+ {
+ return (input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3));
+ }
+
+/*
+* Byte to Word Conversions
+*/
+inline u16bit make_u16bit(byte i0, byte i1)
+ {
+ return ((static_cast<u16bit>(i0) << 8) | i1);
+ }
+
+inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
+ {
+ return ((static_cast<u32bit>(i0) << 24) |
+ (static_cast<u32bit>(i1) << 16) |
+ (static_cast<u32bit>(i2) << 8) |
+ (static_cast<u32bit>(i3)));
+ }
+
+inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
+ byte i4, byte i5, byte i6, byte i7)
+ {
+ return ((static_cast<u64bit>(i0) << 56) |
+ (static_cast<u64bit>(i1) << 48) |
+ (static_cast<u64bit>(i2) << 40) |
+ (static_cast<u64bit>(i3) << 32) |
+ (static_cast<u64bit>(i4) << 24) |
+ (static_cast<u64bit>(i5) << 16) |
+ (static_cast<u64bit>(i6) << 8) |
+ (static_cast<u64bit>(i7)));
+ }
+
+/*
+* Endian-Specific Word Loading Operations
+*/
+template<typename T>
+inline T load_be(const byte in[], u32bit off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(u32bit j = 0; j != sizeof(T); j++)
+ out = (out << 8) | in[j];
+ return out;
+ }
+
+template<typename T>
+inline T load_le(const byte in[], u32bit off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(u32bit j = 0; j != sizeof(T); j++)
+ out = (out << 8) | in[sizeof(T)-1-j];
+ return out;
+ }
+
+template<>
+inline u16bit load_be<u16bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[0], in[1]);
+#endif
+ }
+
+template<>
+inline u16bit load_le<u16bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[1], in[0]);
+#endif
+ }
+
+template<>
+inline u32bit load_be<u32bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[0], in[1], in[2], in[3]);
+#endif
+ }
+
+template<>
+inline u32bit load_le<u32bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+template<>
+inline u64bit load_be<u64bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[0], in[1], in[2], in[3],
+ in[4], in[5], in[6], in[7]);
+#endif
+ }
+
+template<>
+inline u64bit load_le<u64bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[7], in[6], in[5], in[4],
+ in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+/*
+* Endian-Specific Word Storing Operations
+*/
+inline void store_be(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+#endif
+ }
+
+inline void store_le(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(1, in);
+ out[1] = get_byte(0, in);
+#endif
+ }
+
+inline void store_be(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+#endif
+ }
+
+inline void store_le(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(3, in);
+ out[1] = get_byte(2, in);
+ out[2] = get_byte(1, in);
+ out[3] = get_byte(0, in);
+#endif
+ }
+
+inline void store_be(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+ out[4] = get_byte(4, in);
+ out[5] = get_byte(5, in);
+ out[6] = get_byte(6, in);
+ out[7] = get_byte(7, in);
+#endif
+ }
+
+inline void store_le(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(7, in);
+ out[1] = get_byte(6, in);
+ out[2] = get_byte(5, in);
+ out[3] = get_byte(4, in);
+ out[4] = get_byte(3, in);
+ out[5] = get_byte(2, in);
+ out[6] = get_byte(1, in);
+ out[7] = get_byte(0, in);
+#endif
+ }
+
+template<typename T>
+inline void store_le(byte out[], T a, T b)
+ {
+ store_le(a, out + (0 * sizeof(T)));
+ store_le(b, out + (1 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_be(byte out[], T a, T b)
+ {
+ store_be(a, out + (0 * sizeof(T)));
+ store_be(b, out + (1 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_le(byte out[], T a, T b, T c, T d)
+ {
+ store_le(a, out + (0 * sizeof(T)));
+ store_le(b, out + (1 * sizeof(T)));
+ store_le(c, out + (2 * sizeof(T)));
+ store_le(d, out + (3 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_be(byte out[], T a, T b, T c, T d)
+ {
+ store_be(a, out + (0 * sizeof(T)));
+ store_be(b, out + (1 * sizeof(T)));
+ store_be(c, out + (2 * sizeof(T)));
+ store_be(d, out + (3 * sizeof(T)));
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/look_pk.h b/botan/build/botan/look_pk.h
new file mode 100644
index 0000000..27b67dc
--- /dev/null
+++ b/botan/build/botan/look_pk.h
@@ -0,0 +1,78 @@
+/*
+* PK Algorithm Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_LOOKUP_H__
+#define BOTAN_PK_LOOKUP_H__
+
+#include <botan/build.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/**
+* Public key encryptor factory method.
+* @param key the key that will work inside the encryptor
+* @param pad determines the algorithm and encoding
+* @return the public key encryptor object
+*/
+BOTAN_DLL PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key,
+ const std::string& pad);
+
+/**
+* Public key decryptor factory method.
+* @param key the key that will work inside the decryptor
+* @param pad determines the algorithm and encoding
+* @return the public key decryptor object
+*/
+BOTAN_DLL PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key,
+ const std::string& pad);
+
+/**
+* Public key signer factory method.
+* @param key the key that will work inside the signer
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_format the signature format to be used
+* @return the public key signer object
+*/
+BOTAN_DLL PK_Signer* get_pk_signer(const PK_Signing_Key& key,
+ const std::string& pad,
+ Signature_Format = IEEE_1363);
+
+/**
+* Public key verifier factory method.
+* @param key the key that will work inside the verifier
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_format the signature format to be used
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key,
+ const std::string& pad,
+ Signature_Format = IEEE_1363);
+
+/**
+* Public key verifier factory method.
+* @param key the key that will work inside the verifier
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_form the signature format to be used
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key,
+ const std::string& pad,
+ Signature_Format sig_form = IEEE_1363);
+
+/**
+* Public key key agreement factory method.
+* @param key the key that will work inside the key agreement
+* @param pad determines the algorithm, encoding and hash algorithm
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key,
+ const std::string& pad);
+
+}
+
+#endif
diff --git a/botan/build/botan/lookup.h b/botan/build/botan/lookup.h
new file mode 100644
index 0000000..0f48ddd
--- /dev/null
+++ b/botan/build/botan/lookup.h
@@ -0,0 +1,239 @@
+/*
+* Algorithm Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOOKUP_H__
+#define BOTAN_LOOKUP_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/s2k.h>
+
+#include <botan/filters.h>
+#include <botan/mode_pad.h>
+#include <botan/kdf.h>
+#include <botan/eme.h>
+#include <botan/emsa.h>
+
+namespace Botan {
+
+/*
+* Retrieve an object from the lookup table
+*/
+// NOTE: these functions return internally stored objects, library
+// retains ownership
+
+BOTAN_DLL const BlockCipher*
+retrieve_block_cipher(const std::string&);
+
+BOTAN_DLL const StreamCipher*
+retrieve_stream_cipher(const std::string&);
+
+BOTAN_DLL const HashFunction*
+retrieve_hash(const std::string&);
+
+BOTAN_DLL const MessageAuthenticationCode*
+retrieve_mac(const std::string&);
+
+/*
+* Get an algorithm object
+*/
+// NOTE: these functions create and return new objects, letting the
+// caller assume ownership of them
+
+/**
+* Block cipher factory method.
+* @param algo_spec the name of the desired block cipher
+* @return a pointer to the block cipher object
+*/
+BOTAN_DLL BlockCipher* get_block_cipher(const std::string& name);
+
+
+/**
+* Stream cipher factory method.
+* @param algo_spec the name of the desired stream cipher
+* @return a pointer to the stream cipher object
+*/
+BOTAN_DLL StreamCipher* get_stream_cipher(const std::string& name);
+
+/**
+* Hash function factory method.
+* @param algo_spec the name of the desired hash function
+* @return a pointer to the hash function object
+*/
+BOTAN_DLL HashFunction* get_hash(const std::string& name);
+
+/**
+* MAC factory method.
+* @param algo_spec the name of the desired MAC
+* @return a pointer to the MAC object
+*/
+BOTAN_DLL MessageAuthenticationCode* get_mac(const std::string& name);
+
+/**
+* String to key algorithm factory method.
+* @param name the name of the desired string to key (S2K) algorithm
+* @return a pointer to the string to key algorithm object
+*/
+BOTAN_DLL S2K* get_s2k(const std::string& name);
+
+/*
+* Get an EMSA/EME/KDF/MGF function
+*/
+// NOTE: these functions create and return new objects, letting the
+// caller assume ownership of them
+
+/**
+* Factory method for EME (message-encoding methods for encryption) objects
+* @param name the name of the EME to create
+* @return a pointer to the desired EME object
+*/
+BOTAN_DLL EME* get_eme(const std::string& name);
+
+/**
+* Factory method for EMSA (message-encoding methods for signatures
+* with appendix) objects
+* @param name the name of the EME to create
+* @return a pointer to the desired EME object
+*/
+BOTAN_DLL EMSA* get_emsa(const std::string& name);
+
+/**
+* Factory method for KDF (key derivation function)
+* @param name the name of the KDF to create
+* @return a pointer to the desired KDF object
+*/
+BOTAN_DLL KDF* get_kdf(const std::string& name);
+
+/*
+* Get a cipher object
+*/
+
+/**
+* Factory method for general symmetric cipher filters.
+* @param algo_spec the name of the desired cipher
+* @param key the key to be used for encryption/decryption performed by
+* the filter
+* @param iv the initialization vector to be used
+* @param direction determines whether the filter will be an encrypting or decrypting
+* filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir dir);
+/**
+* Factory method for general symmetric cipher filters.
+* @param algo_spec the name of the desired cipher
+* @param key the key to be used for encryption/decryption performed by
+* the filter
+* @param direction determines whether the filter will be an encrypting or decrypting
+* filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
+ const SymmetricKey& key,
+ Cipher_Dir dir);
+
+/** Factory method for general symmetric cipher filters. No key will
+* be set in the filter.
+* @param algo_spec the name of the desired cipher
+
+* @param direction determines whether the filter will be an encrypting or
+* decrypting filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name, Cipher_Dir dir);
+
+/**
+* Check if an algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_algorithm(const std::string& name);
+
+/**
+* Check if a block cipher algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_block_cipher(const std::string& name);
+
+/**
+* Check if a stream cipher algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_stream_cipher(const std::string& name);
+
+/**
+* Check if a hash algorithm exists.
+* @param algo_spec the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_hash(const std::string& name);
+
+/**
+* Check if a MAC algorithm exists.
+* @param algo_spec the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_mac(const std::string& name);
+
+/*
+* Query information about an algorithm
+*/
+
+/**
+* Find out the block size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the block size of the specified algorithm
+*/
+BOTAN_DLL u32bit block_size_of(const std::string& name);
+
+/**
+* Find out the output length of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the output length of the specified algorithm
+*/
+BOTAN_DLL u32bit output_length_of(const std::string& name);
+
+/**
+* Find out the whether a certain key length is allowd for a given
+* symmetric algorithm.
+* @param key_len the key length in question
+* @param name the name of the algorithm
+* @return true if the key length is valid for that algorithm, false otherwise
+*/
+BOTAN_DLL bool valid_keylength_for(u32bit keylen, const std::string& name);
+
+/**
+* Find out the minimum key size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the minimum key length of the specified algorithm
+*/
+BOTAN_DLL u32bit min_keylength_of(const std::string& name);
+
+/**
+* Find out the maximum key size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the maximum key length of the specified algorithm
+*/
+BOTAN_DLL u32bit max_keylength_of(const std::string& name);
+
+/**
+* Find out the size any valid key is a multiple of for a certain algorithm.
+* @param name the name of the algorithm
+* @return the size any valid key is a multiple of
+*/
+BOTAN_DLL u32bit keylength_multiple_of(const std::string& name);
+
+}
+
+#endif
diff --git a/botan/build/botan/lubyrack.h b/botan/build/botan/lubyrack.h
new file mode 100644
index 0000000..ebde313
--- /dev/null
+++ b/botan/build/botan/lubyrack.h
@@ -0,0 +1,38 @@
+/*
+* Luby-Rackoff
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LUBY_RACKOFF_H__
+#define BOTAN_LUBY_RACKOFF_H__
+
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Luby-Rackoff
+*/
+class BOTAN_DLL LubyRackoff : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ BlockCipher* clone() const;
+
+ LubyRackoff(HashFunction* hash);
+ ~LubyRackoff() { delete hash; }
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ HashFunction* hash;
+ SecureVector<byte> K1, K2;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mac.h b/botan/build/botan/mac.h
new file mode 100644
index 0000000..3ec5fff
--- /dev/null
+++ b/botan/build/botan/mac.h
@@ -0,0 +1,60 @@
+/**
+* Base class for message authentiction codes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+#define BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+
+#include <botan/buf_comp.h>
+#include <botan/sym_algo.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents Message Authentication Code (MAC) objects.
+*/
+class BOTAN_DLL MessageAuthenticationCode : public BufferedComputation,
+ public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @param length the length of the byte array
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const byte[], u32bit);
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual MessageAuthenticationCode* clone() const = 0;
+
+ /**
+ * Get the name of this algorithm.
+ * @return the name of this algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Reset the internal state of this object.
+ */
+ virtual void clear() throw() = 0;
+
+ MessageAuthenticationCode(u32bit mac_len,
+ u32bit key_min,
+ u32bit key_max = 0,
+ u32bit key_mod = 1) :
+ BufferedComputation(mac_len),
+ SymmetricAlgorithm(key_min, key_max, key_mod) {}
+
+ virtual ~MessageAuthenticationCode() {}
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mars.h b/botan/build/botan/mars.h
new file mode 100644
index 0000000..ca49695
--- /dev/null
+++ b/botan/build/botan/mars.h
@@ -0,0 +1,38 @@
+/*
+* MARS
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MARS_H__
+#define BOTAN_MARS_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+class BOTAN_DLL MARS : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "MARS"; }
+ BlockCipher* clone() const { return new MARS; }
+ MARS() : BlockCipher(16, 16, 32, 4) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ void encrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const;
+ void decrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const;
+ static void forward_mix(u32bit&, u32bit&, u32bit&, u32bit&);
+ static void reverse_mix(u32bit&, u32bit&, u32bit&, u32bit&);
+
+ static const u32bit SBOX[512];
+ SecureBuffer<u32bit, 40> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/md2.h b/botan/build/botan/md2.h
new file mode 100644
index 0000000..9337c43
--- /dev/null
+++ b/botan/build/botan/md2.h
@@ -0,0 +1,37 @@
+/*
+* MD2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD2_H__
+#define BOTAN_MD2_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* MD2
+*/
+class BOTAN_DLL MD2 : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD2"; }
+ HashFunction* clone() const { return new MD2; }
+ MD2() : HashFunction(16, 16) { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void hash(const byte[]);
+ void final_result(byte[]);
+
+ SecureBuffer<byte, 48> X;
+ SecureBuffer<byte, 16> checksum, buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/md4.h b/botan/build/botan/md4.h
new file mode 100644
index 0000000..df6f229
--- /dev/null
+++ b/botan/build/botan/md4.h
@@ -0,0 +1,36 @@
+/*
+* MD4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD4_H__
+#define BOTAN_MD4_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* MD4
+*/
+class BOTAN_DLL MD4 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD4"; }
+ HashFunction* clone() const { return new MD4; }
+ MD4() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ protected:
+ void compress_n(const byte input[], u32bit blocks);
+ void hash_old(const byte[]);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 48> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/md5.h b/botan/build/botan/md5.h
new file mode 100644
index 0000000..85f684d
--- /dev/null
+++ b/botan/build/botan/md5.h
@@ -0,0 +1,35 @@
+/**
+* MD5
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD5_H__
+#define BOTAN_MD5_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/**
+* MD5
+*/
+class BOTAN_DLL MD5 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD5"; }
+ HashFunction* clone() const { return new MD5; }
+ MD5() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ protected:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mdx_hash.h b/botan/build/botan/mdx_hash.h
new file mode 100644
index 0000000..0c3aa78
--- /dev/null
+++ b/botan/build/botan/mdx_hash.h
@@ -0,0 +1,42 @@
+/**
+* MDx Hash Function
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MDX_BASE_H__
+#define BOTAN_MDX_BASE_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* MDx Hash Function Base Class
+*/
+class BOTAN_DLL MDx_HashFunction : public HashFunction
+ {
+ public:
+ MDx_HashFunction(u32bit, u32bit, bool, bool, u32bit = 8);
+ virtual ~MDx_HashFunction() {}
+ protected:
+ void add_data(const byte[], u32bit);
+ void final_result(byte output[]);
+ virtual void compress_n(const byte block[], u32bit block_n) = 0;
+
+ void clear() throw();
+ virtual void copy_out(byte[]) = 0;
+ virtual void write_count(byte[]);
+ private:
+ SecureVector<byte> buffer;
+ u64bit count;
+ u32bit position;
+
+ const bool BIG_BYTE_ENDIAN, BIG_BIT_ENDIAN;
+ const u32bit COUNT_SIZE;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mem_ops.h b/botan/build/botan/mem_ops.h
new file mode 100644
index 0000000..0fcf34b
--- /dev/null
+++ b/botan/build/botan/mem_ops.h
@@ -0,0 +1,40 @@
+/*
+* Memory Operations
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MEMORY_OPS_H__
+#define BOTAN_MEMORY_OPS_H__
+
+#include <botan/types.h>
+#include <cstring>
+
+namespace Botan {
+
+/*
+* Memory Manipulation Functions
+*/
+template<typename T> inline void copy_mem(T* out, const T* in, u32bit n)
+ { std::memmove(out, in, sizeof(T)*n); }
+
+template<typename T> inline void clear_mem(T* ptr, u32bit n)
+ { if(n) std::memset(ptr, 0, sizeof(T)*n); }
+
+template<typename T> inline void set_mem(T* ptr, u32bit n, byte val)
+ { std::memset(ptr, val, sizeof(T)*n); }
+
+template<typename T> inline bool same_mem(const T* p1, const T* p2, u32bit n)
+ {
+ bool is_same = true;
+
+ for(u32bit i = 0; i != n; ++i)
+ is_same &= (p1[i] == p2[i]);
+
+ return is_same;
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/mem_pool.h b/botan/build/botan/mem_pool.h
new file mode 100644
index 0000000..a578009
--- /dev/null
+++ b/botan/build/botan/mem_pool.h
@@ -0,0 +1,74 @@
+/*
+* Pooling Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POOLING_ALLOCATOR_H__
+#define BOTAN_POOLING_ALLOCATOR_H__
+
+#include <botan/allocate.h>
+#include <botan/exceptn.h>
+#include <botan/mutex.h>
+#include <utility>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Pooling Allocator
+*/
+class BOTAN_DLL Pooling_Allocator : public Allocator
+ {
+ public:
+ void* allocate(u32bit);
+ void deallocate(void*, u32bit);
+
+ void destroy();
+
+ Pooling_Allocator(Mutex*);
+ ~Pooling_Allocator();
+ private:
+ void get_more_core(u32bit);
+ byte* allocate_blocks(u32bit);
+
+ virtual void* alloc_block(u32bit) = 0;
+ virtual void dealloc_block(void*, u32bit) = 0;
+
+ class BOTAN_DLL Memory_Block
+ {
+ public:
+ Memory_Block(void*);
+
+ static u32bit bitmap_size() { return BITMAP_SIZE; }
+ static u32bit block_size() { return BLOCK_SIZE; }
+
+ bool contains(void*, u32bit) const throw();
+ byte* alloc(u32bit) throw();
+ void free(void*, u32bit) throw();
+
+ bool operator<(const Memory_Block& other) const
+ {
+ if(buffer < other.buffer && other.buffer < buffer_end)
+ return false;
+ return (buffer < other.buffer);
+ }
+ private:
+ typedef u64bit bitmap_type;
+ static const u32bit BITMAP_SIZE = 8 * sizeof(bitmap_type);
+ static const u32bit BLOCK_SIZE = 64;
+
+ bitmap_type bitmap;
+ byte* buffer, *buffer_end;
+ };
+
+ std::vector<Memory_Block> blocks;
+ std::vector<Memory_Block>::iterator last_used;
+ std::vector<std::pair<void*, u32bit> > allocated;
+ Mutex* mutex;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mgf1.h b/botan/build/botan/mgf1.h
new file mode 100644
index 0000000..799ba7e
--- /dev/null
+++ b/botan/build/botan/mgf1.h
@@ -0,0 +1,36 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MGF1_H__
+#define BOTAN_MGF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* MGF1 (Mask Generation Function)
+*/
+class BOTAN_DLL MGF1 : public MGF
+ {
+ public:
+ void mask(const byte[], u32bit, byte[], u32bit) const;
+
+ /**
+ MGF1 constructor: takes ownership of hash
+ */
+ MGF1(HashFunction* hash);
+
+ ~MGF1();
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/misty1.h b/botan/build/botan/misty1.h
new file mode 100644
index 0000000..62d4f85
--- /dev/null
+++ b/botan/build/botan/misty1.h
@@ -0,0 +1,35 @@
+/**
+* MISTY1
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MISTY1_H__
+#define BOTAN_MISTY1_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* MISTY1
+*/
+class BOTAN_DLL MISTY1 : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); DK.clear(); }
+ std::string name() const { return "MISTY1"; }
+ BlockCipher* clone() const { return new MISTY1; }
+ MISTY1(u32bit = 8);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 100> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mmap_mem.h b/botan/build/botan/mmap_mem.h
new file mode 100644
index 0000000..bef166a
--- /dev/null
+++ b/botan/build/botan/mmap_mem.h
@@ -0,0 +1,30 @@
+/*
+* Memory Mapping Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MMAP_ALLOCATOR_H__
+#define BOTAN_MMAP_ALLOCATOR_H__
+
+#include <botan/mem_pool.h>
+
+namespace Botan {
+
+/*
+* Memory Mapping Allocator
+*/
+class BOTAN_DLL MemoryMapping_Allocator : public Pooling_Allocator
+ {
+ public:
+ MemoryMapping_Allocator(Mutex* m) : Pooling_Allocator(m) {}
+ std::string type() const { return "mmap"; }
+ private:
+ void* alloc_block(u32bit);
+ void dealloc_block(void*, u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mode_pad.h b/botan/build/botan/mode_pad.h
new file mode 100644
index 0000000..a486d3c
--- /dev/null
+++ b/botan/build/botan/mode_pad.h
@@ -0,0 +1,120 @@
+/**
+* CBC Padding Methods
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_PADDING_H__
+#define BOTAN_CBC_PADDING_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Block Cipher Mode Padding Method
+* This class is pretty limited, it cannot deal well with
+* randomized padding methods, or any padding method that
+* wants to add more than one block. For instance, it should
+* be possible to define cipher text stealing mode as simply
+* a padding mode for CBC, which happens to consume the last
+* two block (and requires use of the block cipher).
+*/
+class BOTAN_DLL BlockCipherModePaddingMethod
+ {
+ public:
+ /**
+ * @param block output buffer
+ * @param size of the block
+ * @param current_position in the last block
+ */
+ virtual void pad(byte block[],
+ u32bit size,
+ u32bit current_position) const = 0;
+
+ /**
+ * @param block the last block
+ * @param size the of the block
+ */
+ virtual u32bit unpad(const byte block[],
+ u32bit size) const = 0;
+
+ /**
+ * @param block_size of the cipher
+ * @param position in the current block
+ * @return number of padding bytes that will be appended
+ */
+ virtual u32bit pad_bytes(u32bit block_size,
+ u32bit position) const;
+
+ /**
+ * @param block_size of the cipher
+ * @return valid block size for this padding mode
+ */
+ virtual bool valid_blocksize(u32bit block_size) const = 0;
+
+ /**
+ * @return name of the mode
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * virtual destructor
+ */
+ virtual ~BlockCipherModePaddingMethod() {}
+ };
+
+/**
+* PKCS#7 Padding
+*/
+class BOTAN_DLL PKCS7_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "PKCS7"; }
+ };
+
+/**
+* ANSI X9.23 Padding
+*/
+class BOTAN_DLL ANSI_X923_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "X9.23"; }
+ };
+
+/**
+* One And Zeros Padding
+*/
+class BOTAN_DLL OneAndZeros_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "OneAndZeros"; }
+ };
+
+/**
+* Null Padding
+*/
+class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const { return; }
+ u32bit unpad(const byte[], u32bit size) const { return size; }
+ u32bit pad_bytes(u32bit, u32bit) const { return 0; }
+ bool valid_blocksize(u32bit) const { return true; }
+ std::string name() const { return "NoPadding"; }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/modebase.h b/botan/build/botan/modebase.h
new file mode 100644
index 0000000..173fde5
--- /dev/null
+++ b/botan/build/botan/modebase.h
@@ -0,0 +1,39 @@
+/*
+* Block Cipher Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MODEBASE_H__
+#define BOTAN_MODEBASE_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* This class represents an abstract block cipher mode
+*/
+class BOTAN_DLL BlockCipherMode : public Keyed_Filter
+ {
+ public:
+ std::string name() const;
+
+ BlockCipherMode(BlockCipher*, const std::string&,
+ u32bit, u32bit = 0, u32bit = 1);
+
+ virtual ~BlockCipherMode() { delete cipher; }
+ protected:
+ void set_iv(const InitializationVector&);
+ const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD;
+ const std::string mode_name;
+ BlockCipher* cipher;
+ SecureVector<byte> buffer, state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mp_asm.h b/botan/build/botan/mp_asm.h
new file mode 100644
index 0000000..7c18343
--- /dev/null
+++ b/botan/build/botan/mp_asm.h
@@ -0,0 +1,54 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS == 8)
+ typedef Botan::u16bit dword;
+#elif (BOTAN_MP_WORD_BITS == 16)
+ typedef Botan::u32bit dword;
+#elif (BOTAN_MP_WORD_BITS == 32)
+ typedef Botan::u64bit dword;
+#elif (BOTAN_MP_WORD_BITS == 64)
+ #error BOTAN_MP_WORD_BITS can be 64 only with assembly support
+#else
+ #error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+ dword z = (dword)a * b + *c;
+ *c = (word)(z >> BOTAN_MP_WORD_BITS);
+ return (word)z;
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+ dword z = (dword)a * b + c + *d;
+ *d = (word)(z >> BOTAN_MP_WORD_BITS);
+ return (word)z;
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/mp_asmi.h b/botan/build/botan/mp_asmi.h
new file mode 100644
index 0000000..21c4db2
--- /dev/null
+++ b/botan/build/botan/mp_asmi.h
@@ -0,0 +1,191 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ x[0] = word_add(x[0], y[0], &carry);
+ x[1] = word_add(x[1], y[1], &carry);
+ x[2] = word_add(x[2], y[2], &carry);
+ x[3] = word_add(x[3], y[3], &carry);
+ x[4] = word_add(x[4], y[4], &carry);
+ x[5] = word_add(x[5], y[5], &carry);
+ x[6] = word_add(x[6], y[6], &carry);
+ x[7] = word_add(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ z[0] = word_add(x[0], y[0], &carry);
+ z[1] = word_add(x[1], y[1], &carry);
+ z[2] = word_add(x[2], y[2], &carry);
+ z[3] = word_add(x[3], y[3], &carry);
+ z[4] = word_add(x[4], y[4], &carry);
+ z[5] = word_add(x[5], y[5], &carry);
+ z[6] = word_add(x[6], y[6], &carry);
+ z[7] = word_add(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+ word t0 = x - y;
+ word c1 = (t0 > x);
+ word z = t0 - *carry;
+ *carry = c1 | (z > t0);
+ return z;
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[4], const word y[4], word carry)
+ {
+ x[0] = word_sub(x[0], y[0], &carry);
+ x[1] = word_sub(x[1], y[1], &carry);
+ x[2] = word_sub(x[2], y[2], &carry);
+ x[3] = word_sub(x[3], y[3], &carry);
+ x[4] = word_sub(x[4], y[4], &carry);
+ x[5] = word_sub(x[5], y[5], &carry);
+ x[6] = word_sub(x[6], y[6], &carry);
+ x[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ z[0] = word_sub(x[0], y[0], &carry);
+ z[1] = word_sub(x[1], y[1], &carry);
+ z[2] = word_sub(x[2], y[2], &carry);
+ z[3] = word_sub(x[3], y[3], &carry);
+ z[4] = word_sub(x[4], y[4], &carry);
+ z[5] = word_sub(x[5], y[5], &carry);
+ z[6] = word_sub(x[6], y[6], &carry);
+ z[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[4], word y, word carry)
+ {
+ x[0] = word_madd2(x[0], y, &carry);
+ x[1] = word_madd2(x[1], y, &carry);
+ x[2] = word_madd2(x[2], y, &carry);
+ x[3] = word_madd2(x[3], y, &carry);
+ x[4] = word_madd2(x[4], y, &carry);
+ x[5] = word_madd2(x[5], y, &carry);
+ x[6] = word_madd2(x[6], y, &carry);
+ x[7] = word_madd2(x[7], y, &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ z[0] = word_madd2(x[0], y, &carry);
+ z[1] = word_madd2(x[1], y, &carry);
+ z[2] = word_madd2(x[2], y, &carry);
+ z[3] = word_madd2(x[3], y, &carry);
+ z[4] = word_madd2(x[4], y, &carry);
+ z[5] = word_madd2(x[5], y, &carry);
+ z[6] = word_madd2(x[6], y, &carry);
+ z[7] = word_madd2(x[7], y, &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ z[0] = word_madd3(x[0], y, z[0], &carry);
+ z[1] = word_madd3(x[1], y, z[1], &carry);
+ z[2] = word_madd3(x[2], y, z[2], &carry);
+ z[3] = word_madd3(x[3], y, z[3], &carry);
+ z[4] = word_madd3(x[4], y, z[4], &carry);
+ z[5] = word_madd3(x[5], y, z[5], &carry);
+ z[6] = word_madd3(x[6], y, z[6], &carry);
+ z[7] = word_madd3(x[7], y, z[7], &carry);
+ return carry;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = *w0;
+ *w0 = word_madd2(a, b, &carry);
+ *w1 += carry;
+ *w2 += (*w1 < carry) ? 1 : 0;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = 0;
+ a = word_madd2(a, b, &carry);
+ b = carry;
+
+ word top = (b >> (BOTAN_MP_WORD_BITS-1));
+ b <<= 1;
+ b |= (a >> (BOTAN_MP_WORD_BITS-1));
+ a <<= 1;
+
+ carry = 0;
+ *w0 = word_add(*w0, a, &carry);
+ *w1 = word_add(*w1, b, &carry);
+ *w2 = word_add(*w2, top, &carry);
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/mp_core.h b/botan/build/botan/mp_core.h
new file mode 100644
index 0000000..ea27a77
--- /dev/null
+++ b/botan/build/botan/mp_core.h
@@ -0,0 +1,98 @@
+/*
+* MPI Algorithms
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_CORE_H__
+#define BOTAN_MP_CORE_H__
+
+#include <botan/mp_types.h>
+
+namespace Botan {
+
+/*
+* The size of the word type, in bits
+*/
+const u32bit MP_WORD_BITS = BOTAN_MP_WORD_BITS;
+
+extern "C" {
+
+/*
+* Addition/Subtraction Operations
+*/
+void bigint_add2(word[], u32bit, const word[], u32bit);
+void bigint_add3(word[], const word[], u32bit, const word[], u32bit);
+
+word bigint_add2_nc(word[], u32bit, const word[], u32bit);
+word bigint_add3_nc(word[], const word[], u32bit, const word[], u32bit);
+
+void bigint_sub2(word[], u32bit, const word[], u32bit);
+void bigint_sub3(word[], const word[], u32bit, const word[], u32bit);
+
+/*
+* Shift Operations
+*/
+void bigint_shl1(word[], u32bit, u32bit, u32bit);
+void bigint_shl2(word[], const word[], u32bit, u32bit, u32bit);
+void bigint_shr1(word[], u32bit, u32bit, u32bit);
+void bigint_shr2(word[], const word[], u32bit, u32bit, u32bit);
+
+/*
+* Simple O(N^2) Multiplication and Squaring
+*/
+void bigint_simple_mul(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size);
+void bigint_simple_sqr(word z[], const word x[], u32bit x_size);
+
+/*
+* Linear Multiply
+*/
+void bigint_linmul2(word[], u32bit, word);
+void bigint_linmul3(word[], const word[], u32bit, word);
+void bigint_linmul_add(word[], u32bit, const word[], u32bit, word);
+
+/*
+* Montgomery Reduction
+*/
+void bigint_monty_redc(word[], u32bit, const word[], u32bit, word);
+
+/*
+* Misc Utility Operations
+*/
+u32bit bigint_divcore(word, word, word, word, word, word);
+s32bit bigint_cmp(const word[], u32bit, const word[], u32bit);
+word bigint_divop(word, word, word);
+word bigint_modop(word, word, word);
+void bigint_wordmul(word, word, word*, word*);
+
+/*
+* Comba Multiplication / Squaring
+*/
+void bigint_comba_mul4(word[8], const word[4], const word[4]);
+void bigint_comba_mul6(word[12], const word[6], const word[6]);
+void bigint_comba_mul8(word[16], const word[8], const word[8]);
+void bigint_comba_mul16(word[32], const word[16], const word[16]);
+
+void bigint_comba_sqr4(word[8], const word[4]);
+void bigint_comba_sqr6(word[12], const word[6]);
+void bigint_comba_sqr8(word[16], const word[8]);
+void bigint_comba_sqr8(word[32], const word[16]);
+void bigint_comba_sqr16(word[64], const word[32]);
+
+}
+
+/*
+* High Level Multiplication/Squaring Interfaces
+*/
+void bigint_mul(word[], u32bit, word[],
+ const word[], u32bit, u32bit,
+ const word[], u32bit, u32bit);
+
+void bigint_sqr(word[], u32bit, word[],
+ const word[], u32bit, u32bit);
+
+}
+
+#endif
diff --git a/botan/build/botan/mp_types.h b/botan/build/botan/mp_types.h
new file mode 100644
index 0000000..1648713
--- /dev/null
+++ b/botan/build/botan/mp_types.h
@@ -0,0 +1,33 @@
+/*
+* Low Level MPI Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MPI_TYPES_H__
+#define BOTAN_MPI_TYPES_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+#if (BOTAN_MP_WORD_BITS == 8)
+ typedef byte word;
+#elif (BOTAN_MP_WORD_BITS == 16)
+ typedef u16bit word;
+#elif (BOTAN_MP_WORD_BITS == 32)
+ typedef u32bit word;
+#elif (BOTAN_MP_WORD_BITS == 64)
+ typedef u64bit word;
+#else
+ #error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
+#endif
+
+const word MP_WORD_MASK = ~static_cast<word>(0);
+const word MP_WORD_TOP_BIT = static_cast<word>(1) << (8*sizeof(word) - 1);
+const word MP_WORD_MAX = MP_WORD_MASK;
+
+}
+
+#endif
diff --git a/botan/build/botan/mutex.h b/botan/build/botan/mutex.h
new file mode 100644
index 0000000..a04ff83
--- /dev/null
+++ b/botan/build/botan/mutex.h
@@ -0,0 +1,56 @@
+/*
+* Mutex
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_H__
+#define BOTAN_MUTEX_H__
+
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* Mutex Base Class
+*/
+class BOTAN_DLL Mutex
+ {
+ public:
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
+ virtual ~Mutex() {}
+ };
+
+/*
+* Mutex Factory
+*/
+class BOTAN_DLL Mutex_Factory
+ {
+ public:
+ virtual Mutex* make() = 0;
+ virtual ~Mutex_Factory() {}
+ };
+
+/*
+* Mutex Holding Class
+*/
+class BOTAN_DLL Mutex_Holder
+ {
+ public:
+ Mutex_Holder(Mutex* m) : mux(m)
+ {
+ if(!mux)
+ throw Invalid_Argument("Mutex_Holder: Argument was NULL");
+ mux->lock();
+ }
+
+ ~Mutex_Holder() { mux->unlock(); }
+ private:
+ Mutex* mux;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mux_noop.h b/botan/build/botan/mux_noop.h
new file mode 100644
index 0000000..94201cb
--- /dev/null
+++ b/botan/build/botan/mux_noop.h
@@ -0,0 +1,26 @@
+/*
+* No-Op Mutex Factory
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOOP_MUTEX_FACTORY_H__
+#define BOTAN_NOOP_MUTEX_FACTORY_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* No-Op Mutex Factory
+*/
+class BOTAN_DLL Noop_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mux_pthr.h b/botan/build/botan/mux_pthr.h
new file mode 100644
index 0000000..1188539
--- /dev/null
+++ b/botan/build/botan/mux_pthr.h
@@ -0,0 +1,26 @@
+/*
+* Pthread Mutex
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_PTHREAD_H__
+#define BOTAN_MUTEX_PTHREAD_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* Pthread Mutex Factory
+*/
+class BOTAN_DLL Pthread_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/mux_win32.h b/botan/build/botan/mux_win32.h
new file mode 100644
index 0000000..a91850e
--- /dev/null
+++ b/botan/build/botan/mux_win32.h
@@ -0,0 +1,26 @@
+/*
+* Win32 Mutex
+* (C) 2006 Luca Piccarreta
+* 2006-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_WIN32_H__
+#define BOTAN_MUTEX_WIN32_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* Win32 Mutex Factory
+*/
+class BOTAN_DLL Win32_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+}
+
+#endif
diff --git a/botan/build/botan/noekeon.h b/botan/build/botan/noekeon.h
new file mode 100644
index 0000000..8938924
--- /dev/null
+++ b/botan/build/botan/noekeon.h
@@ -0,0 +1,37 @@
+/*
+* Noekeon
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOEKEON_H__
+#define BOTAN_NOEKEON_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Noekeon
+*/
+class BOTAN_DLL Noekeon : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Noekeon"; }
+ BlockCipher* clone() const { return new Noekeon; }
+ Noekeon() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const byte RC[17];
+
+ SecureBuffer<u32bit, 4> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/nr.h b/botan/build/botan/nr.h
new file mode 100644
index 0000000..144c5ec
--- /dev/null
+++ b/botan/build/botan/nr.h
@@ -0,0 +1,63 @@
+/*
+* Nyberg-Rueppel
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NYBERG_RUEPPEL_H__
+#define BOTAN_NYBERG_RUEPPEL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/nr_core.h>
+
+namespace Botan {
+
+/*
+* Nyberg-Rueppel Public Key
+*/
+class BOTAN_DLL NR_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "NR"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ NR_PublicKey() {}
+ NR_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ NR_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* Nyberg-Rueppel Private Key
+*/
+class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ NR_PrivateKey() {}
+
+ NR_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/nr_core.h b/botan/build/botan/nr_core.h
new file mode 100644
index 0000000..4837736
--- /dev/null
+++ b/botan/build/botan/nr_core.h
@@ -0,0 +1,37 @@
+/*
+* NR Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NR_CORE_H__
+#define BOTAN_NR_CORE_H__
+
+#include <botan/nr_op.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* NR Core
+*/
+class BOTAN_DLL NR_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ NR_Core& operator=(const NR_Core&);
+
+ NR_Core() { op = 0; }
+ NR_Core(const NR_Core&);
+ NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~NR_Core() { delete op; }
+ private:
+ NR_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/nr_op.h b/botan/build/botan/nr_op.h
new file mode 100644
index 0000000..cba1465
--- /dev/null
+++ b/botan/build/botan/nr_op.h
@@ -0,0 +1,53 @@
+/*
+* NR Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NR_OPS_H__
+#define BOTAN_NR_OPS_H__
+
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* NR Operation
+*/
+class BOTAN_DLL NR_Operation
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual NR_Operation* clone() const = 0;
+ virtual ~NR_Operation() {}
+ };
+
+/*
+* Botan's Default NR Operation
+*/
+class BOTAN_DLL Default_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new Default_NR_Op(*this); }
+
+ Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+
+}
+
+#endif
diff --git a/botan/build/botan/numthry.h b/botan/build/botan/numthry.h
new file mode 100644
index 0000000..e4c0437
--- /dev/null
+++ b/botan/build/botan/numthry.h
@@ -0,0 +1,120 @@
+/*
+* Number Theory Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NUMBER_THEORY_H__
+#define BOTAN_NUMBER_THEORY_H__
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Fused Arithmetic Operations
+*/
+BigInt BOTAN_DLL mul_add(const BigInt&, const BigInt&, const BigInt&);
+BigInt BOTAN_DLL sub_mul(const BigInt&, const BigInt&, const BigInt&);
+
+/*
+* Number Theory Functions
+*/
+inline BigInt abs(const BigInt& n) { return n.abs(); }
+
+void BOTAN_DLL divide(const BigInt&, const BigInt&, BigInt&, BigInt&);
+
+BigInt BOTAN_DLL gcd(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL lcm(const BigInt&, const BigInt&);
+
+BigInt BOTAN_DLL square(const BigInt&);
+BigInt BOTAN_DLL inverse_mod(const BigInt&, const BigInt&);
+s32bit BOTAN_DLL jacobi(const BigInt&, const BigInt&);
+
+BigInt BOTAN_DLL power_mod(const BigInt&, const BigInt&, const BigInt&);
+
+/*
+* Compute the square root of x modulo a prime
+* using the Shanks-Tonnelli algorithm
+*/
+BigInt ressol(const BigInt& x, const BigInt& p);
+
+/*
+* Utility Functions
+*/
+u32bit BOTAN_DLL low_zero_bits(const BigInt&);
+
+/*
+* Primality Testing
+*/
+bool BOTAN_DLL check_prime(const BigInt&, RandomNumberGenerator&);
+bool BOTAN_DLL is_prime(const BigInt&, RandomNumberGenerator&);
+bool BOTAN_DLL verify_prime(const BigInt&, RandomNumberGenerator&);
+
+s32bit BOTAN_DLL simple_primality_tests(const BigInt&);
+
+bool BOTAN_DLL passes_mr_tests(RandomNumberGenerator&,
+ const BigInt&, u32bit = 1);
+
+bool BOTAN_DLL run_primality_tests(RandomNumberGenerator&,
+ const BigInt&, u32bit = 1);
+
+/*
+* Random Number Generation
+*/
+BigInt BOTAN_DLL random_prime(RandomNumberGenerator&,
+ u32bit bits, const BigInt& coprime = 1,
+ u32bit equiv = 1, u32bit equiv_mod = 2);
+
+BigInt BOTAN_DLL random_safe_prime(RandomNumberGenerator&,
+ u32bit);
+
+/*
+* DSA Parameter Generation
+*/
+class Algorithm_Factory;
+
+SecureVector<byte> BOTAN_DLL
+generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p, BigInt& q,
+ u32bit pbits, u32bit qbits);
+
+bool BOTAN_DLL
+generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p_out, BigInt& q_out,
+ u32bit p_bits, u32bit q_bits,
+ const MemoryRegion<byte>& seed);
+
+/*
+* Prime Numbers
+*/
+const u32bit PRIME_TABLE_SIZE = 6541;
+const u32bit PRIME_PRODUCTS_TABLE_SIZE = 256;
+
+extern const u16bit BOTAN_DLL PRIMES[];
+extern const u64bit PRIME_PRODUCTS[];
+
+/*
+* Miller-Rabin Primality Tester
+*/
+class BOTAN_DLL MillerRabin_Test
+ {
+ public:
+ bool passes_test(const BigInt&);
+ MillerRabin_Test(const BigInt&);
+ private:
+ BigInt n, r, n_minus_1;
+ u32bit s;
+ Fixed_Exponent_Power_Mod pow_mod;
+ Modular_Reducer reducer;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ofb.h b/botan/build/botan/ofb.h
new file mode 100644
index 0000000..a3aadc1
--- /dev/null
+++ b/botan/build/botan/ofb.h
@@ -0,0 +1,33 @@
+/*
+* OFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OUTPUT_FEEDBACK_MODE_H__
+#define BOTAN_OUTPUT_FEEDBACK_MODE_H__
+
+#include <botan/modebase.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* OFB Mode
+*/
+class BOTAN_DLL OFB : public BlockCipherMode
+ {
+ public:
+ OFB(BlockCipher* cipher);
+
+ OFB(BlockCipher* cipher,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+ private:
+ void write(const byte[], u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/oids.h b/botan/build/botan/oids.h
new file mode 100644
index 0000000..fdfe61f
--- /dev/null
+++ b/botan/build/botan/oids.h
@@ -0,0 +1,58 @@
+/*
+* OID Registry
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OIDS_H__
+#define BOTAN_OIDS_H__
+
+#include <botan/asn1_oid.h>
+
+namespace Botan {
+
+namespace OIDS {
+
+/**
+* Register an OID to string mapping.
+* @param oid the oid to register
+* @param name the name to be associated with the oid
+*/
+BOTAN_DLL void add_oid(const OID& oid, const std::string& name);
+
+/**
+* See if an OID exists in the internal table.
+* @param oid the oid to check for
+* @return true if the oid is registered
+*/
+BOTAN_DLL bool have_oid(const std::string& oid);
+
+/**
+* Resolve an OID
+* @param oid the OID to look up
+* @return the name associated with this OID
+*/
+BOTAN_DLL std::string lookup(const OID& oid);
+
+/**
+* Find the OID to a name. The lookup will be performed in the
+* general OID section of the configuration.
+* @param name the name to resolve
+* @return the OID associated with the specified name
+*/
+BOTAN_DLL OID lookup(const std::string& name);
+
+/**
+* Tests whether the specified OID stands for the specified name.
+* @param oid the OID to check
+* @param name the name to check
+* @return true if the specified OID stands for the specified name
+*/
+BOTAN_DLL bool name_of(const OID& oid, const std::string& name);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/openpgp.h b/botan/build/botan/openpgp.h
new file mode 100644
index 0000000..890fcf0
--- /dev/null
+++ b/botan/build/botan/openpgp.h
@@ -0,0 +1,34 @@
+/*
+* OpenPGP
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENPGP_H__
+#define BOTAN_OPENPGP_H__
+
+#include <botan/data_src.h>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*
+* OpenPGP Base64 encoding/decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&,
+ const std::map<std::string, std::string>&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&,
+ std::map<std::string, std::string>&);
+
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/out_buf.h b/botan/build/botan/out_buf.h
new file mode 100644
index 0000000..0baacda
--- /dev/null
+++ b/botan/build/botan/out_buf.h
@@ -0,0 +1,43 @@
+/*
+* Output Buffer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OUTPUT_BUFFER_H__
+#define BOTAN_OUTPUT_BUFFER_H__
+
+#include <botan/types.h>
+#include <botan/pipe.h>
+#include <deque>
+
+namespace Botan {
+
+/*
+* Container of output buffers for Pipe
+*/
+class BOTAN_DLL Output_Buffers
+ {
+ public:
+ u32bit read(byte[], u32bit, Pipe::message_id);
+ u32bit peek(byte[], u32bit, u32bit, Pipe::message_id) const;
+ u32bit remaining(Pipe::message_id) const;
+
+ void add(class SecureQueue*);
+ void retire();
+
+ Pipe::message_id message_count() const;
+
+ Output_Buffers();
+ ~Output_Buffers();
+ private:
+ class SecureQueue* get(Pipe::message_id) const;
+
+ std::deque<SecureQueue*> buffers;
+ Pipe::message_id offset;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/par_hash.h b/botan/build/botan/par_hash.h
new file mode 100644
index 0000000..7e75c27
--- /dev/null
+++ b/botan/build/botan/par_hash.h
@@ -0,0 +1,36 @@
+/*
+* Parallel Hash
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PARALLEL_HASH_H__
+#define BOTAN_PARALLEL_HASH_H__
+
+#include <botan/hash.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Parallel
+*/
+class BOTAN_DLL Parallel : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ HashFunction* clone() const;
+
+ Parallel(const std::vector<HashFunction*>&);
+ ~Parallel();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ std::vector<HashFunction*> hashes;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/parsing.h b/botan/build/botan/parsing.h
new file mode 100644
index 0000000..2c29d5b
--- /dev/null
+++ b/botan/build/botan/parsing.h
@@ -0,0 +1,41 @@
+/*
+* Parser Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PARSER_H__
+#define BOTAN_PARSER_H__
+
+#include <botan/types.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/*
+* String Parsing Functions
+*/
+BOTAN_DLL std::vector<std::string> parse_algorithm_name(const std::string&);
+BOTAN_DLL std::vector<std::string> split_on(const std::string&, char);
+BOTAN_DLL std::vector<u32bit> parse_asn1_oid(const std::string&);
+BOTAN_DLL bool x500_name_cmp(const std::string&, const std::string&);
+
+/*
+* String/Integer Conversions
+*/
+BOTAN_DLL std::string to_string(u64bit, u32bit = 0);
+BOTAN_DLL u32bit to_u32bit(const std::string&);
+
+BOTAN_DLL u32bit timespec_to_u32bit(const std::string& timespec);
+
+/*
+* String/Network Address Conversions
+*/
+BOTAN_DLL u32bit string_to_ipv4(const std::string&);
+BOTAN_DLL std::string ipv4_to_string(u32bit);
+
+}
+
+#endif
diff --git a/botan/build/botan/pbe.h b/botan/build/botan/pbe.h
new file mode 100644
index 0000000..f06d593
--- /dev/null
+++ b/botan/build/botan/pbe.h
@@ -0,0 +1,56 @@
+/*
+* PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_BASE_H__
+#define BOTAN_PBE_BASE_H__
+
+#include <botan/asn1_oid.h>
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Password Based Encryption (PBE) Filter.
+*/
+class BOTAN_DLL PBE : public Filter
+ {
+ public:
+ /**
+ * Set this filter's key.
+ * @param pw the password to be used for the encryption
+ */
+ virtual void set_key(const std::string&) = 0;
+
+ /**
+ * Create a new random salt value and set the default iterations value.
+ */
+ virtual void new_params(RandomNumberGenerator& rng) = 0;
+
+ /**
+ * DER encode the params (the number of iterations and the salt value)
+ * @return the encoded params
+ */
+ virtual MemoryVector<byte> encode_params() const = 0;
+
+ /**
+ * Decode params and use them inside this Filter.
+ * @param src a data source to read the encoded params from
+ */
+ virtual void decode_params(DataSource&) = 0;
+
+ /**
+ * Get this PBE's OID.
+ * @return the OID
+ */
+ virtual OID get_oid() const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pbes1.h b/botan/build/botan/pbes1.h
new file mode 100644
index 0000000..2e1855d
--- /dev/null
+++ b/botan/build/botan/pbes1.h
@@ -0,0 +1,53 @@
+/*
+* PKCS #5 v1.5 PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_PKCS_V15_H__
+#define BOTAN_PBE_PKCS_V15_H__
+
+#include <botan/pbe.h>
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* PKCS#5 v1.5 PBE
+*/
+class BOTAN_DLL PBE_PKCS5v15 : public PBE
+ {
+ public:
+ void write(const byte[], u32bit);
+ void start_msg();
+ void end_msg();
+
+ PBE_PKCS5v15(BlockCipher* cipher,
+ HashFunction* hash,
+ Cipher_Dir);
+
+ ~PBE_PKCS5v15();
+ private:
+ void set_key(const std::string&);
+ void new_params(RandomNumberGenerator& rng);
+ MemoryVector<byte> encode_params() const;
+ void decode_params(DataSource&);
+ OID get_oid() const;
+
+ void flush_pipe(bool);
+
+ Cipher_Dir direction;
+ BlockCipher* block_cipher;
+ HashFunction* hash_function;
+
+ SecureVector<byte> salt, key, iv;
+ u32bit iterations;
+ Pipe pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pbes2.h b/botan/build/botan/pbes2.h
new file mode 100644
index 0000000..fc460a2
--- /dev/null
+++ b/botan/build/botan/pbes2.h
@@ -0,0 +1,53 @@
+/*
+* PKCS #5 v2.0 PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_PKCS_v20_H__
+#define BOTAN_PBE_PKCS_v20_H__
+
+#include <botan/pbe.h>
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* PKCS#5 v2.0 PBE
+*/
+class BOTAN_DLL PBE_PKCS5v20 : public PBE
+ {
+ public:
+ static bool known_cipher(const std::string&);
+
+ void write(const byte[], u32bit);
+ void start_msg();
+ void end_msg();
+
+ PBE_PKCS5v20(DataSource&);
+ PBE_PKCS5v20(BlockCipher*, HashFunction*);
+
+ ~PBE_PKCS5v20();
+ private:
+ void set_key(const std::string&);
+ void new_params(RandomNumberGenerator& rng);
+ MemoryVector<byte> encode_params() const;
+ void decode_params(DataSource&);
+ OID get_oid() const;
+
+ void flush_pipe(bool);
+
+ Cipher_Dir direction;
+ BlockCipher* block_cipher;
+ HashFunction* hash_function;
+ SecureVector<byte> salt, key, iv;
+ u32bit iterations, key_length;
+ Pipe pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pbkdf1.h b/botan/build/botan/pbkdf1.h
new file mode 100644
index 0000000..4e5cafd
--- /dev/null
+++ b/botan/build/botan/pbkdf1.h
@@ -0,0 +1,44 @@
+/*
+* PBKDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBKDF1_H__
+#define BOTAN_PBKDF1_H__
+
+#include <botan/s2k.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* This class implements the PKCS #5 PBKDF1 functionality.
+*/
+class BOTAN_DLL PKCS5_PBKDF1 : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ /**
+ * Create a PKCS #5 instance using the specified hash function.
+ * @param hash a pointer to a hash function object to use
+ */
+ PKCS5_PBKDF1(HashFunction* hash_in) : hash(hash_in) {}
+
+ PKCS5_PBKDF1(const PKCS5_PBKDF1& other) :
+ S2K(), hash(other.hash->clone()) {}
+
+ ~PKCS5_PBKDF1() { delete hash; }
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pbkdf2.h b/botan/build/botan/pbkdf2.h
new file mode 100644
index 0000000..7510338
--- /dev/null
+++ b/botan/build/botan/pbkdf2.h
@@ -0,0 +1,40 @@
+/*
+* PBKDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBKDF2_H__
+#define BOTAN_PBKDF2_H__
+
+#include <botan/s2k.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/**
+* This class implements the PKCS #5 PBKDF2 functionality.
+*/
+class BOTAN_DLL PKCS5_PBKDF2 : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ /**
+ * Create a PKCS #5 instance using the specified message auth code
+ * @param mac the MAC to use
+ */
+ PKCS5_PBKDF2(MessageAuthenticationCode* mac);
+ ~PKCS5_PBKDF2();
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ MessageAuthenticationCode* mac;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pem.h b/botan/build/botan/pem.h
new file mode 100644
index 0000000..9fe8acb
--- /dev/null
+++ b/botan/build/botan/pem.h
@@ -0,0 +1,35 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PEM_H__
+#define BOTAN_PEM_H__
+
+#include <botan/data_src.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+/*
+* PEM Encoding/Decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit,
+ const std::string&, u32bit = 64);
+BOTAN_DLL std::string encode(const MemoryRegion<byte>&,
+ const std::string&, u32bit = 64);
+
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&,
+ const std::string&);
+BOTAN_DLL bool matches(DataSource&, const std::string& = "",
+ u32bit search_range = 4096);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/pgp_s2k.h b/botan/build/botan/pgp_s2k.h
new file mode 100644
index 0000000..00e95f7
--- /dev/null
+++ b/botan/build/botan/pgp_s2k.h
@@ -0,0 +1,36 @@
+/*
+* OpenPGP S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENPGP_S2K_H__
+#define BOTAN_OPENPGP_S2K_H__
+
+#include <botan/s2k.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* OpenPGP S2K
+*/
+class BOTAN_DLL OpenPGP_S2K : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
+ ~OpenPGP_S2K() { delete hash; }
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pipe.h b/botan/build/botan/pipe.h
new file mode 100644
index 0000000..120f2fb
--- /dev/null
+++ b/botan/build/botan/pipe.h
@@ -0,0 +1,275 @@
+/*
+* Pipe
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_H__
+#define BOTAN_PIPE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/exceptn.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents pipe objects.
+* A set of filters can be placed into a pipe, and information flows
+* through the pipe until it reaches the end, where the output is
+* collected for retrieval. If you're familiar with the Unix shell
+* environment, this design will sound quite familiar.
+*/
+
+class BOTAN_DLL Pipe : public DataSource
+ {
+ public:
+ typedef u32bit message_id;
+
+ class Invalid_Message_Number : public Invalid_Argument
+ {
+ public:
+ Invalid_Message_Number(const std::string&, message_id);
+ };
+
+ static const message_id LAST_MESSAGE;
+ static const message_id DEFAULT_MESSAGE;
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the byte array to write
+ * @param length the length of the byte array in
+ */
+ void write(const byte in[], u32bit length);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void write(const MemoryRegion<byte>& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the string containing the data to write
+ */
+ void write(const std::string& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the DataSource to read the data from
+ */
+ void write(DataSource& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in a single byte to be written
+ */
+ void write(byte in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the byte array containing the data to write
+ * @param length the length of the byte array to write
+ */
+ void process_msg(const byte in[], u32bit length);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void process_msg(const MemoryRegion<byte>& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the string containing the data to write
+ */
+ void process_msg(const std::string& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the DataSource providing the data to write
+ */
+ void process_msg(DataSource& in);
+
+ /**
+ * Find out how many bytes are ready to read.
+ * @param msg the number identifying the message
+ * for which the information is desired
+ * @return the number of bytes that can still be read
+ */
+ u32bit remaining(message_id msg = DEFAULT_MESSAGE) const;
+
+ /**
+ * Read the default message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length);
+
+ /**
+ * Read a specified message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @param msg the number identifying the message to read from
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length, message_id msg);
+
+ /**
+ * Read a single byte from the pipe. Moves the internal offset so that
+ * every call to read will return a new portion of the message.
+ * @param output the byte to write the result to
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte& output, message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a SecureVector holding the contents of the pipe
+ */
+ SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a string holding the contents of the pipe
+ */
+ std::string read_all_as_string(message_id = DEFAULT_MESSAGE);
+
+ /** Read from the default message but do not modify the internal
+ * offset. Consecutive calls to peek() will return portions of
+ * the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length, u32bit offset) const;
+
+ /** Read from the specified message but do not modify the
+ * internal offset. Consecutive calls to peek() will return
+ * portions of the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length,
+ u32bit offset, message_id msg) const;
+
+ /** Read a single byte from the specified message but do not
+ * modify the internal offset. Consecutive calls to peek() will
+ * return portions of the message starting at the same position.
+ * @param output the byte to write the peeked message byte to
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte& output, u32bit offset,
+ message_id msg = DEFAULT_MESSAGE) const;
+
+ u32bit default_msg() const { return default_read; }
+
+ /**
+ * Set the default message
+ * @param msg the number identifying the message which is going to
+ * be the new default message
+ */
+ void set_default_msg(message_id msg);
+
+ /**
+ * Get the number of messages the are in this pipe.
+ * @return the number of messages the are in this pipe
+ */
+ message_id message_count() const;
+
+ /**
+ * Test whether this pipe has any data that can be read from.
+ * @return true if there is more data to read, false otherwise
+ */
+ bool end_of_data() const;
+
+ /**
+ * Start a new message in the pipe. A potential other message in this pipe
+ * must be closed with end_msg() before this function may be called.
+ */
+ void start_msg();
+
+ /**
+ * End the current message.
+ */
+ void end_msg();
+
+ /**
+ * Insert a new filter at the front of the pipe
+ * @param filt the new filter to insert
+ */
+ void prepend(Filter* filt);
+
+ /**
+ * Insert a new filter at the back of the pipe
+ * @param filt the new filter to insert
+ */
+ void append(Filter* filt);
+
+ /**
+ * Remove the first filter at the front of the pipe.
+ */
+ void pop();
+
+ /**
+ * Reset this pipe to an empty pipe.
+ */
+ void reset();
+
+ /**
+ * Construct a Pipe of up to four filters. The filters are set up
+ * in the same order as the arguments.
+ */
+ Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Pipe from range of filters passed as an array
+ * @param filters the set of filters to use
+ * @param count the number of elements in filters
+ */
+ Pipe(Filter* filters[], u32bit count);
+ ~Pipe();
+ private:
+ Pipe(const Pipe&) : DataSource() {}
+ Pipe& operator=(const Pipe&) { return (*this); }
+ void init();
+ void destruct(Filter*);
+ void find_endpoints(Filter*);
+ void clear_endpoints(Filter*);
+
+ message_id get_message_no(const std::string&, message_id) const;
+
+ Filter* pipe;
+ class Output_Buffers* outputs;
+ message_id default_read;
+ bool inside_msg;
+ };
+
+/*
+* I/O Operators for Pipe
+*/
+BOTAN_DLL std::ostream& operator<<(std::ostream&, Pipe&);
+BOTAN_DLL std::istream& operator>>(std::istream&, Pipe&);
+
+}
+
+#endif
+
+#if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
+ #include <botan/fd_unix.h>
+#endif
diff --git a/botan/build/botan/pk_algs.h b/botan/build/botan/pk_algs.h
new file mode 100644
index 0000000..c41bf1a
--- /dev/null
+++ b/botan/build/botan/pk_algs.h
@@ -0,0 +1,31 @@
+/*
+* PK Key Factory
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H__
+#define BOTAN_PK_KEY_FACTORY_H__
+
+#include <botan/pk_keys.h>
+
+namespace Botan {
+
+/**
+* Get an empty public key object.
+* @param name the name of the desired public key algorithm
+* @return the public key object
+*/
+BOTAN_DLL Public_Key* get_public_key(const std::string&);
+
+/**
+* Get an empty private key object.
+* @param name the name of the desired public key algorithm
+* @return the private key object
+*/
+BOTAN_DLL Private_Key* get_private_key(const std::string&);
+
+}
+
+#endif
diff --git a/botan/build/botan/pk_engine.h b/botan/build/botan/pk_engine.h
new file mode 100644
index 0000000..256a47c
--- /dev/null
+++ b/botan/build/botan/pk_engine.h
@@ -0,0 +1,95 @@
+/**
+* Engine for PK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_PK_LOOKUP_H__
+#define BOTAN_ENGINE_PK_LOOKUP_H__
+
+#include <botan/bigint.h>
+#include <botan/pow_mod.h>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+namespace Botan {
+
+class Algorithm_Factory;
+class Keyed_Filter;
+class Modular_Exponentiator;
+
+namespace Engine_Core {
+
+/*
+* Get an operation from an Engine
+*/
+Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints);
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+DH_Operation* dh_op(const DL_Group&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ECDSA_Operation* ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ECKAEG_Operation* eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/pk_filts.h b/botan/build/botan/pk_filts.h
new file mode 100644
index 0000000..8bf3fc2
--- /dev/null
+++ b/botan/build/botan/pk_filts.h
@@ -0,0 +1,91 @@
+/*
+* PK Filters
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_FILTERS_H__
+#define BOTAN_PK_FILTERS_H__
+
+#include <botan/filter.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/*
+* PK_Encryptor Filter
+*/
+class BOTAN_DLL PK_Encryptor_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+ PK_Encryptor_Filter(PK_Encryptor* c,
+ RandomNumberGenerator& rng_ref) :
+ cipher(c), rng(rng_ref) {}
+ ~PK_Encryptor_Filter() { delete cipher; }
+ private:
+ PK_Encryptor* cipher;
+ RandomNumberGenerator& rng;
+ SecureVector<byte> buffer;
+ };
+
+/*
+* PK_Decryptor Filter
+*/
+class BOTAN_DLL PK_Decryptor_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+ PK_Decryptor_Filter(PK_Decryptor* c) : cipher(c) {}
+ ~PK_Decryptor_Filter() { delete cipher; }
+ private:
+ PK_Decryptor* cipher;
+ SecureVector<byte> buffer;
+ };
+
+/*
+* PK_Signer Filter
+*/
+class BOTAN_DLL PK_Signer_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ PK_Signer_Filter(PK_Signer* s,
+ RandomNumberGenerator& rng_ref) :
+ signer(s), rng(rng_ref) {}
+
+ ~PK_Signer_Filter() { delete signer; }
+ private:
+ PK_Signer* signer;
+ RandomNumberGenerator& rng;
+ };
+
+/*
+* PK_Verifier Filter
+*/
+class BOTAN_DLL PK_Verifier_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ void set_signature(const byte[], u32bit);
+ void set_signature(const MemoryRegion<byte>&);
+
+ PK_Verifier_Filter(PK_Verifier* v) : verifier(v) {}
+ PK_Verifier_Filter(PK_Verifier*, const byte[], u32bit);
+ PK_Verifier_Filter(PK_Verifier*, const MemoryRegion<byte>&);
+ ~PK_Verifier_Filter() { delete verifier; }
+ private:
+ PK_Verifier* verifier;
+ SecureVector<byte> signature;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pk_keys.h b/botan/build/botan/pk_keys.h
new file mode 100644
index 0000000..5b61257
--- /dev/null
+++ b/botan/build/botan/pk_keys.h
@@ -0,0 +1,180 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_KEYS_H__
+#define BOTAN_PK_KEYS_H__
+
+#include <botan/secmem.h>
+#include <botan/asn1_oid.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Public Key Base Class.
+*/
+class BOTAN_DLL Public_Key
+ {
+ public:
+ /**
+ * Get the name of the underlying public key scheme.
+ * @return the name of the public key scheme
+ */
+ virtual std::string algo_name() const = 0;
+
+ /**
+ * Get the OID of the underlying public key scheme.
+ * @return the OID of the public key scheme
+ */
+ virtual OID get_oid() const;
+
+ /**
+ * Test the key values for consistency.
+ * @param rng rng to use
+ * @param strong whether to perform strong and lengthy version
+ * of the test
+ * @return true if the test is passed
+ */
+ virtual bool check_key(RandomNumberGenerator&, bool) const
+ { return true; }
+
+ /**
+ * Find out the number of message parts supported by this scheme.
+ * @return the number of message parts
+ */
+ virtual u32bit message_parts() const { return 1; }
+
+ /**
+ * Find out the message part size supported by this scheme/key.
+ * @return the size of the message parts
+ */
+ virtual u32bit message_part_size() const { return 0; }
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return the maximum message in bits
+ */
+ virtual u32bit max_input_bits() const = 0;
+
+ /**
+ * Get an X509 encoder that can be used to encode this key in X509 format.
+ * @return an X509 encoder for this key
+ */
+ virtual class X509_Encoder* x509_encoder() const = 0;
+
+ /**
+ * Get an X509 decoder that can be used to set the values of this
+ * key based on an X509 encoded key object.
+ * @return an X509 decoder for this key
+ */
+ virtual class X509_Decoder* x509_decoder() = 0;
+
+ virtual ~Public_Key() {}
+ protected:
+ virtual void load_check(RandomNumberGenerator&) const;
+ };
+
+/**
+* Private Key Base Class
+*/
+class BOTAN_DLL Private_Key : public virtual Public_Key
+ {
+ public:
+ /**
+ * Get a PKCS#8 encoder that can be used to encode this key in
+ * PKCS#8 format.
+ * @return an PKCS#8 encoder for this key
+ */
+ virtual class PKCS8_Encoder* pkcs8_encoder() const
+ { return 0; }
+
+ /**
+ * Get an PKCS#8 decoder that can be used to set the values of this key
+ * based on an PKCS#8 encoded key object.
+ * @return an PKCS#8 decoder for this key
+ */
+ virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&)
+ { return 0; }
+ protected:
+ void load_check(RandomNumberGenerator&) const;
+ void gen_check(RandomNumberGenerator&) const;
+ };
+
+/**
+* PK Encrypting Key.
+*/
+class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ virtual ~PK_Encrypting_Key() {}
+ };
+
+/**
+* PK Decrypting Key
+*/
+class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0;
+ virtual ~PK_Decrypting_Key() {}
+ };
+
+/**
+* PK Signing Key
+*/
+class BOTAN_DLL PK_Signing_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const = 0;
+ virtual ~PK_Signing_Key() {}
+ };
+
+/**
+* PK Verifying Key, Message Recovery Version
+*/
+class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_with_MR_Key() {}
+ };
+
+/**
+* PK Verifying Key, No Message Recovery Version
+*/
+class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_wo_MR_Key() {}
+ };
+
+/**
+* PK Secret Value Derivation Key
+*/
+class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0;
+ virtual MemoryVector<byte> public_value() const = 0;
+ virtual ~PK_Key_Agreement_Key() {}
+ };
+
+/*
+* Typedefs
+*/
+typedef PK_Key_Agreement_Key PK_KA_Key;
+typedef Public_Key X509_PublicKey;
+typedef Private_Key PKCS8_PrivateKey;
+
+}
+
+#endif
diff --git a/botan/build/botan/pkcs10.h b/botan/build/botan/pkcs10.h
new file mode 100644
index 0000000..9b435de
--- /dev/null
+++ b/botan/build/botan/pkcs10.h
@@ -0,0 +1,101 @@
+/*
+* PKCS #10
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS10_H__
+#define BOTAN_PKCS10_H__
+
+#include <botan/x509_obj.h>
+#include <botan/pkcs8.h>
+#include <botan/datastor.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* PKCS #10 Certificate Request.
+*/
+class BOTAN_DLL PKCS10_Request : public X509_Object
+ {
+ public:
+ /**
+ * Get the subject public key.
+ * @return the subject public key
+ */
+ Public_Key* subject_public_key() const;
+
+ /**
+ * Get the raw DER encoded public key.
+ * @return the raw DER encoded public key
+ */
+ MemoryVector<byte> raw_public_key() const;
+
+ /**
+ * Get the subject DN.
+ * @return the subject DN
+ */
+ X509_DN subject_dn() const;
+
+ /**
+ * Get the subject alternative name.
+ * @return the subject alternative name.
+ */
+ AlternativeName subject_alt_name() const;
+
+ /**
+ * Get the key constraints for the key associated with this
+ * PKCS#10 object.
+ * @return the key constraints
+ */
+ Key_Constraints constraints() const;
+
+ /**
+ * Get the extendend key constraints (if any).
+ * @return the extended key constraints
+ */
+ std::vector<OID> ex_constraints() const;
+
+ /**
+ * Find out whether this is a CA request.
+ * @result true if it is a CA request, false otherwise.
+ */
+ bool is_CA() const;
+
+ /**
+ * Return the constraint on the path length defined
+ * in the BasicConstraints extension.
+ * @return the path limit
+ */
+ u32bit path_limit() const;
+
+ /**
+ * Get the challenge password for this request
+ * @return the challenge password for this request
+ */
+ std::string challenge_password() const;
+
+ /**
+ * Create a PKCS#10 Request from a data source.
+ * @param source the data source providing the DER encoded request
+ */
+ PKCS10_Request(DataSource& source);
+
+ /**
+ * Create a PKCS#10 Request from a file.
+ * @param filename the name of the file containing the DER or PEM
+ * encoded request file
+ */
+ PKCS10_Request(const std::string& filename);
+ private:
+ void force_decode();
+ void handle_attribute(const Attribute&);
+
+ Data_Store info;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pkcs8.h b/botan/build/botan/pkcs8.h
new file mode 100644
index 0000000..28008bd
--- /dev/null
+++ b/botan/build/botan/pkcs8.h
@@ -0,0 +1,177 @@
+/*
+* PKCS #8
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <botan/ui.h>
+
+namespace Botan {
+
+/**
+* PKCS #8 Private Key Encoder.
+*/
+class BOTAN_DLL PKCS8_Encoder
+ {
+ public:
+ /**
+ * Get the algorithm identifier associated with the scheme
+ * this encoders key is part of.
+ * @return the algorithm identifier
+ */
+ virtual AlgorithmIdentifier alg_id() const = 0;
+
+ /**
+ * Get the DER encoded key.
+ * @return the DER encoded key
+ */
+ // FIXME: Why not SecureVector?
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~PKCS8_Encoder() {}
+ };
+
+/*
+* PKCS #8 Private Key Decoder
+*/
+class BOTAN_DLL PKCS8_Decoder
+ {
+ public:
+ /**
+ * Set the algorithm identifier associated with the scheme
+ * this decoders key is part of.
+ * @param alg_id the algorithm identifier
+ */
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+
+ /**
+ * Set the DER encoded key.
+ * @param key the DER encoded key
+ */
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~PKCS8_Decoder() {}
+ };
+
+/**
+* PKCS #8 General Exception
+*/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+ {
+ PKCS8_Exception(const std::string& error) :
+ Decoding_Error("PKCS #8: " + error) {}
+ };
+
+namespace PKCS8 {
+
+/**
+* Encode a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Private_Key& key, Pipe& pipe,
+ X509_Encoding enc = PEM);
+
+/**
+* Encode and encrypt a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param pass the password to use for encryption
+* @param rng the rng to use
+* @param pbe_algo the name of the desired password-based encryption algorithm.
+* Provide an empty string to use the default PBE defined in the configuration
+* under base/default_pbe.
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encrypt_key(const Private_Key& key,
+ Pipe& pipe,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo = "",
+ X509_Encoding enc = PEM);
+
+
+/**
+* Get a string containing a PEM encoded private key.
+* @param key the key to encode
+* @return the encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key);
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbe_algo the name of the desired password-based encryption algorithm.
+* Provide an empty string to use the default PBE defined in the configuration
+* under base/default_pbe.
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo = "");
+
+/**
+* Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+
+/** Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+
+/** Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @param rng the rng to use
+* @return the new copy of the key
+*/
+BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/point_gfp.h b/botan/build/botan/point_gfp.h
new file mode 100644
index 0000000..771605e
--- /dev/null
+++ b/botan/build/botan/point_gfp.h
@@ -0,0 +1,315 @@
+/*
+* Arithmetic over GF(p)
+*
+* (C) 2007 Martin Doering
+* Christoph Ludwig
+* Falko Strenzke
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POINT_GFP_H__
+#define BOTAN_POINT_GFP_H__
+
+#include <botan/curve_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/bigint.h>
+#include <botan/exceptn.h>
+#include <vector>
+
+namespace Botan {
+
+struct Illegal_Point : public Exception
+ {
+ Illegal_Point(const std::string& err = "") : Exception(err) {}
+ };
+
+/**
+* This class represents one point on a curve of GF(p).
+*/
+class BOTAN_DLL PointGFp
+ {
+ public:
+ /**
+ * uncompressed encoding byte value
+ */
+ static const int UNCOMPRESSED = 0;
+
+ /**
+ * compressed encoding byte value
+ */
+ static const int COMPRESSED = 1;
+
+ /**
+ * hybrid encoding byte value
+ */
+ static const int HYBRID = 2;
+
+ /**
+ * Construct the point O
+ * @param curve The base curve
+ */
+ explicit PointGFp(const CurveGFp& curve);
+
+ /**
+ * Construct a point given its affine coordinates
+ * @param curve the base curve
+ * @param x affine x coordinate
+ * @param y affine y coordinate
+ */
+ explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
+ GFpElement const& y);
+
+ /**
+ * Construct a point given its jacobian projective coordinates
+ * @param curve the base curve
+ * @param x jacobian projective x coordinate
+ * @param y jacobian projective y coordinate
+ * @param z jacobian projective y coordinate
+ */
+ explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
+ GFpElement const& y, GFpElement const& z);
+
+ /**
+ * copy constructor
+ * @param other the value to clone
+ */
+ PointGFp(const PointGFp& other);
+
+ /**
+ * assignment operator
+ * @param other The point to use as source for the assignment
+ */
+ const PointGFp& operator=(const PointGFp& other);
+
+ /**
+ * assign another point which is on the same curve as *this
+ * @param other The point to use as source for the assignment
+ */
+ const PointGFp& assign_within_same_curve(const PointGFp& other);
+
+
+
+ /**
+ * += Operator
+ * @param rhs the PointGFp to add to the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator+=(const PointGFp& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the PointGFp to subtract from the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator-=(const PointGFp& rhs);
+
+ /**
+ * *= Operator
+ * This function turns on the the special reduction multiplication
+ * itself for fast computation, turns it off again when finished.
+ * @param scalar the PointGFp to multiply with *this
+ * @result resulting PointGFp
+ */
+ PointGFp& operator*=(const BigInt& scalar);
+
+ /**
+ * the equivalent to operator*= with countermeasures against
+ * sidechannel attacks, using the randomized exponent
+ * and add-and-double-always
+ * countermeasures (suitable for ECDSA and ECKAEG)
+ * @param scalar the scalar to multiply the point with
+ * @param point_order a multiple of the order of the point
+ *(= n * k in the general case; k is the cofactor)
+ * @param max_secr the maximal size of the scalar
+ * (will usually be n-1 )
+ * @result resulting PointGFp
+ */
+ PointGFp& mult_this_secure(const BigInt& scalar,
+ const BigInt& point_order,
+ const BigInt& max_secr
+ );
+
+ /**
+ * Negate internal value(*this *= -1 )
+ * @return *this
+ */
+ PointGFp& negate();
+
+ /**
+ * Multiply the point by two(*this *= 2 )
+ * @return *this
+ */
+ PointGFp& mult2_in_place();
+
+ /**
+ * Set z coordinate to one.
+ * @return *this
+ */
+ const PointGFp& set_z_to_one() const;
+
+ /**
+ * Turn on the special reduction multiplication (i.e. the
+ * Montgomery multiplication in the current implementation) for
+ * the coordinates. This enables fast execution of mult2_in_place()
+ * and operator+=().
+ */
+ void turn_on_sp_red_mul() const;
+
+ /**
+ * Return a point
+ * where the coordinates are transformed
+ * so that z equals one,
+ * thus x and y have just the affine values.
+ * @result *this
+ */
+ PointGFp const get_z_to_one() const;
+
+ /**
+ * Return base curve of this point
+ * @result the curve over GF(p) of this point
+ */
+ CurveGFp const get_curve() const;
+
+ /**
+ * get affine x coordinate
+ * @result affine x coordinate
+ */
+ GFpElement const get_affine_x() const;
+
+ /**
+ * get affine y coordinate
+ * @result affine y coordinate
+ */
+ GFpElement const get_affine_y() const;
+
+ /**
+ * get the jacobian projective x coordinate
+ * @result jacobian projective x coordinate
+ */
+ GFpElement const get_jac_proj_x() const;
+
+ /**
+ * get the jacobian projective y coordinate
+ * @result jacobian projective y coordinate
+ */
+ GFpElement const get_jac_proj_y() const;
+
+ /**
+ * get the jacobian projective z coordinate
+ * @result jacobian projective z coordinate
+ */
+ GFpElement const get_jac_proj_z() const;
+
+ /**
+ * Is this the point at infinity?
+ * @result true, if this point is at infinity, false otherwise.
+ */
+ bool is_zero() const;
+
+ /**
+ * Checks whether the point is to be found on the underlying curve.
+ * Throws an Invalid_Point exception in case of detecting that the point
+ * does not satisfy the curve equation.
+ * To be used to ensure against fault attacks.
+ */
+ void check_invariants() const;
+
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other the object to swap values with
+ */
+ void swap(PointGFp& other);
+
+ /**
+ * Sets the shared pointer to the GFpModulus that will be
+ * held in *this, specifically the various members of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * Do NOT spread a shared pointer to GFpModulus over different
+ * threads!
+ * @param mod a shared pointer to a GFpModulus that will
+ * be held in the members *this
+ */
+ void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> p_mod);
+
+ static GFpElement decompress(bool yMod2, GFpElement const& x, const CurveGFp& curve);
+
+ private:
+ static const u32bit GFPEL_WKSP_SIZE = 9;
+ void ensure_worksp() const;
+
+ inline std::tr1::shared_ptr<PointGFp> mult_loop(int l, const BigInt& m,
+ std::tr1::shared_ptr<PointGFp> H,
+ std::tr1::shared_ptr<PointGFp> tmp,
+ const PointGFp& P);
+
+ CurveGFp mC;
+ mutable GFpElement mX; // NOTE: these values must be mutable (affine<->proj)
+ mutable GFpElement mY;
+ mutable GFpElement mZ;
+ mutable GFpElement mZpow2; // mZ^2
+ mutable GFpElement mZpow3; // mZ^3
+ mutable GFpElement mAZpow4; // mA*mZ^4
+ mutable bool mZpow2_set;
+ mutable bool mZpow3_set;
+ mutable bool mAZpow4_set;
+ mutable std::tr1::shared_ptr<std::vector<GFpElement> > mp_worksp_gfp_el;
+
+ };
+
+// relational operators
+bool operator==(const PointGFp& lhs, const PointGFp& rhs);
+inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs )
+ {
+ return !operator==(lhs, rhs);
+ }
+
+// arithmetic operators
+PointGFp operator+(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp operator-(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp operator-(const PointGFp& lhs);
+
+PointGFp operator*(const BigInt& scalar, const PointGFp& point);
+PointGFp operator*(const PointGFp& point, const BigInt& scalar);
+PointGFp mult_point_secure(const PointGFp& point,
+ const BigInt& scalar,
+ const BigInt& point_order,
+ const BigInt& max_secret);
+
+PointGFp const mult2(const PointGFp& point);
+
+PointGFp const create_random_point(RandomNumberGenerator& rng,
+ const CurveGFp& curve);
+
+// encoding and decoding
+SecureVector<byte> EC2OSP(const PointGFp& point, byte format);
+PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve);
+
+SecureVector<byte> encode_uncompressed(const PointGFp& point); // maybe make private
+SecureVector<byte> encode_hybrid(const PointGFp& point); // maybe make private
+SecureVector<byte> encode_compressed(const PointGFp& point); // maybe make private
+
+// swaps the states of point1 and point2, does not throw!
+// cf. Meyers, Item 25
+inline
+void swap(PointGFp& point1, PointGFp& point2 )
+ {
+ point1.swap(point2);
+ }
+
+} // namespace Botan
+
+namespace std {
+
+// swaps the states of point1 and point2, does not throw!
+// cf. Meyers, Item 25
+template<> inline void
+swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y) { x.swap(y); }
+
+} // namespace std
+
+#endif
diff --git a/botan/build/botan/pow_mod.h b/botan/build/botan/pow_mod.h
new file mode 100644
index 0000000..6952dcd
--- /dev/null
+++ b/botan/build/botan/pow_mod.h
@@ -0,0 +1,93 @@
+/*
+* Modular Exponentiator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POWER_MOD_H__
+#define BOTAN_POWER_MOD_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+/*
+* Modular Exponentiator Interface
+*/
+class BOTAN_DLL Modular_Exponentiator
+ {
+ public:
+ virtual void set_base(const BigInt&) = 0;
+ virtual void set_exponent(const BigInt&) = 0;
+ virtual BigInt execute() const = 0;
+ virtual Modular_Exponentiator* copy() const = 0;
+ virtual ~Modular_Exponentiator() {}
+ };
+
+/*
+* Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Power_Mod
+ {
+ public:
+ enum Usage_Hints {
+ NO_HINTS = 0x0000,
+
+ BASE_IS_FIXED = 0x0001,
+ BASE_IS_SMALL = 0x0002,
+ BASE_IS_LARGE = 0x0004,
+ BASE_IS_2 = 0x0008,
+
+ EXP_IS_FIXED = 0x0100,
+ EXP_IS_SMALL = 0x0200,
+ EXP_IS_LARGE = 0x0400
+ };
+
+ void set_modulus(const BigInt&, Usage_Hints = NO_HINTS) const;
+ void set_base(const BigInt&) const;
+ void set_exponent(const BigInt&) const;
+
+ BigInt execute() const;
+
+ Power_Mod& operator=(const Power_Mod&);
+
+ Power_Mod(const BigInt& = 0, Usage_Hints = NO_HINTS);
+ Power_Mod(const Power_Mod&);
+ ~Power_Mod();
+ private:
+ mutable Modular_Exponentiator* core;
+ Usage_Hints hints;
+ };
+
+/*
+* Fixed Exponent Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Fixed_Exponent_Power_Mod : public Power_Mod
+ {
+ public:
+ BigInt operator()(const BigInt& b) const
+ { set_base(b); return execute(); }
+
+ Fixed_Exponent_Power_Mod() {}
+ Fixed_Exponent_Power_Mod(const BigInt&, const BigInt&,
+ Usage_Hints = NO_HINTS);
+ };
+
+/*
+* Fixed Base Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Fixed_Base_Power_Mod : public Power_Mod
+ {
+ public:
+ BigInt operator()(const BigInt& e) const
+ { set_exponent(e); return execute(); }
+
+ Fixed_Base_Power_Mod() {}
+ Fixed_Base_Power_Mod(const BigInt&, const BigInt&,
+ Usage_Hints = NO_HINTS);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/prf_ssl3.h b/botan/build/botan/prf_ssl3.h
new file mode 100644
index 0000000..165fc7c
--- /dev/null
+++ b/botan/build/botan/prf_ssl3.h
@@ -0,0 +1,27 @@
+/*
+* SSLv3 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSLV3_PRF_H__
+#define BOTAN_SSLV3_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* SSL3 PRF
+*/
+class BOTAN_DLL SSL3_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/prf_tls.h b/botan/build/botan/prf_tls.h
new file mode 100644
index 0000000..d212795
--- /dev/null
+++ b/botan/build/botan/prf_tls.h
@@ -0,0 +1,34 @@
+/*
+* TLS v1.0 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_PRF_H__
+#define BOTAN_TLS_PRF_H__
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* TLS PRF
+*/
+class BOTAN_DLL TLS_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ TLS_PRF();
+ ~TLS_PRF();
+ private:
+ MessageAuthenticationCode* hmac_md5;
+ MessageAuthenticationCode* hmac_sha1;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/prf_x942.h b/botan/build/botan/prf_x942.h
new file mode 100644
index 0000000..f957566
--- /dev/null
+++ b/botan/build/botan/prf_x942.h
@@ -0,0 +1,31 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X942_PRF_H__
+#define BOTAN_ANSI_X942_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* X9.42 PRF
+*/
+class BOTAN_DLL X942_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ X942_PRF(const std::string&);
+ private:
+ std::string key_wrap_oid;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pubkey.h b/botan/build/botan/pubkey.h
new file mode 100644
index 0000000..c73a54d
--- /dev/null
+++ b/botan/build/botan/pubkey.h
@@ -0,0 +1,392 @@
+/*
+* Public Key Interface
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_H__
+#define BOTAN_PUBKEY_H__
+
+#include <botan/pk_keys.h>
+#include <botan/symkey.h>
+#include <botan/rng.h>
+#include <botan/eme.h>
+#include <botan/emsa.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* The two types of signature format supported by Botan.
+*/
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/**
+* Public Key Encryptor
+*/
+class BOTAN_DLL PK_Encryptor
+ {
+ public:
+
+ /**
+ * Encrypt a message.
+ * @param in the message as a byte array
+ * @param length the length of the above byte array
+ * @param rng the random number source to use
+ * @return the encrypted message
+ */
+ SecureVector<byte> encrypt(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Encrypt a message.
+ * @param in the message
+ * @param rng the random number source to use
+ * @return the encrypted message
+ */
+ SecureVector<byte> encrypt(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Return the maximum allowed message size in bytes.
+ * @return the maximum message size in bytes
+ */
+ virtual u32bit maximum_input_size() const = 0;
+
+ virtual ~PK_Encryptor() {}
+ private:
+ virtual SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/**
+* Public Key Decryptor
+*/
+class BOTAN_DLL PK_Decryptor
+ {
+ public:
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext as a byte array
+ * @param length the length of the above byte array
+ * @return the decrypted message
+ */
+ SecureVector<byte> decrypt(const byte in[], u32bit length) const;
+
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext
+ * @return the decrypted message
+ */
+ SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const;
+
+ virtual ~PK_Decryptor() {}
+ private:
+ virtual SecureVector<byte> dec(const byte[], u32bit) const = 0;
+ };
+
+/**
+* Public Key Signer. Use the sign_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* generate the signature by finally calling signature().
+*/
+class BOTAN_DLL PK_Signer
+ {
+ public:
+ /**
+ * Sign a message.
+ * @param in the message to sign as a byte array
+ * @param length the length of the above byte array
+ * @param rng the rng to use
+ * @return the signature
+ */
+ SecureVector<byte> sign_message(const byte in[], u32bit length,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Sign a message.
+ * @param in the message to sign
+ * @param rng the rng to use
+ * @return the signature
+ */
+ SecureVector<byte> sign_message(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Add a message part (single byte).
+ * @param the byte to add
+ */
+ void update(byte in);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const byte in[], u32bit length);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const MemoryRegion<byte>& in);
+
+ /**
+ * Get the signature of the so far processed message (provided by the
+ * calls to update()).
+ * @param rng the rng to use
+ * @return the signature of the total message
+ */
+ SecureVector<byte> signature(RandomNumberGenerator& rng);
+
+ /**
+ * Set the output format of the signature.
+ * @param format the signature format to use
+ */
+ void set_output_format(Signature_Format format);
+
+ /**
+ * Construct a PK Signer.
+ * @param key the key to use inside this signer
+ * @param emsa the EMSA to use
+ * An example would be "EMSA1(SHA-224)".
+ */
+ PK_Signer(const PK_Signing_Key& key, EMSA* emsa);
+
+ ~PK_Signer() { delete emsa; }
+ private:
+ PK_Signer(const PK_Signer&);
+ PK_Signer& operator=(const PK_Signer&);
+
+ const PK_Signing_Key& key;
+ Signature_Format sig_format;
+ EMSA* emsa;
+ };
+
+/**
+* Public Key Verifier. Use the verify_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* verify the signature by finally calling check_signature().
+*/
+class BOTAN_DLL PK_Verifier
+ {
+ public:
+ /**
+ * Verify a signature.
+ * @param msg the message that the signature belongs to, as a byte array
+ * @param msg_length the length of the above byte array msg
+ * @param sig the signature as a byte array
+ * @param sig_length the length of the above byte array sig
+ * @return true if the signature is valid
+ */
+ bool verify_message(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length);
+ /**
+ * Verify a signature.
+ * @param msg the message that the signature belongs to
+ * @param sig the signature
+ * @return true if the signature is valid
+ */
+ bool verify_message(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig);
+
+ /**
+ * Add a message part (single byte) of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the byte to add
+ */
+ void update(byte msg_part);
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the new message part as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const byte msg_part[], u32bit length);
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the new message part
+ */
+ void update(const MemoryRegion<byte>& msg_part);
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified as a byte array
+ * @param length the length of the above byte array
+ * @return true if the signature is valid, false otherwise
+ */
+ bool check_signature(const byte sig[], u32bit length);
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified
+ * @return true if the signature is valid, false otherwise
+ */
+ bool check_signature(const MemoryRegion<byte>& sig);
+
+ /**
+ * Set the format of the signatures fed to this verifier.
+ * @param format the signature format to use
+ */
+ void set_input_format(Signature_Format format);
+
+ /**
+ * Construct a PK Verifier.
+ * @param emsa the EMSA to use
+ * An example would be new EMSA1(new SHA_224)
+ */
+ PK_Verifier(EMSA* emsa);
+
+ virtual ~PK_Verifier();
+ protected:
+ virtual bool validate_signature(const MemoryRegion<byte>&,
+ const byte[], u32bit) = 0;
+ virtual u32bit key_message_parts() const = 0;
+ virtual u32bit key_message_part_size() const = 0;
+
+ Signature_Format sig_format;
+ EMSA* emsa;
+ private:
+ PK_Verifier(const PK_Verifier&);
+ PK_Verifier& operator=(const PK_Verifier&);
+ };
+
+/*
+* Key Agreement
+*/
+class BOTAN_DLL PK_Key_Agreement
+ {
+ public:
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ /**
+ * Construct a PK Key Agreement.
+ * @param key the key to use
+ * @param kdf the KDF to use
+ */
+ PK_Key_Agreement(const PK_Key_Agreement_Key& key, KDF* kdf);
+
+ ~PK_Key_Agreement() { delete kdf; }
+ private:
+ PK_Key_Agreement(const PK_Key_Agreement_Key&);
+ PK_Key_Agreement& operator=(const PK_Key_Agreement&);
+
+ const PK_Key_Agreement_Key& key;
+ KDF* kdf;
+ };
+
+/**
+* Encryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor
+ {
+ public:
+ u32bit maximum_input_size() const;
+
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the decryptor
+ * @param eme the EME to use
+ */
+ PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& key,
+ EME* eme);
+
+ ~PK_Encryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&);
+ PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&);
+
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ const PK_Encrypting_Key& key;
+ const EME* encoder;
+ };
+
+/**
+* Decryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the encryptor
+ * @param eme the EME to use
+ */
+ PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& key,
+ EME* eme);
+
+ ~PK_Decryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&);
+ PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&);
+
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Decrypting_Key& key;
+ const EME* encoder;
+ };
+
+/**
+* Public Key Verifier with Message Recovery.
+*/
+class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the verifier
+ * @param emsa_name the name of the EMSA to use
+ */
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k,
+ EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {}
+
+ private:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&);
+ PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_with_MR_Key& key;
+ };
+
+/**
+* Public Key Verifier without Message Recovery
+*/
+class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the verifier
+ * @param emsa_name the name of the EMSA to use
+ */
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k,
+ EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {}
+
+ private:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&);
+ PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_wo_MR_Key& key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/pubkey_enums.h b/botan/build/botan/pubkey_enums.h
new file mode 100644
index 0000000..53e319f
--- /dev/null
+++ b/botan/build/botan/pubkey_enums.h
@@ -0,0 +1,77 @@
+/*
+* Enumerations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENUMS_H__
+#define BOTAN_ENUMS_H__
+
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/**
+* X.509v3 Key Constraints.
+*/
+enum Key_Constraints {
+ NO_CONSTRAINTS = 0,
+ DIGITAL_SIGNATURE = 32768,
+ NON_REPUDIATION = 16384,
+ KEY_ENCIPHERMENT = 8192,
+ DATA_ENCIPHERMENT = 4096,
+ KEY_AGREEMENT = 2048,
+ KEY_CERT_SIGN = 1024,
+ CRL_SIGN = 512,
+ ENCIPHER_ONLY = 256,
+ DECIPHER_ONLY = 128
+};
+
+/**
+* BER Decoding Function for key constraints
+*/
+namespace BER {
+
+void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&);
+
+}
+
+/**
+* X.509v2 CRL Reason Code.
+*/
+enum CRL_Code {
+ UNSPECIFIED = 0,
+ KEY_COMPROMISE = 1,
+ CA_COMPROMISE = 2,
+ AFFILIATION_CHANGED = 3,
+ SUPERSEDED = 4,
+ CESSATION_OF_OPERATION = 5,
+ CERTIFICATE_HOLD = 6,
+ REMOVE_FROM_CRL = 8,
+ PRIVLEDGE_WITHDRAWN = 9,
+ AA_COMPROMISE = 10,
+
+ DELETE_CRL_ENTRY = 0xFF00,
+ OCSP_GOOD = 0xFF01,
+ OCSP_UNKNOWN = 0xFF02
+};
+
+/*
+* Various Other Enumerations
+*/
+
+/**
+* The two types of X509 encoding supported by Botan.
+*/
+enum X509_Encoding { RAW_BER, PEM };
+
+/**
+* Value to encode in case of no path limit in the X509
+* BasicConstraints extension.
+*/
+static const u32bit NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
+
+}
+
+#endif
diff --git a/botan/build/botan/randpool.h b/botan/build/botan/randpool.h
new file mode 100644
index 0000000..b6a3add
--- /dev/null
+++ b/botan/build/botan/randpool.h
@@ -0,0 +1,53 @@
+/*
+* Randpool
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDPOOL_H__
+#define BOTAN_RANDPOOL_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+#include <botan/mac.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Randpool
+*/
+class BOTAN_DLL Randpool : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit bits_to_collect);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte input[], u32bit length);
+
+ Randpool(BlockCipher* cipher, MessageAuthenticationCode* mac,
+ u32bit pool_blocks = 32,
+ u32bit iterations_before_reseed = 128);
+
+ ~Randpool();
+ private:
+ void update_buffer();
+ void mix_pool();
+
+ u32bit ITERATIONS_BEFORE_RESEED, POOL_BLOCKS;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+
+ std::vector<EntropySource*> entropy_sources;
+ SecureVector<byte> pool, buffer, counter;
+ bool seeded;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rc2.h b/botan/build/botan/rc2.h
new file mode 100644
index 0000000..cb6f58f
--- /dev/null
+++ b/botan/build/botan/rc2.h
@@ -0,0 +1,37 @@
+/*
+* RC2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC2_H__
+#define BOTAN_RC2_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC2
+*/
+class BOTAN_DLL RC2 : public BlockCipher
+ {
+ public:
+ static byte EKB_code(u32bit);
+
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "RC2"; }
+ BlockCipher* clone() const { return new RC2; }
+ RC2() : BlockCipher(8, 1, 32) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 64> K;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rc5.h b/botan/build/botan/rc5.h
new file mode 100644
index 0000000..0832247
--- /dev/null
+++ b/botan/build/botan/rc5.h
@@ -0,0 +1,35 @@
+/*
+* RC5
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC5_H__
+#define BOTAN_RC5_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC5
+*/
+class BOTAN_DLL RC5 : public BlockCipher
+ {
+ public:
+ void clear() throw() { S.clear(); }
+ std::string name() const;
+ BlockCipher* clone() const { return new RC5(ROUNDS); }
+ RC5(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureVector<u32bit> S;
+ const u32bit ROUNDS;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rc6.h b/botan/build/botan/rc6.h
new file mode 100644
index 0000000..cb2800b
--- /dev/null
+++ b/botan/build/botan/rc6.h
@@ -0,0 +1,35 @@
+/*
+* RC6
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC6_H__
+#define BOTAN_RC6_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC6
+*/
+class BOTAN_DLL RC6 : public BlockCipher
+ {
+ public:
+ void clear() throw() { S.clear(); }
+ std::string name() const { return "RC6"; }
+ BlockCipher* clone() const { return new RC6; }
+ RC6() : BlockCipher(16, 1, 32) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 44> S;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/reducer.h b/botan/build/botan/reducer.h
new file mode 100644
index 0000000..d234e07
--- /dev/null
+++ b/botan/build/botan/reducer.h
@@ -0,0 +1,36 @@
+/*
+* Modular Reducer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MODARITH_H__
+#define BOTAN_MODARITH_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+/*
+* Modular Reducer
+*/
+class BOTAN_DLL Modular_Reducer
+ {
+ public:
+ BigInt multiply(const BigInt&, const BigInt&) const;
+ BigInt square(const BigInt&) const;
+ BigInt reduce(const BigInt&) const;
+
+ bool initialized() const { return (mod_words != 0); }
+
+ Modular_Reducer() { mod_words = 0; }
+ Modular_Reducer(const BigInt&);
+ private:
+ BigInt modulus, modulus_2, mu;
+ u32bit mod_words, mod2_words, mu_words;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rmd128.h b/botan/build/botan/rmd128.h
new file mode 100644
index 0000000..031ae57
--- /dev/null
+++ b/botan/build/botan/rmd128.h
@@ -0,0 +1,35 @@
+/*
+* RIPEMD-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RIPEMD_128_H__
+#define BOTAN_RIPEMD_128_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* RIPEMD-128
+*/
+class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "RIPEMD-128"; }
+ HashFunction* clone() const { return new RIPEMD_128; }
+ RIPEMD_128() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rmd160.h b/botan/build/botan/rmd160.h
new file mode 100644
index 0000000..f2babc5
--- /dev/null
+++ b/botan/build/botan/rmd160.h
@@ -0,0 +1,35 @@
+/*
+* RIPEMD-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RIPEMD_160_H__
+#define BOTAN_RIPEMD_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* RIPEMD-160
+*/
+class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "RIPEMD-160"; }
+ HashFunction* clone() const { return new RIPEMD_160; }
+ RIPEMD_160() : MDx_HashFunction(20, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 5> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rng.h b/botan/build/botan/rng.h
new file mode 100644
index 0000000..41904db
--- /dev/null
+++ b/botan/build/botan/rng.h
@@ -0,0 +1,103 @@
+/*
+* RandomNumberGenerator
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__
+#define BOTAN_RANDOM_NUMBER_GENERATOR_H__
+
+#include <botan/entropy_src.h>
+#include <botan/exceptn.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a random number (RNG) generator object.
+*/
+class BOTAN_DLL RandomNumberGenerator
+ {
+ public:
+ /**
+ * Create a seeded and active RNG object for general application use
+ */
+ static RandomNumberGenerator* make_rng();
+
+ /**
+ * Randomize a byte array.
+ * @param output the byte array to hold the random output.
+ * @param length the length of the byte array output.
+ */
+ virtual void randomize(byte output[], u32bit length) = 0;
+
+ /**
+ * Return a random byte
+ * @return random byte
+ */
+ byte next_byte();
+
+ /**
+ * Check whether this RNG is seeded.
+ * @return true if this RNG was already seeded, false otherwise.
+ */
+ virtual bool is_seeded() const { return true; }
+
+ /**
+ * Clear all internally held values of this RNG.
+ */
+ virtual void clear() throw() = 0;
+
+ /**
+ * Return the name of this object
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Seed this RNG using the entropy sources it contains.
+ * @param bits_to_collect is the number of bits of entropy to
+ attempt to gather from the entropy sources
+ */
+ virtual void reseed(u32bit bits_to_collect) = 0;
+
+ /**
+ * Add this entropy source to the RNG object
+ * @param source the entropy source which will be retained and used by RNG
+ */
+ virtual void add_entropy_source(EntropySource* source) = 0;
+
+ /**
+ * Add entropy to this RNG.
+ * @param in a byte array containg the entropy to be added
+ * @param length the length of the byte array in
+ */
+ virtual void add_entropy(const byte in[], u32bit length) = 0;
+
+ RandomNumberGenerator() {}
+ virtual ~RandomNumberGenerator() {}
+ private:
+ RandomNumberGenerator(const RandomNumberGenerator&) {}
+ RandomNumberGenerator& operator=(const RandomNumberGenerator&)
+ { return (*this); }
+ };
+
+/*
+* Null Random Number Generator
+*/
+class BOTAN_DLL Null_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit) { throw PRNG_Unseeded("Null_RNG"); }
+ void clear() throw() {}
+ std::string name() const { return "Null_RNG"; }
+
+ void reseed(u32bit) {}
+ bool is_seeded() const { return false; }
+ void add_entropy(const byte[], u32bit) {}
+ void add_entropy_source(EntropySource* es) { delete es; }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rotate.h b/botan/build/botan/rotate.h
new file mode 100644
index 0000000..c8f8d4a
--- /dev/null
+++ b/botan/build/botan/rotate.h
@@ -0,0 +1,30 @@
+/*
+* Word Rotation Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WORD_ROTATE_H__
+#define BOTAN_WORD_ROTATE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Word Rotation Functions
+*/
+template<typename T> inline T rotate_left(T input, u32bit rot)
+ {
+ return static_cast<T>((input << rot) | (input >> (8*sizeof(T)-rot)));;
+ }
+
+template<typename T> inline T rotate_right(T input, u32bit rot)
+ {
+ return static_cast<T>((input >> rot) | (input << (8*sizeof(T)-rot)));
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/rsa.h b/botan/build/botan/rsa.h
new file mode 100644
index 0000000..f07533a
--- /dev/null
+++ b/botan/build/botan/rsa.h
@@ -0,0 +1,88 @@
+/*
+* RSA
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RSA_H__
+#define BOTAN_RSA_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/**
+* RSA Public Key
+*/
+class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key,
+ public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RSA"; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RSA_PublicKey() {}
+ RSA_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/**
+* RSA Private Key class.
+*/
+class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
+ public PK_Decrypting_Key,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Default constructor, does not set any internal values. Use this
+ * constructor if you wish to decode a DER or PEM encoded key.
+ */
+ RSA_PrivateKey() {}
+
+ /**
+ * Construct a private key from the specified parameters.
+ * @param rng the random number generator to use
+ * @param prime1 the first prime
+ * @param prime2 the second prime
+ * @param exp the exponent
+ * @param d_exp if specified, this has to be d with
+ * exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to
+ * the constructor to calculate it.
+ * @param n if specified, this must be n = p * q. Leave it as 0
+ * if you wish to the constructor to calculate it.
+ */
+ RSA_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& p, const BigInt& q, const BigInt& e,
+ const BigInt& d = 0, const BigInt& n = 0);
+
+ /**
+ * Create a new private key with the specified bit length
+ * @param rng the random number generator to use
+ * @param bits the desired bit length of the private key
+ * @param exp the public exponent to be used
+ */
+ RSA_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp = 65537);
+ private:
+ BigInt private_op(const byte[], u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/rw.h b/botan/build/botan/rw.h
new file mode 100644
index 0000000..900e5eb
--- /dev/null
+++ b/botan/build/botan/rw.h
@@ -0,0 +1,56 @@
+/*
+* Rabin-Williams
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RW_H__
+#define BOTAN_RW_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/*
+* Rabin-Williams Public Key
+*/
+class BOTAN_DLL RW_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RW"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RW_PublicKey() {}
+ RW_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/*
+* Rabin-Williams Private Key
+*/
+class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ RW_PrivateKey() {}
+
+ RW_PrivateKey(RandomNumberGenerator&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt& = 0, const BigInt& = 0);
+
+ RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2);
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/s2k.h b/botan/build/botan/s2k.h
new file mode 100644
index 0000000..7af9251
--- /dev/null
+++ b/botan/build/botan/s2k.h
@@ -0,0 +1,102 @@
+/*
+* S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_S2K_H__
+#define BOTAN_S2K_H__
+
+#include <botan/symkey.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* S2K Interface
+*/
+class BOTAN_DLL S2K
+ {
+ public:
+ /**
+ * Create a copy of this object.
+ * @return an auto_ptr to a copy of this object
+ */
+ virtual S2K* clone() const = 0;
+
+ /**
+ * Get the algorithm name.
+ * @return the name of this S2K algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Clear this objects internal values.
+ */
+ virtual void clear() {}
+
+ /**
+ * Derive a key from a passphrase with this S2K object. It will use
+ * the salt value and number of iterations configured in this object.
+ * @param key_len the desired length of the key to produce
+ * @param passphrase the password to derive the key from
+ */
+ OctetString derive_key(u32bit key_len,
+ const std::string& passphrase) const;
+
+ /**
+ * Set the number of iterations for the one-way function during
+ * key generation.
+ * @param n the desired number of iterations
+ */
+ void set_iterations(u32bit n);
+
+ /**
+ * Set a new salt value.
+ * @param new_salt a byte array defining the new salt value
+ * @param len the length of the above byte array
+ */
+ void change_salt(const byte new_salt[], u32bit len);
+
+ /**
+ * Set a new salt value.
+ * @param new_salt the new salt value
+ */
+ void change_salt(const MemoryRegion<byte>& new_salt);
+
+ /**
+ * Create a new random salt value using the rng
+ * @param rng the random number generator to use
+ * @param len the desired length of the new salt value
+ */
+ void new_random_salt(RandomNumberGenerator& rng, u32bit len);
+
+ /**
+ * Get the number of iterations for the key derivation currently
+ * configured in this S2K object.
+ * @return the current number of iterations
+ */
+ u32bit iterations() const { return iter; }
+
+ /**
+ * Get the currently configured salt value of this S2K object.
+ * @return the current salt value
+ */
+ SecureVector<byte> current_salt() const { return salt; }
+
+ S2K() { iter = 0; }
+ virtual ~S2K() {}
+ private:
+ S2K(const S2K&) {}
+ S2K& operator=(const S2K&) { return (*this); }
+
+ virtual OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const = 0;
+ SecureVector<byte> salt;
+ u32bit iter;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/safer_sk.h b/botan/build/botan/safer_sk.h
new file mode 100644
index 0000000..e52c583
--- /dev/null
+++ b/botan/build/botan/safer_sk.h
@@ -0,0 +1,40 @@
+/*
+* SAFER-SK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SAFER_SK_H__
+#define BOTAN_SAFER_SK_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* SAFER-SK
+*/
+class BOTAN_DLL SAFER_SK : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const;
+ BlockCipher* clone() const;
+ SAFER_SK(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const byte EXP[256];
+ static const byte LOG[512];
+ static const byte BIAS[208];
+ static const byte KEY_INDEX[208];
+ SecureVector<byte> EK;
+ const u32bit ROUNDS;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/salsa20.h b/botan/build/botan/salsa20.h
new file mode 100644
index 0000000..3dbfddb
--- /dev/null
+++ b/botan/build/botan/salsa20.h
@@ -0,0 +1,41 @@
+/*
+* Salsa20
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SALSA20_H__
+#define BOTAN_SALSA20_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* Salsa20
+*/
+class BOTAN_DLL Salsa20 : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ StreamCipher* clone() const { return new Salsa20; }
+
+ void resync(const byte[], u32bit);
+
+ Salsa20();
+ ~Salsa20() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 16> state;
+
+ SecureBuffer<byte, 64> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/scan_name.h b/botan/build/botan/scan_name.h
new file mode 100644
index 0000000..9e7af40
--- /dev/null
+++ b/botan/build/botan/scan_name.h
@@ -0,0 +1,77 @@
+/**
+SCAN Name Abstraction
+(C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SCAN_NAME_H__
+#define BOTAN_SCAN_NAME_H__
+
+#include <botan/types.h>
+#include <string>
+#include <vector>
+#include <set>
+
+namespace Botan {
+
+/**
+A class encapsulating a SCAN name (similar to JCE conventions)
+http://www.users.zetnet.co.uk/hopwood/crypto/scan/
+*/
+class SCAN_Name
+ {
+ public:
+ /**
+ @param algo_spec A SCAN name
+ */
+ SCAN_Name(const std::string& algo_spec);
+
+ /**
+ @return the original input string
+ */
+ std::string as_string() const { return orig_algo_spec; }
+
+ /**
+ @return the algorithm name
+ */
+ std::string algo_name() const { return name[0]; }
+
+ /**
+ @return the number of arguments
+ */
+ u32bit arg_count() const { return name.size() - 1; }
+
+ /**
+ @return if the number of arguments is between lower and upper
+ */
+ bool arg_count_between(u32bit lower, u32bit upper) const
+ { return ((arg_count() >= lower) && (arg_count() <= upper)); }
+
+ /**
+ @param i which argument
+ @return the ith argument
+ */
+ std::string arg(u32bit i) const;
+
+ /**
+ @param i which argument
+ @param def_value the default value
+ @return the ith argument or the default value
+ */
+ std::string arg(u32bit i, const std::string& def_value) const;
+
+ /**
+ @param i which argument
+ @param def_value the default value
+ @return the ith argument as a u32bit, or the default value
+ */
+ u32bit arg_as_u32bit(u32bit i, u32bit def_value) const;
+ private:
+ std::string orig_algo_spec;
+ std::vector<std::string> name;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/secmem.h b/botan/build/botan/secmem.h
new file mode 100644
index 0000000..d64a376
--- /dev/null
+++ b/botan/build/botan/secmem.h
@@ -0,0 +1,438 @@
+/*
+* Secure Memory Buffers
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
+#define BOTAN_SECURE_MEMORY_BUFFERS_H__
+
+#include <botan/allocate.h>
+#include <botan/mem_ops.h>
+#include <algorithm>
+
+namespace Botan {
+
+/**
+* This class represents variable length memory buffers.
+*/
+template<typename T>
+class MemoryRegion
+ {
+ public:
+ /**
+ * Find out the size of the buffer, i.e. how many objects of type T it
+ * contains.
+ * @return the size of the buffer
+ */
+ u32bit size() const { return used; }
+
+ /**
+ * Find out whether this buffer is empty.
+ * @return true if the buffer is empty, false otherwise
+ */
+ bool is_empty() const { return (used == 0); }
+
+ /**
+ * Find out whether this buffer is non-empty
+ * @return true if the buffer is non-empty, false otherwise
+ */
+ bool has_items() const { return (used != 0); }
+
+ /**
+ * Get a pointer to the first element in the buffer.
+ * @return a pointer to the first element in the buffer
+ */
+ operator T* () { return buf; }
+
+ /**
+ * Get a constant pointer to the first element in the buffer.
+ * @return a constant pointer to the first element in the buffer
+ */
+ operator const T* () const { return buf; }
+
+ /**
+ * Get a pointer to the first element in the buffer.
+ * @return a pointer to the first element in the buffer
+ */
+ T* begin() { return buf; }
+
+ /**
+ * Get a constant pointer to the first element in the buffer.
+ * @return a constant pointer to the first element in the buffer
+ */
+ const T* begin() const { return buf; }
+
+ /**
+ * Get a pointer to the last element in the buffer.
+ * @return a pointer to the last element in the buffer
+ */
+ T* end() { return (buf + size()); }
+
+ /**
+ * Get a constant pointer to the last element in the buffer.
+ * @return a constant pointer to the last element in the buffer
+ */
+ const T* end() const { return (buf + size()); }
+
+ /**
+ * Check two buffers for equality.
+ * @return true iff the content of both buffers is byte-wise equal
+ */
+ bool operator==(const MemoryRegion<T>& other) const
+ {
+ return (size() == other.size() &&
+ same_mem(buf, other.buf, size()));
+ }
+
+ /**
+ * Compare two buffers lexicographically.
+ * @return true if this buffer is lexicographically smaller than other.
+ */
+ bool operator<(const MemoryRegion<T>& other) const;
+
+ /**
+ * Check two buffers for inequality.
+ * @return false if the content of both buffers is byte-wise equal, true
+ * otherwise.
+ */
+ bool operator!=(const MemoryRegion<T>& in) const
+ { return (!(*this == in)); }
+
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * The former contents of *this are discarded.
+ * @param in the buffer to copy the contents from.
+ * @return a reference to *this
+ */
+ MemoryRegion<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * The use of this function is discouraged because of the risk of memory
+ * errors. Use MemoryRegion<T>::set()
+ * instead.
+ * Copy the contents of an array of objects of type T into this buffer.
+ * The former contents of *this are discarded.
+ * The length of *this must be at least n, otherwise memory errors occur.
+ * @param in the array to copy the contents from
+ * @param n the length of in
+ */
+ void copy(const T in[], u32bit n)
+ { copy(0, in, n); }
+
+ /**
+ * The use of this function is discouraged because of the risk of memory
+ * errors. Use MemoryRegion<T>::set()
+ * instead.
+ * Copy the contents of an array of objects of type T into this buffer.
+ * The former contents of *this are discarded.
+ * The length of *this must be at least n, otherwise memory errors occur.
+ * @param off the offset position inside this buffer to start inserting
+ * the copied bytes
+ * @param in the array to copy the contents from
+ * @param n the length of in
+ */
+ void copy(u32bit off, const T in[], u32bit n)
+ { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); }
+
+ /**
+ * Set the contents of this according to the argument. The size of
+ * *this is increased if necessary.
+ * @param in the array of objects of type T to copy the contents from
+ * @param n the size of array in
+ */
+ void set(const T in[], u32bit n) { create(n); copy(in, n); }
+
+ /**
+ * Set the contents of this according to the argument. The size of
+ * *this is increased if necessary.
+ * @param in the buffer to copy the contents from
+ */
+ void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); }
+
+ /**
+ * Append data to the end of this buffer.
+ * @param data the array containing the data to append
+ * @param n the size of the array data
+ */
+ void append(const T data[], u32bit n)
+ { grow_to(size()+n); copy(size() - n, data, n); }
+
+ /**
+ * Append a single element.
+ * @param x the element to append
+ */
+ void append(T x) { append(&x, 1); }
+
+ /**
+ * Append data to the end of this buffer.
+ * @param data the buffer containing the data to append
+ */
+ void append(const MemoryRegion<T>& x) { append(x.begin(), x.size()); }
+
+ /**
+ * Zeroise the bytes of this buffer. The length remains unchanged.
+ */
+ void clear() { clear_mem(buf, allocated); }
+
+ /**
+ * Reset this buffer to an empty buffer with size zero.
+ */
+ void destroy() { create(0); }
+
+ /**
+ * Reset this buffer to a buffer of specified length. The content will be
+ * initialized to zero bytes.
+ * @param n the new length of the buffer
+ */
+ void create(u32bit n);
+
+ /**
+ * Preallocate memory, so that this buffer can grow up to size n without
+ * having to perform any actual memory allocations. (This is
+ * the same principle as for std::vector::reserve().)
+ */
+ void grow_to(u32bit N);
+
+ /**
+ * Swap this buffer with another object.
+ */
+ void swap(MemoryRegion<T>& other);
+
+ ~MemoryRegion() { deallocate(buf, allocated); }
+ protected:
+ MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; }
+ MemoryRegion(const MemoryRegion<T>& other)
+ {
+ buf = 0;
+ used = allocated = 0;
+ alloc = other.alloc;
+ set(other.buf, other.used);
+ }
+
+ void init(bool locking, u32bit length = 0)
+ { alloc = Allocator::get(locking); create(length); }
+ private:
+ T* allocate(u32bit n)
+ {
+ return static_cast<T*>(alloc->allocate(sizeof(T)*n));
+ }
+
+ void deallocate(T* p, u32bit n)
+ { alloc->deallocate(p, sizeof(T)*n); }
+
+ T* buf;
+ u32bit used;
+ u32bit allocated;
+ Allocator* alloc;
+ };
+
+/*
+* Create a new buffer
+*/
+template<typename T>
+void MemoryRegion<T>::create(u32bit n)
+ {
+ if(n <= allocated) { clear(); used = n; return; }
+ deallocate(buf, allocated);
+ buf = allocate(n);
+ allocated = used = n;
+ }
+
+/*
+* Increase the size of the buffer
+*/
+template<typename T>
+void MemoryRegion<T>::grow_to(u32bit n)
+ {
+ if(n > used && n <= allocated)
+ {
+ clear_mem(buf + used, n - used);
+ used = n;
+ return;
+ }
+ else if(n > allocated)
+ {
+ T* new_buf = allocate(n);
+ copy_mem(new_buf, buf, used);
+ deallocate(buf, allocated);
+ buf = new_buf;
+ allocated = used = n;
+ }
+ }
+
+/*
+* Compare this buffer with another one
+*/
+template<typename T>
+bool MemoryRegion<T>::operator<(const MemoryRegion<T>& in) const
+ {
+ if(size() < in.size()) return true;
+ if(size() > in.size()) return false;
+
+ for(u32bit j = 0; j != size(); j++)
+ {
+ if(buf[j] < in[j]) return true;
+ if(buf[j] > in[j]) return false;
+ }
+
+ return false;
+ }
+
+/*
+* Swap this buffer with another one
+*/
+template<typename T>
+void MemoryRegion<T>::swap(MemoryRegion<T>& x)
+ {
+ std::swap(buf, x.buf);
+ std::swap(used, x.used);
+ std::swap(allocated, x.allocated);
+ std::swap(alloc, x.alloc);
+ }
+
+/**
+* This class represents variable length buffers that do not
+* make use of memory locking.
+*/
+template<typename T>
+class MemoryVector : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ MemoryVector<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the specified length.
+ * @param n the length of the buffer to create.
+
+ */
+ MemoryVector(u32bit n = 0) { MemoryRegion<T>::init(false, n); }
+
+ /**
+ * Create a buffer with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the arry in
+ */
+ MemoryVector(const T in[], u32bit n)
+ { MemoryRegion<T>::init(false); set(in, n); }
+
+ /**
+ * Copy constructor.
+ */
+ MemoryVector(const MemoryRegion<T>& in)
+ { MemoryRegion<T>::init(false); set(in); }
+
+ /**
+ * Create a buffer whose content is the concatenation of two other
+ * buffers.
+ * @param in1 the first part of the new contents
+ * @param in2 the contents to be appended to in1
+ */
+ MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
+ { MemoryRegion<T>::init(false); set(in1); append(in2); }
+ };
+
+/**
+* This class represents variable length buffers using the operating
+* systems capability to lock memory, i.e. keeping it from being
+* swapped out to disk. In this way, a security hole allowing attackers
+* to find swapped out secret keys is closed. Please refer to
+* Botan::InitializerOptions::secure_memory() for restrictions and
+* further details.
+*/
+template<typename T>
+class SecureVector : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ SecureVector<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the specified length.
+ * @param n the length of the buffer to create.
+
+ */
+ SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); }
+
+ /**
+ * Create a buffer with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the array in
+ */
+ SecureVector(const T in[], u32bit n)
+ { MemoryRegion<T>::init(true); set(in, n); }
+
+ /**
+ * Create a buffer with contents specified contents.
+ * @param in the buffer holding the contents that will be
+ * copied into the newly created buffer.
+ */
+ SecureVector(const MemoryRegion<T>& in)
+ { MemoryRegion<T>::init(true); set(in); }
+
+ /**
+ * Create a buffer whose content is the concatenation of two other
+ * buffers.
+ * @param in1 the first part of the new contents
+ * @param in2 the contents to be appended to in1
+ */
+ SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
+ { MemoryRegion<T>::init(true); set(in1); append(in2); }
+ };
+
+/**
+* This class represents fixed length buffers using the operating
+* systems capability to lock memory, i.e. keeping it from being
+* swapped out to disk. In this way, a security hole allowing attackers
+* to find swapped out secret keys is closed. Please refer to
+* Botan::InitializerOptions::secure_memory() for restrictions and
+* further details.
+*/
+template<typename T, u32bit L>
+class SecureBuffer : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the length L.
+ */
+ SecureBuffer() { MemoryRegion<T>::init(true, L); }
+
+ /**
+ * Create a buffer of size L with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the array in
+ */
+ SecureBuffer(const T in[], u32bit n)
+ { MemoryRegion<T>::init(true, L); copy(in, n); }
+ private:
+ SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/secqueue.h b/botan/build/botan/secqueue.h
new file mode 100644
index 0000000..fc1fc21
--- /dev/null
+++ b/botan/build/botan/secqueue.h
@@ -0,0 +1,43 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SECURE_QUEUE_H__
+#define BOTAN_SECURE_QUEUE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* SecureQueue
+*/
+class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit = 0) const;
+
+ bool end_of_data() const;
+ u32bit size() const;
+ bool attachable() { return false; }
+
+ SecureQueue& operator=(const SecureQueue&);
+ SecureQueue();
+ SecureQueue(const SecureQueue&);
+ ~SecureQueue() { destroy(); }
+ private:
+ void destroy();
+ class SecureQueueNode* head;
+ class SecureQueueNode* tail;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/seed.h b/botan/build/botan/seed.h
new file mode 100644
index 0000000..54c25d5
--- /dev/null
+++ b/botan/build/botan/seed.h
@@ -0,0 +1,43 @@
+/*
+* SEED
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SEED_H__
+#define BOTAN_SEED_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* SEED
+*/
+class BOTAN_DLL SEED : public BlockCipher
+ {
+ public:
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "SEED"; }
+ BlockCipher* clone() const { return new SEED; }
+ SEED() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ class G_FUNC
+ {
+ public:
+ u32bit operator()(u32bit) const;
+ private:
+ static const u32bit S0[256], S1[256], S2[256], S3[256];
+ };
+
+ SecureBuffer<u32bit, 32> K;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/selftest.h b/botan/build/botan/selftest.h
new file mode 100644
index 0000000..9e36d22
--- /dev/null
+++ b/botan/build/botan/selftest.h
@@ -0,0 +1,22 @@
+/*
+* Startup Self Test
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SELF_TESTS_H__
+#define BOTAN_SELF_TESTS_H__
+
+#include <botan/algo_factory.h>
+
+namespace Botan {
+
+/*
+* Self Tests
+*/
+BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af);
+
+}
+
+#endif
diff --git a/botan/build/botan/serpent.h b/botan/build/botan/serpent.h
new file mode 100644
index 0000000..5b9be25
--- /dev/null
+++ b/botan/build/botan/serpent.h
@@ -0,0 +1,35 @@
+/*
+* Serpent
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SERPENT_H__
+#define BOTAN_SERPENT_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Serpent
+*/
+class BOTAN_DLL Serpent : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "Serpent"; }
+ BlockCipher* clone() const { return new Serpent; }
+ Serpent() : BlockCipher(16, 16, 32, 8) {}
+ protected:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 132> round_key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/sha160.h b/botan/build/botan/sha160.h
new file mode 100644
index 0000000..232cf03
--- /dev/null
+++ b/botan/build/botan/sha160.h
@@ -0,0 +1,38 @@
+/*
+* SHA-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_H__
+#define BOTAN_SHA_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-160
+*/
+class BOTAN_DLL SHA_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-160"; }
+ HashFunction* clone() const { return new SHA_160; }
+ SHA_160();
+
+ protected:
+ SHA_160(u32bit W_size);
+
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 5> digest;
+ SecureVector<u32bit> W;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/sha2_32.h b/botan/build/botan/sha2_32.h
new file mode 100644
index 0000000..05083d1
--- /dev/null
+++ b/botan/build/botan/sha2_32.h
@@ -0,0 +1,59 @@
+/*
+* SHA-{224,256}
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_256_H__
+#define BOTAN_SHA_256_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-{224,256} Base
+*/
+class BOTAN_DLL SHA_224_256_BASE : public MDx_HashFunction
+ {
+ protected:
+ void clear() throw();
+ SHA_224_256_BASE(u32bit out) :
+ MDx_HashFunction(out, 64, true, true) { clear(); }
+
+ SecureBuffer<u32bit, 64> W;
+ SecureBuffer<u32bit, 8> digest;
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+ };
+
+/*
+* SHA-224
+*/
+class BOTAN_DLL SHA_224 : public SHA_224_256_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-224"; }
+ HashFunction* clone() const { return new SHA_224; }
+ SHA_224() : SHA_224_256_BASE(28) { clear(); }
+ };
+
+/*
+* SHA-256
+*/
+class BOTAN_DLL SHA_256 : public SHA_224_256_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-256"; }
+ HashFunction* clone() const { return new SHA_256; }
+ SHA_256() : SHA_224_256_BASE(32) { clear (); }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/sha2_64.h b/botan/build/botan/sha2_64.h
new file mode 100644
index 0000000..dcc6dc8
--- /dev/null
+++ b/botan/build/botan/sha2_64.h
@@ -0,0 +1,60 @@
+/*
+* SHA-{384,512}
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_64BIT_H__
+#define BOTAN_SHA_64BIT_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-{384,512} Base
+*/
+class BOTAN_DLL SHA_384_512_BASE : public MDx_HashFunction
+ {
+ protected:
+ void clear() throw();
+
+ SHA_384_512_BASE(u32bit out) :
+ MDx_HashFunction(out, 128, true, true, 16) {}
+
+ SecureBuffer<u64bit, 8> digest;
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u64bit, 80> W;
+ };
+
+/*
+* SHA-384
+*/
+class BOTAN_DLL SHA_384 : public SHA_384_512_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-384"; }
+ HashFunction* clone() const { return new SHA_384; }
+ SHA_384() : SHA_384_512_BASE(48) { clear(); }
+ };
+
+/*
+* SHA-512
+*/
+class BOTAN_DLL SHA_512 : public SHA_384_512_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-512"; }
+ HashFunction* clone() const { return new SHA_512; }
+ SHA_512() : SHA_384_512_BASE(64) { clear(); }
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/signed_obj.h b/botan/build/botan/signed_obj.h
new file mode 100644
index 0000000..3c233d2
--- /dev/null
+++ b/botan/build/botan/signed_obj.h
@@ -0,0 +1,93 @@
+/*
+* EAC SIGNED Object
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_SIGNED_OBJECT_H__
+#define BOTAN_EAC_SIGNED_OBJECT_H__
+
+#include <botan/asn1_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/freestore.h>
+#include <botan/pipe.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents abstract signed EAC object
+*/
+class BOTAN_DLL EAC_Signed_Object
+ {
+ public:
+ /**
+ * Get the TBS (to-be-signed) data in this object.
+ * @return the DER encoded TBS data of this object
+ */
+ virtual SecureVector<byte> tbs_data() const = 0;
+
+ /**
+ * Get the signature of this object as a concatenation, i.e. if the
+ * signature consists of multiple parts (like in the case of ECDSA)
+ * these will be concatenated.
+ * @return the signature as a concatenation of its parts
+ */
+
+ /*
+ NOTE: this is here only because abstract signature objects have
+ not yet been introduced
+ */
+ virtual SecureVector<byte> get_concat_sig() const = 0;
+
+ /**
+ * Get the signature algorithm identifier used to sign this object.
+ * @result the signature algorithm identifier
+ */
+ AlgorithmIdentifier signature_algorithm() const;
+
+ /**
+ * Check the signature of this object.
+ * @param key the public key associated with this signed object
+ * @return true if the signature was created by the private key
+ * associated with this public key
+ */
+ virtual bool check_signature(class Public_Key&) const = 0;
+
+ /**
+ * Write this object DER encoded into a specified pipe.
+ * @param pipe the pipe to write the encoded object to
+ * @param enc the encoding type to use
+ */
+ virtual void encode(Pipe&, X509_Encoding = PEM) const = 0;
+
+ /**
+ * BER encode this object.
+ * @return the result containing the BER representation of this object.
+ */
+ SecureVector<byte> BER_encode() const;
+
+ /**
+ * PEM encode this object.
+ * @return the result containing the PEM representation of this object.
+ */
+ std::string PEM_encode() const;
+
+ virtual ~EAC_Signed_Object() {}
+ protected:
+ void do_decode();
+ EAC_Signed_Object() {}
+
+ AlgorithmIdentifier sig_algo;
+ SecureVector<byte> tbs_bits;
+ std::string PEM_label_pref;
+ std::vector<std::string> PEM_labels_allowed;
+ private:
+ virtual void force_decode() = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/skein_512.h b/botan/build/botan/skein_512.h
new file mode 100644
index 0000000..fa558fc
--- /dev/null
+++ b/botan/build/botan/skein_512.h
@@ -0,0 +1,41 @@
+/**
+* The Skein-512 hash function
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SKEIN_512_H__
+#define BOTAN_SKEIN_512_H__
+
+#include <botan/secmem.h>
+#include <botan/hash.h>
+#include <string>
+
+namespace Botan {
+
+class BOTAN_DLL Skein_512 : public HashFunction
+ {
+ public:
+ Skein_512(u32bit output_bits = 512,
+ const std::string& personalization = "");
+
+ HashFunction* clone() const;
+ std::string name() const;
+ void clear() throw();
+ private:
+ void add_data(const byte input[], u32bit length);
+ void final_result(byte out[]);
+
+ std::string personalization;
+ u32bit output_bits;
+ SecureBuffer<u64bit, 9> H;
+ SecureBuffer<u64bit, 3> T;
+
+ SecureBuffer<byte, 64> buffer;
+ u32bit buf_pos;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/skipjack.h b/botan/build/botan/skipjack.h
new file mode 100644
index 0000000..231cd9c
--- /dev/null
+++ b/botan/build/botan/skipjack.h
@@ -0,0 +1,38 @@
+/*
+* Skipjack
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SKIPJACK_H__
+#define BOTAN_SKIPJACK_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Skipjack
+*/
+class BOTAN_DLL Skipjack : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Skipjack"; }
+ BlockCipher* clone() const { return new Skipjack; }
+ Skipjack() : BlockCipher(8, 10) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ void step_A(u16bit&, u16bit&, u32bit) const;
+ void step_B(u16bit&, u16bit&, u32bit) const;
+ void step_Ai(u16bit&, u16bit&, u32bit) const;
+ void step_Bi(u16bit&, u16bit&, u32bit) const;
+ SecureBuffer<byte, 256> FTABLE[10];
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/square.h b/botan/build/botan/square.h
new file mode 100644
index 0000000..94a1fc3
--- /dev/null
+++ b/botan/build/botan/square.h
@@ -0,0 +1,52 @@
+/*
+* Square
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SQUARE_H__
+#define BOTAN_SQUARE_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Square
+*/
+class BOTAN_DLL Square : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Square"; }
+ BlockCipher* clone() const { return new Square; }
+ Square() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void transform(u32bit[4]);
+
+ static const byte SE[256];
+ static const byte SD[256];
+ static const byte Log[256];
+ static const byte ALog[255];
+
+ static const u32bit TE0[256];
+ static const u32bit TE1[256];
+ static const u32bit TE2[256];
+ static const u32bit TE3[256];
+ static const u32bit TD0[256];
+ static const u32bit TD1[256];
+ static const u32bit TD2[256];
+ static const u32bit TD3[256];
+
+ SecureBuffer<u32bit, 28> EK, DK;
+ SecureBuffer<byte, 32> ME, MD;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/ssl3_mac.h b/botan/build/botan/ssl3_mac.h
new file mode 100644
index 0000000..dcaf7f4
--- /dev/null
+++ b/botan/build/botan/ssl3_mac.h
@@ -0,0 +1,39 @@
+/*
+* SSL3-MAC
+* (C) 1999-2004 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSL3_MAC_H__
+#define BOTAN_SSL3_MAC_H__
+
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* SSL3-MAC
+*/
+class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ SSL3_MAC(HashFunction*);
+ ~SSL3_MAC() { delete hash; }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ HashFunction* hash;
+ SecureVector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/stl_util.h b/botan/build/botan/stl_util.h
new file mode 100644
index 0000000..18c8b14
--- /dev/null
+++ b/botan/build/botan/stl_util.h
@@ -0,0 +1,86 @@
+/*
+* STL Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_STL_UTIL_H__
+#define BOTAN_STL_UTIL_H__
+
+#include <map>
+
+namespace Botan {
+
+/*
+* Copy-on-Predicate Algorithm
+*/
+template<typename InputIterator, typename OutputIterator, typename Predicate>
+OutputIterator copy_if(InputIterator current, InputIterator end,
+ OutputIterator dest, Predicate copy_p)
+ {
+ while(current != end)
+ {
+ if(copy_p(*current))
+ *dest++ = *current;
+ ++current;
+ }
+ return dest;
+ }
+
+/*
+* Searching through a std::map
+*/
+template<typename K, typename V>
+inline V search_map(const std::map<K, V>& mapping,
+ const K& key,
+ const V& null_result = V())
+ {
+ typename std::map<K, V>::const_iterator i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return i->second;
+ }
+
+template<typename K, typename V, typename R>
+inline R search_map(const std::map<K, V>& mapping, const K& key,
+ const R& null_result, const R& found_result)
+ {
+ typename std::map<K, V>::const_iterator i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return found_result;
+ }
+
+/*
+* Function adaptor for delete operation
+*/
+template<class T>
+class del_fun : public std::unary_function<T, void>
+ {
+ public:
+ void operator()(T* ptr) { delete ptr; }
+ };
+
+/*
+* Delete the second half of a pair of objects
+*/
+template<typename Pair>
+void delete2nd(Pair& pair)
+ {
+ delete pair.second;
+ }
+
+/*
+* Insert a key/value pair into a multimap
+*/
+template<typename K, typename V>
+void multimap_insert(std::multimap<K, V>& multimap,
+ const K& key, const V& value)
+ {
+ multimap.insert(std::make_pair(key, value));
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/stream_cipher.h b/botan/build/botan/stream_cipher.h
new file mode 100644
index 0000000..8ea3591
--- /dev/null
+++ b/botan/build/botan/stream_cipher.h
@@ -0,0 +1,92 @@
+/**
+* Stream Cipher
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_STREAM_CIPHER_H__
+#define BOTAN_STREAM_CIPHER_H__
+
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/*
+* Stream Cipher
+*/
+class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
+ {
+ public:
+ const u32bit IV_LENGTH;
+
+ /**
+ * Encrypt a message.
+ * @param i the plaintext
+ * @param o the byte array to hold the output, i.e. the ciphertext
+ * @param len the length of both i and o
+ */
+ void encrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+
+ /**
+ * Decrypt a message.
+ * @param i the ciphertext to decrypt
+ * @param o the byte array to hold the output, i.e. the plaintext
+ * @param len the length of both i and o
+ */
+ void decrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+
+ /**
+ * Encrypt a message.
+ * @param in the plaintext as input, after the function has
+ * returned it will hold the ciphertext
+
+ * @param len the length of in
+ */
+ void encrypt(byte in[], u32bit len) { cipher(in, in, len); }
+
+ /**
+ * Decrypt a message.
+ * @param in the ciphertext as input, after the function has
+ * returned it will hold the plaintext
+ * @param len the length of in
+ */
+ void decrypt(byte in[], u32bit len) { cipher(in, in, len); }
+
+ /**
+ * Resync the cipher using the IV
+ * @param iv the initialization vector
+ * @param iv_len the length of the IV in bytes
+ */
+ virtual void resync(const byte iv[], u32bit iv_len);
+
+ /**
+ * Seek ahead in the stream.
+ * @param len the length to seek ahead.
+ */
+ virtual void seek(u32bit len);
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual StreamCipher* clone() const = 0;
+
+ /**
+ * Zeroize internal state
+ */
+ virtual void clear() throw() = 0;
+
+ StreamCipher(u32bit key_min, u32bit key_max = 0,
+ u32bit key_mod = 1,
+ u32bit iv_len = 0) :
+ SymmetricAlgorithm(key_min, key_max, key_mod),
+ IV_LENGTH(iv_len) {}
+
+ virtual ~StreamCipher() {}
+ private:
+ virtual void cipher(const byte[], byte[], u32bit) = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/sym_algo.h b/botan/build/botan/sym_algo.h
new file mode 100644
index 0000000..1c8b816
--- /dev/null
+++ b/botan/build/botan/sym_algo.h
@@ -0,0 +1,101 @@
+/**
+* Symmetric Algorithm Base Class
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SYMMETRIC_ALGORITHM_H__
+#define BOTAN_SYMMETRIC_ALGORITHM_H__
+
+#include <botan/types.h>
+#include <botan/exceptn.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+/**
+* This class represents a symmetric algorithm object.
+*/
+class BOTAN_DLL SymmetricAlgorithm
+ {
+ public:
+
+ /**
+ * The maximum allowed key length.
+ */
+ const u32bit MAXIMUM_KEYLENGTH;
+
+ /**
+ * The minimal allowed key length.
+ */
+ const u32bit MINIMUM_KEYLENGTH;
+
+ /**
+ * A valid keylength is a multiple of this value.
+ */
+ const u32bit KEYLENGTH_MULTIPLE;
+
+ /**
+ * The name of the algorithm.
+ * @return the name of the algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Set the symmetric key of this object.
+ * @param key the SymmetricKey to be set.
+ */
+ void set_key(const SymmetricKey& key) throw(Invalid_Key_Length)
+ { set_key(key.begin(), key.length()); }
+
+ /**
+ * Set the symmetric key of this object.
+ * @param key the to be set as a byte array.
+ * @param the length of the byte array.
+ */
+ void set_key(const byte key[], u32bit length) throw(Invalid_Key_Length)
+ {
+ if(!valid_keylength(length))
+ throw Invalid_Key_Length(name(), length);
+ key_schedule(key, length);
+ }
+
+ /**
+ * Check whether a given key length is valid for this algorithm.
+ * @param length the key length to be checked.
+ * @return true if the key length is valid.
+ */
+ bool valid_keylength(u32bit length) const
+ {
+ return ((length >= MINIMUM_KEYLENGTH) &&
+ (length <= MAXIMUM_KEYLENGTH) &&
+ (length % KEYLENGTH_MULTIPLE == 0));
+ }
+
+ /**
+ * Construct a SymmetricAlgorithm.
+ * @param key_min the minimum allowed key length
+ * @param key_max the maximum allowed key length
+ * @param key_mod any valid key length must be a multiple of this value
+ */
+ SymmetricAlgorithm(u32bit key_min, u32bit key_max, u32bit key_mod) :
+ MAXIMUM_KEYLENGTH(key_max ? key_max : key_min),
+ MINIMUM_KEYLENGTH(key_min),
+ KEYLENGTH_MULTIPLE(key_mod)
+ {}
+
+ virtual ~SymmetricAlgorithm() {}
+ private:
+ virtual void key_schedule(const byte[], u32bit) = 0;
+ };
+
+/**
+* The two possible directions for cipher filters, determining whether they
+* actually perform encryption or decryption.
+*/
+enum Cipher_Dir { ENCRYPTION, DECRYPTION };
+
+}
+
+#endif
diff --git a/botan/build/botan/symkey.h b/botan/build/botan/symkey.h
new file mode 100644
index 0000000..5504297
--- /dev/null
+++ b/botan/build/botan/symkey.h
@@ -0,0 +1,62 @@
+/*
+* OctetString
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SYMKEY_H__
+#define BOTAN_SYMKEY_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Octet String
+*/
+class BOTAN_DLL OctetString
+ {
+ public:
+ u32bit length() const { return bits.size(); }
+ SecureVector<byte> bits_of() const { return bits; }
+
+ const byte* begin() const { return bits.begin(); }
+ const byte* end() const { return bits.end(); }
+
+ std::string as_string() const;
+
+ OctetString& operator^=(const OctetString&);
+
+ void set_odd_parity();
+
+ void change(const std::string&);
+ void change(const byte[], u32bit);
+ void change(const MemoryRegion<byte>& in) { bits = in; }
+
+ OctetString(class RandomNumberGenerator&, u32bit len);
+ OctetString(const std::string& str = "") { change(str); }
+ OctetString(const byte in[], u32bit len) { change(in, len); }
+ OctetString(const MemoryRegion<byte>& in) { change(in); }
+ private:
+ SecureVector<byte> bits;
+ };
+
+/*
+* Operations on Octet Strings
+*/
+BOTAN_DLL bool operator==(const OctetString&, const OctetString&);
+BOTAN_DLL bool operator!=(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator+(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator^(const OctetString&, const OctetString&);
+
+/*
+* Alternate Names
+*/
+typedef OctetString SymmetricKey;
+typedef OctetString InitializationVector;
+
+}
+
+#endif
diff --git a/botan/build/botan/tea.h b/botan/build/botan/tea.h
new file mode 100644
index 0000000..8ddf3e3
--- /dev/null
+++ b/botan/build/botan/tea.h
@@ -0,0 +1,34 @@
+/*
+* TEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TEA_H__
+#define BOTAN_TEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* TEA
+*/
+class BOTAN_DLL TEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "TEA"; }
+ BlockCipher* clone() const { return new TEA; }
+ TEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u32bit, 4> K;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/tiger.h b/botan/build/botan/tiger.h
new file mode 100644
index 0000000..63184a9
--- /dev/null
+++ b/botan/build/botan/tiger.h
@@ -0,0 +1,44 @@
+/*
+* Tiger
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIGER_H__
+#define BOTAN_TIGER_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* Tiger
+*/
+class BOTAN_DLL Tiger : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ HashFunction* clone() const { return new Tiger(OUTPUT_LENGTH); }
+ Tiger(u32bit = 24, u32bit = 3);
+ private:
+ void compress_n(const byte[], u32bit block);
+ void copy_out(byte[]);
+
+ static void pass(u64bit&, u64bit&, u64bit&, u64bit[8], byte);
+ static void mix(u64bit[8]);
+
+ static const u64bit SBOX1[256];
+ static const u64bit SBOX2[256];
+ static const u64bit SBOX3[256];
+ static const u64bit SBOX4[256];
+
+ SecureBuffer<u64bit, 8> X;
+ SecureBuffer<u64bit, 3> digest;
+ const u32bit PASS;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/timer.h b/botan/build/botan/timer.h
new file mode 100644
index 0000000..b6e8ef4
--- /dev/null
+++ b/botan/build/botan/timer.h
@@ -0,0 +1,45 @@
+/**
+* Timestamp Functions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMERS_H__
+#define BOTAN_TIMERS_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Timer Interface
+*/
+class BOTAN_DLL Timer : public EntropySource
+ {
+ public:
+ /**
+ @return nanoseconds resolution timestamp, unknown epoch
+ */
+ virtual u64bit clock() const = 0;
+
+ void poll(Entropy_Accumulator& accum);
+
+ virtual ~Timer() {}
+ protected:
+ static u64bit combine_timers(u32bit, u32bit, u32bit);
+ };
+
+/**
+* ANSI Clock Timer
+*/
+class BOTAN_DLL ANSI_Clock_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "ANSI clock"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/tm_posix.h b/botan/build/botan/tm_posix.h
new file mode 100644
index 0000000..8bedccf
--- /dev/null
+++ b/botan/build/botan/tm_posix.h
@@ -0,0 +1,27 @@
+/*
+* POSIX Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_POSIX_H__
+#define BOTAN_TIMER_POSIX_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* POSIX Timer
+*/
+class BOTAN_DLL POSIX_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "POSIX clock_gettime"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/tm_unix.h b/botan/build/botan/tm_unix.h
new file mode 100644
index 0000000..c304dbb
--- /dev/null
+++ b/botan/build/botan/tm_unix.h
@@ -0,0 +1,27 @@
+/*
+* Unix Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_UNIX_H__
+#define BOTAN_TIMER_UNIX_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* Unix Timer
+*/
+class BOTAN_DLL Unix_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "Unix gettimeofday"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/tm_win32.h b/botan/build/botan/tm_win32.h
new file mode 100644
index 0000000..5bcb720
--- /dev/null
+++ b/botan/build/botan/tm_win32.h
@@ -0,0 +1,27 @@
+/*
+* Win32 Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_WIN32_H__
+#define BOTAN_TIMER_WIN32_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* Win32 Timer
+*/
+class BOTAN_DLL Win32_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "Win32 QueryPerformanceCounter"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/turing.h b/botan/build/botan/turing.h
new file mode 100644
index 0000000..d48c1d8
--- /dev/null
+++ b/botan/build/botan/turing.h
@@ -0,0 +1,47 @@
+/*
+* Turing
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TURING_H__
+#define BOTAN_TURING_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* Turing
+*/
+class BOTAN_DLL Turing : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Turing"; }
+ StreamCipher* clone() const { return new Turing; }
+ Turing() : StreamCipher(4, 32, 4) { position = 0; }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void resync(const byte[], u32bit);
+ void generate();
+
+ static u32bit fixedS(u32bit);
+ static void gen_sbox(MemoryRegion<u32bit>&, u32bit,
+ const MemoryRegion<u32bit>&);
+
+ static const u32bit Q_BOX[256];
+ static const byte SBOX[256];
+
+ SecureBuffer<u32bit, 256> S0, S1, S2, S3;
+ SecureBuffer<u32bit, 17> R;
+ SecureVector<u32bit> K;
+ SecureBuffer<byte, 340> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/twofish.h b/botan/build/botan/twofish.h
new file mode 100644
index 0000000..0640e32
--- /dev/null
+++ b/botan/build/botan/twofish.h
@@ -0,0 +1,48 @@
+/*
+* Twofish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TWOFISH_H__
+#define BOTAN_TWOFISH_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Twofish
+*/
+class BOTAN_DLL Twofish : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Twofish"; }
+ BlockCipher* clone() const { return new Twofish; }
+ Twofish() : BlockCipher(16, 16, 32, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void rs_mul(byte[4], byte, u32bit);
+
+ static const u32bit MDS0[256];
+ static const u32bit MDS1[256];
+ static const u32bit MDS2[256];
+ static const u32bit MDS3[256];
+ static const byte Q0[256];
+ static const byte Q1[256];
+ static const byte RS[32];
+ static const byte EXP_TO_POLY[255];
+ static const byte POLY_TO_EXP[255];
+
+ SecureBuffer<u32bit, 256> SBox0, SBox1, SBox2, SBox3;
+ SecureBuffer<u32bit, 40> round_key;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/types.h b/botan/build/botan/types.h
new file mode 100644
index 0000000..304628d
--- /dev/null
+++ b/botan/build/botan/types.h
@@ -0,0 +1,42 @@
+/*
+* Low Level Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TYPES_H__
+#define BOTAN_TYPES_H__
+
+#include <botan/build.h>
+
+namespace Botan {
+
+typedef unsigned char byte;
+typedef unsigned short u16bit;
+typedef unsigned int u32bit;
+
+typedef signed int s32bit;
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 u64bit;
+#elif defined(__KCC)
+ typedef unsigned __long_long u64bit;
+#elif defined(__GNUG__)
+ __extension__ typedef unsigned long long u64bit;
+#else
+ typedef unsigned long long u64bit;
+#endif
+
+static const u32bit DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE;
+
+}
+
+namespace Botan_types {
+
+using Botan::byte;
+using Botan::u32bit;
+
+}
+
+#endif
diff --git a/botan/build/botan/ui.h b/botan/build/botan/ui.h
new file mode 100644
index 0000000..fe62c60
--- /dev/null
+++ b/botan/build/botan/ui.h
@@ -0,0 +1,36 @@
+/*
+* User Interface
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UI_H__
+#define BOTAN_UI_H__
+
+#include <botan/build.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* User Interface
+*/
+class BOTAN_DLL User_Interface
+ {
+ public:
+ enum UI_Result { OK, CANCEL_ACTION };
+
+ virtual std::string get_passphrase(const std::string&,
+ const std::string&,
+ UI_Result&) const;
+ User_Interface(const std::string& = "");
+ virtual ~User_Interface() {}
+ protected:
+ std::string preset_passphrase;
+ mutable bool first_try;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/unix_cmd.h b/botan/build/botan/unix_cmd.h
new file mode 100644
index 0000000..aec1891
--- /dev/null
+++ b/botan/build/botan/unix_cmd.h
@@ -0,0 +1,59 @@
+/**
+* Unix Command Execution
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UNIX_CMD_H__
+#define BOTAN_UNIX_CMD_H__
+
+#include <botan/types.h>
+#include <botan/data_src.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Unix Program Info
+*/
+struct Unix_Program
+ {
+ Unix_Program(const char* n, u32bit p)
+ { name_and_args = n; priority = p; working = true; }
+
+ std::string name_and_args;
+ u32bit priority;
+ bool working;
+ };
+
+/**
+* Command Output DataSource
+*/
+class BOTAN_DLL DataSource_Command : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+ std::string id() const;
+
+ int fd() const;
+
+ DataSource_Command(const std::string&,
+ const std::vector<std::string>& paths);
+ ~DataSource_Command();
+ private:
+ void create_pipe(const std::vector<std::string>&);
+ void shutdown_pipe();
+
+ const u32bit MAX_BLOCK_USECS, KILL_WAIT;
+
+ std::vector<std::string> arg_list;
+ struct pipe_wrapper* pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/util.h b/botan/build/botan/util.h
new file mode 100644
index 0000000..ac78673
--- /dev/null
+++ b/botan/build/botan/util.h
@@ -0,0 +1,39 @@
+/*
+* Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UTIL_H__
+#define BOTAN_UTIL_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Time Access Functions
+*/
+BOTAN_DLL u64bit system_time();
+
+/*
+* Memory Locking Functions
+*/
+BOTAN_DLL bool lock_mem(void*, u32bit);
+BOTAN_DLL void unlock_mem(void*, u32bit);
+
+/*
+* Misc Utility Functions
+*/
+BOTAN_DLL u32bit round_up(u32bit, u32bit);
+BOTAN_DLL u32bit round_down(u32bit, u32bit);
+
+/*
+* Work Factor Estimates
+*/
+BOTAN_DLL u32bit dl_work_factor(u32bit);
+
+}
+
+#endif
diff --git a/botan/build/botan/version.h b/botan/build/botan/version.h
new file mode 100644
index 0000000..3cc44e8
--- /dev/null
+++ b/botan/build/botan/version.h
@@ -0,0 +1,61 @@
+/*
+* Version Information
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_VERSION_H__
+#define BOTAN_VERSION_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Get information describing the version
+*/
+
+/**
+* Get the version string identifying the version of Botan.
+* @return the version string
+*/
+BOTAN_DLL std::string version_string();
+
+/**
+* Get the major version number.
+* @return the major version number
+*/
+BOTAN_DLL u32bit version_major();
+
+/**
+* Get the minor version number.
+* @return the minor version number
+*/
+BOTAN_DLL u32bit version_minor();
+
+/**
+* Get the patch number.
+* @return the patch number
+*/
+BOTAN_DLL u32bit version_patch();
+
+/*
+* Macros for compile-time version checks
+*/
+#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+/**
+* Compare using BOTAN_VERSION_CODE_FOR, as in
+* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
+* # error "Botan version too old"
+* # endif
+*/
+#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \
+ BOTAN_VERSION_MINOR, \
+ BOTAN_VERSION_PATCH)
+
+}
+
+#endif
diff --git a/botan/build/botan/whrlpool.h b/botan/build/botan/whrlpool.h
new file mode 100644
index 0000000..b72ff60
--- /dev/null
+++ b/botan/build/botan/whrlpool.h
@@ -0,0 +1,42 @@
+/*
+* Whirlpool
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WHIRLPOOL_H__
+#define BOTAN_WHIRLPOOL_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* Whirlpool
+*/
+class BOTAN_DLL Whirlpool : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Whirlpool"; }
+ HashFunction* clone() const { return new Whirlpool; }
+ Whirlpool() : MDx_HashFunction(64, 64, true, true, 32) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ static const u64bit C0[256];
+ static const u64bit C1[256];
+ static const u64bit C2[256];
+ static const u64bit C3[256];
+ static const u64bit C4[256];
+ static const u64bit C5[256];
+ static const u64bit C6[256];
+ static const u64bit C7[256];
+ SecureBuffer<u64bit, 8> M, digest;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/wid_wake.h b/botan/build/botan/wid_wake.h
new file mode 100644
index 0000000..4720afd
--- /dev/null
+++ b/botan/build/botan/wid_wake.h
@@ -0,0 +1,41 @@
+/*
+* WiderWake
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WIDER_WAKE_H__
+#define BOTAN_WIDER_WAKE_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* WiderWake4+1-BE
+*/
+class BOTAN_DLL WiderWake_41_BE : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "WiderWake4+1-BE"; }
+ StreamCipher* clone() const { return new WiderWake_41_BE; }
+ WiderWake_41_BE() : StreamCipher(16, 16, 1, 8) {}
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void resync(const byte[], u32bit);
+
+ void generate(u32bit);
+
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ SecureBuffer<u32bit, 256> T;
+ SecureBuffer<u32bit, 5> state;
+ SecureBuffer<u32bit, 4> t_key;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x509_ca.h b/botan/build/botan/x509_ca.h
new file mode 100644
index 0000000..ef2a8d1
--- /dev/null
+++ b/botan/build/botan/x509_ca.h
@@ -0,0 +1,108 @@
+/*
+* X.509 Certificate Authority
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CA_H__
+#define BOTAN_X509_CA_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/x509_ext.h>
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate Authorities (CAs).
+*/
+class BOTAN_DLL X509_CA
+ {
+ public:
+
+ /**
+ * Sign a PKCS#10 Request.
+ * @param req the request to sign
+ * @param rng the rng to use
+ * @param not_before the starting time for the certificate
+ * @param not_after the expiration time for the certificate
+ * @return the resulting certificate
+ */
+ X509_Certificate sign_request(const PKCS10_Request& req,
+ RandomNumberGenerator& rng,
+ const X509_Time& not_before,
+ const X509_Time& not_after);
+
+ /**
+ * Get the certificate of this CA.
+ * @return the CA certificate
+ */
+ X509_Certificate ca_certificate() const;
+
+ /**
+ * Create a new and empty CRL for this CA.
+ * @param rng the random number generator to use
+ * @param next_update the time to set in next update in seconds
+ * as the offset from the current time
+ * @return the new CRL
+ */
+ X509_CRL new_crl(RandomNumberGenerator& rng, u32bit = 0) const;
+
+ /**
+ * Create a new CRL by with additional entries.
+ * @param last_crl the last CRL of this CA to add the new entries to
+ * @param new_entries contains the new CRL entries to be added to the CRL
+ * @param rng the random number generator to use
+ * @param next_update the time to set in next update in seconds
+ * as the offset from the current time
+ */
+ X509_CRL update_crl(const X509_CRL& last_crl,
+ const std::vector<CRL_Entry>& new_entries,
+ RandomNumberGenerator& rng,
+ u32bit next_update = 0) const;
+
+ static X509_Certificate make_cert(PK_Signer*,
+ RandomNumberGenerator&,
+ const AlgorithmIdentifier&,
+ const MemoryRegion<byte>&,
+ const X509_Time&, const X509_Time&,
+ const X509_DN&, const X509_DN&,
+ const Extensions&);
+
+ /**
+ * Create a new CA object.
+ * @param ca_certificate the certificate of the CA
+ * @param key the private key of the CA
+ */
+ X509_CA(const X509_Certificate& ca_certificate, const Private_Key& key);
+ ~X509_CA();
+ private:
+ X509_CA(const X509_CA&) {}
+ X509_CA& operator=(const X509_CA&) { return (*this); }
+
+ X509_CRL make_crl(const std::vector<CRL_Entry>&,
+ u32bit, u32bit, RandomNumberGenerator&) const;
+
+ AlgorithmIdentifier ca_sig_algo;
+ X509_Certificate cert;
+ PK_Signer* signer;
+ };
+
+/**
+* Choose the default signature format for a certain public key signature
+* scheme.
+* @param key will be the key to choose a padding scheme for
+* @param alg_id will be set to the chosen scheme
+* @return A PK_Signer object for generating signatures
+*/
+BOTAN_DLL PK_Signer* choose_sig_format(const Private_Key& key,
+ AlgorithmIdentifier& alg_id);
+
+
+}
+
+#endif
diff --git a/botan/build/botan/x509_crl.h b/botan/build/botan/x509_crl.h
new file mode 100644
index 0000000..6caef42
--- /dev/null
+++ b/botan/build/botan/x509_crl.h
@@ -0,0 +1,90 @@
+/*
+* X.509 CRL
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CRL_H__
+#define BOTAN_X509_CRL_H__
+
+#include <botan/x509_obj.h>
+#include <botan/crl_ent.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate Revocation Lists (CRLs).
+*/
+class BOTAN_DLL X509_CRL : public X509_Object
+ {
+ public:
+ /**
+ * This class represents CRL related errors.
+ */
+ struct X509_CRL_Error : public Exception
+ {
+ X509_CRL_Error(const std::string& error) :
+ Exception("X509_CRL: " + error) {}
+ };
+
+ /**
+ * Get the entries of this CRL in the form of a vector.
+ * @return a vector containing the entries of this CRL.
+ */
+ std::vector<CRL_Entry> get_revoked() const;
+
+ /**
+ * Get the issuer DN of this CRL.
+ * @return the CRLs issuer DN
+ */
+ X509_DN issuer_dn() const;
+
+ /**
+ * Get the AuthorityKeyIdentifier of this CRL.
+ * @return this CRLs AuthorityKeyIdentifier
+ */
+ MemoryVector<byte> authority_key_id() const;
+
+ /**
+ * Get the serial number of this CRL.
+ * @return the CRLs serial number
+ */
+ u32bit crl_number() const;
+
+ /**
+ * Get the CRL's thisUpdate value.
+ * @return the CRLs thisUpdate
+ */
+ X509_Time this_update() const;
+
+ /**
+ * Get the CRL's nextUpdate value.
+ * @return the CRLs nextdUpdate
+ */
+ X509_Time next_update() const;
+
+ /**
+ * Construct a CRL from a data source.
+ * @param source the data source providing the DER or PEM encoded CRL.
+ */
+ X509_CRL(DataSource&, bool throw_on_unknown_critical = false);
+
+ /**
+ * Construct a CRL from a file containing the DER or PEM encoded CRL.
+ * @param filename the name of the CRL file
+ */
+ X509_CRL(const std::string& filename,
+ bool throw_on_unknown_critical = false);
+ private:
+ void force_decode();
+
+ bool throw_on_unknown_critical;
+ std::vector<CRL_Entry> revoked;
+ Data_Store info;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x509_ext.h b/botan/build/botan/x509_ext.h
new file mode 100644
index 0000000..108215e
--- /dev/null
+++ b/botan/build/botan/x509_ext.h
@@ -0,0 +1,317 @@
+/*
+* X.509 Certificate Extensions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_EXTENSIONS_H__
+#define BOTAN_X509_EXTENSIONS_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <botan/asn1_obj.h>
+#include <botan/datastor.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/*
+* X.509 Certificate Extension
+*/
+class BOTAN_DLL Certificate_Extension
+ {
+ public:
+ OID oid_of() const;
+
+ virtual Certificate_Extension* copy() const = 0;
+
+ virtual void contents_to(Data_Store&, Data_Store&) const = 0;
+ virtual std::string config_id() const = 0;
+ virtual std::string oid_name() const = 0;
+
+ virtual ~Certificate_Extension() {}
+ protected:
+ friend class Extensions;
+ virtual bool should_encode() const { return true; }
+ virtual MemoryVector<byte> encode_inner() const = 0;
+ virtual void decode_inner(const MemoryRegion<byte>&) = 0;
+ };
+
+/*
+* X.509 Certificate Extension List
+*/
+class BOTAN_DLL Extensions : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ void add(Certificate_Extension* extn)
+ { extensions.push_back(extn); }
+
+ Extensions& operator=(const Extensions&);
+
+ Extensions(const Extensions&);
+ Extensions(bool st = true) : should_throw(st) {}
+ ~Extensions();
+ private:
+ static Certificate_Extension* get_extension(const OID&);
+
+ std::vector<Certificate_Extension*> extensions;
+ bool should_throw;
+ };
+
+namespace Cert_Extension {
+
+/*
+* Basic Constraints Extension
+*/
+class BOTAN_DLL Basic_Constraints : public Certificate_Extension
+ {
+ public:
+ Basic_Constraints* copy() const
+ { return new Basic_Constraints(is_ca, path_limit); }
+
+ Basic_Constraints(bool ca = false, u32bit limit = 0) :
+ is_ca(ca), path_limit(limit) {}
+
+ bool get_is_ca() const { return is_ca; }
+ u32bit get_path_limit() const;
+ private:
+ std::string config_id() const { return "basic_constraints"; }
+ std::string oid_name() const { return "X509v3.BasicConstraints"; }
+
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ bool is_ca;
+ u32bit path_limit;
+ };
+
+/*
+* Key Usage Constraints Extension
+*/
+class BOTAN_DLL Key_Usage : public Certificate_Extension
+ {
+ public:
+ Key_Usage* copy() const { return new Key_Usage(constraints); }
+
+ Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : constraints(c) {}
+
+ Key_Constraints get_constraints() const { return constraints; }
+ private:
+ std::string config_id() const { return "key_usage"; }
+ std::string oid_name() const { return "X509v3.KeyUsage"; }
+
+ bool should_encode() const { return (constraints != NO_CONSTRAINTS); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ Key_Constraints constraints;
+ };
+
+/*
+* Subject Key Identifier Extension
+*/
+class BOTAN_DLL Subject_Key_ID : public Certificate_Extension
+ {
+ public:
+ Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); }
+
+ Subject_Key_ID() {}
+ Subject_Key_ID(const MemoryRegion<byte>&);
+
+ MemoryVector<byte> get_key_id() const { return key_id; }
+ private:
+ std::string config_id() const { return "subject_key_id"; }
+ std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; }
+
+ bool should_encode() const { return (key_id.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ MemoryVector<byte> key_id;
+ };
+
+/*
+* Authority Key Identifier Extension
+*/
+class BOTAN_DLL Authority_Key_ID : public Certificate_Extension
+ {
+ public:
+ Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); }
+
+ Authority_Key_ID() {}
+ Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {}
+
+ MemoryVector<byte> get_key_id() const { return key_id; }
+ private:
+ std::string config_id() const { return "authority_key_id"; }
+ std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; }
+
+ bool should_encode() const { return (key_id.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ MemoryVector<byte> key_id;
+ };
+
+/*
+* Alternative Name Extension Base Class
+*/
+class BOTAN_DLL Alternative_Name : public Certificate_Extension
+ {
+ public:
+ AlternativeName get_alt_name() const { return alt_name; }
+
+ protected:
+ Alternative_Name(const AlternativeName&,
+ const std::string&, const std::string&);
+
+ Alternative_Name(const std::string&, const std::string&);
+ private:
+ std::string config_id() const { return config_name_str; }
+ std::string oid_name() const { return oid_name_str; }
+
+ bool should_encode() const { return alt_name.has_items(); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::string config_name_str, oid_name_str;
+ AlternativeName alt_name;
+ };
+
+/*
+* Subject Alternative Name Extension
+*/
+class BOTAN_DLL Subject_Alternative_Name : public Alternative_Name
+ {
+ public:
+ Subject_Alternative_Name* copy() const
+ { return new Subject_Alternative_Name(get_alt_name()); }
+
+ Subject_Alternative_Name(const AlternativeName& = AlternativeName());
+ };
+
+/*
+* Issuer Alternative Name Extension
+*/
+class BOTAN_DLL Issuer_Alternative_Name : public Alternative_Name
+ {
+ public:
+ Issuer_Alternative_Name* copy() const
+ { return new Issuer_Alternative_Name(get_alt_name()); }
+
+ Issuer_Alternative_Name(const AlternativeName& = AlternativeName());
+ };
+
+/*
+* Extended Key Usage Extension
+*/
+class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension
+ {
+ public:
+ Extended_Key_Usage* copy() const { return new Extended_Key_Usage(oids); }
+
+ Extended_Key_Usage() {}
+ Extended_Key_Usage(const std::vector<OID>& o) : oids(o) {}
+
+ std::vector<OID> get_oids() const { return oids; }
+ private:
+ std::string config_id() const { return "extended_key_usage"; }
+ std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; }
+
+ bool should_encode() const { return (oids.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<OID> oids;
+ };
+
+/*
+* Certificate Policies Extension
+*/
+class BOTAN_DLL Certificate_Policies : public Certificate_Extension
+ {
+ public:
+ Certificate_Policies* copy() const
+ { return new Certificate_Policies(oids); }
+
+ Certificate_Policies() {}
+ Certificate_Policies(const std::vector<OID>& o) : oids(o) {}
+
+ std::vector<OID> get_oids() const { return oids; }
+ private:
+ std::string config_id() const { return "policy_info"; }
+ std::string oid_name() const { return "X509v3.CertificatePolicies"; }
+
+ bool should_encode() const { return (oids.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<OID> oids;
+ };
+
+/*
+* CRL Number Extension
+*/
+class BOTAN_DLL CRL_Number : public Certificate_Extension
+ {
+ public:
+ CRL_Number* copy() const;
+
+ CRL_Number() : has_value(false), crl_number(0) {}
+ CRL_Number(u32bit n) : has_value(true), crl_number(n) {}
+
+ u32bit get_crl_number() const;
+ private:
+ std::string config_id() const { return "crl_number"; }
+ std::string oid_name() const { return "X509v3.CRLNumber"; }
+
+ bool should_encode() const { return has_value; }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ bool has_value;
+ u32bit crl_number;
+ };
+
+/*
+* CRL Entry Reason Code Extension
+*/
+class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
+ {
+ public:
+ CRL_ReasonCode* copy() const { return new CRL_ReasonCode(reason); }
+
+ CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : reason(r) {}
+
+ CRL_Code get_reason() const { return reason; }
+ private:
+ std::string config_id() const { return "crl_reason"; }
+ std::string oid_name() const { return "X509v3.ReasonCode"; }
+
+ bool should_encode() const { return (reason != UNSPECIFIED); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ CRL_Code reason;
+ };
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/x509_key.h b/botan/build/botan/x509_key.h
new file mode 100644
index 0000000..9404b7e
--- /dev/null
+++ b/botan/build/botan/x509_key.h
@@ -0,0 +1,110 @@
+/*
+* X.509 Public Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract X.509 public key encoders.
+*/
+class BOTAN_DLL X509_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~X509_Encoder() {}
+ };
+
+/**
+* This class represents abstract X.509 public key decoders.
+*/
+class BOTAN_DLL X509_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~X509_Decoder() {}
+ };
+
+/**
+* This namespace contains functions for handling X509 objects.
+*/
+namespace X509 {
+
+/*
+* X.509 Public Key Encoding/Decoding
+*/
+
+/**
+* Encode a key into a pipe.
+* @param key the public key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Public_Key& key, Pipe& pipe,
+ X509_Encoding enc = PEM);
+
+/**
+* PEM encode a public key into a string.
+* @param key the key to encode
+* @return the PEM encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Public_Key& key);
+
+/**
+* Create a public key from a data source.
+* @param source the source providing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(DataSource& source);
+
+/**
+* Create a public key from a string.
+* @param enc the string containing the PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const std::string& enc);
+
+/**
+* Create a public key from a memory region.
+* @param enc the memory region containing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
+
+/**
+* Copy a key.
+* @param key the public key to copy
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
+
+/**
+* Create the key constraints for a specific public key.
+* @param pub_key the public key from which the basic set of
+* constraints to be placed in the return value is derived
+* @param limits additional limits that will be incorporated into the
+* return value
+* @return the combination of key type specific constraints and
+* additional limits
+*/
+
+BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
+ Key_Constraints limits);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/x509_obj.h b/botan/build/botan/x509_obj.h
new file mode 100644
index 0000000..c7f92fa
--- /dev/null
+++ b/botan/build/botan/x509_obj.h
@@ -0,0 +1,67 @@
+/*
+* X.509 SIGNED Object
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_OBJECT_H__
+#define BOTAN_X509_OBJECT_H__
+
+#include <botan/asn1_obj.h>
+#include <botan/pipe.h>
+#include <botan/pubkey_enums.h>
+#include <botan/rng.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents abstract X.509 signed objects as
+* in the X.500 SIGNED macro
+*/
+class BOTAN_DLL X509_Object
+ {
+ public:
+ SecureVector<byte> tbs_data() const;
+ SecureVector<byte> signature() const;
+ AlgorithmIdentifier signature_algorithm() const;
+
+ /**
+ * Create a signed X509 object.
+ * @param signer the signer used to sign the object
+ * @param rng the random number generator to use
+ * @param alg_id the algorithm identifier of the signature scheme
+ * @param tbs the tbs bits to be signed
+ * @return the signed X509 object
+ */
+ static MemoryVector<byte> make_signed(class PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& alg_id,
+ const MemoryRegion<byte>& tbs);
+
+ bool check_signature(class Public_Key&) const;
+
+ void encode(Pipe&, X509_Encoding = PEM) const;
+ SecureVector<byte> BER_encode() const;
+ std::string PEM_encode() const;
+
+ X509_Object(DataSource&, const std::string&);
+ X509_Object(const std::string&, const std::string&);
+ virtual ~X509_Object() {}
+ protected:
+ void do_decode();
+ X509_Object() {}
+ AlgorithmIdentifier sig_algo;
+ SecureVector<byte> tbs_bits, sig;
+ private:
+ virtual void force_decode() = 0;
+ void init(DataSource&, const std::string&);
+ void decode_info(DataSource&);
+ std::vector<std::string> PEM_labels_allowed;
+ std::string PEM_label_pref;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x509cert.h b/botan/build/botan/x509cert.h
new file mode 100644
index 0000000..4a9d11f
--- /dev/null
+++ b/botan/build/botan/x509cert.h
@@ -0,0 +1,185 @@
+/*
+* X.509 Certificates
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERTS_H__
+#define BOTAN_X509_CERTS_H__
+
+#include <botan/x509_obj.h>
+#include <botan/x509_key.h>
+#include <botan/datastor.h>
+#include <botan/pubkey_enums.h>
+#include <map>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate
+*/
+class BOTAN_DLL X509_Certificate : public X509_Object
+ {
+ public:
+ /**
+ * Get the public key associated with this certificate.
+ * @return the subject public key of this certificate
+ */
+ Public_Key* subject_public_key() const;
+
+ /**
+ * Get the issuer certificate DN.
+ * @return the issuer DN of this certificate
+ */
+ X509_DN issuer_dn() const;
+
+ /**
+ * Get the subject certificate DN.
+ * @return the subject DN of this certificate
+ */
+ X509_DN subject_dn() const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.version", "X509.Certificate.serial",
+ * "X509.Certificate.start", "X509.Certificate.end",
+ * "X509.Certificate.v2.key_id", "X509.Certificate.public_key",
+ * "X509v3.BasicConstraints.path_constraint",
+ * "X509v3.BasicConstraints.is_ca", "X509v3.ExtendedKeyUsage",
+ * "X509v3.CertificatePolicies", "X509v3.SubjectKeyIdentifier" or
+ * "X509.Certificate.serial".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> subject_info(const std::string& name) const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> issuer_info(const std::string& name) const;
+
+ /**
+ * Get the notBefore of the certificate.
+ * @return the notBefore of the certificate
+ */
+ std::string start_time() const;
+
+ /**
+ * Get the notAfter of the certificate.
+ * @return the notAfter of the certificate
+ */
+ std::string end_time() const;
+
+ /**
+ * Get the X509 version of this certificate object.
+ * @return the X509 version
+ */
+ u32bit x509_version() const;
+
+ /**
+ * Get the serial number of this certificate.
+ * @return the certificates serial number
+ */
+ MemoryVector<byte> serial_number() const;
+
+ /**
+ * Get the DER encoded AuthorityKeyIdentifier of this certificate.
+ * @return the DER encoded AuthorityKeyIdentifier
+ */
+ MemoryVector<byte> authority_key_id() const;
+
+ /**
+ * Get the DER encoded SubjectKeyIdentifier of this certificate.
+ * @return the DER encoded SubjectKeyIdentifier
+ */
+ MemoryVector<byte> subject_key_id() const;
+
+ /**
+ * Check whether this certificate is self signed.
+ * @return true if this certificate is self signed
+ */
+ bool is_self_signed() const { return self_signed; }
+
+ /**
+ * Check whether this certificate is a CA certificate.
+ * @return true if this certificate is a CA certificate
+ */
+ bool is_CA_cert() const;
+
+ /**
+ * Get the path limit as defined in the BasicConstraints extension of
+ * this certificate.
+ * @return the path limit
+ */
+ u32bit path_limit() const;
+
+ /**
+ * Get the key constraints as defined in the KeyUsage extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ Key_Constraints constraints() const;
+
+ /**
+ * Get the key constraints as defined in the ExtendedKeyUsage
+ * extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ std::vector<std::string> ex_constraints() const;
+
+ /**
+ * Get the policies as defined in the CertificatePolicies extension
+ * of this certificate.
+ * @return the certificate policies
+ */
+ std::vector<std::string> policies() const;
+
+ /**
+ * Check to certificates for equality.
+ * @return true both certificates are (binary) equal
+ */
+ bool operator==(const X509_Certificate& other) const;
+
+ /**
+ * Create a certificate from a data source providing the DER or
+ * PEM encoded certificate.
+ * @param source the data source
+ */
+ X509_Certificate(DataSource& source);
+
+ /**
+ * Create a certificate from a file containing the DER or PEM
+ * encoded certificate.
+ * @param filename the name of the certificate file
+ */
+ X509_Certificate(const std::string& filename);
+ private:
+ void force_decode();
+ friend class X509_CA;
+ X509_Certificate() {}
+
+ Data_Store subject, issuer;
+ bool self_signed;
+ };
+
+/**
+* Check two certificates for inequality
+* @return true if the arguments represent different certificates,
+* false if they are binary identical
+*/
+BOTAN_DLL bool operator!=(const X509_Certificate&, const X509_Certificate&);
+
+/*
+* Data Store Extraction Operations
+*/
+BOTAN_DLL X509_DN create_dn(const Data_Store&);
+BOTAN_DLL AlternativeName create_alt_name(const Data_Store&);
+
+}
+
+#endif
diff --git a/botan/build/botan/x509find.h b/botan/build/botan/x509find.h
new file mode 100644
index 0000000..a7a84c7
--- /dev/null
+++ b/botan/build/botan/x509find.h
@@ -0,0 +1,60 @@
+/*
+* X.509 Certificate Store Searching
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERT_STORE_SEARCH_H__
+#define BOTAN_X509_CERT_STORE_SEARCH_H__
+
+#include <botan/x509stor.h>
+
+namespace Botan {
+
+/*
+* Search based on the contents of a DN entry
+*/
+class BOTAN_DLL DN_Check : public X509_Store::Search_Func
+ {
+ public:
+ typedef bool (*compare_fn)(const std::string&, const std::string&);
+ enum Search_Type { SUBSTRING_MATCHING, IGNORE_CASE };
+
+ bool match(const X509_Certificate& cert) const;
+
+ DN_Check(const std::string&, const std::string&, compare_fn);
+ DN_Check(const std::string&, const std::string&, Search_Type);
+ private:
+ std::string dn_entry, looking_for;
+ compare_fn compare;
+ };
+
+/*
+* Search for a certificate by issuer/serial
+*/
+class BOTAN_DLL IandS_Match : public X509_Store::Search_Func
+ {
+ public:
+ bool match(const X509_Certificate& cert) const;
+ IandS_Match(const X509_DN&, const MemoryRegion<byte>&);
+ private:
+ X509_DN issuer;
+ MemoryVector<byte> serial;
+ };
+
+/*
+* Search for a certificate by subject keyid
+*/
+class BOTAN_DLL SKID_Match : public X509_Store::Search_Func
+ {
+ public:
+ bool match(const X509_Certificate& cert) const;
+ SKID_Match(const MemoryRegion<byte>& s) : skid(s) {}
+ private:
+ MemoryVector<byte> skid;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x509self.h b/botan/build/botan/x509self.h
new file mode 100644
index 0000000..bd3e291
--- /dev/null
+++ b/botan/build/botan/x509self.h
@@ -0,0 +1,198 @@
+/*
+* X.509 Self-Signed Certificate
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_SELF_H__
+#define BOTAN_X509_SELF_H__
+
+#include <botan/x509cert.h>
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+
+namespace Botan {
+
+/**
+* Options for X.509 certificates.
+*/
+class BOTAN_DLL X509_Cert_Options
+ {
+ public:
+ /**
+ * the subject common name
+ */
+ std::string common_name;
+
+ /**
+ * the subject counry
+ */
+ std::string country;
+
+ /**
+ * the subject organization
+ */
+ std::string organization;
+
+ /**
+ * the subject organizational unit
+ */
+ std::string org_unit;
+
+ /**
+ * the subject locality
+ */
+ std::string locality;
+
+ /**
+ * the subject state
+ */
+ std::string state;
+
+ /**
+ * the subject serial number
+ */
+ std::string serial_number;
+
+ /**
+ * the subject email adress
+ */
+ std::string email;
+
+ /**
+ * the subject URI
+ */
+ std::string uri;
+
+ /**
+ * the subject IPv4 address
+ */
+ std::string ip;
+
+ /**
+ * the subject DNS
+ */
+ std::string dns;
+
+ /**
+ * the subject XMPP
+ */
+ std::string xmpp;
+
+ /**
+ * the subject challenge password
+ */
+ std::string challenge;
+
+ /**
+ * the subject notBefore
+ */
+ X509_Time start;
+ /**
+ * the subject notAfter
+ */
+ X509_Time end;
+
+ /**
+ * Indicates whether the certificate request
+ */
+ bool is_CA;
+
+ /**
+ * Indicates the BasicConstraints path limit
+ */
+ u32bit path_limit;
+
+ /**
+ * The key constraints for the subject public key
+ */
+ Key_Constraints constraints;
+
+ /**
+ * The key extended constraints for the subject public key
+ */
+ std::vector<OID> ex_constraints;
+
+ /**
+ * Check the options set in this object for validity.
+ */
+ void sanity_check() const;
+
+ /**
+ * Mark the certificate as a CA certificate and set the path limit.
+ * @param limit the path limit to be set in the BasicConstraints extension.
+ */
+ void CA_key(u32bit limit = 1);
+
+ /**
+ * Set the notBefore of the certificate.
+ * @param time the notBefore value of the certificate
+ */
+ void not_before(const std::string& time);
+
+ /**
+ * Set the notAfter of the certificate.
+ * @param time the notAfter value of the certificate
+ */
+ void not_after(const std::string& time);
+
+ /**
+ * Add the key constraints of the KeyUsage extension.
+ * @param constr the constraints to set
+ */
+ void add_constraints(Key_Constraints constr);
+
+ /**
+ * Add constraints to the ExtendedKeyUsage extension.
+ * @param oid the oid to add
+ */
+ void add_ex_constraint(const OID& oid);
+
+ /**
+ * Add constraints to the ExtendedKeyUsage extension.
+ * @param name the name to look up the oid to add
+ */
+ void add_ex_constraint(const std::string& name);
+
+ /**
+ * Construct a new options object
+ * @param opts define the common name of this object. An example for this
+ * parameter would be "common_name/country/organization/organizational_unit".
+ * @param expire_time the expiration time (from the current clock in seconds)
+ */
+ X509_Cert_Options(const std::string& opts = "",
+ u32bit expire_time = 365 * 24 * 60 * 60);
+ };
+
+namespace X509 {
+
+/**
+* Create a self-signed X.509 certificate.
+* @param opts the options defining the certificate to create
+* @param key the private key used for signing, i.e. the key
+* associated with this self-signed certificate
+* @param rng the rng to use
+* @return the newly created self-signed certificate
+*/
+BOTAN_DLL X509_Certificate
+create_self_signed_cert(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a PKCS#10 certificate request.
+* @param opts the options defining the request to create
+* @param key the key used to sign this request
+* @param rng the rng to use
+* @return the newly created PKCS#10 request
+*/
+BOTAN_DLL PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/botan/build/botan/x509stor.h b/botan/build/botan/x509stor.h
new file mode 100644
index 0000000..4e60378
--- /dev/null
+++ b/botan/build/botan/x509stor.h
@@ -0,0 +1,143 @@
+/*
+* X.509 Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERT_STORE_H__
+#define BOTAN_X509_CERT_STORE_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/certstor.h>
+
+namespace Botan {
+
+/*
+* X.509 Certificate Validation Result
+*/
+enum X509_Code {
+ VERIFIED,
+ UNKNOWN_X509_ERROR,
+ CANNOT_ESTABLISH_TRUST,
+ CERT_CHAIN_TOO_LONG,
+ SIGNATURE_ERROR,
+ POLICY_ERROR,
+ INVALID_USAGE,
+
+ CERT_FORMAT_ERROR,
+ CERT_ISSUER_NOT_FOUND,
+ CERT_NOT_YET_VALID,
+ CERT_HAS_EXPIRED,
+ CERT_IS_REVOKED,
+
+ CRL_FORMAT_ERROR,
+ CRL_ISSUER_NOT_FOUND,
+ CRL_NOT_YET_VALID,
+ CRL_HAS_EXPIRED,
+
+ CA_CERT_CANNOT_SIGN,
+ CA_CERT_NOT_FOR_CERT_ISSUER,
+ CA_CERT_NOT_FOR_CRL_ISSUER
+};
+
+/*
+* X.509 Certificate Store
+*/
+class BOTAN_DLL X509_Store
+ {
+ public:
+ class BOTAN_DLL Search_Func
+ {
+ public:
+ virtual bool match(const X509_Certificate&) const = 0;
+ virtual ~Search_Func() {}
+ };
+
+ enum Cert_Usage {
+ ANY = 0x00,
+ TLS_SERVER = 0x01,
+ TLS_CLIENT = 0x02,
+ CODE_SIGNING = 0x04,
+ EMAIL_PROTECTION = 0x08,
+ TIME_STAMPING = 0x10,
+ CRL_SIGNING = 0x20
+ };
+
+ X509_Code validate_cert(const X509_Certificate&, Cert_Usage = ANY);
+
+ std::vector<X509_Certificate> get_certs(const Search_Func&) const;
+ std::vector<X509_Certificate> get_cert_chain(const X509_Certificate&);
+ std::string PEM_encode() const;
+
+ /*
+ * Made CRL_Data public for XLC for Cell 0.9, otherwise cannot
+ * instantiate member variable std::vector<CRL_Data> revoked
+ */
+ class BOTAN_DLL CRL_Data
+ {
+ public:
+ X509_DN issuer;
+ MemoryVector<byte> serial, auth_key_id;
+ bool operator==(const CRL_Data&) const;
+ bool operator!=(const CRL_Data&) const;
+ bool operator<(const CRL_Data&) const;
+ };
+
+ X509_Code add_crl(const X509_CRL&);
+ void add_cert(const X509_Certificate&, bool = false);
+ void add_certs(DataSource&);
+ void add_trusted_certs(DataSource&);
+
+ void add_new_certstore(Certificate_Store*);
+
+ static X509_Code check_sig(const X509_Object&, Public_Key*);
+
+ X509_Store(u32bit time_slack = 24*60*60,
+ u32bit cache_results = 30*60);
+
+ X509_Store(const X509_Store&);
+ ~X509_Store();
+ private:
+ X509_Store& operator=(const X509_Store&) { return (*this); }
+
+ class BOTAN_DLL Cert_Info
+ {
+ public:
+ bool is_verified(u32bit timeout) const;
+ bool is_trusted() const;
+ X509_Code verify_result() const;
+ void set_result(X509_Code) const;
+ Cert_Info(const X509_Certificate&, bool = false);
+
+ X509_Certificate cert;
+ bool trusted;
+ private:
+ mutable bool checked;
+ mutable X509_Code result;
+ mutable u64bit last_checked;
+ };
+
+ u32bit find_cert(const X509_DN&, const MemoryRegion<byte>&) const;
+ X509_Code check_sig(const Cert_Info&, const Cert_Info&) const;
+ void recompute_revoked_info() const;
+
+ void do_add_certs(DataSource&, bool);
+ X509_Code construct_cert_chain(const X509_Certificate&,
+ std::vector<u32bit>&, bool = false);
+
+ u32bit find_parent_of(const X509_Certificate&);
+ bool is_revoked(const X509_Certificate&) const;
+
+ static const u32bit NO_CERT_FOUND = 0xFFFFFFFF;
+ std::vector<Cert_Info> certs;
+ std::vector<CRL_Data> revoked;
+ std::vector<Certificate_Store*> stores;
+ u32bit time_slack, validation_cache_timeout;
+ mutable bool revoked_info_valid;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x919_mac.h b/botan/build/botan/x919_mac.h
new file mode 100644
index 0000000..1c2a06b
--- /dev/null
+++ b/botan/build/botan/x919_mac.h
@@ -0,0 +1,41 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X919_MAC_H__
+#define BOTAN_ANSI_X919_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* DES/3DES-based MAC from ANSI X9.19
+*/
+class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ ANSI_X919_MAC(BlockCipher*);
+ ~ANSI_X919_MAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ BlockCipher* d;
+ SecureBuffer<byte, 8> state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/x931_rng.h b/botan/build/botan/x931_rng.h
new file mode 100644
index 0000000..44e9b44
--- /dev/null
+++ b/botan/build/botan/x931_rng.h
@@ -0,0 +1,45 @@
+/*
+* ANSI X9.31 RNG
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X931_RNG_H__
+#define BOTAN_ANSI_X931_RNG_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* ANSI X9.31 RNG
+*/
+class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const;
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource*);
+ void add_entropy(const byte[], u32bit);
+
+ ANSI_X931_RNG(BlockCipher*, RandomNumberGenerator*);
+ ~ANSI_X931_RNG();
+ private:
+ void rekey();
+ void update_buffer();
+
+ BlockCipher* cipher;
+ RandomNumberGenerator* prng;
+ SecureVector<byte> V, R;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/xor_buf.h b/botan/build/botan/xor_buf.h
new file mode 100644
index 0000000..39781f0
--- /dev/null
+++ b/botan/build/botan/xor_buf.h
@@ -0,0 +1,74 @@
+/**
+* XOR operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XOR_BUF_H__
+#define BOTAN_XOR_BUF_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
+* @param out the input/output buffer
+* @param in the read-only input buffer
+* @param length the length of the buffers
+*/
+inline void xor_buf(byte out[], const byte in[], u32bit length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in);
+#else
+ out[0] ^= in[0]; out[1] ^= in[1];
+ out[2] ^= in[2]; out[3] ^= in[3];
+ out[4] ^= in[4]; out[5] ^= in[5];
+ out[6] ^= in[6]; out[7] ^= in[7];
+#endif
+
+ out += 8; in += 8; length -= 8;
+ }
+ for(u32bit j = 0; j != length; ++j)
+ out[j] ^= in[j];
+ }
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
+* @param out the output buffer
+* @param in the first input buffer
+* @param in2 the second output buffer
+* @param length the length of the three buffers
+*/
+inline void xor_buf(byte out[],
+ const byte in[],
+ const byte in2[],
+ u32bit length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) =
+ *reinterpret_cast<const u64bit*>(in) ^
+ *reinterpret_cast<const u64bit*>(in2);
+#else
+ out[0] = in[0] ^ in2[0]; out[1] = in[1] ^ in2[1];
+ out[2] = in[2] ^ in2[2]; out[3] = in[3] ^ in2[3];
+ out[4] = in[4] ^ in2[4]; out[5] = in[5] ^ in2[5];
+ out[6] = in[6] ^ in2[6]; out[7] = in[7] ^ in2[7];
+#endif
+
+ in += 8; in2 += 8; out += 8; length -= 8;
+ }
+
+ for(u32bit j = 0; j != length; ++j)
+ out[j] = in[j] ^ in2[j];
+ }
+
+}
+
+#endif
diff --git a/botan/build/botan/xtea.h b/botan/build/botan/xtea.h
new file mode 100644
index 0000000..d9c6066
--- /dev/null
+++ b/botan/build/botan/xtea.h
@@ -0,0 +1,34 @@
+/*
+* XTEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XTEA_H__
+#define BOTAN_XTEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* XTEA
+*/
+class BOTAN_DLL XTEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "XTEA"; }
+ BlockCipher* clone() const { return new XTEA; }
+ XTEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u32bit, 64> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/build/botan/xts.h b/botan/build/botan/xts.h
new file mode 100644
index 0000000..0155817
--- /dev/null
+++ b/botan/build/botan/xts.h
@@ -0,0 +1,76 @@
+/*
+* XTS mode, from IEEE P1619
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XTS_H__
+#define BOTAN_XTS_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* XTS Encryption
+*/
+class BOTAN_DLL XTS_Encryption : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey& key);
+ void set_iv(const InitializationVector& iv);
+
+ std::string name() const;
+
+ XTS_Encryption(BlockCipher* ciph);
+
+ XTS_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+
+ ~XTS_Encryption() { delete cipher; delete cipher2; }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void encrypt(const byte block[]);
+
+ BlockCipher* cipher;
+ BlockCipher* cipher2;
+ SecureVector<byte> tweak;
+ SecureVector<byte> buffer;
+ u32bit position;
+ };
+
+/*
+* XTS Decryption
+*/
+class BOTAN_DLL XTS_Decryption : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey& key);
+ void set_iv(const InitializationVector& iv);
+
+ std::string name() const;
+
+ XTS_Decryption(BlockCipher* ciph);
+
+ XTS_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void decrypt(const byte[]);
+
+ BlockCipher* cipher;
+ BlockCipher* cipher2;
+ SecureVector<byte> tweak;
+ SecureVector<byte> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/checks/algos.cpp b/botan/checks/algos.cpp
new file mode 100644
index 0000000..2edaaf1
--- /dev/null
+++ b/botan/checks/algos.cpp
@@ -0,0 +1,105 @@
+
+#include <botan/botan.h>
+#include <string>
+using namespace Botan;
+
+#include "common.h"
+
+std::vector<algorithm> get_algos()
+ {
+ std::vector<algorithm> algos;
+
+ algos.push_back(algorithm("Block Cipher", "AES-128", "AES-128/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "AES-192", "AES-192/ECB", 24));
+ algos.push_back(algorithm("Block Cipher", "AES-256", "AES-256/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "Blowfish", "Blowfish/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "CAST-128", "CAST-128/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "CAST-256", "CAST-256/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "DES", "DES/ECB", 8));
+ algos.push_back(algorithm("Block Cipher", "DESX", "DESX/ECB", 24));
+ algos.push_back(algorithm("Block Cipher", "TripleDES",
+ "TripleDES/ECB", 24));
+ algos.push_back(algorithm("Block Cipher", "GOST", "GOST/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "IDEA", "IDEA/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "KASUMI", "KASUMI/ECB", 16));
+
+ algos.push_back(algorithm("Block Cipher",
+ "Lion",
+ "Lion(SHA-256,Turing,8192)/ECB", 32));
+
+ algos.push_back(algorithm("Block Cipher", "Luby-Rackoff(SHA-512)",
+ "Luby-Rackoff(SHA-512)/ECB", 16));
+
+ algos.push_back(algorithm("Block Cipher", "MARS", "MARS/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "MISTY1", "MISTY1/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "Noekeon", "Noekeon/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "RC2", "RC2/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "RC5(12)", "RC5(12)/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "RC5(16)", "RC5(16)/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "RC6", "RC6/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "SAFER-SK(10)",
+ "SAFER-SK(10)/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "SEED", "SEED/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "Serpent", "Serpent/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "Skipjack", "Skipjack/ECB", 10));
+ algos.push_back(algorithm("Block Cipher", "Square", "Square/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "TEA", "TEA/ECB", 16));
+ algos.push_back(algorithm("Block Cipher", "Twofish", "Twofish/ECB", 32));
+ algos.push_back(algorithm("Block Cipher", "XTEA", "XTEA/ECB", 16));
+
+ algos.push_back(algorithm("Cipher Mode", "DES/CBC/PKCS7", 8, 8));
+ algos.push_back(algorithm("Cipher Mode", "TripleDES/CBC/PKCS7", 24, 8));
+
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/PKCS7", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/CTS", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(128)", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(64)", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(32)", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(16)", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(8)", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/OFB", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/CTR",
+ "AES-128/CTR-BE", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/EAX", 16, 16));
+ algos.push_back(algorithm("Cipher Mode", "AES-128/XTS", 32, 16));
+
+ algos.push_back(algorithm("Stream Cipher", "ARC4", 16));
+ algos.push_back(algorithm("Stream Cipher", "Salsa20", 32));
+ algos.push_back(algorithm("Stream Cipher", "Turing", 32));
+ algos.push_back(algorithm("Stream Cipher", "WiderWake4+1",
+ "WiderWake4+1-BE", 16, 8));
+
+ algos.push_back(algorithm("Hash", "Adler32"));
+ algos.push_back(algorithm("Hash", "CRC24"));
+ algos.push_back(algorithm("Hash", "CRC32"));
+ algos.push_back(algorithm("Hash", "FORK-256"));
+ algos.push_back(algorithm("Hash", "GOST-34.11"));
+ algos.push_back(algorithm("Hash", "HAS-160"));
+ algos.push_back(algorithm("Hash", "HAS-V"));
+ algos.push_back(algorithm("Hash", "MD2"));
+ algos.push_back(algorithm("Hash", "MD4"));
+ algos.push_back(algorithm("Hash", "MD5"));
+ algos.push_back(algorithm("Hash", "RIPEMD-128"));
+ algos.push_back(algorithm("Hash", "RIPEMD-160"));
+ algos.push_back(algorithm("Hash", "SHA-160"));
+ algos.push_back(algorithm("Hash", "SHA-256"));
+ algos.push_back(algorithm("Hash", "SHA-384"));
+ algos.push_back(algorithm("Hash", "SHA-512"));
+ algos.push_back(algorithm("Hash", "Skein-512"));
+ algos.push_back(algorithm("Hash", "Tiger"));
+ algos.push_back(algorithm("Hash", "Whirlpool"));
+
+ algos.push_back(algorithm("MAC", "CMAC(AES-128)", 16));
+ algos.push_back(algorithm("MAC", "HMAC(SHA-1)", 16));
+ algos.push_back(algorithm("MAC", "X9.19-MAC", 16));
+
+ algos.push_back(algorithm("RNG", "AutoSeeded", 4096));
+ algos.push_back(algorithm("RNG", "HMAC_RNG", 4096));
+ algos.push_back(algorithm("RNG", "Randpool", 4096));
+ algos.push_back(algorithm("RNG", "X9.31-RNG", 4096));
+
+ algos.push_back(algorithm("Codec", "Base64_Encode"));
+ algos.push_back(algorithm("Codec", "Base64_Decode"));
+
+ return algos;
+ }
diff --git a/botan/checks/bench.cpp b/botan/checks/bench.cpp
new file mode 100644
index 0000000..6df7319
--- /dev/null
+++ b/botan/checks/bench.cpp
@@ -0,0 +1,198 @@
+
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+#include <string>
+#include <exception>
+
+#include <botan/filters.h>
+using Botan::byte;
+using Botan::u64bit;
+
+#include "common.h"
+#include "timer.h"
+#include "bench.h"
+
+/* Discard output to reduce overhead */
+struct BitBucket : public Botan::Filter
+ {
+ void write(const byte[], u32bit) {}
+ };
+
+Botan::Filter* lookup(const std::string&,
+ const std::vector<std::string>&,
+ const std::string& = "All");
+
+namespace {
+
+double bench_filter(std::string name, Botan::Filter* filter,
+ Botan::RandomNumberGenerator& rng,
+ bool html, double seconds)
+ {
+ Botan::Pipe pipe(filter, new BitBucket);
+
+ std::vector<byte> buf(128 * 1024);
+ rng.randomize(&buf[0], buf.size());
+
+ pipe.start_msg();
+
+ Timer timer(name, buf.size());
+
+ while(timer.seconds() < seconds)
+ {
+ timer.start();
+ pipe.write(&buf[0], buf.size());
+ timer.stop();
+ }
+
+ pipe.end_msg();
+
+ double bytes_per_sec = timer.events() / timer.seconds();
+ double mbytes_per_sec = bytes_per_sec / (1024.0 * 1024.0);
+
+ std::cout.setf(std::ios::fixed, std::ios::floatfield);
+ std::cout.precision(2);
+ if(html)
+ {
+ if(name.find("<") != std::string::npos)
+ name.replace(name.find("<"), 1, "&lt;");
+ if(name.find(">") != std::string::npos)
+ name.replace(name.find(">"), 1, "&gt;");
+ std::cout << " <TR><TH>" << name
+ << std::string(25 - name.length(), ' ') << " <TH>";
+ std::cout.width(6);
+ std::cout << mbytes_per_sec << std::endl;
+ }
+ else
+ {
+ std::cout << name << ": " << std::string(25 - name.length(), ' ');
+ std::cout.width(6);
+ std::cout << mbytes_per_sec << " MiB/sec" << std::endl;
+ }
+ return (mbytes_per_sec);
+ }
+
+double bench(const std::string& name, const std::string& filtername, bool html,
+ double seconds, u32bit keylen, u32bit ivlen,
+ Botan::RandomNumberGenerator& rng)
+ {
+ std::vector<std::string> params;
+
+ Botan::SecureVector<byte> key(keylen);
+ rng.randomize(key, key.size());
+ params.push_back(hex_encode(key, key.size()));
+
+ //params.push_back(std::string(int(2*keylen), 'A'));
+ params.push_back(std::string(int(2* ivlen), 'A'));
+
+ Botan::Filter* filter = lookup(filtername, params);
+
+ if(filter)
+ return bench_filter(name, filter, rng, html, seconds);
+ return 0;
+ }
+
+}
+
+void benchmark(const std::string& what,
+ Botan::RandomNumberGenerator& rng,
+ bool html, double seconds)
+ {
+ try {
+ if(html)
+ {
+ std::cout << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD "
+ << "HTML 4.0 Transitional//EN\">\n"
+ << "<HTML>\n\n"
+ << "<TITLE>Botan Benchmarks</TITLE>\n\n"
+ << "<BODY>\n\n"
+ << "<P><TABLE BORDER CELLSPACING=1>\n"
+ << "<THEAD>\n"
+ << "<TR><TH>Algorithm "
+ << "<TH>Mib / second\n"
+ << "<TBODY>\n";
+ }
+
+ double sum = 0;
+ u32bit how_many = 0;
+
+ std::vector<algorithm> algos = get_algos();
+
+ for(u32bit j = 0; j != algos.size(); j++)
+ if(what == "All" || what == algos[j].type)
+ {
+ double speed = bench(algos[j].name, algos[j].filtername,
+ html, seconds, algos[j].keylen,
+ algos[j].ivlen, rng);
+ if(speed > .00001) /* log(0) == -inf -> messed up average */
+ sum += std::log(speed);
+ how_many++;
+ }
+
+ if(html)
+ std::cout << "</TABLE>\n\n";
+
+ double average = std::exp(sum / static_cast<double>(how_many));
+
+ if(what == "All" && html)
+ std::cout << "\n<P>Overall speed average: " << average
+ << "\n\n";
+ else if(what == "All")
+ std::cout << "\nOverall speed average: " << average
+ << std::endl;
+
+ if(html) std::cout << "</BODY></HTML>\n";
+ }
+ catch(Botan::Exception& e)
+ {
+ std::cout << "Botan exception caught: " << e.what() << std::endl;
+ return;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Standard library exception caught: " << e.what()
+ << std::endl;
+ return;
+ }
+ catch(...)
+ {
+ std::cout << "Unknown exception caught." << std::endl;
+ return;
+ }
+ }
+
+u32bit bench_algo(const std::string& name,
+ Botan::RandomNumberGenerator& rng,
+ double seconds)
+ {
+ try {
+ std::vector<algorithm> algos = get_algos();
+
+ for(u32bit j = 0; j != algos.size(); j++)
+ {
+ if(algos[j].name == name)
+ {
+ bench(algos[j].name, algos[j].filtername, false, seconds,
+ algos[j].keylen, algos[j].ivlen, rng);
+ return 1;
+ }
+ }
+ return 0;
+ }
+ catch(Botan::Exception& e)
+ {
+ std::cout << "Botan exception caught: " << e.what() << std::endl;
+ return 0;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Standard library exception caught: " << e.what()
+ << std::endl;
+ return 0;
+ }
+ catch(...)
+ {
+ std::cout << "Unknown exception caught." << std::endl;
+ return 0;
+ }
+ }
diff --git a/botan/checks/bench.h b/botan/checks/bench.h
new file mode 100644
index 0000000..07d67e0
--- /dev/null
+++ b/botan/checks/bench.h
@@ -0,0 +1,37 @@
+
+#ifndef BOTAN_BENCHMARCH_H__
+#define BOTAN_BENCHMARCH_H__
+
+#include <botan/rng.h>
+#include <string>
+#include <map>
+#include <set>
+#include "timer.h"
+
+#include <iostream>
+
+class Benchmark_Report
+ {
+ public:
+ void report(const std::string& name, Timer timer)
+ {
+ std::cout << name << " " << timer << std::endl;
+ data[name].insert(timer);
+ }
+
+ private:
+ std::map<std::string, std::set<Timer> > data;
+ };
+
+
+void benchmark(const std::string&, Botan::RandomNumberGenerator&,
+ bool html, double seconds);
+
+void bench_pk(Botan::RandomNumberGenerator&,
+ const std::string&, bool html, double seconds);
+
+u32bit bench_algo(const std::string&,
+ Botan::RandomNumberGenerator&,
+ double);
+
+#endif
diff --git a/botan/checks/bigint.cpp b/botan/checks/bigint.cpp
new file mode 100644
index 0000000..a56fd91
--- /dev/null
+++ b/botan/checks/bigint.cpp
@@ -0,0 +1,353 @@
+#include <vector>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <cstdlib>
+
+#include <botan/bigint.h>
+#include <botan/exceptn.h>
+#include <botan/numthry.h>
+using namespace Botan;
+
+#include "common.h"
+#include "validate.h"
+
+#define DEBUG 0
+
+u32bit check_add(const std::vector<std::string>&);
+u32bit check_sub(const std::vector<std::string>&);
+u32bit check_mul(const std::vector<std::string>&);
+u32bit check_sqr(const std::vector<std::string>&);
+u32bit check_div(const std::vector<std::string>&);
+u32bit check_mod(const std::vector<std::string>&,
+ Botan::RandomNumberGenerator& rng);
+u32bit check_shr(const std::vector<std::string>&);
+u32bit check_shl(const std::vector<std::string>&);
+
+u32bit check_powmod(const std::vector<std::string>&);
+u32bit check_primetest(const std::vector<std::string>&,
+ Botan::RandomNumberGenerator&);
+
+u32bit do_bigint_tests(const std::string& filename,
+ Botan::RandomNumberGenerator& rng)
+ {
+ std::ifstream test_data(filename.c_str());
+
+ if(!test_data)
+ throw Botan::Stream_IO_Error("Couldn't open test file " + filename);
+
+ u32bit errors = 0, alg_count = 0;
+ std::string algorithm;
+ bool first = true;
+ u32bit counter = 0;
+
+ while(!test_data.eof())
+ {
+ if(test_data.bad() || test_data.fail())
+ throw Botan::Stream_IO_Error("File I/O error reading from " +
+ filename);
+
+ std::string line;
+ std::getline(test_data, line);
+
+ strip(line);
+ if(line.size() == 0) continue;
+
+ // Do line continuation
+ while(line[line.size()-1] == '\\' && !test_data.eof())
+ {
+ line.replace(line.size()-1, 1, "");
+ std::string nextline;
+ std::getline(test_data, nextline);
+ strip(nextline);
+ if(nextline.size() == 0) continue;
+ line += nextline;
+ }
+
+ if(line[0] == '[' && line[line.size() - 1] == ']')
+ {
+ algorithm = line.substr(1, line.size() - 2);
+ alg_count = 0;
+ counter = 0;
+
+ if(!first)
+ std::cout << std::endl;
+ std::cout << "Testing BigInt " << algorithm << ": ";
+ std::cout.flush();
+ first = false;
+ continue;
+ }
+
+ std::vector<std::string> substr = parse(line);
+
+#if DEBUG
+ std::cout << "Testing: " << algorithm << std::endl;
+#endif
+
+ u32bit new_errors = 0;
+ if(algorithm.find("Addition") != std::string::npos)
+ new_errors = check_add(substr);
+ else if(algorithm.find("Subtraction") != std::string::npos)
+ new_errors = check_sub(substr);
+ else if(algorithm.find("Multiplication") != std::string::npos)
+ new_errors = check_mul(substr);
+ else if(algorithm.find("Square") != std::string::npos)
+ new_errors = check_sqr(substr);
+ else if(algorithm.find("Division") != std::string::npos)
+ new_errors = check_div(substr);
+ else if(algorithm.find("Modulo") != std::string::npos)
+ new_errors = check_mod(substr, rng);
+ else if(algorithm.find("LeftShift") != std::string::npos)
+ new_errors = check_shl(substr);
+ else if(algorithm.find("RightShift") != std::string::npos)
+ new_errors = check_shr(substr);
+ else if(algorithm.find("ModExp") != std::string::npos)
+ new_errors = check_powmod(substr);
+ else if(algorithm.find("PrimeTest") != std::string::npos)
+ new_errors = check_primetest(substr, rng);
+ else
+ std::cout << "Unknown MPI test " << algorithm << std::endl;
+
+ if(counter % 3 == 0)
+ {
+ std::cout << '.';
+ std::cout.flush();
+ }
+ counter++;
+ alg_count++;
+ errors += new_errors;
+
+ if(new_errors)
+ std::cout << "ERROR: BigInt " << algorithm << " failed test #"
+ << std::dec << alg_count << std::endl;
+ }
+ std::cout << std::endl;
+ return errors;
+ }
+
+namespace {
+
+// c==expected, d==a op b, e==a op= b
+u32bit results(std::string op,
+ const BigInt& a, const BigInt& b,
+ const BigInt& c, const BigInt& d, const BigInt& e)
+ {
+ std::string op1 = "operator" + op;
+ std::string op2 = op1 + "=";
+
+ if(c == d && d == e)
+ return 0;
+ else
+ {
+ std::cout << std::endl;
+
+ std::cout << "ERROR: " << op1 << std::endl;
+
+ std::cout << "a = " << std::hex << a << std::endl;
+ std::cout << "b = " << std::hex << b << std::endl;
+
+ std::cout << "c = " << std::hex << c << std::endl;
+ std::cout << "d = " << std::hex << d << std::endl;
+ std::cout << "e = " << std::hex << e << std::endl;
+
+ if(d != e)
+ {
+ std::cout << "ERROR: " << op1 << " | " << op2
+ << " mismatch" << std::endl;
+ }
+ return 1;
+ }
+ }
+
+}
+
+u32bit check_add(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt c(args[2]);
+
+ BigInt d = a + b;
+ BigInt e = a;
+ e += b;
+
+ if(results("+", a, b, c, d, e))
+ return 1;
+
+ d = b + a;
+ e = b;
+ e += a;
+
+ return results("+", a, b, c, d, e);
+ }
+
+u32bit check_sub(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt c(args[2]);
+
+ BigInt d = a - b;
+ BigInt e = a;
+ e -= b;
+
+ return results("-", a, b, c, d, e);
+ }
+
+u32bit check_mul(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt c(args[2]);
+
+ /*
+ std::cout << "a = " << args[0] << "\n"
+ << "b = " << args[1] << std::endl;
+ */
+ /* This makes it more likely the fast multiply algorithms will be usable,
+ which is what we really want to test here (the simple n^2 multiply is
+ pretty well tested at this point).
+ */
+ a.grow_reg(32);
+ b.grow_reg(32);
+
+ BigInt d = a * b;
+ BigInt e = a;
+ e *= b;
+
+ if(results("*", a, b, c, d, e))
+ return 1;
+
+ d = b * a;
+ e = b;
+ e *= a;
+
+ return results("*", a, b, c, d, e);
+ }
+
+u32bit check_sqr(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+
+ a.grow_reg(16);
+ b.grow_reg(16);
+
+ BigInt c = square(a);
+ BigInt d = a * a;
+
+ return results("sqr", a, a, b, c, d);
+ }
+
+u32bit check_div(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt c(args[2]);
+
+ BigInt d = a / b;
+ BigInt e = a;
+ e /= b;
+
+ return results("/", a, b, c, d, e);
+ }
+
+u32bit check_mod(const std::vector<std::string>& args,
+ Botan::RandomNumberGenerator& rng)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt c(args[2]);
+
+ BigInt d = a % b;
+ BigInt e = a;
+ e %= b;
+
+ u32bit got = results("%", a, b, c, d, e);
+
+ if(got) return got;
+
+ word b_word = b.word_at(0);
+
+ /* Won't work for us, just pick one at random */
+ while(b_word == 0)
+ for(u32bit j = 0; j != 2*sizeof(word); j++)
+ b_word = (b_word << 4) ^ rng.next_byte();
+
+ b = b_word;
+
+ c = a % b; /* we declare the BigInt % BigInt version to be correct here */
+
+ word d2 = a % b_word;
+ e = a;
+ e %= b_word;
+
+ return results("%(word)", a, b, c, d2, e);
+ }
+
+u32bit check_shl(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ u32bit b = std::atoi(args[1].c_str());
+ BigInt c(args[2]);
+
+ BigInt d = a << b;
+ BigInt e = a;
+ e <<= b;
+
+ return results("<<", a, b, c, d, e);
+ }
+
+u32bit check_shr(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ u32bit b = std::atoi(args[1].c_str());
+ BigInt c(args[2]);
+
+ BigInt d = a >> b;
+ BigInt e = a;
+ e >>= b;
+
+ return results(">>", a, b, c, d, e);
+ }
+
+/* Make sure that (a^b)%m == r */
+u32bit check_powmod(const std::vector<std::string>& args)
+ {
+ BigInt a(args[0]);
+ BigInt b(args[1]);
+ BigInt m(args[2]);
+ BigInt c(args[3]);
+
+ BigInt r = power_mod(a, b, m);
+
+ if(c != r)
+ {
+ std::cout << "ERROR: power_mod" << std::endl;
+ std::cout << "a = " << std::hex << a << std::endl;
+ std::cout << "b = " << std::hex << b << std::endl;
+ std::cout << "m = " << std::hex << m << std::endl;
+ std::cout << "c = " << std::hex << c << std::endl;
+ std::cout << "r = " << std::hex << r << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+/* Make sure that n is prime or not prime, according to should_be_prime */
+u32bit check_primetest(const std::vector<std::string>& args,
+ Botan::RandomNumberGenerator& rng)
+ {
+ BigInt n(args[0]);
+ bool should_be_prime = (args[1] == "1");
+
+ bool is_prime = Botan::verify_prime(n, rng);
+
+ if(is_prime != should_be_prime)
+ {
+ std::cout << "ERROR: verify_prime" << std::endl;
+ std::cout << "n = " << n << std::endl;
+ std::cout << is_prime << " != " << should_be_prime << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/checks/block.cpp b/botan/checks/block.cpp
new file mode 100644
index 0000000..1e7de37
--- /dev/null
+++ b/botan/checks/block.cpp
@@ -0,0 +1,98 @@
+
+/*
+ We don't use the standard issue ECB filter, because we also want to check
+ that the encryption and decryption operations are inverses (ie, it works).
+
+ This class only works with NoPadding mode, unlike the regular ECB filters
+*/
+
+#include <iostream>
+#include <string>
+#include <cstdlib>
+#include <botan/filter.h>
+#include <botan/lookup.h>
+using namespace Botan;
+
+#include "common.h"
+
+class ECB_Encryption_ErrorCheck : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+ ECB_Encryption_ErrorCheck(const std::string& cipher_name,
+ const std::string&,
+ const SymmetricKey& key) :
+ BLOCKSIZE(block_size_of(cipher_name))
+ {
+ const std::string HASH = "CRC32";
+
+ cipher = get_block_cipher(cipher_name);
+ input_hash = get_hash(HASH);
+ decrypt_hash = get_hash(HASH);
+ buffer.create(BLOCKSIZE);
+ cipher->set_key(key);
+ position = 0;
+ }
+ ~ECB_Encryption_ErrorCheck()
+ { delete cipher; delete input_hash; delete decrypt_hash; }
+ private:
+ const u32bit BLOCKSIZE;
+ BlockCipher* cipher;
+ SecureVector<byte> buffer;
+ u32bit position;
+ HashFunction* input_hash, *decrypt_hash;
+ };
+
+void ECB_Encryption_ErrorCheck::write(const byte input[], u32bit length)
+ {
+ input_hash->update(input, length);
+ buffer.copy(position, input, length);
+ if(position + length >= BLOCKSIZE)
+ {
+ cipher->encrypt(buffer);
+ send(buffer, BLOCKSIZE);
+ cipher->decrypt(buffer);
+ decrypt_hash->update(buffer, BLOCKSIZE);
+ input += (BLOCKSIZE - position);
+ length -= (BLOCKSIZE - position);
+ while(length >= BLOCKSIZE)
+ {
+ cipher->encrypt(input, buffer);
+ send(buffer, BLOCKSIZE);
+ cipher->decrypt(buffer);
+ decrypt_hash->update(buffer, BLOCKSIZE);
+ input += BLOCKSIZE;
+ length -= BLOCKSIZE;
+ }
+ buffer.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+void ECB_Encryption_ErrorCheck::end_msg()
+ {
+ SecureVector<byte> hash1 = input_hash->final();
+ SecureVector<byte> hash2 = decrypt_hash->final();
+
+ if(hash1 != hash2)
+ {
+ std::cout << "In " << cipher->name()
+ << " decryption check failed." << std::endl;
+ }
+
+ if(position)
+ throw Exception("ECB: input was not in full blocks");
+ }
+
+Filter* lookup_block(const std::string& algname, const std::string& key)
+ {
+ Filter* cipher = 0;
+ try {
+ cipher = new ECB_Encryption_ErrorCheck(algname, "NoPadding", key);
+ }
+ catch(Algorithm_Not_Found) {}
+
+ return cipher;
+ }
diff --git a/botan/checks/check.cpp b/botan/checks/check.cpp
new file mode 100644
index 0000000..678cf4b
--- /dev/null
+++ b/botan/checks/check.cpp
@@ -0,0 +1,240 @@
+/*
+ * Test Driver for Botan
+ */
+
+#include <vector>
+#include <string>
+
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include <limits>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/libstate.h>
+#include <botan/mp_types.h>
+
+using namespace Botan;
+
+#include "getopt.h"
+#include "bench.h"
+#include "validate.h"
+#include "common.h"
+
+const std::string VALIDATION_FILE = "checks/validate.dat";
+const std::string BIGINT_VALIDATION_FILE = "checks/mp_valid.dat";
+const std::string PK_VALIDATION_FILE = "checks/pk_valid.dat";
+const std::string EXPECTED_FAIL_FILE = "checks/fail.dat";
+
+int run_test_suite(RandomNumberGenerator& rng);
+
+namespace {
+
+template<typename T>
+bool test(const char* type, int digits, bool is_signed)
+ {
+ if(std::numeric_limits<T>::is_specialized == false)
+ {
+ std::cout << "WARNING: Could not check parameters of " << type
+ << " in std::numeric_limits" << std::endl;
+
+ // assume it's OK (full tests will catch it later)
+ return true;
+ }
+
+ // continue checking after failures
+ bool passed = true;
+
+ if(std::numeric_limits<T>::is_integer == false)
+ {
+ std::cout << "WARN: std::numeric_limits<> says " << type
+ << " is not an integer" << std::endl;
+ passed = false;
+ }
+
+ if(std::numeric_limits<T>::is_signed != is_signed)
+ {
+ std::cout << "ERROR: numeric_limits<" << type << ">::is_signed == "
+ << std::boolalpha << std::numeric_limits<T>::is_signed
+ << std::endl;
+ passed = false;
+ }
+
+ if(std::numeric_limits<T>::digits != digits && digits != 0)
+ {
+ std::cout << "ERROR: numeric_limits<" << type << ">::digits == "
+ << std::numeric_limits<T>::digits
+ << " expected " << digits << std::endl;
+ passed = false;
+ }
+
+ return passed;
+ }
+
+void test_types()
+ {
+ bool passed = true;
+
+ passed = passed && test<Botan::byte >("byte", 8, false);
+ passed = passed && test<Botan::u16bit>("u16bit", 16, false);
+ passed = passed && test<Botan::u32bit>("u32bit", 32, false);
+ passed = passed && test<Botan::u64bit>("u64bit", 64, false);
+ passed = passed && test<Botan::s32bit>("s32bit", 31, true);
+ passed = passed && test<Botan::word>("word", 0, false);
+
+ if(!passed)
+ std::cout << "Typedefs in include/types.h may be incorrect!\n";
+ }
+
+}
+
+int main(int argc, char* argv[])
+ {
+ try
+ {
+ OptionParser opts("help|html|test|validate|"
+ "benchmark|bench-type=|bench-algo=|seconds=");
+ opts.parse(argv);
+
+ test_types(); // do this always
+
+ Botan::LibraryInitializer init("thread_safe=no");
+
+ Botan::AutoSeeded_RNG rng;
+
+ if(opts.is_set("help") || argc <= 1)
+ {
+ std::cerr << "Test driver for "
+ << Botan::version_string() << "\n"
+ << "Options:\n"
+ << " --test || --validate: Run tests (do this at least once)\n"
+ << " --benchmark: Benchmark everything\n"
+ << " --bench-type={block,mode,stream,hash,mac,rng,pk}:\n"
+ << " Benchmark only algorithms of a particular type\n"
+ << " --html: Produce HTML output for benchmarks\n"
+ << " --seconds=n: Benchmark for n seconds\n"
+ << " --init=<str>: Pass <str> to the library\n"
+ << " --help: Print this message\n";
+ return 1;
+ }
+
+ if(opts.is_set("validate") || opts.is_set("test"))
+ {
+ return run_test_suite(rng);
+ }
+ if(opts.is_set("bench-algo") ||
+ opts.is_set("benchmark") ||
+ opts.is_set("bench-type"))
+ {
+ double seconds = 5;
+
+ if(opts.is_set("seconds"))
+ {
+ seconds = std::atof(opts.value("seconds").c_str());
+ if(seconds < 0.1 || seconds > (5 * 60))
+ {
+ std::cout << "Invalid argument to --seconds\n";
+ return 2;
+ }
+ }
+
+ const bool html = opts.is_set("html");
+
+ if(opts.is_set("benchmark"))
+ {
+ benchmark("All", rng, html, seconds);
+ }
+ else if(opts.is_set("bench-algo"))
+ {
+ std::vector<std::string> algs =
+ Botan::split_on(opts.value("bench-algo"), ',');
+
+ for(u32bit j = 0; j != algs.size(); j++)
+ {
+ const std::string alg = algs[j];
+ u32bit found = bench_algo(alg, rng, seconds);
+ if(!found) // maybe it's a PK algorithm
+ bench_pk(rng, alg, html, seconds);
+ }
+ }
+ else if(opts.is_set("bench-type"))
+ {
+ const std::string type = opts.value("bench-type");
+
+ if(type == "all")
+ benchmark("All", rng, html, seconds);
+ else if(type == "block")
+ benchmark("Block Cipher", rng, html, seconds);
+ else if(type == "stream")
+ benchmark("Stream Cipher", rng, html, seconds);
+ else if(type == "hash")
+ benchmark("Hash", rng, html, seconds);
+ else if(type == "mode")
+ benchmark("Cipher Mode", rng, html, seconds);
+ else if(type == "mac")
+ benchmark("MAC", rng, html, seconds);
+ else if(type == "rng")
+ benchmark("RNG", rng, html, seconds);
+ else if(type == "pk")
+ bench_pk(rng, "All", html, seconds);
+ else
+ std::cerr << "Unknown --bench-type " << type << "\n";
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << std::endl;
+ return 1;
+ }
+ catch(...)
+ {
+ std::cerr << "Unknown (...) exception caught" << std::endl;
+ return 1;
+ }
+
+ return 0;
+ }
+
+int run_test_suite(RandomNumberGenerator& rng)
+ {
+ std::cout << "Beginning tests..." << std::endl;
+
+ u32bit errors = 0;
+ try
+ {
+ errors += do_validation_tests(VALIDATION_FILE, rng);
+ errors += do_validation_tests(EXPECTED_FAIL_FILE, rng, false);
+ errors += do_bigint_tests(BIGINT_VALIDATION_FILE, rng);
+ errors += do_pk_validation_tests(PK_VALIDATION_FILE, rng);
+ //errors += do_cvc_tests(rng);
+ }
+ catch(Botan::Exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Standard library exception caught: "
+ << e.what() << std::endl;
+ return 1;
+ }
+ catch(...)
+ {
+ std::cout << "Unknown exception caught." << std::endl;
+ return 1;
+ }
+
+ if(errors)
+ {
+ std::cout << errors << " test" << ((errors == 1) ? "" : "s")
+ << " failed." << std::endl;
+ return 1;
+ }
+
+ std::cout << "All tests passed!" << std::endl;
+ return 0;
+ }
diff --git a/botan/checks/clock.cpp b/botan/checks/clock.cpp
new file mode 100644
index 0000000..e5565ff
--- /dev/null
+++ b/botan/checks/clock.cpp
@@ -0,0 +1,82 @@
+#include "timer.h"
+#include <botan/build.h>
+
+/*************************************************
+* Platform specific settings for which clock type to use
+*/
+
+#if !defined(USE_CLOCK_GETTIME) && defined(BOTAN_TARGET_OS_IS_LINUX)
+ #define USE_GETTIMEOFDAY 1
+#endif
+
+#if !defined(USE_GETTIMEOFDAY) && defined(BOTAN_TARGET_OS_IS_FREEBSD)
+ #define USE_GETTIMEOFDAY 1
+#endif
+
+/*************************************************
+ Set the default, which is clock
+*/
+#ifndef USE_CLOCK_GETTIME
+ #define USE_CLOCK_GETTIME 0
+#endif
+
+#ifndef USE_GETTIMEOFDAY
+ #define USE_GETTIMEOFDAY 0
+#endif
+
+#ifndef USE_TIMES
+ #define USE_TIMES 0
+#endif
+
+/* the default: ANSI/ISO clock */
+#ifndef USE_CLOCK
+ #define USE_CLOCK 1
+#endif
+
+#if USE_CLOCK_GETTIME
+ #include <time.h>
+#elif USE_GETTIMEOFDAY
+ #include <sys/time.h>
+#elif USE_TIMES
+ #include <sys/times.h>
+ #include <unistd.h>
+#elif USE_CLOCK
+ #include <time.h>
+#endif
+
+/* The implementation: */
+u64bit Timer::get_clock()
+ {
+ static const u64bit billion = 1000000000;
+
+#if USE_CLOCK_GETTIME
+
+ struct timespec tv;
+ clock_gettime(CLOCK_REALTIME, &tv);
+ return (billion * tv.tv_sec + tv.tv_nsec);
+
+#elif USE_GETTIMEOFDAY
+
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (billion * tv.tv_sec + 1000 * tv.tv_usec);
+
+#elif USE_TIMES
+
+ struct tms tms;
+ times(&tms);
+
+ static const u64bit clocks_to_nanoseconds =
+ (billion / sysconf(_SC_CLK_TCK));
+
+ return (tms.tms_utime * clocks_to_nanoseconds);
+
+#elif USE_CLOCK
+
+ static const u64bit clocks_to_nanoseconds =
+ (billion / CLOCKS_PER_SEC);
+
+ return clock() * clocks_to_nanoseconds;
+
+#endif
+ }
diff --git a/botan/checks/common.h b/botan/checks/common.h
new file mode 100644
index 0000000..fa41882
--- /dev/null
+++ b/botan/checks/common.h
@@ -0,0 +1,100 @@
+// common code for the validation and benchmark code
+
+#ifndef BOTAN_CHECK_COMMON_H__
+#define BOTAN_CHECK_COMMON_H__
+
+#include <vector>
+#include <string>
+#include <deque>
+#include <stdexcept>
+
+#include <botan/secmem.h>
+#include <botan/filter.h>
+#include <botan/rng.h>
+
+using Botan::byte;
+using Botan::u32bit;
+
+struct algorithm
+ {
+ algorithm(const char* t, const char* n,
+ u32bit k = 0, u32bit i = 0) :
+ type(t), name(n), filtername(n), keylen(k), ivlen(i) {}
+ algorithm(const char* t, const char* n,
+ const char* f, u32bit k = 0, u32bit i = 0) :
+ type(t), name(n), filtername(f), keylen(k), ivlen(i) {}
+ std::string type, name, filtername;
+ u32bit keylen, ivlen, weight;
+ };
+
+std::vector<algorithm> get_algos();
+
+void strip_comments(std::string& line);
+void strip_newlines(std::string& line);
+void strip(std::string& line);
+std::vector<std::string> parse(const std::string& line);
+
+std::string hex_encode(const byte in[], u32bit len);
+Botan::SecureVector<byte> decode_hex(const std::string&);
+
+Botan::Filter* lookup(const std::string& algname,
+ const std::vector<std::string>& params,
+ const std::string& section);
+
+Botan::Filter* lookup_block(const std::string&, const std::string&);
+Botan::Filter* lookup_cipher(const std::string&, const std::string&,
+ const std::string&, bool);
+Botan::Filter* lookup_hash(const std::string&);
+Botan::Filter* lookup_mac(const std::string&, const std::string&);
+Botan::Filter* lookup_rng(const std::string&, const std::string&);
+Botan::Filter* lookup_encoder(const std::string&);
+Botan::Filter* lookup_s2k(const std::string&, const std::vector<std::string>&);
+Botan::Filter* lookup_kdf(const std::string&, const std::string&,
+ const std::string&);
+
+class Fixed_Output_RNG : public Botan::RandomNumberGenerator
+ {
+ public:
+ bool is_seeded() const { return !buf.empty(); }
+
+ byte random()
+ {
+ if(buf.empty())
+ throw std::runtime_error("Out of bytes");
+
+ byte out = buf.front();
+ buf.pop_front();
+ return out;
+ }
+
+ void reseed(u32bit) {}
+
+ void randomize(byte out[], u32bit len)
+ {
+ for(u32bit j = 0; j != len; j++)
+ out[j] = random();
+ }
+
+ std::string name() const { return "Fixed_Output_RNG"; }
+
+ void add_entropy_source(Botan::EntropySource* src) { delete src; }
+ void add_entropy(const byte[], u32bit) {};
+
+ void clear() throw() {}
+
+ Fixed_Output_RNG(const Botan::SecureVector<byte>& in)
+ {
+ buf.insert(buf.end(), in.begin(), in.begin() + in.size());
+ }
+ Fixed_Output_RNG(const std::string& in_str)
+ {
+ Botan::SecureVector<byte> in = decode_hex(in_str);
+ buf.insert(buf.end(), in.begin(), in.begin() + in.size());
+ }
+
+ Fixed_Output_RNG() {}
+ private:
+ std::deque<byte> buf;
+ };
+
+#endif
diff --git a/botan/checks/cvc_tests.cpp b/botan/checks/cvc_tests.cpp
new file mode 100644
index 0000000..792e9c5
--- /dev/null
+++ b/botan/checks/cvc_tests.cpp
@@ -0,0 +1,600 @@
+/******************************************************
+* CVC EAC1.1 tests *
+* *
+* (C) 2008 Falko Strenzke *
+* strenzke@flexsecure.de *
+* 2008 Jack Lloyd *
+******************************************************/
+
+#include "validate.h"
+#include <botan/build.h>
+
+#if defined(BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES)
+
+#include <iosfwd>
+#include <iostream>
+#include <iterator>
+#include <algorithm>
+#include <fstream>
+#include <vector>
+
+#include <botan/ecdsa.h>
+#include <botan/rsa.h>
+
+#include <botan/x509cert.h>
+#include <botan/x509self.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/cvc_self.h>
+#include <botan/cvc_cert.h>
+#include <botan/util.h>
+#include <botan/cvc_ado.h>
+
+#define TEST_DATA_DIR "checks/ecc_testdata"
+
+using namespace Botan;
+
+#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+
+namespace {
+
+// helper functions
+void helper_write_file(EAC_Signed_Object const& to_write, std::string const& file_path)
+ {
+ SecureVector<byte> sv = to_write.BER_encode();
+ std::ofstream cert_file(file_path.c_str(), std::ios::binary);
+ cert_file.write((char*)sv.begin(), sv.size());
+ cert_file.close();
+ }
+
+bool helper_files_equal(std::string const& file_path1, std::string const& file_path2)
+ {
+ std::ifstream cert_1_in(file_path1.c_str());
+ std::ifstream cert_2_in(file_path2.c_str());
+ SecureVector<byte> sv1;
+ SecureVector<byte> sv2;
+ if (!cert_1_in || !cert_2_in)
+ {
+ return false;
+ }
+ while (!cert_1_in.eof())
+ {
+ char now;
+ cert_1_in.read(&now, 1);
+ sv1.append(now);
+ }
+ while (!cert_2_in.eof())
+ {
+ char now;
+ cert_2_in.read(&now, 1);
+ sv2.append(now);
+ }
+ if (sv1.size() == 0)
+ {
+ return false;
+ }
+ return sv1 == sv2;
+ }
+
+void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC_Options opts;
+ //opts.cpi = 0;
+ opts.chr = ASN1_Chr("my_opt_chr"); // not used
+ opts.car = ASN1_Car("my_opt_car");
+ opts.cex = ASN1_Cex("2010 08 13");
+ opts.ced = ASN1_Ced("2010 07 27");
+ opts.holder_auth_templ = 0xC1;
+ opts.hash_alg = "SHA-256";
+
+ // creating a non sense selfsigned cert w/o dom pars
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
+ ECDSA_PrivateKey key(rng, dom_pars);
+ key.set_parameter_encoding(ENC_IMPLICITCA);
+ EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng);
+
+ SecureVector<byte> der(cert.BER_encode());
+ std::ofstream cert_file;
+ cert_file.open(TEST_DATA_DIR "/my_cv_cert.ber", std::ios::binary);
+ //cert_file << der; // this is bad !!!
+ cert_file.write((char*)der.begin(), der.size());
+ cert_file.close();
+
+ EAC1_1_CVC cert_in(TEST_DATA_DIR "/my_cv_cert.ber");
+ CHECK(cert == cert_in);
+ // encoding it again while it has no dp
+ SecureVector<byte> der2(cert_in.BER_encode());
+ std::ofstream cert_file2(TEST_DATA_DIR "/my_cv_cert2.ber", std::ios::binary);
+ cert_file2.write((char*)der2.begin(), der2.size());
+ cert_file2.close();
+ // read both and compare them
+ std::ifstream cert_1_in(TEST_DATA_DIR "/my_cv_cert.ber");
+ std::ifstream cert_2_in(TEST_DATA_DIR "/my_cv_cert2.ber");
+ SecureVector<byte> sv1;
+ SecureVector<byte> sv2;
+ if (!cert_1_in || !cert_2_in)
+ {
+ CHECK_MESSAGE(false, "could not read certificate files");
+ }
+ while (!cert_1_in.eof())
+ {
+ char now;
+
+ cert_1_in.read(&now, 1);
+ sv1.append(now);
+ }
+ while (!cert_2_in.eof())
+ {
+ char now;
+ cert_2_in.read(&now, 1);
+ sv2.append(now);
+ }
+ CHECK(sv1.size() > 10);
+ CHECK_MESSAGE(sv1 == sv2, "reencoded file of cert without domain parameters is different from original");
+
+ //cout << "reading cert again\n";
+ CHECK(cert_in.get_car().value() == "my_opt_car");
+ CHECK(cert_in.get_chr().value() == "my_opt_car");
+ CHECK(cert_in.get_ced().as_string() == "20100727");
+ CHECK(cert_in.get_ced().readable_string() == "2010/07/27 ");
+
+ bool ill_date_exc = false;
+ try
+ {
+ ASN1_Ced("1999 01 01");
+ }
+ catch (...)
+ {
+ ill_date_exc = true;
+ }
+ CHECK(ill_date_exc);
+
+ bool ill_date_exc2 = false;
+ try
+ {
+ ASN1_Ced("2100 01 01");
+ }
+ catch (...)
+ {
+ ill_date_exc2 = true;
+ }
+ CHECK(ill_date_exc2);
+ //cout << "readable = '" << cert_in.get_ced().readable_string() << "'\n";
+ std::auto_ptr<Public_Key> p_pk = cert_in.subject_public_key();
+ //auto_ptr<ECDSA_PublicKey> ecdsa_pk = dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk);
+ ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
+ // let´s see if encoding is truely implicitca, because this is what the key should have
+ // been set to when decoding (see above)(because it has no domain params):
+ //cout << "encoding = " << p_ecdsa_pk->get_parameter_encoding() << std::endl;
+ CHECK(p_ecdsa_pk->get_parameter_encoding() == ENC_IMPLICITCA);
+ bool exc = false;
+ try
+ {
+ std::cout << "order = " << p_ecdsa_pk->domain_parameters().get_order() << std::endl;
+ }
+ catch (Invalid_State)
+ {
+ exc = true;
+ }
+ CHECK(exc);
+ // set them and try again
+ //cert_in.set_domain_parameters(dom_pars);
+ std::auto_ptr<Public_Key> p_pk2 = cert_in.subject_public_key();
+ ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
+ p_ecdsa_pk2->set_domain_parameters(dom_pars);
+ CHECK(p_ecdsa_pk2->domain_parameters().get_order() == dom_pars.get_order());
+ bool ver_ec = cert_in.check_signature(*p_pk2);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvc certificate");
+ }
+
+void test_enc_gen_req(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC_Options opts;
+
+ //opts.cpi = 0;
+ opts.chr = ASN1_Chr("my_opt_chr");
+ opts.hash_alg = "SHA-160";
+
+ // creating a non sense selfsigned cert w/o dom pars
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ ECDSA_PrivateKey key(rng, dom_pars);
+ key.set_parameter_encoding(ENC_IMPLICITCA);
+ EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng);
+ SecureVector<byte> der(req.BER_encode());
+ std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
+ req_file.write((char*)der.begin(), der.size());
+ req_file.close();
+
+ // read and check signature...
+ EAC1_1_Req req_in(TEST_DATA_DIR "/my_cv_req.ber");
+ //req_in.set_domain_parameters(dom_pars);
+ std::auto_ptr<Public_Key> p_pk = req_in.subject_public_key();
+ ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
+ p_ecdsa_pk->set_domain_parameters(dom_pars);
+ CHECK(p_ecdsa_pk->domain_parameters().get_order() == dom_pars.get_order());
+ bool ver_ec = req_in.check_signature(*p_pk);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (created by myself) cvc request");
+ }
+
+void test_cvc_req_ext(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ //req_in.set_domain_parameters(dom_pars);
+ std::auto_ptr<Public_Key> p_pk = req_in.subject_public_key();
+ ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
+ p_ecdsa_pk->set_domain_parameters(dom_pars);
+ CHECK(p_ecdsa_pk->domain_parameters().get_order() == dom_pars.get_order());
+ bool ver_ec = req_in.check_signature(*p_pk);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (external testdata) cvc request");
+ }
+
+void test_cvc_ado_ext(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_ADO req_in(TEST_DATA_DIR "/ado.cvcreq");
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ //cout << "car = " << req_in.get_car().value() << std::endl;
+ //req_in.set_domain_parameters(dom_pars);
+ }
+
+void test_cvc_ado_creation(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC_Options opts;
+ //opts.cpi = 0;
+ opts.chr = ASN1_Chr("my_opt_chr");
+ opts.hash_alg = "SHA-256";
+
+ // creating a non sense selfsigned cert w/o dom pars
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
+ //cout << "mod = " << hex << dom_pars.get_curve().get_p() << std::endl;
+ ECDSA_PrivateKey req_key(rng, dom_pars);
+ req_key.set_parameter_encoding(ENC_IMPLICITCA);
+ //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
+ EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
+ SecureVector<byte> der(req.BER_encode());
+ std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
+ req_file.write((char*)der.begin(), der.size());
+ req_file.close();
+
+ // create an ado with that req
+ ECDSA_PrivateKey ado_key(rng, dom_pars);
+ EAC1_1_CVC_Options ado_opts;
+ ado_opts.car = ASN1_Car("my_ado_car");
+ ado_opts.hash_alg = "SHA-256"; // must be equal to req´s hash alg, because ado takes his sig_algo from it´s request
+
+ //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
+ EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
+ CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
+
+ std::ofstream ado_file(TEST_DATA_DIR "/ado", std::ios::binary);
+ SecureVector<byte> ado_der(ado.BER_encode());
+ ado_file.write((char*)ado_der.begin(), ado_der.size());
+ ado_file.close();
+ // read it again and check the signature
+ EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
+ CHECK(ado == ado2);
+ //ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
+ //bool ver = ado2.check_signature(*p_ado_pk);
+ bool ver = ado2.check_signature(ado_key);
+ CHECK_MESSAGE(ver, "failure of ado verification after reloading");
+ }
+
+void test_cvc_ado_comparison(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC_Options opts;
+ //opts.cpi = 0;
+ opts.chr = ASN1_Chr("my_opt_chr");
+ opts.hash_alg = "SHA-224";
+
+ // creating a non sense selfsigned cert w/o dom pars
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.11"));
+ ECDSA_PrivateKey req_key(rng, dom_pars);
+ req_key.set_parameter_encoding(ENC_IMPLICITCA);
+ //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
+ EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
+
+
+ // create an ado with that req
+ ECDSA_PrivateKey ado_key(rng, dom_pars);
+ EAC1_1_CVC_Options ado_opts;
+ ado_opts.car = ASN1_Car("my_ado_car1");
+ ado_opts.hash_alg = "SHA-224"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
+ //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
+ EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
+ CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
+ // make a second one for comparison
+ EAC1_1_CVC_Options opts2;
+ //opts2.cpi = 0;
+ opts2.chr = ASN1_Chr("my_opt_chr");
+ opts2.hash_alg = "SHA-160"; // this is the only difference
+ ECDSA_PrivateKey req_key2(rng, dom_pars);
+ req_key.set_parameter_encoding(ENC_IMPLICITCA);
+ //EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2, rng);
+ EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2.chr, opts2.hash_alg, rng);
+ ECDSA_PrivateKey ado_key2(rng, dom_pars);
+ EAC1_1_CVC_Options ado_opts2;
+ ado_opts2.car = ASN1_Car("my_ado_car1");
+ ado_opts2.hash_alg = "SHA-160"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
+
+ EAC1_1_ADO ado2 = CVC_EAC::create_ado_req(ado_key2, req2, ado_opts2.car, rng);
+ CHECK_MESSAGE(ado2.check_signature(ado_key2), "failure of ado verification after creation");
+
+ CHECK_MESSAGE(ado != ado2, "ado's found to be equal where they are not");
+ // std::ofstream ado_file(TEST_DATA_DIR "/ado");
+ // SecureVector<byte> ado_der(ado.BER_encode());
+ // ado_file.write((char*)ado_der.begin(), ado_der.size());
+ // ado_file.close();
+ // read it again and check the signature
+
+ // EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
+ // ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
+ // //bool ver = ado2.check_signature(*p_ado_pk);
+ // bool ver = ado2.check_signature(ado_key);
+ // CHECK_MESSAGE(ver, "failure of ado verification after reloading");
+ }
+
+void test_eac_time(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ const u64bit current_time = system_time();
+ EAC_Time time(current_time);
+ // std::cout << "time as std::string = " << time.as_string() << std::endl;
+ EAC_Time sooner("", ASN1_Tag(99));
+ //X509_Time sooner("", ASN1_Tag(99));
+ sooner.set_to("2007 12 12");
+ // std::cout << "sooner as std::string = " << sooner.as_string() << std::endl;
+ EAC_Time later("2007 12 13");
+ //X509_Time later("2007 12 13");
+ // std::cout << "later as std::string = " << later.as_string() << std::endl;
+ CHECK(sooner <= later);
+ CHECK(sooner == sooner);
+
+ ASN1_Cex my_cex("2007 08 01");
+ my_cex.add_months(12);
+ CHECK(my_cex.get_year() == 2008);
+ CHECK_MESSAGE(my_cex.get_month() == 8, "shoult be 8, was " << my_cex.get_month());
+
+ my_cex.add_months(4);
+ CHECK(my_cex.get_year() == 2008);
+ CHECK(my_cex.get_month() == 12);
+
+ my_cex.add_months(4);
+ CHECK(my_cex.get_year() == 2009);
+ CHECK(my_cex.get_month() == 4);
+
+ my_cex.add_months(41);
+ CHECK(my_cex.get_year() == 2012);
+ CHECK(my_cex.get_month() == 9);
+
+
+
+ }
+
+void test_ver_cvca(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC req_in(TEST_DATA_DIR "/cvca01.cv.crt");
+
+ //auto_ptr<ECDSA_PublicKey> ecdsa_pk = dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk);
+ //ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
+ bool exc = false;
+
+ std::auto_ptr<Public_Key> p_pk2 = req_in.subject_public_key();
+ ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
+ bool ver_ec = req_in.check_signature(*p_pk2);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvca certificate");
+
+ try
+ {
+ p_ecdsa_pk2->domain_parameters().get_order();
+ }
+ catch (Invalid_State)
+ {
+ exc = true;
+ }
+ CHECK(!exc);
+ }
+
+void test_copy_and_assignment(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ EAC1_1_CVC cert_in(TEST_DATA_DIR "/cvca01.cv.crt");
+ EAC1_1_CVC cert_cp(cert_in);
+ EAC1_1_CVC cert_ass = cert_in;
+ CHECK(cert_in == cert_cp);
+ CHECK(cert_in == cert_ass);
+
+ EAC1_1_ADO ado_in(TEST_DATA_DIR "/ado.cvcreq");
+ //EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ EAC1_1_ADO ado_cp(ado_in);
+ EAC1_1_ADO ado_ass = ado_in;
+ CHECK(ado_in == ado_cp);
+ CHECK(ado_in == ado_ass);
+
+ EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
+ //EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ EAC1_1_Req req_cp(req_in);
+ EAC1_1_Req req_ass = req_in;
+ CHECK(req_in == req_cp);
+ CHECK(req_in == req_ass);
+ }
+
+void test_eac_str_illegal_values(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ bool exc = false;
+ try
+ {
+ EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars.cv.crt");
+
+ }
+ catch (Decoding_Error)
+ {
+ exc = true;
+ }
+ CHECK(exc);
+
+ bool exc2 = false;
+ try
+ {
+ EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars2.cv.crt");
+
+ }
+ catch (Decoding_Error)
+ {
+ exc2 = true;
+ }
+ CHECK(exc2);
+ }
+
+void test_tmp_eac_str_enc(RandomNumberGenerator&)
+ {
+ std::cout << "." << std::flush;
+
+ bool exc = false;
+ try
+ {
+ ASN1_Car("abc!+-µ\n");
+ }
+ catch (Invalid_Argument)
+ {
+ exc = true;
+ }
+ CHECK(exc);
+ // std::string val = car.iso_8859();
+ // std::cout << "car 8859 = " << val << std::endl;
+ // std::cout << hex <<(unsigned char)val[1] << std::endl;
+
+
+ }
+
+void test_cvc_chain(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ ECDSA_PrivateKey cvca_privk(rng, dom_pars);
+ std::string hash("SHA-224");
+ ASN1_Car car("DECVCA00001");
+ EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, rng);
+ std::ofstream cvca_file(TEST_DATA_DIR "/cvc_chain_cvca.cer", std::ios::binary);
+ SecureVector<byte> cvca_sv = cvca_cert.BER_encode();
+ cvca_file.write((char*)cvca_sv.begin(), cvca_sv.size());
+ cvca_file.close();
+
+ ECDSA_PrivateKey cvca_privk2(rng, dom_pars);
+ ASN1_Car car2("DECVCA00002");
+ EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, rng);
+ EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, rng);
+ SecureVector<byte> link12_sv = link12.BER_encode();
+ std::ofstream link12_file(TEST_DATA_DIR "/cvc_chain_link12.cer", std::ios::binary);
+ link12_file.write((char*)link12_sv.begin(), link12_sv.size());
+ link12_file.close();
+
+ // verify the link
+ CHECK(link12.check_signature(cvca_privk));
+ EAC1_1_CVC link12_reloaded(TEST_DATA_DIR "/cvc_chain_link12.cer");
+ EAC1_1_CVC cvca1_reloaded(TEST_DATA_DIR "/cvc_chain_cvca.cer");
+ std::auto_ptr<Public_Key> cvca1_rel_pk = cvca1_reloaded.subject_public_key();
+ CHECK(link12_reloaded.check_signature(*cvca1_rel_pk));
+
+ // create first round dvca-req
+ ECDSA_PrivateKey dvca_priv_key(rng, dom_pars);
+ EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, rng);
+ std::ofstream dvca_file(TEST_DATA_DIR "/cvc_chain_dvca_req.cer", std::ios::binary);
+ SecureVector<byte> dvca_sv = dvca_req.BER_encode();
+ dvca_file.write((char*)dvca_sv.begin(), dvca_sv.size());
+ dvca_file.close();
+
+ // sign the dvca_request
+ EAC1_1_CVC dvca_cert1 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req, 1, 5, true, 3, 1, rng);
+ CHECK(dvca_cert1.get_car().iso_8859() == "DECVCA00001");
+ CHECK(dvca_cert1.get_chr().iso_8859() == "DEDVCAEPASS00001");
+ helper_write_file(dvca_cert1, TEST_DATA_DIR "/cvc_chain_dvca_cert1.cer");
+
+ // make a second round dvca ado request
+ ECDSA_PrivateKey dvca_priv_key2(rng, dom_pars);
+ EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, rng);
+ std::ofstream dvca_file2(TEST_DATA_DIR "/cvc_chain_dvca_req2.cer", std::ios::binary);
+ SecureVector<byte> dvca_sv2 = dvca_req2.BER_encode();
+ dvca_file2.write((char*)dvca_sv2.begin(), dvca_sv2.size());
+ dvca_file2.close();
+ EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2,
+ ASN1_Car(dvca_cert1.get_chr().iso_8859()), rng);
+ helper_write_file(dvca_ado2, TEST_DATA_DIR "/cvc_chain_dvca_ado2.cer");
+
+ // verify the ado and sign the request too
+
+ std::auto_ptr<Public_Key> ap_pk = dvca_cert1.subject_public_key();
+ ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get());
+
+ cert_pk->set_domain_parameters(dom_pars);
+ //std::cout << "dvca_cert.public_point.size() = " << ec::EC2OSP(cert_pk->get_public_point(), ec::PointGFp::COMPRESSED).size() << std::endl;
+ EAC1_1_CVC dvca_cert1_reread(TEST_DATA_DIR "/cvc_chain_cvca.cer");
+ CHECK(dvca_ado2.check_signature(*cert_pk));
+
+ CHECK(dvca_ado2.check_signature(dvca_priv_key)); // must also work
+
+ EAC1_1_Req dvca_req2b = dvca_ado2.get_request();
+ helper_write_file(dvca_req2b, TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer");
+ CHECK(helper_files_equal(TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer", TEST_DATA_DIR "/cvc_chain_dvca_req2.cer"));
+ EAC1_1_CVC dvca_cert2 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req2b, 2, 5, true, 3, 1, rng);
+ CHECK(dvca_cert2.get_car().iso_8859() == "DECVCA00001");
+ CHECK_MESSAGE(dvca_cert2.get_chr().iso_8859() == "DEDVCAEPASS00002",
+ "chr = " << dvca_cert2.get_chr().iso_8859());
+
+ // make a first round IS request
+ ECDSA_PrivateKey is_priv_key(rng, dom_pars);
+ EAC1_1_Req is_req = DE_EAC::create_cvc_req(is_priv_key, ASN1_Chr("DEIS"), hash, rng);
+ helper_write_file(is_req, TEST_DATA_DIR "/cvc_chain_is_req.cer");
+
+ // sign the IS request
+ //dvca_cert1.set_domain_parameters(dom_pars);
+ EAC1_1_CVC is_cert1 = DE_EAC::sign_request(dvca_cert1, dvca_priv_key, is_req, 1, 5, true, 3, 1, rng);
+ CHECK_MESSAGE(is_cert1.get_car().iso_8859() == "DEDVCAEPASS00001", "car = " << is_cert1.get_car().iso_8859());
+ CHECK(is_cert1.get_chr().iso_8859() == "DEIS00001");
+ helper_write_file(is_cert1, TEST_DATA_DIR "/cvc_chain_is_cert.cer");
+
+ // verify the signature of the certificate
+ CHECK(is_cert1.check_signature(dvca_priv_key));
+ }
+
+}
+
+u32bit do_cvc_tests(Botan::RandomNumberGenerator& rng)
+ {
+ test_enc_gen_selfsigned(rng);
+ test_enc_gen_req(rng);
+ test_cvc_req_ext(rng);
+ test_cvc_ado_ext(rng);
+ test_cvc_ado_creation(rng);
+ test_cvc_ado_comparison(rng);
+ test_eac_time(rng);
+ test_ver_cvca(rng);
+ test_copy_and_assignment(rng);
+ test_eac_str_illegal_values(rng);
+ test_tmp_eac_str_enc(rng);
+ test_cvc_chain(rng);
+
+ return 0;
+ }
+#else
+u32bit do_cvc_tests(Botan::RandomNumberGenerator&) { return 0; }
+#endif
diff --git a/botan/checks/dolook.cpp b/botan/checks/dolook.cpp
new file mode 100644
index 0000000..0c20448
--- /dev/null
+++ b/botan/checks/dolook.cpp
@@ -0,0 +1,130 @@
+#include <vector>
+#include <string>
+
+#include <botan/lookup.h>
+#include <botan/filters.h>
+#include <botan/libstate.h>
+
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
+#include <botan/bzip2.h>
+#endif
+
+#ifdef BOTAN_HAS_COMPRESSOR_GZIP
+#include <botan/gzip.h>
+#endif
+
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+#include <botan/zlib.h>
+#endif
+
+using namespace Botan;
+
+#include "common.h"
+
+Filter* lookup(const std::string& algname,
+ const std::vector<std::string>& params,
+ const std::string& section)
+ {
+ std::string key = params[0];
+ std::string iv = params[1];
+ Filter* filter = 0;
+
+ // The order of the lookup has to change based on how the names are
+ // formatted and parsed.
+ filter = lookup_kdf(algname, key, iv);
+ if(filter) return filter;
+
+ if(section == "Cipher Modes (Decryption)")
+ filter = lookup_cipher(algname, key, iv, false);
+ else
+ filter = lookup_cipher(algname, key, iv, true);
+ if(filter) return filter;
+
+ filter = lookup_block(algname, key);
+ if(filter) return filter;
+
+ filter = lookup_rng(algname, key);
+ if(filter) return filter;
+
+ filter = lookup_encoder(algname);
+ if(filter) return filter;
+
+ filter = lookup_hash(algname);
+ if(filter) return filter;
+
+ filter = lookup_mac(algname, key);
+ if(filter) return filter;
+
+ filter = lookup_s2k(algname, params);
+ if(filter) return filter;
+
+ return 0;
+ }
+
+Filter* lookup_hash(const std::string& algname)
+ {
+ Filter* hash = 0;
+
+ try {
+ hash = new Hash_Filter(algname);
+ }
+ catch(Algorithm_Not_Found) {}
+
+ return hash;
+ }
+
+Filter* lookup_mac(const std::string& algname, const std::string& key)
+ {
+ Filter* mac = 0;
+ try {
+ mac = new MAC_Filter(algname, key);
+ }
+ catch(Algorithm_Not_Found) {}
+
+ return mac;
+ }
+
+Filter* lookup_cipher(const std::string& algname, const std::string& key,
+ const std::string& iv, bool encrypt)
+ {
+ try {
+ if(encrypt)
+ return get_cipher(algname, key, iv, ENCRYPTION);
+ else
+ return get_cipher(algname, key, iv, DECRYPTION);
+ }
+ catch(Algorithm_Not_Found) {}
+ catch(Invalid_Algorithm_Name) {}
+ return 0;
+ }
+
+Filter* lookup_encoder(const std::string& algname)
+ {
+ if(algname == "Base64_Encode")
+ return new Base64_Encoder;
+ if(algname == "Base64_Decode")
+ return new Base64_Decoder;
+
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
+ if(algname == "Bzip_Compression")
+ return new Bzip_Compression(9);
+ if(algname == "Bzip_Decompression")
+ return new Bzip_Decompression;
+#endif
+
+#ifdef BOTAN_HAS_COMPRESSOR_GZIP
+ if(algname == "Gzip_Compression")
+ return new Gzip_Compression(9);
+ if(algname == "Gzip_Decompression")
+ return new Gzip_Decompression;
+#endif
+
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ if(algname == "Zlib_Compression")
+ return new Zlib_Compression(9);
+ if(algname == "Zlib_Decompression")
+ return new Zlib_Decompression;
+#endif
+
+ return 0;
+ }
diff --git a/botan/checks/dolook2.cpp b/botan/checks/dolook2.cpp
new file mode 100644
index 0000000..51ee8fe
--- /dev/null
+++ b/botan/checks/dolook2.cpp
@@ -0,0 +1,212 @@
+#include <vector>
+#include <string>
+#include <cstdlib>
+
+#include <botan/botan.h>
+#include <botan/lookup.h>
+#include <botan/filters.h>
+
+#include <botan/hmac.h>
+#include <botan/aes.h>
+#include <botan/sha2_32.h>
+#include <botan/sha2_64.h>
+
+#if defined(BOTAN_HAS_RANDPOOL)
+ #include <botan/randpool.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC_RNG)
+ #include <botan/hmac_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_X931_RNG)
+ #include <botan/x931_rng.h>
+ #include <botan/des.h>
+#endif
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ #include <botan/auto_rng.h>
+#endif
+
+#include "common.h"
+using namespace Botan;
+
+
+/* A weird little hack to fit S2K algorithms into the validation suite
+ You probably wouldn't ever want to actually use the S2K algorithms like
+ this, the raw S2K interface is more convenient for actually using them
+*/
+class S2K_Filter : public Filter
+ {
+ public:
+ void write(const byte in[], u32bit len)
+ { passphrase += std::string(reinterpret_cast<const char*>(in), len); }
+ void end_msg()
+ {
+ s2k->change_salt(salt, salt.size());
+ s2k->set_iterations(iterations);
+ SymmetricKey x = s2k->derive_key(outlen, passphrase);
+ send(x.bits_of());
+ }
+ S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i)
+ {
+ s2k = algo;
+ outlen = o;
+ iterations = i;
+ salt = s.bits_of();
+
+ }
+ ~S2K_Filter() { delete s2k; }
+ private:
+ std::string passphrase;
+ S2K* s2k;
+ SecureVector<byte> salt;
+ u32bit outlen, iterations;
+ };
+
+/* Not too useful generally; just dumps random bits for benchmarking */
+class RNG_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ RNG_Filter(RandomNumberGenerator* r) : rng(r) {}
+ ~RNG_Filter() { delete rng; }
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+class KDF_Filter : public Filter
+ {
+ public:
+ void write(const byte in[], u32bit len)
+ { secret.append(in, len); }
+ void end_msg()
+ {
+ SymmetricKey x = kdf->derive_key(outlen,
+ secret, secret.size(),
+ salt, salt.size());
+ send(x.bits_of(), x.length());
+ }
+ KDF_Filter(KDF* algo, const SymmetricKey& s, u32bit o)
+ {
+ kdf = algo;
+ outlen = o;
+ salt = s.bits_of();
+ }
+ ~KDF_Filter() { delete kdf; }
+ private:
+ SecureVector<byte> secret;
+ SecureVector<byte> salt;
+ KDF* kdf;
+ u32bit outlen;
+ };
+
+Filter* lookup_s2k(const std::string& algname,
+ const std::vector<std::string>& params)
+ {
+ S2K* s2k = 0;
+
+ try {
+ s2k = get_s2k(algname);
+ }
+ catch(...) { }
+
+ if(s2k)
+ return new S2K_Filter(s2k, params[0], to_u32bit(params[1]),
+ to_u32bit(params[2]));
+ return 0;
+ }
+
+void RNG_Filter::write(const byte[], u32bit length)
+ {
+ if(length)
+ {
+ SecureVector<byte> out(length);
+ rng->randomize(out, out.size());
+ send(out);
+ }
+ }
+
+Filter* lookup_rng(const std::string& algname,
+ const std::string& key)
+ {
+ RandomNumberGenerator* prng = 0;
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ if(algname == "AutoSeeded")
+ prng = new AutoSeeded_RNG;
+#endif
+
+#if defined(BOTAN_HAS_X931_RNG)
+ if(algname == "X9.31-RNG(TripleDES)")
+ prng = new ANSI_X931_RNG(new TripleDES,
+ new Fixed_Output_RNG(decode_hex(key)));
+ else if(algname == "X9.31-RNG(AES-128)")
+ prng = new ANSI_X931_RNG(new AES_128,
+ new Fixed_Output_RNG(decode_hex(key)));
+ else if(algname == "X9.31-RNG(AES-192)")
+ prng = new ANSI_X931_RNG(new AES_192,
+ new Fixed_Output_RNG(decode_hex(key)));
+ else if(algname == "X9.31-RNG(AES-256)")
+ prng = new ANSI_X931_RNG(new AES_256,
+ new Fixed_Output_RNG(decode_hex(key)));
+#endif
+
+#if defined(BOTAN_HAS_RANDPOOL)
+ if(algname == "Randpool")
+ {
+ prng = new Randpool(new AES_256, new HMAC(new SHA_256));
+
+ prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()),
+ key.length());
+ }
+#endif
+
+#if defined(BOTAN_HAS_X931_RNG)
+ // these are used for benchmarking: AES-256/SHA-256 matches library
+ // defaults, so benchmark reflects real-world performance (maybe)
+ if(algname == "X9.31-RNG")
+ {
+ RandomNumberGenerator* rng =
+#if defined(BOTAN_HAS_HMAC_RNG)
+ new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
+#elif defined(BOTAN_HAS_RANDPOOL)
+ new Randpool(new AES_256, new HMAC(new SHA_256));
+#endif
+
+ prng = new ANSI_X931_RNG(new AES_256, rng);
+
+ }
+#endif
+
+#if defined(BOTAN_HAS_HMAC_RNG)
+ if(algname == "HMAC_RNG")
+ {
+ prng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
+ }
+#endif
+
+ if(prng)
+ {
+ prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()),
+ key.length());
+ return new RNG_Filter(prng);
+ }
+
+ return 0;
+ }
+
+Filter* lookup_kdf(const std::string& algname, const std::string& salt,
+ const std::string& params)
+ {
+ KDF* kdf = 0;
+ try {
+ kdf = get_kdf(algname);
+ }
+ catch(...) { return 0; }
+
+ if(kdf)
+ return new KDF_Filter(kdf, salt, to_u32bit(params));
+ return 0;
+ }
diff --git a/botan/checks/ec_tests.cpp b/botan/checks/ec_tests.cpp
new file mode 100644
index 0000000..2d25e21
--- /dev/null
+++ b/botan/checks/ec_tests.cpp
@@ -0,0 +1,1223 @@
+
+#include <botan/build.h>
+#include "validate.h"
+
+#if !defined(BOTAN_HAS_ECDSA)
+
+void do_ec_tests(RandomNumberGenerator&) { return; }
+
+#else
+
+#include <botan/bigint.h>
+#include <botan/numthry.h>
+#include <botan/mp_types.h>
+#include <botan/curve_gfp.h>
+#include <botan/point_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/ecdsa.h>
+
+using namespace Botan;
+
+#include <iostream>
+#include <assert.h>
+
+#include "getopt.h"
+
+#include "common.h"
+
+#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+
+namespace {
+
+void test_point_turn_on_sp_red_mul_simple()
+ {
+ std::cout << "." << std::flush;
+
+ // setting up expected values
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.36.3.3.2.8.1.1.5"));
+ PointGFp p(dom_pars.get_base_point());
+ p.turn_on_sp_red_mul();
+ CHECK(p.get_affine_x().get_value() != BigInt(0));
+ }
+
+void test_point_turn_on_sp_red_mul()
+ {
+ std::cout << "." << std::flush;
+
+ // setting up expected values
+ std::string test_str("test");
+ BigInt test_bi(3);
+ BigInt exp_Qx(std::string("466448783855397898016055842232266600516272889280"));
+ BigInt exp_Qy(std::string("1110706324081757720403272427311003102474457754220"));
+ BigInt exp_Qz(1);
+
+ // performing calculation to test
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex(p_secp);
+ SecureVector<byte> sv_a_secp = decode_hex(a_secp);
+ SecureVector<byte> sv_b_secp = decode_hex(b_secp);
+ SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp);
+ BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size());
+ BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size());
+ BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size());
+ CurveGFp secp160r1(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1);
+
+ BigInt d("459183204582304");
+
+ PointGFp r1 = d * p_G;
+ CHECK(r1.get_affine_x().get_value() != BigInt("0"));
+
+ PointGFp p_G2(p_G);
+
+ p_G2.turn_on_sp_red_mul();
+
+ PointGFp r2 = d * p_G2;
+ CHECK_MESSAGE(r1 == r2, "error with point mul after extra turn on sp red mul");
+ CHECK(r1.get_affine_x().get_value() != BigInt("0"));
+
+ std::tr1::shared_ptr<PointGFp> p_r1(new PointGFp(r1));
+ std::tr1::shared_ptr<PointGFp> p_r2(new PointGFp(r2));
+
+ p_r1->mult2_in_place(); // wird für Fehler nicht gebraucht
+ p_r2->turn_on_sp_red_mul(); // 1. t_o() macht nur p_r2 kaputt
+ p_r2->turn_on_sp_red_mul(); // 2. t_o() macht auch p_r1 kaputt!!!
+ p_r2->mult2_in_place(); // wird für Fehler nicht gebraucht
+ CHECK_MESSAGE(p_r1->get_affine_x() == p_r2->get_affine_x(), "error with mult2 after extra turn on sp red mul");
+ CHECK(p_r1->get_affine_x().get_value() != BigInt("0"));
+ CHECK(p_r2->get_affine_x().get_value() != BigInt("0"));
+ r1.mult2_in_place();
+
+ r2.turn_on_sp_red_mul();
+ r2.turn_on_sp_red_mul();
+ r2.mult2_in_place();
+
+ CHECK_MESSAGE(r1 == r2, "error with mult2 after extra turn on sp red mul");
+ CHECK_MESSAGE(r1.get_affine_x() == r2.get_affine_x(), "error with mult2 after extra turn on sp red mul");
+ CHECK(r1.get_affine_x().get_value() != BigInt("0"));
+ //std::cout << "r1 x = " << r1.get_affine_x() << endl;
+ r1 += p_G;
+ r2 += p_G2;
+
+ CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul");
+
+ p_G2.turn_on_sp_red_mul();
+
+ r1 += p_G;
+ r2 += p_G2;
+
+ CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul for both operands");
+ p_G2.turn_on_sp_red_mul();
+ r1.turn_on_sp_red_mul();
+ r1 += p_G;
+ r2 += p_G2;
+
+ CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul for both operands");
+ }
+
+void test_coordinates()
+ {
+ std::cout << "." << std::flush;
+
+ //Setting up expected values
+ BigInt exp_x(std::string("1340569834321789103897171369812910390864714275730"));
+ BigInt exp_y(std::string("1270827321510686389126940426305655825361326281787"));
+ BigInt exp_z(std::string("407040228325808215747982915914693784055965283940"));
+ BigInt exp_affine_x(std::string("16984103820118642236896513183038186009872590470"));
+ BigInt exp_affine_y(std::string("1373093393927139016463695321221277758035357890939"));
+
+ // precalculation
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+ PointGFp p0 = p_G;
+ PointGFp p1 = p_G.mult2_in_place();
+ PointGFp point_exp(secp160r1, GFpElement(bi_p_secp, exp_affine_x), GFpElement(bi_p_secp, exp_affine_y));
+ try
+ {
+ point_exp.check_invariants();
+ }
+ catch (Illegal_Point e)
+ {
+ assert(false);
+ }
+
+ // testarea
+ CHECK( p1.get_jac_proj_x().get_value() == exp_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_z);
+ CHECK_MESSAGE( p1.get_affine_x().get_value() == exp_affine_x, " p1_x = " << p1.get_affine_x().get_value() << "\n" << "exp_x = " << exp_affine_x << "\n");
+ CHECK_MESSAGE( p1.get_affine_y().get_value() == exp_affine_y, " p1_y = " << p1.get_affine_y().get_value() << "\n" << "exp_y = " << exp_affine_y << "\n");
+ }
+
+
+/**
+Test point multiplication according to
+--------
+SEC 2: Test Vectors for SEC 1
+Certicom Research
+Working Draft
+September, 1999
+Version 0.3;
+Section 2.1.2
+--------
+*/
+
+void test_point_transformation ()
+ {
+ std::cout << "." << std::flush;
+
+
+ // get a vailid point
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ PointGFp p = dom_pars.get_base_point();
+
+ // get a copy
+ PointGFp q = p;
+
+ //turn on montg.
+ p.turn_on_sp_red_mul();
+ CHECK_MESSAGE( p.get_jac_proj_x().get_value() == q.get_jac_proj_x().get_value(), "projective_x changed while turning on montg.!");
+ CHECK_MESSAGE( p.get_jac_proj_y().get_value() == q.get_jac_proj_y().get_value(), "projective_y changed while turning on montg.!");
+ CHECK_MESSAGE( p.get_jac_proj_z().get_value() == q.get_jac_proj_z().get_value(), "projective_z changed while turning on montg.!");
+ CHECK_MESSAGE( p.get_affine_x().get_value() == q.get_affine_x().get_value(), "affine_x changed while turning on montg.!");
+ CHECK_MESSAGE( p.get_affine_y().get_value() == q.get_affine_y().get_value(), "affine_y changed while turning on montg.!");
+ }
+
+void test_point_mult ()
+ {
+ std::cout << "." << std::flush;
+
+ // setting up expected values
+ std::string test_str("test");
+ BigInt test_bi(3);
+ BigInt exp_Qx(std::string("466448783855397898016055842232266600516272889280"));
+ BigInt exp_Qy(std::string("1110706324081757720403272427311003102474457754220"));
+ BigInt exp_Qz(1);
+
+ // performing calculation to test
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex(p_secp);
+ SecureVector<byte> sv_a_secp = decode_hex(a_secp);
+ SecureVector<byte> sv_b_secp = decode_hex(b_secp);
+ SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp);
+ BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size());
+ BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size());
+ BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size());
+ CurveGFp secp160r1(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1);
+
+ SecureVector<byte> sv_G_dec = EC2OSP(p_G,0x01);
+ std::string str_d_U = "aa374ffc3ce144e6b073307972cb6d57b2a4e982";
+ SecureVector<byte> sv_d_U = decode_hex(str_d_U);
+ BigInt d_U = BigInt::decode(sv_d_U.begin(), sv_d_U.size());
+ PointGFp Q_U = d_U * p_G;
+ CHECK( Q_U.get_jac_proj_x().get_value() == exp_Qx);
+ CHECK( Q_U.get_jac_proj_y().get_value() == exp_Qy);
+ CHECK( Q_U.get_jac_proj_z().get_value() == exp_Qz);
+ }
+
+#if 0
+void test_montgm_calc_R ()
+ {
+ // this tests isnt´t correct anymore. the determination of R has changed
+ // to be 0 mod word_range.
+
+ // setting up (expected) values
+ BigInt prime_modulus(101);
+ u64bit n = prime_modulus.bits();
+ BigInt exp_R(128);
+ // function under test
+ BigInt calc_R = montgm_calc_r_oddmod(prime_modulus);
+ CHECK_MESSAGE(exp_R == calc_R, "exp_R = " << exp_R << ", calc_R = " << calc_R << ", n = " << n << "\n");
+
+ }
+#endif
+
+#if 0
+void test_naive_montg_mult ()
+ {
+ std::cout << "." << std::flush;
+
+ BigInt a_bar(1);
+ BigInt b_bar(2);
+ BigInt m(11);
+ BigInt m_dash(13);
+ BigInt r(5);
+ //BigInt test_res = montg_mult(a_bar, b_bar, m, m_dash, r);
+ //cout << "test_res = " << test_res << "\n";
+ GFpElement a_norm_mult(11, 3);
+ GFpElement b_norm_mult(11, 5);
+ GFpElement c_norm_mult = a_norm_mult * b_norm_mult;
+ //cout << "c_norm_mult = " << c_norm_mult << "\n";
+ GFpElement a_mm(11, 3, true);
+ GFpElement b_mm(11, 5, true);
+ GFpElement c_mm = a_mm * b_mm;
+ //cout << "c_mm = " << c_mm << "\n";
+ CHECK_MESSAGE(c_norm_mult == c_mm, "c_norm_mult = " << c_norm_mult << "\n" << "c_mm = " << c_mm << "\n");
+ }
+#endif
+
+#if 0
+
+void test_trf_mres ()
+ {
+ // this tests isnt´t correct anymore. the determination of R has changed
+ // to be 0 mod word_range.
+
+ //
+ BigInt modulus(11);
+ BigInt r = montgm_calc_r_oddmod(modulus);
+ //cout << "r = " << r << "\n";
+ BigInt r_inv = inverse_mod(r, modulus);
+ //cout << "r_inv = " << r_inv << "\n";
+ // see C43:
+ BigInt exp_m_dash(13);
+ BigInt calc_m_dash = montgm_calc_m_dash(r, modulus, r_inv);
+ CHECK_MESSAGE(exp_m_dash == calc_m_dash, "exp_m_dash = " << exp_m_dash << "\n" << "calc_m_dash = " << calc_m_dash << "\n");
+ BigInt ord_res(7);
+ BigInt exp_m_res(2); // see C43
+ BigInt calc_m_res = montg_trf_to_mres(ord_res, r, modulus);
+ CHECK_MESSAGE(calc_m_res == exp_m_res, "calc_m_res = " << calc_m_res << "\nexp_m_res = " << exp_m_res);
+ BigInt calc_ord_res_back = montg_trf_to_ordres(calc_m_res,modulus, r_inv);
+ CHECK_MESSAGE(ord_res == calc_ord_res_back, "ord_res = " << ord_res << "\ncalc_ord_res_back = " << calc_ord_res_back << "\n");
+ }
+#endif
+
+void test_point_negative()
+ {
+ std::cout << "." << std::flush;
+
+ //Setting up expected values
+ BigInt exp_p1_x(std::string("1340569834321789103897171369812910390864714275730"));
+ BigInt exp_p1_y(std::string("1270827321510686389126940426305655825361326281787"));
+ BigInt exp_p1_neg_x(std::string("1340569834321789103897171369812910390864714275730"));
+ BigInt exp_p1_neg_y(std::string("190674315820216529076744406410627194292458777540"));
+
+ // performing calculation to test
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+
+ PointGFp p1 = p_G.mult2_in_place();
+
+ CHECK( p1.get_jac_proj_x().get_value() == exp_p1_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_p1_y);
+ //cout << "p1.y_proj = " << p1.get_jac_proj_y() << "\n";
+ PointGFp p1_neg = p1.negate();
+ //cout << "p1_neg.y_proj = " << p1_neg.get_jac_proj_y() << "\n";
+ //p1.negate();
+ BigInt calc_y_value = p1_neg.get_jac_proj_y().get_value();
+ BigInt calc_z_value = p1_neg.get_jac_proj_z().get_value();
+ CHECK( p1_neg.get_jac_proj_x().get_value() == exp_p1_neg_x);
+ CHECK_MESSAGE( calc_y_value == exp_p1_neg_y, "calc_y_value = " << calc_y_value << "\nexp_p1_neg_v = " << exp_p1_neg_y);
+ //CHECK_MESSAGE( calc_z_value == exp_p1_neg_y, "calc_y_value = " << calc_y_value << "\nexp_p1_neg_v = " << exp_p1_neg_y);
+ }
+
+void test_zeropoint()
+ {
+ std::cout << "." << std::flush;
+
+
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730");
+ BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787");
+ BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940");
+
+ GFpElement elem_p1_x(bi_p_secp, bi_p1_xval);
+ GFpElement elem_p1_y(bi_p_secp, bi_p1_yval);
+ GFpElement elem_p1_z(bi_p_secp, bi_p1_zval);
+
+
+ PointGFp p1(secp160r1,elem_p1_x, elem_p1_y, elem_p1_z);
+
+ p1.check_invariants();
+ p1 -= p1;
+ // cout << "p1 x " << p1.get_jac_proj_x().get_value() << "\n";
+ // cout << "p1 y " << p1.get_jac_proj_y().get_value() << "\n";
+ // cout << "p1 z " << p1.get_jac_proj_z().get_value() << "\n";
+
+ CHECK_MESSAGE( p1.is_zero(), "p - q with q = p is not zero!");
+ }
+
+void test_zeropoint_enc_dec()
+ {
+ std::cout << "." << std::flush;
+
+
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ CurveGFp curve ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ PointGFp p(curve);
+ CHECK_MESSAGE( p.is_zero(), "by constructor created zeropoint is no zeropoint!");
+
+
+ SecureVector<byte> sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED);
+ PointGFp p_encdec = OS2ECP(sv_p, curve);
+ CHECK_MESSAGE( p == p_encdec, "encoded-decoded (uncompressed) point is not equal the original!");
+
+ sv_p = EC2OSP(p, PointGFp::UNCOMPRESSED);
+ p_encdec = OS2ECP(sv_p, curve);
+ CHECK_MESSAGE( p == p_encdec, "encoded-decoded (compressed) point is not equal the original!");
+
+ sv_p = EC2OSP(p, PointGFp::HYBRID);
+ p_encdec = OS2ECP(sv_p, curve);
+ CHECK_MESSAGE( p == p_encdec, "encoded-decoded (hybrid) point is not equal the original!");
+ }
+
+void test_calc_with_zeropoint()
+ {
+ std::cout << "." << std::flush;
+
+
+
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ CurveGFp curve ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730");
+ BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787");
+ BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940");
+
+ GFpElement elem_p1_x(bi_p_secp, bi_p1_xval);
+ GFpElement elem_p1_y(bi_p_secp, bi_p1_yval);
+ GFpElement elem_p1_z(bi_p_secp, bi_p1_zval);
+
+ PointGFp p(curve,elem_p1_x, elem_p1_y, elem_p1_z);
+
+ p.check_invariants();
+ CHECK_MESSAGE( !p.is_zero(), "created is zeropoint, shouldn't be!");
+
+ PointGFp zero(curve);
+ CHECK_MESSAGE( zero.is_zero(), "by constructor created zeropoint is no zeropoint!");
+
+ PointGFp res = p + zero;
+ CHECK_MESSAGE( res == p, "point + zeropoint is not equal the point");
+
+ res = p - zero;
+ CHECK_MESSAGE( res == p, "point - zeropoint is not equal the point");
+
+ res = zero * 32432243;
+ CHECK_MESSAGE( res.is_zero(), "zeropoint * skalar is not a zero-point!");
+ }
+
+void test_add_point()
+ {
+ std::cout << "." << std::flush;
+
+ //Setting up expected values
+ BigInt exp_add_x(std::string("1435263815649099438763411093143066583800699119469"));
+ BigInt exp_add_y(std::string("1300090790154238148372364036549849084558669436512"));
+ BigInt exp_add_z(std::string("562006223742588575209908669014372619804457947208"));
+
+ // precalculation
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+
+ PointGFp p0 = p_G;
+ PointGFp p1 = p_G.mult2_in_place();
+
+ PointGFp expected ( secp160r1, GFpElement(bi_p_secp, BigInt(exp_add_x)),
+ GFpElement(bi_p_secp, BigInt(exp_add_y)), GFpElement(bi_p_secp, BigInt(exp_add_z)));
+
+ p1 += p0;
+ CHECK(p1 == expected);
+#if 0
+ CHECK( p1.get_jac_proj_x().get_value() == exp_add_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_add_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_add_z);
+#endif
+ }
+
+void test_sub_point()
+ {
+ std::cout << "." << std::flush;
+
+ //Setting up expected values
+ BigInt exp_sub_x(std::string("112913490230515010376958384252467223283065196552"));
+ BigInt exp_sub_y(std::string("143464803917389475471159193867377888720776527730"));
+ BigInt exp_sub_z(std::string("562006223742588575209908669014372619804457947208"));
+
+ // precalculation
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+
+ PointGFp p0 = p_G;
+ PointGFp p1 = p_G.mult2_in_place();
+
+ p1 -= p0;
+ PointGFp expected ( secp160r1, GFpElement(bi_p_secp, BigInt(exp_sub_x)),
+ GFpElement(bi_p_secp, BigInt(exp_sub_y)), GFpElement(bi_p_secp, BigInt(exp_sub_z)));
+ CHECK(p1 == expected);
+
+#if 0
+ CHECK( p1.get_jac_proj_x().get_value() == exp_sub_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_sub_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_sub_z);
+#endif
+ }
+
+void test_mult_point()
+ {
+ std::cout << "." << std::flush;
+
+ //Setting up expected values
+ BigInt exp_mult_x(std::string("967697346845926834906555988570157345422864716250"));
+ BigInt exp_mult_y(std::string("512319768365374654866290830075237814703869061656"));
+ BigInt exp_mult_z(std::string("1"));
+
+ // precalculation
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+
+ PointGFp p0 = p_G;
+ PointGFp p1 = p_G.mult2_in_place();
+
+ p1 *= p0.get_jac_proj_x().get_value();
+
+ PointGFp expected ( secp160r1, GFpElement(bi_p_secp, BigInt(exp_mult_x)),
+ GFpElement(bi_p_secp, BigInt(exp_mult_y)), GFpElement(bi_p_secp, BigInt(exp_mult_z)));
+ CHECK(p1 == expected);
+
+#if 0
+ CHECK( p1.get_jac_proj_x().get_value() == exp_mult_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_mult_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_mult_z);
+#endif
+ }
+
+void test_basic_operations()
+ {
+ std::cout << "." << std::flush;
+
+
+ // set up expected values
+ BigInt exp_p1_x(std::string("1340569834321789103897171369812910390864714275730"));
+ BigInt exp_p1_y(std::string("1270827321510686389126940426305655825361326281787"));
+ BigInt exp_p1_z(std::string("407040228325808215747982915914693784055965283940"));
+
+ BigInt exp_p0_x(std::string("425826231723888350446541592701409065913635568770"));
+ BigInt exp_p0_y(std::string("203520114162904107873991457957346892027982641970"));
+ BigInt exp_p0_z(std::string("1"));
+
+ BigInt exp_plus_x(std::string("1435263815649099438763411093143066583800699119469"));
+ BigInt exp_plus_y(std::string("1300090790154238148372364036549849084558669436512"));
+ BigInt exp_plus_z(std::string("562006223742588575209908669014372619804457947208"));
+
+ BigInt exp_minus_x(std::string("112913490230515010376958384252467223283065196552"));
+ BigInt exp_minus_y(std::string("143464803917389475471159193867377888720776527730"));
+ BigInt exp_minus_z(std::string("562006223742588575209908669014372619804457947208"));
+
+ BigInt exp_mult_x(std::string("43638877777452195295055270548491599621118743290"));
+ BigInt exp_mult_y(std::string("56841378500012376527163928510402662349220202981"));
+ BigInt exp_mult_z(std::string("1"));
+
+ // precalculation
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+
+ PointGFp p0 = p_G;
+ PointGFp p1 = p_G.mult2_in_place();
+
+ // check that all points have correct values
+ CHECK( p1.get_jac_proj_x().get_value() == exp_p1_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_p1_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_p1_z);
+
+ PointGFp expected ( secp160r1, GFpElement(bi_p_secp, exp_p0_x),
+ GFpElement(bi_p_secp, exp_p0_y), GFpElement(bi_p_secp, exp_p0_z));
+ CHECK(p0 == expected);
+#if 0
+ CHECK( p0.get_jac_proj_x().get_value() == exp_p0_x);
+ CHECK( p0.get_jac_proj_y().get_value() == exp_p0_y);
+ CHECK( p0.get_jac_proj_z().get_value() == exp_p0_z);
+#endif
+
+ PointGFp simplePlus= p1 + p0;
+ PointGFp exp_simplePlus ( secp160r1, GFpElement(bi_p_secp, exp_plus_x),
+ GFpElement(bi_p_secp, exp_plus_y), GFpElement(bi_p_secp, exp_plus_z));
+ CHECK(simplePlus == exp_simplePlus);
+#if 0
+ CHECK( simplePlus.get_jac_proj_x().get_value() == exp_plus_x);
+ CHECK( simplePlus.get_jac_proj_y().get_value() == exp_plus_y);
+ CHECK( simplePlus.get_jac_proj_z().get_value() == exp_plus_z);
+#endif
+
+ PointGFp simpleMinus= p1 - p0;
+ PointGFp exp_simpleMinus ( secp160r1, GFpElement(bi_p_secp, exp_minus_x),
+ GFpElement(bi_p_secp, exp_minus_y), GFpElement(bi_p_secp, exp_minus_z));
+ CHECK(simpleMinus == exp_simpleMinus);
+#if 0
+ CHECK( simpleMinus.get_jac_proj_x().get_value() == exp_minus_x);
+ CHECK( simpleMinus.get_jac_proj_y().get_value() == exp_minus_y);
+ CHECK( simpleMinus.get_jac_proj_z().get_value() == exp_minus_z);
+#endif
+
+ PointGFp simpleMult= p1 * 123456789;
+ CHECK( simpleMult.get_jac_proj_x().get_value() == exp_mult_x);
+ CHECK( simpleMult.get_jac_proj_y().get_value() == exp_mult_y);
+ CHECK( simpleMult.get_jac_proj_z().get_value() == exp_mult_z);
+
+ // check that all initial points hasn't changed
+ CHECK( p1.get_jac_proj_x().get_value() == exp_p1_x);
+ CHECK( p1.get_jac_proj_y().get_value() == exp_p1_y);
+ CHECK( p1.get_jac_proj_z().get_value() == exp_p1_z);
+
+ CHECK( p0.get_jac_proj_x().get_value() == exp_p0_x);
+ CHECK( p0.get_jac_proj_y().get_value() == exp_p0_y);
+ CHECK( p0.get_jac_proj_z().get_value() == exp_p0_z);
+ }
+
+void test_enc_dec_compressed_160()
+ {
+ std::cout << "." << std::flush;
+
+
+ // Test for compressed conversion (02/03) 160bit
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffC";
+ std::string b_secp = "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45";
+ std::string G_secp_comp = "024A96B5688EF573284664698968C38BB913CBFC82";
+ std::string G_order_secp_comp = "0100000000000000000001F4C8F927AED3CA752257";
+
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+ SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
+
+ CHECK( sv_result == sv_G_secp_comp);
+ }
+
+void test_enc_dec_compressed_256()
+ {
+ std::cout << "." << std::flush;
+
+
+ // Test for compressed conversion (02/03) 256bit
+ std::string p_secp = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
+ std::string a_secp = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffFC";
+ std::string b_secp = "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B";
+ std::string G_secp_comp = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296";
+ std::string G_order_secp_comp = "ffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551";
+
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 );
+ SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::COMPRESSED);
+
+ CHECK( sv_result == sv_G_secp_comp);
+ }
+
+
+void test_enc_dec_uncompressed_112()
+ {
+ std::cout << "." << std::flush;
+
+
+ // Test for uncompressed conversion (04) 112bit
+
+ std::string p_secp = "db7c2abf62e35e668076bead208b";
+ std::string a_secp = "6127C24C05F38A0AAAF65C0EF02C";
+ std::string b_secp = "51DEF1815DB5ED74FCC34C85D709";
+ std::string G_secp_uncomp = "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97";
+ std::string G_order_secp_uncomp = "36DF0AAFD8B8D7597CA10520D04B";
+
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_uncomp = decode_hex ( G_secp_uncomp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 );
+ SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
+
+ CHECK( sv_result == sv_G_secp_uncomp);
+ }
+
+void test_enc_dec_uncompressed_521()
+ {
+ std::cout << "." << std::flush;
+
+
+ // Test for uncompressed conversion(04) with big values(521 bit)
+ std::string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ std::string a_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC";
+ std::string b_secp = "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00";
+ std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
+ std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409";
+
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_uncomp = decode_hex ( G_secp_uncomp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+
+ CurveGFp secp160r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+
+ PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, secp160r1 );
+
+ SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
+ std::string result = hex_encode(sv_result.begin(), sv_result.size());
+ std::string exp_result = hex_encode(sv_G_secp_uncomp.begin(), sv_G_secp_uncomp.size());
+
+ CHECK_MESSAGE( sv_result == sv_G_secp_uncomp, "\ncalc. result = " << result << "\nexp. result = " << exp_result << "\n");
+ }
+
+void test_enc_dec_uncompressed_521_prime_too_large()
+ {
+ std::cout << "." << std::flush;
+
+
+ // Test for uncompressed conversion(04) with big values(521 bit)
+ std::string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // length increased by "ff"
+ std::string a_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC";
+ std::string b_secp = "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00";
+ std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
+ std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409";
+
+ SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_uncomp = decode_hex ( G_secp_uncomp );
+
+ BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+
+ CurveGFp secp521r1 ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ std::auto_ptr<PointGFp> p_G;
+ bool exc = false;
+ try
+ {
+ p_G = std::auto_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1)));
+ p_G->check_invariants();
+ }
+ catch (std::exception e)
+ {
+ exc = true;
+ }
+
+ CHECK_MESSAGE(exc, "attempt of creation of point on curve with too high prime did not throw an exception");
+#if 0
+ cout << "mX == " << p_G.get_jac_proj_x() << endl;
+ std::cout << "mY == " << p_G.get_jac_proj_y() << endl;
+ std::cout << "mZ == " << p_G.get_jac_proj_x() << endl;
+#endif
+ //SecureVector<byte> sv_result = EC2OSP(p_G, PointGFp::UNCOMPRESSED);
+ //string result = hex_encode(sv_result.begin(), sv_result.size());
+ //string exp_result = hex_encode(sv_G_secp_uncomp.begin(), sv_G_secp_uncomp.size());
+
+ //CHECK_MESSAGE( sv_result == sv_G_secp_uncomp, "\ncalc. result = " << result << "\nexp. result = " << exp_result << "\n");
+ }
+
+void test_gfp_store_restore()
+ {
+ std::cout << "." << std::flush;
+
+ // generate point
+ //EC_Domain_Params dom_pars = global_config().get_ec_dompar("1.3.132.0.8");
+ //EC_Domain_Params dom_pars("1.3.132.0.8");
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ PointGFp p = dom_pars.get_base_point();
+
+ //store point (to std::string)
+ SecureVector<byte> sv_mes = EC2OSP(p, PointGFp::COMPRESSED);
+ std::string storrage = hex_encode(sv_mes, sv_mes.size());
+
+ // restore point (from std::string)
+ SecureVector<byte> sv_new_point = decode_hex(storrage);
+ PointGFp new_p = OS2ECP(sv_new_point, dom_pars.get_curve());
+
+ CHECK_MESSAGE( p == new_p, "original and restored point are different!");
+ }
+
+
+// maybe move this test
+void test_cdc_curve_33()
+ {
+ std::cout << "." << std::flush;
+
+ std::string G_secp_uncomp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
+
+ SecureVector<byte> sv_G_uncomp = decode_hex ( G_secp_uncomp );
+
+ BigInt bi_p_secp = BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
+ BigInt bi_a_secp("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe");
+ BigInt bi_b_secp("0xa9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7");
+
+ CurveGFp curve( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_uncomp, curve);
+ bool exc = false;
+ try
+ {
+ p_G.check_invariants();
+ }
+ catch (std::exception& e)
+ {
+ exc = true;
+ }
+ CHECK(!exc);
+ }
+
+void test_more_zeropoint()
+ {
+ std::cout << "." << std::flush;
+ // by Falko
+
+
+
+ std::string G = "024a96b5688ef573284664698968c38bb913cbfc82";
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G );
+ BigInt bi_p("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ CurveGFp curve( GFpElement ( bi_p,bi_a ), GFpElement ( bi_p, bi_b ), bi_p );
+
+ BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730");
+ BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787");
+ BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940");
+
+ GFpElement elem_p1_x(bi_p, bi_p1_xval);
+ GFpElement elem_p1_y(bi_p, bi_p1_yval);
+ GFpElement elem_p1_z(bi_p, bi_p1_zval);
+
+ PointGFp p1(curve,elem_p1_x, elem_p1_y, elem_p1_z);
+
+ p1.check_invariants();
+ PointGFp minus_p1 = -p1;
+ minus_p1.check_invariants();
+ PointGFp shouldBeZero = p1 + minus_p1;
+ shouldBeZero.check_invariants();
+ GFpElement x1 = p1.get_affine_x();
+ GFpElement y1 = p1.get_affine_y();
+
+ GFpElement shouldBeY2 = -y1;
+
+ CHECK_MESSAGE(minus_p1.get_affine_x() == x1, "problem with minus_p1 : x");
+ CHECK_MESSAGE(minus_p1.get_affine_y() == shouldBeY2, "problem with minus_p1 : y");
+
+ PointGFp zero(curve);
+ zero.check_invariants();
+ CHECK_MESSAGE(p1 + zero == p1, "addition of zero modified point");
+
+#if 0
+ std::cout << "sbz x " << shouldBeZero.get_jac_proj_x().get_value() << "\n";
+ std::cout << "sbz y " << shouldBeZero.get_jac_proj_y().get_value() << "\n";
+ std::cout << "sbz z " << shouldBeZero.get_jac_proj_z().get_value() << "\n";
+#endif
+
+ CHECK_MESSAGE( shouldBeZero.is_zero(), "p - q with q = p is not zero!");
+ }
+
+void test_mult_by_order()
+ {
+ std::cout << "." << std::flush;
+ // std::cout << "starting test_mult_by_order..." << endl;
+
+
+
+ // generate point
+ //EC_Domain_Params dom_pars = global_config().get_ec_dompar("1.3.132.0.8");
+ //EC_Domain_Params dom_pars("1.3.132.0.8");
+ EC_Domain_Params dom_pars = get_EC_Dom_Pars_by_oid("1.3.132.0.8");
+ PointGFp p = dom_pars.get_base_point();
+ PointGFp shouldBeZero = p * dom_pars.get_order();
+#if 0
+ cout << "sbz x " << shouldBeZero.get_jac_proj_x().get_value() << "\n";
+ std::cout << "sbz y " << shouldBeZero.get_jac_proj_y().get_value() << "\n";
+ std::cout << "sbz z " << shouldBeZero.get_jac_proj_z().get_value() << "\n";
+#endif
+ CHECK_MESSAGE(shouldBeZero.is_zero(), "G * order != O");
+ }
+
+void test_gfp_curve_precomp_mres()
+ {
+ std::cout << "." << std::flush;
+
+
+ //EC_Domain_Params parA("1.2.840.10045.3.1.1");
+ EC_Domain_Params parA(get_EC_Dom_Pars_by_oid("1.2.840.10045.3.1.1"));
+ CurveGFp curve1 = parA.get_curve();
+ CurveGFp curve2 = parA.get_curve();
+ BigInt p = curve1.get_p();
+ GFpElement x(p, BigInt("2304042084023"));
+ GFpElement a1_or = curve1.get_a();
+ CHECK(!a1_or.is_trf_to_mres());
+
+ GFpElement b1_mr = curve1.get_mres_b();
+ CHECK(b1_mr.is_trf_to_mres());
+
+ GFpElement a2_mr = curve2.get_mres_a();
+ CHECK(a2_mr.is_trf_to_mres());
+
+ GFpElement b2_or = curve2.get_b();
+ CHECK(!b2_or.is_trf_to_mres());
+
+ GFpElement prodA = a1_or*b1_mr;
+ GFpElement prodB = a2_mr*b2_or;
+ CHECK(prodA == prodB);
+
+ CHECK(a1_or * x == a2_mr * x);
+ CHECK(x* a1_or == a1_or * x);
+ CHECK(x* a1_or == x * a2_mr);
+ CHECK(x* a1_or == a2_mr * x);
+
+ CHECK(a1_or + a2_mr == a2_mr + a1_or);
+ CHECK(a1_or + b1_mr == a2_mr + b1_mr);
+ CHECK(a1_or + x == a2_mr + x);
+ }
+
+#if 0
+void test_point_worksp()
+ {
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ std::tr1::shared_ptr<std::vector<GFpElement> > worksp1;
+ assert(worksp1.get() == 0);
+ {
+ PointGFp p = dom_pars.get_base_point();
+ worksp1 = p.get_worksp_gfp();
+ }
+ PointGFp p2 = dom_pars.get_base_point();
+ p2.set_worksp_gfp(worksp1);
+ PointGFp p3 = p2*6;
+ PointGFp p4 = dom_pars.get_base_point();
+ p4 *= 6;
+ CHECK_MESSAGE(p4 == p3,"points are not equal" );
+ p2 *= 10;
+ for(int i=0; i<3; i++)
+ {
+
+ PointGFp p5 = dom_pars.get_base_point();
+ p5.set_worksp_gfp(worksp1);
+ p5 *= 10;
+ CHECK(p5 == p2);
+ }
+ }
+#endif
+
+void test_point_swap(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+
+ PointGFp a(create_random_point(rng, dom_pars.get_curve()));
+ PointGFp b(create_random_point(rng, dom_pars.get_curve()));
+ b *= BigInt(20);
+
+ PointGFp c(a);
+ PointGFp d(b);
+
+ d.swap(c);
+ CHECK(a == d);
+ CHECK(b == c);
+ }
+
+/**
+* This test verifies that the side channel attack resistant multiplication function
+* yields the same result as the normal (insecure) multiplication via operator*=
+*/
+void test_mult_sec()
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ PointGFp a(dom_pars.get_base_point());
+ BigInt scal("123413545342234");
+ PointGFp b = a * scal;
+ PointGFp c(a);
+ c.mult_this_secure(scal, dom_pars.get_order(), dom_pars.get_order()-1);
+ PointGFp d(a);
+ d.mult_this_secure(scal, BigInt(0), dom_pars.get_order()-1);
+ CHECK(b == c);
+ CHECK(c == d);
+ }
+
+/**
+* This test verifies that the side channel attack resistant multiplication function
+* yields the same result as the normal (insecure) multiplication via operator*=
+*/
+void test_mult_sec_mass(RandomNumberGenerator& rng)
+ {
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ for(int i = 0; i<50; i++)
+ {
+ std::cout << "." << std::flush;
+ std::cout.flush();
+ PointGFp a(create_random_point(rng, dom_pars.get_curve()));
+ BigInt scal(BigInt(rng, 40));
+ PointGFp b = a * scal;
+ PointGFp c(a);
+ c.mult_this_secure(scal, dom_pars.get_order()*dom_pars.get_cofactor(), dom_pars.get_order()-1);
+ //PointGFp d(a);
+ //d.mult_this_secure(scal, BigInt(0), dom_pars.get_order()-1);
+ CHECK(b == c);
+ //CHECK(c == d);
+ }
+ }
+
+/**
+* The following test verifies that PointGFps copy-ctor and assignment operator
+* produce non-sharing Objects
+*/
+void test_point_ctors_ass_unshared()
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ PointGFp p = dom_pars.get_base_point();
+ PointGFp ind_cpy(p);
+
+ // doesn´t work this way, because getters of point return an independent copy!
+ CHECK(p.get_jac_proj_x().get_ptr_mod().get() != ind_cpy.get_jac_proj_x().get_ptr_mod().get());
+ //CHECK(p.get_x().get_ptr_r().get() != ind_cpy.get_x().get_ptr_r().get());
+
+ PointGFp ind_ass(p);
+ ind_ass = p;
+ CHECK(p.get_jac_proj_x().get_ptr_mod().get() != ind_ass.get_jac_proj_x().get_ptr_mod().get());
+ //CHECK(p.get_x().get_ptr_r().get() != ind_ass.get_x().get_ptr_r().get());
+ }
+
+void test_curve_cp_ctor()
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ CurveGFp curve(dom_pars.get_curve());
+ }
+
+/**
+* The following test checks assignment operator and copy ctor for ec keys
+*/
+void test_ec_key_cp_and_assignment(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ SecureVector<byte> sv_g_secp = decode_hex ( g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+
+ EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor);
+ ECDSA_PrivateKey my_priv_key(rng, dom_pars);
+
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+
+ // sign with the original key
+ SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+
+ // make a copy and sign
+ ECDSA_PrivateKey cp_key(my_priv_key);
+ SecureVector<byte> cp_sig = cp_key.sign(sv_message.begin(), sv_message.size(), rng);
+
+ // now cross verify...
+ CHECK(my_priv_key.verify(sv_message.begin(), sv_message.size(), cp_sig.begin(), cp_sig.size()));
+ CHECK(cp_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()));
+
+ // make an copy assignment and verify
+ ECDSA_PrivateKey ass_key = my_priv_key;
+ SecureVector<byte> ass_sig = ass_key.sign(sv_message.begin(), sv_message.size(), rng);
+
+ // now cross verify...
+ CHECK(my_priv_key.verify(sv_message.begin(), sv_message.size(), ass_sig.begin(), ass_sig.size()));
+ CHECK(ass_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size()));
+ }
+
+void test_ec_key_cast(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ SecureVector<byte> sv_g_secp = decode_hex ( g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+
+ EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor);
+ ECDSA_PrivateKey my_priv_key(rng, dom_pars);
+ ECDSA_PublicKey my_ecdsa_pub_key = my_priv_key;
+
+ Public_Key* my_pubkey = static_cast<Public_Key*>(&my_ecdsa_pub_key);
+ ECDSA_PublicKey* ec_cast_back = dynamic_cast<ECDSA_PublicKey*>(my_pubkey);
+
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+
+ // sign with the original key
+ SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success = ec_cast_back->verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+ }
+
+}
+
+void do_ec_tests(RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing ECC: " << std::flush;
+
+ test_point_turn_on_sp_red_mul_simple();
+ test_point_turn_on_sp_red_mul();
+ test_coordinates();
+ test_point_transformation ();
+ test_point_mult ();
+ //test_montgm_calc_R ();
+ //test_naive_montg_mult ();
+ //test_trf_mres ();
+ test_point_negative();
+ test_zeropoint();
+ test_zeropoint_enc_dec();
+ test_calc_with_zeropoint();
+ test_add_point();
+ test_sub_point();
+ test_mult_point();
+ test_basic_operations();
+ test_enc_dec_compressed_160();
+ test_enc_dec_compressed_256();
+ test_enc_dec_uncompressed_112();
+ test_enc_dec_uncompressed_521();
+ test_enc_dec_uncompressed_521_prime_too_large();
+ test_gfp_store_restore();
+ test_cdc_curve_33();
+ test_more_zeropoint();
+ test_mult_by_order();
+ test_gfp_curve_precomp_mres();
+ //test_point_worksp();
+ test_point_swap(rng);
+ test_mult_sec();
+ test_mult_sec_mass(rng);
+ test_point_ctors_ass_unshared();
+ test_curve_cp_ctor();
+ test_ec_key_cp_and_assignment(rng);
+ test_ec_key_cast(rng);
+
+ std::cout << std::endl;
+ }
+
+#endif
+
diff --git a/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.crt b/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.crt
new file mode 100644
index 0000000..8653f96
--- /dev/null
+++ b/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.pem b/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.pem
new file mode 100644
index 0000000..725e163
--- /dev/null
+++ b/botan/checks/ecc_testdata/CSCA.CSCA.csca-germany.1.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAwWgAwIBAgIBATAMBggqhkjOPQQDAQUAMFAxCzAJBgNVBAYTAkRFMQ0w
+CwYDVQQKDARidW5kMQwwCgYDVQQLDANic2kxDTALBgNVBAUTBDQ1NjcxFTATBgNV
+BAMMDGNzY2EtZ2VybWFueTAeFw0wNzA3MTkxNTI3MThaFw0yODAxMTkxNTE4MDBa
+MFAxCzAJBgNVBAYTAkRFMQ0wCwYDVQQKDARidW5kMQwwCgYDVQQLDANic2kxDTAL
+BgNVBAUTBDQ1NjcxFTATBgNVBAMMDGNzY2EtZ2VybWFueTCCARMwgdQGByqGSM49
+AgEwgcgCAQEwKAYHKoZIzj0BAQIdANfBNKomQ2aGKhgwJXXR14ewnwdXl9qJ9X7I
+wP8wPAQcaKXmLKnObBwpmAOmwVMLUU4YKtiwBCpZytKfQwQcJYD2PM/kQTiHBxOx
+qSNp4z4hNdJm27NyOGxACwQ5BA2QKa0sflz0NAgjsqh9xoyeTOMXTB5u/e4SwH1Y
+qlb3csBybyTGuJ5OzawkNUuemcqj9tN2FALNAh0A18E0qiZDZoYqGDAlddD7mNEW
+vEtt3ryjpaeTnwIBAQM6AAQBNkpLDwEC6VAqudxoVdkLBlpvXl5IOV+DCdV8Eauv
+8hdWYH72dX7JiGyiItg8oEsamfpDxam84aOCARAwggEMMDYGA1UdEQQvMC2BGGNz
+Y2EtZ2VybWFueUBic2kuYnVuZC5kZYYRZmF4Ois0OTIyODk1ODI3MjIwDgYDVR0P
+AQH/BAQDAgEGMB0GA1UdDgQWBBQAlkUt5Yj5ZsTM3xYd0fP1NBtx5zAfBgNVHSME
+GDAWgBQAlkUt5Yj5ZsTM3xYd0fP1NBtx5zBBBgNVHSAEOjA4MDYGCQQAfwAHAwEB
+ATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmJzaS5idW5kLmRlL2NzY2EwEgYD
+VR0TAQH/BAgwBgEB/wIBADArBgNVHRAEJDAigA8yMDA3MDcxOTE1MjcxOFqBDzIw
+MjcxMTE5MTUxODAwWjAMBggqhkjOPQQDAQUAA0EAMD4CHQDGtB6DAhf9TJO1np4r
+E3NOCcGC+mP67kEVqO3VAh0A0nk42gG4lRqQZKG2lq7fGBt0logpwTjw6y9iOw==
+-----END CERTIFICATE-----
diff --git a/botan/checks/ecc_testdata/DE1_flen_chars_cvcRequest_ECDSA.der b/botan/checks/ecc_testdata/DE1_flen_chars_cvcRequest_ECDSA.der
new file mode 100644
index 0000000..358ca8f
--- /dev/null
+++ b/botan/checks/ecc_testdata/DE1_flen_chars_cvcRequest_ECDSA.der
Binary files differ
diff --git a/botan/checks/ecc_testdata/Lidia.cer b/botan/checks/ecc_testdata/Lidia.cer
new file mode 100644
index 0000000..58c5568
--- /dev/null
+++ b/botan/checks/ecc_testdata/Lidia.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/Lidia.pem b/botan/checks/ecc_testdata/Lidia.pem
new file mode 100644
index 0000000..c0612d9
--- /dev/null
+++ b/botan/checks/ecc_testdata/Lidia.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID1TCCAz6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJERTEV
+MBMGA1UECgwMVFUgRGFybXN0YWR0MQwwCgYDVQQLDANDREMxFjAUBgNVBAMMDUxp
+RElBIENBIDE6UE4wHhcNMDQwNzA1MTQzNDM1WhcNMDkwNzA1MTQzMDM0WjBKMQsw
+CQYDVQQGEwJERTEVMBMGA1UECgwMVFUgRGFybXN0YWR0MQwwCgYDVQQLDANDREMx
+FjAUBgNVBAMMDUxpRElBIENBIDE6UE4wgaAwDQYJKoZIhvcNAQEBBQADgY4AMIGK
+AoGBAJI+ARML7sZAYYGcmjhxAGCi7Iohg6/dWSP/WWv2dEtRQ1k0GOa7HV2j9aD5
+myVRfNCs/9uFggTLuWGreDHE6+gAIpmGjbohQPopPwK8p0C4Lk+lPwOkXnoC3sQS
+AMpfiIZ9URfkHQ4IdQCBkOtRBLiYN5PKycC4nVXUmf+hjUMNAgRAAACBo4IByDCC
+AcQwDgYDVR0PAQH/BAQDAgIEMHEGA1UdIARqMGgwZgYLKwYBBAHAbQMEAgEwVzBV
+BggrBgEFBQcCARZJaHR0cHM6Ly93d3cubGlkaWEtY2EuY2RjLmluZm9ybWF0aWsu
+dHUtZGFybXN0YWR0LmRlL0FubWVsZHVuZy94NTA5djMuaHRtbDCB6gYDVR0fBIHi
+MIHfMIHcoIHZoIHWhoHTbGRhcDovL2xpZGlhLWNhLmNkYy5pbmZvcm1hdGlrLnR1
+LWRhcm1zdGFkdC5kZTozODkvY249TGlESUEtQ0ElMjBDUkwtU2lnbmVyJTIwMTpQ
+TixvdT1DREMsbz1UVSUyMERhcm1zdGFkdCxjPURFLGRjPUxpRElBLUNBLGRjPWxp
+ZGlhLWNhLGRjPWNkYyxkYz1pbmZvcm1hdGlrLGRjPXR1LWRhcm1zdGFkdCxkYz1k
+ZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeTASBgNVHRMBAf8ECDAG
+AQH/AgEAMB8GA1UdIwQYMBaAFN8gbG59DBnAHra5WZDGLDT9Hd2PMB0GA1UdDgQW
+BBTfIGxufQwZwB62uVmQxiw0/R3djzANBgkqhkiG9w0BAQUFAAOBgQA87i/oRFnF
+2wvZjFOGozRQjXEK1BLqhJEz+atbQzuY0aBdg95zTC/xJR8MuV2PjHuvSnpwf7nt
+Ff5qsD0ewYk41VIlymWDprX6QAAze4oHDmK05Da6E4IzeKFl+/fXF7qNhLNN/Qld
+ETaAOM6MIA5WZtjwQPl1jZphtwm3F5ALwg==
+-----END CERTIFICATE-----
diff --git a/botan/checks/ecc_testdata/ado b/botan/checks/ecc_testdata/ado
new file mode 100644
index 0000000..baa7917
--- /dev/null
+++ b/botan/checks/ecc_testdata/ado
Binary files differ
diff --git a/botan/checks/ecc_testdata/ado.cvcreq b/botan/checks/ecc_testdata/ado.cvcreq
new file mode 100644
index 0000000..09a14bb
--- /dev/null
+++ b/botan/checks/ecc_testdata/ado.cvcreq
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_cvca.cer b/botan/checks/ecc_testdata/cvc_chain_cvca.cer
new file mode 100644
index 0000000..4a7281a
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_cvca.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_dvca_ado2.cer b/botan/checks/ecc_testdata/cvc_chain_dvca_ado2.cer
new file mode 100644
index 0000000..1d6f7c1
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_dvca_ado2.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_dvca_cert1.cer b/botan/checks/ecc_testdata/cvc_chain_dvca_cert1.cer
new file mode 100644
index 0000000..c16c2d2
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_dvca_cert1.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_dvca_req.cer b/botan/checks/ecc_testdata/cvc_chain_dvca_req.cer
new file mode 100644
index 0000000..382351d
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_dvca_req.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_dvca_req2.cer b/botan/checks/ecc_testdata/cvc_chain_dvca_req2.cer
new file mode 100644
index 0000000..1b39cee
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_dvca_req2.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_dvca_req2b.cer b/botan/checks/ecc_testdata/cvc_chain_dvca_req2b.cer
new file mode 100644
index 0000000..1b39cee
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_dvca_req2b.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_is_cert.cer b/botan/checks/ecc_testdata/cvc_chain_is_cert.cer
new file mode 100644
index 0000000..f9ee2d2
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_is_cert.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_is_req.cer b/botan/checks/ecc_testdata/cvc_chain_is_req.cer
new file mode 100644
index 0000000..144495f
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_is_req.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvc_chain_link12.cer b/botan/checks/ecc_testdata/cvc_chain_link12.cer
new file mode 100644
index 0000000..27df92d
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvc_chain_link12.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvca01.cv.crt b/botan/checks/ecc_testdata/cvca01.cv.crt
new file mode 100644
index 0000000..8f27816
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvca01.cv.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvca_illegal_chars.cv.crt b/botan/checks/ecc_testdata/cvca_illegal_chars.cv.crt
new file mode 100644
index 0000000..b1a3d26
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvca_illegal_chars.cv.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/cvca_illegal_chars2.cv.crt b/botan/checks/ecc_testdata/cvca_illegal_chars2.cv.crt
new file mode 100644
index 0000000..00f09b6
--- /dev/null
+++ b/botan/checks/ecc_testdata/cvca_illegal_chars2.cv.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/ec_for_flex_mes.sig b/botan/checks/ecc_testdata/ec_for_flex_mes.sig
new file mode 100644
index 0000000..6d9983b
--- /dev/null
+++ b/botan/checks/ecc_testdata/ec_for_flex_mes.sig
@@ -0,0 +1 @@
+MGQCMG+ULXRAhLe+GESTVKd+aT3tn46209cLl9LTxDoj1lz/G9Xlw4QpwuCP1TJnRwNySgIwUu+8u32frzcZ2EhNMRrFcyH9t/8GGdvAlszc4k4TSvMK+Rz+5eZ+6hYX3lEsusCY
diff --git a/botan/checks/ecc_testdata/ec_oid_not_in_reg_private_2.pkcs8.pem b/botan/checks/ecc_testdata/ec_oid_not_in_reg_private_2.pkcs8.pem
new file mode 100644
index 0000000..7a17079
--- /dev/null
+++ b/botan/checks/ecc_testdata/ec_oid_not_in_reg_private_2.pkcs8.pem
@@ -0,0 +1,7 @@
+-----BEGIN PRIVATE KEY-----
+MIHaAgEAMIG0BgcqhkjOPQIBMIGoAgEBMCIGByqGSM49AQECFw4aFhluYAAAAAC8
+d5mvQORfIMKCpz8jMDIEFwpp6Dq3yY/XFMent6k68ZVN0TLoYuwCBBcF27ytezfC
+QvUCsMLrgpmKMPgl7QmshQQvBAegDesPaZK6sjNlLdtcbzMdfScPlwnsBYlNHz+Z
+VzzAHH+at1C946ahHkssjp4CFw4aFhluYAAAAAC8fxYY2GexW7hkdEGPAgEBBB4w
+HAIBAQQXBJJ/aqWyXJt0gblb7AjQYjSqWnHULjY=
+-----END PRIVATE KEY-----
diff --git a/botan/checks/ecc_testdata/flex_cert.crt b/botan/checks/ecc_testdata/flex_cert.crt
new file mode 100644
index 0000000..0b9015c
--- /dev/null
+++ b/botan/checks/ecc_testdata/flex_cert.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/flex_mes b/botan/checks/ecc_testdata/flex_mes
new file mode 100644
index 0000000..52a91be
--- /dev/null
+++ b/botan/checks/ecc_testdata/flex_mes
@@ -0,0 +1 @@
+!aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa! \ No newline at end of file
diff --git a/botan/checks/ecc_testdata/flex_mes.sig b/botan/checks/ecc_testdata/flex_mes.sig
new file mode 100644
index 0000000..fde3347
--- /dev/null
+++ b/botan/checks/ecc_testdata/flex_mes.sig
Binary files differ
diff --git a/botan/checks/ecc_testdata/insito_expl_ec.pem b/botan/checks/ecc_testdata/insito_expl_ec.pem
new file mode 100644
index 0000000..e8e5784
--- /dev/null
+++ b/botan/checks/ecc_testdata/insito_expl_ec.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDJDCCAqmgAwIBAgIRAMIJXZsHSYcafmLTmEPf5m8wDAYIKoZIzj0EAwEFADA7
+MQswCQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5T
+aVRvIFRlc3QgQ0EwHhcNMDgxMDA5MTg1MzUyWhcNMDkxMDA5MTg1MzUyWjA7MQsw
+CQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5TaVRv
+IFRlc3QgQ0EwggGFMIIBTQYHKoZIzj0CATCCAUACAQEwPAYHKoZIzj0BAQIxAIy5
+HoKjOG0oD11vflDmQd8VL3EJ7VRWtBKx2hl/txEjrNOnKZAdGnGHRwATMQfsUzBk
+BDB7w4LGPYwVDDxyCArOBa+gwr6ijk+yJ4cTkWXvupH5D4qlgUpQOtTrBKjH3SLO
+KCYEMASox90izigmizm1VBbwRHwvt33hB9zSpi6IDqU+62LVfLQ5ApXbyZQ6t4aW
++lBMEQRhBB0cZPBoz0X/oqY6gbfBP2uIR6PnfvFP49t/yv4MvRDo6CbgNDbWRqrv
+h7LiR9SvHoq+HXUg+cKkXLHrjpXP1VJitwsp/uxYZOGcBU/5kSkoDkZGIXeRgRFC
+ggNBJjxTFQIxAIy5HoKjOG0oD11vflDmQd8VL3EJ7VRWsx8WbmysBCWnzzq2r2t/
+wxA7iDIC6QRlZQIBAQMyAAM3OveZo7xFgTJqYZ2C1nydlMMZ6d2KuHgS7Q3+SkbS
+QGy4k7p87QwpLNRhjSPU/qejXjBcMB0GA1UdDgQWBBTLFJODc8gnNtBMOi5lf9qi
+bQoStjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0RBBAwDoEMdGVzdEB0ZXN0LmRlMBIG
+A1UdEwEB/wQIMAYBAf8CAQgwDAYIKoZIzj0EAwEFAANnADBkAjAIqO6/nN20oxQx
+maPvFCBdPXgTEfsZt8hc3GPO7nCiRGcdn877NNyO+vPGuffE47QCME3P8WHvuUU8
+dcrs9ZP/dAX8rRWZ2pTatGjufkwRThYRanM5UMVycsJ6l5Miw1KCyA==
+-----END CERTIFICATE-----
diff --git a/botan/checks/ecc_testdata/insito_oid_ec.pem b/botan/checks/ecc_testdata/insito_oid_ec.pem
new file mode 100644
index 0000000..2e05171
--- /dev/null
+++ b/botan/checks/ecc_testdata/insito_oid_ec.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB5zCCAWygAwIBAgIRAKiVxgiRp/wH4oOF+uzoC/EwDAYIKoZIzj0EAwEFADA7
+MQswCQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5T
+aVRvIFRlc3QgQ0EwHhcNMDgxMDA5MTg1MzUyWhcNMDkxMDA5MTg1MzUyWjA7MQsw
+CQYDVQQGEwJERTETMBEGA1UEChMKRmxleFNlY3VyZTEXMBUGA1UEAxMOSW5TaVRv
+IFRlc3QgQ0EwSjAUBgcqhkjOPQIBBgkrJAMDAggBAQsDMgACE6zPzVimCycfprq0
+rfuJY1kBLJBvClZUkRP0qRBIU9c1pnZcJdoC4Nks3Mwf/QZoo14wXDAdBgNVHQ4E
+FgQUJBauyO+U5gtgw2LqHCG40qle4+owDgYDVR0PAQH/BAQDAgEGMBcGA1UdEQQQ
+MA6BDHRlc3RAdGVzdC5kZTASBgNVHRMBAf8ECDAGAQH/AgEIMAwGCCqGSM49BAMB
+BQADZwAwZAIwMtaUw+Hqnm5hB1T1zIc9OEb3VvUAuWFhppbRO87Yo2UZBc/mSVf2
+7KHGSRBBJBZ3AjB9KJIaRCacFYOb8aENOgDHlwwtAdQKrjPH1bEVdotmQePS2hIv
+DNGNLlqllCnQWvU=
+-----END CERTIFICATE-----
diff --git a/botan/checks/ecc_testdata/link_SHA1.166.crt b/botan/checks/ecc_testdata/link_SHA1.166.crt
new file mode 100644
index 0000000..8f76b32
--- /dev/null
+++ b/botan/checks/ecc_testdata/link_SHA1.166.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/link_SHA256.cer b/botan/checks/ecc_testdata/link_SHA256.cer
new file mode 100644
index 0000000..add40f7
--- /dev/null
+++ b/botan/checks/ecc_testdata/link_SHA256.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/my_cv_cert.ber b/botan/checks/ecc_testdata/my_cv_cert.ber
new file mode 100644
index 0000000..7a14fd3
--- /dev/null
+++ b/botan/checks/ecc_testdata/my_cv_cert.ber
Binary files differ
diff --git a/botan/checks/ecc_testdata/my_cv_cert2.ber b/botan/checks/ecc_testdata/my_cv_cert2.ber
new file mode 100644
index 0000000..7a14fd3
--- /dev/null
+++ b/botan/checks/ecc_testdata/my_cv_cert2.ber
Binary files differ
diff --git a/botan/checks/ecc_testdata/my_cv_req.ber b/botan/checks/ecc_testdata/my_cv_req.ber
new file mode 100644
index 0000000..4e121ee
--- /dev/null
+++ b/botan/checks/ecc_testdata/my_cv_req.ber
Binary files differ
diff --git a/botan/checks/ecc_testdata/nodompar_private.pkcs8.pem b/botan/checks/ecc_testdata/nodompar_private.pkcs8.pem
new file mode 100644
index 0000000..a2c64ec
--- /dev/null
+++ b/botan/checks/ecc_testdata/nodompar_private.pkcs8.pem
@@ -0,0 +1,12 @@
+-----BEGIN PRIVATE KEY-----
+MIIB0QIBADCCAYcGByqGSM49AgEwggF6AgEBMEUGByqGSM49AQECOgthcsnViAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAEdshQ7mkmMLkJZUVU4Ol915g3uKHPNUo9AwD+x4
+7PkweAQ6Cjd97ea1IzM9NseOmw6qO/SM6TBB9tT8NAFNCPaDOAdJje7dQpAQHFhm
+6N+1iUhdEzV7nnjC1/vp/gQ6CprPjIumF3d+JIUJvLRxfU2zRiAr+eNSzVYzcx3Z
+KlG3Kk3Ds9F8gj/Mj72k2gjyXeqJBGCHNCWVpwR1BAgVI9A9TxLNAoed6kv2pPOn
+3ybtiI8QxbIjWhJ0w4ai8hgwDe5u0heEEWRTO83JA/B6CW+fv07pW6wJihEfKW9Y
+MP5cNbPjRNXfOiJWmF9k++bQ7cxMYdGL72gd05nfPQGUxaQxXgEuAkXs6lY2W6qe
+i+H3AjoLYXLJ1YgAAAAAAAAAAAAAAAAAAAAAAAAAAABHbIeQSOXYXqco7S6hwduS
+xOT5ZSNk/c26d1X6bDYvAgEBBEEwPwIBAQQ6CQZ+cOjNmFKHK7JoXGdAPByb7XfI
+kTIoUEiQxOiDRUH9pUqf0lpcCHhjtTb9hQZ1RGYrjqsccdL6ng==
+-----END PRIVATE KEY-----
diff --git a/botan/checks/ecc_testdata/private.pem b/botan/checks/ecc_testdata/private.pem
new file mode 100644
index 0000000..4465da6
--- /dev/null
+++ b/botan/checks/ecc_testdata/private.pem
@@ -0,0 +1,11 @@
+-----BEGIN PRIVATE KEY-----
+MIIBjQIBADCCAU0GByqGSM49AgEwggFAAgEBMDwGByqGSM49AQECMQCMuR6Cozht
+KA9db35Q5kHfFS9xCe1UVrQSsdoZf7cRI6zTpymQHRpxh0cAEzEH7FMwZAQwe8OC
+xj2MFQw8cggKzgWvoMK+oo5PsieHE5Fl77qR+Q+KpYFKUDrU6wSox90izigmBDAE
+qMfdIs4oJos5tVQW8ER8L7d94Qfc0qYuiA6lPuti1Xy0OQKV28mUOreGlvpQTBEE
+YQQdHGTwaM9F/6KmOoG3wT9riEej537xT+Pbf8r+DL0Q6Ogm4DQ21kaq74ey4kfU
+rx6Kvh11IPnCpFyx646Vz9VSYrcLKf7sWGThnAVP+ZEpKA5GRiF3kYERQoIDQSY8
+UxUCMQCMuR6CozhtKA9db35Q5kHfFS9xCe1UVrMfFm5srAQlp886tq9rf8MQO4gy
+AukEZWUCAQEENzA1AgEBBDB5HVMmAiyXDGqBKoKEHNIk02EMVKKdHqXG6kDInWC/
+R4ZVuXK3T8DqJrRX7RHxndk=
+-----END PRIVATE KEY-----
diff --git a/botan/checks/ecc_testdata/root1_SHA256.cer b/botan/checks/ecc_testdata/root1_SHA256.cer
new file mode 100644
index 0000000..021afe5
--- /dev/null
+++ b/botan/checks/ecc_testdata/root1_SHA256.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/root2_SHA256.cer b/botan/checks/ecc_testdata/root2_SHA256.cer
new file mode 100644
index 0000000..a2ecfed
--- /dev/null
+++ b/botan/checks/ecc_testdata/root2_SHA256.cer
Binary files differ
diff --git a/botan/checks/ecc_testdata/root_SHA1.163.crt b/botan/checks/ecc_testdata/root_SHA1.163.crt
new file mode 100644
index 0000000..e1bf39f
--- /dev/null
+++ b/botan/checks/ecc_testdata/root_SHA1.163.crt
Binary files differ
diff --git a/botan/checks/ecc_testdata/withdompar_private.pkcs8.pem b/botan/checks/ecc_testdata/withdompar_private.pkcs8.pem
new file mode 100644
index 0000000..85d7b57
--- /dev/null
+++ b/botan/checks/ecc_testdata/withdompar_private.pkcs8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MGACAQAwGAYHKoZIzj0CAQYNKwYBBAHAbQMBAgkAIQRBMD8CAQEEOgG97/hDkXbJ
+tgF36JmM7NliJIlDFzTm69KYouwhjPOsh6hKo5NPTtsmHafplOqpUf0TyAhB1Q88
+3xA=
+-----END PRIVATE KEY-----
diff --git a/botan/checks/ecc_testdata/x509_req_test_expl.pem b/botan/checks/ecc_testdata/x509_req_test_expl.pem
new file mode 100644
index 0000000..e4ae1a9
--- /dev/null
+++ b/botan/checks/ecc_testdata/x509_req_test_expl.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIDFDCCApgCAQAwaTELMAkGA1UEBhMCREUxCzAJBgNVBAgTAk1EMRIwEAYDVQQH
+EwlCYWx0aW1vcmUxEzARBgNVBAoTCkZsZXhTZWN1cmUxEDAOBgNVBAsTB1Rlc3Rp
+bmcxEjAQBgNVBAMUCXRlc3RfemVydDCCAYUwggFNBgcqhkjOPQIBMIIBQAIBATA8
+BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHaGX+3ESOs06cp
+kB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7InhxORZe+6kfkP
+iqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH3NKmLogOpT7r
+YtV8tDkCldvJlDq3hpb6UEwRBGEEHRxk8GjPRf+ipjqBt8E/a4hHo+d+8U/j23/K
+/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3Cyn+7Fhk4ZwF
+T/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFaz
+HxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEBAzIAAjv2NeapXSWoiFe/2KBvFS8x
+lDmexNgl0TK6vgVCDoI2AOVkkJQ9wjqpFsrKG67YlqCBnjArBgkqhkiG9w0BCQcx
+HhMcYSBmaXhlZCBjaGFsbGVuZ2UgcGFzc3BocmFzZTBvBgkqhkiG9w0BCQ4xYjBg
+MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMCcGA1UdJQQgMB4GCCsGAQUF
+BwMCBggrBgEFBQcDBwYIKwYBBQUHAwQwFwYDVR0RBBAwDoEMdGVzdEB0ZXN0LmRl
+MAwGCCqGSM49BAMBBQADaAAwZQIxAIOkl6jVpL8C2V6zpUqnLQEMC+T8ocxKGxnm
++0ZKEgwMCqfD9WJo2C1hZ/1iZPcQmgIwKNMUgDbn16AZZqJCk/2sU0JvqkR0D/Ue
+FksrSdAxjpnauRDOXMTbzpdsnzAnDNIU
+-----END CERTIFICATE REQUEST-----
diff --git a/botan/checks/ecc_testdata/x509_req_test_oid.pem b/botan/checks/ecc_testdata/x509_req_test_oid.pem
new file mode 100644
index 0000000..2ae0c2e
--- /dev/null
+++ b/botan/checks/ecc_testdata/x509_req_test_oid.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIB1jCCAVsCAQAwaTELMAkGA1UEBhMCREUxCzAJBgNVBAgTAk1EMRIwEAYDVQQH
+EwlCYWx0aW1vcmUxEzARBgNVBAoTCkZsZXhTZWN1cmUxEDAOBgNVBAsTB1Rlc3Rp
+bmcxEjAQBgNVBAMUCXRlc3RfemVydDBKMBQGByqGSM49AgEGCSskAwMCCAEBCwMy
+AAMLt+cMOPYmbgVHwaUFmEJIfYCNpgPyWkIyYHPiY4SF2UC0nTQv7el1+Dpt4Ueo
+mQGggZ4wKwYJKoZIhvcNAQkHMR4THGEgZml4ZWQgY2hhbGxlbmdlIHBhc3NwaHJh
+c2UwbwYJKoZIhvcNAQkOMWIwYDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG
+wDAnBgNVHSUEIDAeBggrBgEFBQcDAgYIKwYBBQUHAwcGCCsGAQUFBwMEMBcGA1Ud
+EQQQMA6BDHRlc3RAdGVzdC5kZTAMBggqhkjOPQQDAQUAA2cAMGQCMC4uFJYZ7CUN
+rqQrCAxJAqWIuZrKvvlHyu+Q6VibIUjwh2guPNJDmbW/iorXcu3yAwIwbOjPSSMD
+5XvumhMwuV6kHmn+5DjCPLUQLuLQhNeU06bExcCuutz5DMVix05w7gox
+-----END CERTIFICATE REQUEST-----
diff --git a/botan/checks/ecc_testdata/x509_test_privkey_expl_pw123456.pem b/botan/checks/ecc_testdata/x509_test_privkey_expl_pw123456.pem
new file mode 100644
index 0000000..20f1713
--- /dev/null
+++ b/botan/checks/ecc_testdata/x509_test_privkey_expl_pw123456.pem
@@ -0,0 +1,13 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIB4TBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIS+GhX0d3oQkCAggA
+AgEYMBQGCCqGSIb3DQMHBAjSmLY2CqIVlgSCAZicGlQqDD2ZC8Tmnp43tqUnFnMc
+ZU6RdY5ys1WQ2Blvn5eKhK0n9yz3b9LvIzs9U6shbBPN/GePeOFFZQi0M9+SIrjj
+NjpjqaJtUvhPt3tDn0B3o0raWLsJ2TvXxO0UNRZYk1YniGEecCUY/shMPpop6Tns
+079QXRNuAqGeEcouKIQcJjGR3GbPbccBUUbkAjrK7f4tMTHOzoei3SJ50IcSh1hh
+vYbyKFBmxi30gYc95T9VO+XsrDLP4QZXrM6S6o8xkbx1o9hHuGeiSiSOpQ/6iVUt
+nRMR1GW1MZGQeJazdnccx+8C4iuW9LOfyvA7HEC8F0LLZ6mCGtLcMt8Vk+en24nJ
+od4W0EqJmcasfbF+VNPNuFzwIPvEzgeyYTp5P6wfc81cqlBMfl1AGKFR8u9372UW
+PWPcsqrGR3OggRcXvRc+9UKtsLoALel8esZrJzNurqkU10XePUR9Vup3Ke7kvT/o
+g+uA5vboio3Jy2FoJE/YF0jKDJfbzMWJeSetJwLfrKEvsmdpUf9jeUoaze0S4LzB
+JHJ+NMg=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/botan/checks/ecc_testdata/x509_test_privkey_oid_pw123456.pem b/botan/checks/ecc_testdata/x509_test_privkey_oid_pw123456.pem
new file mode 100644
index 0000000..ecd188a
--- /dev/null
+++ b/botan/checks/ecc_testdata/x509_test_privkey_oid_pw123456.pem
@@ -0,0 +1,13 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIB4TBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIJ7F/jO3zVxQCAggA
+AgEYMBQGCCqGSIb3DQMHBAjBY6p0ZIHowASCAZg/JGcpBr2lh1x9WUI7J/1jCdwn
+HvJu+aes3+I57MdI75ca7Z5wixO50pYUWkfexfdkm5k11HVz7ETJuNvVw+p937kI
+EJtX0ukBsdsgcGcoKFCZG1JIhClqyCnx38CIdE1C8TE/7Yyk5YFMeNP9LbMH9jC5
+gAJV9+YSpw1F9q6OOXv61s9uKIHq7VWza77CJKjFNLpn1/5FqTISmDXV3V2Rs8eI
+j7hFMRBpRnEAA+DOgjuEkTMgF7UR39YTTBooUSzUB4kSlRQxeP7HrulboLB0ukO3
+CT5qa/kA9lHJgHYZXNjzS5NzsoZeZcU934AEBm7J2vr/voHYU8zPrgRAmz8D25Gf
+UH4kaQLZ3LDGlbcba8yjlOYd+x5Rl9H6vKORoqAGN0sLPLAryjzs+vS486SUlRiy
+LsNqcrSOYoW1MyOYAJajxvUsUDqZyxp64TMegZlyLZGIu2ngFOd1gZsh+T2X3g8C
+Murum3ynFx+H3HF1JwpZB/gImz+BI8JigUnd4fG2gqvx7wu6cqoaRGJQayilj64O
+AZU+x5c=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/botan/checks/ecdsa.cpp b/botan/checks/ecdsa.cpp
new file mode 100644
index 0000000..532a1c5
--- /dev/null
+++ b/botan/checks/ecdsa.cpp
@@ -0,0 +1,556 @@
+/******************************************************
+* ECDSA tests *
+* *
+* (C) 2007 Falko Strenzke *
+* Manuel Hartl *
+* 2008 Jack Lloyd *
+******************************************************/
+
+#include "validate.h"
+
+#if defined(BOTAN_HAS_ECDSA)
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/ecdsa.h>
+#include <botan/rsa.h>
+#include <botan/x509cert.h>
+#include <botan/oids.h>
+
+#include <iostream>
+#include <fstream>
+
+#include "common.h"
+
+using namespace Botan;
+
+#define TEST_DATA_DIR "checks/ecc_testdata"
+
+#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+
+namespace {
+
+std::string to_hex(const SecureVector<byte>& bin)
+ {
+ return hex_encode(bin.begin(), bin.size());
+ }
+
+/**
+
+* Tests whether the the signing routine will work correctly in case the integer e
+* that is constructed from the message (thus the hash value) is larger than n, the order of the base point.
+* Tests the signing function of the pk signer object
+*/
+
+void test_hash_larger_than_n(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ // n:
+ // 0x0100000000000000000001f4c8f927aed3ca752257 // 21 bytes
+ // -> shouldn't work with SHA224 which outputs 23 bytes
+ ECDSA_PrivateKey priv_key(rng, dom_pars);
+ SecureVector<byte> message;
+ for (unsigned j= 0; j<20; j++)
+ {
+ message.append(j);
+ }
+
+ for (int i = 0; i<3; i++)
+ {
+ //cout << "i = " << i << endl;
+ std::string format;
+ if(i==1)
+ {
+ format = "EMSA1_BSI(SHA-224)";
+ }
+ else
+ {
+ format = "EMSA1_BSI(SHA-1)";
+ }
+ std::auto_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, format));
+ SecureVector<byte> signature;
+ bool sig_exc = false;
+ try
+ {
+ signature = pk_signer->sign_message(message, rng);
+ }
+ catch(Encoding_Error e)
+ {
+ sig_exc = true;
+ }
+ if(i==1)
+ {
+ CHECK(sig_exc);
+ }
+ if(i==0)
+ {
+ CHECK(!sig_exc);
+ }
+
+
+ if(i==0) // makes no sense to check for sha224
+ {
+ std::auto_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, format));
+ bool ver = pk_verifier->verify_message(message, signature);
+ CHECK(ver);
+ }
+
+ } // for
+
+ // now check that verification alone fails
+
+ // sign it with the normal EMSA1
+ std::auto_ptr<PK_Signer> pk_signer(get_pk_signer(priv_key, "EMSA1(SHA-224)"));
+ SecureVector<byte> signature = pk_signer->sign_message(message, rng);
+
+ std::auto_ptr<PK_Verifier> pk_verifier(get_pk_verifier(priv_key, "EMSA1_BSI(SHA-224)"));
+
+ // verify against EMSA1_BSI
+ // we make sure it doesn't fail because of the invalid signature,
+ // but because of the Encoding_Error
+
+ bool ver_exc = false;
+ try
+ {
+ pk_verifier->verify_message(message, signature);
+ }
+ catch(Encoding_Error e)
+ {
+ ver_exc = true;
+ }
+ CHECK(ver_exc);
+ }
+
+/**
+* Tests whether the the signing routine will work correctly in case the integer e
+* that is constructed from the message is larger than n, the order of the base point
+*/
+void test_message_larger_than_n(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ ECDSA_PrivateKey priv_key(rng, dom_pars);
+ std::string str_message = ("12345678901234567890abcdef1212345678901234567890abcdef1212345678901234567890abcdef12");
+
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ bool thrn = false;
+ SecureVector<byte> signature;
+ try
+ {
+ signature = priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+ }
+ catch (Invalid_Argument e)
+ {
+ thrn = true;
+ }
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success = priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+ //CHECK_MESSAGE(thrn, "no exception was thrown although message to sign was too long");
+ }
+
+void test_decode_ecdsa_X509()
+ {
+ std::cout << "." << std::flush;
+
+ X509_Certificate cert(TEST_DATA_DIR "/CSCA.CSCA.csca-germany.1.crt");
+ CHECK_MESSAGE(OIDS::lookup(cert.signature_algorithm().oid) == "ECDSA/EMSA1_BSI(SHA-224)", "error reading signature algorithm from x509 ecdsa certificate");
+
+ CHECK_MESSAGE(to_hex(cert.serial_number()) == "01", "error reading serial from x509 ecdsa certificate");
+ CHECK_MESSAGE(to_hex(cert.authority_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading authority key id from x509 ecdsa certificate");
+ CHECK_MESSAGE(to_hex(cert.subject_key_id()) == "0096452DE588F966C4CCDF161DD1F3F5341B71E7", "error reading Subject key id from x509 ecdsa certificate");
+
+ std::auto_ptr<X509_PublicKey> pubkey(cert.subject_public_key());
+ bool ver_ec = cert.check_signature(*pubkey);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned x509-ecdsa certificate");
+ }
+
+void test_decode_ver_link_SHA256()
+ {
+ std::cout << "." << std::flush;
+
+ X509_Certificate root_cert(TEST_DATA_DIR "/root2_SHA256.cer");
+ X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA256.cer");
+
+ std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
+ bool ver_ec = link_cert.check_signature(*pubkey);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA256 link x509-ecdsa certificate");
+
+ }
+void test_decode_ver_link_SHA1()
+ {
+ std::cout << "." << std::flush;
+
+ X509_Certificate root_cert(TEST_DATA_DIR "/root_SHA1.163.crt");
+ X509_Certificate link_cert(TEST_DATA_DIR "/link_SHA1.166.crt");
+
+ std::auto_ptr<X509_PublicKey> pubkey(root_cert.subject_public_key());
+ bool ver_ec = link_cert.check_signature(*pubkey);
+ CHECK_MESSAGE(ver_ec, "could not positively verify correct SHA1 link x509-ecdsa certificate");
+ }
+
+void test_sign_then_ver(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ SecureVector<byte> sv_g_secp = decode_hex(g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+
+ EC_Domain_Params dom_pars = EC_Domain_Params(curve, p_G, order, cofactor);
+ ECDSA_PrivateKey my_priv_key(rng, dom_pars);
+
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ SecureVector<byte> signature = my_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+ signature[signature.size()-1] += 0x01;
+ bool ver_must_fail = my_priv_key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(!ver_must_fail, "corrupted signature could be verified positively");
+ }
+
+bool test_ec_sign(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ try
+ {
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ ECDSA_PrivateKey priv_key(rng, dom_pars);
+ std::string pem_encoded_key = PKCS8::PEM_encode(priv_key);
+
+ std::auto_ptr<PK_Signer> signer(get_pk_signer(priv_key, "EMSA1(SHA-224)"));
+ std::auto_ptr<PK_Verifier> verifier(get_pk_verifier(priv_key, "EMSA1(SHA-224)"));
+
+ for(u32bit i = 0; i != 256; ++i)
+ signer->update((byte)i);
+ SecureVector<byte> sig = signer->signature(rng);
+
+ for(u32bit i = 0; i != 256; ++i)
+ verifier->update((byte)i);
+ if(!verifier->check_signature(sig))
+ {
+ std::cout << "ECDSA self-test failed!";
+ return false;
+ }
+
+ // now check valid signature, different input
+ for(u32bit i = 1; i != 256; ++i) //starting from 1
+ verifier->update((byte)i);
+
+ if(verifier->check_signature(sig))
+ {
+ std::cout << "ECDSA with bad input passed validation";
+ return false;
+ }
+
+ // now check with original input, modified signature
+
+ sig[sig.size()/2]++;
+ for(u32bit i = 0; i != 256; ++i)
+ verifier->update((byte)i);
+
+ if(verifier->check_signature(sig))
+ {
+ std::cout << "ECDSA with bad signature passed validation";
+ return false;
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception in test_ec_sign - " << e.what() << "\n";
+ return false;
+ }
+ return true;
+ }
+
+
+void test_create_pkcs8(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ try
+ {
+ RSA_PrivateKey rsa_key(rng, 1024);
+ //RSA_PrivateKey rsa_key2(1024);
+ //cout << "\nequal: " << (rsa_key == rsa_key2) << "\n";
+ //DSA_PrivateKey key(DL_Group("dsa/jce/1024"));
+
+ std::ofstream rsa_priv_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem");
+ rsa_priv_key << PKCS8::PEM_encode(rsa_key);
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ ECDSA_PrivateKey key(rng, dom_pars);
+
+ // later used by other tests :(
+ std::ofstream priv_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem");
+ priv_key << PKCS8::PEM_encode(key);
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << std::endl;
+ }
+ }
+
+void test_create_and_verify(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+ ECDSA_PrivateKey key(rng, dom_pars);
+ std::ofstream priv_key(TEST_DATA_DIR "/dompar_private.pkcs8.pem");
+ priv_key << PKCS8::PEM_encode(key);
+
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
+ CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
+
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key_1(PKCS8::load_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem", rng));
+ ECDSA_PrivateKey* loaded_rsa_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_1.get());
+ CHECK_MESSAGE(!loaded_rsa_key, "the loaded key is ECDSA_PrivateKey -> shouldn't be, is a RSA-Key");
+
+ //calc a curve which is not in the registry
+
+ // string p_secp = "2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809";
+ std::string a_secp = "0a377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe";
+ std::string b_secp = "0a9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7";
+ std::string G_secp_comp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
+ std::string order_g = "0e1a16196e6000000000bc7f1618d867b15bb86474418f";
+
+ // ::SecureVector<byte> sv_p_secp = decode_hex ( p_secp );
+ SecureVector<byte> sv_a_secp = decode_hex ( a_secp );
+ SecureVector<byte> sv_b_secp = decode_hex ( b_secp );
+ SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp );
+ SecureVector<byte> sv_order_g = decode_hex ( order_g );
+
+ // BigInt bi_p_secp = BigInt::decode ( sv_p_secp.begin(), sv_p_secp.size() );
+ BigInt bi_p_secp("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
+ BigInt bi_a_secp = BigInt::decode ( sv_a_secp.begin(), sv_a_secp.size() );
+ BigInt bi_b_secp = BigInt::decode ( sv_b_secp.begin(), sv_b_secp.size() );
+ BigInt bi_order_g = BigInt::decode ( sv_order_g.begin(), sv_order_g.size() );
+ CurveGFp curve ( GFpElement ( bi_p_secp,bi_a_secp ), GFpElement ( bi_p_secp, bi_b_secp ), bi_p_secp );
+ PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve );
+
+ EC_Domain_Params dom_params(curve, p_G, bi_order_g, BigInt(1));
+ p_G.check_invariants();
+
+ ECDSA_PrivateKey key_odd_oid(rng, dom_params);
+ std::string key_odd_oid_str = PKCS8::PEM_encode(key_odd_oid);
+
+ DataSource_Memory key_data_src(key_odd_oid_str);
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key2(PKCS8::load_key(key_data_src, rng));
+
+ if(!dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get()))
+ {
+ std::cout << "Failed to reload an ECDSA key with unusual parameter set\n";
+ }
+ }
+
+void test_curve_registry(RandomNumberGenerator& rng)
+ {
+ std::vector<std::string> oids;
+ oids.push_back("1.3.132.0.8");
+ oids.push_back("1.2.840.10045.3.1.1");
+ oids.push_back("1.2.840.10045.3.1.2");
+ oids.push_back("1.2.840.10045.3.1.3");
+ oids.push_back("1.2.840.10045.3.1.4");
+ oids.push_back("1.2.840.10045.3.1.5");
+ oids.push_back("1.2.840.10045.3.1.6");
+ oids.push_back("1.2.840.10045.3.1.7");
+ oids.push_back("1.3.132.0.6");
+ oids.push_back("1.3.132.0.7");
+ oids.push_back("1.3.132.0.28");
+ oids.push_back("1.3.132.0.29");
+ oids.push_back("1.3.132.0.9");
+ oids.push_back("1.3.132.0.30");
+ oids.push_back("1.3.132.0.31");
+ oids.push_back("1.3.132.0.32");
+ oids.push_back("1.3.132.0.33");
+ oids.push_back("1.3.132.0.10");
+ oids.push_back("1.3.132.0.34");
+ oids.push_back("1.3.132.0.35");
+ oids.push_back("1.3.6.1.4.1.8301.3.1.2.9.0.38");
+ oids.push_back("1.3.36.3.3.2.8.1.1.1");
+ oids.push_back("1.3.36.3.3.2.8.1.1.3");
+ oids.push_back("1.3.36.3.3.2.8.1.1.5");
+ oids.push_back("1.3.36.3.3.2.8.1.1.7");
+ oids.push_back("1.3.36.3.3.2.8.1.1.9");
+ oids.push_back("1.3.36.3.3.2.8.1.1.11");
+ oids.push_back("1.3.36.3.3.2.8.1.1.13");
+
+ unsigned int i;
+ for (i = 0; i < oids.size(); i++)
+ {
+ std::cout << "." << std::flush;
+
+ try
+ {
+ EC_Domain_Params dom_pars(get_EC_Dom_Pars_by_oid(oids[i]));
+ dom_pars.get_base_point().check_invariants();
+ ECDSA_PrivateKey key(rng, dom_pars);
+
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ SecureVector<byte> signature = key.sign(sv_message.begin(), sv_message.size(), rng);
+ bool ver_success = key.verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+ }
+ catch(Invalid_Argument& e)
+ {
+ std::cout << "Error testing curve " << oids[i] << " - " << e.what() << "\n";
+ }
+ }
+ // std::cout << "test_curve_registry finished" << endl;
+ }
+
+void test_read_pkcs8(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+ try
+ {
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
+ CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
+
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ SecureVector<byte> signature = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success = loaded_ec_key->verify(sv_message.begin(), sv_message.size(), signature.begin(), signature.size());
+ CHECK_MESSAGE(ver_success, "generated signature could not be verified positively");
+
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key_nodp(PKCS8::load_key(TEST_DATA_DIR "/nodompar_private.pkcs8.pem", rng));
+ // anew in each test with unregistered domain-parameters
+ ECDSA_PrivateKey* loaded_ec_key_nodp = dynamic_cast<ECDSA_PrivateKey*>(loaded_key_nodp.get());
+ CHECK_MESSAGE(loaded_ec_key_nodp, "the loaded key could not be converted into an ECDSA_PrivateKey");
+
+ SecureVector<byte> signature_nodp = loaded_ec_key_nodp->sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+ bool ver_success_nodp = loaded_ec_key_nodp->verify(sv_message.begin(), sv_message.size(), signature_nodp.begin(), signature_nodp.size());
+ CHECK_MESSAGE(ver_success_nodp, "generated signature could not be verified positively (no_dom)");
+ try
+ {
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key_withdp(PKCS8::load_key(TEST_DATA_DIR "/withdompar_private.pkcs8.pem", rng));
+
+ std::cout << "Unexpected success: loaded key with unknown OID\n";
+ }
+ catch (std::exception& e) { /* OK */ }
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "Exception in test_read_pkcs8 - " << e.what() << "\n";
+ }
+ }
+
+/**
+* The following test tests the copy ctors and and copy-assignment operators
+*/
+void test_cp_and_as_ctors(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
+ CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
+ std::string str_message = ("12345678901234567890abcdef12");
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ SecureVector<byte> signature_1 = loaded_ec_key->sign(sv_message.begin(), sv_message.size(), rng);
+ //cout << "signature = " << hex_encode(signature.begin(), signature.size()) << "\n";
+
+ ECDSA_PrivateKey cp_priv_key(*loaded_ec_key); // priv-key, cp-ctor
+ SecureVector<byte> signature_2 = cp_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+
+ ECDSA_PrivateKey as_priv_key = *loaded_ec_key; //priv-key, as-op
+ SecureVector<byte> signature_3 = as_priv_key.sign(sv_message.begin(), sv_message.size(), rng);
+
+ ECDSA_PublicKey pk_1 = cp_priv_key; // pub-key, as-op
+ ECDSA_PublicKey pk_2(pk_1); // pub-key, cp-ctor
+ ECDSA_PublicKey pk_3;
+ pk_3 = pk_2; // pub-key, as-op
+
+ bool ver_success_1 = pk_1.verify(sv_message.begin(), sv_message.size(), signature_1.begin(), signature_1.size());
+
+ bool ver_success_2 = pk_2.verify(sv_message.begin(), sv_message.size(), signature_2.begin(), signature_2.size());
+
+ bool ver_success_3 = pk_3.verify(sv_message.begin(), sv_message.size(), signature_3.begin(), signature_3.size());
+
+ CHECK_MESSAGE((ver_success_1 && ver_success_2 && ver_success_3), "different results for copied keys");
+ }
+
+/**
+* The following test tests whether ECDSA keys exhibit correct behaviour when it is
+* attempted to use them in an uninitialized state
+*/
+void test_non_init_ecdsa_keys(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ std::auto_ptr<PKCS8_PrivateKey> loaded_key(PKCS8::load_key(TEST_DATA_DIR "/wo_dompar_private.pkcs8.pem", rng));
+ //ECDSA_PrivateKey* loaded_ec_key = dynamic_cast<ECDSA_PrivateKey*>(loaded_key.get());
+ //CHECK_MESSAGE(loaded_ec_key, "the loaded key could not be converted into an ECDSA_PrivateKey");
+ std::string str_message = ("12345678901234567890abcdef12");
+ ECDSA_PrivateKey empty_priv;
+ ECDSA_PublicKey empty_pub;
+ SecureVector<byte> sv_message = decode_hex(str_message);
+ bool exc1 = false;
+ try
+ {
+ SecureVector<byte> signature_1 = empty_priv.sign(sv_message.begin(), sv_message.size(), rng);
+ }
+ catch (std::exception e)
+ {
+ exc1 = true;
+ }
+ CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECDSA key");
+
+ bool exc2 = false;
+ try
+ {
+ empty_pub.verify(sv_message.begin(), sv_message.size(), sv_message.begin(), sv_message.size());
+ }
+ catch (std::exception e)
+ {
+ exc2 = true;
+ }
+ CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECDSA key");
+ }
+
+}
+
+u32bit do_ecdsa_tests(Botan::RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing ECDSA (InSiTo unit tests): ";
+
+ test_hash_larger_than_n(rng);
+ //test_message_larger_than_n();
+ test_decode_ecdsa_X509();
+ test_decode_ver_link_SHA256();
+ test_decode_ver_link_SHA1();
+ test_sign_then_ver(rng);
+ test_ec_sign(rng);
+ test_create_pkcs8(rng);
+ test_create_and_verify(rng);
+ test_curve_registry(rng);
+ test_read_pkcs8(rng);
+ test_cp_and_as_ctors(rng);
+ test_non_init_ecdsa_keys(rng);
+
+ std::cout << std::endl;
+
+ return 0;
+ }
+#else
+u32bit do_ecdsa_tests(Botan::RandomNumberGenerator&) { return 0; }
+#endif
diff --git a/botan/checks/eckaeg.cpp b/botan/checks/eckaeg.cpp
new file mode 100644
index 0000000..f25fbb2
--- /dev/null
+++ b/botan/checks/eckaeg.cpp
@@ -0,0 +1,286 @@
+/******************************************************
+* ECKAEG tests *
+* *
+* (C) 2007 Manuel Hartl *
+* hartl@flexsecure.de *
+* 2008 Jack Lloyd *
+******************************************************/
+
+#include <botan/build.h>
+
+#include "validate.h"
+#include "common.h"
+
+#if defined(BOTAN_HAS_ECKAEG)
+
+#include <iostream>
+#include <fstream>
+
+#include <botan/symkey.h>
+#include <botan/dh.h>
+#include <botan/eckaeg.h>
+#include <botan/x509self.h>
+#include <botan/der_enc.h>
+
+#include <botan/point_gfp.h>
+#include <botan/curve_gfp.h>
+#include <botan/gfp_element.h>
+
+using namespace Botan;
+
+#define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+#define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
+
+namespace {
+
+void test_eckaeg_normal_derivation(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ /*
+ std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff";
+ std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc";
+ std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45";
+ std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82";
+ ::Botan::SecureVector<byte> sv_p_secp = decode_hex(p_secp);
+ ::Botan::SecureVector<byte> sv_a_secp = decode_hex(a_secp);
+ ::Botan::SecureVector<byte> sv_b_secp = decode_hex(b_secp);
+ ::Botan::SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp);
+ BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size());
+ BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size());
+ BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size());
+ CurveGFp secp160r1(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ */
+
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+ Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
+
+ /**
+ * begin ECKAEG
+ */
+ // alices key (a key constructed by domain parameters IS an ephimeral key!)
+ Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
+ Botan::ECKAEG_PublicKey public_a = private_a; // Bob gets this
+
+ // Bob creates a key with a matching group
+ Botan::ECKAEG_PrivateKey private_b(rng, dom_pars); //public_a.getCurve()
+
+ // Bob sends the key back to Alice
+ Botan::ECKAEG_PublicKey public_b = private_b; // Alice gets this
+
+ // Both of them create a key using their private key and the other's
+ // public key
+ Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
+ Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
+
+ if(alice_key != bob_key)
+ {
+ std::cout << "The two keys didn't match!\n";
+ std::cout << "Alice's key was: " << alice_key.as_string() << "\n";
+ std::cout << "Bob's key was: " << bob_key.as_string() << "\n";
+ }
+ }
+
+void test_eckaeg_some_dp(RandomNumberGenerator& rng)
+ {
+ std::vector<std::string> oids;
+ oids.push_back("1.2.840.10045.3.1.7");
+ oids.push_back("1.3.132.0.8");
+ oids.push_back("1.2.840.10045.3.1.1");
+
+ for(Botan::u32bit i = 0; i< oids.size(); i++)
+ {
+ std::cout << "." << std::flush;
+ Botan::EC_Domain_Params dom_pars(Botan::get_EC_Dom_Pars_by_oid(oids[i]));
+ Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
+ Botan::ECKAEG_PublicKey public_a = private_a;
+ /*auto_ptr<Botan::X509_Encoder> x509_key_enc = public_a.x509_encoder();
+ Botan::MemoryVector<Botan::byte> enc_key_a = Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(x509_key_enc->alg_id())
+ .encode(x509_key_enc->key_bits(), Botan::BIT_STRING)
+ .end_cons()
+ .get_contents();*/
+
+ Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
+ Botan::ECKAEG_PublicKey public_b = private_b;
+ // to test the equivalence, we
+ // use the direct derivation method here
+
+ Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
+
+ //cout << "encoded key = " << hex_encode(enc_key_a.begin(), enc_key_a.size()) << endl;
+
+ Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
+ CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ //cout << "key: " << alice_key.as_string() << endl;
+ }
+
+ }
+
+void test_eckaeg_der_derivation(RandomNumberGenerator& rng)
+ {
+ std::vector<std::string> oids;
+ oids.push_back("1.2.840.10045.3.1.7");
+ oids.push_back("1.3.132.0.8");
+ oids.push_back("1.2.840.10045.3.1.1");
+
+ for(Botan::u32bit i = 0; i< oids.size(); i++)
+ {
+ Botan::EC_Domain_Params dom_pars(Botan::get_EC_Dom_Pars_by_oid(oids[i]));
+
+ Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
+ Botan::ECKAEG_PublicKey public_a = private_a;
+
+ Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
+ Botan::ECKAEG_PublicKey public_b = private_b;
+
+ Botan::MemoryVector<Botan::byte> key_der_a = private_a.public_value();
+ Botan::MemoryVector<Botan::byte> key_der_b = private_b.public_value();
+ Botan::SymmetricKey alice_key = private_a.derive_key(key_der_b.begin(), key_der_b.size());
+ Botan::SymmetricKey bob_key = private_b.derive_key(key_der_a.begin(), key_der_a.size());
+ CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ //cout << "key: " << alice_key.as_string() << endl;
+ }
+ }
+
+/**
+* The following test tests the copy ctors and and copy-assignment operators
+*/
+void test_eckaeg_cp_ctor_as_op(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+ Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
+
+ /**
+ * begin ECKAEG
+ */
+ // alices key (a key constructed by domain parameters IS an ephimeral key!)
+ Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
+ Botan::ECKAEG_PrivateKey private_a2(private_a);
+ Botan::ECKAEG_PrivateKey private_a3;
+ private_a3 = private_a2;
+
+ Botan::DH_PrivateKey dh_pr_empty;
+ Botan::DH_PublicKey dh_pub_empty;
+
+ Botan::ECKAEG_PublicKey public_a = private_a; // Bob gets this
+ Botan::ECKAEG_PublicKey public_a2(public_a);
+ Botan::ECKAEG_PublicKey public_a3;
+ public_a3 = public_a;
+ // Bob creates a key with a matching group
+ Botan::ECKAEG_PrivateKey private_b(rng, dom_pars); //public_a.getCurve()
+
+ // Bob sends the key back to Alice
+ Botan::ECKAEG_PublicKey public_b = private_b; // Alice gets this
+
+ // Both of them create a key using their private key and the other's
+ // public key
+ Botan::SymmetricKey alice_key = private_a.derive_key(public_b);
+ Botan::SymmetricKey alice_key_2 = private_a2.derive_key(public_b);
+ Botan::SymmetricKey alice_key_3 = private_a3.derive_key(public_b);
+
+ Botan::SymmetricKey bob_key = private_b.derive_key(public_a);
+ Botan::SymmetricKey bob_key_2 = private_b.derive_key(public_a2);
+ Botan::SymmetricKey bob_key_3 = private_b.derive_key(public_a3);
+
+ CHECK_MESSAGE(alice_key == bob_key, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ CHECK_MESSAGE(alice_key_2 == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ CHECK_MESSAGE(alice_key_3 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ CHECK_MESSAGE(alice_key == bob_key_2, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ CHECK_MESSAGE(alice_key_2 == bob_key_3, "different keys - " << "Alice's key was: " << alice_key.as_string() << ", Bob's key was: " << bob_key.as_string());
+ }
+
+/**
+* The following test tests whether ECKAEG keys exhibit correct behaviour when it is
+* attempted to use them in an uninitialized state
+*/
+void test_non_init_eckaeg_keys(RandomNumberGenerator& rng)
+ {
+ std::cout << "." << std::flush;
+
+ // set up dom pars
+ std::string g_secp("024a96b5688ef573284664698968c38bb913cbfc82");
+ Botan::SecureVector<Botan::byte> sv_g_secp = decode_hex(g_secp);
+ BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff");
+ BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc");
+ BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45");
+ BigInt order = BigInt("0x0100000000000000000001f4c8f927aed3ca752257");
+ CurveGFp curve(GFpElement(bi_p_secp,bi_a_secp), GFpElement(bi_p_secp, bi_b_secp), bi_p_secp);
+ BigInt cofactor = BigInt(1);
+ PointGFp p_G = OS2ECP ( sv_g_secp, curve );
+ Botan::EC_Domain_Params dom_pars = Botan::EC_Domain_Params(curve, p_G, order, cofactor);
+
+ // alices key (a key constructed by domain parameters IS an emphemeral key!)
+ Botan::ECKAEG_PrivateKey private_a(rng, dom_pars);
+ Botan::ECKAEG_PrivateKey private_b(rng, dom_pars);
+
+ Botan::ECKAEG_PublicKey public_b;
+
+ Botan::ECKAEG_PrivateKey private_empty;
+ Botan::ECKAEG_PublicKey public_empty;
+
+ bool exc1 = false;
+ try
+ {
+ Botan::SymmetricKey void_key = private_empty.derive_key(public_b);
+ }
+ catch (Botan::Exception e)
+ {
+ exc1 = true;
+ }
+
+ CHECK_MESSAGE(exc1, "there was no exception thrown when attempting to use an uninitialized ECKAEG key");
+
+ bool exc2 = false;
+ try
+ {
+ Botan::SymmetricKey void_key = private_a.derive_key(public_empty);
+ }
+ catch (Botan::Exception e)
+ {
+ exc2 = true;
+ }
+
+ CHECK_MESSAGE(exc2, "there was no exception thrown when attempting to use an uninitialized ECKAEG key");
+ }
+
+}
+
+u32bit do_eckaeg_tests(Botan::RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing ECKAEG (InSiTo unit tests): ";
+
+ test_eckaeg_normal_derivation(rng);
+ test_eckaeg_some_dp(rng);
+ test_eckaeg_der_derivation(rng);
+ test_eckaeg_cp_ctor_as_op(rng);
+ test_non_init_eckaeg_keys(rng);
+
+ std::cout << std::endl;
+
+ return 0;
+ }
+
+#else
+u32bit do_eckaeg_tests(Botan::RandomNumberGenerator&) { return 0; }
+#endif
diff --git a/botan/checks/fail.dat b/botan/checks/fail.dat
new file mode 100644
index 0000000..e7be16f
--- /dev/null
+++ b/botan/checks/fail.dat
@@ -0,0 +1,100 @@
+# Botan validation file: expected failures
+
+# Each sequence in here should induce an exception on the part of the
+# filter, or produce the wrong output, or something like that.
+
+# This needs a lot more work
+
+# MARKER: Block Ciphers
+
+[Blowfish]
+0000000000000000:245946885754369B:
+0000000000000000:245946885754369B:AA
+0000000000000000:24594688575436:AA
+
+00000000000000:24594688575436:
+
+0000000000000000:245946885754369B:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+0000000000000000:245946885754369B:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+[CAST5]
+0123456789ABCDEF:238B4FE5847E44B2:0123456712
+
+# MARKER: Hash Functions
+
+[SHA-1]
+A9:19DA91F2603889267DFD77786E07A5B8F067D6
+A8:19DA91F2603889267DFD77786E07A5B8F067D62A
+
+# MARKER: Cipher Modes (Encryption)
+
+[DES/CBC/CTS]
+9F8789F30E3ED728:48C597491E0C3C1706:9076D5A743FC9721:A9A6C2AD38E682C1
+
+9F8789F30E3ED72800:48C597491E0C3C1706:9076D5A743FC9721:A9A6C2AD38E682
+
+9F8789F30E3ED72800:48C597491E0C3C1706:76D5A743FC9721:A9A6C2AD38E682
+
+# MARKER: Cipher Modes (Decryption)
+
+[DES/CBC/PKCS7]
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+E5C7CDDE872BF27C43E934008C389C0788499A7C05F662C16A27E4FCF276:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+1123456789ABCDEF:1234567890ABCDEF
+
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF276:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEE
+
+1D2FECD6F0F733F1:AA:DC3A72A9BA8138EC:67E51C4F8403BF6F
+
+D90246C39C191E98:AA:45AAF3A76E729062:53C1F28656B05986
+
+[DES/CBC/OneAndZeros]
+28582FD8797D3DB5:AA:D404FD15970CB207:88269176E292DE0A
+A2C23F6A496C7BE9:AA:829E7BE8C8A9B326:106E9D2E19FE874D
+
+[DES/CBC/CTS]
+1F807F8FB9678124B8:9E1CA14BE6538A35DB:88B23AFD0683D337:BAC170D943D262CE
+
+[DES/CFB(1)]
+105EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF89946
+105EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF899
+
+[Base64_Decode]
+3D514D3E:31
+
+[Bzip_Compress <EXTENSION>]
+64484953204953204120425A49503220544553540A:\
+525A6839314159265359FDAED210000009DE0000104000100032604C1020\
+0021A4D1EA0FD2840D03401E19B4D4B254EE89F177245385090FDAED2105
+
+[Bzip_Decompress <EXTENSION>]
+523A683917724538509000000110:
+
+425A6839314159265359FDAED210000009DE0000104000100032604C1020\
+0021A4D1EA0FD2840D03401E19B4D4B254EE89F167245385090FDAED2100:\
+54484953204953204120425A49503220544553540A
+
+123A6839314159265359FDAED210000009DE0000104000100032604C1020\
+0121A4D1EA0FD2840D03401E19B4D4B254EE89F166245385090FDAED2100:\
+54484953204953204120425A49503220544553540A
+
+[Zlib_Decompress <EXTENSION>]
+68DA734C4A76042247C7A4A4246710D3392D3F3F29B1880B106C380868:\
+416263416263414141626262436341626343666F6F6261720A
+
+78DA73742416700100E0260AB5:\
+3141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141410A
diff --git a/botan/checks/getopt.cpp b/botan/checks/getopt.cpp
new file mode 100644
index 0000000..c0145ca
--- /dev/null
+++ b/botan/checks/getopt.cpp
@@ -0,0 +1,85 @@
+
+#include "getopt.h"
+
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+
+OptionParser::OptionParser(const std::string& opt_string)
+ {
+ std::vector<std::string> opts = Botan::split_on(opt_string, '|');
+
+ for(size_t j = 0; j != opts.size(); j++)
+ flags.push_back(OptionFlag(opts[j]));
+ }
+
+OptionParser::OptionFlag
+OptionParser::find_option(const std::string& name) const
+ {
+ for(size_t j = 0; j != flags.size(); j++)
+ if(flags[j].name() == name)
+ return flags[j];
+ throw Botan::Exception("Unknown option " + name);
+ }
+
+bool OptionParser::is_set(const std::string& key) const
+ {
+ return (options.find(key) != options.end());
+ }
+
+std::string OptionParser::value(const std::string& key) const
+ {
+ std::map<std::string, std::string>::const_iterator i = options.find(key);
+ if(i == options.end())
+ throw Botan::Exception("Option " + key + " not found");
+ return i->second;
+ }
+
+std::string OptionParser::value_if_set(const std::string& key) const
+ {
+ return is_set(key) ? value(key) : "";
+ }
+
+void OptionParser::parse(char* argv[])
+ {
+ std::vector<std::string> args;
+ for(int j = 1; argv[j]; j++)
+ args.push_back(argv[j]);
+
+ for(size_t j = 0; j != args.size(); j++)
+ {
+ std::string arg = args[j];
+
+ if(arg.size() > 2 && arg[0] == '-' && arg[1] == '-')
+ {
+ const std::string opt_name = arg.substr(0, arg.find('='));
+
+ arg = arg.substr(2);
+
+ std::string::size_type mark = arg.find('=');
+
+ OptionFlag opt = find_option(arg.substr(0, mark));
+
+ if(opt.takes_arg())
+ {
+ if(mark == std::string::npos)
+ throw Botan::Exception("Option " + opt_name +
+ " requires an argument");
+
+ std::string name = arg.substr(0, mark);
+ std::string value = arg.substr(mark+1);
+
+ options[name] = value;
+ }
+ else
+ {
+ if(mark != std::string::npos)
+ throw Botan::Exception("Option " + opt_name +
+ " does not take an argument");
+
+ options[arg] = "";
+ }
+ }
+ else
+ leftover.push_back(arg);
+ }
+ }
diff --git a/botan/checks/getopt.h b/botan/checks/getopt.h
new file mode 100644
index 0000000..6d6cfe8
--- /dev/null
+++ b/botan/checks/getopt.h
@@ -0,0 +1,45 @@
+
+#ifndef BOTAN_CHECK_GETOPT_H__
+#define BOTAN_CHECK_GETOPT_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+class OptionParser
+ {
+ public:
+ std::vector<std::string> leftovers() const { return leftover; }
+ bool is_set(const std::string&) const;
+
+ std::string value(const std::string&) const;
+ std::string value_if_set(const std::string&) const;
+
+ void parse(char*[]);
+ OptionParser(const std::string&);
+ private:
+ class OptionFlag
+ {
+ public:
+ std::string name() const { return opt_name; }
+ bool takes_arg() const { return opt_takes_arg; }
+
+ OptionFlag(const std::string& opt_string)
+ {
+ std::string::size_type mark = opt_string.find('=');
+ opt_name = opt_string.substr(0, mark);
+ opt_takes_arg = (mark != std::string::npos);
+ }
+ private:
+ std::string opt_name;
+ bool opt_takes_arg;
+ };
+
+ OptionFlag find_option(const std::string&) const;
+
+ std::vector<OptionFlag> flags;
+ std::map<std::string, std::string> options;
+ std::vector<std::string> leftover;
+ };
+
+#endif
diff --git a/botan/checks/gfpmath.cpp b/botan/checks/gfpmath.cpp
new file mode 100644
index 0000000..2352bba
--- /dev/null
+++ b/botan/checks/gfpmath.cpp
@@ -0,0 +1,818 @@
+/******************************************************
+* gfp_element tests *
+* *
+* (C) 2007 Patrick Sona *
+* *
+* Falko Strenzke *
+* strenzke@flexsecure.de *
+* (C) 2008 Jack Lloyd *
+******************************************************/
+
+#include "validate.h"
+
+#if defined(BOTAN_HAS_BIGINT_GFP)
+
+#include <botan/bigint.h>
+#include <botan/numthry.h>
+#include <botan/gfp_element.h>
+#include <botan/gfp_modulus.h>
+#include <botan/curve_gfp.h>
+#include <botan/ec_dompar.h>
+
+#include <iostream>
+
+using namespace Botan;
+
+#define CHECK_MESSAGE(expr, print) if(!(expr)) { std::cout << print << "\n"; pass = false; }
+#define CHECK(expr) if(!(expr)) { std::cout << #expr << "\n"; pass = false; }
+
+namespace {
+
+bool test_turn_on_sp_red_mul()
+ {
+ std::cout << "." << std::flush;
+
+ bool pass = true;
+
+ GFpElement a1(23,15);
+ GFpElement b1(23,18);
+
+ GFpElement c1 = a1*b1;
+
+ GFpElement a2(23,15);
+ GFpElement b2(23,18);
+
+ a2.turn_on_sp_red_mul();
+ a2.turn_on_sp_red_mul();
+ b2.turn_on_sp_red_mul();
+ b2.turn_on_sp_red_mul();
+
+ GFpElement c2 = a2*b2;
+
+ if(c1 != c2)
+ {
+ std::cout << "test_turn_on_sp_red_mul: ";
+ std::cout << "c1 = " << c1 << " != ";
+ std::cout << "c2 = " << c2 << "\n";
+ return false; // test failed
+ }
+
+ return pass; // pass
+ }
+
+bool test_bi_div_even()
+ {
+ std::cout << "." << std::flush;
+
+ bool pass = true;
+
+ std::string str_large("1552518092300708935148979488462502555256886017116696611139052038026050952686323255099158638440248181850494907312621195144895406865083132424709500362534691373159016049946612882688577088900506460909202178541447303914546699487373976586");
+ BigInt to_div(str_large);
+ BigInt half = to_div/2;
+ BigInt should_be_to_div = half*2;
+ CHECK_MESSAGE(should_be_to_div == to_div, "error in division/multiplication of large BigInt");
+
+ // also testing /=...
+ BigInt before_div = to_div;
+ to_div /= 2;
+ BigInt should_be_before(to_div*2);
+ CHECK_MESSAGE(should_be_before == before_div, "error in division/multiplication of large BigInt");
+
+ return pass;
+ }
+
+bool test_bi_div_odd()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string str_large("1552518092300708935148979488462502555256886017116696611139052038026050952686323255099158638440248181850494907312621195144895406865083132424709500362534691373159016049946612882688577088900506460909202178541447303914546699487373976585");
+ BigInt to_div(str_large);
+ BigInt half = to_div/2;
+ BigInt should_be_to_div = half*2;
+ BigInt diff = should_be_to_div-to_div;
+ CHECK_MESSAGE((diff <= 1) && (diff >= BigInt("-1")), "error in division/multiplication (/) of large BigInt, differnce = " << diff);
+
+ // also testing /=...
+ BigInt before_div = to_div;
+ to_div /= 2;
+ BigInt should_be_before(to_div*2);
+ BigInt diff2(should_be_before - before_div);
+ CHECK_MESSAGE((diff2 <= 1) && (diff2 >= BigInt("-1")), "error in division/multiplication (/=) of large BigInt, difference = " << diff2);
+
+ return pass;
+ }
+
+bool test_deep_montgm()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ //std::string s_prime = "5";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333334";
+ //std::string s_value_a = "4";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ //std::string s_value_b = "3";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a_trf(bi_prime, bi_value_a, true);
+ GFpElement gfp_a_ntrf(bi_prime, bi_value_a, false);
+ GFpElement gfp_b_trf(bi_prime, bi_value_b, true);
+ GFpElement gfp_b_ntrf(bi_prime, bi_value_b, false);
+
+ //CHECK(!gfp_b_trf.is_trf_to_mres());
+ gfp_b_trf.get_mres();
+ gfp_a_trf.get_mres();
+
+ GFpElement c_trf(gfp_a_trf * gfp_b_trf);
+ GFpElement c_ntrf(gfp_a_ntrf * gfp_b_ntrf);
+
+ if(c_trf != c_ntrf)
+ {
+ std::cout << "test_deep_montgm - " << c_trf << " != " << c_ntrf << "\n";
+ }
+ return pass; // pass
+ }
+
+bool test_gfp_div_small_numbers()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "13";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "2";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "3";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_b, true);
+ GFpElement gfp_c(bi_prime, bi_value_b, false);
+
+ CHECK(!gfp_a.is_trf_to_mres());
+ //convert to montgomery
+ gfp_b.get_mres();
+ CHECK(gfp_b.is_trf_to_mres());
+ CHECK(!gfp_c.is_trf_to_mres());
+
+ GFpElement res_div_m = gfp_a / gfp_b;
+ CHECK(res_div_m.is_trf_to_mres());
+
+ GFpElement res_div_n = gfp_a / gfp_c;
+ CHECK(!res_div_n.is_trf_to_mres());
+
+ CHECK_MESSAGE(res_div_n.get_value() == res_div_m.get_value(), "transformed result is not equal to untransformed result");
+ CHECK_MESSAGE(gfp_a.get_value() == s_value_a, "GFpElement has changed while division operation");
+ CHECK_MESSAGE(gfp_b.get_value() == s_value_b, "GFpElement has changed while division operation");
+ GFpElement inverse_b = inverse(gfp_b);
+ GFpElement res_div_alternative = gfp_a * inverse_b;
+
+ if(res_div_m != res_div_alternative)
+ {
+ std::cout << "test_gfp_div_small_numbers - a/b != a*b^-1 where\n"
+ << "a = " << gfp_a << "\n"
+ << "b = " << gfp_b << "\n"
+ << "b^-1 = " << inverse_b << "\n"
+ << "a*b^-1 = " << res_div_alternative << "\n"
+ << "a/b = " << res_div_n << "\n";
+ pass = false;
+ }
+
+ CHECK_MESSAGE(res_div_m == res_div_alternative, "a/b is not as equal to a * b^-1");
+ //cout << "Div-result transformed:" << res_div_m.get_value() << endl;
+ //cout << "Div-result untransformed:" << res_div_n.get_value() << endl;
+ //cout << "Div-Alternative: " << res_div_alternative.get_value() << endl;
+ return pass;
+ }
+
+bool test_gfp_basics()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ CHECK(gfp_a.get_p() == s_prime);
+ CHECK(gfp_a.get_value() == s_value_a);
+ CHECK(!gfp_a.is_trf_to_mres());
+ gfp_a.get_mres();
+ CHECK(gfp_a.is_trf_to_mres());
+ return pass;
+ }
+
+bool test_gfp_addSubNegate()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_a, true);
+
+ gfp_b.negate();
+ GFpElement zero = gfp_a + gfp_b;
+ BigInt bi_zero("0");
+ CHECK(zero.get_value() == bi_zero);
+ CHECK(gfp_a.get_value() == bi_value_a);
+ return pass;
+ }
+
+bool test_gfp_mult()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_b, true);
+ GFpElement gfp_c(bi_prime, bi_value_b, false);
+
+ CHECK(!gfp_a.is_trf_to_mres());
+ //convert to montgomery
+ gfp_b.get_mres();
+ CHECK(gfp_b.is_trf_to_mres());
+ CHECK(!gfp_c.is_trf_to_mres());
+
+ GFpElement res_mult_m = gfp_a * gfp_b;
+ CHECK(res_mult_m.is_trf_to_mres());
+
+ GFpElement res_mult_n = gfp_a * gfp_c;
+ CHECK(!res_mult_n.is_trf_to_mres());
+
+ if(res_mult_n != res_mult_m)
+ std::cout << gfp_a << " * " << gfp_b << " =? "
+ << "n = " << res_mult_n << " != m = " << res_mult_m << "\n";
+ return pass;
+ }
+
+bool test_gfp_div()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_b, true);
+ GFpElement gfp_c(bi_prime, bi_value_b, false);
+
+ CHECK(!gfp_a.is_trf_to_mres());
+ //convert to montgomery
+ gfp_b.get_mres();
+ CHECK(gfp_b.is_trf_to_mres());
+ CHECK(!gfp_c.is_trf_to_mres());
+
+ GFpElement res_div_m = gfp_a / gfp_b;
+ CHECK(res_div_m.is_trf_to_mres());
+
+ GFpElement res_div_n = gfp_a / gfp_c;
+ CHECK(!res_div_n.is_trf_to_mres());
+
+ CHECK_MESSAGE(res_div_n.get_value() == res_div_m.get_value(), "transformed result is not equal to untransformed result");
+ CHECK_MESSAGE(gfp_a.get_value() == s_value_a, "GFpElement has changed while division operation");
+ CHECK_MESSAGE(gfp_b.get_value() == s_value_b, "GFpElement has changed while division operation");
+ GFpElement inverse_b = inverse(gfp_b);
+ GFpElement res_div_alternative = gfp_a * inverse_b;
+ CHECK_MESSAGE(res_div_m == res_div_alternative, "a/b is not as equal to a * b^-1");
+ //cout << "Div-result transformed:" << res_div_m.get_value() << endl;
+ //cout << "Div-result untransformed:" << res_div_n.get_value() << endl;
+ //cout << "Div-Alternative: " << res_div_alternative.get_value() << endl;
+ return pass;
+ }
+
+bool test_gfp_add()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_b, true);
+ GFpElement gfp_c(bi_prime, bi_value_b, true);
+
+ CHECK(!gfp_a.is_trf_to_mres());
+ //convert to montgomery
+ gfp_b.get_mres();
+ CHECK(gfp_b.is_trf_to_mres());
+ CHECK(!gfp_c.is_trf_to_mres());
+
+ GFpElement res_add_m = gfp_a + gfp_b;
+ CHECK(res_add_m.is_trf_to_mres());
+
+ GFpElement res_add_n = gfp_a + gfp_c;
+ // commented out by patrick, behavior is clear:
+ // rhs might be transformed, lhs never
+ // for now, this behavior is only intern, doesn't matter for programm function
+ // CHECK_MESSAGE(res_add_n.is_trf_to_mres(), "!! Falko: NO FAIL, wrong test, please repair"); // clear: rhs might be transformed, lhs never
+
+ CHECK(res_add_n.get_value() == res_add_m.get_value());
+ return pass;
+ }
+
+bool test_gfp_sub()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b(bi_prime, bi_value_b, true);
+ GFpElement gfp_c(bi_prime, bi_value_b, true);
+
+ CHECK(!gfp_a.is_trf_to_mres());
+ //convert to montgomery
+ gfp_b.get_mres();
+ CHECK(gfp_b.is_trf_to_mres());
+ CHECK(!gfp_c.is_trf_to_mres());
+
+ GFpElement res_sub_m = gfp_b - gfp_a;
+ CHECK(res_sub_m.is_trf_to_mres());
+ CHECK(gfp_a.is_trf_to_mres()); // added by Falko
+
+ GFpElement res_sub_n = gfp_c - gfp_a;
+
+ // commented out by psona, behavior is clear:
+ // rhs might be transformed, lhs never
+ // for now, this behavior is only intern, doesn't matter for programm function
+ // CHECK_MESSAGE(!res_sub_n.is_trf_to_mres(), "!! Falko: NO FAIL, wrong test, please repair"); // falsche
+ // Erwartung: a wurde durch die operation oben auch
+ // ins m-residue transformiert, daher passiert das hier auch mit
+ // c, und das Ergebnis ist es auch
+
+ CHECK(res_sub_n.get_value() == res_sub_m.get_value());
+ return pass;
+ }
+
+bool test_more_gfp_div()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ std::string s_prime = "5334243285367";
+ BigInt bi_prime(s_prime);
+ std::string s_value_a = "3333333333333";
+ BigInt bi_value_a(s_value_a);
+ std::string s_value_b = "4444444444444";
+ BigInt bi_value_b(s_value_b);
+
+ GFpElement gfp_a(bi_prime, bi_value_a, true);
+ GFpElement gfp_b_trf(bi_prime, bi_value_b, true);
+ GFpElement gfp_b_ntrf(bi_prime, bi_value_b, false);
+
+ CHECK(!gfp_b_trf.is_trf_to_mres());
+ gfp_b_trf.get_mres();
+ CHECK(gfp_b_trf.is_trf_to_mres());
+
+ CHECK(!gfp_a.is_trf_to_mres());
+
+ bool exc_ntrf = false;
+ try
+ {
+ gfp_b_ntrf.get_mres();
+ }
+ catch(Botan::Illegal_Transformation e)
+ {
+ exc_ntrf = true;
+ }
+ CHECK(exc_ntrf);
+
+ CHECK(!gfp_b_ntrf.is_trf_to_mres());
+
+ CHECK_MESSAGE(gfp_b_trf == gfp_b_ntrf, "b is not equal to itself (trf)");
+
+ GFpElement b_trf_inv(gfp_b_trf);
+ b_trf_inv.inverse_in_place();
+ GFpElement b_ntrf_inv(gfp_b_ntrf);
+ b_ntrf_inv.inverse_in_place();
+ CHECK_MESSAGE(b_trf_inv == b_ntrf_inv, "b inverted is not equal to itself (trf)");
+
+ CHECK(gfp_b_trf/gfp_b_ntrf == GFpElement(bi_prime, 1));
+ CHECK(gfp_b_trf/gfp_b_trf == GFpElement(bi_prime, 1));
+ CHECK(gfp_b_ntrf/gfp_b_ntrf == GFpElement(bi_prime, 1));
+ GFpElement rhs(gfp_a/gfp_b_trf);
+ GFpElement lhs(gfp_a/gfp_b_ntrf);
+
+ if(lhs != rhs)
+ {
+ std::cout << "test_more_gfp_div - " << lhs << " != " << rhs << "\n";
+ pass = false;
+ }
+
+ return pass;
+ }
+
+bool test_gfp_mult_u32bit()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ /*
+ Botan::EC_Domain_Params parA(Botan::get_EC_Dom_Pars_by_oid("1.2.840.10045.3.1.1"));
+ CurveGFp curve = parA.get_curve();
+ //CurveGFp curve2 = parA.get_curve();
+ BigInt p = curve.get_p();
+ GFpElement a = curve.get_a();
+ GFpElement a_mr = curve.get_mres_a();
+ Botan::u32bit u_x = 134234;
+ BigInt b_x(u_x);
+ GFpElement g_x(p, b_x);
+ CHECK(a*u_x == a*g_x);
+ CHECK(a*u_x == u_x*a);
+ CHECK(a*g_x == g_x*a);
+ CHECK(a_mr*u_x == a*g_x);
+ CHECK(u_x*a_mr == a*g_x);
+ */
+ return pass;
+ }
+
+/**
+* This tests verifies the functionality of sharing pointers for modulus dependent values
+*/
+bool test_gfp_shared_vals()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ BigInt p("5334243285367");
+ GFpElement a(p, BigInt("234090"));
+ GFpElement shcpy_a(1,0);
+ shcpy_a.share_assign(a);
+ std::tr1::shared_ptr<GFpModulus> ptr1 = a.get_ptr_mod();
+ std::tr1::shared_ptr<GFpModulus> ptr2 = shcpy_a.get_ptr_mod();
+ CHECK_MESSAGE(ptr1.get() == ptr2.get(), "shared pointers for moduli aren´t equal");
+
+ GFpElement b(1,0);
+ b = a; // create a non shared copy
+ std::tr1::shared_ptr<GFpModulus> ptr_b_p = b.get_ptr_mod();
+ CHECK_MESSAGE(ptr1.get() != ptr_b_p.get(), "non shared pointers for moduli are equal");
+
+ a.turn_on_sp_red_mul();
+ GFpElement c1 = a * shcpy_a;
+ GFpElement c2 = a * a;
+ GFpElement c3 = shcpy_a * shcpy_a;
+ GFpElement c4 = shcpy_a * a;
+ shcpy_a.turn_on_sp_red_mul();
+ GFpElement c5 = shcpy_a * shcpy_a;
+
+ if(c1 != c2 || c2 != c3 || c3 != c4 || c4 != c5)
+ {
+ std::cout << "test_gfp_shared_vals failed"
+ << " a=" << a
+ << " shcpy_a=" << shcpy_a
+ << " c1=" << c1 << " c2=" << c2
+ << " c3=" << c3 << " c4=" << c4
+ << " c5=" << c5 << "\n";
+ pass = false;
+ }
+
+ swap(a,shcpy_a);
+ std::tr1::shared_ptr<GFpModulus> ptr3 = a.get_ptr_mod();
+ std::tr1::shared_ptr<GFpModulus> ptr4 = shcpy_a.get_ptr_mod();
+ CHECK_MESSAGE(ptr3.get() == ptr4.get(), "shared pointers for moduli aren´t equal after swap");
+ CHECK(ptr1.get() == ptr4.get());
+ CHECK(ptr2.get() == ptr3.get());
+
+ swap(a,b);
+ std::tr1::shared_ptr<GFpModulus> ptr_a = a.get_ptr_mod();
+ std::tr1::shared_ptr<GFpModulus> ptr_b = shcpy_a.get_ptr_mod();
+ CHECK(ptr_a.get() == ptr_b_p.get());
+ CHECK(ptr_b.get() == ptr3.get());
+ return pass;
+ }
+
+/**
+* The following test checks the behaviour of GFpElements assignment operator, which
+* has quite complex behaviour with respect to sharing groups and precomputed values
+* (with respect to montgomery mult.)
+*/
+bool test_gfpel_ass_op()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+
+ // test different moduli
+ GFpElement a(23,4);
+ GFpElement b(11,6);
+
+ GFpElement b2(11,6);
+
+ a = b;
+ CHECK(a==b2);
+ CHECK(a.get_value() == b2.get_value());
+ CHECK(a.get_p() == b2.get_p());
+ CHECK(a.get_ptr_mod().get() != b.get_ptr_mod().get()); // sharing groups
+ // may not be fused!
+
+ // also test some share_assign()...
+ a.share_assign(b);
+ CHECK(a==b2);
+ CHECK(a.get_value() == b2.get_value());
+ CHECK(a.get_p() == b2.get_p());
+ CHECK(a.get_ptr_mod().get() == b.get_ptr_mod().get()); // sharing groups
+ // shall be fused!
+ //---------------------------
+
+ // test assignment within sharing group
+ // with montg.mult.
+ GFpElement c(5,2);
+ GFpElement d(5,2);
+ d.share_assign(c);
+ CHECK(d.get_ptr_mod().get() == c.get_ptr_mod().get());
+ CHECK(d.get_ptr_mod()->get_p() == c.get_ptr_mod()->get_p());
+ CHECK(c.get_ptr_mod()->get_r().is_zero());
+ c.turn_on_sp_red_mul();
+ CHECK(d.get_ptr_mod().get() == c.get_ptr_mod().get());
+ CHECK(d.get_ptr_mod()->get_p() == c.get_ptr_mod()->get_p());
+ CHECK(!c.get_ptr_mod()->get_p().is_zero());
+ GFpElement f(11,5);
+ d = f;
+ CHECK(f.get_ptr_mod().get() != c.get_ptr_mod().get());
+
+ GFpElement e = c*c;
+ GFpElement g = d*d;
+ GFpElement h = f*f;
+ CHECK(h == g);
+
+ GFpElement c2(5,2);
+ GFpElement d2(5,2);
+ d2.share_assign(c2);
+ GFpElement f2(11,5);
+ d2 = f2;
+ c2.turn_on_sp_red_mul();
+ CHECK(d2.get_ptr_mod().get() != c2.get_ptr_mod().get()); // the sharing group was left
+ CHECK(d2.get_ptr_mod()->get_r() == f2.get_ptr_mod()->get_r());
+ CHECK(c2.get_p() == 5); // c2´s shared values weren´t modified because
+ // the sharing group with d2 was separated by
+ // the assignment "d2 = f2"
+
+ d2.turn_on_sp_red_mul();
+ CHECK(d2.get_ptr_mod()->get_p() != c2.get_ptr_mod()->get_p());
+ GFpElement e2 = c2*c2;
+ GFpElement g2 = d2*d2;
+ GFpElement h2 = f2*f2;
+ CHECK(h2 == g2);
+
+ GFpElement c3(5,2);
+ GFpElement d3(5,2);
+ d3.share_assign(c3);
+ GFpElement f3(11,2);
+ d3 = f3;
+ GFpElement e3 = c3*c3;
+ GFpElement g3 = d3*d3;
+
+ CHECK(e == e2);
+ CHECK(g == g2);
+
+ CHECK(e == e3);
+ CHECK(g == g2);
+ return pass;
+ }
+
+bool test_gfp_swap()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+
+ BigInt p("173");
+ GFpElement a(p, BigInt("2342"));
+ GFpElement b(p, BigInt("423420"));
+
+ GFpModulus* a_mod = a.get_ptr_mod().get();
+ GFpModulus* b_mod = b.get_ptr_mod().get();
+
+ //GFpModulus* a_d = a.get_ptr_mod()->get_p_dash();
+ //GFpModulus* b_d = b.get_ptr_mod()->get_p_dash();
+
+ swap(a,b);
+ CHECK_MESSAGE(b.get_value() == 2342%173, "actual value of b was: " << b.get_value() );
+ CHECK_MESSAGE(a.get_value() == 423420%173, "actual value of a was: " << a.get_value() );
+
+ CHECK(a_mod == b.get_ptr_mod().get());
+ CHECK(b_mod == a.get_ptr_mod().get());
+ //CHECK(a_d == b.get_ptr_mod()->get_p_dash());
+ //CHECK(b_d == a.get_ptr_p_dash()->get_p_dash());
+
+ GFpElement c(p, BigInt("2342329"));
+ GFpElement d(1,1);
+ d.share_assign(c);
+ d += d;
+ c.swap(d);
+ CHECK(d.get_value() == 2342329%173);
+ CHECK(c.get_value() == (d*2).get_value());
+ return pass;
+ }
+
+bool test_inv_in_place()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ BigInt mod(173);
+ GFpElement a1(mod, 288);
+ a1.turn_on_sp_red_mul();
+ a1.get_mres(); // enforce the conversion
+
+ GFpElement a1_inv(a1);
+ a1_inv.inverse_in_place();
+
+ GFpElement a2(mod, 288);
+ GFpElement a2_inv(a2);
+ a2_inv.inverse_in_place();
+
+ /*cout << "a1_inv = " << a1_inv << endl;
+ cout << "a2_inv = " << a2_inv << endl;*/
+ CHECK_MESSAGE(a1_inv == a2_inv, "error with inverting tranformed GFpElement");
+
+ CHECK(a1_inv.inverse_in_place() == a1);
+ CHECK(a2_inv.inverse_in_place() == a2);
+ return pass;
+ }
+
+bool test_op_eq()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ BigInt mod(173);
+ GFpElement a1(mod, 299);
+ a1.turn_on_sp_red_mul();
+ a1.get_mres(); // enforce the conversion
+ GFpElement a2(mod, 288);
+ CHECK_MESSAGE(a1 != a2, "error with GFpElement comparison");
+ return pass;
+ }
+
+bool test_rand_int(RandomNumberGenerator& rng)
+ {
+ bool pass = true;
+
+ for(int i=0; i< 100; i++)
+ {
+ std::cout << '.' << std::flush;
+ BigInt x = BigInt::random_integer(rng, 1,3);
+ //cout << "x = " << x << "\n"; // only 1,2 are put out
+ CHECK(x == 1 || x==2);
+ }
+
+ return pass;
+ }
+
+bool test_bi_bit_access()
+ {
+ std::cout << '.' << std::flush;
+
+ bool pass = true;
+
+ BigInt a(323);
+ CHECK(a.get_bit(1) == 1);
+ CHECK(a.get_bit(1000) == 0);
+ return pass;
+ }
+
+#if 0
+bool test_sec_mod_mul()
+ {
+ //cout << "starting test_sec_mod_mul" << endl;
+
+ bool pass = true;
+
+ //mod_mul_secure(BigInt const& a, BigInt const& b, BigInt const& m)
+
+ BigInt m("5334243285367");
+ BigInt a("3333333333333");
+ BigInt b("4444444444444");
+ for(int i = 0; i<10; i++)
+ {
+ std::cout << '.' << std::flush;
+ BigInt c1 = a * b;
+ c1 %= m;
+ BigInt c2 = mod_mul_secure(a, b, m);
+ CHECK_MESSAGE(c1 == c2, "should be " << c1 << ", was " << c2);
+ }
+ //cout << "ending test_sec_mod_mul" << endl;
+ return pass;
+ }
+#endif
+
+#if 0
+bool test_sec_bi_mul()
+ {
+ //mod_mul_secure(BigInt const& a, BigInt const& b, BigInt const& m)
+
+ bool pass = true;
+
+ BigInt m("5334243285367");
+ BigInt a("3333333333333");
+ BigInt b("4444444444444");
+ for(int i = 0; i<10; i++)
+ {
+ std::cout << '.' << std::flush;
+ BigInt c1 = a * b;
+ //c1 %= m;
+ BigInt c2(a);
+ c2.mult_this_secure(b, m);
+ CHECK_MESSAGE(c1 == c2, "should be " << c1 << ", was " << c2);
+ }
+
+ return pass;
+ }
+#endif
+
+}
+
+u32bit do_gfpmath_tests(Botan::RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing GF(p) math " << std::flush;
+
+ u32bit failed = 0;
+
+ failed += !test_turn_on_sp_red_mul();
+ failed += !test_bi_div_even();
+ failed += !test_bi_div_odd();
+ failed += !test_deep_montgm();
+ failed += !test_gfp_div_small_numbers();
+ failed += !test_gfp_basics();
+ failed += !test_gfp_addSubNegate();
+ failed += !test_gfp_mult();
+ failed += !test_gfp_div();
+ failed += !test_gfp_add();
+ failed += !test_gfp_sub();
+ failed += !test_more_gfp_div();
+ failed += !test_gfp_mult_u32bit();
+ failed += !test_gfp_shared_vals();
+ failed += !test_gfpel_ass_op();
+ failed += !test_gfp_swap();
+ failed += !test_inv_in_place();
+ failed += !test_op_eq();
+ failed += !test_rand_int(rng);
+ failed += !test_bi_bit_access();
+ //failed += !test_sec_mod_mul();
+ //failed += !test_sec_bi_mul();
+
+#if 0
+ if(failed == 0)
+ std::cout << " OK";
+ else
+ std::cout << ' ' << failed << " failed";
+#endif
+
+ std::cout << std::endl;
+
+ return failed;
+ }
+#else
+u32bit do_gfpmath_tests(Botan::RandomNumberGenerator&) { return 0; }
+#endif
diff --git a/botan/checks/misc.cpp b/botan/checks/misc.cpp
new file mode 100644
index 0000000..1986714
--- /dev/null
+++ b/botan/checks/misc.cpp
@@ -0,0 +1,77 @@
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include <botan/pipe.h>
+#include <botan/hex.h>
+using namespace Botan;
+
+#include "common.h"
+
+void strip_comments(std::string& line)
+ {
+ if(line.find('#') != std::string::npos)
+ line = line.erase(line.find('#'), std::string::npos);
+ }
+
+void strip_newlines(std::string& line)
+ {
+ while(line.find('\n') != std::string::npos)
+ line = line.erase(line.find('\n'), 1);
+ }
+
+/* Strip comments, whitespace, etc */
+void strip(std::string& line)
+ {
+ strip_comments(line);
+
+#if 0
+ while(line.find(' ') != std::string::npos)
+ line = line.erase(line.find(' '), 1);
+#endif
+
+ while(line.find('\t') != std::string::npos)
+ line = line.erase(line.find('\t'), 1);
+ }
+
+SecureVector<byte> decode_hex(const std::string& in)
+ {
+ SecureVector<byte> result;
+
+ try {
+ Botan::Pipe pipe(new Botan::Hex_Decoder);
+ pipe.process_msg(in);
+ result = pipe.read_all();
+ }
+ catch(std::exception& e)
+ {
+ result.destroy();
+ }
+ return result;
+ }
+
+std::string hex_encode(const byte in[], u32bit len)
+ {
+ Botan::Pipe pipe(new Botan::Hex_Encoder);
+ pipe.process_msg(in, len);
+ return pipe.read_all_as_string();
+ }
+
+std::vector<std::string> parse(const std::string& line)
+ {
+ const char DELIMITER = ':';
+ std::vector<std::string> substr;
+ std::string::size_type start = 0, end = line.find(DELIMITER);
+ while(end != std::string::npos)
+ {
+ substr.push_back(line.substr(start, end-start));
+ start = end+1;
+ end = line.find(DELIMITER, start);
+ }
+ if(line.size() > start)
+ substr.push_back(line.substr(start));
+ while(substr.size() <= 4) // at least 5 substr, some possibly empty
+ substr.push_back("");
+ return substr;
+ }
+
diff --git a/botan/checks/mp_valid.dat b/botan/checks/mp_valid.dat
new file mode 100644
index 0000000..88ec2df
--- /dev/null
+++ b/botan/checks/mp_valid.dat
@@ -0,0 +1,2983 @@
+# BigInt validation file
+
+# These are all in decimal, mostly to help make sure the I/O and decimal
+# conversion stuff is working. We test the hex conversion in the PK tests
+# anyway...
+
+# Some of the numbers have very simple binary representations (such as
+# 2^256-2^192-1) while others are chosen 'randomly', mostly by me hitting
+# random keys into 'bc'. Some where also machine generated with a strong PRNG.
+
+[Addition]
+0:0:0
+0:1:1
+1:0:1
+1:1:2
+1:-1:0
+
+5:-0:5
+-5:-0:-5
+-0:5:5
+
+255:1:256
+
+65535:1:65536
+
+4294967295:1:4294967296
+
+18446744073709551615:1:18446744073709551616
+
+124536363637272472:124536363637272472:249072727274544944
+
+9223372036854775807:281474976710655:9223653511831486462
+
+9223372036854775807:137438953471:9223372174293729278
+
+# Carry tests
+340282366920938463463374607431768211455:\
+340282366920938463463374607431768211455:\
+680564733841876926926749214863536422910
+
+340282366920938463463374607431768211455:\
+340282366920938463463374607431768211450:\
+680564733841876926926749214863536422905
+
+11579208923731619542357098500868790785326998466564056403945758400791\
+3129639935:\
+11579208923731619542357098500868790785326998466564056403945758400791\
+3129639935:\
+23158417847463239084714197001737581570653996933128112807891516801582\
+6259279870
+
+11579208923731619542357098500868790785326998466564056403945758400791\
+3129639935:\
+11579208923731619542357098500868790785326998466564056403945758400791\
+3129639919:\
+23158417847463239084714197001737581570653996933128112807891516801582\
+6259279854
+
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+18446744073709551616:\
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194658\
+8393177722715635711
+
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:1:\
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084096
+
+-397942700139194066108348269604271467697661897648384734165029652\
+9192053560111268857919862747528477749805933030612876334500852832\
+5994574657552726381901:\
+-342238655038:\
+-397942700139194066108348269604271467697661897648384734165029652\
+9192053560111268857919862747528477749805933030612876334500852832\
+5994574657894965036939
+
+2511029185349894083125189792298767815734633609329237357694542628\
+9097725034326735312448621015537884914:\
+-365510811543986457345339657399796975273732516080550566276869562\
+81114038842935173436543461:\
+2511029185346238975009749927725314419160635639576500032533737123\
+2470038078045621273605685842101341453
+
+27802650352:\
+660736146705288303126411072388564329913778942:\
+660736146705288303126411072388564357716429294
+
+-134824589995504186480095446370988146623149603821668360871542456\
+6397833766910915722793041224478985289:\
+1151714952286618235856515264359526625702022859705853911311473221\
+8008332987904361457299261161227276764386173666571334749062651694\
+592291882972:\
+1151714952286618235856515264359526625701888035115858407124993126\
+3544623106438129961261044477618561339819775832804423833339858653\
+367812897683
+
+-175405304416816169628682516351336019150390262549968865836182439\
+14226325157426408929602625346567256761818:\
+8652004279835272452069018101603566414024194616420826231795446815\
+19016990:\
+-175405304416816169628682516351327367146110427277516796818080835\
+57584922737964766846979445801885737744828
+
+1288447760742982615563987140969486034581770182750513292185554983\
+74:\
+4438163138291508763620522351346106032205489281076979612299536118\
+73695276391917150913346479060246759720475193648:\
+4438163138291508763620522351346106032205489282365427373042518734\
+30093990488865754371523497335298088939030692022
+
+1709484189262457846620911889502097055085989595277300243221975568\
+275935717696463:\
+-1646592344139809206374540620411514484579951199941360:\
+1709484189262457846620911887855504710946180388902759622810461083\
+695984517755103
+
+3201758654296371761657093415761871025401806278064180152049287711\
+7023353895132395250905592913967322327352806288308303059519915387\
+7335714942842:\
+-282824169696073608987996588238668793593857085654548122761949764\
+0844399275054327390050478930503975773972:\
+3201758654296371761657093415761871025373523861094572791150488052\
+8784685101538538165251044791205372563268366360802870320514867494\
+6831739168870
+
+-403539836054218172590829531210749614210541501474425943996337720\
+4111754181625695349185753326709217:\
+85450213703789913646546187382091037800:\
+-403539836054218172590829531210749614210541501474425943996329175\
+3898050391712048802998371235671417
+
+-129216644607347987680152236338235788743165763918415128477552538\
+7363973852756087726243671676713861533673009088319851:\
+8045388958745181755374994252823750582362455317985903504033438417\
+6695557207064326714194569562489510933024274993575473943439469171\
+4971:\
+8045388958745181742453329792088951814347231684162324629716862025\
+8280428729511787977797184286880738308657107322189320576138560339\
+5120
+
+-451986588700926309459451756852005697379481014956007968529234251\
+884946522682901215022086432597024324062240835564200177389:\
+15762983479:\
+-451986588700926309459451756852005697379481014956007968529234251\
+884946522682901215022086432597024324062240835548437193910
+
+-390747541211572881697456702205527837411679402562428747433403883\
+1885743634200801846649105209920908153587891040882946582394429615\
+396962188674594744360388466:\
+1938936112365378546948796774781062371570792073982831173929981754\
+54362643521031390:\
+-390747541211572881697456702205527837411679402562428747433403883\
+1885743634006908235412567355226028476109784803725867374996146498\
+003964013220232100839357076
+
+-72603710637966201224690926289:\
+-136184426422985332615812550349236126405125071507280171067688615\
+06299813289801666559564532:\
+-136184426422985332615812550349236126405125071507280171067689341\
+10010451256002891250490821
+
+5607796083571305683140294840679074710788944676935750975947220760\
+3483968107693997028111823994257399379783658853302692762256851623\
+103019589392739:\
+-427057313888431079237360487703561848638868677065083968842:\
+5607796083571305683140294840679074710788944676935750975947220760\
+3483968107693997028111396936943510948704421492814989200408212754\
+425954505423897
+
+-220980083850850444349478376253480033771210140515678470878219758\
+0824527899758308:\
+4284407650303949586450021392583759850781770841835415277411207859\
+6443089606598570396235816327987463393971710495985285591895096794\
+994387176281079:\
+4284407650303949586450021392583759850781770841835415277411207859\
+4233288768090065952741032565452663056259609090828500883112899214\
+169859276522771
+
+3388776730880982684241784117615223232127223178833840452685901937\
+0507113927387984766381329515371768224976188337692:\
+349484339542971517481628970179002500341:\
+3388776730880982684241784117615223232127223178833840452685901937\
+0507113927737469105924301032853397195155190838033
+
+8574808963985866072258732162153629808269070752641242695163010155\
+1228144063151688592419555048867068162:\
+-383634567691961960211191292397062452265352651123492760493087381\
+707279:\
+8574808963985866072258732162153591444812301556445221576033770448\
+8775878710500565099659061961485360883
+
+23889807888563742283608049816129153552608399262924421832404872043475:\
+995:\
+23889807888563742283608049816129153552608399262924421832404872044470
+
+-654786925833474864669230962582694222611472680701859262466465606\
+239654996048306783957549697781271829257774329538985:\
+-276137507159648540503039013089014674747:\
+-654786925833474864669230962582694222611472680701859262466465606\
+239654996048582921464709346321774868270863344213732
+
+50463316268089933:\
+-140591583463431806921000349498135287589005423318927850947894242\
+9953101385694731575213124136524392343244191305277028999171613076\
+57443381774866237429:\
+-140591583463431806921000349498135287589005423318927850947894242\
+9953101385694731575213124136524392343244191305277028999171613076\
+57392918458598147496
+
+1339015021665554488163337105187026760232395594198925052890859936\
+418304234254229440059229155546157793544192:\
+6294037420283433712414743361937677483761554699961644450461297486\
+2247932788230044871756877711635975905661325925915992499702811257\
+81761944353272:\
+6294037420283433712414743361937677485100569721627198938624634591\
+4118200390554000813746128240544575269844368268458286900295102813\
+27919737897464
+
+-241446683:\
+-282671163032866994488211995758272717472259277760825940523445628\
+442206062910449311538519756165635175664610569214430918184214:\
+-282671163032866994488211995758272717472259277760825940523445628\
+442206062910449311538519756165635175664610569214431159630897
+
+2358605503303452637996081421902056515951744611718383128442445119\
+505739707550326378912342448355046239066896995563581:\
+-383043722914532516527336452555126144064884579194968166126094695\
+6860463720730123941973615:\
+2358605503303452637996081418071619286806419446445018602891183678\
+856893915600644717651395491494582518336773053589966
+
+1860794367587960058388097846258490:\
+-237344494507203983863096991896035366478949095337787603280:\
+-237344494507203983863095131101667778518890707239941344790
+
+-286399096802321907543674770412181810379003627366516307780436082\
+546:\
+6433131620680089024037442172197761714707480582555136398379812339\
+597187475099646442833150194:\
+6433131620680089024037441885798664912385573038880365986198001960\
+593560108583338662397067648
+
+1811803390771023695595378175836278947833228041818597295747524425\
+7214680056902377349016498752054120312533829578576324428322456925\
+9250011493:\
+-119912766577350317025030707802803587547945939765717835695952624\
+5067549497129923023348187933280753018204983010837846725666878521\
+137637491:\
+1799812114113288663892875105055998589078433447842025512177929163\
+2707925107189385046681679958726045010713331277492539755755769073\
+8112374002
+
+-641402013955555338114086428916201846520512758110759261762820321\
+4491558550345077676836677565241902214951203461131114985869530775\
+0874152:\
+174441039:\
+-641402013955555338114086428916201846520512758110759261762820321\
+4491558550345077676836677565241902214951203461131114985869530757\
+6433113
+
+1272757944308835857208037878018507337530557445422230495561634616\
+5037244198775127175123602392596401935136013522028214622088960493\
+31599624285621:\
+7326562354017884140300121264633612334070903165496641915889499701\
+38457507491850467631029977010:\
+1272757944308835857208037878018507337530557445422963151797036404\
+9177544320039760787457673295761898577051903021729599197163878997\
+99230654262631
+
+-296171972628230:\
+-829576609912184321900082369936222286517382010256973151771639172\
+7126741710202086962877467940292139:\
+-829576609912184321900082369936222286517382010256973151771639172\
+7126741710202086963173639912920369
+
+7469859140681995100248436821088394448284142227691915206159676323\
+62127522466922882591:\
+-20487191102299831461877807785745372724903547246374023:\
+7469859140681995100248436821088189576373119229377296428081818869\
+89402618919676508568
+
+-4:\
+-234439009075326480604323496098115161312227136676259000693031887\
+6906455201397017135:\
+-234439009075326480604323496098115161312227136676259000693031887\
+6906455201397017139
+
+-448761802739957373377693318750581411296787367117499463888322757\
+67882143882764:\
+20982187786:\
+-448761802739957373377693318750581411296787367117499463888322757\
+67861161694978
+
+-601944008264824351134005823298148744369561537910415436895793990\
+7896782179207195666302228625496897271988494:\
+5325663024991554160033166078015937845836527207540797603647364222\
+91735917382015688217276924340984564880:\
+-601890751634574435592405491637368584991103172638340028919757517\
+1474490443289813650614011348572556287423614
+
+-737554715636160268477263493571675308338509596629210590529282292\
+3781472871944886871927821129478599825311797681268315326408823018\
+2865250970217610487:\
+-30100016097092378349958946184353117306134810372681:\
+-737554715636160268477263493571675308338509596629210590529282292\
+3781472871944886871927821129478602835313407390506150322303441453\
+5982557105027983168
+
+-221117706668970434568685275663894630667495895204444708028536428\
+3965878599873864667094550865713828159912:\
+-536556043937245689200756579876160678199726920153847573681478030\
+0517383963455858081652308237033460360040921820049494698892905680\
+307378540208:\
+-536556043937245689200756579876160678420844626822818008250163305\
+7156330270130817033696755317318824644006800419923359365987456546\
+021206700120
+
+6074122512337108841968521649035076841633691574254417104144285970\
+8190687151580370231498672521465704184848502349798380642493738161\
+63440:\
+301843614094506325875637699:\
+6074122512337108841968521649035076841633691574254417104144285970\
+8190687151580370231498672521465704184848505368234521587556996918\
+01139
+
+-518214776931158149908771340564348982010543985108065053479219152\
+7346598920424997741288096547136515478330872068932567407374262007\
+15673766732196603988:\
+-298351725577476937261155258873861370046745453114225573456588840\
+38760353928226157702249175218280718951979:\
+-518214776931158149908771340564348982010544014943237611226912878\
+8501857794286367788033549661362088934919712456536106689635839029\
+64848985012915555967
+
+15937412249227240968245047444122:\
+1862146803761694261088224507009788278865690534402542585855766455\
+30381613666540347032550716844628275956253:\
+1862146803761694261088224507009788278865690534402542585855766455\
+30381613682477759281777957812873323400375
+
+-125280101162586858550475042529281076239231054587017617079119695\
+27003855713485846140551107967495813584097081777160:\
+-539986280927242338236008809854961759996986302156061552378097160\
+849129372827386927545686899193598721998757419572890:\
+-552514291043501024091056314107889867620909407614763314086009130\
+376133228540872773686238007161094535582854501350050
+
+-2454746908:\
+-382295712788939478005524215636037018707559207865555237605060467\
+9934415014573879513870030211860839641756441626913419699098985245\
+833920954444218:\
+-382295712788939478005524215636037018707559207865555237605060467\
+9934415014573879513870030211860839641756441626913419699098985245\
+833923409191126
+
+-54288706131860071583318409080596095357980447323635:\
+-425339410556015631098973742993327323051438456819027069606294261\
+157940297643297240559452124432779202181589763874:\
+-425339410556015631098973742993327323051438456819027069606294315\
+446646429503368823877861205028874560162037087509
+
+1418766894051319870818496026367686195459604395660119754151922014\
+257535705077512233275240217434104:\
+-111987390206074845527:\
+1418766894051319870818496026367686195459604395660119754151922014\
+257535705077400245885034142588577
+
+-690410131860410477456103857594543515409677479242833618634809302\
+4529626004763532868225501682312348541164651530788457447229874477\
+19420052500874721214723:\
+-258469037743394674731135699243278836145549479106673938483740960\
+9897387109736539600623155880918146331681272708396146283818299:\
+-690410131860410477456103860179233892843624226554190611067597663\
+9084573915430926716599597781286219638530047537020016256411337794\
+00692760897021005033022
+
+-2326153002179462643778624079324592172489363679671158:\
+-109819757548464054181938329012610459679:\
+-2326153002179572463536172543378774110818376290130837
+
+-442875225056652548835385770919494174299378557880791141401695920\
+6453045495320705299466107784149485981354180907411034982168391:\
+-392477782593742153255217680053880075265812358324465405897205608\
+55741992694947322437679214611686905696:\
+-442875225056652548835389695697320111720911110057591680202448578\
+7688877941861295020026963526142180928676618586625646669074087
+
+3047:\
+-735645878503131535237769321637196107334337768903902046180401737\
+9719600010085607082927794304834315616579528230750813527764131521\
+4:\
+-735645878503131535237769321637196107334337768903902046180401737\
+9719600010085607082927794304834315616579528230750813527764131216\
+7
+
+-89094716573076464980713547115099137014719483620102078148320806773871\
+083148864:\
+89094716573076464980713547115099137014719483620102078148320806773871\
+083148864:0
+
+-89094716573076464980713547115099137014719483620102078148320806773871\
+083148864:\
+-89094716573076464980713547115099137014719483620102078148320806773871\
+083148864:\
+-17818943314615292996142709423019827402943896724020415629664161354774\
+2166297728
+
+7139718976538104911036273126224339498939049952371944598728684359\
+8407339615555456955143712741779487184644001767776382991377987516\
+772847242986:\
+-5821969555717973232123574849275726788359152255219972775831:\
+7139718976538104911036273126224339498939049952371944598728684359\
+8407339615555456949321743186061513952520426918500656203018835261\
+552874467155
+
+-181409752656613138777964092635909379021826360390960647186726991\
+165227400176766831466541160049935205507919070233410228328274:\
+-523301382154855044703947051892202646490840761177533623732372519\
+6899184207698424247726764075013505280967149049152973476842478027\
+73107355881667545916901:\
+-523301382154855044703947052073612399147453899955497716368281898\
+7117447811608030719594033986665779282734817363818385077341830082\
+81026426115077774245175
+
+6858961373707073067:\
+-334051508933893061433844279764271107181974906283364991309903077\
+649971606436918071327072869826471946094594594115614990907:\
+-334051508933893061433844279764271107181974906283364991309903077\
+649971606436918071327072869826471946087735632741907917840
+
+-236350989303745694071719069604296168709084242815199446584909401\
+09956689534874971218650241680916564611:\
+-189589178757795228335995891331428279524485393011427187469792714\
+4384667023598274379343968662673642819854164720298367788750543006\
+0922528525205:\
+-189589178757795228335995891331428279524721744000730933163864433\
+5080709985285365221772120657139491913865160389251855285872408030\
+2603445089816
+
+[Subtraction]
+0:0:0
+
+0:1:-1
+
+1:-1:2
+
+100:-100:200
+
+0:-1:1
+
+0:4294967296:-4294967296
+
+4294967296:-4294967296:8589934592
+4294967295:-4294967295:8589934590
+
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:0
+
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+-13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+26815615859885194199148049996411692254958731641184786755447122887443\
+52806014709395360374859633380685538006371637297210170750776562389313\
+9892867298012168190
+
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474124377767893424865485276302219601246094119453082952\
+08500576883815068234246288147391311054082723716335051068458629823994\
+7245938479716304835356329624224137215:\
+-17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474124377767893424865485276302219601246094119453082952\
+08500576883815068234246288147391311054082723716335051068458629823994\
+7245938479716304835356329624224137215:\
+35953862697246318154586103815780494672359539578846131454686016231546\
+53516110019262654169546448150720422402277597427867153175795376288332\
+44985694861278948248755535786849730970552604439202492188238906165904\
+17001153767630136468492576294782622108165447432670102136917259647989\
+4491876959432609670712659248448274430
+
+# 2^512 - 1
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:1:\
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084094
+
+89094716573076464980713547115099137014719483620102078148320806773871\
+083148864:\
+49505213825110728957828173754776257356620450607893971553289366249708\
+672306581:\
+39589502747965736022885373360322879658099033012208106595031440524162\
+410842283
+
+65894747009896006767807716946835412110318548717263922395390971078905\
+789585431:\
+38842697419255082259907154168620472841946037999026507486310396086843\
+67281358:\
+62010477267970498541817001529973364826123944917361271646759931470221\
+422304073
+
+5950196396451977566902121301707054218364717196893101360011491777\
+7619522537369647091659626133477106071641786829877837558948110242\
+88429224592316636383:\
+8750653273562160761286422180115618621879821429145276197424652349\
+306577311499807887070429373153777028581165316131683348567:\
+5950196396451977566902121292956400944802556435606679179895873155\
+8821308245916885117413102640411332956643707959173543827410339957\
+07263908460633287816
+
+9815262808265519920770782360080149146267723690:\
+1406700576889160928136491935811529134135218991825578039756006074\
+8765650205261663193732434161580120817:\
+-140670057688916092813649193581152913413521899182557803877447979\
+40500130284490880833652285015312397127
+
+-390149102941948621568479722346940666704376013734485343840154221\
+6058534125031549938788864908670209347775308945934163371753998650\
+65870417717658815158195790:\
+1456031684988128870809574635750149625240648487837308:\
+-390149102941948621568479722346940666704376013734485343840154221\
+6058534125031549938788864908670209347789869262784044660462094397\
+01620567342899463646033098
+
+7473774301764883450943:\
+-262563698593678907551573728200523874834027237901855629084919338\
+12453:\
+2625636985936789075515737282005238748340272379765933721025681726\
+3396
+
+3624634325121492202413918675700914884929548559339795200323734966\
+0142296147421019916619944353877490544706223768684758263065399016\
+597969:\
+2574427901445527995149185461475228850098549655325125750771680756\
+4031046245695227927925972232181431549249881995623555170649626659\
+54307425375180:\
+-257442786519918474393426343733604209308940080602964015737372875\
+3165754964427226645371577306598198801047497654856131748380204402\
+888908408777211
+
+30129746266682790628283889040897642317014108334116727:\
+-158048052389539876256372171547438090363007387136214391586439872\
+4834897608423:\
+1580480523895398762563751845220647586420702155251184813506715738\
+943231725150
+
+-4614735863800137951667138933166372061:\
+87175694379075561307234146162193190462135078700346746992273:\
+-87175694379075561307238760898056990600086745839279913364334
+
+-3753904:\
+-11269137783745339515071988205310702154422777729974:\
+11269137783745339515071988205310702154422773976070
+
+5925239484953794400820212797381700884029188584554700501406527871\
+71830058864932939900794505955437856926902975870288:\
+-205854658295495452479104108497931263758143158076949293929661651\
+111:\
+5925239484953794400820212797381700884029188584556759047989482826\
+24309162973430871164552649113514806220832637521399
+
+-33993701617495591491176844355:\
+3438065097398894672826284379125235190693300918673662774192379185\
+002391232383325160416036963599856704698280:\
+-343806509739889467282628437912523519069330091867366277419237918\
+5002391232383359154117654459191347881542635
+
+26876428790838270949718735111909136008255051776703:\
+-178112811296681037328619200883114927554699563526876724185996760\
+9117529616872536681035700534316457543887601645022:\
+1781128112966810373286192008831149275546995635268767241859967635\
+993958407710807630754435646225593552142653421725
+
+2059771092932179758019770618974659367350250375647433386639519387\
+69317693429941871882153770641334267205446421916220398066553188:\
+3342500267594994347156312297990633112620923791590960237694328174\
+171473763026:\
+2059771092932179758019770618974659367350250375647399961636843437\
+74970537117643881249041149717542676245208727588046226592790162
+
+5545520403000578843599072515870982842927227412121917598877293331\
+575380404618111609:\
+5991287327241003718821424770352575362437680738923552868139860461\
+945460339860477495902:\
+-598574180683800313997782569783670437959475351151143095054098316\
+8613884959455859384293
+
+248039029608125071340:\
+3664608673:\
+248039029604460462667
+
+15425705711415937103627:\
+-143550406551774570344004527686898291075408140547412300376755421\
+1132837427846963435621523810229738262235546179779885824:\
+1435504065517745703440045276868982910754081405474123003767554211\
+132837427846963435621523810229753687941257595716989451
+
+5088284720510864560728156892268365268867173823603073291434760082\
+1086:\
+12176160963158:\
+5088284720510864560728156892268365268867173823603073290217143985\
+7928
+
+-354265185659858189476700478770330228855421724619735662285097710\
+5341631254320181588119095376220762923216041205830017303882425678\
+3171761132:\
+-486486260736646884318469435312383053458853801109381241820880813\
+5799:\
+-354265185659858189476700478770330228855421724619735662285097710\
+5341630767833920851472211057751327610832987746976216194501183857\
+4363625333
+
+-142859621471226831038214482817138481252017914160812187001355640\
+2879770424002218157546599921571184:\
+-4054101:\
+-142859621471226831038214482817138481252017914160812187001355640\
+2879770424002218157546599917517083
+
+-200931:\
+-445588024601304957594828329131607177911517867255705194754496076\
+5970517168228311149083493083504573514296684748300915751495017756\
+5952218520297258834187372:\
+4455880246013049575948283291316071779115178672557051947544960765\
+9705171682283111490834930835045735142966847483009157514950177565\
+952218520297258833986441
+
+105704314890799915321259:\
+8279235459450764155749124384991698144145630668774941008316577611\
+9049069747385436947778487411878749535140554980332961534712093812\
+3226038208:\
+-827923545945076415574912438499169814414563066877494100831657761\
+1904906974738543694777848741187874953514055498033295096428060473\
+23310716949
+
+1448979433940064018828919290452280235308901982649341:\
+303926827425887072291878308433008512899006711759770318009:\
+-303925378446453132227859479513718060618771402857787668668
+
+-243237595290235750457450892290434789864:\
+1981770207633427640298127306741732109846753330094746386538370200\
+5126562800253466403934608765512316565811954342319565128573969:\
+-198177020763342764029812730674173210984675333009474638653837020\
+05126562800253466403934852003107606801562411793211855563363833
+
+294037338365659932242802023634:\
+4401245995535867764294876849802142926077599828776505639975554254\
+356763769548465:\
+-440124599553586776429487684980214292607759982877621160263718859\
+4424520967524831
+
+7303853946195223307036710881687367004566538357189824031021831088\
+365362:\
+119286025999378935715794641163321741:\
+7303853946195223307036710881687366885280512357810888315227189925\
+043621
+
+5711673553432872356876026107141104160674262893635054129088049406\
+96550592413192300554016875:\
+15872188842802631759540597:\
+5711673553432872356876026107141104160674262893635054129088049406\
+80678403570389668794476278
+
+1002240129784524388754179399598974973256811336031329881209395070\
+412702275169416754240:\
+5942948247886059134314539354042003351647830595287234900671578947\
+7946474753657206800070515207967709079933420746952:\
+-594294824788605913431453935394177933866937815641181696071168145\
+04689663417625876918861120137555006804764003992712
+
+1370431648825444838359719050380239722263203134555431526491525074\
+601463042144798545817957389:\
+3473869878:\
+1370431648825444838359719050380239722263203134555431526491525074\
+601463042144798542344087511
+
+8548280229254726209:\
+3306612503526990498184932043401689273494314593558214198996828084\
+6973981913056248918:\
+-330661250352699049818493204340168927349431459355821419899682808\
+38425701683801522709
+
+-190235588326875064895081507959663321759901299630299289585841701\
+1175963029327693964733408210016910253836443785984639809506517193\
+6899503:\
+2489927112752354534228346876280965340763863196622012469575197689\
+4193103779443050843040771191227522843088079031762445684377195650\
+493065096847292797:\
+-248992711275425689011161562692991615584345982983961148257150068\
+2315168794955481047333404813087485692518824813430081012223704204\
+8588130268784192300
+
+-180035357552270638928830562379719669053087020435672292804206122\
+8497437075035917720399302198953687023:\
+-118756682615304660537085387309407764121711064830726245327571774\
+71384128016458332544642788404765469924496127460164:\
+1187566826152866570013301602455148810654730928638209366255282074\
+8456085955229835107567752487045070622297173773141
+
+-29861551039945217879:\
+1113473025916855642353456146647542930581669082348409639697282960\
+8778892265003199963808382325823762328728689476247937892128298859\
+34:\
+-111347302591685564235345614664754293058166908234840963969728296\
+0877889226500319996380838232582376232872868947654655340252775103\
+813
+
+5655329636567611538382182775649579176587072976497579206763033016\
+55328103665512287797108510139837643506491641987188791892506290:\
+-2188105671531473889939411772533707:\
+5655329636567611538382182775649579176587072976497579206763033016\
+55328103665512287797108510142025749178023115877128203665039997
+
+-349535960680522202843083381184496349093812380954435872337802226:\
+-1829600726218222026679938:\
+-349535960680522202843083381184496349091982780228217650311122288\
+
+-1:-6726974989587128275:6726974989587128274
+
+-107142709838121196902389095205618516687047338619382145236348309\
+762148611647954748824:42484103615491:\
+-107142709838121196902389095205618516687047338619382145236348309\
+762148654132058364315
+
+-905466304300857697648396075281161213818488784945743608120275996\
+40018921358040178215575723:\
+-118922408531468986902800063237122125617455464103913195171141030\
+774109638861272017660698580914239435114280434761425243:\
+1189224085314689869028000631465754951873696943390735876430249093\
+92260760366697656848670981274220513756240256545849520
+
+-554504466708242712880172641672765736000158843011357818285065757\
+3063241939882570324573086267287272360432363387213743735507218270\
+373633222520429:\
+-151423255459028627628896755237194376177115:\
+-554504466708242712880172641672765736000158843011357818285065757\
+3063241939882570324573086267287272360280940131754715107878321515\
+136438846343314
+
+-5247636471953421659649611318164848102069:\
+-4024324110573096565232590473170599175885004:\
+4019076474101143143572940861852434327782935
+
+3941289260601504332248485425387937172318645783859022479504017847\
+2832:\
+-503832132195745214503468781543289068482546657912347492184846539\
+3400312:\
+5077734214563467188357172669686770056548653036962065146643505571\
+873144
+
+-559794145880092270356836245052087667531874697277996402772042742\
+07843317583292736333912783829528270272642583004969175230274821:\
+-109633110576212669339535976775635762395927171313557427036242111\
+4760163985793453669084013340255712657141281083080320737794421813\
+69365924213118258269679:\
+1096331105762126693395359207962211743867001356299329218274753582\
+8854667077970508970412712618225368242139177439524824425117190872\
+6782919243943027994858
+
+-387523538981733893474792162857729999063252864213028668543507370\
+50533204094183249691110:\
+2428819407377764342156426895396654728835493564788997075896393065\
+230009911546390816091652653701035085361:\
+-242881940737776438090878079357004407631470985056199698222167948\
+6532876765897127866624856747884284776471
+
+-2784579005241382005249492720344:\
+-164204542616919252351131740123094674:\
+164201758037914010969126490630374330
+
+2009488574208715447478080609723750390524012808225058048517328681\
+00:\
+-795957177479360455258269298038670876462147576765875895105714:\
+2009496533780490241082633192416730777232777429700825707276279738\
+14
+
+217570540819:\
+1219550835977204209833842821666933073941855304313684768349807483\
+02158718406063500763434561937200696970170700:\
+-121955083597720420983384282166693307394185530431368476834980748\
+302158718406063500763434561937200479399629881
+
+2335319252198456765380587281374076367944:\
+-4500271:\
+2335319252198456765380587281374080868215
+
+-393694614027544181700073367147249369966344727230221941008713805\
+434207925307052598:\
+-153972676737062409261153899615588515236137907791841623991260363\
+8406802955653131579724891681323455217806580074596028231257978067\
+70:\
+1539726767370624092611538996155885152361379077914479293772328196\
+5898022219816590860252282340511529983964929365416861520049075417\
+2
+
+114832549702862263167:\
+1292186490722995955874527641883028787538667360089228102228659716\
+5773569473039953984775959232814911435097412913078625:\
+-129218649072299595587452764188302878753866736008922810222865971\
+65773569473039953984775959232814796602547710050815458
+
+6489502346837936889305337487724547956628371915228387374094443896\
+2663621059310651530729834259117675802940765940789328350084947778\
+66083:\
+1099205476533612407829257935144627350486541654788267826664706620\
+630745291371323154513322608446957760026881954001581:\
+6489502346837936888206132011190935548799113980083760023607902241\
+4780942792663585324422381345404444257807539856319750749816128238\
+64502
+
+1699911441239587542538013131736629773378508702733583789516405216\
+01077152994474340806917796870911557233689087716056557:\
+-15409167:\
+1699911441239587542538013131736629773378508702733583789516405216\
+01077152994474340806917796870911557233689087731465724
+
+[Multiplication]
+0:0:0
+0:1:0
+1:0:0
+1:-1:-1
+-1:1:-1
+-1:-1:1
+
+-0:5:0
+5:-0:0
+-5:-0:0
+-0:-5:0
+
+4294967296:4294967295:18446744069414584320
+
+# Tests on sign handling and linear mul
+15928512:20395958369873946873946873498674938762987:\
+324877267646037601269025261886125746185503585344
+
+-15928512:20395958369873946873946873498674938762987:\
+-324877267646037601269025261886125746185503585344
+
+15928512:-20395958369873946873946873498674938762987:\
+-324877267646037601269025261886125746185503585344
+
+-15928512:-20395958369873946873946873498674938762987:\
+324877267646037601269025261886125746185503585344
+
+20395958369873946873946873498674938762987:15928512:\
+324877267646037601269025261886125746185503585344
+
+-20395958369873946873946873498674938762987:15928512:\
+-324877267646037601269025261886125746185503585344
+
+20395958369873946873946873498674938762987:-15928512:\
+-324877267646037601269025261886125746185503585344
+
+-20395958369873946873946873498674938762987:-15928512:\
+324877267646037601269025261886125746185503585344
+
+# Some tests for comba4
+340282366920938463444927863358058067579:\
+340282366920938463463374325956791500548:\
+11579208923731619541729378749232972134965448161202875719419539386122\
+8599533292
+
+340282366920938463463374607431768211455:\
+170141183460469231731687303715884105728:\
+57896044618658097711785492504343953926464851149359812787997104700240\
+680714240
+
+170141183460469231731687303715884697989:\
+255211775190703847597530955573823923340:\
+43422033463993573283839119378257736288536818090295526758568867574118\
+988163260
+
+297747071055821155530452781502797180927:\
+170141183460468022805867689086709264301:\
+50659039041325475543690391927479197318639397862390185708883012434796\
+959187027
+
+14601326942920387013816701832353570086:\
+24264364577528921915881695974297771845:\
+35429192025871610141024926748879851702222338457773664017578783702084\
+5028670
+
+146013269429203870138167018323535700860:\
+242643645775289219158816959742977718450:\
+35429192025871610141024926748879851702222338457773664017578783702084\
+502867000
+
+14601326942920387013816701832353570086:\
+242643645775289219158816959742977718450:\
+35429192025871610141024926748879851702222338457773664017578783702084\
+50286700
+
+146013269429203870138167018323535700860:\
+24264364577528921915881695974297771845:\
+35429192025871610141024926748879851702222338457773664017578783702084\
+50286700
+
+# This one triggered an internal error in the Karatsuba routines pre-1.5.1
+84464209123861960605955522581978104887597821936897255830387847065955\
+8899906113628751877643450961:\
+98736951733086678034646082696089517704609210537259909243889983275639\
+1381482452634765035178337262:\
+83397385394360978145497699467080869269009479990938738462835142243431\
+68965095514489024855209740810586369398339972616667107927536797156602\
+16305715905081674268833475056324309733116240691616008782
+
+# Bunch of random tests
+65391683115015322641882045438465620784076516421367563767344998373464\
+211053082289513139:\
+14690551177765498638640685224012137037306962019402563878738998365076\
+1050984890:\
+96063986740135661881270234408778414507112892608292678410994214305223\
+58175678639192181958429173932035325313118014847793404794351246657465\
+400198770681540554545469710
+
+1459164589787755339073553407089181299573246969:\
+4955710571301004201072727045590614350659542263:\
+72311973828792724517911747511119452992590495960205135450079047249531\
+44018123225390192150847
+
+3793974577745786452436021977649815501504431203:\
+2923303082707524288431115654231878223978230055:\
+11090937578838235312365399492067271746660860774658228109409108903923\
+640884753924587454406165
+
+101303541515453867913135264584014138619190734343846977507421629791:\
+36729564208551355196057918758932548366821793131129547653209379728:\
+37208349326455106997710672468998674976019345812041319483326955314975\
+51053692760634209776285429196890853333966465984989349956276848
+
+44895767034162990997987303986882660674722497505237491649296190658571\
+47197906588923414435381184370662953551284823547380833018151742197013\
+59303201872276975123159197578062043415450227149917179130060317248184\
+61724742069401359454784533576615919680949125073761586043027941204059\
+690093447093117249681641020785611986:\
+16696330082433130739210985196630214321753266552182432027772967004925\
+52487573743509832387533060375698218277114850491112782115377202073776\
+62825100480410971654051009789510884031202872930809935194297665183801\
+70736075740497155051843194560584923206479837331572253151736065154330\
+02181215131563438851752144164132708:\
+74959454570640520505374182178324326203870806497691482733643463532317\
+75442982425470080130736910895976501997512084030656668411349679742847\
+21690931312000529989464756559726986788294230843854125058213935382088\
+33087270201941766663613578038620398830216648062658181759195126557523\
+37555785758593956590738976578724612143644830770362020115624628734003\
+14793973405636949715493148568894826023486325367366577289710265462268\
+93078189596361078496041841642207401666400444087608269521582499768080\
+07159362627730642339199533209051979652974085966347840098279340160090\
+19527545420793815544675402025957881285966830564213200530247666994380\
+88
+
+31239732497959818638292779200667312725332984706050265703512759466859\
+84736003183931208107094690791134882086398364414246612787541657212152\
+296954515345861259:\
+44486010269203082806521604993132013139417339215738521529001729101974\
+65470989031351517957857643691181436996411785695418178273749379126148\
+152297344989418668:\
+13897310607113977660431400418487955410781290158603183057898927941454\
+42790371799023389229350908578189623154651948470463734628718228022175\
+37160459735416212605027206307627525795256098590275806474422724678539\
+64782315844000916960349331847619603498272594899577643345409426860228\
+282896290162148120168283702192583012
+
+91271582:\
+1044096341139516502862794205655492738851558322471722173871372437\
+43310942332:\
+952963248162153539313947560906101692644945912572602330737192268\
+7571591624552409224
+
+-91271582:\
+1044096341139516502862794205655492738851558322471722173871372437\
+43310942332:\
+-952963248162153539313947560906101692644945912572602330737192268\
+7571591624552409224
+
+91271582:\
+-1044096341139516502862794205655492738851558322471722173871372437\
+43310942332:\
+-952963248162153539313947560906101692644945912572602330737192268\
+7571591624552409224
+
+-91271582:\
+-1044096341139516502862794205655492738851558322471722173871372437\
+43310942332:\
+952963248162153539313947560906101692644945912572602330737192268\
+7571591624552409224
+
+-9007685545468534598743641658049346286545924671394080257:\
+2708960019652616340610787776914583117699836940876415749938089814\
+6081690884713840035653793589401490015282276:\
+-244014600122770296285710957465763428914667734328300934010213909\
+4856883353826536741655516010662407431799548978798414309377210905\
+45677125226465989158836569253624932
+
+428475864:\
+1642909320501970182957064144199510240834448195404018829560344234\
+44879791407290995292738391711524351126135935031044584272585059146:\
+7039469905757345878447661340893057388183882714889777970681372359\
+9286724999378785107476015314565835105810467743874695068716694731\
+073452144
+
+3804585298456788532803090036944486:\
+9742592765295469751314273699067197683737589672961737725951028020\
+8013084557451228262241241203602290304633025697300826898557186337\
+686135242:\
+3706652520369461349681131925078860959899355051485269139180490532\
+0467536020217182138330427311026318308608257076867490449833762996\
+8681057630927906028048393947534475842175612
+
+-35149344750729324695898480464299390828429941822615:\
+1752615203067497391770113249494248437526672507748487522889401580\
+803582387921659886646983402010731854517398777968222841997058767:\
+-616032759879889488930577794740723910260183908336496340745761376\
+2386195653397211971686493794958963315038864032857733526167220510\
+1088470032335610958791871921057479688753244615705
+
+2224887148112689653000916580023252657898661078193469990759133236\
+362617772742210818665763748892926451655031017362736825860:\
+-2254472752938568904593125981795197834529:\
+-501594745378325694157035263090451802038729306146676277613732491\
+0318865702652093235942446178330845500337957245272966813848791221\
+008304843258214793080794968119940
+
+-326328701700361893997973482656600190641887240518503116265346556\
+55295515493003511016396059566561:\
+-21680483:\
+7074963869626767136670866125187215271008195405978317997637869508\
+45488283622299239531287490699813128963
+
+4389513377810870521262475775128351860157070070803223156864617016\
+76781196153736168934878334587194620411888:\
+1591402338122279449286758479905480147444383058415555680119818315\
+:\
+6985481852667243947827954917503754523391596798272663056116832798\
+8639257425760121941859610354487659319836581325691828420744517855\
+7475650610301655551351877918657026128720
+
+-5742879080477972131875:-117203:\
+673082656869259767772145625
+
+-41663152776865616597841653055290004804009193:\
+5835026797641751552624640633869101411165325469966866477145:\
+-243105612927253227498125135247022492715711849036333775420426222\
+096834839368617968764219011608104393985
+
+4173221:-226716880742:-946139647767009982
+
+-2:-419149616949225277707956479498985786267693664978807:\
+838299233898450555415912958997971572535387329957614
+
+-7465837654969091645574504830799010297689933581098938996:\
+-202766795624052324242807175739440132217946363911505883055059139\
+6802793334274781900133686867487904621446567316359570842284699541\
+23774859572282855983153:\
+1513823977947471878037349023375096499530047411943626417913495002\
+9266163268789802231784935230530990513196596039364219349962480236\
+2882318096853516252518151818670572226535777283574688903592768015\
+9878750734388
+
+3279753735679960497081857312:\
+-120409079507914667933587089469886612743428895521786295640815348\
+9755449324053336110735728979481112654778080841040146337772577107\
+9932:\
+-394912128325868511771837525267263805962903118191080245346895278\
+2101319174909498798792301813784053942666817514010081546325334905\
+4670131212205861739934570662784
+
+4087017444924453990694625061188553846924665921421375573052029701\
+043709060984050262732827338392612774866740696110490073121:\
+3201354694306000008850909268274836475189060544721638298393454399\
+7010152870984867537367271090975150700374414635283625090662581086\
+8464508777654674:\
+1308399248301941463281797376424136020032561422146839113205163993\
+0095140051921364225220153999482159067766281848161373837807682105\
+9323529563247238502827327776282135135915279474234713191582888777\
+1511404594446973439104298431438185694530043948690757478249515261\
+147417554
+
+-179313367402631288677862721876578030440889951889929042528322527\
+8085266134713795430545312954193172520148465554221323897345577960\
+264434757547077538451:\
+-33744480794260115381826015778:\
+6050836482472199350882052360070598557985968830769735487227048700\
+2553193437634540742425617610465933528817398184780529934951394335\
+131691780368690568505046871430214639380927679878
+
+3180313045123330718974011402998828102633:\
+-395949120505103380356259679899143757026704962287504981215815665\
+380:\
+-125924215314748995932963128833366357734780900635789980947564937\
+2075592673896477843481666129302983824945540
+
+78394433139310872652394899769973779113149326061838893498:\
+-506317937717:\
+-396925077155891232039161994526220415197346559686986697686085602\
+64066
+
+6992304690095528264306828961300165566845561346363146805401105701\
+874655545973774463962200355744318214727682521358902:\
+-133619017321721689986267587295828262450483752049648766344634742\
+91685037600448415:\
+-934304881504630204568833073073911400366279420013023235031438382\
+2934806501904607000964107025275607243164225972618594885288739045\
+8800341193419320569112624739820560918330202201239246722530352040\
+330
+
+-279747165826180670739009508896477442612565831634509:\
+1001070223323787961662547493417138134890156942660669560843733241\
+4633638061364752177870909932683912027813180522891316:\
+-280046557767811427898723527174997897592562433513837063010261215\
+7561198396498373067781895023542952270308263849208412127831845586\
+715174925803969788307318868622842023844
+
+-152342817045381492055715979459468344477216937481934776490228525\
+31778605803188114866165739904589756975:\
+-2212835903613879894390831209261230372573882516571420663066:\
+3371096552157007383916181066595556807779212082757370662982557178\
+6303181325061530061815766217946054712863588378057790411549645679\
+971413325974723607366298385350
+
+-6494091656668836641394369738257289569440116499061905611026:\
+1112275782840317521987084233672591688806254182453409490318139855\
+2744964172429976273740793816660934415725201105937791700128767940\
+628761787374194934304:\
+-722322088125810479882613158179027486065378866899909715094586413\
+7631103621500568007359634288605863429230875357724233639767911115\
+2068815511020712301669909478881408853498125187530355741482610911\
+208923048035904
+
+1259075970239705718009909682383850925181613342972607875664276820\
+78026:\
+-318663749166949940724436640747496455489904112200179629829091439\
+2694468149048117282961429675979014117768927070124265356881836359\
+049426402836926666527884852:\
+-401221869162599711356856060105595763645472859526212982202400149\
+5177647664741074762667141421159412849263518723551697751858002053\
+7542672075930439535906386249755965714824568354356750289932068520\
+3787316784029369163777807462152
+
+2209196064019679034549708549203671427517764511470713969280084552\
+75125503453318134640933653347485145888239438775112197321859:\
+124322370280092642752:\
+2746524910923777881431201305680978264281158564024544236980377993\
+0636867162970792373254349391903852439413048040893096230035640839\
+019184047515968
+
+3082058203728546610432890576347992072668373530737159518097003484\
+3125203068791784796435721368414598060677372556794113220896530315\
+739449185455779351233:\
+-552090427013053554588518469958636851397777719282856055637956259\
+9226137:\
+-170157482977557810525065897604283065952067566293743982849411731\
+4057452157313429551986153220866320527892664570619020242072409661\
+0134368039649413644973455415575096896642638467426667020714240674\
+6077334196123944909716776921
+
+-750276999830609236437180125267494301299136351451377419221886149\
+8911986254315057380891206497595590249266192106292303419043717156\
+81219472681905129612:\
+4205355271908551:\
+-315518133662938357806548055254433388492269241826339016138263604\
+4618312099336135707474248962067915083570475597285597855437079628\
+850888491804577876260379972266112212
+
+-891480538085009501272618223055661423871310460861205688650041631\
+6753749755092306432442174291514301244257968406437077389253407330\
+1027650622821713282798669:\
+1823891225274156993815141670030683418070006803521364429343774264\
+50339496570500278332821206013754250417471107492:\
+-162596353091593275777884582766611115972439819895849702568800957\
+2367685595981932088283461337162038543383704114341129033405716497\
+0880798827330185683075499346562579922155299739327439570345879557\
+1617840239191503928488539315719099552021212289189718073280973406\
+93528148
+
+2124681182585249920847800665256356364758375848619965937406893722\
+55899052138313727858090571132568351249080019:\
+166675024913973810158544:\
+3541312890416478684229072496000778308444354108581194567659019593\
+9857314201986899403459218685673527418723464730927296640736532532\
+336
+
+1821270812209449323858422000208483696090755511739052940949819411\
+630382944845340233359392421633:\
+2128599324432790723202832411330404647604668944765842006449683716\
+50019:\
+3876755820478193889141631692181181045914395285524928078325690250\
+7363257606428059488182369494828732792776883797717522047063810333\
+3437096328016399478420072360461027
+
+-335011184237031303208123967960797661123087083840830392886248022\
+143119440501379:\
+-230989343999262588479185165706529031246884375719671837094628940\
+050182325:\
+7738401367932796012865144293474273194190542200590231371857014534\
+2578579884777706655220887725142189714172038628849075667359933189\
+054779585318363926175
+
+9198355732743233736216530024186914753135748283508055875656089812\
+193:\
+5265840759145098384429490542373787636725124845354712989635142593\
+95934459401303991397630:\
+4843707653459529764586164414557294257741706853681297466140467212\
+4298268715305496704100180574245676306441226124334746402488026433\
+56143901511622354285302590
+
+8714296327732867082392471731937188058841333771145620157971112718\
+8495045603213379592320067530490555856585188563018570084376435672\
+250185088374873:\
+4210349889307237465841484620878589644044295847340349009991385858\
+7615774626884639631625125100679586906920885988199787927848195684\
+62193938751049439136295957:\
+3669023657886054286232729883213956427553614823342184148988934625\
+8269564694550999939890817870432701814483867503196358666291080568\
+3307419798404926447543906006174853340917944983123029252530968474\
+2688682844881192340842766518335434033712938061191158275417587681\
+07991512024470998588265108393429890288461
+
+2981019:\
+4433245119720584557487584549690245587480169135936518003445698498\
+9177614053957189552768994493672410015:\
+1321558793354433725697708180673306621094454631744034296211369269\
+35453261869513407243405875196532834030505285
+
+3371841482115264548260749392909612923666167033836512042138667346\
+1110922005108438730679287361069225:\
+-1224839645782921647445211493292528894:\
+-412996512659022216647456819920862349778936230990047619735626685\
+9000246454258876625428723876322584511859911068016361053904468404\
+6687150
+
+-339290341643379646242121130133274175571738607527:\
+3271401581452035936363564486098243173858343994842704626634540604\
+0333753792872314861533886742557607640566446319092917014148799834\
+8498182361629081026057:\
+-110995496022355374018357458920157866276843573465657648989031507\
+1492983893793639677118229990155541637204519376994267321550212870\
+3024690173524970745190362239190804266551097416929422331908148558\
+3331039
+
+-302193108025958893465396831014238400181355654244499365872812914\
+0671578942520441667218976086488594667623103779245243552871642908\
+5538517727995241:\
+2017851085218627867440914776334445037676170997318580940821659303\
+5046997219650546605682041506090881913886238203842281306969809595\
+246163485422064601589012:\
+-609780690975771196107607785560739006824539433569270870499177868\
+0127071341610096112489032765719159734331084718676312427284431166\
+3160752183891441001416955478885614399224358737795082762053960238\
+3642229098982445564368202356432336746046757695325766162758445391\
+517573101567916271503836326565773891892
+
+-35188123484838216734793425643059054080:\
+9000600267361446370368675857998:\
+-316714233645582443508665110125938608546684298371094101256326282\
+531840
+
+-287546392987328273673797823271747266125547785306672698267720774\
+608232552065:-724:\
+2081835885228256701398296240487450206748965965620310335458298408\
+16360367695060
+
+7239719440345013275638025455463886572537307213436218405718641390\
+921197615256801869733473418374:\
+1273855558831670011845427584052189147328498974982056877978612327\
+370857472534105245496452412950690926717874:\
+9222356853465202151464594272999727525831895475287638674380433334\
+6933374970835844231896759667044442575039030759210684473734626375\
+4867082551600245844507805177238750672856996150996602083141097106\
+5816876
+
+-467193764317015751447832154618223252689085556761857235622959651\
+6527745:\
+4062614168720459964554950353412675872692580185950353528672485067\
+66348747462819:\
+-189802800645215543819126042173342480893460145936335827236015901\
+5836446083789360925533289958276050415814781716398053517857780132\
+893397801668369413155
+
+-256291521346916076469577753590332243088939322304016068224382551\
+5025546499325406138:\
+-605053480861014149406513375530972230393655979785947325614347032\
+55672033601321733124376224905086861012031956149097:\
+1550700771061164855884803447589885127420417575088485989466750817\
+5220547092689946197222125349076097067231864772732377382975294424\
+7005994565440548405623573916996459703805738162154040744466006957\
+386
+
+37657585687987148872355696565539718:\
+-1434800894234388160687:\
+-54031137619832058507887448613713814837731429449464666266
+
+4393856668836163872660314169038850961070596126492582636740923958\
+869429568049592915508:\
+-725654263195468754856026662040358630736857297829750596111795962\
+7542041685201743870533093436197634453:\
+-318842082361080325483580016771866191199973311649234286812044253\
+9591641099237099919800666371105550379907533870255064162462208188\
+3994207992073068621770789270796474452792924978217098797124
+
+-22262682191673391309862211106958012450603677337242458360760:\
+220733215635032249425562508910063071532478728405839033930940264210:\
+-491411342882883504420371271016231681619217410641501118113820080\
+3099803240779721785281408106422401055283687004275837896399600
+
+-1943809061953917342683052893090:\
+7700827546161027851150293971073751401383411867756623153657156490\
+3719544057834222201379883202137441380031452353172493763083243:\
+-149689383687721546514336832201365455374120959277626078690972108\
+3971845846592875060793450410610935237925773161603531529842259112\
+43685728191984096169649490870
+
+3786170367178724834730573252874138148565139634940161475730134462\
+072806346795721773969696184:\
+5642009735645474144794852846572624514752624565190901861011302937\
+5113755663421195546:\
+2136161007243476508223846179651669079978058344237194176489154392\
+7622668375501304536598877419397709190638503067245194075783305398\
+2326877049744197485569753314370744763673996464
+
+13489797398057489738508057443:\
+-39829491566872094526554950598431919339453350924955014031891083289:\
+-537291771704743910798219370322043426391226290103531988511540464\
+278547553363892492512309370027
+
+-323325112374943657482631147177688351925959386858544487312506089\
+86289604167358883842577746321363893167908786:\
+-246925431746938028131175064627088867042153744157154625487424933\
+24630571161151476958595194:\
+7983719296781021810724607567340308787943618592037051108694438338\
+2489270621359904712938918152105643713875728369108646194020367483\
+4484438934808794593359943127130153265367987222230213154933289974\
+484
+
+-435100258456539648627052287294649432161393329378094060187883773\
+2690708495675481854054541928447945875268:\
+-10155417715410577307402999881053155099930501238885853034128275227:\
+4418624872709263597834477604499556163338660202529113122166495103\
+6300436212506625541915615934966052700868562630468721925914800339\
+297995368984918582710621377945716385836
+
+# comba8 tests (256x256->512)
+11579208923731619541729388327330122708943419524243289762333678181937\
+5385575424:\
+74179307167655687693225162271190690968501083926425986337482366849894\
+604086426:\
+85893769551194762664489787067237470111583081643887491027483108939248\
+54152414995879834924747381994424629165311199542893443807287227310529\
+677629685837594624
+
+11574114654373435432769681547953871289980961721498085841658839565237\
+8326940031:\
+10711660777805634592035489333768778748163480146501669697332609614056\
+735426801:\
+12397798998107734697368913960056304565756856899698066529320990905885\
+80174831683647898327881664370985256756518936891247178025618131778049\
+267698975117170831
+
+27006267526871349343129256945225699676622244016828866963870625652221\
+609619338:\
+10706691322561929820710026337093404691680917641214496572907959829962\
+995350055:\
+28914777018473950489193423936996699498718323255670979720398132582868\
+12326099575727022500582226148289338093647474428048875439902371078972\
+17011952607363590
+
+# Karatsuba tests (512x512->1024)
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243025426876941405973284\
+973216824503042048:\
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243025426876941405973284\
+973216824503042048:\
+44942328371557897693232629769725618340449424473557664318357520289433\
+16895137524078317711933060188400528002846996784833941469744220360415\
+56232118576598685310944419733562163713190755549003115235298632707380\
+21251442209537670585615720368478277635206809290837627671146574559986\
+811484619929076208839082406056034304
+
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243025426876941405973284\
+973216824503042048:\
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243025426876941405973284\
+973216824503042049:\
+44942328371557897693232629769725618340449424473557664318357520289433\
+16895137524078317711933060188400528002846996784833941469744220360415\
+56232118576598685377983459383275149211060880540032345872695461810342\
+17940303990259531467630757141966678572355892742551472687075667803012\
+238361561335049493812299230559076352
+
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149085058651889274919368784987519218104008495487\
+966999617338343424:\
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149085058651889274919368784987519218104008495487\
+966999617338343423:\
+44942328371557897693232629769725618340449424473557664318357520289433\
+16895137524078317711933062342952193277060785350743397497444921769834\
+74555755777883734829695075352889186645794406339299840443362841695908\
+49124479353346416074683250011190629511478487550142982175186156043821\
+992372090244262099992413871225700352
+
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+13407807929942597099574024998205846127479365820592393377723561443721\
+76403007354697680187429816690342769003185818648605085375388281194656\
+9946433649006084095:\
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474097562152033539671286128252223189553839160721441767\
+29825032171526323881440273437995950679223090335649513062086992526784\
+5538430714092411695463462326211969025
+
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243365709243862344436748\
+347824256271253504:\
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243365709243862344436748\
+347824256271253504:\
+44942328371557897693232629769725618340449424473557664318357520289433\
+16895137524078317711933060188400528002846996785290185531506439882279\
+67948175579511934243229492219161469505115934541754787322072497766508\
+32568813609316312895189314891581055577244380152406865341154204627445\
+048144934853380616505964511432278016
+
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243365709243862344436748\
+347824256271253504:\
+67039039649712985497870124991029230637396829102961966888617807218608\
+82015036773488400937149083451713845015929093243025426876941405973303\
+419960898212593664:\
+44942328371557897693232629769725618340449424473557664318357520289433\
+16895137524078317711933060188400528002846996785062063500625330121359\
+98742154443577980079599561074597766784810090551438150849000845701430\
+39463393843012149940933139094628420823280505085783531419710269806521\
+710678242326571370194267352288198656
+
+13407807929942597099574024998205846127479365820592393377723561443372\
+67729797885965581514188847955651931542202341709841678538338597448558\
+6698740166243034228:\
+13407807929942597099574024998205846127479365820592393377723557015178\
+15690541073572989474743035547506906776301480077261237516040494971968\
+7212579269664735026:\
+17976931348623159077293051907890247336179769789423065727343002177599\
+00942480367760499251857295455939596154105772404450931317906536826768\
+15455762278256937871060873932808316066099592555454681197347421682785\
+09568862593066461743520871555375522976812396705343420538862100685795\
+3308142564518141627105027011868469928
+
+13407807929942597099574024998205846127479365820592393377723557015178\
+15690541073572989474743035547506906776301480077261237516040494971968\
+7212579269664735026:\
+13407807929942597099574024998205846127479365820592393377723561443372\
+67729797885965581514188847955651931542202341709841678538338597448558\
+6698740166243034228:\
+17976931348623159077293051907890247336179769789423065727343002177599\
+00942480367760499251857295455939596154105772404450931317906536826768\
+15455762278256937871060873932808316066099592555454681197347421682785\
+09568862593066461743520871555375522976812396705343420538862100685795\
+3308142564518141627105027011868469928
+
+# 1024x1024->2048
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474137785575823367462584850327217807092221598818903544\
+47838349239959440410649295502088991241512540406677820071644448472599\
+8099692362528251405302763273230221311:\
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474124377767893424865485276302219601246094119453082952\
+08500576883815068234246288158970519977814343258692149569327420609321\
+7230604120280344292940337537353777151:\
+32317006071311007300714876688669951960444102669715484032130345427524\
+65513886789089319720141152291346368871796092189801949411955915049092\
+10950881523864482855309433042883335846718668037787037650188893055840\
+73018927951831283900011347985854627812829075980481789955530757008122\
+88824849145421420410206954413439564292684600051414432901225421532791\
+01381942730678481306279979329106412319570512109276383150572147028830\
+25199880085119057947572011024091985929007350883874353448844224836795\
+78442377318748543006187648103374862164234771293283689764786919194438\
+37888284136626985706746129572759980426766233612587290367814732695050\
+64961
+
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009631327084773224075360211201138798713933576587897688144166\
+22492847430639474124377767893424865485276302219601246094119453082952\
+08500576883815068234246288147391311054082723716335051068458629823994\
+7245938479716304835356329624224137247:\
+10112023883600526980977341698188264126601120506550474471630442065122\
+46301405942917621485184938542390118800640574276587636830692449581093\
+50152226679734704194962494440051486835467919998525700927942192359160\
+54781574497145975881763537082907612467921532090438466226007979275997\
+0325840394840421469887935413626077183:\
+18178315915112441606652118137376847977749807751714959768073319302982\
+61851561318862742342579398163882332490385301856763596544225202215114\
+31159870857173771592553548685191068103016094862345941793100727824215\
+91038007155695622986473612841033928065392845889702175791770421586624\
+26143899184951734174822450721084185903177062211837438496534372480202\
+97467411486790074725866007726424039330919514310082034160544731735015\
+05505148992020823080165429348056649053453259548580079987024817945821\
+06278219961860441688154154020423122651667491374047530445279534822367\
+96606089062121158502205590789299321244993290459201196063373244192071\
+35201
+
+17976931348623159077293051907890247336179769789423065727343008115773\
+26758055009616165775278099964665396948321782087417396060386782903823\
+07012341545824090641587839835926419363551226096078071585202389405050\
+15136893796472153753067084907045685619026471680211462175364329863209\
+0971267582066228875273648785630167039:\
+16853373139334211634962236163647106877668534177584124119384070108537\
+43835676571529369141974897570650198001067623794312728051154082635155\
+83587044466224506991604157400085811392446533330876168213236987265267\
+57969290828576626469605895138179354113202553484064110376679965459995\
+054306732473403578314655902271012864:\
+30297193191854069344420196895628079962916346252858266280122198838304\
+36419268864745685317012104530668242911371513575805609806190451951607\
+10557715881476395538121318622342054920551385626039497775648111929192\
+11010149235353314669473560070738635821344900819492979642122564308821\
+93832836355009007808239907501987022158846860226885245037291654118972\
+21789040347542992939815493420694907963244430325400081905612531817013\
+53434121697017777687388707760265950247661467236793723639977817395453\
+05333658727917987431471148302830409557728284992844256725143219605511\
+19105089461515317003555642348174884134868178964134073119096779203778\
+9696
+
+# a1 = random 512 bit integer
+# b1 = (17*a1) mod 2^512
+# a = (a1 * 2^512) + a1
+# b = (b1 * 2^512) + b1
+17930121528120518743193890185292405362795914617726312913105692310966\
+79834089760159821608571760102261884739604751290203318392915809389705\
+18533152042879507565469760620770664602498091326659618430896499562864\
+33097556186753511259807783990999180942484334496111552855551238437298\
+5931442517394084353378720570213259961:\
+17181164400078273397607302623726933788654231870578267885308639434063\
+29050645768615733989348336532688661355059992510519187273205749318328\
+55178025838720042408416717379221896884862317068300037779659390111981\
+97244867335458644846343599813562216158033039927051277398059877872479\
+1239444995247411522594037321941878345:\
+30806036568802130707161344222425760549041581576622091565254201628592\
+14385467809668014385184785152271193843047948236592285206889142604429\
+75839733409984928244101830825691058271214860952936075111998155431716\
+66320122704699248615782786577874030694743967942269571299270175479177\
+49821546067026790701696727687868585663474591471567191830596615534450\
+88805296433793120856742255208087463783715754626092601017174650889346\
+66486074650833697034162201049220647206717383818466106882937622653918\
+76822429098414628373727606690842310063586870064304131814649299854186\
+12692628024925259230119912648154125622594020560204924767989260701214\
+44545
+
+# 4096x4096->8192
+46230924351836247700632620916046176424079105466354534064042561034208\
+87179012808190823424753309565308557946849439937602914646826017759588\
+34308955397574010098112170264341488598373518621050984822173335661543\
+05503155484221582314725443772226962279179435429752927046418702379683\
+85046488722729558633796252405133615796333361764094300077585699651413\
+87522520295445886581348613967739679507144536630498779984858498466466\
+53949495585121328172175753765616536867610443894070462179968529055982\
+76558996753670646519698363689763792814553110716478538561711411517385\
+25392668340231371551312445292385216029091676115617060930552232679124\
+82696223439453451825724430911002048100764625928528148630937654751536\
+06304398468385126736497735857773379804983839043683211519322520305495\
+88047388177062785807692948814175519084337222913843071456581602029935\
+54683753460812611659451099340378672619627415242236591287093912255783\
+13140160231289453522976275483766396153309206695863277854402154450459\
+37546852895213179224578947936523539421852140479791200605839865108481\
+29541228564089187837510575385124529321309276742969232912010920107981\
+03957776659416089212281297890809164014975660550116306748020139153256\
+22848023511467181919573893647538869361729907908714966872881945389100\
+86101428:\
+54530990288249437719619266581633527950202167725686915722413802215908\
+13898808427693785305297340466057132347876044193194335670208491816947\
+45347065813804383143878587001488929429088856726119741100265880818083\
+08072469093027021085621909472228082331188302646328041787611120322548\
+39496025029182050271578730610401719162676648561607998168984589242763\
+61184308631479552158835170369552925804999967396481740557274002486324\
+19060734996166150772822594482483029608131347141723539465860333111879\
+99028176225288916692803103016047215834727819406429598388635703974625\
+46062134344556400079860063468483319482068487707023772004276424916600\
+70752394601181923057555584615258415106502514105268940487020754841912\
+85424335310397208518018385485167186844809177247714124187041081497708\
+96511319230068019588583992177882717832582994338933822583078086805742\
+83390233167682320436242724359199417834794808081825191377785708613777\
+86102596609226847851937748841875768625507263876321447582064560528748\
+35920609680394258473797857062463125872573573911021820161622994930998\
+20654635987081600595958107506315942531393518613570935900767436989518\
+52479980745679719049556332080920670567304319030704337342023640878866\
+09889825375285512294624431826722345023789066121979651546281497741903\
+392437648:\
+25210180868467768546757726362059843626852926905412382608676629170550\
+13500472614635251047265443464861022066815047034258382305517605789179\
+87828662358961696066164456254433404354134132444755460484661087112315\
+33092792254341786823634449794876609511305489030701548587221933119990\
+83152382137766693945997257582640307701836825909703642483047169261811\
+29415178374784201058252543144281486261236848516767550523665279551861\
+74465512384172617149107052187550658300617578084736260341723260747161\
+99876271562142167533309479325645255667176279131317552047451026692967\
+20839234037422676688042090117497405271103578405099807691583810119265\
+54336379063605406653618342419878681737223923065560012276952760198274\
+01935961653423534734281217002142980219703525915889622098752381243251\
+51337680928833690966007811584949672395686773570000393884061584225434\
+46095563213259068817841045213587660574716357554630835216272902060443\
+34556862089899310391156917797805143517814316196396914215338901147216\
+79277404380234128913536426196746405226500140030500544578565101666905\
+45355602687691883828602277709718492121846971571916556642975486330113\
+36222756064112088369190359637323581593192113210931211230367909305308\
+34626706120315368242528268242337577529275810260388371559227416421225\
+18288153930546296286935770867979820870699234878779491860155905073232\
+51502558862837164130223049756749662881084284616449485647823253076640\
+97817765026456231979422968578849627137552880186111486959114938973490\
+88961199014636207851962534069247724700485273408823799958467863418841\
+50462661461823344684758580652604422779162692518313890388399982545703\
+35206898267568862459046844795531325319249988156277069565297520226091\
+64600766297485223302985129710063725127737025349700933151412377658954\
+23709434501778907216692625235665266668930171909330255035266777372724\
+58877961350127654808072552639834541127026665379146043251830475968219\
+15018615283403488179263459581211497821758602281724174575392739616669\
+25703910463568680165861589391919447127830393426572990195899393637221\
+86477741974371802750413668808535147675421719142045765725335254381364\
+41785131009861024178374832421597792578801840696203626157231517656464\
+14052894526701810933176118179541201020906393719709492349877490392992\
+00696634018140352649412293680281970033556175696751860800582932013588\
+35349743517428143168973670929259662004881928288066741418602389631277\
+36600832956552929991925721216698487543280154312867126099744478225237\
+72707253967514116707979742986501040393426058104944823682176865543029\
+42410605893761344
+
+# Tests for the asymetric Karatsuba. Historically this code has had
+# more bugs in it. Getting good test cases can be hard for this stuff
+
+14092703816360934475287812379721584643540920654551533543420378905278\
+43263869087702953436962300677113653357118503684241080095903812797217\
+981771103880205148628392675409404139:\
+85196387648463903836201075338727419426772257423386800834159433024105\
+22722534550698330414221220484658429569965031071685565584585568273727\
+521831711430243837:\
+12006474573536728376030033121297441343323401321882664768043719554452\
+72355962084445501636044192472676171283378029237295859040510289867684\
+42082336586473179649397097120830906529744851914004493486594202273964\
+92849411579105282151504500626551480203959164076691081552725026900241\
+832342905034386191256909160400547992155689411647041343
+
+57586096570152913699974892898380567793532123114264532903689671329431\
+52103259504474008372078212980297151898765610906745757706580551032703\
+6019308994315074097345724415:\
+14396524142538228424993723224595141948383030778566133225922417832357\
+88025814876118502093019553245074287974691402726686439426645137758175\
+9004827248578768524336431105:\
+82903962954674429277182094016068528967498403743392611678986796248035\
+46708705089408694697316410864619322862709322416615890526565883322100\
+81247286886157264936638535413026388243763541729092783487919143933560\
+11669949922966041936103836718052579102251260556254458882685015932709\
+9748064577321171189330220691056136254107213091963928575
+
+# Got this one wrong in early versions of the asymetric Karatsuba code
+69328033643988284668153554428298153814569184083886776453465872993395\
+29710746972404168269687728407520676676052832464833364865313305188652\
+27796258747613771385136143521786728820782913230366107236761071531140\
+69858079626875179117509513890923817643832927518504150773412897517798\
+24069151513573630274310883822191771430575394116104021217164852793487\
+74039487132887730707079890109620203394040795732717864706534187311456\
+47616397480632810489298476433897092835849191354914181079718876936239\
+96759799034047278741267946259806379049845381337965241128934112089387\
+26387200493807084368512264417392541693498708056601725438254379619500\
+04878549999476514473638562844231061393907117784824855718620742441873\
+33707730767137725282689693949863277338600908221830652962675544003225\
+784824252054526036890965:\
+69328033643988284668153554428298153814569184083886776453465872993395\
+29710746972404168269687728407520676676052832464833364865313305188652\
+27796258747613771385136143521786728820782913230366107236761071531140\
+69858079626875179117509513890923817643832927518504150773412897517798\
+24069151513573630274310883822191771430575394116104021217164852793487\
+74039487132887730707079890109620203394040795732717864706534187311456\
+47616397480632810489298476433897092835849191354914181079718876936239\
+96759799034047278741267946259806379049845381337965241128934112089387\
+26387200493807084368512264417392541693498708056601725438254379619500\
+04878549999476514473638562844231061393907117784824855718620742441873\
+33707730767137725282689693949863277338600908221830652962675544003225\
+784824252054526036890965:\
+48063762489419715168951981307754794589808870758952639965091476616647\
+54056167932393419567481296681069246248216008267853889839320423981745\
+60479443107279226057663425943342008520701374986979347783572983701184\
+85422697584729139817700527441440371002219958422883649678565900879400\
+20025210106297773515746894906726443036026187076658079744151459354129\
+76880294234848336533442648147663722096199825871118396947178334215521\
+76943880892409643115274415151713386236948639022804530054018234460138\
+65934020545172727964007195157289495135921213561302426988267171336165\
+92297396800884174510773976233843978906677436838567701962214997325767\
+17494685809458185719292759364630203908885946118898336175097083972837\
+89342035200573700398720235821406614593531258231227043379738167751614\
+68684582976839207443768269161778663395778873870774323940683360928515\
+48027194465603770338336645857674917792255648723659298382428421752797\
+57375177034382470966583814365325881784225896969066012430257742547184\
+72418596829523189950619686978201887223055028706607853375875849336866\
+58034693741263352377027728101357005623322435070019152178347117503006\
+68898867912930645058149633650634442077017541758124699937775536013889\
+00090985949751232201541388041823183135436540422469067343022614303960\
+55855903221443598575395492738166423176780792097697804248465562838489\
+55947563036566122615600202990367217608222400507033340848053927107788\
+50110168698504066173013701126736282373942179302874896060705586003228\
+79037941627812442489494360833298836822298442280730034168111230609093\
+310545565906004082962175112065394876123298631225
+
+[Square]
+0:0
+
+-1:1
+
+1:1
+
+549755813888:302231454903657293676544
+
+18140671814051116644:329083973865108631122076757343293822736
+
+18446744073709551615:340282366920938463426481119284349108225
+
+85070591670813493966310340604280700927:\
+72370055672222822149686532165239924548184855554193955235705358728264\
+18659329
+
+85070591670813493966310340603475394559:\
+72370055672222822149686532163869766764144178225565969340654319581407\
+26804481
+
+85070591670813493970922026622708088831:\
+72370055672222822157532909328992644361925323993014681825303471075565\
+86946561
+
+85070591670813493980145398659562864639:\
+72370055672222822173225663656498083990682319746609654242487350548038\
+36600321
+
+340282366920938463463374607431768211455:\
+11579208923731619542357098500868790785258941993179868711253083479304\
+9593217025
+
+3138550867693340381917894711603833208069318394046068373092:\
+98505015490986198030697600250359034513838056601414221774853647899383\
+99716620339203600092485547982803495343709640464
+
+3291009114642412084309938365114701009965471749407831540748334692:\
+10830740992659433045228180406808920716548582445089016068317535718032\
+308295472658277178853031537853949474393196307576171250734864
+
+# These set off the bug in word3_muladd_2 with sizeof(word) == 1
+251232322172118783022840239225457019863:\
+63117679703995287066909540140557654581113950055128878944628202319505\
+176538769
+
+273689842353342519508740475928754711696:\
+74906129807397480797309133044676004424334564639782656684007505697520\
+079196416
+
+271302823667110475639266093952890097614:\
+73605222129747240032647628582852465568122948805929122728180342334818\
+448492996
+
+319387279021025860024422185475130973014:\
+10200823400045462544411223752203740218511249559589398235010527269723\
+0396244196
+
+293643199753680203052743123832843662352:\
+86226328761579733262787961688682814116999624225084316052032576511892\
+182171904
+
+# word3_muladd_2 bug with sizeof(word) == 2
+202324725318880963191371356135299852624:\
+40935294475360631472543732691759944656086403346062162368816126408076\
+119685376
+
+309321842385349400717946354447033364075:\
+95680002176666937035836738263162897574421497416350873907840493696211\
+500605625
+
+233489517300128090786970749707229607527:\
+54517354689046815002040771363970021549478312409815296261172173208794\
+455055729
+
+[LeftShift]
+2121258017766159160754962465958381577677890208124499494536189186\
+869637798499791383037162061664492554205374097:204:\
+5453968336700566799508983726051663849667997549076624612345231282\
+8439638899716201006845993775936915589934028192020733447985075402\
+867441526514914927633382250278301101719552
+
+9127815530925814339720645654057304030995143310324020188491605652\
+0167383202307739291645752386748299386607033417580789665740910548\
+485496057884342754125:116:\
+7583092465041842489806678334004575989684288504372713429243106807\
+3821340263788338036051275796540123856480834349684104861172576642\
+18512263948855799232636502228939840695954790558990336000
+
+2720447254558553014578566972012963115777446398846598038146885883\
+1866886314261120634838361392523025566783357944737665:164:\
+6361500986895495805616781332881685455158868774711923425935172754\
+6665493357037199343516238602124200135772591677608344475613159685\
+2488399997844504678061831690534256640
+
+2346814922039931311567833556790864002896525919808081028569793383\
+4008825609596357974972673276604:112:\
+1218535974727059175894407931694205043690238717758619344357411498\
+0976423842428997921600747804778709388243970226872640908420343398\
+4
+
+136766652934857914:106:\
+11095829099781028284216214312551702886842940522496
+
+-401051144733532769909045041716441134958154294462987253741112236\
+561026903932355958855274471955131:63:\
+-369904391368386363775763871932535866765470702774151965641848084\
+2144652587998489299622223077809753503943936440270848
+
+2620878467008554581948549874850974711547561914123735587938770041\
+8388598339275821514904454964587607270922729716663659446422771149\
+9620476383257:195:\
+1316121661879758521098806625253965626323323320500789427869263340\
+6367324456851018233189899650111735222276905756611447392283605658\
+6424209018483795579529997393099798973115070359293039187878410704\
+39858176
+
+4986386024639314608574963909430738820138995826850354329027683283\
+7084148930520285795218001501791951858649714264370213994065039723\
+183:24:\
+8365767539475510328001762170072394222505708301016699425463251243\
+0365357678350782716810417828388796339416772455162018414465188948\
+4421398528
+
+-455552309543147716127587827277903635248610246950391821050011180\
+4998378889619941436810075030388024035287640271262080871447338739:\
+87:\
+-704933054965487499017626788420861259932661059464379088499410099\
+2559199084336675766400427127749751321008643932765664940335284556\
+99667386383995835821064192
+
+1037757592587696398725288196824188929011363632075879222442626801\
+16359163984447531185310046467135652319371987503:95:\
+4110981359797486520990313529905064933484217701344426282406713957\
+3073026585644903347542613235747258250235327631427113860134353360\
+95122325504
+
+1078541466278039800083311:111:\
+2800053733577506391526406073538574747169164913752227708928
+
+-458929098580755:143:\
+-5117230445820379540747782782105603341274706553475212247040
+
+-122928855329072870073433015110819526943336867562196620340919010\
+07272608951275193:11:\
+-251758295713941237910390814946958391179953904767378678458202132\
+62894303132211595264
+
+2253797880121520663606973674330182144804901367932449178312384948\
+1031054670305841291542789729087450336886747413803342773383544037\
+2581272420142035100:211:\
+7417269366041670925252065169199359207792625796677651698479867559\
+0580700643261572311187905593603949279149066613049589728766147448\
+5040626948461011388280995781694782614846527093302465736147768556\
+526048195169484800
+
+6442142951860149863781434107200105215105005142361888584824558528\
+2484597164156116892847036815:107:\
+1045297456599241794709977613787275378715930460342137602357284620\
+3705135174457613106078796927549665575893358403516669173432320
+
+5097783526093860243839154243285093453167843731134916160503060680\
+6809190520533632436146045688586:126:\
+4336714610774466073591769540544761879648163769201204653675081413\
+2084346529112353622016096796405522770364375296300671020674092934\
+10304
+
+-331899363008322441533569955164860025843805741291332922663910367\
+2943065616917605415617171113991360901486760154578289560762927508\
+7724:91:\
+-821743020962630744101604179924332933222787625033777030204941339\
+2423604240087684356284281911697948345840642580768340681886419299\
+0501324963749459198616746852352
+
+-184253938912501307159324447512804721862709269931381112790263931\
+81321750494139191589459903767473167677816275893773523:152:\
+-105190403673940947755727602264308003613546006738759564870362217\
+0667469418523232027185126832293519850235443686300723583174147136\
+58107043639016550258714106195345408
+
+4027173611709683208685144938635076643642081573452904517803697826\
+5275420130:216:\
+4241108819962870257795832303288513204199186270237663098986852370\
+8839925819263809342179370062199525789246961806149451534207820475\
+33392199680
+
+1654910280148247058930466878701929681980555724947453908536393353\
+732583647848670616170583254506:78:\
+5001659417042237892080348861898586734617398707583112481824590338\
+23652150179951382510963323144882735068533089594507264
+
+-353256518864739539912727355980967022578755727546889874982122719\
+759:107:\
+-573191472861980058226433447553366186933814120008015485620963412\
+26306829015345625594865954588721152
+
+3358622889967376849369646308014887582255587127977426994425421674\
+4686208321633331897065809513496651:69:\
+1982581020522590603474492135975397792733918369926415317084561070\
+3822831264254057644126980676514200036423975856884416512
+
+-8326918561933317515897484042242279813635:222:\
+-561233200828572354853379214799650393202723352144809535912742619\
+21980589457786088539861748815344432096215040
+
+1738239605092625935802720509793:210:\
+2860281191896129448328585042777498571666530315075635885634512550\
+142285038644212151822720172032
+
+1541590531164046827151493969434074217996086405826244177284191842\
+623229626655598394491064824017724575585890968239654882203827:130:\
+2098304299069634414151232805637412871131277307615398366601971342\
+9665834217942888720462643703124214574302721592303513592056859315\
+13427518479162077139334989713768448
+
+1822414219485473007729455052579570934353421556802754634400780753\
+581487672806631709:25:\
+6115007400355837902569347395883763750593834759507216779268585854\
+2958784576028372828684288
+
+5336246625295048457347325312327723275413189882766845079019668950\
+23491709759645168524198853958247909:145:\
+2380045526144475863333782125314997581392105067362688736487270903\
+5095219526391819075074039117499741190364575496806391148745118026\
+089345253900288
+
+-276651306081170196285504936260680311592104354245874357656134941\
+6718897362629511494172851413903784541053958724076679151843367695\
+9748070409785949098743856:225:\
+-149170089146918319214991272148007797149650392266859882932532072\
+0896314266755406819672840795334582356690986796948912969229786129\
+8759392443252182124719967927140260518022196506128222178285661500\
+32303899305525355025417633792
+
+-103357876921000174182112715460846616262383449332882137139998255\
+68582685162004410585410474998733490779307256347656936844453628:\
+128:\
+-351708629986009787155639181729583046307639877673123732501848524\
+3559886115426724541117518475093181639785217728536729396711614403\
+275792414126622561825487435090362368
+
+1094708276267187017583512230031436979221999105657255772315062187\
+0590945418853726695999585645264076550:76:\
+8271381875782668577777728720058787519656348054693237381352477271\
+29815039067706300744940289871871309203285264026829638860800
+
+-815525457724752321603940535029563571154068567797107498491974746\
+2624523816971433695155984655769263875263814891:185:\
+-399932520776254684164524385851380762766645298639846935216904114\
+2896647055743804753583601279854374681737834012702515619494942793\
+50304095670986950350223830081561690112
+
+4052679849880044255138459864411550773099421944874654179650065311\
+7857061613513287290910396020606030441122363087181232793161493035:1:\
+8105359699760088510276919728823101546198843889749308359300130623\
+5714123227026574581820792041212060882244726174362465586322986070\
+
+-248399491197694456686506789360892375748400795979825040399299010\
+53517808438265883:176:\
+-237919445383638978127975473390525029152877274034190677596480116\
+8519869938343860007136898454280955008871656020990685920874468986\
+585088
+
+-341602794141123390057384653491582990307091266762526194256752907\
+742814:102:\
+-173213194813054140534683117609830955377834183581805190021073324\
+3591496880056169249935512491320672256
+
+-958393530005648757477093349096350288904499954214052393312348399\
+2770943667934610603880158622319612235433869275282625539708353046\
+09:167:\
+-179288795303756735253272048111864507295054051907270903858033299\
+1984105913251800521090082264035457471680922762784248326006303327\
+80357892372568802535086338017562314555143800752177152
+
+-244934270799654899396979330417224591920216069659327770883960842\
+308099872348715409398096:24:\
+-410931516700830297264139197394514709915731976734558842691872198\
+6944930107966825746000286580736
+
+-2106457461641547906609473458:69:\
+-1243433014305839647767580171740431469025056260096
+
+135142685675091:202:\
+8686636920585527698499063657324055240285043487766458873488405392\
+44004900864
+
+-116790541221558472322206451254911347381714818839018118383610841\
+510309754344586351337420036400717803838650415501291198800754587:74:\
+-220611094952357360270322465694065886169870282492555195903063877\
+7058528470895456709658637256734101042181231965942902938524566534\
+006236702950668894208
+
+-113662437497188191611046105180147670725123405622356749057822533\
+9374200354866981925638532649150827622554422704805900523233811186\
+7804339566343416115467056:164:\
+-265788541608259131511323286352380846617232004964000794820926894\
+1982659118064626109656559724002147778215968030048122363389101341\
+4916257633270717425007538758533769604203658211543099937688495500\
+8515178496
+
+3139835124875473212694109318074161136799592793072048253708819570\
+6031251397956934770541559259048189239569502903816890554914148616\
+8710074892985168204104697:95:\
+1243816837708147260845084661039007547826018395188591656306366764\
+7513402868999491043335036172230767347465042406686594960568733454\
+486595586019513727045751542829562936306306793756164096
+
+5599994070119518146348:199:\
+4499421759449900671784284327121118030698801585196299978528243915\
+527017858726887424
+
+10270683209834825258725306919273690176679518030925177258309490:43:\
+9034188491533697033850866046124648731048958323889347163636163337\
+5107153920
+
+4578000383070746273307:184:\
+1122522427702119950972128384343669227408405080033193267723578847\
+06832894656512
+
+4806080526717717017641435948049790217951184540837962383194474375\
+4177372178226:213:\
+6326741927653364567544399799665952033829979000600292660407440869\
+8862171634248299057579558184663298119372699195026451647955448240\
+7792959291392
+
+-213240753886670778938493896779297584390212374893239014196784169\
+31016786722016582:85:\
+-824935210136591658197356601203169660873055716952680926144487605\
+063939313393392322678258809253441593933824
+
+-187286407031666462047035483383441327248520717346072223723620843\
+4454125887374738735368124928725176429609366:134:\
+-407873676011864041904214443478531790285593140265704678916369737\
+8659007443902659865299628228125085923760625746613398039989747449\
+2137333668230201344
+
+8621689714197434562630867265841464865623072938828506100870809463\
+96744539349725331277869713700313427547966:97:\
+1366161267647991190642664883853673418069284183801958399635868396\
+0937205383180691314472971265906730508050012658612328503341173152\
+3633152
+
+16955933412697913917032678757506722466737685:229:\
+1462819393593898553961710324275156357656459346902684987437691843\
+5481519688706703310919911715271056730027164958720
+
+2180018258288311836232601230248111131649953969135839015779353659\
+8104321725586576274057148974991731503239472085567581116:165:\
+1019552081247881910408108587819850135603932052219933414781931958\
+7658929796456697439849089055853009742845594506749609005029155283\
+87206223717397886377023326519137153318912
+
+[RightShift]
+3163645694280286863843274284995813000413750703767888062060371447\
+2548769377833432476732199026703457620511:71:\
+1339856068247304299517035929669762064048406302964464795193542030\
+8616778680708128951
+
+-14453551017278988424486997167045:183:0
+
+-14453551017278988424486997167045:184:0
+
+-14453551017278988424486997167045:250:0
+
+-243110742861195501591733619507439366721710893401851315001032874\
+934976816617401149916967847829528780962:77:\
+-160877194558516235935268045675608004834374082748681492335699377\
+1554731869523279
+
+1578511491667772739870432690812184603408439934845400990951391424\
+2042606791815444346835351458430330984370157647950174636188696067\
+901582998887813:172:\
+2636868630877883693962671763727310843333678410156464570287439347\
+867714845687034115945072876
+
+-369990587551414900909444219626623817296602594145580698921004093\
+03886523992221862362854753622740275252526720452:175:\
+-772576394901327014846975657022405166419128733678436351046
+
+664523869708591456637358847652496607157050130461836524747531314:\
+191:211729
+
+-424946102426960838249158490450106473832054726611725352096551869\
+301633439915:132:-78050272313569003846694186065678698
+
+-2477488754280410161548750939069:92:-500
+
+3885576822798328723491155206700259517121985332303318810671479550\
+5721679465077987975131032494226814645578292798864088316633495241\
+72281732561:116:\
+4677092971402698635823599561404354384957452158155534044221842927\
+8654700322373721814974862542990905781201
+
+-7784136527805956:72:0
+
+173:199:0
+
+4615578569620677656625:149:0
+
+4905579994733063495470152932606524195238444602458194107223829134\
+6548096468622028014016518915362921381743841987304665341504653820\
+77:36:\
+7138558422932784735851095949483750439304923351240277562790767311\
+0236786987839191008266816665655527877597839669476765763
+
+6860659646513892651503913841872495917865372347379124495074404003\
+48669:86:\
+8867194763939375066201545129950170866662337
+
+4932993580763155556722299514:18:18817877123882887102975
+
+-278747767898647506540238310041925406724691634519605101611983422\
+6204966588409142854005261436295569885823506142825506136904961441\
+137712103262466261:104:\
+-137433260320539729826934608254525294966481185197904919592889909\
+661839883445042061361887992911622135941137977531125
+
+1882169262671501641122532021045100553271183358274828402533612516\
+4:215:0
+
+-113308045504297792964762442633165425691924733661899127245385800\
+0508491250659909229734510933018929528943605300925959716095482095\
+0781551497986883190460:29:\
+-211052681327420832523633619087125036291637893136402829075950756\
+7637583707757125105214325586369129883020381072398200102328289477\
+3001878518586
+
+57567025533800:64:0
+
+-132072785244069918116388563501248470774742728409639846537789812\
+5119402223003876981196535555849118422274367340745545:47:\
+-938433581467776307621794014588434654731534070106419040781914109\
+4019259860231421876594989980795833320
+
+332:218:0
+
+-559822315679298304410139625796782279674102061246050482023351416\
+534297836795811816038579409314284017985789979551604:185:\
+-11415659555585642743745444064957984965053472879394546525917
+
+-165370654266946240954843198912509990578949570887804349975976624\
+7848:193:-131725325
+
+-194216125550322203453264566553636693381698:190:0
+
+-574918037852237888178117788291362893480850545560575590351360319\
+3555180688115045992424767676514653030256481410814556185745502407\
+367635738697301:25:\
+-171338927105736103110944565621424583637967868316345092758941745\
+5659860577617599365837802790556744644122267189864682014508695127\
+77556053
+
+22512966965683176238772169284:210:0
+
+-571304627859240495908938310435848221105034147099897333911621990\
+2429210200375110530363596454364595974303366523715867605148466947\
+82:64:\
+-309704859338005592964733519326108195603366962254800737268694205\
+05469907491401631445860907279418326766038568169
+
+-309596777436591740355404153813541201302898762127036944631572788\
+15893302883997570045883151320905855931366:104:\
+-152642996313836176964502120620181580006920013080253805054740742\
+4297460034
+
+29089712758204609787443669188235835:57:201850430524318292
+
+3772893855139299527739062333307773429569483215869291954483303258\
+8826307095346005890226120725877767624562307811438348806708086825\
+272884:33:\
+4392226523649063342878434729422178852336345258948034553885580109\
+062873187398771509787314655943513804180816259635420144385202
+
+-107286131603440054982169113843212878238243177589333571934531:\
+220:0
+
+-171860798431436300064006491940938069877937918743982288348494291\
+9605122825021394820452085254301230580701:35:\
+-500180753970740770641733228522754710510890927235544334248681238\
+27185564005671616773239955489
+
+-736899297617589968040433744284158522983339306401749767611116884\
+1084063920382957413309258573768392475688901297388389668250828837:10:\
+-719628220329677703164486078402498557600917291407958757432731332\
+1371156172248981848934822825945695777039942673230849285401200
+
+6494520002849829489554410861273180035603713191696971145227421658\
+53859125361930352324226:199:808309944002185489853551692
+
+-8811428348398:35:-256
+
+-472961757341800595001320983673882525933533190954393100297169797\
+9931906653571844489680727773893833490556432129528242730860714016\
+19:32:\
+-110119990385556732071871166972881771142951490114068868639219970\
+906430544647663936244340794484453124239957708155928243204
+
+-950911712685005613285113124954832473131420819362306322439787774\
+9569705:103:-937671343067445278042307956226145570513
+
+-879814295274183624334539929331740552569451467718612745386330333\
+5306363907959342879342226672:194:\
+-350406259275000216456910916623341
+
+5510885178270303556262037168746873477241029300667748255749519664\
+7790961278402228092443936180348351958592120159109985931085584854\
+072:127:\
+3239007197543508321556333059695431531874740086907067131644479312\
+48944861718637164159925014157
+
+-532599980357955121299969897485530088860096014928320106613667412\
+7658734:197:-26515022518
+
+-751201308625232459519354741343046361775777470541080710058601279\
+4485802280356383896946090:190:-4786930913611882742357623031549
+
+3399159309738603281217586458627167057868700201720622195013008494\
+5155275705802319966198750893042523074386045050458079803807735428\
+3187:206:\
+3305159424435509522890985455639702285024494664087298807252559331\
+827343
+
+-163860953109333686549278104073264560158695392823410089526219985\
+3597217435977552163706193289327636667043413089396300868558342495\
+10158:28:\
+-610429618914923394282453149830045402641204717842527067386433427\
+630818425110560716579181436198814461768944967313222910671808
+
+1169677491246850751212:155:0
+
+1636926214665128743997698266803409352776056144809201:28:\
+6098025346789988666764267782879655632287473
+
+32036789:197:0
+
+-179819529231495425818261190658137469439875298005446780128564386\
+431:217:0
+
+-13881:96:0
+
+-201081314010698664682270171218698566959371060867314287561113777\
+01129681335253:40:\
+-182882389718268918552230544463508128464464844789576352524012488\
+18
+
+[Division]
+31082702275611665134711390509176302506278509424834232340028998555822\
+468563283335970816:\
+12141680576410806693246636917646993166515042744075872007823827560868\
+1517825325531136:256
+
+31082702275611665134711390509176302506278509424834232340028998555822\
+468563283335970816:\
+12947964052188086825220046400459488806478932301299660383343378609832\
+0524868413554688:240
+
+44966555772413807289969128318278041600000000000000000000000000000000\
+00000000000000000000000000000000000000000000000000000000000:\
+10000000000000000000000000000000000000000000000000000000000000000:\
+449665557724138072899691283182780416000000000000000000000000000
+
+21098512396730698729871269182769821769128761892761987:3:\
+7032837465576899576623756394256607256376253964253995
+
+105492561983653493649356345913849108845643809463809935:13:\
+8114812460281037973027411224142239141972600727985379
+
+60281463990659139228203626236485205054653605407891394:5:\
+12056292798131827845640725247297041010930721081578278
+
+105210958105812350283560987:65536:\
+1605391816800115208184
+
+29614251982539440611171209425825912338459:524288:\
+56484703030661469671575945712711167
+
+56978246562469415670177504927986945371616100345225344293332816228560\
+0752167:2147483648:\
+265325636428172773077047918587862259576172103850288988525666372052
+
+37676726270241192487393385601963645387543268661126:\
+3162948793160806:11911898906396771271361947212182077
+
+5381521826168870805682913114359466560841856996681731280221235281\
+1509347982906963231033117814383486428722076978472087592957820313\
+6046584241121779503933:\
+9668544070174123246320200737076440955801117408066349193856053605\
+114866903799592820480948520645947171624952907359157045540:\
+55660105462724064753070630466
+
+1723834528325652138144287068293892732593026664886852512770150633\
+2776744620689:880523393623328:\
+19577384778297865485961051332688212998820791370774585297291841
+
+1515496213019297763233177841945187397678421298227998213327928627\
+88716894139006899352549523462891658:\
+2837504714791238631293154232954335398939684196417059468771514311\
+350:53409469422883270966457345156344
+
+9404536008735908917791097512770771428224998938693723982728653696\
+7624988457783138098124870580583091:142622867370:\
+6593988875807797411127801190252266506668676674421094260691453448\
+48811732719710346250661
+
+1392866713189645633121390285073523887805815484659191269343858827\
+8526805205835017180928664701580352738609190657216273081064279937\
+78000446364:\
+3994371100075737516464195988347917583672726362309747721542773781\
+23623981222779902598092910701666748270156408025264:\
+3487073880449504057292395
+
+2676049916504901888523537181437273561212503:\
+9341913943837642277221766393692439892564:286
+
+2596351449981306834637204601381844425730435831169992187762230868\
+9984974618995828593891933726738665906555705360752479986:\
+1206034745333560481629722627489368003481730232554297338790:\
+21527998758138745589857127563572880142324265819094147184332850
+
+5972458816709701659388787816816316579897252032508674599704692592\
+7058649324526265892715874715058327035883363955854176049442032564\
+309441091155243908284:363119954882801248387416067701593:\
+1644761940620239975738766021378227306491031556802927687823754679\
+29691855045229469191916674982018556672788351294907277
+
+1179031947959075688529396972036519234258725785851394295456390535\
+71085372280587925290861953121759382460651235055866819:\
+6944577951175401788316018705171160466581578649464599557174064469\
+156454663085245879135170220436247473693597253951:\
+16977
+
+2026650664981190253207120825245989396597395032888279675327874031\
+6428571783495257002384926183573616802093352971457675644937672443\
+66086144671180173:\
+11631153560785819891286797700491247192758386954476186081000494851:\
+1742433073718499161789694097861808628892528194276009183278062135\
+44214369556426533
+
+2839636837334372650605745847855168203149142969651746071725807516\
+5633540988132586349575016474518431300299708784295829212402097919\
+78638935225269061241787155:\
+1906569338917937819117576221675263213381604280817243982366441014\
+3748504584308116848567559666016129206267348790454121809997280576\
+258634989:\
+148939604732445334
+
+6371345663036222144347827991463755679970672243967017350001151581\
+3149043621560543503748545334895102360498672050891243434943238417\
+147807583195634840:\
+2803012481163625225461909183974367795369310930636762769680881703\
+4432088350353366279882990440057382400481292913134:\
+2273035067040180000190499573423209
+
+3448761565369806483093631443732798385337886837688124530151199904\
+35214907404151562329499651293972622329230621111836:\
+1154398728297611607347339889796530761810873173035278653857672812\
+71070669711745252818396963830424218:\
+2987495984559585
+
+3939766758764969916635508714517181254109527059899723535687606136\
+704576526260284945948460575945132796870670558656976658696699246:\
+2039193601576864286342975169071164596968234:\
+1932021930491755924504494733348282114697992509296048596879364255\
+013992177897790479689
+
+2599570067192469214877296440421668709321992436666111483543544040\
+9558626508316404576861534763496892008536679796682457407142:\
+9865947223638288117488793858111648559036360190603549966937638974\
+384878768890886202494341034:\
+2634891519553273835810191600375
+
+9953582546881861626054758979348156073957328868768555275026281270\
+3558132981561279486898511993570779719758639416109225470113031476\
+11758278075817:\
+72753887765933437843645860013004267290394240181603205482549:\
+1368116928528260130222427481511416637491457702447115334585560552\
+89688431510521935105
+
+2777707354230450548824097922478859820718131575494711827631509815\
+849966141849784996342423141941423856370057172664302140424005921:\
+9887732931045287681192967993534615207992429003750153183843126191\
+7060602813748941:\
+28092459349393082079339190162534632411372212185
+
+135175390055754599158926343035891673287590:4587240067074273761847622538022:\
+29467694753
+
+1474508901852067097539817612956066371267340106475397703336120311\
+3477874932185558462473899178369214022436285310129280494436591650245178:\
+4880369721764333040209711516636996332699096293749849371410907103\
+371872025659064629729192743174282304112524555885248623478:\
+3021305732793
+
+2458344447588213641014490759478425477739674803315383837923650388\
+1993781110774393121943801110702528757067967698929051580978401073\
+21258908424060287326045:\
+4220549808710022650484813532790907621975000231990739804525754365\
+8980362:\
+5824701896693376525879103155093475976637389780048291339267026554\
+0931549290645770
+
+2235359829795993754168620762055024950392775900247276637443301544\
+6834872612125728471199341647165418100481804191461888838714869412\
+86190239242546459829:\
+1079446102417965701004684159063911518960227791488787275338443605\
+347380965151141469660172384738541132220010177148:\
+2070839687862853380670878474716925600
+
+2261859020237326202277047516915478440734386573562935959890434522\
+4642995494057840711903761496596915458217743732578579075270459080\
+0633340:14203382288913876345794743990430:\
+1592479153365299674692434597912939527498958604158881610792107099\
+0007263922267553892387895651241383531760
+
+1627272730547121895847771240538443456605751355188756262440532414\
+6146087377529161595400371637008556124469065:\
+4556444082143966348635739253264:\
+3571365523663868043578518888635769405026391569324510140958668270\
+949379670607
+
+7053322761929289086579214480771179517943045501137109771651701088\
+637150889882789201445500740549670389506:\
+5820761818383944703677222410067006495183070681923349620668953689\
+735114782073218950052335558230765131355225215024903803474:0
+
+72782874795717830428761392759834069051935680000647471818367555:\
+676006789231214575171585611498648177407768:\
+107665893235317651024
+
+2678488124982838045802785770118519145558475116428679203089749164\
+976612334859762291787998110260325948674165281:\
+7944336793457702698467826157627761976858612495202494286895968701\
+65:3371569200324712887203021916554964731360476
+
+[Modulo]
+9:7:2
+
+7:9:7
+
+36049713:3409630:1953413
+
+-5:7:2
+
+-14:7:0
+
+0:512568576:0
+-0:512568576:0
+
+-512568576:512568576:0
+
+-10062526826820804:29:0
+
+-5:199461981:199461976
+
+-8:7:6
+-7:7:0
+-6:7:1
+-5:7:2
+-4:7:3
+-3:7:4
+-2:7:5
+-1:7:6
+0:7:0
+
+8254156815303331281824478486972822803470138521315156647307553049\
+3310587284245750487869183215107304761500042605982935676360476706\
+01141527698603403:\
+3106222408827874796097424168822651228359402578430811:\
+595826521675090943156444889338281014934863303289705
+
+136863920521571139850391995526246731:\
+271472461994419020251392394864015015809448271748774:\
+136863920521571139850391995526246731
+
+1828810863480002099820314884714568551379787631093473955109129851\
+510111922379100046301719263372:567966528088927995495333:\
+385016512426968327768361
+
+861:7863900424362475800352483828371:861
+
+31298056599359036104:\
+6834101648969675037772759079916190769657938079502342632053787936\
+8365474573457851465113672049521142215618176993202488827600681:\
+31298056599359036104
+
+301132649529789235293089719211083808148317022029687377:\
+8985923799959631221206612:\
+174445061721403490019281
+
+2281346996471575399039236209159382841371310520671504115347726755\
+6405318252398792419321309385257790020895332595371743866761791127\
+088953387770:\
+9148250100428904287337426958133211831148659494946573378694903126\
+9368755379167072338:\
+5712279541400722125363135520469561121058328307700157395773665287\
+3288007253222581108
+
+18204134548129881201198951067056774604374867858971160:\
+2073934172352760752130567032660041512076751995427049488228564629\
+5445506418304709424209443465714405592187482184410284216568297836\
+202471453:\
+18204134548129881201198951067056774604374867858971160
+
+1965719248782007406536742098914361273948365800827075363669455004\
+986089949754002988457038216772776062129273:55:8
+
+242013738395129963274394550113335771936345:\
+5855690525992972254238170169720083764160159959672754491605994128\
+073126517:242013738395129963274394550113335771936345
+
+25207834098049778316063817949139583672551899941064748428641:\
+2394034335403109766635463364608199166358381072109847929528549615\
+46998:25207834098049778316063817949139583672551899941064748428641
+
+2806019740162818318268355414902530432876592478224294545991479160\
+4283116668034698476687974823971:\
+1582972323756438784786521922113831032463998151772165:\
+1502639578247286068956607674581436779911413521925746
+
+7646186835577905185055298334837136208896759894169440852778842148\
+501161592245256816858212924947738806827200173857627:\
+52896776132731697503809705:\
+24742696196904988498029477
+
+173957948128989810779090250062796172580059019371598891820856745013:\
+1799947313993959943024637237734385080822192208938376976998702929\
+3875551371653028911096579734599831769935491738680281300932262194\
+4984764:\
+173957948128989810779090250062796172580059019371598891820856745013
+
+1013844499640750066199242350792839164:\
+19498430190523094593606790431509419:\
+19424559924072241925296038785858795
+
+8622490124309718848844541942762:\
+2809153572052317438723547427922294488297174937286864313874241961\
+8679887592231751654390695362494978870866660168195696176431350266\
+533:\
+8622490124309718848844541942762
+
+1072609375974667769429773421465107051839877399085576311546582931\
+2311070154546061306145007166868107111741792231898435921633768385:\
+1463259917133913245195500729566820615925140728085869641490936807\
+875627045359340:\
+1136336627131206018599354228978585378999102832169870507738700505\
+866665661308205
+
+434178716356826614868022910336:\
+6634862369769044245968610325063754582:\
+434178716356826614868022910336
+
+1415406337306642091120413528271804224015406023026499:\
+7034899662310880590118948531539534220057245091097123989790225455\
+718320598907482500:\
+1415406337306642091120413528271804224015406023026499
+
+2119242142523650184634691519911880425707508853468661410230000555\
+581608937:\
+2008383355777044545530942339055540267683709901883165870378113231\
+22625039264578687:\
+2119242142523650184634691519911880425707508853468661410230000555\
+581608937
+
+69585923602069681658329224976930117468163915197373271065425178:\
+2020927964630024370658097798162044021281840678272412358937742685\
+874564410640015186840535854739937:\
+69585923602069681658329224976930117468163915197373271065425178
+
+96975588332536394385315130323058:\
+1315802351305852717882890944093568207768868622073415386004618717\
+2175427025633631880306918912341930581398571945990395254404556930\
+1546423248306886079218006:\
+96975588332536394385315130323058
+
+1005028458858291820643604063469013555486792420347821851888080697\
+7432670023176937393067923:\
+9828498588177084544380049:\
+2075442833247971646995411
+
+1189727226195844529530585:\
+6538657640728177165013773329092206385482700449306247249506942167\
+8887069241318642226489470387127398972818622366:\
+1189727226195844529530585
+
+9913890361391387217552509180:38186248654:26592864996
+
+7734726198125785627433577053431512633637067455428717621996818752\
+2575060294193475687274421372950273116057529131026941243649403546\
+7830323368528007:\
+5416039783030069273660577195279406145075794925910316773014188695\
+424126525007469657167631593847463121496915435500645:\
+4964806369541933457271704487044498217022879054817785578812091084\
+454769612571500637156272668116039380758996484864172
+
+71080186231578425712419354407360937437540:\
+1176980859009014803857106593068944458701173958687578469120934483\
+659139465526500936333672752:\
+71080186231578425712419354407360937437540
+
+6766067674766915237012186799976734148500111990982325235714483836\
+083584935230592805199170249391665243373021274113:\
+324423691845570163374834:\
+252059054229526041391927
+
+2823188323141882531578618333354253113311374951152404070296742852\
+061375867436124935489341:\
+1728156565766891281495579170663414558716728498925558384066168759\
+527625796619507427264134231896939288551956874380:\
+2823188323141882531578618333354253113311374951152404070296742852\
+061375867436124935489341
+
+262779290090979866282191640705312933450751046001:\
+1089280788909080319090197382760567576418992525818853374350259176\
+94325561016010292207663524094967470016917014:\
+262779290090979866282191640705312933450751046001
+
+8360271732029582503734310894572886727078012043023629221111060787\
+7138104216267918615216895281636771:555311145:120907711
+
+2366610337862898747408792992366342895990689944827378360469117410:\
+76427322404335731456359122655716444433:\
+30544640615708299605352469363039636872
+
+97771381685586783382636393:2:1
+
+435337671693078154773623349696989:834970971193485102214182395:\
+506732218892181192932591889
+
+2322513198662380013738103320830701289301787295559139301156091472\
+554729188662496855277024270062871128249398241623259939409120778:\
+2:0
+
+4680113793844806249835648380663376025372596959777178380:\
+2904997032241569138092132512949608009650334804336242983698449850\
+529852963482246181:\
+4680113793844806249835648380663376025372596959777178380
+
+2117036483187135:\
+2956811587252136030883436487547510285350147695210005035315279431\
+098717006229487861087796324851514192381549211074032:\
+2117036483187135
+
+5405482742629299751643548818366182062777872542836164736969326959\
+5853544020603118041671461286137567987302593373027659716:\
+4573526887169513117846642791864935937856091980821696964895032993\
+8:16470976317121249525195764490105435306011497015289420117425749982
+
+4359239142132654586747373757743417755349625230737312986309991827\
+8424863374421135266551983:64803544028311:37353941578659
+
+6890135792819098747339200650197811212669835729907537732727533511\
+643927448939258863466836536126445044614:1696179960288:\
+1324995865638
+
+4586314642595210536059912268094819407838151440257177384187072112:\
+2948676315159331003320418147316303300898329201084534802048646109\
+2015178004559585679:\
+4586314642595210536059912268094819407838151440257177384187072112\
+
+1295408061166295007189929428327291997766033572889635238933149973:\
+1972670797419796219560042479665734511348274052918937432115112357\
+6010380851770692946791:\
+1295408061166295007189929428327291997766033572889635238933149973\
+
+3293867584681053035957322938418784576730188582989206165304195433\
+9408357109851822801814954109216343414383237957096721562712712888\
+0653015247183660828064748:\
+8765772621072630220689785618513364012217258182568420497034708789\
+586373847828131714253297705781538931737255620107899492006608937806:\
+8601837373552535609108321170415754873427613358207755850219844413\
+541399748799344512722771514163410191291986915042108883348141430988
+
+1377746154164779665651413126473853834067870962817490604919589355\
+6407321117598745222627688834382600647541603271142562521784054:6:2
+
+1667979945553031384209256450228364963479415272610809793730506411\
+9303788198076909155676052962187532066482528524026964557345352216\
+5283446668047080:\
+1259826323514238805985170200301657600905328450695745758777562588\
+7186049156983679189477135784008594900590887239:\
+8186664560221138319073860758641161066866118482696737858152118048\
+749012625273296415253954330502016523386663032
+
+1604558310259870720456999045309843418780215517:\
+2314764593137129686707089727262818413583267016192300531282204770\
+7680963809189153750977995631646696992678572235424774049002424266\
+88494047914464727456:\
+1604558310259870720456999045309843418780215517
+
+1409736422781005655489884086727910650059319122250699179352885575\
+1322893090584507459430329601684018675016713:\
+3037097985924054837918:2373301421797167262781
+
+6701198625704:\
+3208271584698650102424018685293737567361186784549354155908725982\
+8050085877527140878207342707:6701198625704
+
+6570726263552141736792215188836614380398234183174708281848591553\
+9115168019938378584836876558466414158281554497244823448201181:\
+1502182222571155013035645850314652637622098563760970718145694442\
+1198813038883709721878584487611894267955370991921368152768464674\
+7953186479:\
+6570726263552141736792215188836614380398234183174708281848591553\
+9115168019938378584836876558466414158281554497244823448201181
+
+334479763778167:\
+2620180822092752558176129834916304534899606970427451061631144668\
+8169619730877675269585659135601795114355310342255614595194757773\
+7880241235214292696563:334479763778167
+
+# Some that exposed old bugs
+-19182011317708747655415793663840398231387658659684921854518950675010744\
+798088074160106794721561977563494710663654383617982647307741145787165689\
+415568325855995687160688325738126476982782410876428471011884289880631644\
+788665773228578260075978399410972382915954067959276715042755056729572829\
+093851913104244223672:\
+110589902576771067285674161059371867150853087104563757926013065022800986\
+359888876672387170062905874195180770816843413908369113777424570833424320\
+42777093021:\
+109391537162363400163656468557497811793910234020743027803411478222848317\
+478652922638466903221971706458039541796317994671218746507915453121571156\
+99186806428
+
+-12729002947374921813333325067985579104471306056810166870370214872461518\
+835258302087462325432188644174454003894356884235513517741560628902891180\
+85736535643:\
+857393771208094202104259627990318636601332086981:\
+347124740076798815206019311966363093945724145995
+
+-33561455954313714494272438259200225781962996013006223887793125858291980\
+416548560804296564715491363651855619074936805970007723556609659667595500\
+71261003601:\
+857393771208094202104259627990318636601332086981:\
+69829137374876952908916033728673445025
+
+[ModExp]
+# Sanity tests
+
+# 1:0:1:0 ???
+
+1:0:2:1
+
+2:103:150:8
+
+3923:380:4033:1
+
+6208938:141338444:179403587:74845992
+
+# Random small test cases
+35541290007:27861071413:54405498455:18392163817
+
+33810311815:21623687837:67955609697:6168450286
+
+390846234986723490867:258069:77811797476286981199753:388669864014945308514
+
+# g=2 is a special case in pow_mod.cpp; make sure it's well tested
+2:1024:159387639486734986734896734289672398467:\
+101251470522689220420018278313264853126
+
+2:4096:4634968374896:302457470528
+
+2:8190:46349683748963469823749683276389476398467349287:\
+22477714489988909289079275821119423277588139290
+
+2:65537:4634968374896346982374968327638947639846734928734603867934764974\
+978569847636666666666663948673967394673496739673496739486739467:\
+39545100683930137608837226660935619825254176150139370772680647311426\
+83367133155871655171332348089412143539565993577352969480643
+
+# A very big test case. bitsizes: (2624^2395)%2565
+79929780860261081309977632552711610540802328270286009268787208946266\
+52959801126270181797858326539991808408501955736107211154089990880864\
+13303849208224219100591662616178697815457369194539353353497852835501\
+41050889822915371610531527622477756791100346237932148802218221147910\
+83764160121545158487346802968250797762918640822953726116267698324397\
+97218709812746716531207101626249641544666652454598936868588048379676\
+16272912941048200311549530333983535276332190445765429717475889329196\
+82723327383286444096495073061099816572815545646462399372759381873394\
+86919484956198277784202729520512749754342112052047850740549446316888\
+78036856294503455545058266059097463500482961705306677988487417742491\
+15342399979893391684184998084322821589461452070845054017545885544579\
+571298686351226398527864005606439403913215:\
+57905475544917604320471424647112496473975795682168523689996102576776\
+26237088778306631051069455546703439634818835586436374397201459270953\
+73320224593906109498830519623033054321336538157343986271182875008898\
+46400895285646814945099135578078712638653971354390893897513549226862\
+42288943235147182911794944000641930092937330351756206882625430975695\
+44517498509112574132890275024912111320852904074917394291149467803521\
+35858911321807178002982306495559510988786798025982798386952917933172\
+94803214105228859170942097230151211488601051217081893388443911838163\
+36005486029723368697022501011466335322002083542926898677979222112122\
+26602746563675308094794277325137581108077975533806822750634437146271\
+95586058676179645844985231821190979452929:\
+10399205046598242703229657351883132701652276964362108506952937688714\
+32748288996020332036899375414937330955428206666889017559888570519250\
+50646752050470991826964779958550793771265289251619085920928563751890\
+69887180372385733236214632572059802975058104127044922162389962101924\
+84687865663461891419811205882677932740064370564080283318891658075996\
+58544432626283448453420230409266259464245167575870377225089095472270\
+35936225873319683727097162939426767650247431692626091054378261933883\
+04444592844359283277150336016415487591544524543727803303478523219741\
+67585351918391390323730198435093034895278122139553159165456287861721\
+05733915744785361299323192153909893286267220726431407206795271107384\
+11115626646378829487932946663804144605711055044827184543371896600950\
+5066861013496859002404865:\
+76383126271403199465553629505580460064061138700480822311446783865005\
+94033351331759734478813350785616549057262115034183484701333480536277\
+68750392900860337148760236002293999903452043982157916536463831543329\
+81510716218290076553514718078562286562453573978032941974718159086704\
+26254141182888039292181731039710070744775875012183282365743418038436\
+68118132938651461047089720835645326444415743163725663534054526664632\
+63369477979502118345322416804826584935088694928774075019074758940531\
+93696779256795084313220287359244619510038817488191412143951928835003\
+09516216069636385063459729195557820282023577637677540172121768705892\
+64355863735811421469235193223472628311338081133201771681274202506343\
+43861119601917402017293095701055272115112783553081034528116130152891\
+276971073856411987253305
+
+958568327191:\
+10820434407851188405104973511902906513518224342681350271810370438073617412:\
+385412694768521967592874726457715560537359750887572236310781387057217187291:\
+124514485573662879135724475226939854111051534076732305767767212261825204773
+
+993:\
+158082274092371197688912481356696199899964270448955828125938845871237934609:\
+195335598174576479907825469879133749630277214529613044392254617116806465841:\
+76319125426811367239700120840606231265432388418754186363393007030575232763
+
+5837:5387594231:\
+52910803894426776035608204231136092295842162542576147924991587830017346711785:\
+41256038256951041015975957103736087906734912779021641091323861709915393683478
+
+11820:\
+349248154095284306437849303504509069624812572044321414531019412890823663:\
+11695070112125499434524238623571455233638695379976237857792518028967433696813:\
+4877591936163920485322716677654737966141266950607206024720481980778956876733
+
+1279509:\
+228828116455132585158359573618073983726467809680019810077325482377363026:\
+596955405275729008892203759914236488647769846458724773926971979942130809:\
+548455744959985761919173432531376978888129348803576565818991241228678799
+
+1169325226204036541181168587818457846915410492286163370049583817559172758:583:\
+1347789004686354026667591408699204029024258192368477695588810277715014901:\
+986753196897611638420753041983500285520492197918271348656818055904410861
+
+39684855714221597676995827906679339738237777820353232844682939092337386955:\
+79808721821529030962053171978817611068275131312667370272216709366985607610:\
+168218000729293476661981768796405354274622797227127241788417326533874081227:\
+10243904434954110191313565832244070050272803217812912164431747671168317597
+
+473396006114590115230521230276516897096:\
+387145532418575837430469368595868663742:\
+554862946848974049157489689418354631387:\
+448855900130388136390865414336576134923
+
+383239913102526615892890047333017777270:\
+5212692713946112175761972297467118924556477:\
+9600330398725582192064124044651400063154809:\
+553434761331054066751131351244038395387413
+
+17023533902565202029648472226171284665775885307:\
+172062909283726569049023770937247425801:\
+2803129820108668499802071463467295777012106623420016438138627500\
+520764503324471534463345465793841061510744977815:\
+1087221030676278725112163308497001956646825599606083907052530601\
+511129847691028000053571012933461738616679305207
+
+6861608600119069162748766903320668621565184418412102985517914652\
+495806067714718757017641467375130420763543:\
+6090170638405015131997058617056249184350028938641981546887188901\
+427704577888167364319592127129279546370159:\
+9244137284483765901488318500741614548852246750950515340492572279\
+249663219793564958021372197661101436416951:\
+4357639256086891490742558173162011739263189633058589469209912059\
+837628983627026566654010174880786564650028
+
+1708391349301269900029298214389921761264445766152620652843393219\
+358035361114524948237829535432550149898389816132:\
+2879295558693495162441272767383253789140301947026867788739382060\
+6202058461437115060253107180150356177029255392:\
+4562451461011443048616592993727831094905333529601929282014937177\
+804484518010765376407040702135536959480150175881:\
+4780971485381051463987885157471185516431563444901967941411376359\
+86642717690683975282976174121121834972342669810
+
+10517206412589906914919094336031596865011:\
+76918459253520716071622848977323758816926:\
+1505994032870020776188597437379504956214103601873594169817828353\
+64671206273170823011738702809865490437980268482169:\
+6782959072847327960243512935142614796318322133888530532951869324\
+5770409979689571346380672589348570036123781607470
+
+11150372599265311570767859136324180752990207:\
+242724485078592151169084549880604092836:\
+5335081937310201228237642071226891497098426337909703107583644285\
+670654712470768061820964879543360755501155583507:\
+5289945663803755598608137950548888139591380435852466790487033227\
+703935262787324650046364967638572584406632742426
+
+931466513478626427306310727788682496419061:\
+217994111091681034507066335081667319859874:\
+961964829688733829104056632507823404588589:\
+833173750092106303567501575871102318441517
+
+33561455954313714494272438259200225781962996013006223887793125858291\
+98041654856080429656471549136365185561907493680597000772355660965966\
+759550071261003601:2:857393771208094202104259627990318636601332086981:\
+466300477512220407817532870461493708182430162598
+
+# Format number:is_prime, where is_prime is 0 or 1
+[PrimeTest]
+0:0
+1:0
+2:1
+3:1
+4:0
+65537:1
+
+# This one passes Miller-Rabin with a base of 2, but not with most others
+4294967297:0
+
+# Random ones
+10416536965533130067:1
+
+62073521899194104903553565787:1
+
+170585900781008069215236465296032411499:1
+
+1443993313735051633697456797423139085424112074517:1
+
+10771372029656662585340604592252023412983364818055143344382694346546\
+2298290643:1
+
+11771372029656662585340604592252023412983364818055143344382694346546\
+2298290643:0
+
+42588518477191145729:0
+
+# The following are of the form p1*p2*p3*...*pn + 1 where px is the x'th prime
+# This is to make sure the number gets past any checks for small prime factors,
+# and tests the Miller-Rabin routines. It would be nice to look up or search
+# for some Carmichael numbers to help this testing some.
+32589158477190044731:0
+
+4014476939333036189094441199026045136645885247731:0
+
+1907826688958019501360189182099275775721983966835701205590751690\
+4309700014933909014729740191:0
+
+4445236185272185438169240794291312557432222642727183809026451438\
+704160103479600800432029464271:0
+
+6107692946593319609927894338899785515035614388823837148866549657\
+4810764573680243467182799164806563626522181311132959748531230211:0
+
+6989612506894284794136067796445539076219364950255126280242854713\
+9923075880112964253713561700013194221462347575861905534037645370\
+21369947456703810795390696338067840821591:0
+
+2577426147548683169379880845613862450845254401055092509543183257\
+2701791887072337189992932234179329410389241899414841054215169960\
+1546741832617953638436279944072980418788682453341495300190580109\
+0622787969540076319408964006231:0
diff --git a/botan/checks/nist_tests/failure.txt b/botan/checks/nist_tests/failure.txt
new file mode 100644
index 0000000..0166e0e
--- /dev/null
+++ b/botan/checks/nist_tests/failure.txt
@@ -0,0 +1,12 @@
+Known Failures/Problems
+
+Policy extensions are not implemented, so we skip tests #34-#53.
+
+Tests #75 and #76 are skipped as they make use of relatively obscure CRL
+extensions which are not supported.
+
+In addition, please note that some of the tests have their results altered from
+what the test result should be according to NIST's documentation. The changes
+are clearly marked (see x509test.cpp; search for "CHANGE OF TEST RESULT") and
+there are comments explaining why the results where changed. Currently, tests
+#19, #65, and #67 have had their results changed from the official results.
diff --git a/botan/checks/nist_tests/readme.txt b/botan/checks/nist_tests/readme.txt
new file mode 100644
index 0000000..b992a5b
--- /dev/null
+++ b/botan/checks/nist_tests/readme.txt
@@ -0,0 +1,26 @@
+
+This package contains a program to exercise Botan's path validation
+algorithm, as contained in the X509_Store object. The data used is
+NIST's X.509v3 certificate path validation testing data, as found on
+NIST's web site (version 1.0.7 of the testing data is currently
+used). The PKCS #7 and PKCS #12 data files have been removed, as they
+are not used in this test.
+
+Currently, some tests fail or are not be run for various reasons (in
+particular, we don't have support policy extensions yet, so that
+excludes running a good number of the tests). Even if all of the tests
+DO pass, that does not imply that Botan's path validation and
+certificate processing code is bug free, as there are many (*very
+many*) possible options in X.509 which this testing data does not make
+use of at all. However, it is helpful for implementation testing and
+assurance (I have found a good number of bugs using these tests).
+
+Currently, we do not make use of the S/MIME or PKCS #12 testing data
+contained in these tests, because Botan does not support either of
+these standards.
+
+To use this, compile x509test.cpp, and run the resulting
+executable. The results are written to standard output. Your system
+must have a POSIX.1 dirent.h, and the code assumes Unix-style paths.
+
+Email me with any questions or comments about these tests.
diff --git a/botan/checks/nist_tests/tests/test01/end.crt b/botan/checks/nist_tests/tests/test01/end.crt
new file mode 100644
index 0000000..d7e64d6
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test01/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test01/root.crl b/botan/checks/nist_tests/tests/test01/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test01/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test01/root.crt b/botan/checks/nist_tests/tests/test01/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test01/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test02/end.crt b/botan/checks/nist_tests/tests/test02/end.crt
new file mode 100644
index 0000000..f97da05
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test02/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test02/int.crl b/botan/checks/nist_tests/tests/test02/int.crl
new file mode 100644
index 0000000..e7dfa96
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test02/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test02/int.crt b/botan/checks/nist_tests/tests/test02/int.crt
new file mode 100644
index 0000000..0aba750
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test02/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test02/root.crl b/botan/checks/nist_tests/tests/test02/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test02/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test02/root.crt b/botan/checks/nist_tests/tests/test02/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test02/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test03/end.crt b/botan/checks/nist_tests/tests/test03/end.crt
new file mode 100644
index 0000000..9b0463a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test03/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test03/int.crl b/botan/checks/nist_tests/tests/test03/int.crl
new file mode 100644
index 0000000..528f323
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test03/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test03/int.crt b/botan/checks/nist_tests/tests/test03/int.crt
new file mode 100644
index 0000000..c8cfc05
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test03/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test03/root.crl b/botan/checks/nist_tests/tests/test03/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test03/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test03/root.crt b/botan/checks/nist_tests/tests/test03/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test03/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/end.crt b/botan/checks/nist_tests/tests/test04/end.crt
new file mode 100644
index 0000000..75d2fd5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/int1.crl b/botan/checks/nist_tests/tests/test04/int1.crl
new file mode 100644
index 0000000..2f30c77
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/int1.crt b/botan/checks/nist_tests/tests/test04/int1.crt
new file mode 100644
index 0000000..f4e88d5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/int2.crl b/botan/checks/nist_tests/tests/test04/int2.crl
new file mode 100644
index 0000000..e8596c3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/int2.crt b/botan/checks/nist_tests/tests/test04/int2.crt
new file mode 100644
index 0000000..727035b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/root.crl b/botan/checks/nist_tests/tests/test04/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test04/root.crt b/botan/checks/nist_tests/tests/test04/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test04/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test05/end.crt b/botan/checks/nist_tests/tests/test05/end.crt
new file mode 100644
index 0000000..a3a6589
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test05/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test05/int.crl b/botan/checks/nist_tests/tests/test05/int.crl
new file mode 100644
index 0000000..a34ef27
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test05/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test05/int.crt b/botan/checks/nist_tests/tests/test05/int.crt
new file mode 100644
index 0000000..610df75
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test05/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test05/root.crl b/botan/checks/nist_tests/tests/test05/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test05/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test05/root.crt b/botan/checks/nist_tests/tests/test05/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test05/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test06/end.crt b/botan/checks/nist_tests/tests/test06/end.crt
new file mode 100644
index 0000000..1e68f0d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test06/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test06/int.crl b/botan/checks/nist_tests/tests/test06/int.crl
new file mode 100644
index 0000000..d87cd7e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test06/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test06/int.crt b/botan/checks/nist_tests/tests/test06/int.crt
new file mode 100644
index 0000000..5bb74d2
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test06/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test06/root.crl b/botan/checks/nist_tests/tests/test06/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test06/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test06/root.crt b/botan/checks/nist_tests/tests/test06/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test06/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test07/end.crt b/botan/checks/nist_tests/tests/test07/end.crt
new file mode 100644
index 0000000..0f97e6f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test07/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test07/int.crl b/botan/checks/nist_tests/tests/test07/int.crl
new file mode 100644
index 0000000..8064e91
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test07/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test07/int.crt b/botan/checks/nist_tests/tests/test07/int.crt
new file mode 100644
index 0000000..5c1ddd3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test07/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test07/root.crl b/botan/checks/nist_tests/tests/test07/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test07/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test07/root.crt b/botan/checks/nist_tests/tests/test07/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test07/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test08/end.crt b/botan/checks/nist_tests/tests/test08/end.crt
new file mode 100644
index 0000000..cb99c2a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test08/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test08/int.crl b/botan/checks/nist_tests/tests/test08/int.crl
new file mode 100644
index 0000000..d5ee3c3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test08/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test08/int.crt b/botan/checks/nist_tests/tests/test08/int.crt
new file mode 100644
index 0000000..d26979c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test08/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test08/root.crl b/botan/checks/nist_tests/tests/test08/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test08/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test08/root.crt b/botan/checks/nist_tests/tests/test08/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test08/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test09/end.crt b/botan/checks/nist_tests/tests/test09/end.crt
new file mode 100644
index 0000000..4dd2352
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test09/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test09/int.crl b/botan/checks/nist_tests/tests/test09/int.crl
new file mode 100644
index 0000000..fbd8514
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test09/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test09/int.crt b/botan/checks/nist_tests/tests/test09/int.crt
new file mode 100644
index 0000000..c107dd7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test09/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test09/root.crl b/botan/checks/nist_tests/tests/test09/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test09/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test09/root.crt b/botan/checks/nist_tests/tests/test09/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test09/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test10/end.crt b/botan/checks/nist_tests/tests/test10/end.crt
new file mode 100644
index 0000000..de39240
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test10/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test10/int.crl b/botan/checks/nist_tests/tests/test10/int.crl
new file mode 100644
index 0000000..daefd50
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test10/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test10/int.crt b/botan/checks/nist_tests/tests/test10/int.crt
new file mode 100644
index 0000000..2d691ab
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test10/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test10/root.crl b/botan/checks/nist_tests/tests/test10/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test10/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test10/root.crt b/botan/checks/nist_tests/tests/test10/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test10/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test11/end.crt b/botan/checks/nist_tests/tests/test11/end.crt
new file mode 100644
index 0000000..6e14527
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test11/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test11/int.crl b/botan/checks/nist_tests/tests/test11/int.crl
new file mode 100644
index 0000000..cc91ad5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test11/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test11/int.crt b/botan/checks/nist_tests/tests/test11/int.crt
new file mode 100644
index 0000000..87fa079
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test11/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test11/root.crl b/botan/checks/nist_tests/tests/test11/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test11/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test11/root.crt b/botan/checks/nist_tests/tests/test11/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test11/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test12/end.crt b/botan/checks/nist_tests/tests/test12/end.crt
new file mode 100644
index 0000000..158c6ae
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test12/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test12/int.crl b/botan/checks/nist_tests/tests/test12/int.crl
new file mode 100644
index 0000000..7ce6928
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test12/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test12/int.crt b/botan/checks/nist_tests/tests/test12/int.crt
new file mode 100644
index 0000000..a55333b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test12/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test12/root.crl b/botan/checks/nist_tests/tests/test12/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test12/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test12/root.crt b/botan/checks/nist_tests/tests/test12/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test12/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test13/end.crt b/botan/checks/nist_tests/tests/test13/end.crt
new file mode 100644
index 0000000..d1ddf4b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test13/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test13/int.crl b/botan/checks/nist_tests/tests/test13/int.crl
new file mode 100644
index 0000000..df86506
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test13/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test13/int.crt b/botan/checks/nist_tests/tests/test13/int.crt
new file mode 100644
index 0000000..abc6fe5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test13/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test13/root.crl b/botan/checks/nist_tests/tests/test13/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test13/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test13/root.crt b/botan/checks/nist_tests/tests/test13/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test13/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test14/end.crt b/botan/checks/nist_tests/tests/test14/end.crt
new file mode 100644
index 0000000..f43e038
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test14/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test14/int.crl b/botan/checks/nist_tests/tests/test14/int.crl
new file mode 100644
index 0000000..ae372f3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test14/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test14/int.crt b/botan/checks/nist_tests/tests/test14/int.crt
new file mode 100644
index 0000000..6e97ee2
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test14/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test14/root.crl b/botan/checks/nist_tests/tests/test14/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test14/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test14/root.crt b/botan/checks/nist_tests/tests/test14/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test14/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test15/end.crt b/botan/checks/nist_tests/tests/test15/end.crt
new file mode 100644
index 0000000..a240831
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test15/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test15/int.crl b/botan/checks/nist_tests/tests/test15/int.crl
new file mode 100644
index 0000000..626049a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test15/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test15/int.crt b/botan/checks/nist_tests/tests/test15/int.crt
new file mode 100644
index 0000000..23fb78c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test15/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test15/root.crl b/botan/checks/nist_tests/tests/test15/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test15/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test15/root.crt b/botan/checks/nist_tests/tests/test15/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test15/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test16/end.crt b/botan/checks/nist_tests/tests/test16/end.crt
new file mode 100644
index 0000000..108a75d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test16/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test16/int.crl b/botan/checks/nist_tests/tests/test16/int.crl
new file mode 100644
index 0000000..d345a33
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test16/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test16/int.crt b/botan/checks/nist_tests/tests/test16/int.crt
new file mode 100644
index 0000000..6f2a332
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test16/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test16/root.crl b/botan/checks/nist_tests/tests/test16/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test16/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test16/root.crt b/botan/checks/nist_tests/tests/test16/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test16/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test17/end.crt b/botan/checks/nist_tests/tests/test17/end.crt
new file mode 100644
index 0000000..b903408
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test17/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test17/int.crl b/botan/checks/nist_tests/tests/test17/int.crl
new file mode 100644
index 0000000..0b1ba6f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test17/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test17/int.crt b/botan/checks/nist_tests/tests/test17/int.crt
new file mode 100644
index 0000000..25e7b48
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test17/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test17/root.crl b/botan/checks/nist_tests/tests/test17/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test17/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test17/root.crt b/botan/checks/nist_tests/tests/test17/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test17/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test18/end.crt b/botan/checks/nist_tests/tests/test18/end.crt
new file mode 100644
index 0000000..2edb513
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test18/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test18/int.crl b/botan/checks/nist_tests/tests/test18/int.crl
new file mode 100644
index 0000000..2948246
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test18/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test18/int.crt b/botan/checks/nist_tests/tests/test18/int.crt
new file mode 100644
index 0000000..eac3e86
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test18/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test18/root.crl b/botan/checks/nist_tests/tests/test18/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test18/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test18/root.crt b/botan/checks/nist_tests/tests/test18/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test18/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test19/end.crt b/botan/checks/nist_tests/tests/test19/end.crt
new file mode 100644
index 0000000..a9c7a1f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test19/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test19/int.crt b/botan/checks/nist_tests/tests/test19/int.crt
new file mode 100644
index 0000000..eff60dd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test19/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test19/root.crl b/botan/checks/nist_tests/tests/test19/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test19/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test19/root.crt b/botan/checks/nist_tests/tests/test19/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test19/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test20/end.crt b/botan/checks/nist_tests/tests/test20/end.crt
new file mode 100644
index 0000000..b26e77c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test20/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test20/int.crl b/botan/checks/nist_tests/tests/test20/int.crl
new file mode 100644
index 0000000..5755a2e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test20/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test20/int.crt b/botan/checks/nist_tests/tests/test20/int.crt
new file mode 100644
index 0000000..d7daa69
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test20/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test20/root.crl b/botan/checks/nist_tests/tests/test20/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test20/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test20/root.crt b/botan/checks/nist_tests/tests/test20/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test20/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test21/end.crt b/botan/checks/nist_tests/tests/test21/end.crt
new file mode 100644
index 0000000..798e5cf
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test21/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test21/int.crl b/botan/checks/nist_tests/tests/test21/int.crl
new file mode 100644
index 0000000..ea3cbb9
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test21/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test21/int.crt b/botan/checks/nist_tests/tests/test21/int.crt
new file mode 100644
index 0000000..9082c4d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test21/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test21/root.crl b/botan/checks/nist_tests/tests/test21/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test21/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test21/root.crt b/botan/checks/nist_tests/tests/test21/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test21/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test22/end.crt b/botan/checks/nist_tests/tests/test22/end.crt
new file mode 100644
index 0000000..d130c75
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test22/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test22/int.crl b/botan/checks/nist_tests/tests/test22/int.crl
new file mode 100644
index 0000000..07e1839
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test22/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test22/int.crt b/botan/checks/nist_tests/tests/test22/int.crt
new file mode 100644
index 0000000..d0f401b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test22/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test22/root.crl b/botan/checks/nist_tests/tests/test22/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test22/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test22/root.crt b/botan/checks/nist_tests/tests/test22/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test22/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test23/end.crt b/botan/checks/nist_tests/tests/test23/end.crt
new file mode 100644
index 0000000..787941b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test23/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test23/int.crl b/botan/checks/nist_tests/tests/test23/int.crl
new file mode 100644
index 0000000..2841be7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test23/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test23/int.crt b/botan/checks/nist_tests/tests/test23/int.crt
new file mode 100644
index 0000000..2890b39
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test23/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test23/root.crl b/botan/checks/nist_tests/tests/test23/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test23/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test23/root.crt b/botan/checks/nist_tests/tests/test23/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test23/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test24/end.crt b/botan/checks/nist_tests/tests/test24/end.crt
new file mode 100644
index 0000000..0d145b2
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test24/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test24/int.crl b/botan/checks/nist_tests/tests/test24/int.crl
new file mode 100644
index 0000000..f608de6
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test24/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test24/int.crt b/botan/checks/nist_tests/tests/test24/int.crt
new file mode 100644
index 0000000..a4633ee
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test24/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test24/root.crl b/botan/checks/nist_tests/tests/test24/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test24/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test24/root.crt b/botan/checks/nist_tests/tests/test24/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test24/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test25/end.crt b/botan/checks/nist_tests/tests/test25/end.crt
new file mode 100644
index 0000000..d126701
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test25/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test25/int.crl b/botan/checks/nist_tests/tests/test25/int.crl
new file mode 100644
index 0000000..553e1bb
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test25/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test25/int.crt b/botan/checks/nist_tests/tests/test25/int.crt
new file mode 100644
index 0000000..5d06aac
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test25/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test25/root.crl b/botan/checks/nist_tests/tests/test25/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test25/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test25/root.crt b/botan/checks/nist_tests/tests/test25/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test25/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test26/end.crt b/botan/checks/nist_tests/tests/test26/end.crt
new file mode 100644
index 0000000..5abc966
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test26/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test26/int.crl b/botan/checks/nist_tests/tests/test26/int.crl
new file mode 100644
index 0000000..9f2f1b0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test26/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test26/int.crt b/botan/checks/nist_tests/tests/test26/int.crt
new file mode 100644
index 0000000..e9c273a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test26/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test26/root.crl b/botan/checks/nist_tests/tests/test26/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test26/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test26/root.crt b/botan/checks/nist_tests/tests/test26/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test26/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test27/end.crt b/botan/checks/nist_tests/tests/test27/end.crt
new file mode 100644
index 0000000..2147dbd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test27/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test27/int.crl b/botan/checks/nist_tests/tests/test27/int.crl
new file mode 100644
index 0000000..fd769e5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test27/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test27/int.crt b/botan/checks/nist_tests/tests/test27/int.crt
new file mode 100644
index 0000000..4de4a9f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test27/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test27/root.crl b/botan/checks/nist_tests/tests/test27/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test27/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test27/root.crt b/botan/checks/nist_tests/tests/test27/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test27/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test28/end.crt b/botan/checks/nist_tests/tests/test28/end.crt
new file mode 100644
index 0000000..c72c97b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test28/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test28/int.crl b/botan/checks/nist_tests/tests/test28/int.crl
new file mode 100644
index 0000000..35e87eb
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test28/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test28/int.crt b/botan/checks/nist_tests/tests/test28/int.crt
new file mode 100644
index 0000000..fee01f2
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test28/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test28/root.crl b/botan/checks/nist_tests/tests/test28/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test28/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test28/root.crt b/botan/checks/nist_tests/tests/test28/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test28/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test29/end.crt b/botan/checks/nist_tests/tests/test29/end.crt
new file mode 100644
index 0000000..e4e2dd0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test29/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test29/int.crl b/botan/checks/nist_tests/tests/test29/int.crl
new file mode 100644
index 0000000..2739bd9
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test29/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test29/int.crt b/botan/checks/nist_tests/tests/test29/int.crt
new file mode 100644
index 0000000..e830043
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test29/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test29/root.crl b/botan/checks/nist_tests/tests/test29/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test29/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test29/root.crt b/botan/checks/nist_tests/tests/test29/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test29/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test30/end.crt b/botan/checks/nist_tests/tests/test30/end.crt
new file mode 100644
index 0000000..abdc038
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test30/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test30/int.crl b/botan/checks/nist_tests/tests/test30/int.crl
new file mode 100644
index 0000000..fed695a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test30/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test30/int.crt b/botan/checks/nist_tests/tests/test30/int.crt
new file mode 100644
index 0000000..26fd2cb
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test30/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test30/root.crl b/botan/checks/nist_tests/tests/test30/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test30/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test30/root.crt b/botan/checks/nist_tests/tests/test30/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test30/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test31/end.crt b/botan/checks/nist_tests/tests/test31/end.crt
new file mode 100644
index 0000000..cd766ef
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test31/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test31/int.crl b/botan/checks/nist_tests/tests/test31/int.crl
new file mode 100644
index 0000000..9014141
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test31/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test31/int.crt b/botan/checks/nist_tests/tests/test31/int.crt
new file mode 100644
index 0000000..396947b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test31/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test31/root.crl b/botan/checks/nist_tests/tests/test31/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test31/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test31/root.crt b/botan/checks/nist_tests/tests/test31/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test31/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test32/end.crt b/botan/checks/nist_tests/tests/test32/end.crt
new file mode 100644
index 0000000..3804a27
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test32/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test32/int.crl b/botan/checks/nist_tests/tests/test32/int.crl
new file mode 100644
index 0000000..2e2e505
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test32/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test32/int.crt b/botan/checks/nist_tests/tests/test32/int.crt
new file mode 100644
index 0000000..6df3396
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test32/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test32/root.crl b/botan/checks/nist_tests/tests/test32/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test32/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test32/root.crt b/botan/checks/nist_tests/tests/test32/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test32/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test33/end.crt b/botan/checks/nist_tests/tests/test33/end.crt
new file mode 100644
index 0000000..6ef1d03
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test33/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test33/int.crl b/botan/checks/nist_tests/tests/test33/int.crl
new file mode 100644
index 0000000..4008e3d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test33/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test33/int.crt b/botan/checks/nist_tests/tests/test33/int.crt
new file mode 100644
index 0000000..ba18369
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test33/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test33/root.crl b/botan/checks/nist_tests/tests/test33/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test33/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test33/root.crt b/botan/checks/nist_tests/tests/test33/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test33/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test34/end.crt b/botan/checks/nist_tests/tests/test34/end.crt
new file mode 100644
index 0000000..695de1c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test34/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test34/int.crl b/botan/checks/nist_tests/tests/test34/int.crl
new file mode 100644
index 0000000..a8d11e7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test34/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test34/int.crt b/botan/checks/nist_tests/tests/test34/int.crt
new file mode 100644
index 0000000..5657dda
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test34/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test34/root.crl b/botan/checks/nist_tests/tests/test34/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test34/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test34/root.crt b/botan/checks/nist_tests/tests/test34/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test34/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test35/end.crt b/botan/checks/nist_tests/tests/test35/end.crt
new file mode 100644
index 0000000..26846be
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test35/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test35/int.crl b/botan/checks/nist_tests/tests/test35/int.crl
new file mode 100644
index 0000000..f7021d3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test35/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test35/int.crt b/botan/checks/nist_tests/tests/test35/int.crt
new file mode 100644
index 0000000..6a66418
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test35/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test35/root.crl b/botan/checks/nist_tests/tests/test35/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test35/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test35/root.crt b/botan/checks/nist_tests/tests/test35/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test35/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/end.crt b/botan/checks/nist_tests/tests/test36/end.crt
new file mode 100644
index 0000000..ee6ec5f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/int1.crl b/botan/checks/nist_tests/tests/test36/int1.crl
new file mode 100644
index 0000000..d4ad101
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/int1.crt b/botan/checks/nist_tests/tests/test36/int1.crt
new file mode 100644
index 0000000..a300e8d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/int2.crl b/botan/checks/nist_tests/tests/test36/int2.crl
new file mode 100644
index 0000000..d45cedc
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/int2.crt b/botan/checks/nist_tests/tests/test36/int2.crt
new file mode 100644
index 0000000..87c8253
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/root.crl b/botan/checks/nist_tests/tests/test36/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test36/root.crt b/botan/checks/nist_tests/tests/test36/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test36/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/end.crt b/botan/checks/nist_tests/tests/test37/end.crt
new file mode 100644
index 0000000..e5c5ae8
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/int1.crl b/botan/checks/nist_tests/tests/test37/int1.crl
new file mode 100644
index 0000000..6b488fd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/int1.crt b/botan/checks/nist_tests/tests/test37/int1.crt
new file mode 100644
index 0000000..26b6b96
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/int2.crl b/botan/checks/nist_tests/tests/test37/int2.crl
new file mode 100644
index 0000000..7240511
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/int2.crt b/botan/checks/nist_tests/tests/test37/int2.crt
new file mode 100644
index 0000000..c0e986a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/root.crl b/botan/checks/nist_tests/tests/test37/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test37/root.crt b/botan/checks/nist_tests/tests/test37/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test37/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/end.crt b/botan/checks/nist_tests/tests/test38/end.crt
new file mode 100644
index 0000000..9331b90
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/int1.crl b/botan/checks/nist_tests/tests/test38/int1.crl
new file mode 100644
index 0000000..81f75d4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/int1.crt b/botan/checks/nist_tests/tests/test38/int1.crt
new file mode 100644
index 0000000..c8ee614
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/int2.crl b/botan/checks/nist_tests/tests/test38/int2.crl
new file mode 100644
index 0000000..ae1d7d5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/int2.crt b/botan/checks/nist_tests/tests/test38/int2.crt
new file mode 100644
index 0000000..8d28342
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/root.crl b/botan/checks/nist_tests/tests/test38/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test38/root.crt b/botan/checks/nist_tests/tests/test38/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test38/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/end.crt b/botan/checks/nist_tests/tests/test39/end.crt
new file mode 100644
index 0000000..57263d4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int1.crl b/botan/checks/nist_tests/tests/test39/int1.crl
new file mode 100644
index 0000000..f2a0138
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int1.crt b/botan/checks/nist_tests/tests/test39/int1.crt
new file mode 100644
index 0000000..b7003f7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int2.crl b/botan/checks/nist_tests/tests/test39/int2.crl
new file mode 100644
index 0000000..b6672d8
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int2.crt b/botan/checks/nist_tests/tests/test39/int2.crt
new file mode 100644
index 0000000..c56ce57
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int3.crl b/botan/checks/nist_tests/tests/test39/int3.crl
new file mode 100644
index 0000000..453420b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/int3.crt b/botan/checks/nist_tests/tests/test39/int3.crt
new file mode 100644
index 0000000..ce1224a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/root.crl b/botan/checks/nist_tests/tests/test39/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test39/root.crt b/botan/checks/nist_tests/tests/test39/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test39/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/end.crt b/botan/checks/nist_tests/tests/test40/end.crt
new file mode 100644
index 0000000..24ce9e4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int1.crl b/botan/checks/nist_tests/tests/test40/int1.crl
new file mode 100644
index 0000000..5bd6a9f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int1.crt b/botan/checks/nist_tests/tests/test40/int1.crt
new file mode 100644
index 0000000..5a8ac50
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int2.crl b/botan/checks/nist_tests/tests/test40/int2.crl
new file mode 100644
index 0000000..dde5a12
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int2.crt b/botan/checks/nist_tests/tests/test40/int2.crt
new file mode 100644
index 0000000..70e4d90
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int3.crl b/botan/checks/nist_tests/tests/test40/int3.crl
new file mode 100644
index 0000000..713fa4b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/int3.crt b/botan/checks/nist_tests/tests/test40/int3.crt
new file mode 100644
index 0000000..a0c6734
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/root.crl b/botan/checks/nist_tests/tests/test40/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test40/root.crt b/botan/checks/nist_tests/tests/test40/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test40/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/end.crt b/botan/checks/nist_tests/tests/test41/end.crt
new file mode 100644
index 0000000..b88e38e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int1.crl b/botan/checks/nist_tests/tests/test41/int1.crl
new file mode 100644
index 0000000..2d4c415
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int1.crt b/botan/checks/nist_tests/tests/test41/int1.crt
new file mode 100644
index 0000000..4b96b2a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int2.crl b/botan/checks/nist_tests/tests/test41/int2.crl
new file mode 100644
index 0000000..e389a7f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int2.crt b/botan/checks/nist_tests/tests/test41/int2.crt
new file mode 100644
index 0000000..4b1edc7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int3.crl b/botan/checks/nist_tests/tests/test41/int3.crl
new file mode 100644
index 0000000..d26dc1b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/int3.crt b/botan/checks/nist_tests/tests/test41/int3.crt
new file mode 100644
index 0000000..6012a3a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/root.crl b/botan/checks/nist_tests/tests/test41/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test41/root.crt b/botan/checks/nist_tests/tests/test41/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test41/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/end.crt b/botan/checks/nist_tests/tests/test42/end.crt
new file mode 100644
index 0000000..9815c5d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int1.crl b/botan/checks/nist_tests/tests/test42/int1.crl
new file mode 100644
index 0000000..d4f21db
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int1.crt b/botan/checks/nist_tests/tests/test42/int1.crt
new file mode 100644
index 0000000..f344a9f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int2.crl b/botan/checks/nist_tests/tests/test42/int2.crl
new file mode 100644
index 0000000..3290605
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int2.crt b/botan/checks/nist_tests/tests/test42/int2.crt
new file mode 100644
index 0000000..a2fd05c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int3.crl b/botan/checks/nist_tests/tests/test42/int3.crl
new file mode 100644
index 0000000..ee2b2b1
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int3.crt b/botan/checks/nist_tests/tests/test42/int3.crt
new file mode 100644
index 0000000..8104a65
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int4.crl b/botan/checks/nist_tests/tests/test42/int4.crl
new file mode 100644
index 0000000..7602160
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/int4.crt b/botan/checks/nist_tests/tests/test42/int4.crt
new file mode 100644
index 0000000..5b6ffbd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/root.crl b/botan/checks/nist_tests/tests/test42/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test42/root.crt b/botan/checks/nist_tests/tests/test42/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test42/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/end.crt b/botan/checks/nist_tests/tests/test43/end.crt
new file mode 100644
index 0000000..9465ea5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int1.crl b/botan/checks/nist_tests/tests/test43/int1.crl
new file mode 100644
index 0000000..4ce26fd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int1.crt b/botan/checks/nist_tests/tests/test43/int1.crt
new file mode 100644
index 0000000..e18a4e1
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int2.crl b/botan/checks/nist_tests/tests/test43/int2.crl
new file mode 100644
index 0000000..9820bc6
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int2.crt b/botan/checks/nist_tests/tests/test43/int2.crt
new file mode 100644
index 0000000..1521fce
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int3.crl b/botan/checks/nist_tests/tests/test43/int3.crl
new file mode 100644
index 0000000..b8dfd8d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int3.crt b/botan/checks/nist_tests/tests/test43/int3.crt
new file mode 100644
index 0000000..30b9706
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int4.crl b/botan/checks/nist_tests/tests/test43/int4.crl
new file mode 100644
index 0000000..4b41362
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/int4.crt b/botan/checks/nist_tests/tests/test43/int4.crt
new file mode 100644
index 0000000..9495622
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/root.crl b/botan/checks/nist_tests/tests/test43/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test43/root.crt b/botan/checks/nist_tests/tests/test43/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test43/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/end.crt b/botan/checks/nist_tests/tests/test44/end.crt
new file mode 100644
index 0000000..5fc9bec
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int1.crl b/botan/checks/nist_tests/tests/test44/int1.crl
new file mode 100644
index 0000000..2d4478c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int1.crt b/botan/checks/nist_tests/tests/test44/int1.crt
new file mode 100644
index 0000000..fbfd2a4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int2.crl b/botan/checks/nist_tests/tests/test44/int2.crl
new file mode 100644
index 0000000..780ef7c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int2.crt b/botan/checks/nist_tests/tests/test44/int2.crt
new file mode 100644
index 0000000..26f3193
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int3.crl b/botan/checks/nist_tests/tests/test44/int3.crl
new file mode 100644
index 0000000..5e5267e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int3.crt b/botan/checks/nist_tests/tests/test44/int3.crt
new file mode 100644
index 0000000..7f62ef6
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int4.crl b/botan/checks/nist_tests/tests/test44/int4.crl
new file mode 100644
index 0000000..5d775f5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/int4.crt b/botan/checks/nist_tests/tests/test44/int4.crt
new file mode 100644
index 0000000..76d6111
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/root.crl b/botan/checks/nist_tests/tests/test44/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test44/root.crt b/botan/checks/nist_tests/tests/test44/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test44/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/end.crt b/botan/checks/nist_tests/tests/test45/end.crt
new file mode 100644
index 0000000..a2ddb04
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int1.crl b/botan/checks/nist_tests/tests/test45/int1.crl
new file mode 100644
index 0000000..079062c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int1.crt b/botan/checks/nist_tests/tests/test45/int1.crt
new file mode 100644
index 0000000..90ee8e3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int2.crl b/botan/checks/nist_tests/tests/test45/int2.crl
new file mode 100644
index 0000000..7c12bd0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int2.crt b/botan/checks/nist_tests/tests/test45/int2.crt
new file mode 100644
index 0000000..7fc0467
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int3.crl b/botan/checks/nist_tests/tests/test45/int3.crl
new file mode 100644
index 0000000..f81b504
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int3.crt b/botan/checks/nist_tests/tests/test45/int3.crt
new file mode 100644
index 0000000..fb9500f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int4.crl b/botan/checks/nist_tests/tests/test45/int4.crl
new file mode 100644
index 0000000..9e67a4a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/int4.crt b/botan/checks/nist_tests/tests/test45/int4.crt
new file mode 100644
index 0000000..60b6c91
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/root.crl b/botan/checks/nist_tests/tests/test45/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test45/root.crt b/botan/checks/nist_tests/tests/test45/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test45/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/end.crt b/botan/checks/nist_tests/tests/test46/end.crt
new file mode 100644
index 0000000..39ebf20
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int1.crl b/botan/checks/nist_tests/tests/test46/int1.crl
new file mode 100644
index 0000000..f9a2236
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int1.crt b/botan/checks/nist_tests/tests/test46/int1.crt
new file mode 100644
index 0000000..985a5d5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int2.crl b/botan/checks/nist_tests/tests/test46/int2.crl
new file mode 100644
index 0000000..02e82c4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int2.crt b/botan/checks/nist_tests/tests/test46/int2.crt
new file mode 100644
index 0000000..ade6433
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int3.crl b/botan/checks/nist_tests/tests/test46/int3.crl
new file mode 100644
index 0000000..ddd59a8
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int3.crt b/botan/checks/nist_tests/tests/test46/int3.crt
new file mode 100644
index 0000000..6e33faa
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int4.crl b/botan/checks/nist_tests/tests/test46/int4.crl
new file mode 100644
index 0000000..3dedfb1
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/int4.crt b/botan/checks/nist_tests/tests/test46/int4.crt
new file mode 100644
index 0000000..1b3fc57
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/root.crl b/botan/checks/nist_tests/tests/test46/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test46/root.crt b/botan/checks/nist_tests/tests/test46/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test46/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/end.crt b/botan/checks/nist_tests/tests/test47/end.crt
new file mode 100644
index 0000000..7337bc5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int1.crl b/botan/checks/nist_tests/tests/test47/int1.crl
new file mode 100644
index 0000000..938e3f4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int1.crt b/botan/checks/nist_tests/tests/test47/int1.crt
new file mode 100644
index 0000000..bf3e222
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int2.crl b/botan/checks/nist_tests/tests/test47/int2.crl
new file mode 100644
index 0000000..f715c11
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int2.crt b/botan/checks/nist_tests/tests/test47/int2.crt
new file mode 100644
index 0000000..1b7854e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int3.crl b/botan/checks/nist_tests/tests/test47/int3.crl
new file mode 100644
index 0000000..786aa50
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int3.crt b/botan/checks/nist_tests/tests/test47/int3.crt
new file mode 100644
index 0000000..62eb3b2
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int4.crl b/botan/checks/nist_tests/tests/test47/int4.crl
new file mode 100644
index 0000000..925b783
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/int4.crt b/botan/checks/nist_tests/tests/test47/int4.crt
new file mode 100644
index 0000000..1c9a143
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/root.crl b/botan/checks/nist_tests/tests/test47/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test47/root.crt b/botan/checks/nist_tests/tests/test47/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test47/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test48/end.crt b/botan/checks/nist_tests/tests/test48/end.crt
new file mode 100644
index 0000000..933f279
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test48/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test48/int.crl b/botan/checks/nist_tests/tests/test48/int.crl
new file mode 100644
index 0000000..89ad99c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test48/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test48/int.crt b/botan/checks/nist_tests/tests/test48/int.crt
new file mode 100644
index 0000000..b2eefc4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test48/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test48/root.crl b/botan/checks/nist_tests/tests/test48/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test48/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test48/root.crt b/botan/checks/nist_tests/tests/test48/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test48/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test49/end.crt b/botan/checks/nist_tests/tests/test49/end.crt
new file mode 100644
index 0000000..d0e4a26
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test49/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test49/int.crl b/botan/checks/nist_tests/tests/test49/int.crl
new file mode 100644
index 0000000..1defb1e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test49/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test49/int.crt b/botan/checks/nist_tests/tests/test49/int.crt
new file mode 100644
index 0000000..037f68d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test49/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test49/root.crl b/botan/checks/nist_tests/tests/test49/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test49/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test49/root.crt b/botan/checks/nist_tests/tests/test49/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test49/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test50/end.crt b/botan/checks/nist_tests/tests/test50/end.crt
new file mode 100644
index 0000000..ed9b0a3
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test50/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test50/int.crl b/botan/checks/nist_tests/tests/test50/int.crl
new file mode 100644
index 0000000..0c7cdfe
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test50/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test50/int.crt b/botan/checks/nist_tests/tests/test50/int.crt
new file mode 100644
index 0000000..74c41f0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test50/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test50/root.crl b/botan/checks/nist_tests/tests/test50/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test50/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test50/root.crt b/botan/checks/nist_tests/tests/test50/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test50/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test51/end.crt b/botan/checks/nist_tests/tests/test51/end.crt
new file mode 100644
index 0000000..12ebc74
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test51/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test51/int.crl b/botan/checks/nist_tests/tests/test51/int.crl
new file mode 100644
index 0000000..c887c9a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test51/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test51/int.crt b/botan/checks/nist_tests/tests/test51/int.crt
new file mode 100644
index 0000000..def7e90
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test51/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test51/root.crl b/botan/checks/nist_tests/tests/test51/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test51/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test51/root.crt b/botan/checks/nist_tests/tests/test51/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test51/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test52/end.crt b/botan/checks/nist_tests/tests/test52/end.crt
new file mode 100644
index 0000000..0bd1918
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test52/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test52/int.crl b/botan/checks/nist_tests/tests/test52/int.crl
new file mode 100644
index 0000000..ec22087
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test52/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test52/int.crt b/botan/checks/nist_tests/tests/test52/int.crt
new file mode 100644
index 0000000..3429d7c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test52/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test52/root.crl b/botan/checks/nist_tests/tests/test52/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test52/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test52/root.crt b/botan/checks/nist_tests/tests/test52/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test52/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test53/end.crt b/botan/checks/nist_tests/tests/test53/end.crt
new file mode 100644
index 0000000..9b99dc5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test53/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test53/int.crl b/botan/checks/nist_tests/tests/test53/int.crl
new file mode 100644
index 0000000..79fed24
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test53/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test53/int.crt b/botan/checks/nist_tests/tests/test53/int.crt
new file mode 100644
index 0000000..72eac94
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test53/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test53/root.crl b/botan/checks/nist_tests/tests/test53/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test53/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test53/root.crt b/botan/checks/nist_tests/tests/test53/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test53/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/end.crt b/botan/checks/nist_tests/tests/test54/end.crt
new file mode 100644
index 0000000..185f019
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/int1.crl b/botan/checks/nist_tests/tests/test54/int1.crl
new file mode 100644
index 0000000..5b1c443
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/int1.crt b/botan/checks/nist_tests/tests/test54/int1.crt
new file mode 100644
index 0000000..140ef06
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/int2.crl b/botan/checks/nist_tests/tests/test54/int2.crl
new file mode 100644
index 0000000..c531566
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/int2.crt b/botan/checks/nist_tests/tests/test54/int2.crt
new file mode 100644
index 0000000..506761d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/root.crl b/botan/checks/nist_tests/tests/test54/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test54/root.crt b/botan/checks/nist_tests/tests/test54/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test54/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/end.crt b/botan/checks/nist_tests/tests/test55/end.crt
new file mode 100644
index 0000000..923d4c5
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/int1.crl b/botan/checks/nist_tests/tests/test55/int1.crl
new file mode 100644
index 0000000..371821e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/int1.crt b/botan/checks/nist_tests/tests/test55/int1.crt
new file mode 100644
index 0000000..7597faf
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/int2.crl b/botan/checks/nist_tests/tests/test55/int2.crl
new file mode 100644
index 0000000..9a24291
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/int2.crt b/botan/checks/nist_tests/tests/test55/int2.crt
new file mode 100644
index 0000000..982235a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/root.crl b/botan/checks/nist_tests/tests/test55/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test55/root.crt b/botan/checks/nist_tests/tests/test55/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test55/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test56/end.crt b/botan/checks/nist_tests/tests/test56/end.crt
new file mode 100644
index 0000000..d1dc821
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test56/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test56/int.crl b/botan/checks/nist_tests/tests/test56/int.crl
new file mode 100644
index 0000000..840b209
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test56/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test56/int.crt b/botan/checks/nist_tests/tests/test56/int.crt
new file mode 100644
index 0000000..9b622ca
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test56/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test56/root.crl b/botan/checks/nist_tests/tests/test56/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test56/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test56/root.crt b/botan/checks/nist_tests/tests/test56/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test56/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test57/end.crt b/botan/checks/nist_tests/tests/test57/end.crt
new file mode 100644
index 0000000..2f93938
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test57/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test57/int.crl b/botan/checks/nist_tests/tests/test57/int.crl
new file mode 100644
index 0000000..a0be908
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test57/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test57/int.crt b/botan/checks/nist_tests/tests/test57/int.crt
new file mode 100644
index 0000000..79f6d6b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test57/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test57/root.crl b/botan/checks/nist_tests/tests/test57/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test57/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test57/root.crt b/botan/checks/nist_tests/tests/test57/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test57/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/end.crt b/botan/checks/nist_tests/tests/test58/end.crt
new file mode 100644
index 0000000..674009c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int1.crl b/botan/checks/nist_tests/tests/test58/int1.crl
new file mode 100644
index 0000000..aa9dc9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int1.crt b/botan/checks/nist_tests/tests/test58/int1.crt
new file mode 100644
index 0000000..42e9831
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int2.crl b/botan/checks/nist_tests/tests/test58/int2.crl
new file mode 100644
index 0000000..7dec9c1
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int2.crt b/botan/checks/nist_tests/tests/test58/int2.crt
new file mode 100644
index 0000000..08eb808
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int3.crl b/botan/checks/nist_tests/tests/test58/int3.crl
new file mode 100644
index 0000000..bec6344
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/int3.crt b/botan/checks/nist_tests/tests/test58/int3.crt
new file mode 100644
index 0000000..6c5e6ef
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/root.crl b/botan/checks/nist_tests/tests/test58/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test58/root.crt b/botan/checks/nist_tests/tests/test58/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test58/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/end.crt b/botan/checks/nist_tests/tests/test59/end.crt
new file mode 100644
index 0000000..da5ee9e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int1.crl b/botan/checks/nist_tests/tests/test59/int1.crl
new file mode 100644
index 0000000..eb7f0e8
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int1.crt b/botan/checks/nist_tests/tests/test59/int1.crt
new file mode 100644
index 0000000..be0ee21
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int2.crl b/botan/checks/nist_tests/tests/test59/int2.crl
new file mode 100644
index 0000000..2b2fe9c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int2.crt b/botan/checks/nist_tests/tests/test59/int2.crt
new file mode 100644
index 0000000..a84a7ba
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int3.crl b/botan/checks/nist_tests/tests/test59/int3.crl
new file mode 100644
index 0000000..cb7885c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/int3.crt b/botan/checks/nist_tests/tests/test59/int3.crt
new file mode 100644
index 0000000..0b13f9f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/root.crl b/botan/checks/nist_tests/tests/test59/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test59/root.crt b/botan/checks/nist_tests/tests/test59/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test59/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/end.crt b/botan/checks/nist_tests/tests/test60/end.crt
new file mode 100644
index 0000000..8741105
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int1.crl b/botan/checks/nist_tests/tests/test60/int1.crl
new file mode 100644
index 0000000..e778e91
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int1.crt b/botan/checks/nist_tests/tests/test60/int1.crt
new file mode 100644
index 0000000..01d8442
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int2.crl b/botan/checks/nist_tests/tests/test60/int2.crl
new file mode 100644
index 0000000..4f4ac6b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int2.crt b/botan/checks/nist_tests/tests/test60/int2.crt
new file mode 100644
index 0000000..0054dc6
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int3.crl b/botan/checks/nist_tests/tests/test60/int3.crl
new file mode 100644
index 0000000..0b568e7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int3.crt b/botan/checks/nist_tests/tests/test60/int3.crt
new file mode 100644
index 0000000..6fff65c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int4.crl b/botan/checks/nist_tests/tests/test60/int4.crl
new file mode 100644
index 0000000..4cf694a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/int4.crt b/botan/checks/nist_tests/tests/test60/int4.crt
new file mode 100644
index 0000000..c5eebca
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/root.crl b/botan/checks/nist_tests/tests/test60/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test60/root.crt b/botan/checks/nist_tests/tests/test60/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test60/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/end.crt b/botan/checks/nist_tests/tests/test61/end.crt
new file mode 100644
index 0000000..7be023c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int1.crl b/botan/checks/nist_tests/tests/test61/int1.crl
new file mode 100644
index 0000000..05c2809
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int1.crt b/botan/checks/nist_tests/tests/test61/int1.crt
new file mode 100644
index 0000000..ba03f6c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int2.crl b/botan/checks/nist_tests/tests/test61/int2.crl
new file mode 100644
index 0000000..d74b916
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int2.crt b/botan/checks/nist_tests/tests/test61/int2.crt
new file mode 100644
index 0000000..bd4e40e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int3.crl b/botan/checks/nist_tests/tests/test61/int3.crl
new file mode 100644
index 0000000..7e6e83f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int3.crt b/botan/checks/nist_tests/tests/test61/int3.crt
new file mode 100644
index 0000000..4f9342b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int4.crl b/botan/checks/nist_tests/tests/test61/int4.crl
new file mode 100644
index 0000000..7161f41
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/int4.crt b/botan/checks/nist_tests/tests/test61/int4.crt
new file mode 100644
index 0000000..5962eed
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/root.crl b/botan/checks/nist_tests/tests/test61/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test61/root.crt b/botan/checks/nist_tests/tests/test61/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test61/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/end.crt b/botan/checks/nist_tests/tests/test62/end.crt
new file mode 100644
index 0000000..bff8ea4
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int1.crl b/botan/checks/nist_tests/tests/test62/int1.crl
new file mode 100644
index 0000000..aa26a41
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int1.crt b/botan/checks/nist_tests/tests/test62/int1.crt
new file mode 100644
index 0000000..aee257d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int2.crl b/botan/checks/nist_tests/tests/test62/int2.crl
new file mode 100644
index 0000000..61e712f
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int2.crt b/botan/checks/nist_tests/tests/test62/int2.crt
new file mode 100644
index 0000000..a62d9a0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int3.crl b/botan/checks/nist_tests/tests/test62/int3.crl
new file mode 100644
index 0000000..09707fd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int3.crt b/botan/checks/nist_tests/tests/test62/int3.crt
new file mode 100644
index 0000000..aa91f34
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int4.crl b/botan/checks/nist_tests/tests/test62/int4.crl
new file mode 100644
index 0000000..997a057
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/int4.crt b/botan/checks/nist_tests/tests/test62/int4.crt
new file mode 100644
index 0000000..7446030
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/root.crl b/botan/checks/nist_tests/tests/test62/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test62/root.crt b/botan/checks/nist_tests/tests/test62/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test62/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/end.crt b/botan/checks/nist_tests/tests/test63/end.crt
new file mode 100644
index 0000000..16c1c68
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int1.crl b/botan/checks/nist_tests/tests/test63/int1.crl
new file mode 100644
index 0000000..40c4afc
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int1.crt b/botan/checks/nist_tests/tests/test63/int1.crt
new file mode 100644
index 0000000..6b3f6eb
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int2.crl b/botan/checks/nist_tests/tests/test63/int2.crl
new file mode 100644
index 0000000..7bffd46
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int2.crt b/botan/checks/nist_tests/tests/test63/int2.crt
new file mode 100644
index 0000000..f2e88f9
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int3.crl b/botan/checks/nist_tests/tests/test63/int3.crl
new file mode 100644
index 0000000..20f503c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int3.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int3.crt b/botan/checks/nist_tests/tests/test63/int3.crt
new file mode 100644
index 0000000..2d636dd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int3.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int4.crl b/botan/checks/nist_tests/tests/test63/int4.crl
new file mode 100644
index 0000000..71e6229
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int4.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/int4.crt b/botan/checks/nist_tests/tests/test63/int4.crt
new file mode 100644
index 0000000..a0ed3a1
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/int4.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/root.crl b/botan/checks/nist_tests/tests/test63/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test63/root.crt b/botan/checks/nist_tests/tests/test63/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test63/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test64/end.crt b/botan/checks/nist_tests/tests/test64/end.crt
new file mode 100644
index 0000000..771423e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test64/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test64/int.crl b/botan/checks/nist_tests/tests/test64/int.crl
new file mode 100644
index 0000000..0e3e2bd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test64/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test64/int.crt b/botan/checks/nist_tests/tests/test64/int.crt
new file mode 100644
index 0000000..1ae8258
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test64/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test64/root.crl b/botan/checks/nist_tests/tests/test64/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test64/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test64/root.crt b/botan/checks/nist_tests/tests/test64/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test64/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/end.crt b/botan/checks/nist_tests/tests/test65/end.crt
new file mode 100644
index 0000000..29d51a7
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/int.crl b/botan/checks/nist_tests/tests/test65/int.crl
new file mode 100644
index 0000000..bd2d906
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/int1.crt b/botan/checks/nist_tests/tests/test65/int1.crt
new file mode 100644
index 0000000..214c839
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/int2.crt b/botan/checks/nist_tests/tests/test65/int2.crt
new file mode 100644
index 0000000..57c2e59
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/root.crl b/botan/checks/nist_tests/tests/test65/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test65/root.crt b/botan/checks/nist_tests/tests/test65/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test65/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test66/end.crt b/botan/checks/nist_tests/tests/test66/end.crt
new file mode 100644
index 0000000..ccdb0e0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test66/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test66/int.crl b/botan/checks/nist_tests/tests/test66/int.crl
new file mode 100644
index 0000000..f80b444
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test66/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test66/int.crt b/botan/checks/nist_tests/tests/test66/int.crt
new file mode 100644
index 0000000..23f8b17
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test66/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test66/root.crl b/botan/checks/nist_tests/tests/test66/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test66/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test66/root.crt b/botan/checks/nist_tests/tests/test66/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test66/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/end.crt b/botan/checks/nist_tests/tests/test67/end.crt
new file mode 100644
index 0000000..85d5508
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/int.crt b/botan/checks/nist_tests/tests/test67/int.crt
new file mode 100644
index 0000000..92a4b3a
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/int1.crl b/botan/checks/nist_tests/tests/test67/int1.crl
new file mode 100644
index 0000000..3fe8349
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/int2.crl b/botan/checks/nist_tests/tests/test67/int2.crl
new file mode 100644
index 0000000..15593fa
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/root.crl b/botan/checks/nist_tests/tests/test67/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test67/root.crt b/botan/checks/nist_tests/tests/test67/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test67/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/end.crt b/botan/checks/nist_tests/tests/test68/end.crt
new file mode 100644
index 0000000..bddd72d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/int1.crl b/botan/checks/nist_tests/tests/test68/int1.crl
new file mode 100644
index 0000000..fdbf8ea
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/int1.crt b/botan/checks/nist_tests/tests/test68/int1.crt
new file mode 100644
index 0000000..4bc8127
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/int2.crl b/botan/checks/nist_tests/tests/test68/int2.crl
new file mode 100644
index 0000000..33b7640
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/int2.crt b/botan/checks/nist_tests/tests/test68/int2.crt
new file mode 100644
index 0000000..1ca8d5c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/root.crl b/botan/checks/nist_tests/tests/test68/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test68/root.crt b/botan/checks/nist_tests/tests/test68/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test68/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test69/end.crt b/botan/checks/nist_tests/tests/test69/end.crt
new file mode 100644
index 0000000..00fc716
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test69/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test69/int.crl b/botan/checks/nist_tests/tests/test69/int.crl
new file mode 100644
index 0000000..fc09d35
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test69/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test69/int.crt b/botan/checks/nist_tests/tests/test69/int.crt
new file mode 100644
index 0000000..6c19ee0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test69/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test69/root.crl b/botan/checks/nist_tests/tests/test69/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test69/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test69/root.crt b/botan/checks/nist_tests/tests/test69/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test69/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/end.crt b/botan/checks/nist_tests/tests/test70/end.crt
new file mode 100644
index 0000000..c576960
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/int1.crl b/botan/checks/nist_tests/tests/test70/int1.crl
new file mode 100644
index 0000000..77dafb9
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/int1.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/int1.crt b/botan/checks/nist_tests/tests/test70/int1.crt
new file mode 100644
index 0000000..5509c54
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/int1.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/int2.crl b/botan/checks/nist_tests/tests/test70/int2.crl
new file mode 100644
index 0000000..4e22f39
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/int2.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/int2.crt b/botan/checks/nist_tests/tests/test70/int2.crt
new file mode 100644
index 0000000..9af80b8
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/int2.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/root.crl b/botan/checks/nist_tests/tests/test70/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test70/root.crt b/botan/checks/nist_tests/tests/test70/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test70/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test71/end.crt b/botan/checks/nist_tests/tests/test71/end.crt
new file mode 100644
index 0000000..0cc1718
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test71/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test71/int.crl b/botan/checks/nist_tests/tests/test71/int.crl
new file mode 100644
index 0000000..c34a95d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test71/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test71/int.crt b/botan/checks/nist_tests/tests/test71/int.crt
new file mode 100644
index 0000000..0707601
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test71/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test71/root.crl b/botan/checks/nist_tests/tests/test71/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test71/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test71/root.crt b/botan/checks/nist_tests/tests/test71/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test71/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test72/end.crt b/botan/checks/nist_tests/tests/test72/end.crt
new file mode 100644
index 0000000..6c61375
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test72/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test72/int.crl b/botan/checks/nist_tests/tests/test72/int.crl
new file mode 100644
index 0000000..643141b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test72/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test72/int.crt b/botan/checks/nist_tests/tests/test72/int.crt
new file mode 100644
index 0000000..36b1f20
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test72/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test72/root.crl b/botan/checks/nist_tests/tests/test72/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test72/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test72/root.crt b/botan/checks/nist_tests/tests/test72/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test72/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test73/end.crt b/botan/checks/nist_tests/tests/test73/end.crt
new file mode 100644
index 0000000..9bae532
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test73/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test73/int.crl b/botan/checks/nist_tests/tests/test73/int.crl
new file mode 100644
index 0000000..6b76dc0
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test73/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test73/int.crt b/botan/checks/nist_tests/tests/test73/int.crt
new file mode 100644
index 0000000..ff6df25
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test73/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test73/root.crl b/botan/checks/nist_tests/tests/test73/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test73/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test73/root.crt b/botan/checks/nist_tests/tests/test73/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test73/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test74/end.crt b/botan/checks/nist_tests/tests/test74/end.crt
new file mode 100644
index 0000000..93e05bd
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test74/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test74/int.crl b/botan/checks/nist_tests/tests/test74/int.crl
new file mode 100644
index 0000000..8733b18
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test74/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test74/int.crt b/botan/checks/nist_tests/tests/test74/int.crt
new file mode 100644
index 0000000..c925814
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test74/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test74/root.crl b/botan/checks/nist_tests/tests/test74/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test74/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test74/root.crt b/botan/checks/nist_tests/tests/test74/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test74/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test75/end.crt b/botan/checks/nist_tests/tests/test75/end.crt
new file mode 100644
index 0000000..7d8179b
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test75/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test75/int.crl b/botan/checks/nist_tests/tests/test75/int.crl
new file mode 100644
index 0000000..19f472c
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test75/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test75/int.crt b/botan/checks/nist_tests/tests/test75/int.crt
new file mode 100644
index 0000000..4a4c27e
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test75/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test75/root.crl b/botan/checks/nist_tests/tests/test75/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test75/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test75/root.crt b/botan/checks/nist_tests/tests/test75/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test75/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test76/end.crt b/botan/checks/nist_tests/tests/test76/end.crt
new file mode 100644
index 0000000..bde477d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test76/end.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test76/int.crl b/botan/checks/nist_tests/tests/test76/int.crl
new file mode 100644
index 0000000..dbbbd43
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test76/int.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test76/int.crt b/botan/checks/nist_tests/tests/test76/int.crt
new file mode 100644
index 0000000..ab1c643
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test76/int.crt
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test76/root.crl b/botan/checks/nist_tests/tests/test76/root.crl
new file mode 100644
index 0000000..de65024
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test76/root.crl
Binary files differ
diff --git a/botan/checks/nist_tests/tests/test76/root.crt b/botan/checks/nist_tests/tests/test76/root.crt
new file mode 100644
index 0000000..d7dfd9d
--- /dev/null
+++ b/botan/checks/nist_tests/tests/test76/root.crt
Binary files differ
diff --git a/botan/checks/nist_tests/x509test.cpp b/botan/checks/nist_tests/x509test.cpp
new file mode 100644
index 0000000..7f4fe94
--- /dev/null
+++ b/botan/checks/nist_tests/x509test.cpp
@@ -0,0 +1,411 @@
+/*
+ Code to run the X.509v3 processing tests described in "Conformance Testing of
+ Relying Party Client Certificate Path Proccessing Logic", which is available
+ on NIST's web site.
+*/
+
+#include <botan/x509stor.h>
+#include <botan/init.h>
+using namespace Botan;
+
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+
+#include <dirent.h>
+
+#define POLICY_TEST1 1000
+#define POLICY_TEST2 2000
+#define POLICY_TEST3 3000
+
+std::vector<std::string> dir_listing(const std::string&);
+
+void run_one_test(u32bit, X509_Code,
+ std::string, std::string,
+ std::vector<std::string>,
+ std::vector<std::string>);
+
+std::map<u32bit, X509_Code> expected_results;
+
+u32bit unexp_failure, unexp_success, wrong_error, skipped;
+
+void populate_expected_results();
+
+int main()
+ {
+ const std::string root_test_dir = "tests/";
+ unexp_failure = unexp_success = wrong_error = skipped = 0;
+
+ try {
+
+ LibraryInitializer init;
+
+ populate_expected_results();
+
+ std::vector<std::string> test_dirs = dir_listing(root_test_dir);
+ std::sort(test_dirs.begin(), test_dirs.end());
+
+ for(size_t j = 0; j != test_dirs.size(); j++)
+ {
+ const std::string test_dir = root_test_dir + test_dirs[j] + "/";
+ std::vector<std::string> all_files = dir_listing(test_dir);
+
+ std::vector<std::string> certs, crls;
+ std::string root_cert, to_verify;
+
+ for(size_t k = 0; k != all_files.size(); k++)
+ {
+ const std::string current = all_files[k];
+ if(current.find("int") != std::string::npos &&
+ current.find(".crt") != std::string::npos)
+ certs.push_back(test_dir + current);
+ else if(current.find("root.crt") != std::string::npos)
+ root_cert = test_dir + current;
+ else if(current.find("end.crt") != std::string::npos)
+ to_verify = test_dir + current;
+ else if(current.find(".crl") != std::string::npos)
+ crls.push_back(test_dir + current);
+ }
+
+ if(expected_results.find(j+1) == expected_results.end())
+ {
+#if 0
+ std::cout << "Testing disabled for test #" << j+1
+ << " <skipped>" << std::endl;
+#endif
+ skipped++;
+ continue;
+ }
+
+ run_one_test(j+1, expected_results[j+1],
+ root_cert, to_verify, certs, crls);
+ }
+
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+
+ std::cout << "Total unexpected failures: " << unexp_failure << std::endl;
+ std::cout << "Total unexpected successes: " << unexp_success << std::endl;
+ std::cout << "Total incorrect failures: " << wrong_error << std::endl;
+ std::cout << "Tests skipped: " << skipped << std::endl;
+
+ return 0;
+ }
+
+void run_one_test(u32bit test_no, X509_Code expected,
+ std::string root_cert, std::string to_verify,
+ std::vector<std::string> certs,
+ std::vector<std::string> crls)
+ {
+ std::cout << "Processing test #" << test_no << "... ";
+ std::cout.flush();
+
+ X509_Code result = VERIFIED;
+
+ X509_Store store;
+
+ store.add_cert(X509_Certificate(root_cert), true);
+
+ X509_Certificate end_user(to_verify);
+
+ for(size_t j = 0; j != certs.size(); j++)
+ store.add_cert(X509_Certificate(certs[j]));
+
+ for(size_t j = 0; j != crls.size(); j++)
+ {
+ DataSource_Stream in(crls[j]);
+
+ X509_CRL crl(in);
+ /*
+ std::vector<CRL_Entry> crl_entries = crl.get_revoked();
+ for(u32bit k = 0; k != crl_entries.size(); k++)
+ {
+ std::cout << "Revoked: " << std::flush;
+ for(u32bit l = 0; l != crl_entries[k].serial.size(); l++)
+ printf("%02X", crl_entries[k].serial[l]);
+ std::cout << std::endl;
+ }
+ */
+ result = store.add_crl(crl);
+ if(result != VERIFIED)
+ break;
+ }
+
+ /* if everything has gone well up until now */
+
+ if(result == VERIFIED)
+ {
+ result = store.validate_cert(end_user);
+
+ X509_Code result2 = store.validate_cert(end_user);
+
+ if(result != result2)
+ std::cout << "Two runs, two answers: " << result << " "
+ << result2 << std::endl;
+ }
+
+ if(result == expected)
+ {
+ std::cout << "passed" << std::endl;
+ return;
+ }
+
+ if(expected == VERIFIED)
+ {
+ std::cout << "unexpected failure: " << result << std::endl;
+ unexp_failure++;
+ }
+ else if(result == VERIFIED)
+ {
+ std::cout << "unexpected success: " << expected << std::endl;
+ unexp_success++;
+ }
+ else
+ {
+ std::cout << "wrong error: " << result << "/" << expected << std::endl;
+ wrong_error++;
+ }
+ }
+
+std::vector<std::string> dir_listing(const std::string& dir_name)
+ {
+ DIR* dir = opendir(dir_name.c_str());
+ if(!dir)
+ {
+ std::cout << "Error, couldn't open dir " << dir_name << std::endl;
+ std::exit(1);
+ }
+
+ std::vector<std::string> listing;
+
+ while(true)
+ {
+ struct dirent* dir_ent = readdir(dir);
+
+ if(dir_ent == 0)
+ break;
+ const std::string entry = dir_ent->d_name;
+ if(entry == "." || entry == "..")
+ continue;
+
+ listing.push_back(entry);
+ }
+ closedir(dir);
+
+ return listing;
+ }
+
+/*
+ The expected results are essentially the error codes that best coorespond
+ to the problem described in the testing documentation.
+
+ There are a few cases where the tests say there should or should not be an
+ error, and I disagree. A few of the tests have test results different from
+ what they "should" be: these changes are marked as such, and have comments
+ explaining the problem at hand.
+*/
+void populate_expected_results()
+ {
+ /* OK, not a super great way of doing this... */
+ expected_results[1] = VERIFIED;
+ expected_results[2] = SIGNATURE_ERROR;
+ expected_results[3] = SIGNATURE_ERROR;
+ expected_results[4] = VERIFIED;
+ expected_results[5] = CERT_NOT_YET_VALID;
+ expected_results[6] = CERT_NOT_YET_VALID;
+ expected_results[7] = VERIFIED;
+ expected_results[8] = CERT_NOT_YET_VALID;
+ expected_results[9] = CERT_HAS_EXPIRED;
+ expected_results[10] = CERT_HAS_EXPIRED;
+ expected_results[11] = CERT_HAS_EXPIRED;
+ expected_results[12] = VERIFIED;
+ expected_results[13] = CERT_ISSUER_NOT_FOUND;
+
+ // FIXME: we get the answer right for the wrong reason
+ // ummm... I don't know if that is still true. I wish I had thought to
+ // write down exactly what this 'wrong reason' was in the first place.
+ expected_results[14] = CERT_ISSUER_NOT_FOUND;
+ expected_results[15] = VERIFIED;
+ expected_results[16] = VERIFIED;
+ expected_results[17] = VERIFIED;
+ expected_results[18] = VERIFIED;
+
+ /************* CHANGE OF TEST RESULT FOR TEST #19 ************************
+ One of the certificates has no attached CRL. By strict X.509 rules, if
+ there is no good CRL in hand, then the certificate shouldn't be used for
+ CA stuff. But while this is usually a good idea, it interferes with simple
+ uses of certificates which shouldn't (IMO) force the use of CRLs. There is
+ no assigned error code for this scenario because I don't consider it to be
+ an error (probably would be something like NO_REVOCATION_DATA_AVAILABLE)
+ **************************************************************************/
+ expected_results[19] = VERIFIED;
+ expected_results[20] = CERT_IS_REVOKED;
+ expected_results[21] = CERT_IS_REVOKED;
+
+ expected_results[22] = CA_CERT_NOT_FOR_CERT_ISSUER;
+ expected_results[23] = CA_CERT_NOT_FOR_CERT_ISSUER;
+ expected_results[24] = VERIFIED;
+ expected_results[25] = CA_CERT_NOT_FOR_CERT_ISSUER;
+ expected_results[26] = VERIFIED;
+ expected_results[27] = VERIFIED;
+ expected_results[28] = CA_CERT_NOT_FOR_CERT_ISSUER;
+ expected_results[29] = CA_CERT_NOT_FOR_CERT_ISSUER;
+ expected_results[30] = VERIFIED;
+
+ expected_results[31] = CA_CERT_NOT_FOR_CRL_ISSUER;
+ expected_results[32] = CA_CERT_NOT_FOR_CRL_ISSUER;
+ expected_results[33] = VERIFIED;
+
+ /*
+ Policy tests: a little trickier because there are other inputs which
+ affect the result.
+
+ In the case of the tests currently in the suite, the default method (with
+ acceptable policy being "any-policy" and with no explict policy required),
+ will almost always result in a verified status. This is not particularly
+ helpful. So, we do several different tests for each test set:
+
+ 1) With the user policy as any-policy and no explicit policy
+ 2) With the user policy as any-policy and an explicit policy required
+ 3) With the user policy as test-policy-1 (2.16.840.1.101.3.1.48.1) and
+ an explict policy required
+ 4) With the user policy as either test-policy-1 or test-policy-2 and an
+ explicit policy required
+
+ This provides reasonably good coverage of the possible outcomes.
+ */
+
+ /*
+ expected_results[34] = VERIFIED;
+ expected_results[34+POLICY_TEST1] = ;
+ expected_results[34+POLICY_TEST2] = ;
+ expected_results[34+POLICY_TEST3] = ;
+ expected_results[35] = VERIFIED;
+ expected_results[35+POLICY_TEST1] = ;
+ expected_results[35+POLICY_TEST2] = ;
+ expected_results[35+POLICY_TEST3] = ;
+ expected_results[36] = VERIFIED;
+ expected_results[36+POLICY_TEST1] = ;
+ expected_results[36+POLICY_TEST2] = ;
+ expected_results[36+POLICY_TEST3] = ;
+ expected_results[37] = VERIFIED;
+ expected_results[37+POLICY_TEST1] = ;
+ expected_results[37+POLICY_TEST2] = ;
+ expected_results[37+POLICY_TEST3] = ;
+ expected_results[38] = VERIFIED;
+ expected_results[38+POLICY_TEST1] = ;
+ expected_results[38+POLICY_TEST2] = ;
+ expected_results[38+POLICY_TEST3] = ;
+ expected_results[39] = VERIFIED;
+ expected_results[39+POLICY_TEST1] = ;
+ expected_results[39+POLICY_TEST2] = ;
+ expected_results[39+POLICY_TEST3] = ;
+ expected_results[40] = VERIFIED;
+ expected_results[40+POLICY_TEST1] = ;
+ expected_results[40+POLICY_TEST2] = ;
+ expected_results[40+POLICY_TEST3] = ;
+ expected_results[41] = VERIFIED;
+ expected_results[41+POLICY_TEST1] = ;
+ expected_results[41+POLICY_TEST2] = ;
+ expected_results[41+POLICY_TEST3] = ;
+ expected_results[42] = VERIFIED;
+ expected_results[42+POLICY_TEST1] = ;
+ expected_results[42+POLICY_TEST2] = ;
+ expected_results[42+POLICY_TEST3] = ;
+ expected_results[43] = VERIFIED;
+ expected_results[43+POLICY_TEST1] = ;
+ expected_results[43+POLICY_TEST2] = ;
+ expected_results[43+POLICY_TEST3] = ;
+ expected_results[44] = VERIFIED;
+ expected_results[44+POLICY_TEST1] = ;
+ expected_results[44+POLICY_TEST2] = ;
+ expected_results[44+POLICY_TEST3] = ;
+ expected_results[45] = EXPLICT_POLICY_REQUIRED;
+ expected_results[45+POLICY_TEST1] = ;
+ expected_results[45+POLICY_TEST2] = ;
+ expected_results[45+POLICY_TEST3] = ;
+ expected_results[46] = ACCEPT;
+ expected_results[46+POLICY_TEST1] = ;
+ expected_results[46+POLICY_TEST2] = ;
+ expected_results[46+POLICY_TEST3] = ;
+ expected_results[47] = EXPLICT_POLICY_REQUIRED;
+ expected_results[47+POLICY_TEST1] = ;
+ expected_results[47+POLICY_TEST2] = ;
+ expected_results[47+POLICY_TEST3] = ;
+ expected_results[48] = VERIFIED;
+ expected_results[48+POLICY_TEST1] = ;
+ expected_results[48+POLICY_TEST2] = ;
+ expected_results[48+POLICY_TEST3] = ;
+ expected_results[49] = VERIFIED;
+ expected_results[49+POLICY_TEST1] = ;
+ expected_results[49+POLICY_TEST2] = ;
+ expected_results[49+POLICY_TEST3] = ;
+ expected_results[50] = VERIFIED;
+ expected_results[50+POLICY_TEST1] = ;
+ expected_results[50+POLICY_TEST2] = ;
+ expected_results[50+POLICY_TEST3] = ;
+ expected_results[51] = VERIFIED;
+ expected_results[51+POLICY_TEST1] = ;
+ expected_results[51+POLICY_TEST2] = ;
+ expected_results[51+POLICY_TEST3] = ;
+ expected_results[52] = VERIFIED;
+ expected_results[52+POLICY_TEST1] = ;
+ expected_results[52+POLICY_TEST2] = ;
+ expected_results[52+POLICY_TEST3] = ;
+ expected_results[53] = VERIFIED;
+ expected_results[53+POLICY_TEST1] = ;
+ expected_results[53+POLICY_TEST2] = ;
+ expected_results[53+POLICY_TEST3] = ;
+ */
+
+ expected_results[54] = CERT_CHAIN_TOO_LONG;
+ expected_results[55] = CERT_CHAIN_TOO_LONG;
+ expected_results[56] = VERIFIED;
+ expected_results[57] = VERIFIED;
+ expected_results[58] = CERT_CHAIN_TOO_LONG;
+ expected_results[59] = CERT_CHAIN_TOO_LONG;
+ expected_results[60] = CERT_CHAIN_TOO_LONG;
+ expected_results[61] = CERT_CHAIN_TOO_LONG;
+ expected_results[62] = VERIFIED;
+ expected_results[63] = VERIFIED;
+
+ expected_results[64] = SIGNATURE_ERROR;
+
+ /************ CHANGE OF TEST RESULT FOR TEST #65 *************************
+ I cannot figure out what exactly the problem here is supposed to be;
+ looking at it by hand, everything seems fine. If someone can explain I
+ would be happy to listen.
+ ************************************************************************/
+ expected_results[65] = VERIFIED;
+ expected_results[66] = CRL_ISSUER_NOT_FOUND;
+
+ /************ CHANGE OF TEST RESULT FOR TEST #67 *************************
+ The test docs say this should be verified. However, the problem being that
+ there is an extra CRL with an unknown issuer. Returning VERIFIED in this
+ case is obviously bad, since the user may well want to know that the CRL
+ in question has no known issuer. So we return CRL_ISSUER_NOT_FOUND instead
+ of VERIFIED. The actual certificate path of course still verifies, but
+ it's kind of an all-or-nothing testing procedure.
+ ************************************************************************/
+ expected_results[67] = CRL_ISSUER_NOT_FOUND;
+
+ expected_results[68] = CERT_IS_REVOKED;
+ expected_results[69] = CERT_IS_REVOKED;
+ expected_results[70] = CERT_IS_REVOKED;
+ expected_results[71] = CERT_IS_REVOKED;
+ expected_results[72] = CRL_HAS_EXPIRED;
+ expected_results[73] = CRL_HAS_EXPIRED;
+ expected_results[74] = VERIFIED;
+
+ /* These tests use weird CRL extensions which aren't supported yet */
+ //expected_results[75] = ;
+ //expected_results[76] = ;
+ }
diff --git a/botan/checks/pk.cpp b/botan/checks/pk.cpp
new file mode 100644
index 0000000..c020052
--- /dev/null
+++ b/botan/checks/pk.cpp
@@ -0,0 +1,775 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_DLIES)
+ #include <botan/dlies.h>
+ #include <botan/kdf.h>
+#endif
+
+#include <botan/filters.h>
+#include <botan/look_pk.h>
+#include <botan/numthry.h>
+using namespace Botan;
+
+#include "common.h"
+#include "validate.h"
+
+namespace {
+
+BigInt to_bigint(const std::string& h)
+ {
+ return BigInt::decode(reinterpret_cast<const byte*>(h.data()),
+ h.length(), BigInt::Hexadecimal);
+ }
+
+}
+
+#define DEBUG 0
+
+namespace {
+
+void dump_data(const SecureVector<byte>& out,
+ const SecureVector<byte>& expected)
+ {
+ Pipe pipe(new Hex_Encoder);
+
+ pipe.process_msg(out);
+ pipe.process_msg(expected);
+ std::cout << "Got: " << pipe.read_all_as_string(0) << std::endl;
+ std::cout << "Exp: " << pipe.read_all_as_string(1) << std::endl;
+ }
+
+void validate_decryption(PK_Decryptor* d, const std::string& algo,
+ const SecureVector<byte> ctext,
+ const SecureVector<byte> ptext,
+ bool& failure)
+ {
+ SecureVector<byte> decrypted = d->decrypt(ctext);
+ if(decrypted != ptext)
+ {
+ std::cout << "FAILED (decrypt): " << algo << std::endl;
+ dump_data(decrypted, ptext);
+ failure = true;
+ }
+ delete d;
+ }
+
+void validate_encryption(PK_Encryptor* e, PK_Decryptor* d,
+ const std::string& algo, const std::string& input,
+ const std::string& random, const std::string& exp,
+ bool& failure)
+ {
+ SecureVector<byte> message = decode_hex(input);
+ SecureVector<byte> expected = decode_hex(exp);
+ Fixed_Output_RNG rng(decode_hex(random));
+
+ SecureVector<byte> out = e->encrypt(message, rng);
+ if(out != expected)
+ {
+ std::cout << "FAILED (encrypt): " << algo << std::endl;
+ dump_data(out, expected);
+ failure = true;
+ }
+
+ validate_decryption(d, algo, out, message, failure);
+ delete e;
+ }
+
+void validate_signature(PK_Verifier* v, PK_Signer* s, const std::string& algo,
+ const std::string& input, const std::string& random,
+ const std::string& exp, bool& failure)
+ {
+ SecureVector<byte> message = decode_hex(input);
+
+ SecureVector<byte> expected = decode_hex(exp);
+
+ Fixed_Output_RNG rng(decode_hex(random));
+ SecureVector<byte> sig = s->sign_message(message, message.size(), rng);
+
+ if(sig != expected)
+ {
+ std::cout << "FAILED (sign): " << algo << std::endl;
+ dump_data(sig, expected);
+ failure = true;
+ }
+
+ if(!v->verify_message(message, message.size(), sig, sig.size()))
+ {
+ std::cout << "FAILED (verify): " << algo << std::endl;
+ failure = true;
+ }
+
+ /* This isn't a very thorough testing method, but it will hopefully
+ catch any really horrible errors */
+ sig[0]++;
+ if(v->verify_message(message, message.size(), sig, sig.size()))
+ {
+ std::cout << "FAILED (accepted bad sig): " << algo << std::endl;
+ failure = true;
+ }
+
+ delete v;
+ delete s;
+ }
+
+void validate_kas(PK_Key_Agreement* kas, const std::string& algo,
+ const SecureVector<byte>& pubkey, const std::string& output,
+ u32bit keylen, bool& failure)
+ {
+ SecureVector<byte> expected = decode_hex(output);
+
+ SecureVector<byte> got = kas->derive_key(keylen,
+ pubkey, pubkey.size()).bits_of();
+
+ if(got != expected)
+ {
+ std::cout << "FAILED: " << algo << std::endl;
+ dump_data(got, expected);
+ failure = true;
+ }
+
+ delete kas;
+ }
+
+u32bit validate_rsa_enc_pkcs8(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 4 && str.size() != 5)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_RSA)
+ std::string pass;
+ if(str.size() == 5) pass = str[4];
+ strip_newlines(pass); /* it will have a newline thanks to the messy
+ decoding method we use */
+
+ DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
+ str[0].length());
+
+ std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
+
+ RSA_PrivateKey* rsapriv = dynamic_cast<RSA_PrivateKey*>(privkey.get());
+ if(!rsapriv)
+ throw Invalid_Argument("Bad key load for RSA key");
+
+ RSA_PublicKey* rsapub = dynamic_cast<RSA_PublicKey*>(rsapriv);
+
+ std::string eme = algo.substr(12, std::string::npos);
+
+ PK_Encryptor* e = get_pk_encryptor(*rsapub, eme);
+ PK_Decryptor* d = get_pk_decryptor(*rsapriv, eme);
+
+ bool failure = false;
+ validate_encryption(e, d, algo, str[1], str[2], str[3], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rsa_enc(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 6)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_RSA)
+ RSA_PrivateKey privkey(rng,
+ to_bigint(str[1]), to_bigint(str[2]),
+ to_bigint(str[0]));
+
+ RSA_PublicKey pubkey = privkey;
+
+ std::string eme = algo.substr(6, std::string::npos);
+
+ PK_Encryptor* e = get_pk_encryptor(pubkey, eme);
+ PK_Decryptor* d = get_pk_decryptor(privkey, eme);
+
+ bool failure = false;
+ validate_encryption(e, d, algo, str[3], str[4], str[5], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_elg_enc(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 6 && str.size() != 7)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ DL_Group domain(to_bigint(str[0]), to_bigint(str[1]));
+ ElGamal_PrivateKey privkey(rng, domain, to_bigint(str[2]));
+ ElGamal_PublicKey pubkey = privkey;
+
+ std::string eme = algo.substr(8, std::string::npos);
+
+ PK_Decryptor* d = get_pk_decryptor(privkey, eme);
+
+ bool failure = false;
+ if(str.size() == 7)
+ {
+ PK_Encryptor* e = get_pk_encryptor(pubkey, eme);
+ validate_encryption(e, d, algo, str[4], str[5], str[6], failure);
+ }
+ else
+ validate_decryption(d, algo, decode_hex(str[5]),
+ decode_hex(str[4]), failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rsa_sig(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 6)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_RSA)
+ RSA_PrivateKey privkey(rng,
+ to_bigint(str[1]), to_bigint(str[2]),
+ to_bigint(str[0]));
+
+ RSA_PublicKey pubkey = privkey;
+
+ std::string emsa = algo.substr(7, std::string::npos);
+
+ PK_Verifier* v = get_pk_verifier(pubkey, emsa);
+ PK_Signer* s = get_pk_signer(privkey, emsa);
+ bool failure = false;
+ validate_signature(v, s, algo, str[3], str[4], str[5], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rsa_ver(const std::string& algo,
+ const std::vector<std::string>& str)
+ {
+ if(str.size() != 5) /* is actually 4, parse() adds an extra empty one */
+ throw Exception("Invalid input from pk_valid.dat");
+
+#if defined(BOTAN_HAS_RSA)
+ RSA_PublicKey key(to_bigint(str[1]), to_bigint(str[0]));
+
+ std::string emsa = algo.substr(6, std::string::npos);
+
+ std::auto_ptr<PK_Verifier> v(get_pk_verifier(key, emsa));
+
+ SecureVector<byte> msg = decode_hex(str[2]);
+ SecureVector<byte> sig = decode_hex(str[3]);
+
+ bool passed = true;
+ passed = v->verify_message(msg, msg.size(), sig, sig.size());
+ return (passed ? 0 : 1);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rsa_ver_x509(const std::string& algo,
+ const std::vector<std::string>& str)
+ {
+ if(str.size() != 5) /* is actually 3, parse() adds extra empty ones */
+ throw Exception("Invalid input from pk_valid.dat");
+
+#if defined(BOTAN_HAS_RSA)
+ DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
+ str[0].length());
+
+ std::auto_ptr<Public_Key> key(X509::load_key(keysource));
+
+ RSA_PublicKey* rsakey = dynamic_cast<RSA_PublicKey*>(key.get());
+
+ if(!rsakey)
+ throw Invalid_Argument("Bad key load for RSA public key");
+
+ std::string emsa = algo.substr(11, std::string::npos);
+
+ std::auto_ptr<PK_Verifier> v(get_pk_verifier(*rsakey, emsa));
+
+ SecureVector<byte> msg = decode_hex(str[1]);
+ SecureVector<byte> sig = decode_hex(str[2]);
+
+ bool passed = v->verify_message(msg, msg.size(), sig, sig.size());
+ return (passed ? 0 : 1);
+
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rw_ver(const std::string& algo,
+ const std::vector<std::string>& str)
+ {
+ if(str.size() != 5)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+
+#if defined(BOTAN_HAS_RW)
+ RW_PublicKey key(to_bigint(str[1]), to_bigint(str[0]));
+
+ std::string emsa = algo.substr(5, std::string::npos);
+
+ std::auto_ptr<PK_Verifier> v(get_pk_verifier(key, emsa));
+
+ SecureVector<byte> msg = decode_hex(str[2]);
+ SecureVector<byte> sig = decode_hex(str[3]);
+
+ bool passed = true;
+ passed = v->verify_message(msg, msg.size(), sig, sig.size());
+ return (passed ? 0 : 1);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_rw_sig(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 6)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_RW)
+ RW_PrivateKey privkey(rng, to_bigint(str[1]), to_bigint(str[2]),
+ to_bigint(str[0]));
+ RW_PublicKey pubkey = privkey;
+
+ std::string emsa = algo.substr(3, std::string::npos);
+
+ PK_Verifier* v = get_pk_verifier(pubkey, emsa);
+ PK_Signer* s = get_pk_signer(privkey, emsa);
+
+ bool failure = false;
+ validate_signature(v, s, algo, str[3], str[4], str[5], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_dsa_sig(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 4 && str.size() != 5)
+ throw Exception("Invalid input from pk_valid.dat");
+
+ std::string pass;
+ if(str.size() == 5) pass = str[4];
+ strip_newlines(pass); /* it will have a newline thanks to the messy
+ decoding method we use */
+
+#if defined(BOTAN_HAS_DSA)
+
+ DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
+ str[0].length());
+
+ std::auto_ptr<Private_Key> privkey(PKCS8::load_key(keysource, rng, pass));
+
+ DSA_PrivateKey* dsapriv = dynamic_cast<DSA_PrivateKey*>(privkey.get());
+ if(!dsapriv)
+ throw Invalid_Argument("Bad key load for DSA private key");
+
+ DSA_PublicKey* dsapub = dynamic_cast<DSA_PublicKey*>(dsapriv);
+
+ std::string emsa = algo.substr(4, std::string::npos);
+
+ PK_Verifier* v = get_pk_verifier(*dsapub, emsa);
+ PK_Signer* s = get_pk_signer(*dsapriv, emsa);
+
+ bool failure = false;
+ validate_signature(v, s, algo, str[1], str[2], str[3], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_dsa_ver(const std::string& algo,
+ const std::vector<std::string>& str)
+ {
+ if(str.size() != 5) /* is actually 3, parse() adds extra empty ones */
+ throw Exception("Invalid input from pk_valid.dat");
+
+ DataSource_Memory keysource(reinterpret_cast<const byte*>(str[0].c_str()),
+ str[0].length());
+
+
+#if defined(BOTAN_HAS_DSA)
+ std::auto_ptr<Public_Key> key(X509::load_key(keysource));
+
+ DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get());
+
+ if(!dsakey)
+ throw Invalid_Argument("Bad key load for DSA public key");
+
+ std::string emsa = algo.substr(7, std::string::npos);
+
+ std::auto_ptr<PK_Verifier> v(get_pk_verifier(*dsakey, emsa));
+
+ SecureVector<byte> msg = decode_hex(str[1]);
+ SecureVector<byte> sig = decode_hex(str[2]);
+
+ v->set_input_format(DER_SEQUENCE);
+ bool passed = v->verify_message(msg, msg.size(), sig, sig.size());
+ return (passed ? 0 : 1);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_nr_sig(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 8)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+
+ DL_Group domain(to_bigint(str[0]), to_bigint(str[1]), to_bigint(str[2]));
+ NR_PrivateKey privkey(rng, domain, to_bigint(str[4]));
+ NR_PublicKey pubkey = privkey;
+
+ std::string emsa = algo.substr(3, std::string::npos);
+
+ PK_Verifier* v = get_pk_verifier(pubkey, emsa);
+ PK_Signer* s = get_pk_signer(privkey, emsa);
+
+ bool failure = false;
+ validate_signature(v, s, algo, str[5], str[6], str[7], failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_dh(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 5 && str.size() != 6)
+ throw Exception("Invalid input from pk_valid.dat");
+
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DL_Group domain(to_bigint(str[0]), to_bigint(str[1]));
+
+ DH_PrivateKey mykey(rng, domain, to_bigint(str[2]));
+ DH_PublicKey otherkey(domain, to_bigint(str[3]));
+
+ std::string kdf = algo.substr(3, std::string::npos);
+
+ u32bit keylen = 0;
+ if(str.size() == 6)
+ keylen = to_u32bit(str[5]);
+
+ PK_Key_Agreement* kas = get_pk_kas(mykey, kdf);
+
+ bool failure = false;
+ validate_kas(kas, algo, otherkey.public_value(),
+ str[4], keylen, failure);
+ return (failure ? 1 : 0);
+#endif
+
+ return 2;
+ }
+
+u32bit validate_dlies(const std::string& algo,
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
+ {
+ if(str.size() != 6)
+ throw Exception("Invalid input from pk_valid.dat");
+
+#if defined(BOTAN_HAS_DLIES)
+ DL_Group domain(to_bigint(str[0]), to_bigint(str[1]));
+
+ DH_PrivateKey from(rng, domain, to_bigint(str[2]));
+ DH_PrivateKey to(rng, domain, to_bigint(str[3]));
+
+ const std::string opt_str = algo.substr(6, std::string::npos);
+
+ std::vector<std::string> options = split_on(opt_str, '/');
+
+ if(options.size() != 3)
+ throw Exception("DLIES needs three options: " + opt_str);
+
+ MessageAuthenticationCode* mac = get_mac(options[1]);
+ u32bit mac_key_len = to_u32bit(options[2]);
+
+ PK_Decryptor* d =
+ new DLIES_Decryptor(to,
+ get_kdf(options[0]),
+ mac->clone(), mac_key_len);
+
+ DLIES_Encryptor* e =
+ new DLIES_Encryptor(from,
+ get_kdf(options[0]),
+ mac, mac_key_len);
+
+ e->set_other_key(to.public_value());
+
+ std::string empty = "";
+ bool failure = false;
+ validate_encryption(e, d, algo, str[4], empty, str[5], failure);
+ return (failure ? 1 : 0);
+#else
+ return 2;
+#endif
+ }
+
+void do_pk_keygen_tests(RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing PK key generation: " << std::flush;
+
+#define DL_SIG_KEY(TYPE, GROUP) \
+ { \
+ TYPE key(rng, DL_Group(GROUP)); \
+ key.check_key(rng, true); \
+ std::cout << '.' << std::flush; \
+ }
+
+#define DL_ENC_KEY(TYPE, GROUP) \
+ { \
+ TYPE key(rng, DL_Group(GROUP)); \
+ key.check_key(rng, true); \
+ std::cout << '.' << std::flush; \
+ }
+
+#define DL_KEY(TYPE, GROUP) \
+ { \
+ TYPE key(rng, DL_Group(GROUP)); \
+ key.check_key(rng, true); \
+ std::cout << '.' << std::flush; \
+ }
+
+#if defined(BOTAN_HAS_RSA)
+ {
+ RSA_PrivateKey rsa1024(rng, 1024);
+ rsa1024.check_key(rng, true);
+ std::cout << '.' << std::flush;
+ }
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ {
+ RW_PrivateKey rw1024(rng, 1024);
+ rw1024.check_key(rng, true);
+ std::cout << '.' << std::flush;
+ }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/512");
+ DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/768");
+ DL_SIG_KEY(DSA_PrivateKey, "dsa/jce/1024");
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DL_KEY(DH_PrivateKey, "modp/ietf/768");
+ DL_KEY(DH_PrivateKey, "modp/ietf/2048");
+ DL_KEY(DH_PrivateKey, "dsa/jce/1024");
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ DL_SIG_KEY(NR_PrivateKey, "dsa/jce/512");
+ DL_SIG_KEY(NR_PrivateKey, "dsa/jce/768");
+ DL_SIG_KEY(NR_PrivateKey, "dsa/jce/1024");
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ DL_ENC_KEY(ElGamal_PrivateKey, "modp/ietf/768");
+ DL_ENC_KEY(ElGamal_PrivateKey, "modp/ietf/1024");
+ DL_ENC_KEY(ElGamal_PrivateKey, "dsa/jce/1024");
+#endif
+
+ std::cout << std::endl;
+ }
+
+}
+
+u32bit do_pk_validation_tests(const std::string& filename,
+ RandomNumberGenerator& rng)
+ {
+ std::ifstream test_data(filename.c_str());
+
+ if(!test_data)
+ throw Botan::Stream_IO_Error("Couldn't open test file " + filename);
+
+ u32bit errors = 0, alg_count = 0;
+ std::string algorithm, print_algorithm;
+
+ while(!test_data.eof())
+ {
+ if(test_data.bad() || test_data.fail())
+ throw Botan::Stream_IO_Error("File I/O error reading from " +
+ filename);
+
+ std::string line;
+ std::getline(test_data, line);
+
+ strip_comments(line);
+ if(line.size() == 0) continue;
+
+ // Do line continuation
+ while(line[line.size()-1] == '\\' && !test_data.eof())
+ {
+ line.replace(line.size()-1, 1, "");
+ std::string nextline;
+ std::getline(test_data, nextline);
+ strip_comments(nextline);
+ if(nextline.size() == 0) continue;
+ line.push_back('\n');
+ line += nextline;
+ }
+
+ if(line[0] == '[' && line[line.size() - 1] == ']')
+ {
+ std::string old_algo = print_algorithm;
+ algorithm = line.substr(1, line.size() - 2);
+ print_algorithm = algorithm;
+ if(print_algorithm.find("_PKCS8") != std::string::npos)
+ print_algorithm.replace(print_algorithm.find("_PKCS8"), 6, "");
+ if(print_algorithm.find("_X509") != std::string::npos)
+ print_algorithm.replace(print_algorithm.find("_X509"), 5, "");
+ if(print_algorithm.find("_VA") != std::string::npos)
+ print_algorithm.replace(print_algorithm.find("_VA"), 3, "");
+
+ if(old_algo != print_algorithm && old_algo != "")
+ {
+ std::cout << std::endl;
+ alg_count = 0;
+ }
+
+ if(old_algo != print_algorithm)
+ std::cout << "Testing " << print_algorithm << ": ";
+ continue;
+ }
+
+ std::vector<std::string> substr = parse(line);
+
+#if DEBUG
+ std::cout << "Testing: " << print_algorithm << std::endl;
+#endif
+
+ u32bit new_errors = 0;
+
+ try
+ {
+
+ if(algorithm.find("DSA/") != std::string::npos)
+ new_errors = validate_dsa_sig(algorithm, substr, rng);
+ else if(algorithm.find("DSA_VA/") != std::string::npos)
+ new_errors = validate_dsa_ver(algorithm, substr);
+
+ else if(algorithm.find("RSAES_PKCS8/") != std::string::npos)
+ new_errors = validate_rsa_enc_pkcs8(algorithm, substr, rng);
+ else if(algorithm.find("RSAVA_X509/") != std::string::npos)
+ new_errors = validate_rsa_ver_x509(algorithm, substr);
+
+ else if(algorithm.find("RSAES/") != std::string::npos)
+ new_errors = validate_rsa_enc(algorithm, substr, rng);
+ else if(algorithm.find("RSASSA/") != std::string::npos)
+ new_errors = validate_rsa_sig(algorithm, substr, rng);
+ else if(algorithm.find("RSAVA/") != std::string::npos)
+ new_errors = validate_rsa_ver(algorithm, substr);
+ else if(algorithm.find("RWVA/") != std::string::npos)
+ new_errors = validate_rw_ver(algorithm, substr);
+ else if(algorithm.find("RW/") != std::string::npos)
+ new_errors = validate_rw_sig(algorithm, substr, rng);
+ else if(algorithm.find("NR/") != std::string::npos)
+ new_errors = validate_nr_sig(algorithm, substr, rng);
+ else if(algorithm.find("ElGamal/") != std::string::npos)
+ new_errors = validate_elg_enc(algorithm, substr, rng);
+ else if(algorithm.find("DH/") != std::string::npos)
+ new_errors = validate_dh(algorithm, substr, rng);
+ else if(algorithm.find("DLIES/") != std::string::npos)
+ new_errors = validate_dlies(algorithm, substr, rng);
+ else
+ std::cout << "WARNING: Unknown PK algorithm "
+ << algorithm << std::endl;
+
+ if(new_errors == 0) // OK
+ std::cout << '.';
+ else if(new_errors == 1) // test failed
+ std::cout << 'X';
+ else if(new_errors == 2) // unknown algo
+ std::cout << '?';
+
+ std::cout.flush();
+
+ alg_count++;
+ if(new_errors == 1)
+ errors += new_errors;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ if(new_errors == 1)
+ std::cout << "ERROR: \"" << algorithm << "\" failed test #"
+ << std::dec << alg_count << std::endl;
+ }
+
+ std::cout << std::endl;
+
+ errors += do_gfpmath_tests(rng);
+ do_ec_tests(rng);
+ errors += do_ecdsa_tests(rng);
+ errors += do_eckaeg_tests(rng);
+ do_pk_keygen_tests(rng);
+ do_x509_tests(rng);
+
+ return errors;
+ }
+
diff --git a/botan/checks/pk_bench.cpp b/botan/checks/pk_bench.cpp
new file mode 100644
index 0000000..88a72af
--- /dev/null
+++ b/botan/checks/pk_bench.cpp
@@ -0,0 +1,682 @@
+#include <botan/pkcs8.h>
+#include <botan/mem_ops.h>
+#include <botan/look_pk.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_DLIES)
+ #include <botan/dlies.h>
+ #include <botan/kdf2.h>
+ #include <botan/hmac.h>
+ #include <botan/sha160.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg.h>
+#endif
+
+using namespace Botan;
+
+#include "common.h"
+#include "timer.h"
+#include "bench.h"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+
+namespace {
+
+void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec,
+ Timer& enc_timer, Timer& dec_timer,
+ RandomNumberGenerator& rng,
+ u32bit runs, double seconds)
+ {
+ SecureVector<byte> plaintext, ciphertext;
+
+ for(u32bit i = 0; i != runs; ++i)
+ {
+ if(enc_timer.seconds() < seconds || ciphertext.size() == 0)
+ {
+ plaintext.create(enc.maximum_input_size());
+
+ // Ensure for Raw, etc, it stays large
+ if((i % 100) == 0)
+ {
+ rng.randomize(plaintext.begin(), plaintext.size());
+ plaintext[0] |= 0x80;
+ }
+
+ enc_timer.start();
+ ciphertext = enc.encrypt(plaintext, rng);
+ enc_timer.stop();
+ }
+
+ if(dec_timer.seconds() < seconds)
+ {
+ dec_timer.start();
+ SecureVector<byte> plaintext_out = dec.decrypt(ciphertext);
+ dec_timer.stop();
+
+ if(plaintext_out != plaintext)
+ { // has never happened...
+ std::cerr << "Contents mismatched on decryption during benchmark!\n";
+ }
+ }
+ }
+ }
+
+void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig,
+ Timer& verify_timer, Timer& sig_timer,
+ RandomNumberGenerator& rng,
+ u32bit runs, double seconds)
+ {
+ SecureVector<byte> message, signature, sig_random;
+
+ for(u32bit i = 0; i != runs; ++i)
+ {
+ if(sig_timer.seconds() < seconds || signature.size() == 0)
+ {
+ if((i % 100) == 0)
+ {
+ message.create(48);
+ rng.randomize(message.begin(), message.size());
+ }
+
+ sig_timer.start();
+ signature = sig.sign_message(message, rng);
+ sig_timer.stop();
+ }
+
+ if(verify_timer.seconds() < seconds)
+ {
+ verify_timer.start();
+ bool verified = ver.verify_message(message, signature);
+ verify_timer.stop();
+
+ if(!verified)
+ std::cerr << "Signature verification failure\n";
+
+ if((i % 100) == 0)
+ {
+ sig_random.create(signature.size());
+ rng.randomize(sig_random, sig_random.size());
+
+ verify_timer.start();
+ bool verified2 = ver.verify_message(message, sig_random);
+ verify_timer.stop();
+
+ if(verified2)
+ std::cerr << "Signature verification failure (bad sig OK)\n";
+ }
+ }
+ }
+ }
+
+/*
+ Between benchmark_rsa_rw + benchmark_dsa_nr:
+ Type of the key
+ Arguments to the constructor (A list of some arbitrary type?)
+ Type of padding
+*/
+
+#if defined(BOTAN_HAS_RSA)
+void benchmark_rsa(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+
+ size_t keylens[] = { 512, 1024, 2048, 4096, 6144, 8192, 0 };
+
+ for(size_t i = 0; keylens[i]; ++i)
+ {
+ size_t keylen = keylens[i];
+
+ //const std::string sig_padding = "EMSA4(SHA-1)";
+ //const std::string enc_padding = "EME1(SHA-1)";
+ const std::string sig_padding = "EMSA-PKCS1-v1_5(SHA-1)";
+ const std::string enc_padding = "EME-PKCS1-v1_5";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(sig_padding + " verify");
+ Timer sig_timer(sig_padding + " signature");
+ Timer enc_timer(enc_padding + " encrypt");
+ Timer dec_timer(enc_padding + " decrypt");
+
+ try
+ {
+
+#if 0
+ // for profiling
+ PKCS8_PrivateKey* pkcs8_key =
+ PKCS8::load_key("rsa/" + to_string(keylen) + ".pem", rng);
+ RSA_PrivateKey* key_ptr = dynamic_cast<RSA_PrivateKey*>(pkcs8_key);
+
+ RSA_PrivateKey key = *key_ptr;
+#else
+ keygen_timer.start();
+ RSA_PrivateKey key(rng, keylen);
+ keygen_timer.stop();
+#endif
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(key, enc_padding));
+ std::auto_ptr<PK_Decryptor> dec(get_pk_decryptor(key, enc_padding));
+ benchmark_enc_dec(*enc, *dec, enc_timer, dec_timer, rng, 10000, seconds);
+
+ std::auto_ptr<PK_Signer> sig(get_pk_signer(key, sig_padding));
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(key, sig_padding));
+ benchmark_sig_ver(*ver, *sig, verify_timer,
+ sig_timer, rng, 10000, seconds);
+ }
+
+ const std::string rsa_keylen = "RSA-" + to_string(keylen);
+
+ report.report(rsa_keylen, keygen_timer);
+ report.report(rsa_keylen, verify_timer);
+ report.report(rsa_keylen, sig_timer);
+ report.report(rsa_keylen, enc_timer);
+ report.report(rsa_keylen, dec_timer);
+ }
+ catch(Stream_IO_Error)
+ {
+ }
+ catch(Exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+ }
+
+ }
+#endif
+
+#if defined(BOTAN_HAS_RW)
+void benchmark_rw(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+
+ const u32bit keylens[] = { 512, 1024, 2048, 4096, 6144, 8192, 0 };
+
+ for(size_t j = 0; keylens[j]; j++)
+ {
+ u32bit keylen = keylens[j];
+
+ std::string padding = "EMSA2(SHA-256)";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ RW_PrivateKey key(rng, keylen);
+ keygen_timer.stop();
+
+ std::auto_ptr<PK_Signer> sig(get_pk_signer(key, padding));
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(key, padding));
+
+ benchmark_sig_ver(*ver, *sig, verify_timer, sig_timer, rng, 10000, seconds);
+ }
+
+ const std::string nm = "RW-" + to_string(keylen);
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+
+void benchmark_ecdsa(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "1.3.132.0.6", // secp112r1
+ "1.3.132.0.28", // secp128r1
+ "1.3.132.0.30", // secp160r2
+ "1.3.132.0.33", // secp224r1
+ "1.3.132.0.34", // secp384r1
+ "1.3.132.0.35", // secp512r1
+ NULL };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ EC_Domain_Params params = get_EC_Dom_Pars_by_oid(domains[j]);
+
+ u32bit pbits = params.get_curve().get_p().bits();
+
+ u32bit hashbits = pbits;
+
+ if(hashbits < 160)
+ hashbits = 160;
+ if(hashbits == 521)
+ hashbits = 512;
+
+ const std::string padding = "EMSA1(SHA-" + to_string(hashbits) + ")";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ ECDSA_PrivateKey key(rng, params);
+ keygen_timer.stop();
+
+ std::auto_ptr<PK_Signer> sig(get_pk_signer(key, padding));
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(key, padding));
+
+ benchmark_sig_ver(*ver, *sig, verify_timer,
+ sig_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = "ECDSA-" + to_string(pbits);
+
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+ }
+
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+
+void benchmark_eckaeg(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "1.3.132.0.6", // secp112r1
+ "1.3.132.0.28", // secp128r1
+ "1.3.132.0.30", // secp160r2
+ "1.3.132.0.33", // secp224r1
+ "1.3.132.0.34", // secp384r1
+ "1.3.132.0.35", // secp512r1
+ NULL };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ EC_Domain_Params params = get_EC_Dom_Pars_by_oid(domains[j]);
+
+ u32bit pbits = params.get_curve().get_p().bits();
+
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ while(kex_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ ECKAEG_PrivateKey eckaeg1(rng, params);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ ECKAEG_PrivateKey eckaeg2(rng, params);
+ keygen_timer.stop();
+
+ ECKAEG_PublicKey pub1(eckaeg1);
+ ECKAEG_PublicKey pub2(eckaeg2);
+
+ SecureVector<byte> secret1, secret2;
+
+ for(u32bit i = 0; i != 1000; ++i)
+ {
+ if(kex_timer.seconds() > seconds)
+ break;
+
+ kex_timer.start();
+ secret1 = eckaeg1.derive_key(pub2);
+ kex_timer.stop();
+
+ kex_timer.start();
+ secret2 = eckaeg2.derive_key(pub1);
+ kex_timer.stop();
+
+ if(secret1 != secret2)
+ std::cerr << "ECKAEG secrets did not match, bug in the library!?!\n";
+ }
+ }
+
+ const std::string nm = "ECKAEG-" + to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, kex_timer);
+ }
+ }
+
+#endif
+
+template<typename PRIV_KEY_TYPE>
+void benchmark_dsa_nr(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL) || defined(BOTAN_HAS_DSA)
+ const char* domains[] = { "dsa/jce/512",
+ "dsa/jce/768",
+ "dsa/jce/1024",
+ "dsa/botan/2048",
+ "dsa/botan/3072",
+ NULL };
+
+ const std::string algo_name = PRIV_KEY_TYPE().algo_name();
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ u32bit pbits = to_u32bit(split_on(domains[j], '/')[2]);
+ u32bit qbits = (pbits <= 1024) ? 160 : 256;
+
+ const std::string padding = "EMSA1(SHA-" + to_string(qbits) + ")";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ PRIV_KEY_TYPE key(rng, group);
+ keygen_timer.stop();
+
+ std::auto_ptr<PK_Signer> sig(get_pk_signer(key, padding));
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(key, padding));
+
+ benchmark_sig_ver(*ver, *sig, verify_timer,
+ sig_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = algo_name + "-" + to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+#endif
+ }
+
+#ifdef BOTAN_HAS_DIFFIE_HELLMAN
+void benchmark_dh(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/768",
+ "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ NULL };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ while(kex_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ DH_PrivateKey dh1(rng, group);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ DH_PrivateKey dh2(rng, group);
+ keygen_timer.stop();
+
+ DH_PublicKey pub1(dh1);
+ DH_PublicKey pub2(dh2);
+
+ SecureVector<byte> secret1, secret2;
+
+ for(u32bit i = 0; i != 1000; ++i)
+ {
+ if(kex_timer.seconds() > seconds)
+ break;
+
+ kex_timer.start();
+ secret1 = dh1.derive_key(pub2);
+ kex_timer.stop();
+
+ kex_timer.start();
+ secret2 = dh2.derive_key(pub1);
+ kex_timer.stop();
+
+ if(secret1 != secret2)
+ std::cerr << "DH secrets did not match, bug in the library!?!\n";
+ }
+ }
+
+ const std::string nm = "DH-" + split_on(domains[j], '/')[2];
+ report.report(nm, keygen_timer);
+ report.report(nm, kex_timer);
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN) && defined(BOTAN_HAS_DLIES)
+void benchmark_dlies(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/768",
+ "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ NULL };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ Timer enc_timer("encrypt");
+ Timer dec_timer("decrypt");
+
+ while(enc_timer.seconds() < seconds || dec_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ DH_PrivateKey dh1_priv(rng, group);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ DH_PrivateKey dh2_priv(rng, group);
+ keygen_timer.stop();
+
+ DH_PublicKey dh2_pub(dh2_priv);
+
+ DLIES_Encryptor dlies_enc(dh1_priv,
+ new KDF2(new SHA_160),
+ new HMAC(new SHA_160));
+
+ dlies_enc.set_other_key(dh2_pub.public_value());
+
+ DLIES_Decryptor dlies_dec(dh2_priv,
+ new KDF2(new SHA_160),
+ new HMAC(new SHA_160));
+
+ benchmark_enc_dec(dlies_enc, dlies_dec,
+ enc_timer, dec_timer, rng,
+ 1000, seconds);
+ }
+
+ const std::string nm = "DLIES-" + split_on(domains[j], '/')[2];
+ report.report(nm, keygen_timer);
+ report.report(nm, enc_timer);
+ report.report(nm, dec_timer);
+ }
+ }
+#endif
+
+#ifdef BOTAN_HAS_ELGAMAL
+void benchmark_elg(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/768",
+ "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ NULL };
+
+ const std::string algo_name = "ElGamal";
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ u32bit pbits = to_u32bit(split_on(domains[j], '/')[2]);
+
+ const std::string padding = "EME1(SHA-1)";
+
+ Timer keygen_timer("keygen");
+ Timer enc_timer(padding + " encrypt");
+ Timer dec_timer(padding + " decrypt");
+
+ while(enc_timer.seconds() < seconds ||
+ dec_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ ElGamal_PrivateKey key(rng, group);
+ keygen_timer.stop();
+
+ std::auto_ptr<PK_Decryptor> dec(get_pk_decryptor(key, padding));
+ std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(key, padding));
+
+ benchmark_enc_dec(*enc, *dec, enc_timer, dec_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = algo_name + "-" + to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, enc_timer);
+ report.report(nm, dec_timer);
+ }
+ }
+#endif
+
+}
+
+void bench_pk(RandomNumberGenerator& rng,
+ const std::string& algo, bool, double seconds)
+ {
+ /*
+ There is some strangeness going on here. It looks like algorithms
+ at the end take some kind of penalty. For example, running the RW tests
+ first got a result of:
+ RW-1024: 148.14 ms / private operation
+ but running them last output:
+ RW-1024: 363.54 ms / private operation
+
+ I think it's from memory fragmentation in the allocators, but I'm
+ not really sure. Need to investigate.
+
+ Until then, I've basically ordered the tests in order of most important
+ algorithms (RSA, DSA) to least important (NR, RW).
+
+ This strange behaviour does not seem to occur with DH (?)
+
+ To get more accurate runs, use --bench-algo (RSA|DSA|DH|ELG|NR); in this
+ case the distortion is less than 5%, which is good enough.
+
+ We do random keys with the DL schemes, since it's so easy and fast to
+ generate keys for them. For RSA and RW, we load the keys from a file. The
+ RSA keys are stored in a PKCS #8 structure, while RW is stored in a more
+ ad-hoc format (the RW algorithm has no assigned OID that I know of, so
+ there is no way to encode a RW key into a PKCS #8 structure).
+ */
+
+ global_state().set_option("pk/test/private_gen", "basic");
+
+ Benchmark_Report report;
+
+#if defined(BOTAN_HAS_RSA)
+ if(algo == "All" || algo == "RSA")
+ benchmark_rsa(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(algo == "All" || algo == "DSA")
+ benchmark_dsa_nr<DSA_PrivateKey>(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(algo == "All" || algo == "ECDSA")
+ benchmark_ecdsa(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ if(algo == "All" || algo == "ECKAEG")
+ benchmark_eckaeg(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(algo == "All" || algo == "DH")
+ benchmark_dh(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN) && defined(BOTAN_HAS_DLIES)
+ if(algo == "All" || algo == "DLIES")
+ benchmark_dlies(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(algo == "All" || algo == "ELG" || algo == "ElGamal")
+ benchmark_elg(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(algo == "All" || algo == "NR")
+ benchmark_dsa_nr<NR_PrivateKey>(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(algo == "All" || algo == "RW")
+ benchmark_rw(rng, seconds, report);
+#endif
+ }
diff --git a/botan/checks/pk_valid.dat b/botan/checks/pk_valid.dat
new file mode 100644
index 0000000..1e2a84c
--- /dev/null
+++ b/botan/checks/pk_valid.dat
@@ -0,0 +1,4808 @@
+# Validation File for Public Key Algorithms
+# Not as comprehensive as it should be
+
+# RSA Format: exponent:p:q:message:nonce:output
+[RSAES/Raw]
+# Tests for keys 512,520,...,1016,1024 bits, and random messages
+3ED19:\
+D987D71CC924C479D30CD88570A626E15F0862A9A138874F7016684216984215:\
+C5660F33AB35E41CB10A30D3A58354ADB5CC3243342C22E1A5BCCB79C391A533:\
+098825DEC8B4DAB5765348CEE92C4C6A527A172E4A4311399B0B02914E75822F1789B583180AD\
+EADE98C200B7B7670D7B9FBA19946F3D8A7FC8322F80CF67C::\
+A54A45C5F534A6C727212802CD4B2A0B9D0069EFE32B1D239D3B13958BC49711E1CA5BB499FBF\
+7402B6006E654C719C5FB7614C7C00699866B38445228EC7663
+
+3ED19:\
+C5660F33AB35E41CB10A30D3A58354ADB5CC3243342C22E1A5BCCB79C391A533:\
+D987D71CC924C479D30CD88570A626E15F0862A9A138874F7016684216984215:\
+098825DEC8B4DAB5765348CEE92C4C6A527A172E4A4311399B0B02914E75822F1789B583180AD\
+EADE98C200B7B7670D7B9FBA19946F3D8A7FC8322F80CF67C::\
+A54A45C5F534A6C727212802CD4B2A0B9D0069EFE32B1D239D3B13958BC49711E1CA5BB499FBF\
+7402B6006E654C719C5FB7614C7C00699866B38445228EC7663
+
+1F1DD:\
+DA78C89EBDDB277831DC1591C26AAB1C11CE9721DBB3AAFAE8F73178BC2D60055:\
+CDA647FE7D18AE11DB26331116DD7F0C22D1E79E524D6886768260156827C6E9D:\
+CC11049A69951999393D2F48CF7DD27F99C735BC424E538F60EDB512815F88F17B71C27C875D0\
+5BD3DDE4B1573C61F8C91AE22D50BC2AC32422C87C34F2B8A40::\
+946F392678443684494FA6AEC5A862C2825CB3B27B6FB6EA5E9654A9C18503F41E8D6FD34AF40\
+76B5A703E14287F133E6A2B0222FF812309DEBE733543FCE97792
+
+35AF7:\
+B6B91AC270B7F066374A83555D690D67F0122398B3BFE69EE955F385A87C7736DF:\
+FF43B5A334ED37C059E693C68B9567C41E7EC17A3BFD922EDF50CC000902846A7D:\
+C1BDC66E04769D8D104B4FAC19AA8756FEAB153BF57E3FE305F2A6DA718EA7A140D8C4B5A8FC2\
+05E327DCC13554A378F1D19ACEAF5DB3D06266F90EC4C72ED6B5B::\
+73604C1C3F699A56053A627A46502A67D0B604009F811D2E3A296830F5DE6DB0820EF1288A37A\
+3DD47974D339FD06DDBDCA44C53F3A88765F4532A26DAC97BFF7F3A
+
+1EFB3:\
+DB08ED25044A98F91CDCD7A92FC81C376A51FF58329E2D2EC54AE71C25C17B639EF:\
+B99DBF6E1FD6D5A2986FBB818B6887AA41BADE5761C333EE98B095E7D551CC70865:\
+6BBB92A591C6A9B612EA82FD766100E7B37D8DE8FACDECE322B20E18D7932B854A5594FA67972\
+B13D79AA9D37CDE29386644D9FCA609A7717C55EBF568687015A2E0::\
+50825633A36B199F23931AD09DB38DBC8548AACC6A37F1923ABC6F94CE7256427E98E5A433A7F\
+0FDC6DC8C8519B0DFD94A5A98C8AE80D1B502C0EC3592173DCBBC8E5A
+
+22E79:\
+FC0A336E6CA2935826038319B45E921F77E4917D978B3177D162FB0CF75058B6EE2B:\
+B8551618F76501F4518336A579117533AB27866B44A4D15A4C0999D919024F1C558D:\
+483E61678CFF7AF78306C5E538D0AE750F1B172BA0BECAF561EF7D9C6369F713AD0FDD7C75F56\
+F1D4570B668D45563CE7801BD97C6EBB7C9909A9C454369DEAFB57E97::\
+ADE77710A5E9C390151CF6E7226E63692367567D1C02A7E5C1554ABE84E487B48EB18BFA20A8B\
+F42180BF0AD5A6E1A6FFC7EC45A4CFCFEEF1E3F3333B85C98101FE8E339
+
+EAF1:\
+FFE0213AED2397C0663C26A85DC88DD4C95AA61345C4B68492C3FB1F63B61B1AB1CE3:\
+FD1DCC4D3B4B474BF2269DB028091B4A4C8AA244D2F2D9C5F55FE449ECF5D2F2DB491:\
+BE889EC220BEBD6F542B5FE8E670453333BBBD438EA2DAB4718E72872189FB74E1D1D677C1D45\
+8D769C82D8CE7FE163E2384DFE458C39FB5E8ABB78E5D5D3454CEF0AA74::\
+4213C1FBF227222B30F20340E345ACD86F90656034F3B318E43D3BC1A46A0FCFFA2E0E6998826\
+97025096D999290CC80801E10F5CB9FC0BC52A2170A16B52B9AEEFF6C5FBD
+
+6B7D:\
+CEDD0A94A36B76B858DDC6936C74AD06FFDB4924DB40A67A92E1E04B2D8C40F79C323D:\
+B78925E051D7502B08DF6E08CCE50079CD135C4E598A0C4401AE7300580ABC4E8EBE03:\
+98F60C8C957EE09B5AA93A4F1260143AD426B5C4A3704DBF02006766910247D2629F867B50DB7\
+00C4BE6BE97571D00BB201B2B3F3A4D663DF47C0F54BC48556E5EBC34AD82::\
+7CB497661BE76C5DF706EB0C0501946ACDC5F29FAEE801A77F8977663C1428136DCBE39A27146\
+272635C3F793546D1EE26850612D784D57C5F3F3F1C14A2DD58E07B06C2773A
+
+3F5DF:\
+CFDB1855F00EF13CE24453CA18C30292853D7E67AFE568F0C03E1AFBB68A0FC957559EF:\
+BD6E7EDAC9168F48C0B79E5C8DEBFEE0344AFD7DF63632C9F10084605EA7EA2C37DAAEB:\
+F34B51F68AE00AB209B178FA4ABA876F1DCF438016CF7054A4E979B1D239C6FE087E492AD69C4\
+7C5F4574DA5C506AB9CE37E6088FC82BCFA7ECAAEC4C14F2C8C7D9144C351D0::\
+94450AA696DB0715A5EB2B4FBE5A9CD4B1396A6DD8748359947C809061E13122C5266368415EA\
+7D4AB343B7981229CAC73BBE2233B3DF2F706DC26F32AA428377A0172AC58C662
+
+17577:\
+C3DFA0C60823C8F5355CA1768BABB4A33C3FFC55CE89FD372F5D9B2B2B49DDD23C669A77:\
+EF50ED5CD6B6BF898586F8DAACBCBD5FEE637F56936C2535F4F5E30B35B9F5DD8B8D6D61:\
+FE19C87AA946B87FB8CA1C274DAC3D67F5E2D67EF2518BA3C1C6779D42E90FADC96C849065908\
+D836E74F5932536C2CA8F6B65ADCA245F78C6D4F3230D50264E804B460D6C50B7::\
+13AF743D2FE2542AE28DB8BC52119F3B563C8D800D88ACCBF66EEDF6C418D9919D21A7B4AEB02\
+882CD8BC201CB66DD81953E27BBC29584148CAD99A4AADB5864B403326A56B19F18
+
+3967B:\
+EA749A2B3E172EDD565949DFF7C6D6862CD6C0926221E02E48A4C57169DB99058F1AA0B1F:\
+FBCE4C37F70845A76B894DA16FE38ABA97AC9BB41502DDBB3B8A324D49ED6BCFE424AEECF:\
+2C6BD8FEDCB431F2F5C4EC93841BC7C96E5AF33CD0A92C40D552F18F27D1021122F1841402059\
+41BCD9943C17FB14EAB112BD0298BBD73280611DD873EDB7F8431840D01618564F7::\
+06D86CBFCCCD3053F2280DF34E2EE6CFD7C8F9A2C2E1F610918C160BEB3D96C677A44B0F26BF73\
+8AE8A94764ECD03AF8F450761CC58698C2D4D62C8357A97EF09811E5AD7272888398
+
+2B62B:\
+B9C09DF3CFC53D3C72EA055D8F4C10E4D477CD657D37F0ABAF4EEA736AC1B2628B00726F0D:\
+FE01AC6F0BBE2BA6C593FB96A0C24829183D1D99F5CF39909BEF7B2F0D8859D325689CF93F:\
+DEAEE8D8F4D64EB0D88BC82DCBF7883558A44886105BEAAA2E193ED843C956521F155A750BEA3\
+76E179B54465574C75E817B38BC51C2451739DCC8F6A55193076E4654CCED925DFDB4::\
+AD285E351DF685D52E53BECFF44B24288C323F1E3ECD960D0773D530A7D4D622473222BA35F50\
+78ECD49D2234FEBE178AC099BCAF0C6D11D6309099BEA61DB86AAC27AFC2452034CCD5D
+
+A57D:\
+EE13F2AF183D15108C8A537E0FE9B39B3ECAF21B3E29995F121C6C0234FAF590102E90B46BD:\
+F369E93A0B0B6F459077A41C4548218D32CB0C2F7E3227EB61E06A2D77D5A638DE0DCAFE987:\
+BC46B68B8D7CDA2EE172E33D3D4B0A0C3A6174C69920BDDFF99795F36178BE629970182EFF3D3\
+A1D796AB6EEEA3FCCA7AC719436718619D86D8BD6F8F4415464899CCC852E104CC5841B::\
+5F85961809D44F4D5FA6161F1F69DCEEF6B4D9B1EAC9378595A329761480B9658CC5C5A2E0AA4\
+F63B96E7961AC450C0C37B57BE0956BFB8B4613C9B4FF88C0849E02CFD586AA03847482DA
+
+13B57:\
+F7B57711898D0CD9F7A01F3089748199E36657205D9886C225BF2CB2E592745F139B1C4EEFCB:\
+BFAA7B146C59824446B21716A991A09742D9A84B94F7F0A16BF0717B2D9C1A4665C3E8C17E35:\
+913167F67F74B1AC7D534A9A6C5DE71227B7F53BCB806897284666E147AF50CB263433F938DD0\
+7B5609DA8E0BE690220B57D99F4051AC8D5D67E86ADE626F1EEB0771C62DAB8F4452A637E::\
+97A5809F41C9AF2CE06CB4E43D96D0762B5317D3DA5B56F38493D4D8A75CB3C7361801887C921\
+0D39B5772BA7F32D302F91CD622CDD9FAB50C3A14AD95824692660D1631AC601C310DB91D61
+
+2FF3F:\
+F6F1763D1518036D58CA36D95E429BB9B47B2C064227B8C8875E0B16326A09E8397EA805DA825:\
+FF0ADACC5EE6B8D4E5E94985C9DFCC826A650A1AE1CE888ACD44D474483873E855FEC4EE7C235:\
+92D02535AB6B255F85546AB69CE4223E63F4355ECB57DC8DF1F0E56505721A78233A9D94A5B60\
+1537CBEAD6E092F1ED4441B32510883B2CA7C2211D04785E78E5A1AB4EA07E4983DACC4DA1C::\
+E131DB04F4578910C3DB88C909BF429D29D02541219925CB4447493CE13BA756D5EAC4D68EBBD\
+3AE853844EBD5E3914F3001A5B722D4EFE0C1203D89B9045440145966B61D3BA1CED4AD32C773\
+
+22E97:\
+E420CB77F5D12BA62595E0472843C39756E9CB097992EE1CD06F96EFA9AC\
+C96D664764A674C953:\
+E65E2465225710AF7467023D6E9546BFCD04BBFEEEF6A29302B584ED6C9F\
+E4ED4E0680ACB9A79F:\
+B2D4480F64C8E6D357A260031C3940D93380AAA828FC80171DE482B4788A\
+F1373EA3833F2D547\
+B5AC63279BFB8E68A2BF5C9721352F650E0F00E1932D9106235B2A99D74D\
+133374CFB08D9FBD0::\
+072FB6A4F6B90C43226E0ED5A5233BE19529055EC3005D161AE60506A98DDD5B5E60C48FFA2DEE\
+0CCD2B4F3F39938D52A5FFD3C48496232C4FD6C05D05E72BACC87087908FEFC6849BD196686D7F
+
+3EF9B:\
+F6F758693253F88229EE11BB55982A8D27B424032BDB3FB47DBEE09ED159D54D2B4F3D9B3E540\
+97:\
+D3C1DBA4606571FD58FF9CAE5B0B74CA2F496F444C37BBC0672AE5CC22547EC5CA90837A68654\
+77:\
+26B0E340A506CF587FE2AEAA4BBFF8E8A721C5DD9F96823274EC3050C3AE7C04ED8D102044AAA\
+86F4AE7BCDB8D53FB0129B152E4CBEE7C176A7945BDFA561D03554EC6135205A0B0D7FB79B98C\
+63::\
+6D48A0CA04F5E1B1CB5C8C58A14A3F79AE1FE20583D6A22BAAD4BE1F9CDE028935E7246C2DEF2\
+BF591BAB9AB2974AC6EE226031207754FF6E0FA032CED158AD41B9183FE13087C5C07624B4192\
+B1F1
+
+15465:\
+D005A4FCE046350601ACFF864B0D2B2A09E38D5E96F2CCD6AFD0A1C52270FCE297219A52EB10BD\
+AD:\
+DFDF0E254343E651DD4EB4B04B881B8274565CCCE054DEA6CF2E24B18B1B124B9C455A898C6D98\
+9B:\
+105D43C035EA626D0474851CA5EDCBA0C4848737F0C24653AC2C0025D0076A7164DFC6BE2F383\
+3D34CC52773C4A9E5C29D18CF02558D3A3A0BA45BC142221933923066F745386E4FFCB12600AC\
+DEDB::\
+5AD148B4FD171F7CF6D44F69A5A90D96097D20C2119A88692490D9D86F1CF3D00DD0D0D84D71D\
+3634EFD7EADCF1052161608355D1FB00DA6C36679C51BCF079348A62C1D6BD5E094F9CD9095EB\
+828057
+
+1D9AD:\
+E2698781666556447427B2E3956F7A8A9C089021158415144C4C48555C4B8AD95862C275C7D31\
+9FDF:\
+E7588730EDF12A42C40BF58E0E32E0FEA473D683577C7901F46B26793DD002B6EBA0F9E72D79B\
+1B97:\
+B31908872EB8E97BDF94B976F04F24546FEDDD4E20D91B6555DD4B4B8E33EABE577AD922C5EEB\
+3EFE8E060EB69763D9D9072F121DD26097B262A765C1556BBA32AC3D80FF23538ED50CD759480\
+5D8165::\
+94A809E73195D7EB2155623CC8B383C28B971920A4399787809EC0CC2E6B41AC9027C0B939157\
+AC45936DE7CA116F625C01EE6419010061B8CD2D0A9047F89FB5B5DB630AC86AA5572A81C326B\
+6906355D
+
+32623:\
+C83A47D71C360BC385D1A52A792F209596F5B71A0E1743B7AE19ADEB0C84E3A74288884786AC5\
+F5B4D:\
+E72046AFE6C5478EC868F602A71316FBED2FDC8D872D48A5EAAA05235EBFC42A4DFB599C13BC6\
+1D8A3:\
+5C5CE3F7AE9AF68B16F451F67057F8C041398A53C6FD194BEC1CBBF0F074C2A45C5C88ED48E4A\
+215E32CDFABDA45C92F24F94CED95E8C2DBCFEFF9506181BAAFB8EB6F5688ACFB42C0AA0DD1DA\
+8CF4B760::\
+1D7BCBCA46326BB722340D45EAD0825F5FB1D6C9FF3C7841C749815500A227990592D599BD210\
+4F53C9D2DE460CE8078222A3FF34218F89FE0065E4FB852E623024987FAC1AD0A12EF239BFFB8\
+781B38A86B
+
+1F471:\
+FD762F93472C2FC5B3198306AC6E4D18088B0A65AD4975EE26FDC78C52C4B7CE3E754532E95A5\
+B548BF:\
+F15450F4E38CB8DAFC3153725CC289DA9F0F218CFC65F6D62BCE770F4D42763CFFADFD26DD236\
+82F419:\
+C4BD415792D696D83CAD82285A0E7A06CD7F05455653F13F56DC4D463CEE6753B6237B301A511\
+2D7C8995815650C38113272BD0F6AF0D5D51D7E5EFC82B9DA66242B5A71FC6A6C0436DCBEB86A\
+3C1CCDB75B::\
+EBE9C9D258C09B1F708235D5CDC2751923A993A9176241A5554356C752C62F081AEBFF2E13300\
+2B1E70F5902CBE6C8DE8B12080FB9CFE04C1E7EF7036D0A6D07CA091DA3B085FB9159BC5107C7\
+28F55FAA25A2
+
+2DF8F:\
+C3362EF39B78C21469D23C2FEC1642D3EB7A7B72695A14FD07A0E6D616B0C50884540BCE16597\
+1AD3833:\
+DF631F65CDC45053FDDBA18E67E47F45F14D876E4D89101E531303735B38C883621A2CB7C16AF\
+DCBF26B:\
+50F14DFFF4F8B138F12159A52BD7B22BCB6979062C8EFDA7E9923A7EF43996C954EF15524745D\
+3A3E5BE1A57D416B02F11D9F7BE36BBF56CA3CC22DC27DAADB3423B4788B5DC72BD0E6D3083F3\
+303AD92AAD72::\
+5F5BA5370BCD31B61BA12DFACE38C80A3941C76091E3CD629DB5B6BA90415D83EDDE9C640D84D\
+8D671F13974DB70A85ED0956EE53ACBCE54EBC328729630AED05321A2FF3C3FD7F1DCCEE8968F\
+9317FE00FE3244
+
+33801:\
+ED0A07AAA76BE91DE67ED0EB199779B16FCA57E376724DDE07B11C538ECA422B15E20D2668E6E\
+76E6023F:\
+F053CA61904163A5AD824276A97ADD3153B473CC1A45C401EA87DF2CC9150B2B8BF817499A2A0\
+E2EF7C3D:\
+585918DAE91862F4B8AA6F15273D1CDB9FE2ED4D7F0AAE8AB18D2568BB844B37297FD3B7AF38C\
+A29C3FD944DF17C62258CB0A4774FCFCF3D46C1D8A96EC87E935D38D9069F337998C7960DE1BF\
+808940E2E5ADD7::\
+978782932C74CE5E40602583D3A3F4C18444692C62F13B571C2FBB0BC3512F5305A90298EE626\
+C3E32AFAED17BC3CD85EA6C05A8F84E8262160AD9486EC5706560769494E0B3E90CA6B752DCF2\
+75FEEEBAEB1C78AA
+
+28F63:\
+F69378CC655534C08A24FF41A6984AA981AA71574EFBBC565ABC63320F1CB5A20CB599FEDFD12\
+559C884A9:\
+C954A6E1207C0C36D39ECA530B5496D91A12175E2BD9FDD2DD897542694DF50292D9313625249\
+3F5FDF347:\
+6D63D56180ACB06BA7DBE50E01F9D50424B9545CD054AFE4BFD6BD4B14B718014F2A9E712B3EB\
+EEEC83B1209F895C709186E9D898CC9CED462168B129534CB241D6C06FB2CE1984D04C2434153\
+AAC472994AA6D3B3::\
+4A2046DBC2C49E68FB37D77CFF89E2883610F0076AC081FCB9684A4962BF8A21829EB10E94C35\
+C5816FADD1F1CFC4405FE9833F79CD363A512DBACC6517D98305FB38F17F5F04CBB3C8E944845\
+C3727295CD5A097824
+
+3C283:\
+D9E9285C4E77272100900893E78AFF01DE4C6CF03EB8B7B62B4615DC09B58DF98ACCA559DE476\
+255363DB7B:\
+E756DE8333A525E410D4E896B4E8C4404B55C919BA168F97B6E0B6D1922CC56EF3BCA5991A3D9\
+822EF04725:\
+3134FD350325ECBC1E8E1E702C1CB3EFA940122410B2A31BF90B7578D8B5370AE8C961CF2824C\
+5D5A8B298F84CA31F57353C432A22C17C9CCA6501250A6B930E4C043E634CD0308057C0E719E2\
+20478022C4A13D27B4::\
+3BF6E6EC491B9615E640A19A9C50AA27AB57E3493F96C4271CAE56C377815CCF2A65867CF9327\
+7948D6ADBDAECFA629E41E72E20974735AC615692DB76EB7CB83F9388FC86C86C615E13CFDBEA\
+9567A95E2D6B61FE6077
+
+E505:\
+F0D1129E96239792FF1B59BE8D2B755018BD8CB83DE5D825C04685917762185A62A080DCE9D98\
+D389AF0040F:\
+F4227E1F8DE368420D5D6069E03709168A8BFAED59C8E85C8294317C6FFB98332D736540CF888\
+EEF6C0C5CA7:\
+72D86399CF78FC56C6E3FCFEB75AD0399692D3864AA1060E5D92473E82BC9950D037D478D2130\
+994A2ED377D8ECF987048E0014A1227D818C5913CC1F8646B0EE10961A3189A031073867D7632\
+62BBCCA2FD04AB7DA443::\
+AEDA2E28A4DBD01A7F288202D1D3D83BECD2DDAC7E6CB38261CAC58F5DB02916DFF53A9FE8EF5\
+70CC804209081D465560CFE9563C8A217581DF8FAB4E1F7FC22AB8D89A9D1BD9A78C1AFCA5197\
+BCF6BC9A8D84AF53A5EBAA
+
+3DEB:\
+C09753C0621B13376CECE340B0B0048DA5F4BAA4C8DA1F0E7EA92ED44E5DE757971F155A6AECE\
+BE751E485A9B:\
+CA4B0930AB38FF92E10A4AAC631797ACAD2924219FBF36E4AF18DC918BB40574B072F23ACC1CC\
+2C4B5ED15187:\
+C82FA6530BBF74AB38EAB8C116F5AD50AB007BD36E2BF91B9E14AE69CA2639E6FD928FCDBA3B0\
+AE7A1E58142B37167B41885DC2B6E07DB003944BE7D1815F3EC442B47FD4518BF3B31909DAD3D\
+950ADF4FBB212B31C9B62F::\
+03B2926F1560ED49557BA17D127C669D4DA2B37809F14C0ACEE845F6AEA36EAA118125D94F9D9D\
+017C9EFAC9AFB2EBA7C4DA17B95833CE1EDBD846761E0F7872247C23EFE8B2451CD4F5F84C6888\
+159705A9C4AAFC3489C2AB
+
+F4E7:\
+D8658E89C4E85DD9EB45D4584265686E8D19E9AA823D5C37532C6F9EAE8BE236713DCD3DB23F4\
+14C55D8B6D867:\
+DC3A02867F7A3BE96A167491BA202175E8902776A9F3D9A852929F27DEE0FF99F5C321A8D5663\
+F7CF074D7AF01:\
+A77BC6D9F770F51BAC0612C4939F10AC9F336B61EA6D87E3C5E25B053792D9A90F990A18CFB82\
+08D027D7C63E14FD4076243803D4EF226C4E17C801EAA3265AF361B8434EC8AAC8144777FC005\
+41898C637A7681353C99CD7C::\
+3CD72CDEA001A4F815D1634599DC6BE03371FD68D30D2AD40FB38E1ADD92057E4481822E5977A\
+94EA02F9DEAE1D59DEC6F9158D45D0841A981D4D9FAC7C766A8F9E92BA06B67AE058CF022FE39\
+FD7373230B831AF141C3CA721F
+
+10C8F:\
+D946C37A4DA5F1D01ECE1ABCCA98DF361D2AE47BD1AF421464106FDCEA6DCBECFF3B91163FF9C\
+0AF06EF9FE368F:\
+E3D6B43DDFAD06AAA4941129A4FAB542C41BC55834B4D9BA01C5A4BDEBA010B0EA2D125C23396\
+B669B8CDFA5651:\
+FCCB925AC2AD6E6E5855455E84E266CAF5E6A397AEA993003E80F3F7D3A1B83E3A1DF9F87233C\
+BC3F2969152057EE85254B84260EB6D156DAF844C994F03EEFC0B4446B25D6C1B4C464238871A\
+5EEFB45DC37794DD64E4A8C175::\
+3026BC29CE98BE196930D34F12C2DA7702373BF4B15860DDD5FD61DAE4EF0DBDB353DAAD8091B\
+D89723BFAD2AEC3CA127594A9A8F2E7244AD821483EB73B014DB00806A8C5BECAFC92FD79609E\
+7F9469EEA28F21BF4CB1AD468E4D
+
+D89D:\
+D65E29ADBAD552696C44154EA2C80C23F49A604DF256730AB1BDEE5FCB9D9C2480CB1EBC78830\
+DCA559F40ED42F3:\
+EEA2E85BCCEB57BA0730F0D01940F79A55B91D2CAFF54B709E7616364B020FF9F640C4AB1884B\
+8EF031523855693:\
+702D36984EFF9FDD16A879C177768B4C497E384E657CCE78C9DB496F0898FC3DE110E46A96798\
+38900A5177027E9AF0907A8074BF553019327FE47DCD86E11E4C545D80AC4275FADD2E0909236\
+E55C6846317BED4D286A8B9D5122::\
+3A3E20F621512BA40CBFA6CECA990404275CFD2D6465DF62EC70A3CF0AFAA337D6968EBFE5E66\
+B6FF9666BCC800E80F4BCEC9DD33076DEA1033A391AB220DBEEFE6257505F8DA1F61EA0219BE7\
+B93A89CEDD5EB1E6895EE81DF52DCD
+
+96B7:\
+BA0A5FCBF606CCA93394B2874ACD6B27E8A56B358ADAABE8FE70577C37B13EB508278ABFA5C3D\
+055419150FA77145:\
+B8399927DAD237158D4385C3D52A5237BAB2FDE90A50CA601CF8C9A91316D69E8AF3A66DC400F\
+884FFFCCA4B4D6E3:\
+1BDAAE1316925E851F9A25903F3551D8EB7DD69B81A63D9574C961CB8A3F2ADAE7341C82D8C60\
+DD6F28D947A40D48063FBDCF4AF69D5B355C0C931850129EB8384CA5B805692EDAD9D5A26C0C9\
+D2A02B195BD8617DC39ACA0F349B7E::\
+7660C59184EE406D35A4B6909A5711B2F7053F948DE92C3D75947191406959434B529C035AAB7\
+785DDA4B14D9D741085AE1ACC5113AA0A3E93A26845F0E6A25DC88C4865CA046F35A1EC6E8E4D\
+AB59055DC49955021EDF85A50FF3D08D
+
+1CDB:\
+DFADFD5EF2FFE2F823AA107FAB9388C6E4614833F697701882301A874CF2D2CC8C5E8D881DE3B\
+1C86D043B0EAEEE87:\
+D5483867A334313530C629B9B6386CC1A385716FEF988EA995DE8987380FDC1F2518388107C93\
+9DA0E1F3D869A66FD:\
+E1B889BB7FE5A95A69CEFB78A20C748F3F44E9734F7ABCD7D241E9831DCD3B33A36622F21EE32\
+FF85FFBB1C56A379D8ED3A0CFF791E61BD6E4822AFC05F22E356CB10899DF3B2D5119BD9350FB\
+901A261995D616FBC5F851D0C787E31A::\
+04D5337CD443A196514E2FF4A3C264481DA91FD1A01C8C819BD376222A824CA6527F7C4884936\
+45808577F17E896A6D9A39B6A3E9CDFDCEAC46A2160752D4F30223FBEC4ACA5A01C3AE3CAFC34\
+ADABDF661BF198C7A0EB4C696C60D590E9
+
+FE1D:\
+FC7C6FE9C0AEB5586DAD9FE052587B0174899B7BA9336E1F43AA74DA97B6A51C1095255F88F25\
+18070C79CD3D1753E3:\
+BA97ED086E482E723CF61B68685946173D5E3E18E08755EDF817671144D752D388C6CFFE89E0A\
+A1B0C204E9BDD749DB:\
+ACCD4BA9136BDF04D0DE4EEA9DF329AD891D115E2426A3AAAC41F69F2AE156D01BA34B5B2515A\
+7CE7191A0266A7EB280798D6BEE627B65AD3A8D7A5E94603C79DE429D9EF8BC9C4DCCDAD768D0\
+BE24E89AD29FDE7978651ED712D17F4269::\
+66F0DA8E2D30844A391FA9320732CB75AB1ECC4D6694B0775DA41D029A8A8FDD0CC7AB74E52D2\
+E2D522AE7F336D3A7C21BEAA708C933AFF48BF117C99062D899052B2F9CC5C7C86DB7F2A5CF91\
+95A1CC8E73B82ED6F3B4C7AAFC9760843E15
+
+2F99:\
+E2AF62AD078155F452BCDD17DD1F37F73F22652E4D341AE558A261FD958E7304FB6A7DAA6F1D9\
+4F670F2A6163ECCCFD7:\
+E716A2EEE122C98651180F8AFB865C6617389489B69462D9A18570A4DA0A1006AFCDE60DE41F3\
+33908DCFD82C31C39EB:\
+1350D7DD6D558BF7B2CC13628D12E6DA39F925D6F966103BF00529005E6B0A90A63FD58A67446\
+7468B065EA3E48636B9B409EB4167443699A47B435ADB68847D1EF00C90BB890AEDC6EB57BC3E\
+8DB01CC990F14E6076AB5E7DFE5B7C5246DC::\
+46DE5E9C22FBBB39C33457C66F4C447E922EA5B4D822BAFA60FA072B83628D34B27316B8FC418\
+AEA2FA0C6E495C474BC205DC35F32BE6FADAC38D2BE7E0CD1AF1A548908F0D5C1F97ABBC1A3AB\
+C30664E46579E12CC9624DFA7D431D44ED4809
+
+E3D:\
+E7D355D9F62F6E79567C02305D34EBE95852FD5E77123BD392ED843E3D28C22FAFF3390E7A1FF\
+42E453730ADDB98598BD:\
+D6AF51AA7C89556E79A491895000665242EE272FE3E18E79A6CDD9B7BA694784BF1A9611C9FB1\
+0183105DF0535DA57207:\
+8B7800B682AD7562D7677DF8AE845D1A67582F5400D32CF51B044DC7DD9507C5074BE468AAAE7\
+A6C862E7C5267389A93D365CED7E60D70E0FCBCCAEE2ED4CF549B7FE6BB2A3D561AFE19B9EE0D\
+094082921FBF7DA194B884189A659E72989DB2::\
+815912EA98FAD3D186E4E778617398B99482FD96B642B5D97C76B401FD028C0925017DA2938DD\
+756289DA08F8409F73E0D382AC7709AD0924AFABC918380C2A5B00804BDEB99B249FDA0AAC227\
+083861D9961EBDE7A64935E2B71271B9558CACB8
+
+37337:\
+C3335C0E3243BB8172670A390A4C6F1D51CC249F8AAFDC77B53CA05912808CB2A7AEFF1A8CF56\
+129D45C80256C6760E9F1:\
+C8978DAD5BC81B1DCE811A010274BB838F641C996AE49B186018BFE91EA04A54E8488CF31D9E1\
+DD1ED2486CD817CB7F05F:\
+7EE901DD41DF722A51579A4499C02E981D73664634BD6A032BCECC326E1CE5C7247ABF9E62358\
+77312D282F3D3F6613D3B7BB97F963B4437C69C6EDFB6DDEDD519F72BB99E155406A7577AEBA8\
+5390AC7EDC18046D639C70D5EBE3EBD73466DF68::\
+4B2E3B069A2B0559A1BA2E50170C0DC28930B7D2F6954DD02D4FBD2D97975D8FF1E2CA851640E\
+D8522DEAC48A7FBCF85DFB18D698F9D3DEFCDDACD99AEBE52651CB2456420497507D3CE55CC4C\
+E411249840D776AC2952FA5011C68DF7353F832FEA
+
+4935:\
+CFEE1A3877BEEC28653154CC1E158B7DF10BB6BC046A0DA3A4BCBB9545964D34BCDB256508D47\
+7B4C2DAF0C3A15BF602487:\
+FB2AD04D99FFA45B66A5A60F1F674107A384D121C5B463177FBEE5964A1B3713BFD37CD051713\
+2B74F85B792DE1EE71E7CB:\
+8E90BB43D3CF22F8A7893F4B36C746259DA901FABECFA8F4667798AB74DAE54C9B2539DFE6B25\
+211EB9A1E169B609B3F84C212B4A568CE1B86157780612E41E90D20B6A1F71507D16992FA88A1\
+1D9C897C8E98CBCFE6B265E31A1B242670E23B5AD4::\
+54F84FCBF1573D4B08E67172693B2BA017EA34E8D27ACB16C9A43B0CFCD0C7CEC122C1B8ABEE8\
+FD58CF82F98FED112A31FB4DED936143BB442F947BACED07555041DAF78785C63D3B323347F45\
+BA800E78E545FC115D873BEEDEE9AA14D281439141FE
+
+DBC5:\
+F75E869AD89EC4CF9BB028E3A67A40533FB4BDF8E663DC038E70A19C23B37D49ADE4CFD219C3D\
+F67DD18A0CD6869494EC05D:\
+C921AA94CC7653F9D02548B5DB56A46FC5304A9308CC0232773537EA52E03D5A2E6CAB5061B5C\
+788B357BFB34C4CA782FCEF:\
+7B766FAA923F1925F89D91707735570A0E856AEF65FB5232A1EAEAFB1966BCADB826120DE38D4\
+6513368A864290B36A5708F970AC9C114743964ACCC95E100AA2AC1A0A4993B34A70BA336968A\
+9C7CCDC264A06BCEA69D47092856FE451BE7892B17F1::\
+5DCBA27ED4BA89D25550AE6587846322D73483F60EE2F128B025C496A0440680FB49B49A57CAC\
+9479ED3210A27BC31F06257878FE3278D79DE65C14083DAD0B29ABC32C4C1DF53019267C69843\
+8FEE0609C3E2492009F2E28B39A04553F6D6B18D16D867
+
+20B7B:\
+EE50E2D3362D0950E6A79003E342238AD710D03737EBAE5BAAB7A0A4FD7A7F6AFA814E768D9F1\
+2B16C52A5294A8652E4BD44D:\
+C9977D38FACE5D6003FA12B76880D2545BC15A78FBB19DA19FBDBCB5C5916DFF18A35E10E0479\
+FF9F5C5D807D219F2A10D64F:\
+A298A470C3B161484FC89CB9CCF39F6ED2E141447DF74EF559CB049F2DDBF1DB354864814E961\
+37E790390AF567253B3461D3FE0FD359D8C59268B0E6BB401A17F849414D6B33FB43DB254ED55\
+7CF14A97FBC72CE7F13D1B0F607381D009C88C64889BB7::\
+6C777A801C39D3E984289AA21D01456AFE5946DA4C236373B3FCE7DCF15621DA90871AF969CBC\
+06E671DFA7105892C89BE8649B3F27E28461D1C02C071C7D319F8F5A3D5A53B1A66D033057980\
+7B7F6AE0C897A71367207A7BD3263B10F4C3824BFD11B8C5
+
+C31:\
+BFD406DD82D7EB42637387460A82E2948FCBF40F9CBD8025F1B02499ECF9B84D5777C596F3004\
+814F746360BD6F599526E4099:\
+EC593281958D49E5E4D8CA8EC3C68A00A19CB520255E19E1A6813E724A0B7A8C7ED9ACD221997\
+E2CC915570F702A58CB9B4B1B:\
+06FC724F11105899E12F70570719F342CF56476A1631C7391196F856012032C97B94C10865CE4\
+BBBD6D524316B0A6DD4796F56B62FCF585F83DA7D138EAEA0FBD7E9E7074C5F1D835C267D2DFA\
+369EFE75C2D1AB473A29B035750AB3E048A5CAE8CBB7CB7C::\
+A34426C6435AAAE6C0A176881E4EC4FA6DCF1963761C36144B109F01BAC3ECC7FCCD63591C708\
+6BE2BF77EEEE7B707CB13D19533FB82AF97F80E430552BA461DB9E6DFB37B573C0B8875C86C90\
+60342235A2727EE1B291F9B8F89A84CDE67FD48BDD923AC1D1
+
+3165:\
+E13F572C3892DE9E82619F265EF1D0E028AB2112A9F6B855883837C930AF6C50DE5958B8EF9E7\
+06E8A5BF1FD041FA89D4E1A66F:\
+E255C42A2B88D2E4B1FC51167ED335964D980670B30B9EEFC8E896A52DCFFBE8AB5C15D465C06\
+9040312DB7B9D9C62D990A78B5:\
+62505EB7C1E4AB70E230CF8B9974CC32845FCDC37174DFF0CEFF7BB28FB44D4DC9C326393C4B1\
+85E8B2F5E306CD56D33DCDA16DBB33832F3FCB437AD3A31D7205C87BECAFBF42C81CFFB14D430\
+9B1503604015480BA539AA79653455E481A34FD24D6086C04F::\
+00B5D962C18B90010043C6B3B73DAB6644EBDC9BEA758C890F60B8F5694DB3419C29968AA245C\
+AFCD6784E91608670E50F6C9E726200ACBA8C776438C2D35E6E0CCD52E2B73EC9F50DF0BC864B\
+F45909AFB80AB9CD3DD2C2C1246E7AE78FC759669C43A1D69A5D
+
+139B3:\
+E87416D7D28BF6370DBF37061938D4098CE25E503F6974CBB36494B21FE81AE18DA11C25C0077\
+E8F147115B259B2663733CA24FF:\
+BDE29B664ED4544404CFB420E81CCC2875CC6088A82D193167CCE66EFA4D6E30790D882F4DE4F\
+D6852568E8A81B52769C8D4E039:\
+5B514F002EEE84D142DB23D38386460AF5EFDAA7FBDE017347A3AE359573338DE196215D4935A\
+E0F8EFD5929FCFF748FEF07FD42C9614635B249130F291DAF70F8193991EB2D7D2B77096395A1\
+12C0E792F76B4049BA7037D4CBC4D2964DE324FD456B52E4D153::\
+662807DC23C41CA24C64A2E5502C389314EBC3C9949E93DA2D2BDF7FB1C1EEC21619C373948A7\
+C62F2B902F77B7B5BD5823ABA38991CFE6A60C12FAF6C1FDFAB2AF539CACBCA7F805C33875D89\
+85B3C7642CE9551738C214BAF9F465309CF94F91C2029D5900823C
+
+BB4D:\
+CF8454329613DFADA528D9556A346FD8566F5B1B42A5EE1E972F0A7B8D03DB800C9A04D93DE07\
+ECBF14CD67A11BE27F8909F603B9:\
+F67C6ED7DDAD52B15215D9A1798A099BCF20B7D65434CCA74A279BD63CDDF9D27F381410167C6\
+7294535784F860BF22CFB9E90501:\
+ABD2BD2EF35FF7CAB549E375FCDD9396CCC9F6D51F390DBB06AFCDFA2690BCF4E7B4EB8FD3470\
+2CF7C272ECB64A8D3EC50F551FE8548DF5D58455D8113940E65D8D32864BFB36CD641410B6013\
+7DA69EDDA58A45EA19834031E788204E4C57B7CCB300F8264F2150::\
+26AB09BA08816E7EE65791E8B5539DD6D19A60A4559315969EF3ECB299334F6A9838502555FC7\
+449D80B3434C4C824805BD1F4BA3537D7C0C8DFE56792AF5664B8337031C393498AAA558FA892\
+78988D33ED4DD0BB896F44ADF623A78F385E135085288BCFDF5E31DD
+
+2EC05:\
+C5BBAA73868BB968A5A3693AE84E7FFC58D7B77AFF05BED1B6D2CFBB62207F95CA33CA7BD2900\
+0A1592C9895CA60175C4E8EC9F7F3:\
+FEFA4B1CE3D3A3A00FDA17D05E0A95D4AADC7118801B54C04E06A6D6F417D07322EDA0EB9E867\
+2C3CD2C40D90D50D8AEBD61ECA747:\
+F294399D778469FDE1D6062DDA214686C51069A8F4EE2DD4056D68E3CAA76FFB149AB5B3F2D09\
+51190411B4795CA893A87CE2832FD728FCBB865491349EF9091BEC02FB4611AEFF9B88E7C5D5E\
+3CB2F26D6311FE4742DC234F12A15DCBFBC09DB18ED8D663EDDF3801::\
+6A01851AB2C0F15AEB5F3C0F7C4ED4B80D0DB1075B25352DBDB2DB7BA6DFBD07AF4C262AD0C61\
+5E8885EDE377738406391BF6402C3A7EE8BEFCF26C91DA0F4D9FABD4A6F06E76047B87B8EE0A5\
+D9C8A04B174504F1E3C4E6A4DDFEED36FA4F5E78F63ABF4838A89DB8EA
+
+1B30D:\
+D0E3CCBAEEF5BA9BAFAD06D5B5C6727D5AB85B23D1C231BC0A18EE4F166D4EDDAD542BFDDFF0A\
+9185F3EC41216768774239400D7567:\
+C55B49B03706EF2293963E81A301DF8856C42FC2C2CB10E1CD36E1F91100C87718D06D20A1C7B\
+0DC125D0029104A6B957513DD1926D:\
+881A8AF4FC9C7F9C48102D904F44829E80A5F8879B8E65792E36B8F15AE189DD36AC9E976BE57\
+A69CE59BD455116C3E281C4371CE0A89A4B59B12CEB51948FD3CEB67B8682B966B9874A67AA61\
+C497E72AB8516F595B582BB828C94AADCCABB51C00498CF7D5BD8CF005::\
+25816413403B2DC77D9345ECF1B02C9A95F715AA3A46E8EB9DAE5E7953FC30BA601F22CD28DE3\
+C0397699C004631FF297CD48985B13629FF9E8527FFDDDEE18E6D371DC0CD75353590C8DF50C0\
+9032D16C3CBDBFB72C0272D4816349B07459C2F7020955B6A88FC03A0DC4
+
+349F1:\
+FD6F20281B82FA202413D8E4C9A6873AC3387FF46DEED6E320F80430A1B8B6BD8509FCC0AD982\
+DDCB2583CFA2EE092838881C8F292B9:\
+D46FC162BE2FEA78106D7111E94AA9CE05067D4577E32400FCFB80085976F75DAD9EC175532B0\
+C2E3DB59CEE5F00B02B361754F27A77:\
+0BFEDB7551AD05FA01CBCCD7EFDA1FFE2BEF0959D0707B74047F7CB64A165AFE80737F259D741\
+1D5C0BB7713470325EC4C282D7B4F5CEEDFD9C57383AD0409A76BFA7D9F391BE001F3A3CB535A\
+DE0D2726EF9F7D33D805E6A607B19AA83A7457F3911DAE74145E2FE732A0::\
+4685DAE11C6F04EAC0BA5FC5017CAC0F398B0290D128C857D0F791A9D5B0E19329C86461C1D04\
+F08EA31FA7B64B899AF5414C3B9183338AFE87278D74A1E7B2B40A7B2973D2C4F13D848A9F81A\
+F279622E1CC097296CF370634B0DBE6FD31B6763B6D9F22A5CC1E85A9655AA
+
+38D9F:\
+F4F791961203FD4D4015567EC4CE6C4C281900A0E73EC013C766D0211F20CD369B698208EBC76\
+F9573942A8FED30CEB201E4508776D31:\
+DEEF6180D28D8B4DBADD5274DE22A249FF83E8A3E77F381B01A455FB3BC461BCCED640A6CF399\
+B48DCC2B35B5250BF82212F49BF0101B:\
+B52F8BF8BF76798AA7F876E0D76D4EB5821186244A5570D26029F2E720B966A610D4275BA74D1\
+C369990F6174F6DFB4090F3C6E98E3A0363019FD98C1EB913F0F5AE47095224064FA01EE862DD\
+089A6A16B6AB78719927F571BC04A2D1CCF90906D93C3AB5BBE89FA368385F::\
+455F2109456B04D35ADB476EBD40DE17B5843DFB011872A444B14DBB3EF1EDC9508C16DFEC97B\
+29047F46E5837284AF8A5EF12B28CBF61BAB7EE7B92ED5D60B121FA8EC4B8027FE9A63E24E85E\
+4E7E01817073AA40AEA874710452C3C5067106BFF3F2DA855AB7DF04787D0711
+
+26B67:\
+F160B54868F1B3FF0AD90572170B554F75E7F49A579783BD6338F55AD88678DE5AFF6BAEA9F51\
+159CCC80B84B196C357B0B89F58EAFC55:\
+CF68CCDA550EB334438AF72DE86D8CF18B0D218E1A15B2061E1EA663083905762427533CE71B4\
+04B965D37124DB8391638C62F5F747E41:\
+41C35AD24402B4D134126B140B75150CA4192AB757E03F243150FFF9B69B721C51DC09716782B\
+494948522185A1EEAF642492DE7B4523896B4A73B264FE8A5739754DE7FD1261047F0446C9B44\
+D85EC72262A03EFE848EF19E471BD110D380C0E555D0E8B8377DBFE07B38A8E8::\
+B4702064042C93F7B2BE232DC34B8F8EB59554DB7B68B98F1B642A91F1AFA89F6D33BE1DD8B61\
+62767D444B3D8207C578DC83A69F85BDF8E4784A266C9F474A556C1423C54C9940EF602F1063D\
+BC0D6CAF08E05D628A2426DA8CF6978A41D4EA0611FA43BC5C6BB92C39F2486468
+
+238D3:\
+C607A2D95AB46A416CC4694E087C93E73EBCAFD1738D7B5CFEBC322FE0A1632099A129596C3AE\
+955C77A6171A7BE65E0B9610842556B7AB:\
+EDD4D4CA2759A11B0D256830C17CE7DE58E7152B971246CCBB7E52F3863173C1819F633F3AD7D\
+5EE1217F747169718EB8EC14B68DBE6D31:\
+EB8006B8C13866902B142447B8A360719CDBFB017B1A9473565648B9940A61B495412881BEC7E\
+023B410186C8F57F555EABB860469C22C155546F78C9DFB957707EA6F4E51E79E1CCFC3A8C7CD\
+8B560EF11C28509F034832DD095F3B378BF2AEAA6ECB1813E0462955825A3EC14B::\
+6ADEE0AECBED2E017022BA21FC0B369E1CA9D7C9A3359A53FDE22A817E0C8A8E4853433CF4C96\
+E20B72F0AE6102065C6401C31B87A7CA48EE75494EF31BE7AB42C7B127E558716CC57E9AFF019\
+AF32FD0CC1C7A09922A46B3DF31C8094D4F996C87C980AAA49A50FB4F6B97AEA4530
+
+FC65:\
+E51741CAD444F02E7F689DEE1AFDAA02C6F7BD29847F3535C988E7284F6434C4CD8FAE24E04AD\
+8AD605155D264DA6DD31AEC0919B3FBCF27:\
+EB66E3C33FF2BD0F27072C71455B8CD72B732345FA06B94C2F4A3D799C2E12DDC3BF2EDD59B4D\
+4B29DBBB96C3346DCDE5EC1E3B2030C5565:\
+7C06B972ECB5E6457E7BC929E2095469A724A641F93DA43EF9C2AAE756D2A5558C7F21EE47612\
+B57DB9104F90C52567DA8E68208D487AFEDD30F2EFFC3642FF010591075AD1B03D543B1E3E025\
+D4529A1D3970BE040AC8CFDA9C5B5B41F2E6E28C7FFE8C2A17123D5CEC05BFA3DBA9::\
+4CCE57B3471D119AB5D0D8EDB148B38C48CCEC514E11E6A00C023448374F011C78E2D1ABDE688\
+C3BB2B48733FF9B9523A7AB3B01F6FE116293D8E36080672E4A726E2796ADE6097A2000097350\
+C99E36B584B652880930942A6918BB0DE28DB94C846AEEF8151BEE6A3E96D423B32097
+
+C407:\
+BE39B346B02ACDF3F067D1CC0689ACA4811AFE9509B1513E9E4B52E6BF648F219253824105114\
+E749DF1857758C5A0C54830B1ED96B15E301:\
+C1C2031D5F29D74B4ACCAB0C211A1FB29A7087BE34A800AB601363662CD998574314F6A60F76E\
+A153DCCE7FE75BC7D13C859B45BED8CFB259:\
+E2C9221D1C5B3C297E54881C4A484DC88E229A1F89CB9E03A7A836C0478696ED1448636BE98E0\
+6A549BAF0BE30DA4AC1552B17211662DA4D945F0849900EA02CCAF1215EE1B631D795BE58F572\
+CA1B498961780B2C50A88C67A3EDAA950BA986193BF10B3DFF1EE9E0F6D8814F4EA821::\
+0F19E9BEA836057F18CBC1C1A7ED08DAD6D58FE84864755FDAD69BEC2BD1AD9D\
+DF0097D21B05268737898F852643F3DAE32FB5097D95B4AD70A74EF2E7AC1E77\
+14FA57436A904AE361EDF9451EC406C9B726DABD0269EA5BB9F92A74BA4808A9\
+51204A92C6EC3AAC9466F2086CDC4EB279
+
+1DB8B:\
+E1677D97157A28E686A6DA2327E0DB9B1BB00C0A286D2939348B44B14A1484F5C32F1281D9250\
+3DDEE248145FAB855F41959C7372AED2D7647:\
+F86F396FB930A154377F68536927C5EE34F9A948AB1887AF13D296505F4762F459015CA892E5D\
+92F44938E3E4F855130A624322F2D0D5698A5:\
+6F1FBD316F2B02DD8917432A5E941C511C482F93CB179AC4C7DFC34C334932976A1D8FE9D7057\
+1CB02BD8A34125FAF0E0F136E6C3EDB74F3B0F2D8188AB73FB25DA5A3B1D6472B4009A6F53AAE\
+0B58FADDD971B808118230C88AFC628B3DCF85A238053642BCD1F1478BE2B05514A56ACA::\
+B3D24948C2D3BFF08B9B3B11818E0517890DE8FFCB40AB7DD40AC1B0FBDA19E2678C67C53C6C3\
+F921CC4AAF05CAC7DA47B5CBF6EC5731561CF5F42FAA0A394D1CF7FA4874AE7E344883D3982FF\
+B91175E56AC49D21B01859D93787AAC3AC1C24A03D73C93E1E43981D860C7DC4C84D307A53
+
+3CAD5:\
+BAF9A508017229DEDAAAC51B93F8E12A8C10E489AD9CF90CEB127EF503C1F56158F92972A3748\
+DD4CD20AC162DDC4DA061626176525E9A80365:\
+C8504C3E93C15C6241850609EEAED406F18E0E5B9EFB9FD6BFC0D474D35D7BDAA63CA925B3A1F\
+4EDAE9F9A99C1366D6EF5432188EB672EE86A3:\
+6BEB86F20DC86874BC052DC6C032E40E2E555D563D6002A6C269FF9C335680C0BCD901D02583E\
+F30A3FC3E68AB218CC47228EF9E6CC14930CF78CA67F5618323C95605D73BEC5389017B77C300\
+D0361AFEAB7E97D7215A8B826F91B9BE823D2467032EC6A58A9DF42766CD912F6D3EFE2AE9::\
+765765BCEAEF80D33430417318FD4775357D8DFFFBB4147B60EC0BB7704E5801A6E329B2D7A39\
+587DE75AE2143671AF854213664583C69CDE7A26BF7F108513B9F0BA6CDF81B28A65C7E2AA541\
+F4BE5817761F146AB1ECAC76EB2EF1D1FC42A5F4D10C93CC2F3D2556CCA71A0215B96257BCA7
+
+203B3:\
+C9336B9F9A8D36E22D93739B8EF9506C3A9A6BB976ADC8777BD29747FF186681B5E77A5ECF525\
+3B1E9AE531EF7B32EB86FEC641AA718916C64CB:\
+BC37BB3C56AF232171EE83DE4113C79CF78E675B7E4E1F4F6771384949382CED626507FA5F489\
+B3CCFD69E18191C21AFDECE4D9A17BC7EACE0E9:\
+2C4B930C9ADEBCD1E36957E1817989B56304B53B03C9BA009875825CCCF5B0D77A7F7F76164EB\
+0B35DD262817D8E1EB5C498ACF16F4D4CDB0AF8918E54E7F5EFF050283D533598E4E6CD128E58\
+CDF5417F520F0980671FEF7CE77E75E64EF2261F27BD50ACA5C68D8FE96F33B85A76337556FF::\
+1327DCEBED97BCEFA5EC0D6F4BFCD98B28AB14C555D31480C81F31E1E0FECC2DC4608E8BED5F2\
+AB89237B3B44C46443C4169E25AEEDE620C7625B18B862614DE26DABACCC21901218D667D27C8\
+A676EAA261E575579E06532DFFA1EC9E18F23D8A94B6DF6DFB5C52A30F9AFD22B6590081DF745\
+3
+
+2487F:\
+DF3FF505147F8C7CD7352E57F5CCC3661B4DA5B003BF7D3DE39761EE8CAD575B64BEB5332DDD4\
+C3ED6BA64162633A0453FE4FBF33AF34329C5759:\
+BBA02FF73B4C0ED4F774C4A878D696658CACEB13F56C9A936193C28F3FA20A4056213B8A7E710\
+23806DB7C0D49161C59E2F88B00604E442AFB909:\
+A527A2D970C829A7C3E0FD2BFFE9590B3A3C8E05C3DF8EA923AF156DDC30222BB304CFFFEFA4D\
+F81A63B597FF983052C556E69D6CEDEA86518F9A5A301D03E6686D19E346780EDB5DB589C9047\
+C18E6CC6216D4A0C2E14505E744E3DED365DA0F1B1FF00EAD5FEC05E6BC9F7EBE8408AD89757C\
+A::\
+57FF544A0A4E5E892217382BE63F656D0CB49582414DA7AD5257C09AAC803D60CBCFAFCCC00E8\
+DA84D02AC0059CA11868996F8E163C226FDF23C7C7F7550AF30AADD03A484EA81DE3D6411BA9B\
+0642532A22A57D01953BA8D21814B72AF28EA499070938224BB8F98A0569F00BA55D7D4FE6813\
+D43
+
+35AE7:\
+CC072B3228FDB247BBCD39BE7CDE954BF98133426E79C6416E8658BE8DF09269BA3E5A5AC0784\
+065895D3E03355DD1DFD7EFF7F0859F317F8A32DF:\
+C78470AE335A28BB07ACF2DE39A1C180481C0F5DB37C0B60B97F68D584B24A3C39A4C315D2D20\
+04105D774D966892BB0659DAB963C298FBC7720E7:\
+6B18E5D6236AEB054CDE9DBCCC8710E2F8505F7836AD84B4F90BA5E1F96361871DD99AC16913E\
+8168A74A1B39E607B6FC0E47799A5E55970D53A9D5B0708D7BF7FFF88CB9EFBAA18F6A0101093\
+AD2272A1829594206B329783D299DD139F1EBF85C7FDB18330D91223ADAA6EDB317F6C54854D0\
+02F::\
+42F95CD54C8F50ECCE32D08DD5C66A8D2B5D20B3E3A5FF70CB772CB6706120D666EAE0C608E42\
+FBFFBB3C064D7810B424A640EC7E01930A76B2EFD6618A8C967F126CFECDC61476C7BD0981A0C\
+86A0A50B5F04166FBDE23479CBFF6430A6C5D433AD4BD7F0F0C9A47D060D795191FD49D8B71DB\
+F8111
+
+4813:\
+D55EB495A0EDD8784C918DB2C9905CADB34AA873865B61F959CC39F3944444E4E411CA490B323\
+FF92A47E780BF90FD861EB630ADA012F4B17C8FB19:\
+DF5304947138D4539E8D0DF7F5A521DA90D0A79468FBCE67108DAC5D904ED820444C84FE09C09\
+93DF8CA649AED14E7B77A8C8E96F3EBBDF6FEE063F:\
+407D8F49B0A0162D162DB9E89547FCA67DF28597E3EDF4024225A815CD16C113EBC2406DD8D5A\
+57C7828E80C81F87F6AAC25E69382C4F23B6DAD015EB4A373D48025188A3861E6DD5B6430CD21\
+EFBC0DD48B80225810831F23F75E4BE2FB5AE9A6191C633F073463FEC87B33C5B03D6ABC3DF82\
+5EDCE::\
+A9FD95925F1EB6A3D6D1396DDD8F459FE31135A07BE71DD9449596F457DF174124B2D9A4993D1\
+15055EFB664EDAFB73D51992E366D6010299E0CA65EA40CA76AF496EF024F72706C04AC618A50\
+823FC4647868F607B6CC6BB489AD6D2041970074452B8A0826D4BB0E9463D296C0DC54D241736\
+F59B506
+
+1E497:\
+F9DA4CF8C42981521AE47857D0A58BAA9B0D7EB223646D19E3D1F418B980FA9BE962AFB73619A\
+09D3B308E7E42AA3899FB9194C6325C3AA423CEC03B:\
+D6E7608CB975895E638794C140060A7B19794890E373274D24D29B786D1510B923CDD83EE844B\
+78035219E4ADFD085A91752B4A0DEFC8CC3411904C9:\
+677C0ABB673F029F63CDC4854CECC572EB8FD3AE9EC5B254CD64803CD853B8AFBB958399D077F\
+8F0F8DF0F109C780B89D317D293953D3C814F8F9EC1E4AAC029B6B895453D951090558DA2614F\
+94DB90ED3E62164D12E2A5ECA60234E153274154B82181FD3B060E84EFB9718F643ADCA016EED\
+2C89D40::\
+21E9AACA4B288AD3843FEA09406E17D94599BB610FFB02C86EA9843076DA91ED2CF55EE3D32C1\
+F6C53B5777DDA632D05403DFD77AED342521B988ABED48ADCA7FC1F4E3599949F257A5CC27102\
+18FE6F7E18554C9C26383198808C32B41A4600C19FF249291B788B8C438C999B2872F8CBA86FA\
+FE8838E96
+
+12B8D:\
+C6C04E18BA8EEA6AD830FE2652FF3547F4F693F41B681B516B2F397BE89C2562D259C0FC3698B\
+326290366331582F687C0DE212C30D1F573A5494DDA9:\
+D4D610D560F7AF67828C7602E12EC69F6665DADE3E339619DCCD53518009DA9EB019D4DF7D14D\
+29B1CAEB46AB04A414C50C1073E61BC85310144730F9:\
+F55E6FEA0FFF7EE032AD7C94208C337EE80B2AA0F4F2E0D066A05DC8FB528EA638539DB948203\
+33CA86D759086CF2E78E9695BED9B1DBF8DBF3E362801C685F688E36D7C41D37BF4B4DECAE181\
+6070518246FF9B73E807BB91B7057DBC74B8991E0B7E1C79FC1C1F87C780D7221FC476494D1F4\
+AB666DB3D::\
+27B21E28A286DD57100FCFD98CCE8C2ED2F1E2D2108E5A02BF96A0125AF563DA0EED6AF54BB8D\
+0D993BA772079EA644A2884E7160776F31F5F11D7BB47495611B30441F990FC107667F740C08B\
+660232EDD4A83484AE029E34326AD69E01EDE3461B54733580773B1DFE807CB54926980213896\
+7F59F59826C
+
+52D9:\
+ED557EA9DB53E4E24795FAA88F8414BC67C6354111CA244E2AC0C99C48A0BEF2FA69E69AECC74\
+F5E6DC79B0E2EF849C95E881CE9BD5B60516408D8A8D5:\
+D08480C28C9228B2E196E5F672272551E456E80086EA3A0300D5440978F35420211823516D2D1\
+30D444602DBEF4E68EAD7AF41F06E970BC95D9E90BA8B:\
+EA763D61DFA0624CFE25EEA744FF0AC80C5C85C4ED6A7E8C2303A1CAC4010931EF4D9B9414A98\
+ECB5300CAFF1AAFEE877813545EE56F7DD26A6005F142F771F4D3D1A97CA5995F91FEF25B1BB7\
+72B12AFC6A1D37A1CDA7175E5CE22571A3F8CB88664A06FC907FFCBFD5E6BF3FD2BFA98D5993B\
+D5D949EE887::\
+BC9AC00C07CB8BAB375AC69C14556D39DA85D019BA1D776CBC4857546AD44E857E616EC312839\
+E2A9AB55C3432373682255A1CC06BEB9CE7C3973E8B4FC02C1729B992AC40C0B371195E0A5CAF\
+80F074D0608CA75885F63C340C96A1E29237C64AA3D60F9EE59D425D757ECF8CC9009DE2B2AAE\
+8AC3786F639B3
+
+17549:\
+E60CA06397622C744F64ECF95F3264F1C8C819FE0D596877859DC7DA2EAF6CFE25907E4D018D8\
+FE457EE7113B09AE7E2D14B54A7AD7C1F294FAEA719A2B:\
+E3FE78DD4001FC135E4185121D5E8F6BD766DFE45B818DFCC1C2DC9F1E1CD4D1E9F5F7D42582F\
+36A918E7787D446E93DF1CA90AE6A52220D9A1D2683F89:\
+C0D448DE6D8C704B5AFBA03AFD8DCFE4CDCA0493A9D64D095B0A19320861E5F42B0EC566B82B1\
+BBEB4198815AE19238EBCEDF59FE26E4283E5942CF77CD1B23C5B901A542648D28051B5F99416\
+3C877D57FE27BB3D3B54CB929F9F4C24FC1B05F9EE7BCB7E1414DA3843032657FCE85787A1185\
+F2BE2C025D100::\
+C9E14845932307783E85CF97F3D9FCAB04C3872E5767E04AE1F954E7A45956CC7FBA483DB7891\
+36702B48446B177F8D36917674732972990053F5896D35D563C975962C4C405F522DD44E5D007\
+2AE7A403AAA1C8DB53E47E87534148B55CCC38896A8105A583D363D3C5EBBCA3076729F69E127\
+2B24F12AB7DC983
+
+189F9:\
+C630CD0B8D86A93343EEDDA96B43122C8DC58318F5664950CF34CECDC9EF3796F71675712EDD7\
+D08E675F491EFA99383EF1DDECBA36CFB4F2CEABF3BBD4B:\
+F9012CA0D0A2C91BC317819EA8EC23127357B84FF6F4B4995BD3DC6EBFDFFE8A7809C42B4C4D6\
+4267CDC77D29FEBAF99355F00B4D64872C7B4A466C7195F:\
+C42CF8F1ABF85A849137F421EE51F3B2237D052E89F62D2F8576EDFBAC6D926285096C4F5AB82\
+10D467F2ABC0A8C99FD39EF76EF51CD479B9DA20F082ED598E006E0EFE884D33B59D5F52E969B\
+D42F7997447BB052F70AE020E7E1FB6E8BDB90E5B8E53AE483CD29970184BA4BE51747BDC1D75\
+2B214497705D75F::\
+A2BFCB298708CC1D0F0E5B3817F669757CA02AF173BD04B6C77ABFD7446331E4E7E2526DA90D2\
+E79B60ADC06284F72FF053854CE1EF8E449FFB70333450887EFBEDB4BB833696105AF4109ECE8\
+E24FF9AAC5B16C3D3467B081967C1534782C29205706E199ED51D2FC87832C2ED5568EAD28F66\
+8009908AD66834A24
+
+26175:\
+BD3E5ED73F6D8751F6B7F6A9791AFB12A42AFC6BD4E2F73C14146945ABFD1073BFA87778B6805\
+891860A636884618ABB924E681C26C44D08A6A2354351EA5:\
+D14A005FB2E1CE65F51F36F10C23211BDA04159AA1E25510CC1A7BD643A76B923BA0ED4754516\
+1B50AE0E137EAC684D9064E258D0389818695715431B6695:\
+01224CC754FC5E4922AAE8D64BCF2EE50D13765F80317818CB3973B187BF3C17DED4B3AF27C93\
+8BD0E36F875A6D953808B590444A1B0C161189A93938063C80A78DB5DB689BC4AAC587F0DF6EA\
+119DFFE6CA9B67549005FA4FF451354174175D2AB236B3D6A1E604DF2D5ACAF956AA42B82A5F0\
+3DED91DA07039C464::\
+466BBAB71EF00D9436CDBDC02DA1C7CFD3D59AB48D60E82A87C39097BCF8DFF3D6807D6DD73CA\
+D16101245515ACD333DC808C9A894B9BD754F6921C518C5E9E16F71B6009B078E15F53CA3400F\
+0BD927D2416BE129DEE6035BFA74E3D8630A70055C229BA3B0AEA304D8F77A8407DD8998E124B\
+93DBD1EAB29CE11B558
+
+32C0D:\
+BFD70BCEA35FB6BC5C4C753CAD49FB6E86985D6F3687AAD9CACA49753676D121AADD87D175D17\
+EE5D80B9D6659B00289EC4475BF003D7D400177012ACCB72F:\
+EA764CF0C0D3583F0C4B4F9D096E1E4668439343F9A937EFFCC1A0E589BD3B64F4F14D745FF1E\
+38D720E581A64A3045F70B92A6BF2031E67EFF656749EA1D9:\
+A4F527A26115BC6402C7DACC1D8925A28D5AB036B56677634DEAE7560EE6F79DF87293564556E\
+155C8CBB934ABE781313AF7DBA88D65D0DEF4975AD6284A5077CA35CE49F1DE12FB46ABBB3072\
+C2B17FDDD93D010408F9790A9D1896FFA362C43FE3B61B6065A09F715E97B353BB471F2AD94F1\
+15CAF8A5FDE6B91826E::\
+80C7B635AD6C6499764DE4AD8F9EE1654FC83763B4097E4AFF6713EF1B3C7D627B291CDAF41D9\
+D8567758D6F9107AF7ECD0021DA4F54FBF979F1C1AF24993B46347008F51BA00F3AE1386B5C9A\
+D29B378FE434CC6B620CB2239CE94D5C2755FEE67621649B526505A49451F4469B29003DF8396\
+C2213475FE7CC671CF0D7
+
+D6A9:\
+DD24EA4BA93BCCEA6C7676405EA6F04F13838390AFC51713DAFE299D36362C525F6C2D1CD4DB1\
+5DA08B743005F46E243BF34F285A9458575DD61C31F12A2DE5:\
+C152185775ADD140C1FF045BCADC81A81DB36BDFB61B6581F78B29B9130F8B7F3D31C508524E0\
+B487F441F01BA831D8C05F23CF47D14B35DFA5402F0A9C003F:\
+14815E63D355877FF38F110A6B5BBDC86633936B9B28669E66E6DAEBC85A213D40C63080C5DDA\
+21237D04602C02DD480E753E4230206DC216263E56E129566D094D5B574ADAD461C04D3D20145\
+855F94E02ADD5854E89C48EF18330C5F9BBF7D1EC9638E4ABD835755DB84ADE864E3AD2DF04D6\
+26E91ABD952EF451292CB::\
+2A432208D0CC726487A772598BE3DA4799B484D4C28ADF06E2A914BDF7ACF826080BD56DFCBC9\
+C1E8DB37AD3D57E2EB42CC5589E4DFB2AAC63B7F61A05FF744CDF6D68441694947B2EE1003D33\
+E25F706C4EA70EF39DE831B520B39FB7DC02EF7A9427ABF86900053DD316BDE944ED001CAD53F\
+4C6E68C336B3050AF52B081
+
+34213:\
+E35B81A5A1B6199B689C0484C332C4E9CF8237BA3B3215A3C50B9FA9704BEE13BBF8D96B8FCB7\
+16390A4A52D9E0D8066F4C171DE3007C0E3CCAF7E7ED0A3974D:\
+BBBDE5B062860702D894E1B70C555330E8CAC1688484C94DD8C9029487E181FD32B3E4A263789\
+43B5AA33DA24676E240973076712FFD89A66A9B58C5BA83C69D:\
+96BA67D8ACBE483DB6CADA644C2D8A30710395047775A43D5DEC9F2C1E81D2B5D3D926B27DE20\
+7A7000189AC87F10ED06DE57793C301A9B05958537C9E5D486B3769BF41E9B18904C5D1EFF9B5\
+A90C040E1E5FF21E872A06FFA9C5F0BE274A346F425D46BD3B666CE2C0D9843DC4067C04CE019\
+FE447131D78A610A5BD648C::\
+7A7667774523649C72636F1A0599A0D1865B32A14E9C50201849A6DAD8AB96D1CBCE55054BAF7\
+31947DDF6645937C9C39D9F11ACB9D2A3DBC7C16EC7CD5CE13AC82C85DDE8213E769A6440B67C\
+1A78A1A8BE142D50A9CF127EA9BE1BA252B21460A4C8A196B50D7DF022E289B6C0977D13C2D57\
+FD0F4F90675C7E8F018EC780F
+
+# RSA PKCS8 format: KEY:message:nonce:output:password
+
+# If password is not specified, the key had better either be an unencrypted
+# PKCS #8 key, or encrypted using the empty string as a password.
+
+[RSAES_PKCS8/Raw]
+-----BEGIN PRIVATE KEY-----\
+MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEArpub5dL9a8aZji3a\
+w3205ODGa/HgXylGNDWCanG5V6smkqiDZfpr2Ldh+HL4hZCIe5NOBf3DsTCocit4\
+BMyBxwIBAwJAdGe9Q+H+R9m7tB6R16kjQ0CER/aVlMYuzXkBnEvQ5RuqUIthLugh\
+lUEHgzdj+vd8magYEJnkatQ3v43GeIYYuwIhANrmAnvA+cpZoFav67qxSSn8jSZl\
+A2QMncJquHvLvBRNAiEAzDPU9d6kbx81gAO0J9vUI5iKA4gTiQRUkmgeUoRHSGMC\
+IQCR7qxSgKaG5mrkdUfRy4Yb/bNu7gJCsxPW8dBSh9K4MwIhAIgijfk/GEoUzlVX\
+zW/n4sJlsVewDQYC4wxFaYxYL4WXAiAxtWZl8m1fSBhTkhLJJ7ZZqAojlyTkPYJZ\
+q3JR3z0fZg==\
+-----END PRIVATE KEY-----:\
+01B40EAED76EC2A26C41DF58CC23516E7974537ADDB1D3ECD0DCBAA4F09458AC\
+49675A20D51CC2415DA2992AC5EA983E5EEBB83B9C8C276C68E11158756904BE::\
+32E6A9BFF82BF351E96292947AC218E977AEEB069D09CF438DA0B96478DF7A18\
+53EB8BA770C16B5024D31B6C2D2F83E867AA37C9AD42E7F13369F171BDF2308D
+
+-----BEGIN PRIVATE KEY-----\
+MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAxYJRkiu+shjNapT3\
+ra+jaefGrLY6mH96JR9cbnBCZhNktqLa8Cn0y4rJVGuScwtqYKpmy46jS3d+AEqy\
+MOf2fQIBAwJBAIOsNmFyfyFl3kcN+nPKbPFFLx3O0br/psNqPZ71gZlhFzvXDpH2\
+pis8mkPPCn15KPe81S9vjaZVYzxiAZLpVWsCIQDmkmjzvCF/8Eq8ReiBlWjA1b0H\
+FV+IcMbHs4RzBDv2KQIhANtKd1FZFnuaZSWozIEhbOwXUh/vB8ZhMKFyMzzQTgA1\
+AiEAmbbwon1rqqAx0tlFq7jwgI5+BLjqWvXZ2netogLSpBsCIQCSMaTg5g79EZjD\
+xd2ra53yuja/9K/ZliBroXd94DQAIwIgZjnLdn9+HnIRhfrix52NDS5nY9yaisGu\
+kQlWG2ag2AY=\
+-----END PRIVATE KEY-----:\
+01453FBFA6B146374602261D86822493E2CCC960B75D2A124B182EC70F22FFBF\
+673F7E0EF0C54536C76B534DED77E1D044AA30FB075A0D52733C19825E1941C6::\
+AAADBBBEA2716C35EAD89736AA97A8FFF0078A07F48A9888294929B8917297CC\
+53AA9CBA9FA9D80791F24F749BB1133D0A48C2117572DB73C5813881F4B5087A
+
+-----BEGIN PRIVATE KEY-----\
+MIIB4wIBADANBgkqhkiG9w0BAQEFAASCAc0wggHJAgEAAmEAotk6TE/qf3yBOcQL\
+jo0t6KVeOgtNLwCwP2dR7wp4bFTWUpMOx/Y4dQ+2izzRl5neyEHxIaUc11jMuua1\
+s+HW58L3WifM04yT9BQ5gkxxZuqA3+UjKeD9fs/qP+y0CDULAgMBAAECYGCO4xVa\
+kVWUMl9ZEe0tYto+K3fJObOz+c0uaxOMpsi9KPN/RNVl9iXa8kbvAeudDNx8FfI7\
+1u9FDLFfmZsSqDR/VVAvkMwXu4zg5uc9xmwhefdY+URTdt9IshAdlgMiaQIxANJ+\
+YtpDxwL1ROjnNEWKnrCd4gVsMBSsn+zRw0pUw3iVDt0kVllxXVMhbR+NNNNRTwIx\
+AMYN9PgfUr07e5p/3xE5rXJJpBTKktVB0APHORafHsauhs2rBd7F62ZWMfdTdb3Z\
+hQIwG9557hYNMloQ7pk19YMd8Zplw3wIfaRBZFR9e8jvPHbXyfW2rQ7yYUBKt2O1\
+u8jHAjAd7uQUUB+gLApNWoArSU1WlZyv68Hva0f2GjkdmyT6oEwNb4iul7kxOVvJ\
+5ppH/EUCMF13TTGrTH9qiNUHOoS8RLZmPoNwjePw02BYUBcLEwhUw+AbR12FlNf2\
+O3iiv1ounw==\
+-----END PRIVATE KEY-----:\
+010E1F619D8F90D37563050B014DEB3FA3E9B735F8D28D625682D6A4663E6B33\
+4C8B94E91A24BD8F88C29A890F85C9B36F80E8675275C9A8F79F4D5DDDB89129\
+4325125D4ACFECD291875BA10C24547BA43CE2F7B1AB9FA84AEC0627A59750E8::\
+296F935C38845C940F820C379F8032101EA4003CED8BEEE212F2C6F72EB430C0\
+ADF48B7ECDDB296544D8FAE80E2FFF084671E88A88334EB8E718FE8B2524358C\
+CF9EC32CEDF93087CBD39E784FA66B3BD32A427D69EEC93607A8352955C774E1
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIICETAbBgkqhkiG9w0BBQMwDgQI164w6OtruCcCAggABIIB8HCD8Ae9Zia6ppjK\
+OgZTy4I85VqUgHT1lcOjveqRTtnKeexhbhwR+M8kN4p4wiCHoLu+kNp2lX56Id7+\
+wt+PnN4HofDGkepxS7bve4emEIJN3TLMS1ux17Ste7cJMs4KAKLbtwh5E/slQeAz\
+/uEpTpKnyfDXbI21GxRdiJtHQuw7z+RpX1uuOIZB9t4dE5QSASdbtDJsrvekcNaV\
+tDxzWkZ1BoXcf2otaEW9yzFWlVCuerzc+IcsAtyt3GUuOkLAoY82TQ5XuJFpc2XX\
+J1GVtncjReFdzLyb1gZePiEyE9TZDtbzR2Q/iJkJE61hgNIptCwhe4nvHzMs+fGV\
+8zsudkfzvsgwb05qHt9CJVSs6Hd0frCJsqahpQSsiNUoV3SD2EsH44T5gJrTg3Ke\
+DJu46uIpMyM8VbFc5Ra6CSOuD5udSx2yV1klx7bMHWONzTOCLZnaZVT9cKC/4og/\
+em3A9OdPrfAZouqZsQ3j8u7ZS9Qun9WOZApjRxD1vObuz2VPHglIxp/ckvDJ8BJt\
+Sb4QEqFwe+Vd6tBiBTmK7Is8Fji5Ummbx0tLMSd/Xtw6jBtrrzyf85ywnFAAoTyZ\
+Or4ey/Mf5KDp4LscmXVgkAauBn/Q/wWjK+rdjTBMUW8eQFiLsQnv6087sLSdEUSm\
+jg3w4Mg=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+012E1CD97DB414715594E404B8B0BA9C3928CDC2CCF5F71C712C462B7BC44B90\
+F36869701C7DE17111C575CA752F66AE583371242868409A9486C5104B10A03E\
+780AAE94878F0599547A63C9AAC97802FCE926255167BFE5ED84F5389496760D::\
+3ACD3EC198014D833BBF4DF281C82C96777C9534584CC926F9DEC42E7C1F846B\
+582A267B95EE4CDAAEA7AA953330BE584BDAF75089FCAF66D386AFAE39C9BF70\
+B9D21C0E4C6590C67302AAC0A8917A3F33A39F7F921820E8DF6E6DF85CD6B6E2:\
+password
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIICoTAbBgkqhkiG9w0BBQMwDgQIXbcBBmYh+DoCAggABIICgFFUCKS9lRmjJR33\
+Gndp+hSXD7IHV1kpR6ayZcbGGfYlqsDc63yaWcLiROTQzZ+DMYxaFxePhd8tKtLP\
+38iw/MyXa6IRAYA/C6JHPsXATrKRc+Og8cD5pCxc4STCrt0Wg/SCWl7V6nbnnWco\
+vfOBUHXmflnvQYMEUahsu6lZkR0wJeSyK8G5dMKb4IZ6vOffADQ0U8UuYYK+ymfJ\
+bv5XKXhfje0Iesg6eReLdQMxLI1CURCg4oio1aQsfTosa0wJ9deSry0cjXk7K4c+\
+7MROei4UWXT0Otv1CFYR6zbmBrFbds+CY7EaqoVzgsBcNPLmWWdFlrKebquGc8xy\
+HoIvJ9e/YSnE+YU+C/LapQpmyXoqcQB/Gr4Zdrb3+5ED5WYzgVY+jw8z2f2DAGJt\
+bdzzL9JvFuEG4iZ1vNi9TSy9CyEgoqTyxfcLlHZY9BG2iIhu8pajkjnYmrxodSQB\
+uRyYNJ/T9vFOJGUWHbe9Zii82TedNUBnF0G0e/aRMxBT6wQUrsB4Q2P6ntIIHuaW\
+8q0lhOG7MRnC1FtQ+qSrzpMTX9i/01F0YXegnzeiww4ROMTcO4vUtIRmF55LZv0v\
+8YOjZClzYQP6nNhpHX/+jDpZy+4GFXPVmiOhqjnqJtRbclu+CcDZG6NRFH2V9vrg\
+P+leIuPeA4hV20lbkG3xxrlnxEUAqMNCC+uwj1zTVdNKY8AlWK7umsdWiAPIIITY\
+GQCn/D/Jom7PzbMSVa4HmvsGntPxXP4PxrwErWbCNOZpE2fe0y+tiZidaoQZqmUj\
+UDvM5gYsamu9O5UcEes6QneMr6+NakYwWNl14V3jNB480sI5z8R5bmJW+tGRmYr7\
+/+MveWY=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+01C4B6CAAFF5ABF4FA027C945EE26974E77DAF3FDE5F51899CD64DD7DDDCAE09\
+A164D350597E445481C1E8DFA352538ACF03C9AD621A37FEF184D5CE6083D701\
+E8AB5141299695AA577E89FAD0DD849FE04E4C4268834159071628689AFF6982\
+AABBC3D451597EA8D708A2A7E52646C5749207DD1648361D5F5E85F95EEF7B08::\
+8095B914D477DE2AE3F2AC7648B32EB497B7C1F4FF298D4B82F0A77298574E94\
+530DD9FF57A205499100D5920999182E1CED1F25971B27C0C3BCB06F0507305E\
+E90AD35A00469341B47A6E2E1BB7DD792F6543F74D1FDC2CDBD433DC7C9728F5\
+58DA656E5134FC174723012151360E0310B31D4112FF5CC5829B0709F8EE7303:\
+alt.alien.vampire.die.die.die
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIICoTAbBgkqhkiG9w0BBQMwDgQIfbv0EM4sRhcCAggABIICgIOfgSDzsjOhLX+b\
+1h3lXZiIw4nhiyV9q88CDEyB0x5y+aNkWipVetWoRPqZ6oAD6qE4yGQRhJuSa0o7\
+SzHQlZ7aqBAjtiNXw3Q7yeAP9lagXLolhnIovOKbhyj9iyblgKQgzTerbevaDgp/\
+jYTWXutKLhvjZeYVH1lRBgQYw3z1jIQQDRxw5ok4sYwD0/fpv9WtQ0Rr7XvdDRDB\
+PUhDqEu8GelR+qO7yH3M8Q5qhnTxHRpDWRU+K7f3XRNwJQTdiwWJtSJtUdrSpqYV\
+cqhDzejL3BJZRTcMbjsmq/uABwL5X9prXG2M6j2+9SrQQTWFQrLsyRIGXfKbKN8i\
+wFXaUNzGFKMskk7N6ywkiLMvAIhcaDO2ATm1bHunAcTeuIfdJfdpSWcQ6oz9x9Re\
+ACnWiQ0CRRYQlSYib/u0tt28rwOvCj4F/dSSUMyXegVz0gq3koGNwk3pbHEVvvUm\
+1bqiGQSr2d7DJ+ffe5IoIWB9cUgLeTFP4BBC1hegjDfTsaGEYPVFv5Qxi6W0BaN8\
+cq/HVWofFqu9jXeGgFq1W0IjYU7zftoVc9DyKor6ffDoDzYbNcivd8OcDydLnRVI\
+aofPN+fBAREXHuSz3cYr+arBe5PLbaHTz0iCi4zZUCWU83Usz8oLAtwkK/Ta4rDR\
+KLdv8RB3C3z4r811tWuTrgvoZeG2a4Xa94rb6okHWqOXbSHV00Z2eaqqLIuc89eX\
+JDu1iJrfARsaCN/Xu9unUnJWBRcqGzWgDRMSjnOoUhTCtjKqF3WDTsOfS1n8RSQs\
+F0zMsrXMiHXrWfcN4gDB8q/uz/laLapd8BTp6IZ0oygsHc9J5OHy36TLfoPhObo5\
+HcVJbxc=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+01C84780E9F341C7AC81703D1E1727D134E08DE7F80636F38284BC4EE3D55F95\
+9DA715879A564E46D8BF83F6D6AAC70B8A55F2825B2875DDAC312B90068B25A4\
+323A2BCC9079126838965F0F40261ACB7B0C4DD634C3B3E1F4DF71FB6A969F9C\
+D0CA6860437AC97C10288B514EA51CCAB169A0E52C54C62133371C9DCDBB399D::\
+A22AF2E3FDC9AD8215510CF6B55118A720DE36C84DE8CE00FA769325E03BB0CA\
+81BBD2960E834543443472E58754F9ECDE84D32B4F7CB2C2A5A14A60CA91C908\
+0D3AA675E56E53B2198627938C9B00ADAC3F07A50AB0622833F2DAD34C73D0EC\
+5717613E02A58936EEA60928C1A894C589FE4995607B1AF62C2BE8FD3E8ABB83:\
+foofoofoo_bar
+
+# PBES2 encrypted (DES-EDE)
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIzgSAjcnspfUCAggA\
+MBQGCCqGSIb3DQMHBAiupWhsYLF7rQSCAoC8ySMPx/GEUvnlb4pj/KjYaeyUJ7En\
+9jzyLKNhfP2L+aCLao3FRSXEz3UL/Bzqx15XW96xfADw+LOXbVfM+HDyDwTm8W33\
+XQbjSyTCf+4hG+XZdzCppTo5jlGLv+3St6Tx/V4D4GbN7mZnO9tSHKim2qPzITE4\
+PCiV1pzDkOFDz/BtOEqL4AQaelBHldyyTrsSBuBVk5iN20mZ5SiEA7bhSuyBxIYW\
+QAqo2/M1JSvqXzXfgcLUNWG02ROmEc1hEvGIdZZAnjVHRUaC8oecTZlROCGyQ0ec\
+5HJt+hSVTtjVvVYRyR9k0Qn+E2tz1VBLFTxXdL2bD+vbGXhHUKLG0NM1Ks9Xea7s\
+YHTGb1wvwxAGh9MoK4bWeEl14fDRIlDlEnHtt6CpF+hXhOcI1UU9MHDQhXqA6E5w\
++0FtnGMdxd/RgSkOvkvmMzTlbBGnA2W93R3Vv66iiDVIUO4DMAxOSlH4lZmn4kiG\
+gXHIu2BpYiR/CaeKCGDW1L5Ii/T5gnxYz6rKE1NJihRlrCplGe3ip9Ra7K4h+yA4\
+S3P2OuTjImCwBI1uL65vwnPLvdKuA6exGtI6eTyoyL3XN8Wt8LAXQwn1ijVNMXej\
+f/9zQnrdkhgYwQU5yvCi5yi5ewGi+Lqfo4rxJV2lt2b2wDfHoUULFVpIHlpUsWnR\
+aVIwa0t7S5gq/lFRxbnhsHBREJgZWP9kN1XHv8hrEcyedFO4aFj2J6I9GX1vvqrp\
+F5o4a38RBjfmR8FDsH9Au7IvuuH/TUipBybgCbIUyvQADexibuthq5MI2lpmS53c\
+vo6QOp6bwusFSPUE/qbDoW4lX9SWi3vF/RcQs1j7opsDbhqQk+G05h0R\
+-----END ENCRYPTED PRIVATE KEY-----:\
+3BA94D8CC1749902F4599D63A527DACA74870714BC794813247D000DCF31BC57\
+E285CE5A1236EFD1956723B800C3C19094185EAAD7C744DA4917E34D3DCE5FCE\
+F4E6D797510B7A5BA67087ABBFB69FCEE5D8A98AD9A3D3B2AEE9876B9358562F\
+460A0D6C4B5D98E3D305D6B944832859CFB01072C6FCEB5D0558BA7D101458BD::\
+1185126E43C7B5F8D15523E65DAEEB6526CDCF2C8901DC7A1EC836C22CD4C344\
+1C24B16AC8ABC3E00A95C6BD03EBEC74DCA1EBD0DA6E61395452587B36DCD734\
+7184C9005177839FEDA5273007DD0AAC0E8C87A3EEA71F7DBEDDC7FDDD637A2D\
+FCA2FA1215DE8C332ED4BA093B6443C65B32AF294D8A56A1BF8702C1B9086E36:\
+foo
+
+# PBES2 encrypted (DES-EDE)
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBoTBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQItEsDvV486kcCAggA\
+AgEYMBQGCCqGSIb3DQMHBAgzfU6L9FUlJgSCAViXz0OqV1SBvbiF0sEH8GsMQJwB\
+Q1RVEjyO8uncdbujalyVCeLukh/H0W0unlgceVMSdN7/nQBitkGkvLSoWRv9hYc/\
+UlkCMcq4R3Fx2hLF6Yquq/DyBgF57LVyOpomRa/Kj8TYjfZkx3JXJnRsqjoLhTbH\
+USzwv3DkKV5gljZqLTXdPAYFyWw28GAb+3iNfzwhudblH5JXaZ3X0GWSJEium0UC\
+WPpvBGlNOUyoMFo44q100ywORYAWl/Cc7UNXWMFLQT773FypPsx+bcWpA6Lmx665\
+POrVFb4rTh+AGX9f6Kp/yfgY1VJxuju55imTaHIHZUf6phAnwoTDI+UIZTw1IwHT\
+JdYbYaxjEZglCx0u9wZT5J9IwQVKT7/eLjowV4GS8zDr/tlssDMixQboJ/dRmUYp\
+jcwhnv36cThFx6GoqWMA7ShTVT//QDpvBbebuDOnlSmqq+5qmw==\
+-----END ENCRYPTED PRIVATE KEY-----:\
+35489193F2E4B7B7FC7A52CB4A3AE2F7F97C02CBF43A60934CBD8AC221592666\
+92767C6C587BAE7B73E63EA470A07EA67927923FEC2ACDDB1ADDDAC75E8FFA15::\
+29772BC15B6095A66060CC76884B3E4C77A2330A880D9FE64B007C1DF792CBA5\
+B3422F9BDDF51C48E567F114776566653A7F7DDDB8686BFCEBC94B224D7CB0B3:\
+i_am_very_poor
+
+# PBES2 encrypted (DES)
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBnjBABgkqhkiG9w0BBQ0wMzAeBgkqhkiG9w0BBQwwEQQI9uqEGDMT/W0CAggA\
+AgEIMBEGBSsOAwIHBAiMfWZMW3qofASCAVgcAhB3yW1aNLIQaoo+WlTe6IRLjKWF\
+itkCW4/m6qJRvR0Yy5BTyDy5mD4QyOcVwvPGUPs6q5R+tjfbBb1orWttBDXvQn38\
+OMD8qV7voCVlDgljidAtSLmHOHy1jq7gCeyKdyC3XEMX1RZa9NIS5/fyJtrcQKxd\
+ktclLolFkiujbGH5i+LiRHWJBE8+9StxBdO+v0PE0FYR7vwxj05xKieg4UiKAVfp\
+C3+iX5XpVqMI+FTqtz/+4sm51ZgGRpz3vmNRJWqh3VqDWiwN8/w53qceDfjmNm5T\
+SfyA0K0dfSkaylprLFd666567HjDXGJlxtA4nM8N1yahRWMz/ufSd1u70dfN9l2L\
+mjghOP+WWverl+Td1cNHRE7/rvkOuhwLJpC4rnZHA4rnIxzwcQmsapk8rsu0S3I4\
+tdZEBhRZsoswIVQo030K6x9DZHMSIpghSc6BlMmu2Jbnew==\
+-----END ENCRYPTED PRIVATE KEY-----:\
+35068206D5C287A47F95BD8ECD11E557D86EDDC993FCAD94F03D86C1BC97E2B2\
+68E637ED1A6B0EE459214E0F61099B74469AD36A3A37217182C42B0C48A4B413::\
+261D5A9298BE592400EE703BC27C2A16761F6C855607D9AA62A9B36307FC5100\
+6EEE06E59C55C9606FFBCF8DF74A98B5C9FBD17F0D7ABB867B4A7CB8DD5DC15D:\
+give_me_$$$
+
+# The first bunch are from an RSA DSI document
+[RSAES/EME1(SHA-1)]
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+6628194E12073DB03BA94CDA9EF9532397D50DBA79B987004AFEFE34:\
+18B776EA21069D69776A33E96BAD48E1DDA0A5EF:\
+354FE67B4A126D5D35FE36C777791A3F7BA13DEF484E2D3908AFF722FAD468FB\
+21696DE95D0BE911C2D3174F8AFCC201035F7B6D8E69402DE5451618C21A535F\
+A9D7BFC5B8DD9FC243F8CF927DB31322D6E881EAA91A996170E657A05A266426\
+D98C88003F8477C1227094A0D9FA1E8C4024309CE1ECCCB5210035D47AC72E8A
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+D94AE0832E6445CE42331CB06D531A82B1DB4BAAD30F746DC916DF24D4E3C245\
+1FFF59A6423EB0E1D02D4FE646CF699DFD818C6E97B051:\
+2514DF4695755A67B288EAF4905C36EEC66FD2FD:\
+423736ED035F6026AF276C35C0B3741B365E5F76CA091B4E8C29E2F0BEFEE603\
+595AA8322D602D2E625E95EB81B2F1C9724E822ECA76DB8618CF09C5343503A4\
+360835B5903BC637E3879FB05E0EF32685D5AEC5067CD7CC96FE4B2670B6EAC3\
+066B1FCF5686B68589AAFB7D629B02D8F8625CA3833624D4800FB081B1CF94EB
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+26521050844271:\
+E4EC0982C2336F3A677F6A356174EB0CE887ABC2:\
+42CEE2617B1ECEA4DB3F4829386FBD61DAFBF038E180D837C96366DF24C097B4\
+AB0FAC6BDF590D821C9F10642E681AD05B8D78B378C0F46CE2FAD63F74E0AD3D\
+F06B075D7EB5F5636F8D403B9059CA761B5C62BB52AA45002EA70BAACE08DED2\
+43B9D8CBD62A68ADE265832B56564E43A6FA42ED199A099769742DF1539E8255
+
+10001:\
+0159DBDE04A33EF06FB608B80B190F4D3E22BCC13AC8E4A081033ABFA416EDB0B3\
+38AA08B57309EA5A5240E7DC6E54378C69414C31D97DDB1F406DB3769CC41A43:\
+012B652F30403B38B40995FD6FF41A1ACC8ADA70373236B7202D39B2EE30CFB46D\
+B09511F6F307CC61CC21606C18A75B8A62F822DF031BA0DF0DAFD5506F568BD7:\
+8FF00CAA605C702830634D9A6C3D42C652B58CF1D92FEC570BEEE7:\
+8C407B5EC2899E5099C53E8CE793BF94E71B1782:\
+0181AF8922B9FCB4D79D92EBE19815992FC0C1439D8BCD491398A0F4AD3A329A\
+5BD9385560DB532683C8B7DA04E4B12AED6AACDF471C34C9CDA891ADDCC2DF34\
+56653AA6382E9AE59B54455257EB099D562BBE10453F2B6D13C59C02E10F1F8A\
+BB5DA0D0570932DACF2D0901DB729D0FEFCC054E70968EA540C81B04BCAEFE720E
+
+10001:\
+0159DBDE04A33EF06FB608B80B190F4D3E22BCC13AC8E4A081033ABFA416EDB0B3\
+38AA08B57309EA5A5240E7DC6E54378C69414C31D97DDB1F406DB3769CC41A43:\
+012B652F30403B38B40995FD6FF41A1ACC8ADA70373236B7202D39B2EE30CFB46D\
+B09511F6F307CC61CC21606C18A75B8A62F822DF031BA0DF0DAFD5506F568BD7:\
+A7EB2A5036931D27D4E891326D99692FFADDA9BF7EFD3E34E622C4ADC085F721\
+DFE885072C78A203B151739BE540FA8C153A10F00A:\
+9A7B3B0E708BD96F8190ECAB4FB9B2B3805A8156:\
+00A4578CBC176318A638FBA7D01DF15746AF44D4F6CD96D7E7C495CBF425B09C\
+649D32BF886DA48FBAF989A2117187CAFB1FB580317690E3CCD446920B7AF82B\
+31DB5804D87D01514ACBFA9156E782F867F6BED9449E0E9A2C09BCECC6AA0876\
+36965E34B3EC766F2FE2E43018A2FDDEB140616A0E9D82E5331024EE0652FC7641
+
+10001:\
+0159DBDE04A33EF06FB608B80B190F4D3E22BCC13AC8E4A081033ABFA416EDB0B3\
+38AA08B57309EA5A5240E7DC6E54378C69414C31D97DDB1F406DB3769CC41A43:\
+012B652F30403B38B40995FD6FF41A1ACC8ADA70373236B7202D39B2EE30CFB46D\
+B09511F6F307CC61CC21606C18A75B8A62F822DF031BA0DF0DAFD5506F568BD7:\
+2EF2B066F854C33F3BDCBB5994A435E73D6C6C:\
+EB3CEBBC4ADC16BB48E88C8AEC0E34AF7F427FD3:\
+00EBC5F5FDA77CFDAD3C83641A9025E77D72D8A6FB33A810F5950F8D74C73E8D\
+931E8634D86AB1246256AE07B6005B71B7F2FB98351218331CE69B8FFBDC9DA0\
+8BBC9C704F876DEB9DF9FC2EC065CAD87F9090B07ACC17AA7F997B27ACA48806\
+E897F771D95141FE4526D8A5301B678627EFAB707FD40FBEBD6E792A25613E7AEC
+
+10001:\
+0159DBDE04A33EF06FB608B80B190F4D3E22BCC13AC8E4A081033ABFA416EDB0B3\
+38AA08B57309EA5A5240E7DC6E54378C69414C31D97DDB1F406DB3769CC41A43:\
+012B652F30403B38B40995FD6FF41A1ACC8ADA70373236B7202D39B2EE30CFB46D\
+B09511F6F307CC61CC21606C18A75B8A62F822DF031BA0DF0DAFD5506F568BD7:\
+2D:B600CF3C2E506D7F16778C910D3A8B003EEE61D5:\
+018759FF1DF63B2792410562314416A8AEAF2AC634B46F940AB82D64DBF165EE\
+E33011DA749D4BAB6E2FCD18129C9E49277D8453112B429A222A8471B0709939\
+98E758861C4D3F6D749D91C4290D332C7A4AB3F7EA35FF3A07D497C955FF0FFC\
+95006B62C6D296810D9BFAB024196C7934012C2DF978EF299ABA239940CBA10245
+
+10001:\
+01BF01D216D73595CF0270C2BEB78D40A0D8447D31DA919A983F7EEA781B77D85F\
+E371B3E9373E7B69217D3150A02D8958DE7FAD9D555160958B4454127E0E7EAF:\
+018D3399658166DB3829816D7B295416759E9C91987F5B2D8AECD63B04B48BD7B2\
+FCF229BB7F8A6DC88BA13DD2E39AD55B6D1A06160708F9700BE80B8FD3744CE7:\
+087820B569E8FA8D:\
+8CED6B196290805790E909074015E6A20B0C4894:\
+026A0485D96AEBD96B4382085099B962E6A2BDEC3D90C8DB625E14372DE85E2D5B\
+7BAAB65C8FAF91BB5504FB495AFCE5C988B3F6A52E20E1D6CBD3566C5CD1F2B831\
+8BB542CC0EA25C4AAB9932AFA20760EADDEC784396A07EA0EF24D4E6F4D37E5052\
+A7A31E146AA480A111BBE926401307E00F410033842B6D82FE5CE4DFAE80
+
+10001:\
+01BF01D216D73595CF0270C2BEB78D40A0D8447D31DA919A983F7EEA781B77D85F\
+E371B3E9373E7B69217D3150A02D8958DE7FAD9D555160958B4454127E0E7EAF:\
+018D3399658166DB3829816D7B295416759E9C91987F5B2D8AECD63B04B48BD7B2\
+FCF229BB7F8A6DC88BA13DD2E39AD55B6D1A06160708F9700BE80B8FD3744CE7:\
+6CC641B6B61E6F963974DAD23A9013284EF1:\
+6E2979F52D6814A57D83B090054888F119A5B9A3:\
+02994C62AFD76F498BA1FD2CF642857FCA81F4373CB08F1CBAEE6F025C3B512B42\
+C3E8779113476648039DBE0493F9246292FAC28950600E7C0F32EDF9C81B9DEC45\
+C3BDE0CC8D8847590169907B7DC5991CEB29BB0714D613D96DF0F12EC5D8D3507C\
+8EE7AE78DD83F216FA61DE100363ACA48A7E914AE9F42DDFBE943B09D9A0
+
+10001:\
+027458C19EC1636919E736C9AF25D609A51B8F561D19C6BF6943DD1EE1AB8A4A3F\
+232100BD40B88DECC6BA235548B6EF792A11C9DE823D0A7922C7095B6EBA5701:\
+0210EE9B33AB61716E27D251BD465F4B35A1A232E2DA00901C294BF22350CE490D\
+099F642B5375612DB63BA1F20386492BF04D34B3C22BCEB909D13441B53B5139:\
+4A86609534EE434A6CBCA3F7E962E76D455E3264C19F605F6E5FF6137C65C56D\
+7FB344CD52BC93374F3D166C9F0C6F9C506BAD19330972D2:\
+1CAC19CE993DEF55F98203F6852896C95CCCA1F3:\
+04CCE19614845E094152A3FE18E54E3330C44E5EFBC64AE16886CB1869014CC578\
+1B1F8F9E045384D0112A135CA0D12E9C88A8E4063416DEAAE3844F60D6E96FE155\
+145F4525B9A34431CA3766180F70E15A5E5D8E8B1A516FF870609F13F896935CED\
+188279A58ED13D07114277D75C6568607E0AB092FD803A223E4A8EE0B1A8
+
+10001:\
+027458C19EC1636919E736C9AF25D609A51B8F561D19C6BF6943DD1EE1AB8A4A3F\
+232100BD40B88DECC6BA235548B6EF792A11C9DE823D0A7922C7095B6EBA5701:\
+0210EE9B33AB61716E27D251BD465F4B35A1A232E2DA00901C294BF22350CE490D\
+099F642B5375612DB63BA1F20386492BF04D34B3C22BCEB909D13441B53B5139:\
+B0ADC4F3FE11DA59CE992773D9059943C03046497EE9D9F9A06DF1166DB46D98\
+F58D27EC074C02EEE6CBE2449C8B9FC5080C5C3F4433092512EC46AA793743C8:\
+F545D5897585E3DB71AA0CB8DA76C51D032AE963:\
+0097B698C6165645B303486FBF5A2A4479C0EE85889B541A6F0B858D6B6597B13B\
+854EB4F839AF03399A80D79BDA6578C841F90D645715B280D37143992DD186C80B\
+949B775CAE97370E4EC97443136C6DA484E970FFDB1323A20847821D3B18381DE1\
+3BB49AAEA66530C4A4B8271F3EAE172CD366E07E6636F1019D2A28AED15E
+
+10001:\
+03B0D3962F6D17549CBFCA11294348DCF0E7E39F8C2BC6824F2164B606D687860D\
+AE1E632393CFEDF513228229069E2F60E4ACD7E633A436063F82385F48993707:\
+02E4C32E2F517269B7072309F00C0E31365F7CE28B236B82912DF239ABF39572CF\
+0ED604B02982E53564C52D6A05397DE5C052A2FDDC141EF7189836346AEB331F:\
+AF71A901E3A61D3132F0FC1FDB474F9EA6579257FFC24D164170145B3DBDE8:\
+44C92E283F77B9499C603D963660C87D2F939461:\
+036046A4A47D9ED3BA9A89139C105038EB7492B05A5D68BFD53ACCFF4597F7A686\
+51B47B4A4627D927E485EED7B4566420E8B409879E5D606EAE251D22A5DF799F79\
+20BFC117B992572A53B1263146BCEA03385CC5E853C9A101C8C3E1BDA31A519807\
+496C6CB5E5EFB408823A352B8FA0661FB664EFADD593DEB99FFF5ED000E5
+
+10001:\
+03B0D3962F6D17549CBFCA11294348DCF0E7E39F8C2BC6824F2164B606D687860D\
+AE1E632393CFEDF513228229069E2F60E4ACD7E633A436063F82385F48993707:\
+02E4C32E2F517269B7072309F00C0E31365F7CE28B236B82912DF239ABF39572CF\
+0ED604B02982E53564C52D6A05397DE5C052A2FDDC141EF7189836346AEB331F:\
+15C5B9EE1185:49FA45D3A78DD10DFD577399D1EB00AF7EED5513:\
+0812B76768EBCB642D040258E5F4441A018521BD96687E6C5E899FCD6C17588FF5\
+9A82CC8AE03A4B45B31299AF1788C329F7DCD285F8CF4CED82606B97612671A45B\
+EDCA133442144D1617D114F802857F0F9D739751C57A3F9EE400912C61E2E6992B\
+E031A43DD48FA6BA14EEF7C422B5EDC4E7AFA04FDD38F402D1C8BB719ABF
+
+10001:\
+04A6CE8B7358DFA69BDCF742617005AFB5385F5F3A58A24EF74A22A8C05CB7CC38\
+EBD4CC9D9A9D789A62CD0F60F0CB941D3423C9692EFA4FE3ADFF290C4749A38B:\
+0404C9A803371FEDB4C5BE39F3C00B009E5E08A63BE1E40035CDACA5011CC701CF\
+7EEBCB99F0FFE17CFD0A4BF7BEFD2DD536AC946DB797FDBC4ABE8F29349B91ED:\
+684E3038C5C041F7:\
+3BBC3BD6637DFE12846901029BF5B0C07103439C:\
+008E7A67CACFB5C4E24BEC7DEE149117F19598CE8C45808FEF88C608FF9CD6E6\
+95263B9A3C0AD4B8BA4C95238E96A8422B8535629C8D5382374479AD13FA3997\
+4B242F9A759EEAF9C83AD5A8CA18940A0162BA755876DF263F4BD50C6525C560\
+90267C1F0E09CE0899A0CF359E88120ABD9BF893445B3CAE77D3607359AE9A52F8
+
+10001:\
+04A6CE8B7358DFA69BDCF742617005AFB5385F5F3A58A24EF74A22A8C05CB7CC38\
+EBD4CC9D9A9D789A62CD0F60F0CB941D3423C9692EFA4FE3ADFF290C4749A38B:\
+0404C9A803371FEDB4C5BE39F3C00B009E5E08A63BE1E40035CDACA5011CC701CF\
+7EEBCB99F0FFE17CFD0A4BF7BEFD2DD536AC946DB797FDBC4ABE8F29349B91ED:\
+4046CA8BAA3347CA27F49E0D81F9CC1D71BE9BA517D4:\
+DD0F6CFE415E88E5A469A51FBBA6DFD40ADB4384:\
+0630EEBCD2856C24F798806E41F9E67345EDA9CEDA386ACC9FACAEA1EEED06ACE5\
+83709718D9D169FADF414D5C76F92996833EF305B75B1E4B95F662A20FAEDC3BAE\
+0C4827A8BF8A88EDBD57EC203A27A841F02E43A615BAB1A8CAC0701DE34DEBDEF6\
+2A088089B55EC36EA7522FD3EC8D06B6A073E6DF833153BC0AEFD93BD1A3
+
+10001:\
+0749262C111CD470EC2566E6B3732FC09329469AA19071D3B9C01906514C6F1D26\
+BAA14BEAB0971C8B7E611A4F79009D6FEA776928CA25285B0DE3643D1A3F8C71:\
+06BC1E50E96C02BF636E9EEA8B899BBEBF7651DE77DD474C3E9BC23BAD8182B619\
+04C7D97DFBEBFB1E00108878B6E67E415391D67942C2B2BF9B4435F88B0CB023:\
+47AAE909:43DD09A07FF4CAC71CAA4632EE5E1C1DAEE4CD8F:\
+1688E4CE7794BBA6CB7014169ECD559CEDE2A30B56A52B68D9FE18CF1973EF97B2\
+A03153951C755F6294AA49ADBDB55845AB6875FB3986C93ECF927962840D282F9E\
+54CE8B690F7C0CB8BBD73440D9571D1B16CD9260F9EAB4783CC482E5223DC60973\
+871783EC27B0AE0FD47732CBC286A173FC92B00FB4BA6824647CD93C85C1
+
+10001:\
+0749262C111CD470EC2566E6B3732FC09329469AA19071D3B9C01906514C6F1D26\
+BAA14BEAB0971C8B7E611A4F79009D6FEA776928CA25285B0DE3643D1A3F8C71:\
+06BC1E50E96C02BF636E9EEA8B899BBEBF7651DE77DD474C3E9BC23BAD8182B619\
+04C7D97DFBEBFB1E00108878B6E67E415391D67942C2B2BF9B4435F88B0CB023:\
+D4738623DF223AA43843DF8467534C41D013E0C803C624E263666B239BDE40A5\
+F29AEB8DE79E3DAA61DD0370F49BD4B013834B98212AEF6B1C5EE373B3CB:\
+7866314A6AD6F2B250A35941DB28F5864B585859:\
+0AB14C373AEB7D4328D0AAAD8C094D88B9EB098B95F21054A29082522BE7C27A31\
+2878B637917E3D819E6C3C568DB5D843802B06D51D9E98A2BE0BF40C031423B00E\
+DFBFF8320EFB9171BD2044653A4CB9C5122F6C65E83CDA2EC3C126027A9C1A56BA\
+874D0FEA23F380B82CF240B8CF540004758C4C77D934157A74F3FC12BFAC
+
+10001:\
+0A02EF8448D9FAD8BBD0D004C8C2AA9751EF9721C1B0D03236A54B0DF947CBAED5\
+A255EE9E8E20D491EA1723FE094704A9762E88AFD16EBB5994412CA966DC4F9F:\
+092D362E7ED3A0BFD9E9FD0E6C0301B6DF29159CF50CC83B9B0CF4D6EEA71A61E0\
+02B46E0AE9F2DE62D25B5D7452D498B81C9AC6FC58593D4C3FB4F5D72DFBB0A9:\
+050B755E5E6880F7B9E9D692A74C37AAE449B31BFEA6DEFF83747A897F6C2C82\
+5BB1ADBF850A3C96994B5DE5B33CBC7D4A17913A7967:\
+7706FFCA1ECFB1EBEE2A55E5C6E24CD2797A4125:\
+09B3683D8A2EB0FB295B62ED1FB9290B714457B7825319F4647872AF889B304094\
+72020AD12912BF19B11D4819F49614824FFD84D09C0A17E7D17309D12919790410\
+AA2995699F6A86DBE3242B5ACC23AF45691080D6B1AE810FB3E3057087F0970092\
+CE00BE9562FF4053B6262CE0CAA93E13723D2E3A5BA075D45F0D61B54B61
+
+10001:\
+0A02EF8448D9FAD8BBD0D004C8C2AA9751EF9721C1B0D03236A54B0DF947CBAED5\
+A255EE9E8E20D491EA1723FE094704A9762E88AFD16EBB5994412CA966DC4F9F:\
+092D362E7ED3A0BFD9E9FD0E6C0301B6DF29159CF50CC83B9B0CF4D6EEA71A61E0\
+02B46E0AE9F2DE62D25B5D7452D498B81C9AC6FC58593D4C3FB4F5D72DFBB0A9:\
+8604AC56328C1AB5AD917861:EE06209073CCA026BB264E5185BF8C68B7739F86:\
+4BC89130A5B2DABB7C2FCF90EB5D0EAF9E681B7146A38F3173A3D9CFEC52EA9E0A\
+41932E648A9D69344C50DA763F51A03C95762131E8052254DCD2248CBA40FD3166\
+7786CE05A2B7B531AC9DAC9ED584A59B677C1A8AED8C5D15D68C05569E2BE780BF\
+7DB638FD2BFD2A85AB276860F3777338FCA989FFD743D13EE08E0CA9893F
+
+10001:\
+FC8D6C04BEC4EB9A8192CA7900CBE536E2E8B519DECF33B2459798C6909DF4F1\
+76DB7D23190FC72B8865A718AF895F1BCD9145298027423B605E70A47CF58390\
+A8C3E88FC8C48E8B32E3DA210DFBE3E881EA5674B6A348C21E93F9E55EA65EFD:\
+D200D45E788AACEA606A401D0460F87DD5C1027E12DC1A0D7586E8939D9CF789\
+B40F51AC0442961DE7D21CC21E05C83155C1F2AA9193387CFDF956CB48D153BA\
+270406F9BBBA537D4987D9E2F9942D7A14CBFFFEA74FECDDA928D23E259F5EE1:\
+F735FD55BA92592C3B52B8F9C4F69AAA1CBEF8FE88ADD095595412467F9CF4EC\
+0B896C59EDA16210E7549C8ABB10CDBC21A12EC9B6B5B8FD2F10399EB6:\
+8EC965F134A3EC9931E92A1CA0DC8169D5EA705C:\
+267BCD118ACAB1FC8BA81C85D73003CB8610FA55C1D97DA8D48A7C7F06896A4D\
+B751AA284255B9D36AD65F37653D829F1B37F97B8001942545B2FC2C55A7376C\
+A7A1BE4B1760C8E05A33E5AA2526B8D98E317088E7834C755B2A59B12631A182\
+C05D5D43AB1779264F8456F515CE57DFDF512D5493DAB7B7338DC4B7D78DB9C0\
+91AC3BAF537A69FC7F549D979F0EFF9A94FDA4169BD4D1D19A69C99E33C3B554\
+90D501B39B1EDAE118FF6793A153261584D3A5F39F6E682E3D17C8CD1261FA72
+
+10001:\
+FC8D6C04BEC4EB9A8192CA7900CBE536E2E8B519DECF33B2459798C6909DF4F1\
+76DB7D23190FC72B8865A718AF895F1BCD9145298027423B605E70A47CF58390\
+A8C3E88FC8C48E8B32E3DA210DFBE3E881EA5674B6A348C21E93F9E55EA65EFD:\
+D200D45E788AACEA606A401D0460F87DD5C1027E12DC1A0D7586E8939D9CF789\
+B40F51AC0442961DE7D21CC21E05C83155C1F2AA9193387CFDF956CB48D153BA\
+270406F9BBBA537D4987D9E2F9942D7A14CBFFFEA74FECDDA928D23E259F5EE1:\
+53E6E8C729D6F9C319DD317E74B0DB8E4CCCA25F3C8305746E137AC63A63EF37\
+39E7B595ABB96E8D55E54F7BD41AB433378FFB911D:\
+FCBC421402E9ECABC6082AFA40BA5F26522C840E:\
+232AFBC927FA08C2F6A27B87D4A5CB09C07DC26FAE73D73A90558839F4FD66D2\
+81B87EC734BCE237BA166698ED829106A7DE6942CD6CDCE78FED8D2E4D81428E\
+66490D036264CEF92AF941D3E35055FE3981E14D29CBB9A4F67473063BAEC79A\
+1179F5A17C9C1832F2838FD7D5E59BB9659D56DCE8A019EDEF1BB3ACCC697CC6\
+CC7A778F60A064C7F6F5D529C6210262E003DE583E81E3167B89971FB8C0E15D\
+44FFFEF89B53D8D64DD797D159B56D2B08EA5307EA12C241BD58D4EE278A1F2E
+
+10001:\
+ECF5AECD1E5515FFFACBD75A2816C6EBF49018CDFB4638E185D66A7396B6F809\
+0F8018C7FD95CC34B857DC17F0CC6516BB1346AB4D582CADAD7B4103352387B7\
+0338D084047C9D9539B6496204B3DD6EA442499207BEC01F964287FF6336C398\
+4658336846F56E46861881C10233D2176BF15A5E96DDC780BC868AA77D3CE769:\
+BC46C464FC6AC4CA783B0EB08A3C841B772F7E9B2F28BABD588AE885E1A0C61E\
+4858A0FB25AC299990F35BE85164C259BA1175CDD7192707135184992B6C29B7\
+46DD0D2CABE142835F7D148CC161524B4A09946D48B828473F1CE76B6CB6886C\
+345C03E05F41D51B5C3A90A3F24073C7D74A4FE25D9CF21C75960F3FC3863183:\
+BCDD190DA3B7D300DF9A06E22CAAE2A75F10C91FF667B7C16BDE8B53064A2649\
+A94045C9:\
+5CACA6A0F764161A9684F85D92B6E0EF37CA8B65:\
+6318E9FB5C0D05E5307E1683436E903293AC4642358AAA223D7163013ABA87E2\
+DFDA8E60C6860E29A1E92686163EA0B9175F329CA3B131A1EDD3A77759A8B97B\
+AD6A4F8F4396F28CF6F39CA58112E48160D6E203DAA5856F3ACA5FFED577AF49\
+9408E3DFD233E3E604DBE34A9C4C9082DE65527CAC6331D29DC80E0508A0FA71\
+22E7F329F6CCA5CFA34D4D1DA417805457E008BEC549E478FF9E12A763C477D1\
+5BBB78F5B69BD57830FC2C4ED686D79BC72A95D85F88134C6B0AFE56A8CCFBC8\
+55828BB339BD17909CF1D70DE3335AE07039093E606D655365DE6550B872CD6D\
+E1D440EE031B61945F629AD8A353B0D40939E96A3C450D2A8D5EEE9F678093C8
+
+5:\
+C7FBA2CB9FB24C6034C9E239E9350080AC8B9CB2DC8D428C5A1DA72767179679\
+1021093809F5F79052ACACA1EC1ED7E019818D8B2D417E8FC60812EE1A67992B:\
+FD06033468C106ADBCAA26AC4B6BD24CF4919EA5EEB99458D6E3C758ED606D63\
+9AA3D3B0BC36CFCAEC3507AD0280BF6E9F9C3EBCF41A0B33A95CC6EEBBDD57EF:\
+7730307421:67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+1A025CC4A2C1B8488760786162C62EC677F6546F329D84E6EE0DA11379573D17\
+92526104BF637DE57807C4394C492919021DD81ADECE3530D8D2BC1802EC2E88\
+A46C9C5E8FF11E34D7476530B7E11DE0236992DE293355494471223263664199\
+01CA2F27E4A996512BDC650D76280A54D1DE2BE17D6E59EE1D156745036D8DC5
+
+11:\
+EECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632\
+124EF0236E5D1E3B7E28FAE7AA040A2D5B252176459D1F397541BA2A58FB6599:\
+C97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D86\
+9840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503:\
+D436E99569FD32A7C8A05BBC90D32C49:\
+AAFD12F659CAE63489B479E5076DDEC2F06CB58F:\
+1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF7\
+63722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB\
+6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48\
+DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955
+
+11:\
+C078DF95FFF0FC15570627120760AE74601094E47D0C879075B1F1A3EC33B255\
+3490AB1484E588C18A62A166876C5FD1F9790C265CD5ECB5ADA8BE03D5ACE4DF:\
+CDECBA049D6379CAF66158D85E5A1CA40ECFB849E832109B6E018DBE5F2DC8D8\
+63DDC8DF00D93BBAD5AA1EEEF896AEF694D253C11B806547D8F3621F6C0B7041:\
+7730307421:67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+40BD2CCDFEB88BDBF6AE80EE37045142EEBA60D51063335F6145BD30223A1635\
+D18C4E67FAD80D158BFA711A6BBCCCE8980A171027083D2D4E6B7DA2C465ADDB\
+D1F44350C51A9E03D808EB5784F0A3602B7E23903CE4530DF3D45829375E1113\
+7FCD639874F71E68742B9C145D21ADF4C4C8416B54AC4A01B25AB4CF1570CFBD
+
+13:\
+C975657B7786E7335EA9B72E0DFE6FA895F5F7CE9E559CED9E6C9960ECECFCC1\
+EC9D515BD14849E798B4D699F7C2898B6C256A63EA5F33D2FD77A51232B722A3:\
+D502E40CEA5B850C45E3BDE7E05EF0B13F4AE0DE9D93FCE969E5A119191785A6\
+3E5C181BD0CB3F440A1B519B3961B2FB519A8526BF29A3DA6DAC68261F70149B:\
+7730307421:67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+4B4B2F855CE4E8D5675589DE93335E31C1EC3ADA263855252DF49BD4836DBF29\
+3E07BE72C537B9C7685B38F7C838E067BC9172DF032C1F7AE337310A41A5F103\
+B00E662E3F78E04C234825A3DA6D31CC84D591EF5E8FE970ECC2C0B23E280463\
+25D88534EC256FED8C501034F8017C771983A07EB60E396F97418AD903282B59
+
+67:\
+BEDC7B14D1A21178D999DAAF657792371C8E55D29DA042030BBCAF411D36FDD2\
+F2A1F79DBEF6B61AF19A750562ED9C7A73386929951C9D330789504FB322C99B:\
+DA9ACA1C011181903DD4C24863408D49E4E134283CE92C65C842B753FBFBA463\
+4024837D6C1C17C18254BD8CA696F85BFCEB2578BD41B2584F2F47D6B12C18F7:\
+7730307421:67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+11C86DA2269774A6F24161A81B25D913B1A8C9F7332D066F96AE896221BF0B30\
+63C2254FF1B082721C18BE2BC3F0B1E0CEC028D8CEF7C762E985A6C327ECEE03\
+6070B9BCA0E6E41EF72B8404C7874CBA08E2D05612D69D11DD14C1EA42E605A2\
+92AB1C5A19C2F0EF39441225C783BC573775A28857F8AEFFF4C7748C164C8A79
+
+FFFB:\
+C7479D7196291025D82523AC1840AAF09C3FF8844A444A9FED1C63996FD34566\
+B75FB997746D175CB1B253C470AF4CBC5A0EB9969A85EF32A12C75053B8D7681:\
+EC73649E669157A56375BEC8AA903491543605C6A55AA7E4C804A0A8854C1363\
+56485CF4595B5922FF408E2A364F19F8BA82D658CD179118227BAC50046802B1:\
+4920414D20534F20475245415421204920414D20534F20475245415421:\
+67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+B73D7477B95133222DF24ECE7F6FC3E183DC7378503F2DB0E95CCBCAD9134CB4\
+7F5CEBDBE94AB4063E473A5168CB7402E75B2423E5774FB328D2D463AB79D62D\
+46DBC2AE11382F90AB2D63CC061816991062C17B08FF6D29DB1F646C57BF122A\
+1F23017207DF6630B739134995B250260907096971F530E8006B06534A333974
+
+11:\
+FAEC2B060722051B29D1A7E1D3E060CE3CCBCB29CCFC68819F26BB7566B7C5BB\
+D02C16C5A99E7F8EC22AA7050175DEA2C6C8939A24FBFD9015DA5C33C9E13985\
+F6E788E3BB02771A4B273B4C9D376E8204E469EE1433CE4ADEE78FF6B0B96445\
+673D5A0CB10156647B5F0418CC47A3469C6D0027D6AAEBC402D2DDBA1DA5B693:\
+D4795D21407AB236151E75957B45907F27BCFCDC38A0D9E322B1F2810FADA359\
+61527F1834B1909BDAFDD8D6B779C60694E36380BA45CFC786FD28C8310AEE62\
+30432FBA0996E87D22F7792D101EA4C171AAE38956762E3EDB2DCC8919BA0269\
+F9CDE6B3D95F6D9EC93D22D118FCC837B2EE5990D6E84CB181D3416FCFFA9A23:\
+7730307421:67C6697351FF4AEC29CDBAABF2FBE3467CC254F8:\
+67114A6F725F764D578FFB44F36CEB3A2B51CDEB1183AEA7201337DF4D2F9A0E\
+7DADE80202AD35BE2C5A209E493D31437189B95C86B53EE4B849536F94782E03\
+35E1501978588A525192001D2D1B1C521A31F94ADC1A3119D50E07318246D352\
+61F44EB0C2677F0E358E486A82E2B971996C926474F3199A4686ABAE7AFE130F\
+BF419FDB7B92CB69D8FCB7FD1536234C9B82409474F9968BF16CFBDFBB57EA34\
+C01436A684B8C521A435462CB6A6EBDB5DA4D97AAD2662738810DBC40C2616D3\
+241D47085D53D92518BB24D26B2D7E8404ABE334E6C4848DEE793F0EB6B61ACA\
+D0BAAFB220CB2C9ECBCF9667ACA41661B21E0A68E187DCBB39C3D7C5C31A7771
+
+# These catch a bug in versions before 0.8.7
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+54657374206F6620454D453120286F75745B305D3D3D6F75745B315D3D3D3029:\
+55BF28124E5DCC8B92E4419464AAD74B9D489259:\
+21154AF8EAAB2063615CE16397CB0AE8FA55C94D8DB6A1738F90CE17B1F2B77C\
+57A5E2B7D892FCE8715B950070C2AEDCC6972A5B06BB20607D948FE755E24EBC\
+408456375121DB3A0205F45030DC840EBFF0ED359449B670B3AB77B9E8167658\
+DD73AE971C6B131F77C3A5143974393A2121F2F457146C7AA22DD56A7EEE86EB
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+454D45313A20286F75745B302C312C325D3D3D3029:\
+825B0D7E7CCA6E1DE021437268D678C0CB8427D2:\
+039FB7DCBC3ED3DC57BF06055A269E47C00119FBF1F55FEF6E4174F9859C1BBE\
+FC40B0A73E128FC5DF5DC6DA3C292BD13E428CB90A181983FA2383B092375B1B\
+66FB2263174CD75266AD03B1DA49FC5BF69ED911017ACB87FA405DC118E8EE69\
+26C7ADE4392802C8CBD26D7534B8347F9C6C40F7CB776857F45EFF31D6D17CA5
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+454D45313A20286F75745B302C312C325D3D3D3029:\
+20A708C1E55F288CFAE84EE6A521D3268234673B:\
+80960E4DF6DBD44A685EF7175BDCC12A53EC5DB0C8CD2866D72C120274D0F525\
+88A71E97B449B65A9E0D36AF3A6C3437440163444EA9CC03C26FC52596576B54\
+67CAFB8F171A2156135FD8CE93F7BA2E1418A4646E977DE60B19F1E7140B28EF\
+C241AB3068FD4F0B70332962F253D67B6FC41D60806D0E6B62A81C759C24F405
+
+[RSAES_PKCS8/EME1(SHA-1)]
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIICoTAbBgkqhkiG9w0BBQMwDgQIvr4d1PWvUvsCAggABIICgHacnCUtLfHl6orN\
+3TlqanvKYD4NVYiXpM4lhPbOk43UDH4iR+uEXmoGbt6HCjDJuFLt8HNcxMO0jrrZ\
+fjD14doLd5Byv8oldAKBHz4GHP2wGxb0l5vPqHE9WgDN/NKke35TJLuzkrV104K+\
+hir+LhhwDsDCV71jqsVL7ld2+AxCKF8+1uC+uSOoD91tFAXPLt2BApqByMJ59OMQ\
+MK5LKsTQJivywXSyQHVXVTCkJyx0jiChpr/ns+ABsZ7BVD8B+C2QTY4j9w4F80ms\
+dJkdEmmiRtIIPZoHrLKisPjLWE2oBgMxwfgE0twL6LgjMPAKaXPX5z9rmD+is0D7\
+BovbmCVNDLNvIB0z3ehP/EzP9V2WtPfpjwnKL746+Hy4h5bdt7pVUYjWiTxXpiAr\
+twjm8R5OUseNYrsVf2mitm8VRF97egF9BTQ74kUDQPKvwDSfVxkaOPttfo7xB0j2\
+GYRgXOsO/fosiafakBs3ARLJ7U8vjq2JtkTbKBtWvlJQmc3VHALZ64Ukt7epOlV3\
+W+hE1Hd6YnAuzCQIgPW8TtJkcSeUbH2NtR1ZCY7hUnLmqbiLAVqNezmYg5HIKZIQ\
+/IWMonvvrJimIRzz9F+EUIGM1JjgMrIIQ2zHIB8Hp0IhLNel+pWtSAZ/CDSTbOkP\
+An63u+Btp0CNGaIYPBNkW3rN9rKSRn85QFAU54LKRrtY3agVJs8VCH/jU1nBNl+P\
+pti1MKjJGAa8yCjn15jLBmS/PSRmLT04XwlDEuxBrfsAy8zScQkvMYLlVUj0JXJj\
+uEsBmm2wi8aCsD7cylqyflyePKOSAlig88cmFGWR37nq2HP8Gfi6IrzSFcLFyeOi\
+SJjGj3U=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+B2207519BAFEA1FFA5561CE47F903CE59DA9FE82DA7D4C867A92F28F180D:\
+FC0DBB14EEF2D2FBD6D75C7D920D96F5057C45DA:\
+C1659606D25D6D3274B0380373D8F0F740EECFBE0E7C5AF20F22ADFE54063E0D\
+B5AA23737992C216A66550E8B0D1730684588B1CA0FEAC63680A7EAC2EB6DD73\
+EA5B2DFDFE2A41C47D28027E9400FD71A2A8109271993C629A39A9B006AA11AB\
+E798FCB1297BCA3B42CE1BFCE817928DC3BDD7661BFB2CFEA5B1C2D02B48B821:\
+ilikepie
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIeNQ67v0/C1QCAggABIIBYDTbkO1cl0ur+Osz\
+kTIQYqsi+YChtwLeTE0HipSPbuvlsFI5eoQvKjaEZjSMjsZwT6hX9zVbaclDFu7o\
+fOzrEwGSGXoquFzS0GfbtynnUhk1IAPviLRdesPFCrRWFByaTRC4y2G3zT0bopo+\
+Q6as/Tk28V88dpN7qC0Q5GlAaPTzc2PAy9FGc4lnu71WGQQOVByZ4LFomBPez2F8\
+S95H85Q0OZADlp+7gGUjUtlhZqlmn0b1OGNIsU9Ua4VntOFODr2AWMhoKpmZ2nNd\
+9Nc97uwP4jx1F8hfQP3/eRlG/FgYPX9FtVPAmKV8NA1QoBIIrfW0T8/JDnOYsxA1\
+/EwyNoamD1UJ3xq0kHS9a6c1zU00l7fgc1Cn+qECu93FxAffVN/cpA/+QwQwNXhs\
+ypmHWNSJuTUwx+MvjO/aEUAaGFN5HNwiwjOgoPecnSbHyPeyc7Fy6fVp6bjYuCJH\
+gjnIOR4=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+A3208DF23DFB014D257B4C3D7238A857AD:\
+0E151CD5DD9014F9BCE7BB3500D1E3A7EF3F36F8:\
+374FCFFE225903D58CE988FC469AF9B6D660A90A48FFB7DCE207888D871587D5\
+0494260231664CB03C18A427B04BED666770B503B6EF08632A00D9D03888B1A0:\
+unguessable_password
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIfovX98csqwwCAggABIIBYA3nZapMLCVG6H+1\
+GVg9ThDA2RPjb5bI24AU8UcRV08Tw81SMQmZ3BCFgcbUlcEAM8BlGfc3g4KbxSt0\
+P8o0/ImCsZG4tcjQqw10CjQkG7Wg4WrKJ7wVUoKenR+9vPkzDtAFLctNqfWgbtmX\
+hD/O0twe0NT3puypunDReKq0HRu4LnMnXBzSNg9FHFvW95KU3JX6Lk0Yt77Lb0nk\
+663We9Tdr5kQnONjai5Q9gPst8suI6K9miInimPWgPSyCVy8Yp9Epl660QOpS3P4\
+mSg5ZPCT3pzcyKdSK/I1HfFSuXfP8+XYixjNHGjX3TZWl/x0g0EACowNlKQi63s2\
+9MRpBpMxu5Y/AhrpZ2GwUPQnFxmJXKOIXoSaTSzAW15QwfBGybB9F2goM3KM+xEY\
+g177HF0JWHexJGbMurT8shUjwrxFb190hoHIUYsmVN2qRT4tFNsUYAGjDAE287SW\
+YX8pFFg=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+8F6B78A9F0D0F35BEFD38B:25D6DBAA5DEA01099646C5DD25589A10C414B6AE:\
+0091AA69E80C2690C78B99D5BB71002BDF019B12CC6ED5F7ADB0D2AF7284D1E2F\
+E14E372C71FEBBCE91309D7D18EC979DACCFE11799E31BEFF9B4D25D2B9DEF8DD:\
+akira
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQI4boeHBzsmTgCAggABIIBYNQg9WdcjfVuPIof\
+D5/vhwOE3m3fxFqPmEeGf1m6729KiaVGuICWos3o0+rca6zGwulfUe++yARG4TW4\
+Ug/kjQhYVBZ6C+0cU8HmkpyO7mNcOrIGLJVgYmfcZbIm5DKS4g8vdLLF+mC7ic3n\
+ccBmbAN7JpPUjUiPVLlmNU691TajXdf0H14oKvmagjW9revy6KPrp9Hm0DkA5k9m\
+eMc6CyVk5IUijwEQyl5kwgCZMvR1N5ojum+FS5/+m4oOOPlowypEWPJYIIrH8vqv\
+bL/ZrBN1BsNKo2vkFvgs2AUJWhtuCdOI30HpVuI9t8crCZ2jHD1N+UdPQK474xhj\
+7/kTvM+LxAJm5ZKbcTJ8IlwVvEKvjN3+NPHpOIhThNI7IuBiLbljf5Q2hO68fUrL\
+D+6blox9MfSfpObyHzAk1sz9TnglnwgszUnnQDnF0akbR0sjmAntr2J0SPQ04Ore\
+GMrVEDI=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+E729D4D596553F96AF:36FBC9529B999745EF9F19DF5A7C4E783013C661:\
+02A9176EF95FD74880B641C1E67367F3780B59456EBBDC05A4B6EEC3D3F8B8ED\
+E063DD1E2300E24CFABF475C8F3BCCF987C043A9A839976ED7B3995752EB3A746B:\
+It's my hobby, Sakura-chan
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIikN0UUeS0WcCAggABIIBYB5e4OfogtTUEoKL\
+N1xxteoWJirrMjzmXFVbief3OhiPTrLLAHZxQFdvnljURvY3UTUCDAJsBwgVfQlt\
+v0sYNdgxCv3seyb4f+MmDQKppHcaoPUfoE6R7J35lwE8eZs7S7sQIhA2loBuYrGf\
+V7GJ1nr0zWzb+JfRoOypMWbt0f06PMfJGdjd9dWaiR01L8PAHwwNNNREtbobrGcc\
+9jrw3bUDwMW/hkJIIrrPbQ41OqIJsQ09x+1VVBqaqcS/dy9wnB6FmUT8xvGY8YMx\
+ru23dTzd7ONBVWmhOq3Sov6o0i2eaFG8U656/L64qlw74lAUgJOVlZ8YNUEgaegc\
+rOSDDAe04/Piddbq8wpgpkB3pqJzFkleNVSBfduZaQ5azdtgpNKahIneAPbltnKm\
+hJVZ9OZImRKQaVOVZfqM5dJoohTrvTee+rT4n9O6/YcBgoP3QtTscPLSHyaQB8+A\
+X2ppo4M=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+45A04558B8:6587ECBA1C8A7BA7C2A8B4DAE9D4076D85CAA2FE:\
+011F8E0F8A7FAF157D2C5938B137AE3A8A2158F9784E1F09E205A7C7C71505E7\
+D50DB8E967B1CC637EDB766B12570328B7C7832DAE3F79C25D14F26DF0729F72\
+6C80:qwerty
+
+-----BEGIN PRIVATE KEY-----\
+MIIB4QIBADANBgkqhkiG9w0BAQEFAASCAcswggHHAgEAAmEAsgsx0714GvWOspp9\
+CrFOjZ+rSKi2q1nt22CJM/vGvtVr3wfCvaszroOths+vl8OzNFWJWXLQjYx6vsiX\
+n5lcQyzeXW7Qd9VCRGoTwgd6aVvhHjfqEBttQVDJmFf+R1wrAgELAmBAvkCqFlo4\
+WUsprIqPhkscOg+9VJ+EILOVl3e1z+suHw/0AtJzhBLLGJwxBbQ3L+N3a0aQYOwP\
+uiYXuJbt7KzaKWnFP0XHzme+6X3zOGai7+2xM0CkIiAzNqdHJ49xneMCMQDkL4WP\
+uwc4vo4biGjfjqqdb29RLR3JLZ+b3C9c0LZYlW7oA/L4zeaWs1TvobkCuWMCMQDH\
+vwG8rUApjgPiBI+xv9ZNy4wt07LJMAVbi8oIW6nQsqSO5wVT764dxyilCXrMMJkC\
+MHx3AwiUj5NQqpqnfwWTouGCmc8v4bONP8lg1AQUwI1oyCF2hIe2IK9Ki2tvfDAI\
+BwIwNnnpM3URf7JeJl5VvB0L5qvgaZbTqzukXskIjep0IaUVm1ZHRW/pqwfFREhn\
+TvX7AjA/Z/CkJNDAkHNUTW67+VzPRulGiW4+Lzs0f+laa/ZL9SizJ1nS+HtUeREG\
+Ya7AO/g=\
+-----END PRIVATE KEY-----:\
+F5BF1834145D40D0A09D6331204035F76EB7DC981734E09CD1D755B46484675A\
+447F8E58DDCE287D6B8CAE8BCCE3833A9A5F:\
+C91DFAC04EBDD389B0A172520B3D189C6E19FDFB:\
+75CBD6ABBDDA5A8DF4470955E212778FD872B0816E659C42F9D796A48ED86EAE\
+FFAE39EB4D25A218A5EB6252DAC6A73DA23B35D967286C673FC9A603AC9B2803\
+A8F75BAA72A22A3601FC0A1AD9923CF8A75B749126E2C98BD3AEB4EE2FE3452F
+
+# The actual (internal) name is PKCS1v15, so test out the aliasing code.
+[RSAES/EME-PKCS1-v1_5]
+5:\
+DA8D6D0AE1B959B8A446CE3807F195BC6737491490206535AC8F85E5D6E5C18F:\
+F74FE3F3CFC5BDF517A50A887676E7CC2D20C509758B7657ACAB73DFDD581D07:\
+426C696E672D426C696E672E:\
+C66FF974AC57FF20D15AADF04D472ECF48F945F50945822FDA962591C160072A\
+AFAC9AB61302ABAD458A2528D610C73DCD:\
+11F10A948BAE2ED28555EE8B36028C8AE3001E8AE76DA4567A59DD59EE8B490E\
+54617009CF6E346360BE39E22B432DD7B50F0C41BEB1A6DF655E486FD5D822AA
+
+C3E9:\
+B90114E3BA96AD3076C08F63255E07A6BA0F46C0EC9332EB9081EA81100FFF2E\
+D3F886DB2DE1CE4F01ABD44D477DA8E61B66C65A9FB666B1CA8F79FC7B3EF25F:\
+E67921A8F5C8C04169E8CCEDE6EE147CB3B1E139BFA6CB6789E24238CBBA10AD\
+522B4BBA6F3B3138C7B038856F01C3735B2B61FDB18A47DB57D5B4B5B52B6E77:\
+426C696E672D426C696E672E:\
+8D4557C36F53ECB344131ADE3F85684BD10DCE1B84BB9B95A8AAF565D73283C4\
+46251D7FAFAF6C84FB216C627EEBEBD0F38C0E4C2849BB5FD95E453C9F4729E8\
+B54E0AA5700EA7ED197A0A64DA43AA33A0D232ED403F2DD5C519FD070242DBA4\
+6FAA023D4FCA255AABB85A9AEC28DB83A6:\
+9642171747FA6A731DF3D17AE28EC0AA0FB8E4046CDC0170335610B1FEBA9673\
+8E4A7FB6BD7761A035B41161696A2270AD429C09980005307A6F154B65F6CCAE\
+0C7C9CC1FC2E61BB52B5AE4AB41618023B673201D14C83DFADFDCB21BC7EF65F\
+CB497A7625E324F1ABE70B045D465051C4668A02B5F38F25606FACFAF62296FD
+
+11:\
+F233C84BB80BD0BCA772A629AFAE474650A81C10B863747364DF21776B1ED919\
+39FE9011E45B6C317F7C913F1A2E9395797C2E778FB97A0B1F57AEF663213557:\
+FB5B0E26BDD59E3494998727361831FDEC1715C0DB65E0FFF318A2BE9B33993B\
+76984F868CA9179807F29C1DE6C5489C1D43C76BBB7959BBF85922016BCECC43:\
+4C65742773206F7665727468726F772074686520676F7665726E6D656E742120\
+286D616B65207375726520746F20656E6372797074207374756666206C696B65\
+207468617429:\
+2D76481668E437FBFD3DF446DF2BC5F7F0EAA857CB913E739D5CDB6042D32ACD\
+BD332E5A99EDD3B4B210FC2937440EF8EDA3EEDE33D7B7:\
+7B8F8AAC5BBC997CD4A1DE682FBB96AC8E80C6FC2102B1E7926D9AAD97BC10A4\
+6F981BE12F8F1B51F9A9E1F8D8B7AED9CC42F2AC0420368341D994D942071766\
+79B5F2187FB6BD8F962B678CC379009D0A82ABB9933093371B71C6CDECEED957\
+EE08962B0A94C7DCF40325E5CE38C61C81D327AAE5E140F345597EE7774B8A11
+
+11:\
+C768A0691EA020997054C37D371440D61BBE79DA842AB00DB0FED730D00BEFB7\
+A466BEFED1BD928211E7E3F56B59A275135C80EF31B6F7348EAA7887E798FE41:\
+E12F3186A97838D1D57671508F249E538C85DCFD34CFEC3A98DF3A16C9559408\
+5A7F706FBAD2ABB69D654BDF2EF64C11A0B20CF70BA9AF62E416031C090F6D8B:\
+57616E7465643A20437574652063727970746F2067726F757069652E20507265\
+66657261626C792066656D616C652E:\
+22FA636CF24BFC2DAA1ED4FFA8D8D65370A45AD16A24454A2132ABA993A935B6\
+EAF3932BF7AFCC89CCE080CC4AD06914148C164C659A24468DAC947B73BE7B5B\
+09FC516E16EF7E89AE02F590EC23:\
+A0DF6D9AB85D31C7AF2E9748005C10E245A25987BA91990046FAD410E9640CE9\
+DDB51D11E8A05423D80CA8AEA69AA08A42D58AC8609B0D1390F4FBB6E48EE8D4\
+FB031A13CBA1050240E1CB5C03793CA0ECBCD543718B3DF51F6ED411512ACE95\
+FACCEF2A127D731AC0E25A47722C07FFD1A1DD5DFE0B1EEF6EDEB3C8C654AAD4
+
+1300D:\
+E8E314B7ECD4CEDE513D6E229A3A3A0E1D0DAF974ABDA9997E1978972FD0863A\
+FFD6259861CFC26F136DEBD1ED9CB227E091823C21DD79B57E8ECF67B9293113:\
+CE47F1506E6DDA70A95A6EC56E34B9F3F929D15C92DD4AC537162C6E3BD6C4EB\
+FD3C51D08BA61216685A333062EBABA4B5E647C81550C7FBE132A1D48D7EF00D:\
+486F7720646F2049206C6F766520746865653F20204D7920616363756D756C61\
+746F72206F766572666C6F77732E:\
+25B8D6560A33737B64EE77A02D5A3BA53F0F165468CCB98E7DBC6DFFA4C29033\
+A209E8B6821A3A7CF9EE89C02B42CD25F62FAFCE56B80E703897A3299F78520B\
+A251DAC421CC5A0B52E0E4B15FBB1E:\
+5A188A2132B9331B1072BCEA281DAE53070C0AAB0722D583BC7FE767BC85443B\
+5E36286AC568246781792CE04FCEA86D26124F14F3E8ADB69CF1E8A0A1D86E3E\
+0AC0F141C18CCA5F1B8228AC2996E81938B6593F37A603A41128D4CC0D453610\
+42B5F86539BDBAC1B1867E4FE351F599E955B452F675B0945093FE8310A70C9F
+
+13271:\
+D4AA40364C695FC262073498EAE363EAE585720A8AA211D37CC2BB74ABDAE7A8\
+B6D9C55D5D8E3A0E4D3B39D57D543E8A17F697FBBD45E32EC53B9240188F7EF5:\
+D4420A0041902AFD838833F2EF3AD89AFCF3EF66CA5B20036692BDC45FF861B2\
+0BE756CE35DCEC97A7BDD28DBBC09315E5B7E0249E61772436CA728C7639A8B5:\
+5768617465766572206F63637572732066726F6D206C6F766520697320616C77\
+617973206265796F6E6420676F6F6420616E64206576696C2E:\
+25C23B57F9C9E9A3A2C08F3320214F5365B1A70417F5A6AFDAEFDCF76D4CCA56\
+3D9F9625E2BA783733DE9691108973AF66BDE07A7E8854035B972387BEEA4DBD\
+4A2081CF:\
+985B3B945917B229B8274441C174B1748627F6A83986AAE295745694174928AF\
+8D6E3D309A8FDEB57F3BFB73AF2B776D13278028E7A7CFDD3F489AD3A46B2045\
+409683AABDD1C01CDF60ED850D4C918608ABC5B58C9BE3A438DB0D6D6B9C1019\
+C9498E17233D5092165471B0A1DAECE0A68104539FB85C51648176E8B7AEC1B4
+
+1A11:\
+32A4716E0F397B9340565530800F691F9E457C2C5F8ABF0A8F62971B89B43584\
+EFCD7EF66765E8BF6B84163D914364F855DF8F6C82DD49BEF76EDB1397257215:\
+360C8C90CA0B2216B342A9681EEF05BB8CF8DE2AB8F0997C97738AA32B88B956\
+D94515E35FE96238974AE8A8F0164E0FBE25C1161D7A1E9D170B821FEAD5A3CD:\
+4772617669746174696F6E2063616E6E6F742062652068656C6420726573706F\
+6E7369626C6520666F722070656F706C652066616C6C696E6720696E206C6F76\
+652E20202D2D20416C626572742045696E737465696E:\
+DADE975E4B9FCE8E3010EB1568FFDF1BCDED9A454796A0DFA6F793093A2FBE25\
+813FC6EADC4225:\
+06DE6646853E49A067C85492FCA580E49D286981CCFDC4E13B5642489CC19E80\
+3A69116BC2D75CD005B768F3FE7AA780BF7E5A2A3EA53085619946DB4B3E9DB7\
+592A8D060CDF185B3AB2C1BD551587EA8AC3745FEF60D945387B27C2001CF7A9\
+EAE9A086AA58B769A59CC4D09BCF9E100ED630EE44889F341C8DCCF52F003CF1
+
+[RSAES_PKCS8/EME-PKCS1-v1_5]
+-----BEGIN PRIVATE KEY-----\
+MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAt1wZLCQfj0PUKyhr\
+fWhKMm1DnCH+sT6xKHwPiyH1UTbaMaXjoKLKdfwK42UwDgJHGcSfQ9/ZYjj97o8P\
+8YiBSwIBAwJAej1mHW1qX4KNchryU5rcIZ4tEsFUdinLcFK1B2v44M4Z6+AwBTtS\
+Kb4KbbDsY3vruqonUnKa/wxxIhzZdero+wIhAO59Gs349up2k0gUJhwl+ght6JOs\
+cjb84p4QGQfob0EvAiEAxNK6zZ/S5MDLsyq1sVLOXRPc0JvBuebDtitKwdg44qUC\
+IQCe/hHepfnxpGIwDW69bqawSUW3yEwkqJcUCrtamvTWHwIhAIM3JzO/4e3V3SIc\
+eSDh3ui36IsSgSaZ187Hhyvle0HDAiEAmIKQMDlgg/7bJV+gm28s7qMpWyFfT+HI\
+oGFH/wROJlI=\
+-----END PRIVATE KEY-----:\
+A7AAF7FC80A74D35A163A575173A094DB366949207150DBFFF1D0B9DB01A43:\
+77BA577E606EF4A69F7C66726923ECDAB4EFF065BCAB972AD9EEF7478C09:\
+AF1F80B3057046EDE4EB139FE4954141350325E0D8291D1431F73FB601F57DA6\
+05D986965EC3B141E7BD467108EC29003C7F56315E11FA89708588B7A562A738
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIndH0S5IM+YwCAggABIIBYPxUf3adJCBZMSwg\
+whFKB9mFbB++xWg9UxkyZwpUsqReJMloMmtyYqGhAVvR753CWAkSi/l4cUK9hwnO\
+zs0vbQcU8MfwihHed61SwDqVHN2gp76KwdFtXKAsPlQ2WHBp2azO4VySxIYu8yMr\
+zpl5o6dnKqX9p0m38OcuMOvWiWjUbPdtNKPP9/t9xUY2dYdxoOJ02h2dWRH1bYth\
+jXFD5Zf0dgv958tcsUvCd6Omn6zyYvm0k0j8XFr3btJN6msWALYadCN7QrrJDsZL\
+eKD+a5eu3AYHA7Kk4or3AAKGH4LfDN/JsFe+Z9PO1xdxwwEf75mJbOyG4LQWkDP9\
++pUPkPY311fcblEOx9Vin5c3is/+QnackDvnKjwU7JhP7mLHk5sRwDVswN1DPA+c\
+mlC3M8/Bib94M3ts/U6EjE4r+JW3/bVsVslKelJ2zOEiqt9HK+wZBb38NgGWwrBZ\
+7Ik3umA=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+6ECA65B7FDB0986062B70E8C68171DCAF736:A83BC3A6BA075EDE453B7338CEE\
+83BB8F5AE8B5968E3A99462181DC4E73F943B66E433F43D0E8E6F08DA14:\
+1346A7E48F0ED39B333041451A0A293DBD8E1C906B21200A1AAC228DB8C9FC0A\
+9A24DD2B434E2279051106BD625AE24DD1554704E57EC48D659AA3E9515D2B41:\
+password
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIjb2KJZiMO9cCAggABIIBYHQXbyKPzgfuHZYm\
+b81zMQ7Kk4w5O+3XrNpFjSiRppkx3stZphGJ6vtI6NwDKb7mCf7arfeCzMIiF+gg\
+n4j27huU1KRl8SRSD9qaLaqrYrHOCpxnG3owavB8LtWacGQq3tD1/pyw/DXM/H3F\
+bdOd4q2ByvvltRAREy+0PjAwRaGBCdF3bEUP+ikIZ1zUUAhGalil1H8pPTf+8W04\
+/4NvlCyhWPqNwUEZJhFzzO1IRrAWSvn0PZAg0CHsNGHVwCRGB5/MfdEvvn6D31V2\
+wDFR/BzgNmPo7jFo7x83C/RRP/HCHHMhfTg3LHxehf1oCGI65Pj04PyHkYSNmyXz\
+QbQoP/Z6cTcbC250Q/2AT0xPamF9eAnhAcvu8QRq7M7wQQtW1z2+B/kvA5mf2020\
+4mGslEX3Iz08lZcdMwghw0xwVBZW+VCB1y07JXE8KxAhlsEj6aIbwg0KBM+d+npX\
+Ddyijnc=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+64E8425A6B898502A081B6B78A0546F4BF2DEB85E187ED:57893B2A6A4AA7863\
+785AB8FFA68E81F3239BDA659E704833319DF5E3377AEC911AA90F205B1:\
+871A94A51ED756EAD36EE976354D2D6DE467CA5B8C9D198FAFA6D5B24BFA674A\
+20F89CF53B85F75F7E17481E212F2BF543AEC428B841C79E3E36CFD75BB7CA8D:\
+pkcsv15_isnt_very_secure
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIbcPIyX5hozwCAggABIIBYIL0VCCWjld4Zk1N\
+0s3+Uec+axsZm1cuOEm6KKqiSDUPA5bIwWJFTksEWqEfspq6VkQVGGD95hQY4a7u\
+PflXcQ2PcFeTe5vvKNcQ/5lnSY56gidhFIHYEUQMPXjzkruxzbnLMBN5Cc4oFf15\
+YnF4B3uZjsb9e0k7hb1h7lSbf1/Y2du1xdbhvXhF3q/uoCsrnxeGnjKIwesA9skS\
+U8gdojj96STbZl78HZ9vbS+RP9Dtg73qCQkeWnMz4pES9GZ1u9HJ7Q/D4sU/NaOq\
+Gg5y/WW1oNqI6Q8hTtat6oWE0pBnD5q8xuovlycEk9PJbh/b4waGh5Lc/CFUV75b\
+gxAbqn9OIzeXVZsKnHU+JQpgX3x/3+dGHKGd54w1N/0a+N8YUNyYXxyDlU7f4zNp\
+fuc2uwzfxFm4spigfxTTul+E90SMMZOIVHSp58cakq+ibeprcp2zMJcxO2EpXfas\
+GfgFhK0=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+1548C7CEC500A26A59D493176E3B6ECECDC23FFBC485D75E4E20C978AD14F9C2\
+5CC19021C1328B1A061E317559A04326628222:66832C587BB0FC43A7380A:\
+022092438BAB2CF4A6C50D71EE39419E2E11C9E9644E0B9C2221EF81098FE318\
+8E9BE0E6E27C02A742571C0BD757C6B7F2160DCFA9A734AB6E90BDB0EF27DCD567:\
+whereismymind
+
+[RSASSA/EMSA1(SHA-1)]
+5:\
+BE88E0EF4EC64120FBD9E0CC62E931D0DCB02D7FBC59FC6B\
+3E919777E5178DA0E1C83696670F02DF3166D8ACB5B09A15:\
+EC1C473C7D3ED0B090C7DEC82343B1E3C5E6018947DC6820\
+17941BA4754715A8599D779A340FD85FC6613A1757D5B51B:\
+4920686F70652049276C6C2062652061626C6520746F2066\
+696E6420776F726B20746869732073756D6D6572::\
+9F35898F6508FB66FBF266C8D057F4FA9FB875213FA62051AFC62ABA177D42F4\
+B37FBC6F7236B01F27C1A856EA2F8CBDF88AD9FB4FEFDE0065BB7FE6F8978225\
+074A8F220C3D328C50070A953BB4E852B3F56E84594CD289A14F8F8717F5A4D1
+
+4F:\
+F1066D3E8128C009B795BBC5AC0988D73A981C108E631AC43424D63E6C964FDE\
+6B0E331D4A1FE6CEF3B744607723F4BDB1F9683D69651813AC03C757ED2412A1:\
+C00F576BC6CD63F75ECA04FB7FA5CABCC3287CBCBF99EC456CB75E9F56E2D20A\
+7F8C99BE857FA9E819BFE02C08D0405CC5045BB97C3F766F734390D881B27DEB:\
+447564652C2077686572652773206D79206361723F::\
+AD50D554C24FDE2B4D312C64D17B25F471C32CF76E54430BE37CAD31E6C961C3\
+4957AB1B4D1D2AC6782B4A979118CF7FE58BA40FB0900C2C2F5BFF26134C9489\
+136EC16EFA0E82A9B01F1C6AE744E4D4C4D126FC6466AEBA86353E83D69065AB\
+A220F460AD4AE3AB3083732290FED091D4675864EBA47B0DCB7C858264574360
+
+[RSASSA/EMSA2(SHA-1)]
+11:\
+BEFBF638255034EFF995CF15A610243A48784CEFB89CF10A11982F5ADFA0C5F2\
+49B373E33900A1A4A957F38A1EBFD49C4C74A2D7E74EEF2168F18424C6B6A843:\
+E538D5D8FE4A5800F16398B7732FCDCBBA9D397A8E77A67204458F0A89F13BEC\
+8AADE35E2346F489FF7005398596BA8A496D48D114BDBCC6D9CE292EE6ED7C93:\
+447564652C2077686572652773206D79206361723F::\
+4B9BE36BE0AAACC62FFA857A34D8032BE865C0D757C7A7827AD5D5C6DF6C5FD6\
+FD32A2EB0E851A0D04258FDBB94849CA2AD78FFA2CCC56070219B8AC198D0F98\
+165956D027A6D0325619B8C1458F01EC6A34DA517D89F3F3046AED0F169A2797\
+442FB6E586C6099B7CBE4F07682ACF751E291123AC5DF312088A9D84A54A7D54
+
+# An official IEEE 1363 test vector, sort of. The vector in question is using
+# the RSA2 signing primitives, where the output is "modulus - signature" if
+# signature is greater than modulus/2. So we just use the intermediate result,
+# since Botan doesn't support the RSA2 scheme
+3:\
+D8CD81F035EC57EFE822955149D3BFF70C53520D769D6D76646C7A792E16EBD8\
+9FE6FC5B606B56F63EB11317A8DCCDF203650EF28D0CB9A6D2B2619C52480F51:\
+CC1092495D867E64065DEE3E7955F2EBC7D47A2D7C9953388F97DDDC3E1CA19C\
+35CA659EDC3D6C08F64068EAFEDBD91127F9CB7EDC1748711B624E30B857CAAD:\
+616263::\
+A6B496F4A802AF9092F1F561931D84DBD0B943EF34C102B94DD51AB01E1054BC\
+0E0572A1FB2DB034569883F382B74E449F6C80C4060FBC0FFBD3A9CA9D66685B\
+90873007D207C1D64C692D0111157BB976A4551E72DDC83C767A9D75A4746C51\
+9B73CE52C2BFBD1C3C431D254FE8BB4308FEA486787F239FD2944390DA49DE45
+
+[RSASSA/EMSA2(SHA-224)]
+10001:\
+FBB75326D3DC76F89BB46C6D66A8CE0F0E2167309750D5CA6158BF7306DA8C6ED2D0E9D62524\
+8977ED06900A5C23CC1F:\
+D92E794F850892F13B6CBBCE1C67E1C670ACF8DCF8DEEA2DF958529C1CF5D89E30D5D05787A2\
+5602AAFFA5B5007800B3:\
+7072696F6E636F7270::\
+0EEA6057C2FE9892BE77B7A7E38E00EF2537D4E8EE7F2B856CBD4B29C7B5E38299D02B2A845991C2A8F4AC6BFA5E58A34139716B20CDD27471F549037D07DB76A02C3372AE2FAFDA3BF1414E9BFF71C0DFA03AA0409D62CC9D5FEEAA7B42D52A
+
+10001:\
+D620C17FD01B4B8986B2C4934F2B78CF9EA43B862D70AB88763E2B133D7398E4E6633D8DD408\
+05D02EC5F2E59C0EB19A85B87D2F2EBFEB2E8189B2E21C71368D:\
+E0B20464041EC9EC74FE86CC00D7191A1F6730E05C80ECE6B7714CE158ED72BDF3215D96E3E8\
+ADDB4D8123B6006509362BE8B2EFC853C959AAB0D21C09A2B835:\
+7072696F6E636F7270::\
+A10AD2439FA7F9638298CAD2E8BD18830A580555F0D0A71CB2DAAB2392ED61FB6C3659FA706D434C7F373761165580D9E3B4B72423AE3C27F71C53DE3DD812BB064C3F52A86C2C5E42BA10BAF4C90E2064D988B56C59186B48D16B151FFDA0859FE41C585D388884EBF6B2E570A69F5EF5B5D96E005BF353076662F7697DEA3A
+
+10001:\
+E3BAAE58893F9DEE6CFF0F0551AE0C95B1E8EC0F3F7C9E271C6DB3D84A24EB37FF785425FE90\
+6D9B9A4905CCAAA6CB95658635FB58BAA6691383DBFC3B05E403:\
+CEE7816F245FE20C99EB54A067340ED98A2003958186E78E2F9BAC8242E6F894FAA2726374E8\
+86CB3B718399BF5DA67B2558E086993897BEF2F6C580C7E04201:\
+7072696F6E636F7270::\
+85EFECF3B1EEB4386A61AA4AB0D0A4335F64C56C24C258AECEE4CA8547638F52858FFB7842EA399E3EC97C882891E9B52A76D3A4B76BBB843D6165EF06181BC887B342900C0EDFD42EC355967AD052A76A760EF2130499A24FD9A059C79C334C586AB44C400278C5DEA17BFA9CC5127CBF392DC74B65458627A34437A8AE9FDE
+
+10001:\
+FA1CAC0BF58B08369A927D3B2FDE1C1F926A2EA31F26C2AA49EBA42DFBB8661E79660928D476\
+D5F82D0C370BD6514F492A8D4AA95039B0E5D1E5512E257532A0AC6BE1C294F75253A2B2255C\
+7B7A84EC7D0E0A34BD67CED0E9BCC1897B3D4897:\
+F6366AEBC742DA02A8B5884B0AF4A0DC24F8A7652D1F30E5A176C8ABEE3AC5527429EC62A3C1\
+6715A782D4BE9B8C40721909F4B5D466836050C637479DAE39528DC284ADADEB0471FFAB90F2\
+368784977B8F21F53BFFBD4D065DBDC19CBED061:\
+7072696F6E636F7270::\
+7F721D5DD07950287F217BC11C130E32567BD45E538A1FAD278CF25A66150448B486BCDBFC4A\
+D3FB81A4EFC7E6081DC6613982940D1149C514AF67351B9E096C8977B5F9776BFEC7CD70C56C\
+666C49BFE9618F4ACF281F6CFC3B2F5B91BD7CE3DBBE643EF0B5BE9CB133CD3C22A2355CE87B\
+10E538A4AD3A098CC7E7125409765F22B5D78D5F3F0603EE6721C68C2D5F22C84B7714067BDF\
+28B82091CD1B9943F9D619F501F5C0D418425B63AB2BE2DB5A43BF8455E6ADB7B60C86C606699D69
+
+[RSASSA/EMSA2(SHA-256)]
+10001:\
+EFBF3A50D1165B053F78FF95134BA3AE221F7ED5E7037675B633557899978B154F1E4A505E3A\
+3A10247FD4FC3F8698B7:\
+CA052EDE74D1308CE00551FD8E9DE9BC5F9DAD3ABFB6EDF14820480D3FB9E468A02DFF23B6D0\
+C0E009544091CEC9108B:\
+7072696F6E636F7270::\
+38FBB52FF41301D176F11DD6A536AEC2161DD783C455556CCFD51468292C8C68AEE955EE4947\
+DFCE5D090A5DC81A7ED925623DE7C52A4872303002CD89A7A63798F29D13337274AE0F59886A\
+62EE58FDF73CFA29DD7B1BF4CA8A23B803B68E67
+
+10001:\
+CCEAD3D62F90C7E9F3E8E59F8989C4FFDD4921D7B6A2309B967CADB0B844362D4FC9A23A8ED2\
+8DFBF908A87FB04D880D7C1B68B8AA0B7CB5CD46656328189AFF:\
+CD9F8E596AF2C90F2811086F8D3AD8EB35E83593CCC09ECD57874DC98EF5120CA2F8EEE1FE73\
+1220578CDFD5CB31D019825904D8FB7811CA99C017C1963E1D4B:\
+7072696F6E636F7270::\
+1891F9604BC85FCE085AEC5C8221D0E06119A5B1E1D399764CEF9BC732F01A3C4A29D31FEA49\
+72EFCFA749A900CC8FD1238EAA90B7B04F0A092BBC90E5C01B5B6F7022193290CD2237F6509F\
+84150D542842BA98157D1C69C067DB357F52013632F6961533D7672D05394E76C219EF532ED1\
+BBAD1A5AC7AF5A0CE36C1173A8E1
+
+10001:\
+CC1D8027CE1F5163B3D5DC6DCC63DD14E5685894437A1A8734CC4AA4EE5CC8BFF96298D4FCBD\
+2208C17C3A069D0B4E1EE6B43A553DDBECB2ABCAB7F0CFA9CE01:\
+EDFFF64FC3E0CBAD1F36B472E868B0317DEEF27854D40179FC875DCE1C5CE3D3BADE0AFD191E\
+4661B5931844C56C53E53409B824DE0EC24E2C7C04508F022A6D:\
+7072696F6E636F7270::\
+86E1AAF65A3C352A514148D8C3B8CBB77E7C59CF001E2AA7850CBBB703D2684160A362ACE398\
+71EA60207044F9E266FF9BEC03E647E0A30B74CF24B45161619F1DBDDE0FEF6B491337EE2D66\
+BF2E9E5B5BB8E4C568D580C8584DBD4F758194523A34218631978DAF8BF8364D6C4399063DCB\
+E866029E6418F4D0BE384B66AF19
+
+10001:\
+E92BE18C86C96D98C8C47C9C279C42EC136D8CAB91F74DBD383611DEE72977411CDA0188146C8\
+9CEAF6AF4674CBDC56D0045F94033868EA7AD2871C349EC885FC832F394425A70BFFE5652A569\
+8AB3884A0780162A4B9E6DEBF3D091E1D7BE29:\
+D18F7F50ECEDE65887B004C7A9D715F1DE87D8FE37A14302848AD1C93A0502267A6A0E446F480\
+9F6F8FE43B934A456BD10975E819B7F2037EAB3BAFD5E699354B8B7384467CE25D80F8FB6F231\
+CBE28D39E55D2ABEF2107D719D0A758676D7B7:\
+7072696F6E636F7270::\
+AB183E642A3A50775FE8F158DE2085CF02C1F78A55DAD193D1F0F68DE45BCF8AE6812CCB81D47\
+6C27D4ECF63D9F1D9E9C5EEFA269CE214AF5A8FF24D933DABAEC2080491DA4BBB9654473C06A6\
+BAE99095C247515611B5A45D0E02E8AED9D708D20E823288D5761ECF80AC72D307260B9443747\
+4923AA53D34058147709CA35105B98C7039D1ADD75F0E38FEAE7E3121331937C0A01399177698\
+7522E43AC1072182C98BFA3D28940D03B0CF0533E41A42DC574A835BC57D77396B43D4A007A4
+
+[RSASSA/EMSA2(SHA-384)]
+10001:\
+DEC98FD436DE44985FDC398C4EDDD4356AE3D95A2A7CD0DDF5CCBC47C35405F85F05599C59A3C\
+CD143E5B663C4435F29:\
+D2556E2A05CEBC6D61F7485D1F8D4CA410D2EFB65055D461AD1D28031B4478261C5DC5C9B58AD\
+C7C4C609C7CA0A30F15:\
+7072696F6E636F7270::\
+36495268E4297C9F416915F3F9057C1B772FE6ED204995A2C30FBBDADEF3CDCF38420E3A11014\
+1BCC8BDD06F688B139E6D8BE97CF3201E48585B4391CE9CF2ADB91B5C20991B2AFC5C6A6F5E84\
+5E055971631E066391D962FB265FF3D90F3530
+
+10001:\
+FC488F1438DA425D701C068382AB37E85798CA4D7A6A151A20C7ECCA84CDAE3EDD3AC22F6ABF0\
+01107DA6188382F0CD8B5B591EEF45DF60C016FD22B6AB91F97:\
+E8A7CD9F6BE666AF5F10A81EBA40BE26B69A20A6F090C43035268B65AB7742D1410FC28F16D18\
+090F776E7162771765A757F754A8EFD75FAA83BC9258ACD9999:\
+7072696F6E636F7270::\
+09EFAA53EBF1FA0A23B84EA68DC7292F235C7F2A2EB555FC85F73A11A7A3785AF4284BE98840A\
+4F6D289647B04FAC1D867EE0EFD1E95E060FE4D2D766D11B03E678607E474621A0F5212139146\
+00977E8F3F31FB0E678D1C79079ECF39F5EC6FD2F62480C0C3F1DCEE06139ED661B33A32CCD1B\
+213F7557F6CF87A0425BBE88C
+
+10001:\
+F74FAFF1F8533804A2ED81EA92E9872505551954DF623503615B558EFCA368D32C7CC10B39679\
+160E0FDABEB0DDB874469677C2DDF45E369FAC599F4EBBCD5C5:\
+BBB2824D01BF3A3820C349D77CB6761081590767A8BD5753AAF71893C9220080ADF01D89D5217\
+FE714FCAD68AFEAD388F103DA7273AE2A67414198CE7022DD29:\
+7072696F6E636F7270::\
+858691CD4D14CD74841AEA3CF1564734D939CB7D8B4341BA1F74D88FDA993761AA5D850B258BDBEB228BECCC0F6B6C0EF96A3DEDC43A7078BF05D9FF4EA0224184572DEB43D77F0C9162CE69192EE3E50402579317B56838AEAC091369F216F19D271E7141149F1A5760071A65F08515D7226336C9C5EA6CF35691B1C92451C4
+
+10001:\
+F6B23AAC1C0FD29065D68C3DE26B5868E7ECEB7CCB2AA9A2DAD4497678E77547AD8BA78BFED51\
+3D2C303355B7850184A3C6DA974322ACA6CC553393BD532B8ABCFD02B961A5CDF81ADBC9F5A6F\
+A36D55652428788BA133741055635911595947:\
+F2C5190C41D49FAD95CE70CF1CD086F32F9C154E856156DC95007215B2D1C01F485370AB4A091\
+C919168732C99FA57BCF44A6041EDFC878EEC65EC54C0360A6320AFFEE19EFE7A4A0F62137A29\
+98BACFD7D364320FA178C8724EEBAC65D0E7DF:\
+7072696F6E636F7270::\
+9A399CE7D50ECA7184290BE01D43FF7D570F0A2232D385182AA068EA0FB097691C197B25ADF90\
+9397CC0648AE74029DA3477DB95CA4F3328E5E4CDA4A4BC67BF1D34020C8D9AA24B56861B0365\
+92D207026CFE4AA04B0B2ABDEF3911320D948776304FA648B60A18F7D07018804476E904213D0\
+9B1E99C31E66A8F37B4BBC1A57A753069BF9024C3636AD3690CC1FC1E6DEA4211F5E49F7F1DBE\
+2B94C31C19B0DFFDF41949D1AA6337BDFF1336486FFEF1369C3770C837FA2E1526B93A64CBB2
+
+[RSASSA/EMSA2(SHA-512)]
+10001:\
+F37DB2223CC3E4FB8D7FB028992B01A553CBDBCC700386BFA1A21422F1D15BE3E6E0CAAB5A7EB\
+5F0A58E4FDDEF70AEDD:\
+C490D201792C50C9840EB241B736093E647E27159EBEB336295985847E866FD5C44103ABCA57E\
+BA86AD3E6159D485755:\
+7072696F6E636F7270::\
+7F175F5E66601757E1B0ABC051602FDAE2B652B69B551BB35F8C6B295F580DD0D27360E91B8D5\
+3184D3E1C1606690ED84EFB9C2A5122936BB94C4ED7FA49D40195508499FB87249BC1FE07DAB2\
+17970EAAB46809BC6925D3AE54ECF6F62E76A9
+
+10001:\
+DF3B69AB64C8CB728CAFCC27A18233789AF1423A6D916860A4FCEF21FBA4DEEC43DE4A8E7BBB3\
+272F55FEE50565BB18A1B944B73EE20F13DAD9444BF9225505D:\
+FE7079379535E7BAB62DA87263F089364FAAA27796DACA16C7C82D29FED8FFC93C1E8B3B65431\
+4D336AF98932708EA37BDC150BA749A28DB4F12492966B51FFD:\
+7072696F6E636F7270::\
+786C58FA17D5A5A5B411B0A85F3306062D27978B84C9ACCFA79665E1C951AFB2746CD0FF03616\
+0BCCCBAAB15E7848E8E8582168804B0520867AA15F44456B018051AB290C9FE72AA121E5A1CF8\
+8B761C9F73B81F329B76DD2A4FF2A7F7905418B3343136C524089D368948CB9223A2FBD35C14A\
+3B994BAA333F5CFD60BCF47B8
+
+10001:\
+FC3439077A50A7A006CD1077683A5A5BE8E4B9B66CA0AB80AE5DEB4315D746DE493F354A3E172\
+D080132BEEB7F17B80CDC10E7301289CBEEA18A80D20F0387FD:\
+F20A00C5C12DB0F8E57C98DF1F69F76F14BA9E2137FFD7AC228DB02D2EFC1D574B9DA545A331E\
+0D906D57075FA15B7CD6ABC58362703DB9E9670709D33C9C1B1:\
+7072696F6E636F7270::\
+8DC903239378EA69E965121FD519C85D1D136D67126626EA93A31EA3706410E420984A6443AC8\
+731AEC98BA412CF4E2B39F2BE7308065F7BABAA15D25E126C996D7244D499C5E907B58441426A\
+407F001F62AAEC4274EF84AAD979FE504B05E277CD1B06A74DBB838EB7A20DC34D19B2CAB5206\
+351AF53BB968651CA4116F54B
+
+10001:\
+DCA8E48536240777EFE1290C0C89DB9492B33BD5767F7B8C12BC9659D21D35D253C054469FFC2\
+574EEED15509093B7606C59EB108A4F4EF4576BD84D2B61922A4CD3587E0A92D3A95AB3CDEE4F\
+31410CB1270F369E9E395524E22AD261609A05:\
+CAF14E53927C9C38D0EEE7DDA60162B9FD3A270EC0B8B301BAA41F880527FBF015BABE0413DFC\
+FF22338E8E1FED4F2026FAF720373F2ED955EE5252F486B13BAE0930E5012D0149B1780053029\
+96D967370C272513E20CAD5721F49A46869E4F:\
+7072696F6E636F7270::\
+3697C05A657A8904C792E750515BCB11751D2D4C4C1460FA6055A10A2C5F2320CFF2D82C0CF08\
+6E2E213CF5C4A4BE890F5C0A9F98789710646A500DA83333AE1CC6A24E99167B97B7E7EC06FDC\
+789037DF23F6FD1608695643C7D7C6462A0B37AD926FCA364A826DE539CC89419C99397C7FA1F\
+1CD244B0C7D3C27E77B6A4D4806E749B1291A23F8F3E6873BC8DE349F871530AE11CF4EC42E27\
+B6E3BACAA3DD6A40AE51463EDE39B510E94F0A177328F868C91B5C35F13AF0FEF0AA4AD88B4D
+
+[RSASSA/EMSA2(RIPEMD-128)]
+10001:\
+C6C21C5648183B9EF1AD5A7FEBD163C247F324CC8E4D1D57604B1CBF2E7FD20E501ED4E23C984\
+A19D67B006A46131597:\
+CCD27CFDADBD21DFE2E63324DA85389CC9DC4EEBEA55505E271A8BEFA966ABBD9AD57B714B09F\
+580B9E87C6BAE1FC2C3:\
+7072696F6E636F7270::\
+63F9A46002EEDF74A3B21A58AF360C78A0389A6FA469CC6C7F3F37B9298CB666C59CF993CD3EE\
+741C8D6896F61135D2223C3D02B0AE001DF8EC270968F8E999FFD7575F437747E2C0B4181EB3A\
+CFE51ADAD24924D75E86EFA2DF4531FFD1A718
+
+10001:\
+D9111254AD4B5B0403A9E3DD027F9C121A48A4B2ED5AB5F47E3F9C7EFC7CD1956AF1079EF2D78\
+B80034E9AF2455FEAEE955D718964E89C7588992B1E6D1022D5:\
+B8E8CA6745A849EC7F3471C1C83EFAD8AE65A8D5551A6924B45869D40ECCAE5B784A353F84301\
+EDC6A8365CDB25768B4BCEE67382E05E15367DF3F4274F06599:\
+7072696F6E636F7270::\
+38CDF4F149F7CAE46ECC24C32F98F30A73DA6B57F0281009493CBCCEE2B902F66DCCCFDEBB142\
+2992BBB4D62030D24FF6674C27163CE4015A3BC899CFE6A01ACC06A7E0CC36754ABFAD8D19F5E\
+7372747557FC9B2F5F8F19563F33AFD0D4E3CAF639657922468457E44032E72E865517E095B72\
+8E8ED3169D37B45374E53D692
+
+10001:\
+D130C34C595669CA5711EEEFE6176671DAE51D8841D0571A70C9F0B0A3DC9A7409B0AAEC4BE23\
+37B45163FC8A41AD5A16AF72462E0FDE6224D15082AEFFB5BB7:\
+E4DE294D95CD57AED2F82B8487FC20FBBD3A8E5C6A35D9BAF5C7DE67AE8FEC8BA82634A5654B9\
+3340D447F62367A861F10D1ED976D2B9CB0C856336F514BC301:\
+7072696F6E636F7270::\
+9CC6743EA34FB010B0B64975E37CF4C90BEDC063B9CA90F543CCA616C67D16A8EA0883DCAE11F\
+BA595CA8D42F45DA84532E8173149A55196D01E45588FF372A1D95DEBC58353B3892810F43F58\
+A935E85AFF87B46BCB77C6176422E887BA3671F44BD6112DB0E4A56B44BBED76EFDB01B079C43\
+FE9AD593E65162C9FDB92B42A
+
+10001:\
+F63306C54246545F8A552CA5E15BA425F1B2E096D8FFA17E8E2DB786FBB50D2D3EDC94D676955\
+E69B98A87674B4CBAD9651A99BA4D53B78B60F3A9ED4C871102D0E3A3576009439D55FA412191\
+D55F93EDBF0239DA1F60B5B68F270A629642B1:\
+EC9F3A07B1783A510793763A9D1B8F190E4ECA35165AF643E9C8365897D9803C3DE5BBAB35C37\
+D43475A9E4062C1B8A2FBA574C4C44778D75BA3706B4242ECB976EC0F58D0D04CE4D9B9E2465C\
+0723B3F0970F04C8E8236A9FAED6797CD87401:\
+7072696F6E636F7270::\
+3D2E76A438D4B927C4578B27EAAD666CC041D4495A14A462A530BC81AF115D961C4CF840E9B14\
+6C83BE619E9D7730ACC4589DC17665CB4B10A19E021BF4E5BD0F7A1CAF720BC4677B809F6E2BD\
+6A15B94590A5DA3F03E83D819B1A429F22D595D2D042468EF602944508915C88480AAE928ABA3\
+2B4CC8FB4C7125496623912FCEBFF28D8DB33CAF008AB6B7195019DF8BAC96E23238EA8EC60D1\
+C9527D91EC4018AA23A50B8B3998BB70006EC441334C1301D0A47C160FCE995A14831A737681
+
+[RSASSA/EMSA2(RIPEMD-160)]
+10001:\
+DC6B9418363C6D83813A2588C0C4DFE5105F3A7305D5A0539E157379DFA832D7F9C59FD8FAD36\
+2A716D111A374D6865F:\
+CF72057C7ACAC7F030000803AE1EEFB72C3812727FF304FAC9B086C2248BB36936AC9200C4605\
+BD7142BC3C17EB144E5:\
+7072696F6E636F7270::\
+3D2F44712403CAD3F07AC10278811EF59DE6441522F323CB3CD1C287B233B5FAC7EC2A3398383\
+FCD4A0AF6E404392707C72B22CA1C503C6FAEE3F3E992AE9D02C38564173CB492C9ED2EAA9664\
+859A06EBCAC73836DC80F7282D604A43B41BDE
+
+10001:\
+CBF2B084B2F9A826A2A1E1C6C3889E5B43A906B6A773AC56F44CC06E92F36EB5F624BDC0E550E\
+25DF80B9720988819FA79675DC4A9D28E86BFE0D95EE2A8B851:\
+E56C1DB39B5B2DC6893D4383433C33FD78B1260660B7FC2313B9ED808126D685AD9F2EA7DCAD6\
+5B8FF78F2D9F2BEBCE9A3EA33D68C2D4A2995DA2DBD50E32951:\
+7072696F6E636F7270::\
+A10E2A0C3743B0C8E9C4BA0AC71A60A368E98F0BE67623A22FBBE958FB590A31E2E07B016E55F\
+EDFCC8472F9CA002BC6F0A107FD77E839D77D24E65B48AE6688AA1309C3E8727C62337792DD43\
+0FBA8ACBB1B3F730C8D316F66683E13D892EA35E57E145E1F54AA0B786E19561BBB910C4D7997\
+D88852923C5D84DFFC9EF8644
+
+10001:\
+EBD673DDF90D8CBA51137B6F81EE230365F912C58B4D4792914C7FC8FFF9618CF494A59F31B8B\
+0DEC407F28FABF6F95360C8F42D2C1B4D8D485BE42A25646CE5:\
+E0AB6EA0A78039FED1A9192B22E0E3131717B79824DB21EC6013C34C63F60D1AD7E73DF2BA71B\
+F29279995EAA8C4116EB783199E3A0ADE2E1F597BC3A011C1FF:\
+7072696F6E636F7270::\
+2AAF175A74264765198AFE9556BA61BE30069B909D8D13C31B7EB5051ACCC2BCD80D51C0D0407\
+0A7C0BDA0E9C2F88E531D2CD0B27DABA850AD37F7B7390914AB1E40EA4C27F700D91C6F17D177\
+FACBD439A98CA75CD8B4D1DEC88A975A03C9727A75815A47909D490920CD9C9A7C7E1FBE63F7B\
+A724F4985B84C283176E0A28E
+
+10001:\
+F74DA54D764C5C4A5FA36661C976F579BD857ECB969B94078A16179B109D92021BFD8D09EFC05\
+B889874489E631F1132194FB5B7970A74ACEB17984C6AA2132BDE2C2C8770F63E36A85DCFA080\
+7DE2FA3DCF16CB34A2AC9A95078613193ADE47:\
+C71F05592CBA0FCA8879FE18C8A251C49386C45BE0A0BB96A60AA434E369050660293A61A56AD\
+B2D2B14A5DEC650539151A30007C2E5313298B240CD8C4DC83E93B1C8F9D74D622587C4FDC080\
+0D14C5900413DA7BCAE98C41E8731486D9D2D3:\
+7072696F6E636F7270::\
+86BC93AF170E1C26E10914E9D403FBC6B5CCD3F2B5EF2E2D94118E4DD024A82095EC8B6F71BFF\
+2CF91F0528CF7ACA12F2C74DCBC01D1DBD52A87A369AABE406F62F3FCC975826EAC8F56D3482E\
+2FD396D06F5BB1CFED3EC5B3C08AB318FDE17A7807054BDBE44EB0BDABCCFE3A627569B58EF91\
+FD8BC9E06B2EA40AE55E3C124418D6CD469F8F9552176B0229240660325E452802CEB3A01D726\
+9460AD098FB25A8ABB98F122F3ACB84B7158954DDFFC6FB3EEAF3615877D7BDE533CE8A6A8BA
+
+[RSASSA/EMSA2(Whirlpool)]
+10001:\
+C29370B3C4A445B4E638BA903092A7E6110DC8B5317FCD1E0729110C2324FC266CD6F2AE787EF\
+67CB219AA8CC382C3FB:\
+F5489C8111D841E2D4FBCF7FA2A06ABBC451B730835D41786D3CC4AAA3B31CA63A6E7D3FD2C26\
+79272A682D1BA40565B:\
+7072696F6E636F7270::\
+79C185314A87A5518D05B68A26889DA466A04D66497704D8FD0566B263F9FF4250D214B1A27EF\
+D557D79C9EBADF08A6715183D0225D45CA81A643898572B24DAF7FCCA7856F36D0168EE480A89\
+E15836B7235ACF83E75A83628424E7B058A61B
+
+10001:\
+C249C71113E5E469BA2689A821439024EDBFF7E1C01378BA65E4E8FD0ED377D6ED03F4935C4F0\
+F203CCD9F9CDDE6B59D313A7F76760C680E9DAF0FB2C6A30593:\
+B9C9A9BDC0FFB402EA1996E46C51E654AA7CA62400FE0441E8DA7F78E4A70D00348B54F5B664D\
+C0DF24DD760888D65A81D4380D3BDFCD2241EDAA777F8A4EC89:\
+7072696F6E636F7270::\
+2B7BB8B433BB6696562290BFE540BAEA1EF89D22DEAE1B5EAC8EE950772D0AADC6234CB598CFA\
+9FB2179AF94D320A177A8468C5AB8EA7AD71A14552001FC4FC578E0A1D1BB5D862B35EFC075E4\
+9FB085F3195CB1D332CD07881978BA4729B1B3C180D8D2FDF63D3F7E0E9C6A93B1AB70323BFD3\
+203520F28AF06E1CEE43D6C54
+
+10001:\
+DE2341F362821590F880B50B5AC864447DE5AF850BAF4D1B9FE89887DB107C9C94F4B978F6556\
+DE0D976E640F40590EA06557BA9FD53834AB3084A8717F9B91D:\
+CF5B9021453ABE9351007DC6F8B325F2A4FEAE0FDBB1AC667BC6CABCF9EC296D7230C2988ECF7\
+0425917718CB60B1397A40E5368CB68CB8B4C216FE7B4A1B6D7:\
+7072696F6E636F7270::\
+2402FDCA5051000AAB63E930AEDB1DFF71D8EB1BD0AEF2E9038D62E90849B9890BD5460C8A4B3\
+611C05F967E53F4E789DCDB0A1855BDA841C4DC92056B8B49F8056C5FD2651AD2ABAB6FE85493\
+31912CF0C0142590357964879E5C875143D589B5D7FD5BB210A51EE77F3447092ED2C6BF16FD8\
+935E9A509371CBB790B1AEE32
+
+10001:\
+CE1C752C02B795269599B060A5B88B6D1736B0B61534F841C316FEDDA6F429BF517821C21F924\
+CA115A3CFC902F35080354D036026717A720AFF85B4F1BBDA360A2D98207E6A6933659DB50B51\
+CF213F71908E0841417650DB80B5FE776CB885:\
+D6B9456FE2A050A0795BFA09025866CEDF378D2124FAC433B07366E0B16390A2C1463333136B9\
+79C2DB9006681185B3ED23223BD0B96BAE8F1F3CE173F7D405CE79FCAC09C4151A012D84B775C\
+445B6BD8C836F06005FC8994961B57B62C8C9D:\
+7072696F6E636F7270::\
+7748BFC3043893FCFBF4CBDD3F9BA00F995DB6183C39777D4545CA57287EDC6D5D6B620AD26EA\
+EA1FE60F4B809831614CC4D78A209BCE6CD712D4D3CC71623962F4EC7FC8519E861206E26AA9B\
+0B6FB1E16D0816E19B00F63E0701189688214FC063CE6835D1007794AE86E23A515C261B54E5F\
+963FC519FD8F4FE26FBBF7A445CA379857CD037753788E1A278F12BE61EB62AB7099FED68E8CA\
+78F2A5D35E873CBEC10B612FCB5A11084AF8D99A85EBB8685D54FA4E4EF5362A421D760346F0
+
+[RSASSA/EMSA3(Raw)]
+
+10001:\
+EC52390A18D0746B6CEED07F19FEA4C259BD24828E864DA60B13E6E125B21AC62B8FCA7EAFC98\
+E1FFF88909C250317C790254EEE922535C45A1D6CFAF3A73BBB:\
+B855A27256300A0DFAF83F8FF98FAC15112EE4A1498C2F70277529A4A968250321834347B5244\
+BC0E019934742993FCAA113DB15F6B24B74AA134600E127C8F7:\
+3021300906052B0E03021A05000414C26EDACE80B947FCFF75EC4CEC1AF0D1872674A9::\
+0E5FEDDAABCAC45E40ED484C89742408A1225204246EF04BF0F5FC87CF97EBB68EB3911E54824\
+0B5528FDA1E1C6D1DFFC2A70480466900FA7524ADEBA694B291CDCDF2560D9D6F70364AECF20F\
+504876AA1DDB8C69897E52DE92A13FD9E4684AD9EB8256A5723B1CCD34D4E552D9E2A5FA8B48F\
+AE13AF7CAE023450D65731DE8
+
+10001:\
+1C136DA3E140F55A5F07C1F314FBE3D97E4A69DF7456E95E4E06405375071405426D81261E4D1D089754D50C4C4AF42BF4D:\
+1F7303CD6DC61CC6833563E83C3AF5706E20BC7651257C0F890F2C8B1CB78554EE43715EBC1D026908CD78F56B489B33F03:\
+3021300906052B0E03021A05000414C26EDACE80B947FCFF75EC4CEC1AF0D1872674A9::\
+01E6EF82D25EE46471883D373869C553A54E0C256968958FBAC41D79C571940E523B96494360E\
+EEEC45DA943F94CE44DDBDFBF141E8F7B251E44EC47B64DDEEE2873C4B78A849242F3377F135E\
+EFC9AD4658061F575516C7B19321A3120D0BB3B11BC7
+
+10001:\
+C0E2F8859C52B2455C02E64F14D55CA27D91E802586702E028093D623153C63EBD03EBFB0C891\
+563C893E3DD5A7DF4DF7EB29FF7D4E7C14A3002FDDCF3B8617F:\
+FD058A73BB8BA46BB8F23BDA37BA33706BCA2E8B648DA3FB5D76A3C46DED8A2438A43A3E84D3B\
+5CA22C4DC30B0A607557032C53F6D95B825F18BDF1DC188EA27:\
+3021300906052B0E03021A05000414C26EDACE80B947FCFF75EC4CEC1AF0D1872674A9::\
+B2D322A392288D260F4D0AF6A3412A3F11B97A141367559FE3F2BDEEF208E14F2987E63B5C6A8\
+56190B37BE98A36A217AB8E49862427851A2C0E3FBFB8B1A2845A14DF7170B045833A8B2CC663\
+F481432E9B4B72E1AF141ACFF368C8DEEFECDBB35598BD5B815C3B26BB496BCEFE5CA308D56AF\
+870F3D92CCBCC9D3642FEDAD5
+
+10001:\
+E283F14941AC5DCFFA0A7C20B057885F75846966D15A88A02DC9837ED39EAB7D493CEA91D54F1\
+8EDCB0F8574CA257635663DD92B8881F0BCA3DDBEF415A8801B:\
+BB743C0E63157B359737BA7615DEEDF953B79CFB99A266BFAA05253F5E04051647450CEF0F7E7\
+15E6CA7A09A907B8F80EE99A4269E02714B9854C9B4D192941D:\
+3021300906052B0E03021A05000414C26EDACE80B947FCFF75EC4CEC1AF0D1872674A9::\
+5D71634BD519BF992AC97451C3BD856735498D963A37FD4E5F36E4611EAC7002CE762607EFAA8\
+A50FE0A054084E5DA46B99AC242733444087F94D7EF0FE1B0297EAFE035D13B4AE75BEF37B5BC\
+DB2F38C2216320351E09D277B3D6AAE701236550EA44B8AFB6A75B21721CA5C780DEE26244072\
+8A245036385CF917310DA42D6
+
+10001:\
+EA7D376F36A655748DBC105361285D9E2DD5A90F7087380EE6EA1EC931BEFCC76BD8FF1C0E9C2\
+05A4271FA5CFF3260BFE92319737CFEBCA0AFD56C0EF5A5DC404416F642E188A9574700687A71\
+937C2EBD6B4A047C4D35C901C6E28BAEC7EE03:\
+D6770E9C288C807D4E0BF8A4BAC4AA70E7A83E2E394BC448F0874B909C061392F4FBF51DB10F2\
+C87E117F242B222A31B74A9BD72522062AD87BEDE477D47A96A2D74477E7A9936E14F3488D3CF\
+620024A8EE42133ADBC7C49526D74804CD15A7:\
+3021300906052B0E03021A05000414C26EDACE80B947FCFF75EC4CEC1AF0D1872674A9::\
+5559398D21B7EF94223BB1BFFC8BB230640737A3F6D1E780DC59CF23A188206C1BF85EF086FBC\
+9D44B76B70F09E86C464AE53301CA8F31C704F5BA0CA4348B505FAB3B0940FFD831EDEBD22F8D\
+1215FA1CD0EB8ED678A3C7D4C713EBC8EC613F5D9B4BBC2E4AC47E403207E43C79E8F6EA12E7D\
+B8FA08D723864EA8D9580A274E84E2FFC3C57F366ED0CAEC9790F4B7E82B3E8419CE0F6143965\
+74F95CA498DDB75EB23AEC063C2B81251895F4A119A3B579D56011DCD412EF2B24FA4725D5FD
+
+
+[RSASSA/EMSA3(MD2)]
+10001:\
+33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61:\
+335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B:\
+45766572796F6E65206765747320467269646179206F66662E::\
+05FA6A812FC7DF8BF4F2542509E03E846E11B9C620BE2009EFB440EFBCC66921\
+6994AC04F341B57D05202D428FB2A27B5C77DFD9B15BFC3D559353503410C1E1
+
+[RSASSA/EMSA3(MD5)]
+11:\
+F8C72F6AD1A116B15688E6DDB4458E1CD69A21E4330AAB1F1024CA09AEA20C57\
+C1A1D3DFB612928E7FEEE51987D5898A24817F9A389A39A0E5A7C43CF30A16D9:\
+DDA05F490F538B6F09B2C1D14D85E66DC724D8B77D3218958A8AD6D1E9DC62D3\
+05A1FD010251CF0AD2BE511464CF33E5D8F7108E4E6E0FDBE0ED524A95DBF027:\
+556E7265717569746564206C6F7665207375636B732E::\
+7B558B0763B621830BDAF0AF9BD183A026041051579C303F351DCBC9DC168444\
+75D54EF5CCCEF59467015C4E4F8E17FF233BDE1D69B01DE46837884DFC265664\
+C5384E734555E5811259A206A05126EE70C2C1ED36A7EC2FD4F71F4F637EEF5C\
+833F92FAC30062434C43788DFB75B85BAF05227F5B1258CBC9EFF3F1D7BB9916
+
+10003:\
+D53E981F3D9AE9628B5038C8E48CBB944534522E8293145A3A98B855C4BB091E\
+67493348454DFDE02FF3C7148E313B917A199415937407B4856A98E50A570BDF:\
+CE8671329A80756167093EEFDB10D2E0E0906BDBC58C4A1A8E8FF1CD2AD25086\
+8C79F360A357B7EDC1A7220CF698D0565385ECCC9FFBB89EE76EFAA6B70E8881:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E::\
+319F7DA1448E5BA7EDAC7A5FB422A401481E895E0508D1C0FDEDA2AC51DE1D39\
+913F0D412E6E6D9313141992A202FBEFF3BD333542C88F626457046190AEB16F\
+F2A499DF5820240A5248074445B2D54DDF0C298F57B61D89EEABE7ABC728D4BD\
+E82834BA594C2231F2757A7FCD047039D3A3FE220571F30C41B5C25FDDE4FE87
+
+5:\
+314C5009A2E3B5B5C7C2E1C2A44AD98921F8005CD2C2AAB617F4DE5932FD5599\
+391584977B46ACB1020DE1E106E6B2861C2A6E0C980C151860967E51372E19F09:\
+331C1FA43BF7B78EEC60EB3627954A971FC50357F1ABDA7EFBF758793A75D601\
+6154DD9F5F878CFFDA6C5DD4F88BB5958C4D6EF4633DB0F3E578382BD69B2D567:\
+2831303238206269742074657374206F6620504B4353233129::\
+0484FEA19814279782BD0732A7A7E29738B2B2DF0D0D2928253921990B4F3908\
+F69B968FAF934C227FAF39BD35DBFD82F1C9BEAE66C4977E3AF69E0567635E18\
+A7D831D5C66A75AD8D80A6BC994EDBBE7D6F7FEC327A1E2055AA81720B336530\
+05C2CE87DF23E4A286D5A3CFF376643B969134C49E6929CC69A23E4137CE9AC719
+
+7:\
+436D230A470CA8401CA047FF1AEBAFF72FECC04A3D085576866701D5B2108D7B\
+355E8AFBEF3A687EEB6FBFF7C1152769E100EC77D72D000D6460E99C68BE30065:\
+57CDC664033ACB369AD87F6624A1342CD57E95F1CA0B44386AABD1664B511690\
+10AD4D724A900DBA16A8F10411800C15A91BE59D10ABF7147B4C291B0B0DE3AFB:\
+2831303239206269742074657374206F6620504B4353233129205075752120::\
+13AB41A8252B19A23ECC3781A7AA969ABF929AA562418750B9347F140F2C6DEE\
+BD760C27F650D403D4BC692B1BB9C99B0A8CB20D75502C3B451AEFE81BB1278E\
+23A4B7F5C3C438064CFC25890F68ED689EC7815F015C018BDCE766EE3A4A1535\
+19020BEAEC16F56F5559B8413BF0C4240645D2D8EF69B023639B336F1A2BD2A622
+
+3:\
+77757FAB85AED403810500EC7FF71C2D702A2681F4152757A6F553B3BFE264D8\
+78800D4D8021F95A425FF61153BBB9536BC67E92B5DA6FF752EC17B7F812A3DE9:\
+686C51FF0113EE267F13E63615215EF4988EF8EE5D519B41BCE5F405CFA73E7F\
+FD01E8B16727733A9F09F9E8114FDE3E6E40E93CB6B0D6DBAEBA9CE2368BBAFD3:\
+2831303330206269742074657374206F6620504B4353233129205075752120::\
+0F017BEC0E1206F2F7BD50500898EA57A1E798FBE0D8C66594F85064E1CD7FF6\
+FD528D562667C9B1D75492B83131CB1262906ABD657B3B15871CDE20F871D81D\
+E98CDF6FD87C5753A0A9E8C223BA1F1761273B9BF8756ACBDC0BD7E6E1CDCFAB\
+3C1722F1B3053ED85CE3CAA15A843112788E779E463BBF51BE3B51243CB14E6FF1
+
+B:\
+800CE163A96B6457B06761B5D3869E44137E7213E39ADE143127E9A539E1B0D8\
+1B28C3B950E90F437EF6ED8B983C0EDCA9A63B0B995A06230769069576CE144C3:\
+92A8C827CFD05C51EFA0BE5C958ED88B9813948B99A20042E3F54A8FF71F2FD3\
+5BC83DE9A242CBB3760071EDD6980C3BA7204B5CFB625FAC1367CB2DC83200CB7:\
+2831303330206269742074657374206F6620504B4353233129205075752120::\
+38DE0D39AECE20C3DA94E1B869C09F04BD22C072B1DB012E986DEEA9E254A5DD\
+5E6A946901EFC92A5EBABE010603125B60FD594A3D974986F58F6FC714473334\
+27B1FDC960512C121E8C81F0354EB956698EEE49A4F989390950B679E03A0B6D\
+964EBA3829C52C989A1ADDAE430D600188F1A215BB306EDFDE6E512E23F113C52C
+
+5:\
+A9E8F0A318CB66175E30DA2291CD2EDCD9A48DBDE30CC6D4AE4E479452DCB873\
+370599E4417350FA1F70E2F9B918C2284DF773680950983BBE35743010439A9F1:\
+83BAD868C9AD825C6C6CADE47F55F4D89974B2056293DA9C3D867EC11147720D\
+F048357E3331384C0EE2F6AFD28B9B8746BCA799C8896190C6879C1F59BD1B363:\
+2831303331206269742074657374206F6620504B4353233129205075752120::\
+192283FBAF7B9018D464D30A428689046AE3E25A499F8E437096800E09F4883B\
+E72626B9C0B50E982C5D53B6C733CECB6FF5C3CC2958BCE854BE89AA1D166361\
+ADFC0CA4B23D7A5D404B0F75ADE3FB134C965E427233F743925AB36DD45564F0\
+7FEC46F424A61977645E0C4D275A2BFB65A403FE14B20210B0CD3ED319C9D31420
+
+723B:\
+D7AFE0CDE0A05A44FEA97C7710960C3F1D7341279C025CBE16D4038C8EEF49BD\
+A81F1149AD31B33DE594C97431C52AF0F2D52198E3847CCE0AD02C5D6BFFE39D\
+52824BD671CE867AC0E219612A2AB769D82DCEA187E8AAA02428FCDE8ACCBDEF:\
+BA36A3D8F1F8AFFC57251452119236A532516ECBE4CF5AA6AC44533F4CA9995A\
+DA0FD9B0A742941AACA7FF0B12F2D317B046F5C3BC0609B519C4F564604D2969\
+19F677D590AF519ED70DE189ADEC8E024286D4C2E8866F7056E2333AF584E847:\
+47697665206D652073747566662E::\
+5C9417A66AE951AFD8900FF15463CBEC5D01DB8D771BE4BC35FBB2416D2D4D1D\
+89151E3CE6AFBC4F676627B538511C40EA1361FC2AE34DA5DE06C6507EF6FE27\
+E362830230F3B990AE26221960B459CAF308246EB6183FBB75A38A89A1A34A2D\
+D4466F18832917AC3A68AE63A8920FFC7F3353802D8E18F760F00B3BC62D5981\
+0F7F132CCB8C4A5EE2F2ABD6EC2A8FE03911F1336D70A4BBA00DDE153683CA0A\
+F730619C15AF48AC2021DF431C675874BD10B42432260EC07FAF5C2E93DE868F
+
+7205:\
+DEFB5C1A68C464B3190677215DD4D5098673AC1B510684135E5BF2AA8EF07395\
+6F29BE13C058AFD613308000261A2C90D8A8328AC2DCFBD65AD132B5D32FEDA8\
+FDF4601AA0BBCE72B56B1C01C65E6B2F3F1DAB6975574B70160BC2DA2F72F658\
+9FB9C35A8DEC519F7E4759CA4E71EB27C3CE37BF6152134B477CD8E9F5656D23:\
+EF363BC1C200BA863315BE1EBB8D0FBD5445D168BD8802D9E0DA108D4ABA276F\
+64C54006D180B53DDB655692740BE6FFAFE82565526E45626683C5CEFB768E64\
+6CA0348F5D70F435247775C5DCDFF681D955480EE5C41A2E739DDF27F321F24D\
+A4022998624D43FD566453C4603F2207A4CE906660D0D6EEFDCBC6B0585A633B:\
+47697665206D652073747566662E::\
+693E0EB1075D852FC14E4C3E54CC180F9B215A663C53AA85FE3F8777F25EF089\
+8871C922DE5508B7CD068559DEAAF1BB2C8FF590CDA7586BB8D8CD2FED31122F\
+E09A858ACE8BE7CDBD7DCEB1FB6E80ED4D1E203EA60DA5B4FC4127D3B649FE4E\
+F4991394F4B28AE8D2FF33A4B89FF8E18B9656137C43F4F950FB013882C1CCAB\
+486289B162256038F882AECFA6A5FC0B377A1B61F95B34ABCE4562805E614859\
+22B36B10C1DABAB069BDFE0EFBA0C44587CCB4FEB6839E6B2F7F07B2E90EFC1F\
+C8FA953FD56D603AE54458AFDEBDBDB99BCC29733194E1DF5DB9E7E63E993756\
+A043443A254CF4E41A171A65BE4DD3CF5AA4079F3AA69D220615B0BF935134E0
+
+71BB:\
+EED87D797D13FDD31AAD41AC7F88FED35F6483D4AC6989FDDCB540C04E69E2B5\
+085FF650613BDF8B8BCFF09E328176B8C6E5E8608A6B0BC6EA2C6461BC060FD7\
+B884A9155FB7DA583F95EA9EC896AE8C678454D9D9337C9E21F658E6B5B2EAE9\
+A8477E7D2A3F9115625A1D429087C3DA4DC71E7C9A08A44C91697B564A8ECE7C\
+E7BFF1C626F6C2D898E512CEED855A64090648FF5B71B385B551658B04F29D81\
+A00C6DA0600375D7BCB26AAE5E211EFA97AB806DABB4D783C5F8FE61BEE81565:\
+E9E6B997D92FB0DB4162D4412326D008CEA106665DEEBFC9B819E5B044A7B98B\
+3E628887BAE89C86066FFDBADFD0A52715DADCE0F4A2CCCBCCCBB095A2DD0014\
+FD8BEE4FEDEB95F19C1B7CF694E2C505BD614D06E18F362713A3DCAA41DA398D\
+29D507698D4B3FB1D8C070285A4B8A4808BE4BF60299D4E6912BA4C43CAB65D9\
+5B06F96FF50838E13B4938084C4D736FFB28477B30E4FBCD4C6826D1250B3A85\
+68DC0A7A0997CB2669DA44D925FCBD248ACDED9F5930DC805F019014AA806781:\
+47697665206D652073747566662E::\
+D0C2D44B72627C4CDF868393F38BA331742F7C553F930DBD85C2F52E8C57CEB5\
+08C31D7284DFCAD0EE161F298AB52D0B3E04FB0A6D1785F7EF0AD2B527F1DB04\
+50831A832F3F1D46357F042970DFEA8F81BBEC44B2B99272D15D6ED9587F116D\
+97E572B6534B4ED107BF43AA3DE758C074B4EB391B9AE3BDFE6D4A4FB2180A60\
+A1EC259E22825FDEADD6A13B19F011045EE8DDEF14EB404A0063DE0D953E9245\
+EF022943AF6476118600E6A726994C94309571C47B2155C9459D8BC757CB226C\
+057820443E593B4A78023F5D8BAA64BB48DD46C4AA77CE39E256A6388E2FC59C\
+E2B453AF687DA37A2C6D7E10D8328D25FF1CDE51926BB27C6200A590C8BA4BF4\
+274CC8E72CCD10271F14018573A1F41F9F1C582FC102D7621C2AC5078A14DAAB\
+36D26E055B3AA6DFBE6BE1C463C4415891086DECA173D99495188FA21F497E9D\
+270FDEB830B3F9D62F15CC843AE19F490717E9A7979139175BB7240F706851A0\
+F56BAD12970F2E0F031C313F93C9DAD4AAD0A26592D5E618B9E73566E68DCF72
+
+6FC1:\
+F34CAEA3D0B3D9BBEA6519414CDBAAF20A44AB2014D51545961B5917FF2D8F40\
+ADB5971ACB2116B7C5600DB30D8F80D54F54DDDE605A4AB5C7A4269A5678508A\
+545BB9EC585EA877EDC4C23C2370F44DB68A2FCEB73C09307CF22468CC4F51A4\
+2C1EF139FCE1867598F909931E7C364AFF8B5C1B60FAD396A641FE949888C6A0\
+C2FFF84FD7EB476B1292FACFF2DFB7F8B48934ED0352615E1AD701491C47098A\
+49920DCA9C9BE01C1C70F4AFC9BCFE869362816E21C552BBB918F521FD57688C\
+018969C6C48308D18589C2EC486A8C84E41263F594BC35993F15BD23BCE1EAB3\
+185D0828F441064D38D84148367DA2F6FFC9C29510ABABEBC33F6E525090C7B3:\
+FF433D0B39AE58722F5A84FBF7A09D31AC8D7A8A78C30E00EDB3B062C635C6DB\
+29472989F3039DB7319AC5F806E02BFAD02BFE61C01BDAD786DEFA6445E6F36E\
+CB3773B5A509E14BD414491DF694D4C5E798A33B1E4A0D371DA83B4C7B8D8D9C\
+7C8AAD77FE9ADC5CC67CFA0C9DC0772435EC455A6BC7F65D43E1B5653A80064A\
+E4EA6D910F509E16BBA32C3949BE9037F52A9A96AE49ACE787BEB0FF28E6061D\
+DB8004F4B34F65FB96DB8173AC72ACD89CFAA3428944612D4509546A3CBD0AB1\
+5B8C9CCCECF2D634CEF7D7DBB2DB35C107E7E3E6AAD6C8C73FF22166FADF2C6B\
+4F788889B7720A43EA2DA69203BE545C5A7897A8B9971E5EED87C3D57072A985:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E::\
+C4F7914A7930FF55A16083CCF84D72F03C900374BF60145EDEF156AF48ADCBCC\
+51AD3912EF0F27A84AACE8CF7DB7EDFC2133BE617EDA7AD5C69C82C2BC1532CC\
+04B005CE6349EC5F4951BDECCA0D65AA5A07923570A23F51A30C972B0966B2C7\
+FC3D0821D14555A2A2EF281AB0D533F5C37FA6B3A683B794C8770CCD41BBE418\
+262D1D6EFB98108BEFA271BA5441FCF68FDFAA450E02AEB78AAE5FBE8FE02D37\
+EFF8D7D250503F6BD5E6805BEDF3177FBBF8DEEEE4D2A36BEC34106B7E2FA7ED\
+1874C9023B6B71CBA87ED2954D0B0F52C1C51D8242B4012AA22689F9FCCA74C4\
+C1BEB23DA240C6FA183A2AFC494615382D3AB7C3A96601C2097B381C5EB5F530\
+AF1DA74FB05BDBC52B5F08030CB8C3518D8B9AE17A6164A781493FA7827E1E95\
+7EE09D0277019DE3304C03FA8071F8A4C720290DCF4ADEBA54C93BA3B71F886C\
+D20D959424599480BC35D7F6D6A3B0A112BCB5CD99F16DEF87B08816497E9B6A\
+6FA9D28049239776B0266AA28557D3B811B48FEB601E6CA16951CB899D6F56C7\
+828E37201420A9A51360750698BAD1DB0567BE0A3CE32CFEF34566FCEAC272FF\
+944FB8990C29A3430A5CFE9048D8F595B47AFA93CD910FEB471139FC9D992EEC\
+BDC0DD304AD20F551D2AC1AF97AA7C2F058DEDD9302BB7EAA3210748B49BBA81\
+95BC3B83719656AC55773D0A49A9F74F0DA0FFFA76BAF700F430EFCE96DF961C
+
+[RSASSA/EMSA3(SHA-1)]
+10001:\
+33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61:\
+335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B:\
+45766572796F6E65206765747320467269646179206F66662E::\
+0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604\
+A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81
+
+10001:\
+D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF:\
+C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3:\
+74657374::\
+A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296C\
+F612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE
+
+11:\
+D255E2DEC6F7B4A61424CCDBAA356FAC0D29CA7912EC755AD4C72D8F4C4ADA5B\
+51790C518C074098C5CF97CF651AD8F5D2D3926BC16872D69DF533ADCF71251D:\
+DAF30344A35FE911419B2BFB9C8B461B57A1FAB11DA8451391357AEA6B81348F\
+5CCC4E23B38D3DBA82603CC52AA5F1BDC6F37015246F33CD02C3027F557A265D:\
+7730307421::\
+A372D1D551F9260896C2513932A0828748086C5AAE2E8B5DFADEA3250E9A8748\
+3C9DBA5D6F3513202510C2970624C1EFDE858C432DE7E50ADCDC7D639C30AE8D\
+9D3B6E521AAC286D8613223066559148E6B06EFCEF9799541447C468D6B49ABD\
+E9B51B14B34E475B3D04A6747DEB2CCAC5400D1032DD977C0A98D79A74EB38AE
+
+11:\
+BFE1C1173207E6E33F699074865B0C285CDB92A7973DD2DE1E10F525E845DDA0\
+2A2145CE553BC039DFEE68AA6826855F9DD8398820536BCF83EF422E2E75A93F:\
+C542F0BF4CB661A6D3B0FBC3952BC85BF7C8A13F81F3D66A78A39A1A4480A172\
+26B913A53D0AF44775D76E611030782BEFFD979C74BF3483A709FF1A58F140A7:\
+556E7265717569746564206C6F7665207375636B732E::\
+0B43E57A2A216D15795C2538ADFE794FF0D4342CE4F61D0D0A5E7F38A2968F9D\
+6A032DF4B772DC7E0AEE89B5BC829D3F0BBB05758F0B95A10CF8B26677862737\
+CC3277443E4B5D162182B326723E210A3E2D8E6E9BFDC7C935CA2BF4E57036A5\
+A83661AC1EACC4033E79FD2B9EC525623B1EBA9F13BD70822EEFD0EF443B0993
+
+10003:\
+C739CEC54F45D25B3B4D69D70CAE94F2B5299A406F4F045076ACD84687A59E8A\
+1AFBE7DBE229186EC588D12397E401CE51A42BEA67CB6B10C984C117E2CB876B:\
+D549FD1428B28FBFC7CFE760D16AD9E4BD6129AB407AD79D4B964F6362B78DDF\
+AF20C8EA51471CD49A5E329F49420571F3A6E30E781BEB80CEB1CD7E07F57D61:\
+49742773206D7920626972746864617920746F646179212053656E64206D6520\
+736F6D657468696E6721::\
+1EE0E873EE0EBF9DCFD452596D731936F8115BD3EFDFA2D1383CDCF04B97DCE6\
+ED35853C19ECBCADAE81E431BD31ACBF9E4CD709D2490E552853FD523D6C680E\
+C59A0E6E51DC0BBDC4E783608BACF3B6648931B5DCC2979D932652A42D9F0EFC\
+6B1E6AAA85C97BF5DF88736BBDAF33139B729FB0340C89CED70AD556097EBA0F
+
+10003:\
+BAE8E1ECE4B7E06903A894BCDB1E4B576D8C7719D23343814D6EA2B65E26EA06\
+ED68DAA07048917EA74B8A75B6DF6BB68060BE68F3C0594EF99DAD5CAF9C2A75:\
+F1C1AF40EBC0BBD628E105246AC61FBDFE7C926156D8A644F6297C758500DC4E\
+943B392014068978BEBB3ACDEB73358D1E1F035DB73D01BDCF0536928EBDE885:\
+49206D65616E206974212053656E64206D6520736F6D657468696E6721204E4F\
+5721203A29::\
+4D0AC8B75C4338C456533A431596339617955F786998BA05BFE41A4BE24AEBAD\
+DF92201340E076E7384BB8E211FBEC7662573C1F63915E3033CD6C351D7CDAB8\
+AED5F3458AFFEBEFAB21612BF742EE012674D04AAD37C592775A55D6F78C6674\
+DFC0F927303F486E82AFDAFE28A55660E91687FEC0CA2AEDDC83512BEADA05B2
+
+11:\
+FBBB490DE6F5F485B0A25B71394A393488AF8131B5391C8D3F99ADAB2B5B1F89\
+87B9556C5FBF2F85DD56BA0F9507C500787E07C88726476F56A07491CC4FB97F:\
+E1C5F70CC3DA03313682723C22241CEC93AAE0455B59501F4E6603E790A06083\
+3710E9CFBD2D8472E193C0B9433B2290CF303389B3CEED97CD1F5C934AFDCAF3:\
+57687920646F204920616C7761797320656E64207570206C696B696E67206769\
+726C7320696E206C6F6E672D7465726D2072656C6174696F6E73686970733F::\
+4AE5B5600003871EDF01BC589DBDE5F5F8B558AF6F286D09572555FB4D34F640\
+173F0D17AEB67E18D05CD598595C78AA4E1246DDB0D311F38E3E21C02241F4F5\
+542B872DA50ADFE17407DC115C14DCB35847C3AFF8914967D8714B89CECC5745\
+C353D9831AE5B2C666A3077D5AC1131160AA59113193278587308D3E5BAED895
+
+3:\
+B6E4B50A4B61F147CC30C319CCEBEA1BB8151EE3012BFD2C80E8B13DBAE1657E\
+7AED914E80A26A4D1FCAFED54BF4457D609A33C6AE7631DE9A310E3EFD4353F1:\
+B841BF00069AE6F05A68CB11FF5E6389ED0C8AC9D2DBDD24CF0E0076B05FC226\
+E771C0D06C220908A559E5BF6626537B265B8D9C50E05E214724155F1C14A7E1:\
+4920616D20736F20677265617421204920616D20736F2067726561742120::\
+24D98B51D0419DD3D987D7E51528F571790AC78D2C80F36F64C7B4E05D90239E\
+8A5D9D7F46D636741B9F9A1DA58E58002D268A814528A4BF6B0AEE3B8EFEF0BD\
+72C956E4895FAA28E3EBD13E7EFD46A7BDFC3872D220EF4A2455E6CCCC407411\
+C2274D7F2BEDF4A727B569BFAE999F910BF69F5689DB7686328F97DED76C64E5
+
+7:\
+1343E65E7C11BE13536BB8BB569AAF091119ADE46FDCA9AE627910A39F9F909B\
+F921EDD9AB862813AA5AA5969620FD97ABD051352C89A336E420D1BCFB37A9CDF:\
+10A76D6261BE5FB018492566D9819028CA13B55A982C8A2A7CA31520124AB832\
+0F583BD5003F0E800775664DE2718481C15C841888350BF980D8F3EC017B9D851:\
+4920616D20736F20677265617421204920616D20736F20677265617421202831\
+3032352062697429::\
+0069212B4D49B93D56DBFD35534686BC4CE5EF057D3E5EB08E38C0CAC44A33C8\
+1ACF7E54ACB2F7D7029F63778B55D63C31E0FEBED8AF57050EC46E7C6B857112\
+B8A1FA0B4D5C11F976D01B5F56EBF55C678393CECFC801E51D6040A3631A0E77\
+56F9E81E2FF7A03E1B8A20F7DFAE90CF631043029AFFE3F615A54EA68ED470B393
+
+3:\
+1F16A49C815B9878A399B22419F0D948B33E8D7367A9F5928ED63146FEA7C69F\
+6C8A0EACA711970E370FB87CA3CCCDA71E1DBA9A12DBC003ED79F545876BFDA7D:\
+1F5C7840900C1C2E18340C156F8BE4EE70A4A0603412E689602C93B09FDD205E\
+23A775E7E1EAD3078EF9D5487D8A2EA5BABE8EE94AA0536CBA268B3BE7AD4B519:\
+4920616D20736F20677265617421204920616D20736F20677265617421202831\
+3032362062697429::\
+030551DE7296296876189AC2155EA4F80B3A68EF2A51F926494821E038A52548\
+4BDCA8CC4525D4BD04BEE373313D79DFEC59E22F21FB853C688FF9DA4CDCF6D1\
+2255BECED6DF3EFDED6046D4381D69B89EF17B892685707AE7B49E2205D95F73\
+0A1A003638FBCDDE5F4A5AEB028252F46195DB3CA1C708AAE22ACA7687B0DD2401
+
+7:\
+2037B35FDD14FACFA8B6DC8F48EC575F43CE8E2B5B89375A6FDDE1CFB66DACB9\
+8D7C57CE0F025BC7DD15533233AFCCBF392C0CB9DD79F49334D31F1FC0D17465D:\
+21265626E63E26739C0D086C3F19D7C8DA5B2FCD1452CE5290FF16F80AE6CDC3\
+49722661765B5AE418F23FBDAE4048C4FBB845822B2264C012ED6A8A257365F69:\
+4920616D20736F20677265617421204920616D20736F20677265617421202831\
+3032372062697429::\
+0090FD2E6B167F5B8E68AD965C170F87E2DDC69BA9312DE03B79018C90A80BF1\
+67704999C1A1B8AD31041428DBFE74FD89B398F5682F252DE85E19F33830CA2B\
+B775966C01EFCD6F95A5334DCEF07A0DF1F1114C21FEAA03D619EBCA60010F47\
+F671C35D754BD63DD5045E45CA21F7CB15FE2731AB27D91162D52320A540B17AE1
+
+# Following were genererated by Crypto++ 5.5.2
+11:\
+B7B1C37488F9585ABEE4F6C1255E70726F9FEC2532D86321:\
+C22463589E6BFBF3D9ACEC3D29F978BA3CD80D48478F40ED:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20\
+64617461206D696E696E672C206578706572742073797374656D732C2063727970746F\
+6772617068792C2073746567616E6F6772617068792C20646563656E7472616C697A65\
+64207472757374206D616E6167656D656E742C206661756C7420746F6C6572616E6365\
+2C207265706C69636174696F6E20616E642063616368696E672C2073656C662D686561\
+6C696E6720736F6674776172652C20776972656C65737320636F6D6D756E6963617469\
+6F6E732C20656D6265646465642073797374656D732C206D6963726F6B65726E656C20\
+617263686974656374757265732C206D7574616E74732C206379626F726765722E0A0A\
+776520646F6E277420746F79::\
+7019481E38A7ECA4D6E865FA22BFECBEE46963D4582419C3C79A272ED88630B4152AD9\
+336B08DE71B5C45FCE6C45B925
+
+11:\
+D83C1647F81DF86BD9F30E06C54CB22CDFB1BAA3224FBEE7:\
+E57DB05FC990CFDE83B59433D37C69CA6079AB4EBC103C59:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20\
+64617461206D696E696E672C206578706572742073797374656D732C2063727970746F\
+6772617068792C2073746567616E6F6772617068792C20646563656E7472616C697A65\
+64207472757374206D616E6167656D656E742C206661756C7420746F6C6572616E6365\
+2C207265706C69636174696F6E20616E642063616368696E672C2073656C662D686561\
+6C696E6720736F6674776172652C20776972656C65737320636F6D6D756E6963617469\
+6F6E732C20656D6265646465642073797374656D732C206D6963726F6B65726E656C20\
+617263686974656374757265732C206D7574616E74732C206379626F726765722E0A0A\
+776520646F6E277420746F79::\
+340E91C744AB8748E6891202979BDDFBA6003FFDAE83584359BF6FA5CAAFC8E811598C\
+5985CAFBC679417B64F6F42B02
+
+11:\
+CC1416D18974D023AF2D6FCA7BEEE85FCE5F036739E2AD8D89032C591C3B50498971F4FC2E25\
+384B789001D6526F4733963F2D98BCE1BA53121D15CE51C0C237:\
+EB2CB9DEAA582AEA4B7322C77308CADABCB824A2E511B93CBCF60A0DD6AFDA456A7FCEC6F7DE\
+F2F7CD3EE32C36BBD2A4445F2C6DDE86BD3881B25CFA6B4EE279:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+3B2CB445D8A533B0C3CF4C05EA87C266902EDB4CDF9BCB0289340253DD3110753D0712AA51FE\
+91CD0E59B73226BE63673FEABFE472BBF136B0C8F4A803284FE3DAD892233A8E81C97406E065\
+C5AADC4DA86746EA88E7E107FCFE1C925AEF5E5E4C13E76BE2129F114527A467A6227FE22BB0\
+2B6866ADBA5F6B11E8F85DFB4A8E
+
+# Generated by Crypto++ 5.5.2
+[RSASSA/EMSA3(SHA-224)]
+11:\
+BA54D5BBCC6D8E5A4DB29FF530C38DFBA7F970DDD062B74AB768F4E44353CA6DD790F4ADD677\
+38BAFE49D30ECDF22C55A856440F43D718433D5A508BF6A77183:\
+F08BDCEE74246EDD61D1FFCECE322630219FC68EFB5337AC80AA88630D2332654397759B18BD\
+F709004AFC150F2EE339B60F72E16C1BA3B6EEF910F698C2EDA1:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+9B3E6BA1DC0AF7133861A0EA2B956BE516918292AB708FF762548DCFBB02B1742AA3331DEF07\
+7504718F827C13E27F9102EE7B93D36E601C5A3E687F2F7289A20BDA7BDD1463BC2BED074AB9\
+8E7A4F3A0ECD579E8F40679D877DA0A8A7B97115A1CB965FD0B3BB65C84F62E5BE38E6C2E328\
+D8940DA14522E53075386712B8A4
+
+11:\
+EB5C08446CE56F03AB2B0AE7A4D9E4EF1FE2D706FB226577B03CEF9F004B3FD258814319F586\
+BFBAC234DBB5E9ADA33F638DB333FA948824C0C5F917E05201B03CAB20558F7D7CDB0DE42549\
+D51EBA4CF93068433F02727472C2559626D47A8E071B0AD848FD5B35965FB8E06DB4F65995CA\
+E876227DDD8A34C401ABE5BCB11D:\
+F4833CD56CEF4C9DACE2039CA3FB287172CF37C899D1D3267EC0D14EB967E42859A001CFA440\
+9DC1D8BA4952C5EA13D12FC4C016617F9062778E5B9F3BF0FB79C2870BE355F39BACC4B6178F\
+FD0B7A1C8B545A3FC781C1A2D54A962A93F7E41CE144B6C6E22AD3CF61DDB05A8F27508DD5AB\
+6725D8D0579732E621C33360ED7B:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+D685C80FB40EC09FC602880E6E55BCBA96332964505BA8BDFB8A181DC6700C2CBCDE6BD35E13\
+32E56FC5F6E2F80AAD046F9CCBBA36A6E3CB115969A2AF661CBAD42AC0D3C22662CFDE9C8544\
+E41018E88D5BD173AA59D0FE5FD0731730C44261E792F7958C76D7587CDDDF9AF0B99D70BFB7\
+4D6DCA952ADDCBBBAA711E6226E2568E532AE8DBF2BA2AE80F35DFCE1EFCC11BF68C100B32B4\
+8B2D4E22D782B42C97DF8B18164B3E73CC6A129F99E11AF30830A54376C9A5BE4A7F7B3C0115\
+F2B595EC5A4D841D55048E6BB226FC53D5998079E5F38D51BD1281B77E9E69E44DF8F1ED0F6A\
+BC10D2E11B941ABE6238ECEEFDC277EE6719B43F54317E98029AB437
+
+10001:\
+F75306FB8700184C998959EB1D271B3DBAB883726D270E21B91CA78C1BD148D1D428533853A8\
+8E4AB4E4CB033CF27E2A8A6C1A12880206D6B4D74A9373F35B5F:\
+E615C504FD127394B4522FF5BC0143C93A07636D184B9B40DF6461E3BAACC23AA1937C52B06E\
+95849692465060D092713D36B9E49FD76CA86D2389CF1B0F1A73:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+04C401283813191B750C8F6CEE6C41C1C9ADB7CBE26685E568D046D7F073775F19F9ACA0A43A\
+B9A6C200C07174C6AC6A67E89B6367DBA7135DC5C2236218BE42B7DEC0A40C1E165BF24F9B33\
+E69AB196B8FAADBDCAA657512B1641AF7D0DBBB9BE1BFD8895C6B79EA30C104A5DF1380182D3\
+D2C9B553D59F564DB82D7940E18A
+
+# Generated by Crypto++ 5.5.2
+[RSASSA/EMSA3(SHA-256)]
+10001:\
+B6661EB38B9C75A91E65FE5E6743C6949D6415D57CC4BCE84ED81E39EB8B4A77A867A15A3415\
+5B7E1CCCF972D6A06D73:\
+B85D9FA07D4F7CE1CF05150256FCE15BF7E647CDA350DDC574E72104DBDAF1F1F87930D1FAD8\
+C8E3094746ABE9E8C46B:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+275AB9846DD6999FDF4FC46F0E454B3CFF8C125096C0880DA957D65766A6298EDB41AE0F33DB\
+9FB15F9369E98B2738B37FF7165175E529B2349961C48B9459432FD58795052ADC2506D0B5F8\
+37879E771C66F59880F1371D78290B03F86454F9
+
+10001:\
+EF97A42D03FAA9A42A22D161B7819A932C4C5FAF5338A6E57C4379AE8C0A32C924B1398A53E1\
+37409B322A0E793090361417290C159D7B34A6A62A0D2E84D997:\
+DAA28E8CB6CCBF9A4EA5884AF7C791DC08BAEFEAB75F23EADE53A7D29D26B35CBE806C65886C\
+70597A03007949F556924E7D60E5298689E4D5F4E46311E48BAB:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+23223B652D5D0A17866DE55C77ECDA94A3B69ABB8CE335E5ACC03FE33A7D2D8257FF4227036DCAAD05820C135E2E5F332A01D77BE4FB3013529F6B1B9255669FFB64C134DBF01995CBF24C1735AE0028381B40A657E5C28D983478632C7975CD0C776CD8CFC3796DE7D8FDA86A0112ECE359361B35EB6DBDC7F5E44D469AED13
+
+10001:\
+D3B065134310F6A02A68E78829DBE58C5AFB148D95B30C7E54D8F463F0A66DFD3A78E2A15A26\
+18D5C6C972AD2BB14785E524CAFBA3B652C94D8F2579FA9C1F05:\
+F2CD098B9EBBD2B5AD589C30FD963EACD78D559190EB4D06880C8BA12EB55404D43AD51562D4\
+BC9B61B304AE664D22290AC6F4E20601A4DB97FE16A5DD0ACA5F:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+382C32D8EED4F7364BF68925FBE83338957605B064109AFF275457A3EE9BE4FD1EC1EBFBB3A4\
+72C3395F44DDBF378FEFEFC2B64CBFBC9C557B315DF6E8016FE3BBACB56A7DD3505F16A5F4A2\
+469250C77CEAFD2DE55D2FE96250E50CE813D529A909B8262456FFEF298D7472A8F5264CE667\
+24ABDB9F65C64C3747227804BCD1
+
+10001:\
+C24FBEA1E9F303117CF19C1EAC7721AF5DC228E39007336E48B1462CB5E7D2C9E61A69E8F501\
+FD26E71F5D881398A5FDE56FF565EED8715AA2CC0B46D78DB74F083253649A22E0C99DAABC26\
+3E87FE3F713A1270FBE3843FA596F35D43E577FB:\
+E346A9F2672A70264D5F2EAC6F17FEFA50457ACF92F30F4E849ADDDE6F3B95FDB6E17F55B939\
+D50FEE1D2F6114B0F7FB74AE8B4AACDD491FB085B2ED7D125A32121DFA87F2319F8357BEE127\
+F103EB1B31D98A52403498476A1E34F18B6CBAFB:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+8F4A78545DD1F10329A692EC66DBAE0B5D3302FCF6AA2561DF2CC73FA16C71EA947C919BA326\
+50A7C1F7938BDCF75C4E77CFEA7BAB8A083EDB531F95B4A67CF93CB5EDFE6B4BA07CEF887CA6\
+10C9A917C374399BE8CCD4B84BD15295C02028502348278E50A64D4B990E9F754C64FD55B8C4\
+E6E7EF8A2A2182864159A1BA012F325B3BF7F1B23D44593B749E51F382C290FBC6AD65EF5011\
+47F3A9A5A92AC5EBE4C82E259A212E52C95F94BA91CDFA88DF26BED55E4305EB08675A430CAC5B04
+
+# Generated by Crypto++ 5.5.2
+[RSASSA/EMSA3(SHA-384)]
+10001:\
+D6392D7E84F9A7233FAEE9B2F386C7921BC9974393EB3581EAFA66D8E7DDFB75BC2F0AF8A674\
+6563FF9C80A420B56BD1:\
+D6D02FCFD0CEBEC15844AB927C37BAE12E8EFD552FF706B3B632A30E5FC14C39BC0ACF423C73\
+C412BC8AF0A473276283:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+8CF24497F9C2DDB9183822444F2074CA22C5D51B52E3F513919EA69BDA0082B9C40680EB813B\
+E914E95EB9DACD3A3A238AAA675FB7DEFD55D2F981D5B3D6B9467DB8060081AE6F56EC7C0FC6\
+E6E078D614497ECF896DE4DAA4F679F683FE0A2D
+
+10001:\
+E39E5402011ED488B404C162C767046DFF79619DBA222F7EBF8B0FF0525F1213DA8316DCFB6B\
+35E22987CDF373EBD91F9467491391345DB4F15DE2D1928563A5:\
+D1B9E418890830E84D570E5209BFE6BC5A619C01F27E7EEDC1DD8FF0153B5891FEBC94A1843B\
+FFE8F8D3CEB9351CA75EE208AE2A9EC08DD52445AB3194489553:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+64A89B5FFD98351CEFC750C278B2E4A8808EFD83EA57FE6752AE245E058A2BB821DF2AE980F1\
+9618C2C6201CE72FE46F9E9CD0502B12EEE6A9E180B3FF61C97640CC82DB7D583FB17A78BA88\
+86884FEDB1D4F27929A203069B142FC314D27E4342AAFFC5100F7BDFF8162CAA98DC3A8A1F5C\
+5DD7B7234F67F1AEB34D911E7CD6
+
+10001:\
+C773EB83CEAF603D4C2D187CCE60A2564C7358C318E8817E183BDFA03BFBDE7EAB98A3A42E97\
+30F5E9D6F0849B438C7AB00E3B3032DEE05CBF32888BD63245CD:\
+BE95654D6DB5FDEFA2D3CB805687BD08D859982896071C433CA0C5051A44D8F49F1311BD35C4\
+9C8B6CA0CA746BE1ECF2126302758A5423BC0926AF4E96517931:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+519A0A554D5C8B4E749CDD92C21DCD8CBD5BB4494E9F15C91876F073756A896EE5A983A9AB72\
+6CCC6BDC0AA093B6643D683BFAAFE5BCD1A637ACBCA2B14C652C4926671A12275D4B3BEAA8A9\
+D5C57182B7AD6F8C89FE6A2555C8B8057A431FFF5BF1902E52183FFAD4D916563EA765809E92\
+6C626505FBDCE74ECD70F1EADEDD
+
+10001:\
+F914636EBBB1EBF51B642B8B8DE6BBB43390119D517139C9C6072C60A16E9E4CBD0598F929FF\
+D6B25C904CEFF6A434FD101B095E3AB5D454D07D813DF7823CEE33F638519BD2103E014DE215\
+0B6D8BAFAA698BB5619930FB39C64C3C1C31E72D:\
+F06C3A4F26E3144A3030B8424C41A7709812EEDABF37FB919DECA5554EF2AA2AFB4DB9A0986D\
+10ECFBA5897F43A7709FE7D3526C57A6EFAEFC116E26ECE0C577A63CF83638EB24911FAF54E0\
+C468215BAA4151178ACF872D2E5B3399A97C31F7:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+3577C7731A6D1E436F66F4367AE53EC80A3B632A8755DA97CA1DC7B5B7D6A946CA0D6AD0BA2B\
+B6C0EB8E2BC74725B606C00D6E96C87B75E73FD80F68DA2C829C57963855A85A66FD857FBF2C\
+7BF584501E5ED58BA06D5CE73FAA45BBE2F5C806409507A7F403E95FBC2971E0B7F399603F5E\
+EC3A67F4C912369A9FE03467AF0139CAF9D92A1364ECA159FBA485A73A10B9AA33667810707F\
+E8061F3632C43178BBA3C5113734F50A6360347A6119F87AD6A7A2308C9E42FA5FE096558586AC0D
+
+# Generated by Crypto++ 5.5.2
+[RSASSA/EMSA3(SHA-512)]
+10001:\
+FF1414834AF27B94F7818DC435D95D756FCC9F4F4DD9B25FFDC23BDACB511DAA9F76E39B411D\
+AD20D543AF198F8CC867:\
+F025AE2AC9135A5E23B1D90E17DEEAA872D45E6700CF011015E949429D320142EC0A802B7863\
+C8BDF99313FDAF2BF5CF:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+0C98A091C5B53A71F0BA4FD4CE5F58B0773070C05DB916B4FCFE5298267F28C457322A3AB262\
+E44079CE440DB56997AFCF30AF33E13DE774D066F07B92CBB8B6321F2DD967A94524DF050A1C\
+67AAA05D28C232472FAB214CE819792DD1147750
+
+10001:\
+B876A61A8F19113F9D5396BDDB5F54FFCCF8A35D1255979C797246F96D94D99A5B000B2DE9AB\
+81D1BBD16FFAAA092029500472F1FAAEADDC9E8D077F2E694B81:\
+DB86AB91CF13E90943B0D18016DADF2C4702AC4D6989299CF8338C3AB1620C8532D5297929D0\
+C1A0F76AA4D4DFC78D5D407399EEF35483BA6C8ACCC0A0C09C05:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+84E79B96AA2A3C43EA41FA415ECBF88D3DF93C15D8378EBC51CE114B6FAB16A8B07A3DD9148E\
+D1018A0E0385B19BE2AAEF0CB7603E3493DAA92C1ADB18EC5489BBCEAB9FDBEC41B423109A74\
+551425DBEA6A52A61530ACB8F955D102EBDCD15F2C96F01461DC1F196A87ED25F0B61DEB24B9\
+B7A02324B095219D3EB01855A40F
+
+10001:\
+D37A85110EE0F0CF8843EDFA1480F3CA4798798B5B592AD80F40C9E42BD21B162979F6002F64\
+EDDAC84E1D6DF41E02ABBC85D862B9ABE6B38FA9193701826CC9:\
+F3DA6327A3276EC647E5B1B9E8846314C2F7B5E84D3DA78E1EF18714158CAA3D700F438A03A4\
+D45A8B7422943F64ADCD582271BC30A687F6FF73A26263E89621:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+C18FF41DB165E740B5BE6D649E9C5F01E4C84862FA453DBD12485975F4BA802A460AC263AB1F\
+BCB53ABD46CA057C195A70381A83707515B154E2B5DA3529C8986034C47F6AE706D06B96D5A2\
+4B9A370276CF93129DB3519C15BCB2A35150C7EFE1B06CAFDD7DAA0B111E10DEBCCF53C04CF7\
+5D86DCD03F9B2C20336EC3FCD1C8
+
+10001:\
+C1CC91EFC0B3EA7938897E5675CE09E44A531492742770EA9C2AF96F7614F6ED4B6A17E85DBE\
+F6A24652CAACEA68E4E0F4100BAABE78F744668A973727B3B188194190F67D6E4E152E1498F9\
+45E7714CAAE6C37E215E2511596720C7B9DE49AD:\
+EB4D1A619C6E3947B9E3B07C84DD87244E130251B3F9C5D22B0162DBDA3BDFFED664C14848E9\
+9B02523B3D382D15546F8414888E4D3F95DD542F48C46CEFE19A85F36D98DBFC4BBBF3B5A1E6\
+0BCE38DC5DFC787C5D4C3B72011CAB73912A41F3:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+0437766509CEEFEA9ABC433289884E578D65BA463C572ED61BF3A48AE34769E8DDA73F2F4898\
+431068D518C16B7057467D7402796A0665A7FC7C4D8FD30077D4ABC08CB1E5207D78F130843D\
+42928F1968F49A87481B1B40B441E6E1135025BB23F8A9EA1F43F27EDF03FCF36EDFBE418A89\
+F7C11184571D8D80AFCEDF41A4F93FCFBD73A39D7BFAC2E263FCF91D4264E8571D044B1D568B\
+BA6F228FD47324132B2274EBF26CD4BC7520A2DBFFFBEE41A5DF72A5D8FD2C6647E62C28F04995AB
+
+
+[RSASSA/EMSA3(RIPEMD-160)]
+# Generated by Crypto++ 5.5.2
+10001:\
+BB305054066BEE5B66E9C651583F6B5F4005D3CE970520CDF277EF463EF1EF1B10E9428C6BCA\
+4254F42E40F0040C7577:\
+BE54384C3A200BBB597B8A59F8165D553B24B2A9F96236521580AB79924EBC6095E0905E58A7\
+C1BB302DFDA4FE489395:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+05C9082DAF39A7A706F6AE5CC1FE1A26F820301257DCDDB7B4DD91DB01B472E4C855E1AE6108\
+C32967659C69169197949BA58A194FFDE8449911FD5A8E7751A4E15CCED118DF2FF677D89827\
+99A76B59409BC76A31E696B26FEA324EC2CB6558
+
+10001:\
+D59E1378C1E752ACA0454839C11AA792AB2F0064920CABC3697A1701671DE4178103D8C619BA\
+12B453B3575BAD2E61CDD02C4509F188FF01B052121E2EB8634F:\
+F9761A2C67B685690846BD6746F0741FEACF188808B441CC66A54FA21B68C9CCA6F1BE26BD3C\
+CD67C11C0B6CD048CA5904A56F368D16843EE1E086B4A8461C6B:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+50971DC72D885146BCD0AE6D48271A71FEA3EFBD2B23F94F07333F421939F44DF8CA92CE88C0\
+10A65540F904D6FF9E2C4A4A0755CB21D6181581BB77FC58042A1A6F9993B24BC048B06F1985\
+A08CF902C06B0DAEB3997DB94398FC26C7E3EAF0D0787BFA3370C1E5E186F2064B803679B05E\
+481F0363895240FF54FF88E03C59
+
+10001:\
+EA0E165F4F81A6A6ED0FC49F26DE95FB7C42ACE29E650EBFFA2B1093389C987EC43B601B02E0\
+D3596D9718062CB071576D31BECB98E53570187CA122F3E20A83:\
+B731579363899B63B6E8857F983E0AFB56CD07EA8D3225A7A182BA2EAB6D3BDE2CC43620447E\
+A2D76947A7BD83439213271002261749F3E9F31E30209106F945:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+5A7A06EAA128549977CD5C0CDD8E1E4689EBEEB06B6EDDC2E39FEBE7BCF4D0068CB14CA8FF11\
+853C00A868F3B520F6503EED8055E9801AF20A277232C037079ECF06AEFD91CFAF387E4EC0C1\
+2C8D4635C5FA5FEFAD2F67E770FD7FD4115FF98A9B4883FC9D2BBD236126AB45EA3A05BF9F0A\
+355BD5F2AEA9158C4D70DF4A83FD
+
+10001:\
+DBB4D78472CE88FD41DAF8F0A6AE2D147BF34EDFFCD14B3855F5CE7C2ADA8AD08569BEA843B1\
+B568BE73BC7A567175114F8F493BBA87E777426828CDF044E08D1DB7E54231221FC64DE7A993\
+EF4281687EBC11E654E58BDAB125E289CFECC779:\
+D8CD194A4EA3650C927355B187BFE4367604F4BCE10D7633529455A6D11B8AE2745F9A3F0C99\
+D85853D0D645F25D7C9D03AAE28AA85FA3F434D72BBDCDB74AF5B2910B1BDBA9618FB5ADDA0F\
+34E201003E832764A55E6B625F2BB66DC124ECB1:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+85A0774004DF91004DF8A118EEB46EBEFFE690C964BC2F4D1429C76FB19B44969BA80C492FAD\
+BCAC6E36A1F118C3AB8E9BBE0DCE93E7B938E97177B3621CAAB19F1CBDC0AE9261B774782FDC\
+D2DB62AEB93F2EFB16386C5D1439A5CA6545D59FA11BD330BC0F49336FADF0A7EBF2636F6037\
+364DAFAEA4FEC9C290D34CF68FB1D9698E36385E56058CE62C0D25B98F95DA416AE9A5697CD2\
+6305D8DA193C7BA1AB9F66EDAC9087C9495B4B40B50D9812F2F2F6FB9FBDAD19B243FAFDCA7CEF2A
+
+
+[RSASSA/EMSA3(Tiger)]
+10001:\
+D402D64E23A5EA4FE4A256B14BBDF89832C814E0400B3C9673774073AE5D6EEE039C0744D486\
+3A0492DE49D402066A69:\
+FE7202E1A686745A0576A21FF1603090EA5CE042BBC943ED9BD4E931271542C77A12E6E1B5E5\
+FEEC5B90B5EA27D90237:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+908DD085BB0A924EECEA7F3DBDCDEFB8989A1F6971DE434F227289733F24D3F66AFF294BBF9D\
+23E80CCA352F232076397D5A862D4AE32DDC901C67416FECEAD311714105FF46044B0996CCC3\
+2938CE2EB5A95EC8E0631516BCA3855C82A712B7
+
+10001:\
+E826441E9CEDB949A69AE8C15C088F507B3095CAF8BDADF49F317DEABF45113F70E90910C182\
+EC1A2C433FCFF181CECC9211BAF3943517FCB32383F4CCBE526B:\
+C3B08505952722C91C384AA7962FDB3F96B27EDA6D7C65D081D924BCF8CF8AC6B8BECD12AA81\
+BD8D0B6CC8CA4646240A66A3718F89DC324C5E315D40F90AA51B:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+0F41FBA33B6E3A11EF94F8FD736431288C277B2E00DEE94B447FECD215E61E19B383687911BF\
+B2F46C0A9EF1AA3A787487C88A8C43006BC7D4D6C1D6137939B6B815D532EACFE05FEA6BC3A7\
+57E2A625F4188CE30792D6C75F205EB2C6515FC639780A86E1ED56C32CB223C7FBA8479682AC\
+24FCCC993F32EF55F818DC2F018E
+
+10001:\
+E493B0520556D6D50DACBF90EC41772CAE3873000EF163A94CE9F52BEF1F7962D7933E727ED3\
+EB4F03633CB3868F59BEC993B7DDF28FAA315456CA381D6650D5:\
+B996BB66BDF65F2FFDE68C156848DEC56BECEFBB6604CB0FE04A404D592CD13EC44DC0C5511B\
+25B7D5AB808B3FC16873BFF19210AD7245FC806062A6C72F3A47:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+0AF90FE65CB6FCB7BE90C5090943DC697534F9ED3A384FCE6F85AD5FDA36644D4BD68A0EC363\
+98E7F704796244B4793DF320F6D034D62AA4ECC579474D4EEA0E5F91C82F729B5A62A8314022\
+9C5DA882A6EB0D7DBC3436B73D1B493BFD7ECD32E11716A424A5FB2195A7865D1DCB05FCB95C\
+BED76FC52A85DE2AA9A9C2AA29D2
+
+10001:\
+C0800968E0C6E46099141267F195911D4EE36876E7D79DC6CB679FB1FE7C18387100CA9702F8\
+3E373EDB3799CBD97BBE966FE8B4A344BA4CCE3FEF86275ED0C42A1089B90C63010A135064EC\
+79769D2FC2B44ACC280AA7601329C8EB6E9C1AEB:\
+D939658B1F8C590B3A190CBCDFB9CAD087033FBCD775D18EA9EE5461EBFDB3286A488D196F03\
+426A939BC387A864E1657FFFD1C31651D8A7CBD6E57190C98590EE97BAE08CC29FB9822B4949\
+321BBEE59E9F8E5CBA8A62A1F3BE75E8F24DAFD1:\
+7072696F6E636F7270202D20676C6F62616C20696E6672617374727563747572652C20646174\
+61206D696E696E672C206578706572742073797374656D732C2063727970746F677261706879\
+2C2073746567616E6F6772617068792C20646563656E7472616C697A6564207472757374206D\
+616E6167656D656E742C206661756C7420746F6C6572616E63652C207265706C69636174696F\
+6E20616E642063616368696E672C2073656C662D6865616C696E6720736F6674776172652C20\
+776972656C65737320636F6D6D756E69636174696F6E732C20656D6265646465642073797374\
+656D732C206D6963726F6B65726E656C20617263686974656374757265732C206D7574616E74\
+732C206379626F726765722E0A0A776520646F6E277420746F79::\
+05C402CB39615771565E3F6E2C2CBC81B7528EFB38D19CB493E6F3525198D7B2604706811FC8\
+A28D9AE028C31326E5C43D1EF9F02FA74D12C9D8EB3639520BD190F2084E34DAFD70E761C9EB\
+1D410034A90A8475410E5DA5DDC5B5628060B1CEDE86E8C86D1ABFF24F2EFD725BEAB66957E2\
+464B57379308556D2E93F28743F4A652785B29247A5DB2A3D913C3B5C19ECC8F46FEB3C3C41A\
+4360D557BDE14022897F312FEE1F964508DE44A4B5CA23AF1D2A2D00C2183D0D5733E3CC3EF76A7D
+
+# These are (some of) the official RSADSI PSS test vectors,
+# plus a few specially constructed ones at the end
+[RSASSA/EMSA4(SHA-1)]
+10001:\
+E7E8942720A877517273A356053EA2A1BC0C94AA72D55C6E86296B2DFC967948\
+C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B3B6DCD3EDA8E6443:\
+B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA90479B6E48DE8D\
+67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A6799FD:\
+10AAE9A0AB0B595D0841207B700D48D75FAEDDE3B775CD6B4CC88AE06E4694EC\
+74BA18F8520D4F5EA69CBBE7CC2BEBA43EFDC10215AC4EB32DC302A1F53DC6C4\
+352267E7936CFEBF7C8D67035784A3909FA859C7B7B59B8E39C5C2349F1886B7\
+05A30267D402F7486AB4F58CAD5D69ADB17AB8CD0CE1CAF5025AF4AE24B1FB87\
+94C6070CC09A51E2F9911311E3877D0044C71C57A993395008806B723AC38373\
+D395481818528C1E7053739282053529510E935CD0FA77B8FA53CC2D474BD4FB\
+3CC5C672D6FFDC90A00F9848712C4BCFE46C60573659B11E6457E861F0F604B6\
+138D144F8CE4E2DA73:A8AB69DD801F0074C2A1FC60649836C616D99681:\
+2A34F6125E1F6B0BF971E84FBD41C632BE8F2C2ACE7DE8B6926E31FF93E9AF98\
+7FBC06E51E9BE14F5198F91F3F953BD67DA60A9DF59764C3DC0FE08E1CBEF0B7\
+5F868D10AD3FBA749FEF59FB6DAC46A0D6E504369331586F58E4628F39AA2789\
+82543BC0EEB537DC61958019B394FB273F215858A0A01AC4D650B955C67F4C58
+
+10001:\
+D17F655BF27C8B16D35462C905CC04A26F37E2A67FA9C0CE0DCED472394A0DF7\
+43FE7F929E378EFDB368EDDFF453CF007AF6D948E0ADE757371F8A711E278F6B:\
+C6D92B6FEE7414D1358CE1546FB62987530B90BD15E0F14963A5E2635ADB6934\
+7EC0C01B2AB1763FD8AC1A592FB22757463A982425BB97A3A437C5BF86D03F2F:\
+859EEF2FD78ACA00308BDC471193BF55BF9D78DB8F8A672B484634F3C9C26E6478AE1026\
+0FE0DD8C082E53A5293AF2173CD50C6D5D354FEBF78B26021C25C02712E78CD4694C9F46\
+9777E451E7F8E9E04CD3739C6BBFEDAE487FB55644E9CA74FF77A53CB729802F6ED4A5FF\
+A8BA159890FC:E3B5D5D002C1BCE50C2B65EF88A188D83BCE7E61:\
+8DAA627D3DE7595D63056C7EC659E54406F10610128BAAE821C8B2A0F3936D54DC3BDCE4\
+6689F6B7951BB18E840542769718D5715D210D85EFBB596192032C42BE4C29972C856275\
+EB6D5A45F05F51876FC6743DEDDD28CAEC9BB30EA99E02C3488269604FE497F74CCD7C7F\
+CA1671897123CBD30DEF5D54A2B5536AD90A747E
+
+10001:\
+E7E8942720A877517273A356053EA2A1BC0C94AA72D55C6E86296B2DFC967948\
+C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B3B6DCD3EDA8E6443:\
+B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA90479B6E48DE8D\
+67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A6799FD:\
+BC656747FA9EAFB3F0:056F00985DE14D8EF5CEA9E82F8C27BEF720335E:\
+4609793B23E9D09362DC21BB47DA0B4F3A7622649A47D464019B9AEAFE53359C\
+178C91CD58BA6BCB78BE0346A7BC637F4B873D4BAB38EE661F199634C547A1AD\
+8442E03DA015B136E543F7AB07C0C13E4225B8DE8CCE25D4F6EB8400F81F7E18\
+33B7EE6E334D370964CA79FDB872B4D75223B5EEB08101591FB532D155A6DE87
+
+10001:\
+016601E926A0F8C9E26ECAB769EA65A5E7C52CC9E080EF519457C644DA6891C5A1\
+04D3EA7955929A22E7C68A7AF9FCAD777C3CCC2B9E3D3650BCE404399B7E59D1:\
+014EAFA1D4D0184DA7E31F877D1281DDDA625664869E8379E67AD3B75EAE74A580\
+E9827ABD6EB7A002CB5411F5266797768FB8E95AE40E3E8A01F35FF89E56C079:\
+DABA032066263FAEDB659848115278A52C44FAA3A76F37515ED336321072C40A\
+9D9B53BC05014078ADF520875146AAE70FF060226DCB7B1F1FC27E9360:\
+57BF160BCB02BB1DC7280CF0458530B7D2832FF7:\
+014C5BA5338328CCC6E7A90BF1C0AB3FD606FF4796D3C12E4B639ED9136A5FEC\
+6C16D8884BDD99CFDC521456B0742B736868CF90DE099ADB8D5FFD1DEFF39BA4\
+007AB746CEFDB22D7DF0E225F54627DC65466131721B90AF445363A8358B9F60\
+7642F78FAB0AB0F43B7168D64BAE70D8827848D8EF1E421C5754DDF42C2589B5B3
+
+10001:\
+016601E926A0F8C9E26ECAB769EA65A5E7C52CC9E080EF519457C644DA6891C5A1\
+04D3EA7955929A22E7C68A7AF9FCAD777C3CCC2B9E3D3650BCE404399B7E59D1:\
+014EAFA1D4D0184DA7E31F877D1281DDDA625664869E8379E67AD3B75EAE74A580\
+E9827ABD6EB7A002CB5411F5266797768FB8E95AE40E3E8A01F35FF89E56C079:\
+52A1D96C8AC39E41E455809801B927A5B445C10D902A0DCD3850D22A66D2BB07\
+03E67D5867114595AABF5A7AEB5A8F87034BBB30E13CFD4817A9BE7623002360\
+6D0286A3FAF8A4D22B728EC518079F9E64526E3A0CC7941AA338C437997C680C\
+CAC67C66BFA1:FCA862068BCE2246724B708A0519DA17E648688C:\
+007F0030018F53CDC71F23D03659FDE54D4241F758A750B42F185F87578520C3\
+0742AFD84359B6E6E8D3ED959DC6FE486BEDC8E2CF001F63A7ABE16256A1B84D\
+F0D249FC05D3194CE5F0912742DBBF80DD174F6C51F6BAD7F16CF3364EBA095A\
+06267DC3793803AC7526AEBE0A475D38B8C2247AB51C4898DF7047DC6ADF52C6C4
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+594B37333BBB2C84524A87C1A01F75FCEC0E3256F108E38DCA36D70D0057:\
+F31AD6C8CF89DF78ED77FEACBCC2F8B0A8E4CFAA:\
+0088B135FB1794B6B96C4A3E678197F8CAC52B64B2FE907D6F27DE761124964A\
+99A01A882740ECFAED6C01A47464BB05182313C01338A8CD097214CD68CA103B\
+D57D3BC9E816213E61D784F182467ABF8A01CF253E99A156EAA8E3E1F90E3C6E\
+4E3AA2D83ED0345B89FAFC9C26077C14B6AC51454FA26E446E3A2F153B2B16797F
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+8B769528884A0D1FFD090CF102993E796DADCFBDDD38E44FF6324CA451:\
+FCF9F0E1F199A3D1D0DA681C5B8606FC642939F7:\
+02A5F0A858A0864A4F65017A7D69454F3F973A2999839B7BBC48BF7864116917\
+9556F595FA41F6FF18E286C2783079BC0910EE9CC34F49BA681124F923DFA88F\
+426141A368A5F5A930C628C2C3C200E18A7644721A0CBEC6DD3F6279BDE3E8F2\
+BE5E2D4EE56F97E7CEAF33054BE7042BD91A63BB09F897BD41E81197DEE99B11AF
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+1ABDBA489C5ADA2F995ED16F19D5A94D9E6EC34A8D84F84557D26E5EF9B02B22\
+887E3F9A4B690AD1149209C20C61431F0C017C36C2657B35D7B07D3F5AD87085\
+07A9C1B831DF835A56F831071814EA5D3D8D8F6ADE40CBA38B42DB7A2D3D7A29\
+C8F0A79A7838CF58A9757FA2FE4C40DF9BAA193BFC6F92B123AD57B07ACE3E6A\
+C068C9F106AFD9EEB03B4F37C25DBFBCFB3071F6F9771766D072F3BB070AF660\
+5532973AE25051:986E7C43DBB671BD41B9A7F4B6AFC80E805F2423:\
+0244BCD1C8C16955736C803BE401272E18CB990811B14F72DB964124D5FA7606\
+49CBB57AFB8755DBB62BF51F466CF23A0A1607576E983D778FCEFFA92DF7548A\
+EA8EA4ECAD2C29DD9F95BC07FE91ECF8BEE255BFE8762FD7690AA9BFA4FA0849\
+EF728C2C42C4532364522DF2AB7F9F8A03B63F7A499175828668F5EF5A29E3802C
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+8FB431F5EE792B6C2AC7DB53CC428655AEB32D03F4E889C5C25DE683C461B53A\
+CF89F9F8D3AABDF6B9F0C2A1DE12E15B49EDB3919A652FE9491C25A7FCE1F722\
+C2543608B69DC375EC:F8312D9C8EEA13EC0A4C7B98120C87509087C478:\
+0196F12A005B98129C8DF13C4CB16F8AA887D3C40D96DF3A88E7532EF39CD992\
+F273ABC370BC1BE6F097CFEBBF0118FD9EF4B927155F3DF22B904D90702D1F7B\
+A7A52BED8B8942F412CD7BD676C9D18E170391DCD345C06A730964B3F30BCCE0\
+BB20BA106F9AB0EEB39CF8A6607F75C0347F0AF79F16AFA081D2C92D1EE6F836B8
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+FEF4161DFAAF9C5295051DFC1FF3810C8C9EC2E866F7075422C8EC4216A9C4FF\
+49427D483CAE10C8534A41B2FD15FEE06960EC6FB3F7A7E94A2F8A2E3E43DC4A\
+40576C3097AC953B1DE86F0B4ED36D644F23AE14425529622464CA0CBF0B1741\
+347238157FAB59E4DE5524096D62BAEC63AC64:\
+50327EFEC6292F98019FC67A2A6638563E9B6E2D:\
+021ECA3AB4892264EC22411A752D92221076D4E01C0E6F0DDE9AFD26BA5ACF6D\
+739EF987545D16683E5674C9E70F1DE649D7E61D48D0CAEB4FB4D8B24FBA84A6\
+E3108FEE7D0705973266AC524B4AD280F7AE17DC59D96D3351586B5A3BDB895D\
+1E1F7820AC6135D8753480998382BA32B7349559608C38745290A85EF4E9F9BD83
+
+10001:\
+01BD36E18ECE4B0FDB2E9C9D548BD1A7D6E2C21C6FDC35074A1D05B1C6C8B3D5\
+58EA2639C9A9A421680169317252558BD148AD215AAC550E2DCF12A82D0EBFE853:\
+01B1B656AD86D8E19D5DC86292B3A192FDF6E0DD37877BAD14822FA00190CAB2\
+65F90D3F02057B6F54D6ECB14491E5ADEACEBC48BF0EBD2A2AD26D402E54F61651:\
+EFD237BB098A443AEEB2BF6C3F8C81B8C01B7FCB3FEB:\
+B0DE3FC25B65F5AF96B1D5CC3B27D0C6053087B3:\
+012FAFEC862F56E9E92F60AB0C77824F4299A0CA734ED26E0644D5D222C7F0BD\
+E03964F8E70A5CB65ED44E44D56AE0EDF1FF86CA032CC5DD4404DBB76AB85458\
+6C44EED8336D08D457CE6C03693B45C0F1EFEF93624B95B8EC169C616D20E553\
+8EBC0B6737A6F82B4BC0570924FC6B35759A3348426279F8B3D7744E2D222426CE
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+9FB03B827C8217D9:ED7C98C95F30974FBE4FBDDCF0F28D6021C0E91D:\
+0323D5B7BF20BA4539289AE452AE4297080FEFF4518423FF4811A817837E7D82\
+F1836CDFAB54514FF0887BDDEEBF40BF99B047ABC3ECFA6A37A3EF00F4A0C4A8\
+8AAE0904B745C846C4107E8797723E8AC810D9E3D95DFA30FF4966F4D75D1376\
+8D20857F2B1406F264CFE75E27D7652F4B5ED3575F28A702F8C4ED9CF9B2D44948
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+0CA2AD77797ECE86DE5BF768750DDB5ED6A3116AD99BBD17EDF7F782F0DB1CD0\
+5B0F677468C5EA420DC116B10E80D110DE2B0461EA14A38BE68620392E7E893C\
+B4EA9393FB886C20FF790642305BF302003892E54DF9F667509DC53920DF583F\
+50A3DD61ABB6FAB75D600377E383E6ACA6710EEEA27156E06752C94CE25AE99F\
+CBF8592DBE2D7E27453CB44DE07100EBB1A2A19811A478ADBEAB270F94E8FE36\
+9D90B3CA612F9F:22D71D54363A4217AA55113F059B3384E3E57E44:\
+049D0185845A264D28FEB1E69EDAEC090609E8E46D93ABB38371CE51F4AA65A5\
+99BDAAA81D24FBA66A08A116CB644F3F1E653D95C89DB8BBD5DAAC2709C89840\
+00178410A7C6AA8667DDC38C741F710EC8665AA9052BE929D4E3B16782C16621\
+14C5414BB0353455C392FC28F3DB59054B5F365C49E1D156F876EE10CB4FD70598
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+288062AFC08FCDB7C5F8650B29837300461DD5676C17A20A3C8FB5148949E3F7\
+3D66B3AE82C7240E27C5B3EC4328EE7D6DDF6A6A0C9B5B15BCDA196A9D0C76B1\
+19D534D85ABD123962D583B76CE9D180BCE1CA:\
+4AF870FBC6516012CA916C70BA862AC7E8243617:\
+03FBC410A2CED59500FB99F9E2AF2781ADA74E13145624602782E2994813EEFC\
+A0519ECD253B855FB626A90D771EAE028B0C47A199CBD9F8E3269734AF416359\
+9090713A3FA910FA0960652721432B971036A7181A2BC0CAB43B0B598BC62174\
+61D7DB305FF7E954C5B5BB231C39E791AF6BCFA76B147B081321F72641482A2AAD
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+6F4F9AB9501199CEF55C6CF408FE7B36C557C49D420A4763D2463C8AD44B3CFC\
+5BE2742C0E7D9B0F6608F08C7F47B693EE:\
+40D2E180FAE1EAC439C190B56C2C0E14DDF9A226:\
+0486644BC66BF75D28335A6179B10851F43F09BDED9FAC1AF33252BB9953BA42\
+98CD6466B27539A70ADAA3F89B3DB3C74AB635D122F4EE7CE557A61E59B82FFB\
+786630E5F9DB53C77D9A0C12FAB5958D4C2CE7DAA807CD89BA2CC7FCD02FF470\
+CA67B229FCCE814C852C73CC93BEA35BE68459CE478E9D4655D121C8472F371D4F
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+E17D20385D501955823C3F666254C1D3DD36AD5168B8F18D286FDCF67A7DAD94\
+097085FAB7ED86FE2142A28771717997EF1A7A08884EFC39356D76077AAF8245\
+9A7FAD45848875F2819B098937FE923BCC9DC442D72D754D812025090C9BC03D\
+B3080C138DD63B355D0B4B85D6688AC19F4DE15084A0BA4E373B93EF4A555096\
+691915DC23C00E954CDEB20A47CD55D16C3D8681D46ED7F2ED5EA42795BE17BA\
+ED25F0F4D113B3636ADDD585F16A8B5AEC0C8FA9C5F03CBF3B9B73:\
+2497DC2B4615DFAE5A663D49FFD56BF7EFC11304:\
+022A80045353904CB30CBB542D7D4990421A6EEC16A8029A8422ADFD22D6AFF8\
+C4CC0294AF110A0C067EC86A7D364134459BB1AE8FF836D5A8A2579840996B32\
+0B19F13A13FAD378D931A65625DAE2739F0C53670B35D9D3CBAC08E733E4EC2B\
+83AF4B9196D63E7C4FF1DDEAE2A122791A125BFEA8DEB0DE8CCF1F4FFAF6E6FB0A
+
+10001:\
+029232336D2838945DBA9DD7723F4E624A05F7375B927A87ABE6A893A1658FD4\
+9F47F6C7B0FA596C65FA68A23F0AB432962D18D4343BD6FD671A5EA8D148413995:\
+020EF5EFE7C5394AED2272F7E81A74F4C02D145894CB1B3CAB23A9A0710A2AFC\
+7E3329ACBB743D01F680C4D02AFB4C8FDE7E20930811BB2B995788B5E872C20BB1:\
+AFBC19D479249018FDF4E09F618726440495DE11DDEEE38872D775FCEA74A238\
+96B5343C9C38D46AF0DBA224D047580CC60A65E9391CF9B59B36A860598D4E82\
+16722F993B91CFAE87BC255AF89A6A199BCA4A391EADBC3A24903C0BD667368F\
+6BE78E3FEABFB4FFD463122763740FFBBEFEAB9A25564BC5D1C24C93E422F750\
+73E2AD72BF45B10DF00B52A147128E73FEE33FA3F0577D77F80FBC2DF1BED313\
+290C12777F50:A334DB6FAEBF11081A04F87C2D621CDEC7930B9B:\
+00938DCB6D583046065F69C78DA7A1F1757066A7FA75125A9D2929F0B79A60B6\
+27B082F11F5B196F28EB9DAA6F21C05E5140F6AEF1737D2023075C05ECF04A02\
+8C686A2AB3E7D5A0664F295CE12995E890908B6AD21F0839EB65B70393A7B5AF\
+D9871DE0CAA0CEDEC5B819626756209D13AB1E7BB9546A26FF37E9A51AF9FD562E
+
+10001:\
+03F2F331F4142D4F24B43AA10279A89652D4E7537221A1A7B2A25DEB551E5DE9\
+AC497411C227A94E45F91C2D1C13CC046CF4CE14E32D058734210D44A87EE1B73F:\
+034F090D73B55803030CF0361A5D8081BFB79F851523FEAC0A2124D08D4013FF\
+08487771A870D0479DC0686C62F7718DFECF024B17C9267678059171339CC00839:\
+30C7D557458B436DECFDC14D06CB7B96B06718C48D7DE57482A868AE7F065870\
+A6216506D11B779323DFDF046CF5775129134B4D5689E4D9C0CE1E12D7D4B06C\
+B5FC5820DECFA41BAF59BF257B32F025B7679B445B9499C92555145885992F1B\
+76F84891EE4D3BE0F5150FD5901E3A4C8ED43FD36B61D022E65AD5008DBF3329\
+3C22BFBFD07321F0F1D5FA9FDF0014C2FCB0358AAD0E354B0D29:\
+081B233B43567750BD6E78F396A88B9F6A445151:\
+0BA373F76E0921B70A8FBFE622F0BF77B28A3DB98E361051C3D7CB92AD045291\
+5A4DE9C01722F6823EEB6ADF7E0CA8290F5DE3E549890AC2A3C5950AB217BA58\
+590894952DE96F8DF111B2575215DA6C161590C745BE612476EE578ED384AB33\
+E3ECE97481A252F5C79A98B5532AE00CDD62F2ECC0CD1BAEFE80D80B962193EC1D
+
+10001:\
+03F2F331F4142D4F24B43AA10279A89652D4E7537221A1A7B2A25DEB551E5DE9\
+AC497411C227A94E45F91C2D1C13CC046CF4CE14E32D058734210D44A87EE1B73F:\
+034F090D73B55803030CF0361A5D8081BFB79F851523FEAC0A2124D08D4013FF\
+08487771A870D0479DC0686C62F7718DFECF024B17C9267678059171339CC00839:\
+328C659E0A6437433CCEB73C14:\
+9AEC4A7480D5BBC42920D7CA235DB674989C9AAC:\
+0BC989853BC2EA86873271CE183A923AB65E8A53100E6DF5D87A24C4194EB797\
+813EE2A187C097DD872D591DA60C568605DD7E742D5AF4E33B11678CCB639032\
+04A3D080B0902C89ABA8868F009C0F1C0CB85810BBDD29121ABB8471FF2D39E4\
+9FD92D56C655C8E037AD18FAFBDC92C95863F7F61EA9EFA28FEA401369D19DAEA1
+
+10001:\
+04F0548C9626AB1EBF1244934741D99A06220EFA2A5856AA0E75730B2EC96ADC\
+86BE894FA2803B53A5E85D276ACBD29AB823F80A7391BB54A5051672FB04EEB543:\
+0483E0AE47915587743FF345362B555D3962D98BB6F15F848B4C92B1771CA8ED\
+107D8D3EE65EC44517DD0FAA481A387E902F7A2E747C269E7EA44480BC538B8E5B:\
+0F6195D04A6E6FC7E2C9600DBF840C39EA8D4D624FD53507016B0E26858A5E0A\
+ECD7ADA543AE5C0AB3A62599CBA0A54E6BF446E262F989978F9DDF5E9A41:\
+A87B8AED07D7B8E2DAF14DDCA4AC68C4D0AABFF8:\
+086DF6B500098C120F24FF8423F727D9C61A5C9007D3B6A31CE7CF8F3CBEC1A2\
+6BB20E2BD4A046793299E03E37A21B40194FB045F90B18BF20A47992CCD799CF\
+9C059C299C0526854954AADE8A6AD9D97EC91A1145383F42468B231F4D72F237\
+06D9853C3FA43CE8ACE8BFE7484987A1EC6A16C8DAF81F7C8BF42774707A9DF456
+
+10001:\
+04F0548C9626AB1EBF1244934741D99A06220EFA2A5856AA0E75730B2EC96ADC\
+86BE894FA2803B53A5E85D276ACBD29AB823F80A7391BB54A5051672FB04EEB543:\
+0483E0AE47915587743FF345362B555D3962D98BB6F15F848B4C92B1771CA8ED\
+107D8D3EE65EC44517DD0FAA481A387E902F7A2E747C269E7EA44480BC538B8E5B:\
+9906D89F97A9FDEDD3CCD824DB687326F30F00AA25A7FCA2AFCB3B0F86CD41E7\
+3F0E8FF7D2D83F59E28ED31A5A0D551523374DE22E4C7E8FF568B386EE3DC411\
+63F10BF67BB006261C9082F9AF90BF1D9049A6B9FAE71C7F84FBE6E55F02789D\
+E774F230F115026A4B4E96C55B04A95DA3AACBB2CECE8F81764A1F1C99515411\
+087CF7D34AEDED0932C183:FBBE059025B69B89FB14AE2289E7AAAFE60C0FCD:\
+0A40A16E2FE2B38D1DF90546167CF9469C9E3C3681A3442B4B2C2F581DEB385C\
+E99FC6188BB02A841D56E76D301891E24560550FCC2A26B55F4CCB26D837D350\
+A154BCACA8392D98FA67959E9727B78CAD03269F56968FC56B68BD679926D83C\
+C9CB215550645CCDA31C760FF35888943D2D8A1D351E81E5D07B86182E751081EF
+
+10001:\
+07EEFB424B0E3A40E4208EE5AFB280B22317308114DDE0B4B64F730184EC68DA\
+6CE2867A9F48ED7726D5E2614ED04A5410736C8C714EE702474298C6292AF07535:\
+070830DBF947EAC0228DE26314B59B66994CC60E8360E75D3876298F8F8A7D14\
+1DA064E5CA026A973E28F254738CEE669C721B034CB5F8E244DADD7CD1E159D547:\
+8D80D2D08DBD19C154DF3F14673A14BD03735231F24E86BF153D0E69E74CBFF7\
+B1836E664DE83F680124370FC0F96C9B65C07A366B644C4AB3:\
+0C09582266DF086310821BA7E18DF64DFEE6DE09:\
+10FD89768A60A67788ABB5856A787C8561F3EDCF9A83E898F7DC87AB8CCE7942\
+9B43E56906941A886194F137E591FE7C339555361FBBE1F24FEB2D4BCDB80601\
+F3096BC9132DEEA60AE13082F44F9AD41CD628936A4D51176E42FC59CB76DB81\
+5CE5AB4DB99A104AAFEA68F5D330329EBF258D4EDE16064BD1D00393D5E1570EB8
+
+10001:\
+07EEFB424B0E3A40E4208EE5AFB280B22317308114DDE0B4B64F730184EC68DA\
+6CE2867A9F48ED7726D5E2614ED04A5410736C8C714EE702474298C6292AF07535:\
+070830DBF947EAC0228DE26314B59B66994CC60E8360E75D3876298F8F8A7D14\
+1DA064E5CA026A973E28F254738CEE669C721B034CB5F8E244DADD7CD1E159D547:\
+45013CEBAFD960B255476A8E2598B9AA32EFBE6DC1F34F4A498D8CF5A2B4548D\
+08C55D5F95F7BCC9619163056F2D58B52FA032:\
+9D5AD8EB452134B65DC3A98B6A73B5F741609CD6:\
+07EB651D75F1B52BC263B2E198336E99FBEBC4F332049A922A10815607EE2D98\
+9DB3A4495B7DCCD38F58A211FB7E193171A3D891132437EBCA44F318B280509E\
+52B5FA98FCCE8205D9697C8EE4B7FF59D4C59C79038A1970BD2A0D451ECDC5EF\
+11D9979C9D35F8C70A6163717607890D586A7C6DC01C79F86A8F28E85235F8C2F1
+
+10001:\
+08DAD7F11363FAA623D5D6D5E8A319328D82190D7127D2846C439B0AB72619B0\
+A43A95320E4EC34FC3A9CEA876422305BD76C5BA7BE9E2F410C8060645A1D29EDB:\
+0847E732376FC7900F898EA82EB2B0FC418565FDAE62F7D9EC4CE2217B97990D\
+D272DB157F99F63C0DCBB9FBACDBD4C4DADB6DF67756358CA4174825B48F49706D:\
+E2F96EAF0E05E7BA326ECCA0BA7FD2F7C02356F3CEDE9D0FAABF4FCC8E60A973\
+E5595FD9EA08:435C098AA9909EB2377F1248B091B68987FF1838:\
+2707B9AD5115C58C94E932E8EC0A280F56339E44A1B58D4DDCFF2F312E5F34DC\
+FE39E89C6A94DCEE86DBBDAE5B79BA4E0819A9E7BFD9D982E7EE6C86EE68396E\
+8B3A14C9C8F34B178EB741F9D3F121109BF5C8172FADA2E768F9EA1433032C00\
+4A8AA07EB990000A48DC94C8BAC8AABE2B09B1AA46C0A2AA0E12F63FBBA775BA7E
+
+10001:\
+08DAD7F11363FAA623D5D6D5E8A319328D82190D7127D2846C439B0AB72619B0\
+A43A95320E4EC34FC3A9CEA876422305BD76C5BA7BE9E2F410C8060645A1D29EDB:\
+0847E732376FC7900F898EA82EB2B0FC418565FDAE62F7D9EC4CE2217B97990D\
+D272DB157F99F63C0DCBB9FBACDBD4C4DADB6DF67756358CA4174825B48F49706D:\
+04DC251BE72E88E5723485B6383A637E2FEFE07660C519A560B8BC18BDEDB86E\
+AE2364EA53BA9DCA6EB3D2E7D6B806AF42B3E87F291B4A8881D5BF572CC9A85E\
+19C86ACB28F098F9DA0383C566D3C0F58CFD8F395DCF602E5CD40E8C7183F714\
+996E2297EF:C558D7167CBB4508ADA042971E71B1377EEA4269:\
+33341BA3576A130A50E2A5CF8679224388D5693F5ACCC235AC95ADD68E5EB1EE\
+C31666D0CA7A1CDA6F70A1AA762C05752A51950CDB8AF3C5379F18CFE6B5BC55\
+A4648226A15E912EF19AD77ADEEA911D67CFEFD69BA43FA4119135FF642117BA\
+985A7E0100325E9519F1CA6A9216BDA055B5785015291125E90DCD07A2CA9673EE
+
+10001:\
+CFD50283FEEEB97F6F08D73CBC7B3836F82BBCD499479F5E6F76FDFCB8B38C4F\
+71DC9E88BD6A6F76371AFD65D2AF1862B32AFB34A95F71B8B132043FFEBE3A95\
+2BAF7592448148C03F9C69B1D68E4CE5CF32C86BAF46FED301CA1AB403069B32\
+F456B91F71898AB081CD8C4252EF5271915C9794B8F295851DA7510F99CB73EB:\
+CC4E90D2A1B3A065D3B2D1F5A8FCE31B544475664EAB561D2971B99FB7BEF844\
+E8EC1F360B8C2AC8359692971EA6A38F723FCC211F5DBCB177A0FDAC5164A1D4\
+FF7FBB4E829986353CB983659A148CDD420C7D31BA3822EA90A32BE46C030E8C\
+17E1FA0AD37859E06B0AA6FA3B216D9CBE6C0E22339769C0A615913E5DA719CF:\
+883177E5126B9BE2D9A9680327D5370C6F26861F5820C43DA67A3AD609:\
+04E215EE6FF934B9DA70D7730C8734ABFCECDE89:\
+82C2B160093B8AA3C0F7522B19F87354066C77847ABF2A9FCE542D0E84E920C5\
+AFB49FFDFDACE16560EE94A1369601148EBAD7A0E151CF16331791A5727D05F2\
+1E74E7EB811440206935D744765A15E79F015CB66C532C87A6A05961C8BFAD74\
+1A9A6657022894393E7223739796C02A77455D0F555B0EC01DDF259B6207FD0F\
+D57614CEF1A5573BAAFF4EC00069951659B85F24300A25160CA8522DC6E6727E\
+57D019D7E63629B8FE5E89E25CC15BEB3A647577559299280B9B28F79B040900\
+0BE25BBD96408BA3B43CC486184DD1C8E62553FA1AF4040F60663DE7F5E49C04\
+388E257F1CE89C95DAB48A315D9B66B1B7628233876FF2385230D070D07E1666
+
+# These have specially constructed seeds that result in leading
+# bytes of the output being 0 (this was a problem in version prior
+# to 0.8.7)
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+454D5341342074657374206F66206C656164696E67203073:\
+5C7F7F0932FC4FF8555C3875CE3A0F86BF5B744E:\
+049C40560875766E164A89B2D19D91EF2AABAB4AC182657CAD93680319D8CDBE\
+3CABCF3E87BF41C16013AC4E3D2DEBFB8F89E9E057012B8EDFD0310E24E2BBF4\
+3D54B2664DF3AC82D7E8913ABE29D0A022277EB74D2E0C8C5F4C3F46FABB35D9\
+32A4A713A82FC9464581D9B1F43A2AFB9AB8177DEE8C38CC9F15A7E8F3F9B4D3
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+454D5341342074657374206F66206C656164696E67203073:\
+B0E37FD9119056FBC17F9C726B0AE7829350F93D:\
+82E54D1CD28D562D85DD3774636C65313CF26628076FC16A4D25AACCB566FCC8\
+77401BB44DFCB8ADBC6E595D515146D227E9AE6D4D585759F435642DFF2BB1EA\
+3AC72E633C05FB3DC0D8E63395099D5A535DF6EA89341E36D73808D5116299EE\
+C827BB2B6C3141AC0A5698DCDC252B7EDC3A5C24DE75287EEB60F45A37DFBEA3
+
+10001:\
+D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30A\
+F38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D:\
+CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C\
+4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77:\
+454D5341342074657374206F66206C656164696E67203073:\
+E4AE5BB1DD6DF73F8F75E441DA531F0E493AC0A7:\
+8A64E30AEC76B278B08FF3BF61B7FF439DC2B0F6B789459F1386C0FBF24AF863\
+EFC5A58C5E9CB841EA08D2E22E40293B1876BBB976947038AEEAA36B1751FF97\
+13B9F7BD306D9360CC8D78B7A607F9CA7B4C18C308D85330E534337998D97D6F\
+70F828D6AD1C9C7F6916476127993E4E6F7D596BA6C246F0EB7312A02D09BFB3
+
+# These test verification with various seed sizes. Botan cannot actually create
+# such a signature, since seed sizes != size of hash are not allowed. These
+# were created by some RSA PSS test code, with various salt sizes. This is not
+# an exhautive test (obviously), but from this, and a careful reading of
+# emsa4.cpp, it looks like Botan's EMSA4 will accept any valid EMSA4 message
+# representative.
+
+# Format for verification: e:n:message:signature
+[RSAVA/EMSA4(SHA-1)]
+# No salt
+10001:\
+AABBFB1E4E6F15D4D59E50C25998870956ED9E822D3DD899CAB0FA597B4D1C0E\
+61997501FD1C6E9D756BDCBE9BF49C7FA32926F3FDB387D83296BE35EF360872\
+350AE98C934D760BE7A933CFE85DFB99621D32105AC89496C9F001FE9CEAB097\
+C8DD55D6FD3D913496106BB04F265ED12F8ACD5F4B3FD7129809CA8D80E2E1D3:\
+B841D0374D3C86E67B67BDF00B:\
+1060A74E3EF067A9B17754500B16B8C9F6B3B453FB290C71FCAE779DD37A6B9A\
+24A45D1560DF5E4BC31143E6197AB15684236D8FE578E022495897F70451FD90\
+2BFA5703947EDFF0B63BF1140C63AE1C8D369A87B192E8BF6A3D486E909C3979\
+703806010367CA0E0026F8920EA766B7E3759E23954D0EC2F746E6046FC14758
+
+# No salt
+10001:\
+AABBFB1E4E6F15D4D59E50C25998870956ED9E822D3DD899CAB0FA597B4D1C0E\
+61997501FD1C6E9D756BDCBE9BF49C7FA32926F3FDB387D83296BE35EF360872\
+350AE98C934D760BE7A933CFE85DFB99621D32105AC89496C9F001FE9CEAB097\
+C8DD55D6FD3D913496106BB04F265ED12F8ACD5F4B3FD7129809CA8D80E2E1D3:\
+0F1D14F9:\
+7D4F2EE63FF4B46A09EBB8F9E2F58B4634234B890F7270FDF3454CD2EEAF1BAC\
+AC3516BB5D0F678365E5226034032D6AD49069ED9C7B8BE471BFC6D9BBE3327C\
+BA545675212A5552948524E52567FCE84D9D211191AAB864153C08DFC7576703\
+C21FB9315578A0F1C167FF4D2B810578DC98FBC1235A4CD62ED89BD092C31C00
+
+# 1 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+AEAD5A03023E17D894226CB2C7C77D5D4341E8BF7F1453140D58B427B40B0B18A9:\
+27ABB6E27D9DBA0F9E5DB3607BF04E20112150A779EAF67D4AA76D50A6060F70\
+03BB33BE5A580789E567C3768AF938BDBADE712F7344B72655118636095EA8D6\
+97888B9382BF3030D56A685079980A992A9BED3AF0DC81AE4316AF31681A3BDD\
+78CC4E83FD3C227A9984C261ADF36D201AA417243A28BA47488BD81CB1DA63A4
+
+# 2 byte salt
+10001:\
+AABBFB1E4E6F15D4D59E50C25998870956ED9E822D3DD899CAB0FA597B4D1C0E\
+61997501FD1C6E9D756BDCBE9BF49C7FA32926F3FDB387D83296BE35EF360872\
+350AE98C934D760BE7A933CFE85DFB99621D32105AC89496C9F001FE9CEAB097\
+C8DD55D6FD3D913496106BB04F265ED12F8ACD5F4B3FD7129809CA8D80E2E1D3:\
+6A4BAEE539612920ECB3075EF6C31BD7EEA01F43:\
+36F7211C290577ED0CF54007551BA65943C388BF2AE58F12E8BF7B6E7339348F\
+2534E7515232D0AD72AD8F6EA173FA3D21DE13D392DE10C457DDA7C569AAAE17\
+0C8806A3ACA457461EFBAA7EC870947ABE2D5A91821B9254EA34A74E95E7648E\
+D98A7ACD2300D4FC88C8B968E0AE68DF9BFF849E53AF03A2E12965C1453AAFC4
+
+# 3 byte salt
+10001:\
+CB6484FE402A7E96E3E43AC26CBF3FED47FBDF6921D40072FC27FA110CFF8D94\
+EDAC5E119D0801CEC89875BBB6FBD838BD0FB7F7F7FA62FAEA798CC6975F43ED\
+CADA7947BABA41DBDEB321E273C870973A9E741791380886B4B131165EDDFCF4\
+F162E17AD36E8D7A763502920527DFA9CDFF0D1046914195D2924D4075DEA235:\
+0F50:\
+707E1B680D4D7E2CD102ED7AF2B63AE63CAD9266476418F330FB739FD052A777\
+4A0182624E81C3AD14C12BA5BA1D99315217D84EA1FAABF4A90E7CFF19875351\
+46D4944AE27E2C84F313E5E5A22C5B86A88333DBBC4D17425F180C6B0F4BFD3E\
+9F03DE21B422EC125DA6FF2835A93CEBED8C1283568E04BB634CAC410D144B91
+
+# 4 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+5C3DB99915C8F7EEACB045ECBB7C35C06D4ED5A96AA9025A49093B70D7C2EDD4\
+85930D18DEB57C0282563F2B07FBA63245FDC773CF851985475DFB4F6FA335BE\
+1B4C2C28A294E84E50172AA585B382BE1E1038FBD02F2BD37691D85A18346AD0\
+4CC81948698FF248CFAF33E222EA8B5FCAEC0E5AA8F753521EC47BCB756E05CF\
+95E4365E06A69BB6C99A34A62939B478AC1209FFACC49BA4027749801D4A9F58\
+3395B34340:\
+9705B191BE8BD52D3E6CA1743DACDA5EDC1C7665B6EBC769A5983BB74D2F52C7\
+9F94954DC8CAB9A44FB3B387A0FF2843311CDA640DC39BA975518B511DF87064\
+B17709804D707DA08A315F14D24CF6385310A62D7F6C47689B66C4A12F449FC9\
+5796F1821EA6838DE2941D0725B55EC860CB553B36878C2BA3994DCD0A8992FF
+
+# 5 byte salt
+10001:\
+CB6484FE402A7E96E3E43AC26CBF3FED47FBDF6921D40072FC27FA110CFF8D94\
+EDAC5E119D0801CEC89875BBB6FBD838BD0FB7F7F7FA62FAEA798CC6975F43ED\
+CADA7947BABA41DBDEB321E273C870973A9E741791380886B4B131165EDDFCF4\
+F162E17AD36E8D7A763502920527DFA9CDFF0D1046914195D2924D4075DEA235:\
+F1FE75913B7A152626C287B1287B6ED4A04EB546950C0414B2D7AAF82DF8F255\
+E08E20A2CACD2399C4304FD9F77B9CF8B2A244C15ABC25DCFE1B144F2B125AF7\
+91B05877E11BEAF3ECC75FC9:\
+87337D2D71F36C4452216459D55586634D755C84D9D8F80D058E029A1CB61A6D\
+4819E3993B623AF90FF915AC585AE6088DF7565A2A205D6282252EA0863A7F12\
+F07A06189F2E2C4EC6B27EBDF3955ADC7C85B803C612D44B9EA5D5FC0B7F15D8\
+AC704D83DEC3D8F84808C2AA5F984FD06D1456B4EF875C33A7346051514DCECC
+
+# 6 byte salt
+10001:\
+CB6484FE402A7E96E3E43AC26CBF3FED47FBDF6921D40072FC27FA110CFF8D94\
+EDAC5E119D0801CEC89875BBB6FBD838BD0FB7F7F7FA62FAEA798CC6975F43ED\
+CADA7947BABA41DBDEB321E273C870973A9E741791380886B4B131165EDDFCF4\
+F162E17AD36E8D7A763502920527DFA9CDFF0D1046914195D2924D4075DEA235:\
+04F7B2C9BEEE7F00FD42C651A3492E6F61816AB3B0903477CFB49B2DDE8AB64D\
+898019C6C937FE653A92C1BD992A3304F357:\
+14949A71A7AF9EC4364DDF90E5A7C4283F8FEF7DD3A544FFA4B1BCEC5FEA6C21\
+4FE7C9105393E72D308CA0994F6F900479219439B8FDC850E15404C024AB757B\
+F7DDF35B0CEC668AEAAAB5039EC81F739C160DD57B26ACDECE905F608AB0396F\
+9DE8F99A53F765D37FB625C8E90C68B4E5B32AEF48C0FDA39B7314FCE942A9E9
+
+# 7 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+71D2C0843ACA68C291953E66:\
+4C22BC81446B062A561D9A922E959036E7763B0803DD84168C48AC51DBE79A12\
+9D017E22BF9DA19996C09BE7369C4F0808ACC2E708DFF48AA2AD41EF78F5F97B\
+914FFE079BE9F9D30E67049BA28BEE714FE622A18A3524FC7E58ED7C451714F1\
+4718F4475814B6D9A6590845D9CF6FEA2DCD313CFD580B47D5BEF6960CB0E463
+
+# 9 byte salt
+10001:\
+A8802DFF63A68E53D5B4AEFDF9BFBDDC2F3FF809D248CBC4AA250AE710830671\
+4ECD4BA4C465298C7E7EFAAD9ED969BDD23D851D31BAD61FA942B24A60D34469\
+F2774133D488E82E66B01FE4C7C8CDF95CB194D721FBE3B98FFC61D31F07D8CE\
+E32318EFF73E374755CBCB3785D93772A414DA3C25B240B16F40C83723448861:\
+9D5116B54CBA7970742B66BE6924D122A1D7E570F037DA06B29A2B34175C8F94\
+28D1E8E908EF492892AFD6B08019EED0123F32B74D04324DDB98171ADE66347C\
+1FFB56BD1B05E1CECE2ADD838BD95CDEB74E36A51B69F2602322593462182437\
+AF357BB63EF748F45CDDB66BE5357E9701C8B21C6613857432CB99C91CDFCB72\
+54D087B361CCF05E77AF961F023E83416D9FF539A572A5C89117FE1506AF6633\
+5321A0CB7BF096DA0590D2E79FA60DD7A38B9DF2D352673F5A31A873111E3C8D:\
+A73BC3BD89ADF92FF2B8EE3B5430849301C322074696BD58FCA3D0C113BC9CD7\
+9D6D822FCE31ABF1C276C1272D045E5FD92BAE9FBC07EE54742D3342A2B03E85\
+47B1DC94E86C5D08A13708780952498CE3EF3B07710E5777683C9630821248A9\
+D38BEC8AB7C77DF1CA6E695F0289443C13A8A4834D97CE6DCBB6782A70F866B1
+
+# 10 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+75352B85B47E73B18E8CD9608354ACCA4DF8E2B73313C681A8119D6578CAF8F9\
+A52EB4710B97D334D2CD49C365BC0E0BB89D63CEBE3EC62055E7948C9DF696B4\
+06EAB60881B0371F5AE092D0A43ED9AD307D026B2CB6477AF5ACC32919D470C3\
+9C9BAA71B0FA78F8687BF762C399407BB39C59727AF3B61DF3EA486E473D4CC8\
+D67805E8810F:\
+7F51B49FA57C4EC7AC72A90C9EBB51F6E21E3B6EE67E6DE32119AC9FCF97FB19\
+09F74491CDE182ECBED994B66EEC44AC817A8F620444BB6520A3A223BE4AFA78\
+B50F11C057FA4F4835D55283157F5C8AE60A2A46D0CB9D4BE3411FD3505F0FAC\
+5202ED1C0629575B59001488B30E9F12E738F2B388C7EF8A82684CBA43115010
+
+# 11 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+DA40B3B401DEED4DBCC3848CC729C8B5FD169A140914C40FEB752E2D3F2F7EFA\
+A97CE26BABE4099BDBBAA522BB09DB37A1D06CB53A3BF7D621:\
+328E325D4F95D0013019B97F5936EBB347F1E5B01A559560518C1C47DC044343\
+92BD2168DA08668E4EEA9A06A5CED7C9076BF7CAC667503FE6B7903953958BAB\
+B31EE9B29E356274F7136F35F5224A1BF50F3663D002B6220C3EA8572C1368D1\
+1D3C6DD6E1F3D700811257EF8B46246C2A6A975C08DEA782003F5CD45703FD22
+
+# 16 byte salt
+10001:\
+AABBFB1E4E6F15D4D59E50C25998870956ED9E822D3DD899CAB0FA597B4D1C0E\
+61997501FD1C6E9D756BDCBE9BF49C7FA32926F3FDB387D83296BE35EF360872\
+350AE98C934D760BE7A933CFE85DFB99621D32105AC89496C9F001FE9CEAB097\
+C8DD55D6FD3D913496106BB04F265ED12F8ACD5F4B3FD7129809CA8D80E2E1D3:\
+1C79CF64CCAA6C913ABAA5A555558BC251:\
+0C9485139F787BB6EFBF23783CEC74A53DFF16937FA6E76BF120D15ACF87D848\
+0B7EACED7B44ACD2A87C92A3F5AB185B81664AE248C7557C2766656C05A5D206\
+DD110E0E97F4F63364BB396F8431ECA2352FF84B4DB5F54FFAB155768624489F\
+D6E7C40282D1F9D85674D21E01571FD24423461F3D04D9595C43BFEB8EC586E3
+
+# 19 byte salt
+10001:\
+A7DB819EAAF3E6876B927ED6EEA94B97E20D06753C7555A7440631216FF4E943\
+720DE7BE6364B8DE17E663705549051F04141D8612214BC269CC09FBDF1F561E\
+474A2ECA28ADDE3530CA339015F23CEE63750C508A1416FE5D1AEF5AA09BBA7F\
+36CFC02874B15DCA913E35B52B281D32B1CEBD22EAF3C629123988FE78FD0561:\
+3096922A62DABF6B98A4480D2F86629D1992FFE1545869DCE5E69F810EB793C5\
+ABFFAEE2EEB846644C8BE8E31942BA16FE51B7988F355999CFFBA28CFB9DDB1B\
+5F4919790B7E63E37F00289C6CD42F56F7520A2DDA73AEA4BCB2D10053AB9720\
+B201D52AAE450BF22AF2C4E3AC:\
+43F583905ED6D2D53045C60E472FC1FED12EBD88C190EE810F9576E262F3881F\
+BF006211DD5943A48BAC7FF21C4317BC28E4968C98FF6E0F94C055FB104555C1\
+E7B533F9DDC49D200CAA8C2F62C5EDC6A9E9E76290DDEBF38BAEC88EEF8B32B3\
+DE804FF19627C04B13261CE2EF2101619CA1D6BDF3C5C7DEDCF21E18726081CE
+
+
+# Format: KEY:message:signature
+# These tests are copies of a couple above. The only reason they exist
+# is to test parsing of RSA public keys in X.509 format.
+[RSAVA_X509/EMSA4(SHA-1)]
+-----BEGIN PUBLIC KEY-----\
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqu/seTm8V1NWeUMJZmIcJVu2e\
+gi092JnKsPpZe00cDmGZdQH9HG6ddWvcvpv0nH+jKSbz/bOH2DKWvjXvNghyNQrp\
+jJNNdgvnqTPP6F37mWIdMhBayJSWyfAB/pzqsJfI3VXW/T2RNJYQa7BPJl7RL4rN\
+X0s/1xKYCcqNgOLh0wIDAQAB\
+-----END PUBLIC KEY-----:\
+B841D0374D3C86E67B67BDF00B:\
+1060A74E3EF067A9B17754500B16B8C9F6B3B453FB290C71FCAE779DD37A6B9A\
+24A45D1560DF5E4BC31143E6197AB15684236D8FE578E022495897F70451FD90\
+2BFA5703947EDFF0B63BF1140C63AE1C8D369A87B192E8BF6A3D486E909C3979\
+703806010367CA0E0026F8920EA766B7E3759E23954D0EC2F746E6046FC14758
+
+-----BEGIN PUBLIC KEY-----\
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn24GeqvPmh2uSftbuqUuX4g0G\
+dTx1VadEBjEhb/TpQ3IN575jZLjeF+ZjcFVJBR8EFB2GEiFLwmnMCfvfH1YeR0ou\
+yiit3jUwyjOQFfI87mN1DFCKFBb+XRrvWqCbun82z8AodLFdypE+NbUrKB0ysc69\
+IurzxikSOYj+eP0FYQIDAQAB\
+-----END PUBLIC KEY-----:\
+5C3DB99915C8F7EEACB045ECBB7C35C06D4ED5A96AA9025A49093B70D7C2EDD4\
+85930D18DEB57C0282563F2B07FBA63245FDC773CF851985475DFB4F6FA335BE\
+1B4C2C28A294E84E50172AA585B382BE1E1038FBD02F2BD37691D85A18346AD0\
+4CC81948698FF248CFAF33E222EA8B5FCAEC0E5AA8F753521EC47BCB756E05CF\
+95E4365E06A69BB6C99A34A62939B478AC1209FFACC49BA4027749801D4A9F58\
+3395B34340:\
+9705B191BE8BD52D3E6CA1743DACDA5EDC1C7665B6EBC769A5983BB74D2F52C7\
+9F94954DC8CAB9A44FB3B387A0FF2843311CDA640DC39BA975518B511DF87064\
+B17709804D707DA08A315F14D24CF6385310A62D7F6C47689B66C4A12F449FC9\
+5796F1821EA6838DE2941D0725B55EC860CB553B36878C2BA3994DCD0A8992FF
+
+[RSAVA/EMSA4(SHA-224)]
+10001:\
+B8961C3F4D6A9DC27FAE6C30229E1DA910AF796C4EFB2E97DB11E636A7D6ED94672BE33FD7771\
+75CD0D879D805D06F1C9B2A064DCCFB38A63BD768BC092A0AC3740FE390452492A4BB1C2ECD38\
+C771264D0B2FF0496AF5CD6D139287ED3200A9:\
+7072696F6E636F7270:\
+B7530DA7632263B5AA4B0DC9FCBC3BCDF8B44EE2B4BECFD90BDEC108F50EBE325BE6F4EC8900B\
+A1C345F2B6F59FB625C3D99BC6F04D99704144B05C2ACDD61927D3EBD886650E933774DF72EED\
+0A5A3AA2810C17B56F877D989AF3A469950D0B
+
+10001:\
+CA76759F53C1F5F771C00A7C6E09E20754132CEE14C671ACAF687DD4006CCC54F34018C554601\
+18DA1036951EF27EB3211138369D9C3C5EB1C3960A9F6DE7794798E2B33856EB0120CA6771CAA\
+824F1F00FFB4596604700676A6C117C87E12EAEFB6476CD4D83A08C6A6A2EAB3ABC3B71FAF967\
+9EA09735DCC8849ACF80F3705:\
+7072696F6E636F7270:\
+B4816EA318CD92A64FBCF77C4E42E283534B2C500652DF6D88FF24130EB5C84350E9F52E4822B\
+F60D7C4AE4FA11C811A7A0B4DF93C0215BC9B3D04337BC044E1994959D67E0E33121C9CDE1C50\
+699B6C00966160F51C606334E15EBF60FBB8C76EFBBBA51460C75D30DE0F47863A1020885F5A4\
+DF8AAA397C03AA409833380B1
+
+10001:\
+EA70F789F0117223878E296C191838EC52A63918C0B47E02430331182938F8590CB3295FEE645\
+9A90C9923A888F0FCCEF8D422D75B60DCA3ADD01D6C738472211CECE779420FD4BD381C04C572\
+F9AFF554CABB6532C6361F78EE0AAB4FF5A1FA33C5FE7EF3AFE1C5F6CFEA0BA25B0CC4C6FC396\
+BF30535D69928282B6E20371B:\
+7072696F6E636F7270:\
+4FAF0FB7EEBB26B9BA778D092B42CEECBBA36B4DBBBE35C6B383439F23F2062642CB3D091BA77\
+C4E1C46280E85C8C40A24FCEF5CDC9F4E383A54B19BB3BCD8B5DC28070CD5FFCA1525F6A655CE\
+672EF96438F375E6483ACEB338180B24FAD3E4F67B58E246D0BCE09DFEDF5249F30517DA52FDE\
+9340EE69B1B1316B81C2E2E1E
+
+10001:\
+FA294359ECC80FF6077B2BC558710A384A24A72CBF61FBDFF3820BA2DE987906A93FD7591BB0D\
+CCB7FA287343876FEB5CF5ABAE579D01A5626C7924FDA429BEADB924CA9E49F99074A850F7084\
+F7E8747E9A7531BAF576524994AEEDA1CFF1D561B3D16793310280626A2FD0A942324FD04E6B9\
+B80AE0A9CBFC3D8E0D5CA12CE5D04C3C49ABF871D62366A8657342690EA73CE1EC68F65A1835D\
+48B4008346E8EECBCC4FA48C7D62E8844C149AAA4E75717DDE3F38F72FE37CE1269B3C2BF7A7:\
+7072696F6E636F7270:\
+EB6106EBBC6F7F29B503E7AED4CF9FD01F75F2C11433DE73188AC19A9A41D59F995107AD9F8B6\
+57B0718226245A4C149E352BF5D129F53971E30A4DE702876528EA67A8EBFD096396B7229BA9D\
+6DA710DB37613F5FB1F3993B391741CE8E11EE0C324E3F33CFBEB78DB0F270B0C0CC7D3497F85\
+94EC262D88EF9E03EBFD9E26ECE0921006C521A4B1B41D75BD79B5534B183893A18FE183DCCD1\
+506B22E0E7FEF53E56B74870B62EDD262AA45F3FA9CBFC18045A549D5E202D2D20E08322799D
+
+[RSAVA/EMSA4(SHA-256)]
+10001:\
+9E244363D137F1E002C5071CD7E7B7F59823770FADDF1D3D8AF934438C9B6A97258BD5FC0390F29\
+971DDEB394E7D2A6E1C8422368D6A5EB7E1F51E6472546EED2CAF1AD242AFD03C1A4FDD8894B305\
+EE31EEA8F8A36C099A00478EC29D11E17F:\
+7072696F6E636F7270:\
+73F68238B7F19889120893C903258DBE620171982CAD9D155892CDEFECB3C153224D8A94BFD13B4\
+691A4D51175756186AE4F689B6A1A1432EA255C0E8DD844E9C055397090C110C632EB6E24BA5ACA\
+380239D399BF010E1451293DB948D4274C
+
+10001:\
+C34649A69B6C468C51A93B54B7FC54BA7287C14563867406FC87FD98E0B70B307811FD2A7EC2646\
+4D50B5A0213A04C4567CD22B22F2DB162DD464E617A7445A8ECA9DDF71BE38AA32F44181E20922A\
+7AE9851282478741FF69B24158EED69568B0B27AE54FA043F778DC54DD2B23E3D5E0C00113181CC\
+DAD35E04573018155AF:\
+7072696F6E636F7270:\
+3CFA8F2D410D5BE87DA2B644BD6615CE3588C7E4B261F05C18673F24CB570355A7F5D41BBF62F85\
+9BC0CDD5300CCA3DBF2B2AF13DDF455DD6D919811836B22BD4280EFAD24DF30EA185D7357C89599\
+CF0C08A22F4D03162295379E842215DEBEA0DA0AE985F355AF392DD0F9F8A6A1F2827AF781630C5\
+D2A2B917C5544B3206C
+
+10001:\
+B3705A2FBAEB5B8A311150C3EC5315B29C7FB17F9A0680B0CC0A6E463113D9DB68FBD8CEB8C12FB\
+833639F29C76136B70320D0C9A5C4F191ED419598FD4D876ABFD815C1D4E0AA594C1C5D08EB56D3\
+707263CD1F9A09C12F5E9717177E39986F82EA2F65780D2121C537D9D14BA7BED64B46365A898B4\
+5FC1D5386BA954B613B:\
+7072696F6E636F7270:\
+417D26DAAC12A39FEDA2C17EA2ED932AF9544DA11E6BB84B0E9D4758A57FBD9878457171DE72B88\
+8EF7AF40183EE7FDF81044512232D7199C11CF52A53CDE62022352EA747292FB3187EE51B2A17E9\
+AF8DABA658DB6C4A5E4F07A5CF2E9203295E59B1916F526C1EF8F84F72CBA70065EFF5D4BA0467C\
+B77165BAC3ACE21462D
+
+10001:\
+A323715CEF7F9FB81BDA579ADD3CB75FFF4051DD5D7ED2B0D3A48DE237A003831042C44A7E9FBD5\
+55F791C350B1C8424384D1E005E54ACFD67C8747EDC8DD8DC9A5AA48D0EFE5CC127CA706E1E7670\
+8A0130519572A1FCB35CBEBC8575454EF6A72DC2F2A6394E1FB593FD60AA9BDB84C99523B91F371\
+7E263793301685BD380357134BB56AC499AA80B887A28596C2208BD4CA7910CAFDDDB565A788F02\
+1C295F3C3DDB064271D917D986D72BAE38C1BC8A6644320F61C84E71FC5BA378D681:\
+7072696F6E636F7270:\
+7BBB18C1CA207CE639E323DF26B14475CD407995EC612F6D53ECEE977D4400E4BFC198ADF8B40BF\
+E27363241A1F9541F01677AAD98F87E93998935146A8F77E7FFBD3DE59A2E22E5766409733F06EA\
+2993620A27122B71C4D9DE755E70C703B4EC6AF5F314E0F720B656FDA93E2B3EE9A1688D711174E\
+0D72D0D486DE36DCE1F9DA031EA46FBD6156B1E7A65A25B42696C9ACCD453D8E467313DA76F70DB\
+225D3C44E133E65E8BCC177D065F53BB81AF13076AB0695AD2205040CD9B4DF851FD
+
+[RSAVA/EMSA4(RIPEMD-160)]
+10001:\
+BB3066B7BA3873399F0B957B6993E7E4AE7D97E1D3579F2AD45F48ABDA8730C74B09A4DBFB5F6A9\
+0769BA261D5FE0F7290A06F91FB8C9B45AEA37EF61CC7F5C407960F89C0699890C2C49C10E18BB6\
+42FA27FB8B38E9A1E406114027F914E587:\
+7072696F6E636F7270:\
+B24136372B7716310F83846719F61CB4F86B11855BE752E85AE6DE9CAAD99746693B255666DFEB8\
+C4A709C93A9DD1B2A08A9BE75831DA000AFA7D6230212C40F0DA59AB8B6291D1CC1DBA24D86D92F\
+C318F764E905E0BE2CCE73E074498A7DC6
+
+10001:\
+86BC0A053525DD69C5D827DD664A07063C6099565D3AF545DEC168BA5FDDA7E355D426266D7D6CC\
+FE204E53390D2287347593201D5798F937A9A06B853FDCD3516526EC3F697B3F519611B9D124286\
+54A5C7A6EC1872067B308DB2EC172963160FB17DEC45D27792A39CB3F398D48282B6536A0B1E6A9\
+911005DDBE73EA8787D:\
+7072696F6E636F7270:\
+0795B1835ED3412E4EF2DA7DF692D04E959D5204331C6CA3D978F48F319A79B3A1A51CB584E56B0\
+572853527B1C2F99CA3390C91E006466AAD7628A0FA48887397A865F864D6921575CCF186D3FA56\
+9EAF9137EB626A9FB920466FC042AE9B6FB6B8D7EEB4F8193E7DC175B9093FA3E49FBE4D6D472F3\
+F38289A755933234C46
+
+10001:\
+ED1782D5C4807EA628D68A733D736B5438B1A9D9340537576FCC55BDF0121AA423659B67576DA2A\
+3FB8B06009CBB1A009B5010C7A76FA8F1A50BEA540E9A6AFC0E48A95A2FE849F41075E94494E11E\
+459B8AD5D0311900C6DD0FD9215B0A5B33DB0B49B9BE67597D57F636AA3B3E4677AEC213E419EB2\
+777D752A1613334AB15:\
+7072696F6E636F7270:\
+375AC6A2B3CC508CDE09109C1FA52980098EA989C2021CC19D74097A7D67B07F599F3FA0C65B02B\
+DA6FCCBA9219D33A1F07219B616C30B1D455311726FE2470F63B86A02DE283391272D85B77C6D83\
+4ACE4246B692E1B4B512D5E72F3192142E765E38553CD3FCA435D129C7543F777997D8715A2CBE2\
+B15A5659CDC67DA72F5
+
+10001:\
+B4B8E2EC2E25925A087F2731D8FBE4D180681A229D190B58F829099E3781F1A850D564999EBD14B\
+0FC4D8BAC48642FD38B7DC9E2DE709FE8C14FDB2477B72BBC58EC0F5FA6A810E44B2C84E207CBDB\
+1BC7A0358AD6F60CF9061EFCD40A3CF665FC976BF167F8A610D747A1075B7C3753131E78967106A\
+D2F20D5BB1E28D6A0D3D722B2F044670B20530FD1F7983513D7F3527A662571A3AE98E1DAFF9403\
+04B2BA6481B766DB0812AC4BBCD1B87E2A29A74565A5C82A2821F6F1E1B5C764690B:\
+7072696F6E636F7270:\
+32631E346368C620BAF6FA5475F04B56FB60BA5CA67D1E3E22805ED5910ECEE71777FE198279831\
+51E88AA1F9E57E96FDC536CE2F927AA3B34A94441E72FB498A649864488D976A0A4AB7B6490451A\
+4F4712A3AF3587579A791CF8CB18EA4AD388B5C34F6BF54E9CB0F4AC5EA21EA2AA42A2266EA755D\
+5EFFC02FD41C583E1CBDA53C1821BB79FB392D68A4524B0F65EBB64FF6656C52BF54D5774DF2D91\
+6C9B793E206E0D5351D7B4D18DE3CA4CCFA8F7A3ABFB36048C9297F7512B3FDA70F7
+
+# RW Format: exponent:p:q:message:nonce:output
+[RW/EMSA2(SHA-1)]
+2:\
+F21624A28732743BBE9B1A2B320CA31EF4A127456547ACDF5C523995E25A990B:\
+BC6EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F23F635FF988E284E31CF:\
+5075752E::\
+44CB3C6CD992A656AC2D8C92E044FCCC60FAA1B47FE153E7BA4B647136DA4A42\
+88BD50FB0935E3B9180AF477F8B88E1EA1106569CCAB8D354E0A7E3AC92D70B3
+
+2:\
+F2E5CDF6CA7387C132242CE031CEC8FE2CEAFA8530EC9795F16605B1CBD97BCB:\
+DA330E4440FE5CD00A37A738DDFBDD5623A31FAE273AD98E41DA0D3DB937CEBF:\
+4C6F7665207375636B732E20556E7265717569746564206C6F7665207375636B\
+73206D6F72652E::\
+5AB035B8E6415D691951DBCEACC6A61987599000A590A414363BF52FB95C5BAB\
+C12812152C5BCBC6A443C68B971EE0AA5E864C9FF9ABE0A85BB86FA544239958
+
+2:\
+13CE5CDF6CA7387C132242CE031CEC8FE2CEAFA8530EC9795F16605B1CBD978A3:\
+14FE360AA550965F93CE76E4B01F55FBFDD7A049B2761817505CB6959A73A4C07:\
+4C6F7665207375636B732E20556E7265717569746564206C6F7665207375636B7\
+3206D6F72652E::\
+0085AC363AEA57F36E348936599A77167BAF17194D250787F347C710019558A9F\
+773DDC25A2216DA694D38E03CAA4F7423BDF03DB0E75161221906222FC9E0F23D
+
+2:\
+1947A060ECFEFA3F8DDED8AE580D45B02D82DE108496AFC322FFD14EA02B7BFE3:\
+1E1384A66A21500DEE4DC2B36F43EF398B1C50BDEE7600CD4340B663471F0F16F:\
+4A65737369652048616E68616D20697320612064616D6E2063757465206769726C::\
+00BE5B2A5EE3CB613ABE4548C856F6C8F8B4B9EAD3795675E59E4DDC4A015D019\
+2F29B6352CDD913C289961BE57F84005F0BBD3AE7E2BBE73DABC50B2201923CC0
+
+2:\
+1AA83F51426F2BDA398221C48E8D322EF66D59098D0418E0C2B06DE6EA2F97D33:\
+1E4C7924C9E6D7ABDB372B112601D4C091FAE6C8FEB518595DF436FE9B354E26F:\
+492077616E742061206472696E6B2E204E6F772E::\
+010E8838216B05B4C2739B65AB2A7ABC114A046E3CD37CF1E97815ECA53750B1B\
+F486A9BA684B9FE2D983BBA5F9D97565F0DCF6A5176C169EC67B6BB6C9616CEA6
+
+2:\
+22C9D42C6803B9AC87F641E9465D300DE8898694427D138761C4A5B121B0632DB:\
+25DA5C05701C99EDDF0FBAA61DCDBA404C05D860DD539E06B0AECA7E56354DEA7:\
+54657374696E6720766172696F7573206B657973697A657320666F72205257207\
+369676E6174757265733A2035313220746F203531392C20616E642031303234::\
+0191F1BA45BC571445612D8C1A7818B52DFF78566E6CCFF7AB55B2F35FA21210C\
+951F171E27A2921032718AE01BB4F209164BA0B21A5842D1925B35D09C7538050
+
+2:\
+388F732F05B06F5BA10816242E8F75A000E235C97174F57931E8D845442147F8B:\
+2F3758EBE44182841FB1743D3BA6AEEC0AEC5758660E1DB37C818199B90A1A307:\
+54657374696E6720766172696F7573206B657973697A657320666F72205257207\
+369676E6174757265733A2035313220746F203531392C20616E642031303234::\
+046C31E4EA320DF130FE1F361184DDC03713BBAC169E08266B91655B42A01F39E\
+1E3FF781B04B2F44B2504F37ACC9688C1ADD7EB94A998779EFCDFBEB9FAFFC82D
+
+2:\
+4AE4F716610D77E35A6FA2FEAAAC3E92706B996414C012EF72BCBE86E3F1A97BB:\
+5145D9E08DA9021E87080C437BE1835B06E5C9ECCDA8E7CF7E30F682D0CB1A9F7:\
+54657374696E6720766172696F7573206B657973697A657320666F72205257207\
+369676E6174757265733A2035313220746F203531392C20616E642031303234::\
+01BF0E20BF646E5E427B8D28CBAF696D7AA6B6DE878BB91C295D5559B1FA9A94F\
+114FF61C11C0BC97066C2FC919815B0FD150CE70F63D696CEA4D5D1D7BDEDC035
+
+2:\
+6AA3DB8710567A30D7E9E61956962D4E4D50BC0510C2238D9136A93CC5DC3A73B:\
+6CAC9FF49F1035D179668B399927A610608788A8C884B76A94A6DDBCA94A52327:\
+57414E5445443A2043757465204A6170616E657365206769726C667269656E64::\
+1695A91578EBC67ED86C20EC4886B2E3895E11A7647D22FFB41091E1C7A3CA0DC\
+E091A1FCBACB859C4A5C8B3B841C0F0F7039BEFEA790A423114F35F9D809DBCD2
+
+2:\
+9EADA4F7D1BEC405BC2BFB4F836E19A488E079030F8C09DE76810B9E63FB41873:\
+AD5DEBCF83372200B106812A6A7CF3A702C35BAF4FC095617794314EBCAC4DE47:\
+476F6C642073747564733F213F204576656E20746865204D544120756E6465727\
+374616E647320746865206E65656420666F722074686520424C494E472D424C494E4721::\
+203FCE80570CA0DA3C2D50634A33BAACEA6D397618F36620EE10DE4E6A51018C0\
+BADE98DF220E47DBA140AEAE910A28F3177D4349740EC05A5EB7BA280D7BF8F34
+
+2:\
+E39815FB87BACBCCF779BC66EA0AE9784FC95E0DA094E9BEDE99FB45F73E2078\
+3038AE0488539A2CE982B4F180FC71858F2E5759E61E2C5A5FAFA435BA3A62A3:\
+CDC7D5FE3805572EA3FF554C086C7DD4020A3CE48DF5A09A5CEB75E6AABCD338\
+F800F362448E87CE7E1A55331ADF2BBF3A22B3E6134035FDA52D9578FD3F72F7:\
+57687920696E20746865206E616D65206F6620616C6C20746861742069732067\
+6F6F6420616E6420686F6C792061726520796F752072656164696E6720746869\
+733F213F21::\
+05BDC911B3F19F2201EDF6CCC792A68BCEC40506F00112A6DCAEEAA2D7A62192\
+931D8968F7312EBFE7F7646CED6A8948E58327862527EFD960F15CD8EC74D1DF\
+1FDC37F369A4A844D15DB7ACC6DB5ADA884B119148929439D5305B6916D0A081\
+1D395E6A28042F83D1154FF45DA6A79A3801858031A2C91EA699C02DD6055CC2
+
+2:\
+EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\
+5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\
+F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\
+8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\
+2CA039854B55688740E3::\
+1AF029CBEC9C692CE5096E73E4E9A52EC9A28D207A5511CCEC7681E5E3D867A4\
+AE2E22DE4909D89196A272F1B50DE6FA3248BCA334D46E0D57171A790B6F4697\
+E7BA7047DB79DECD47BD21995243DEBBF25915DDBC93C45875C14DE953792257\
+C5C6825C905AFF40109C8CC7E793123D47AC1B5B6304A436CFA9BEEC8E0054E7
+
+2:\
+EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\
+5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\
+F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\
+8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\
+2119A954F1AC0F3DCDB2::\
+60C3CCF4F086B15B7F850B445F384333F7AE5A4B5EDE2820C7233239E1B86D6E\
+4B4FCA4F50B087CE1DF17DA5D62672A17F2CF87A2875BBD9B138CAF6863821D6\
+A4D553E9EB64C9254A8F9A6B960E57E39069D65E3F561AA1FA91643D42FEEFB9\
+270D34AB0861DEA1E234EA587F580503D46A1989D413DAC2FFE0FC4CA663CE68
+
+2:\
+EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD36CC25330548B347AC158A34\
+5631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E743E9281B:\
+F5BB4289C389D9019C36F96C6B81FFFBF20BE0620C6343E2B800AEFB1B55A330\
+8CC1402DA7A2A558579A2A5146B30CB08E3F20B501081248F2F1DE36CDFCE9DF:\
+7A4C634DE6F16315BD5F::\
+308A5D65224201BED626CC83FB901EC84874EE03B2E7AB4E752EDBDE024C754E\
+3CC9841CA062100A8843DE9183354B4E0596E8C68F1605828287884F0F9BA696\
+8FC7A9F0CA09418A8485B90465E5D3F96CE4995A5FC7A6E5ABD9CC06BB8A2C3C\
+8109F72EAE67FB4C108852C881CA645B3C5586F27F12FF3028ADE56E32AD9434
+
+02:\
+0BC31C063F43B3ADE2CD633D554913339071D6EBED5FD665FC5DD7D47B80721A\
+976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\
+0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\
+0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\
+EF0F1D56F4E5D587C212::\
+3E544FEBB6623F5D392003B729FE2BFC20E2CB3ECAC22734DFCA55150254E616\
+A41C5E54CE3B50FBC2FE2363EE9AF9B15C70615497B0A458F8AB6D850992EEEB\
+56D65F87EA1BD6E2B4B7E40A0F5E1635C7DDB17110C61039CF712D3524C9C2C1\
+F35D9163BE5C70276F46634514BE16EC09602782E88FE74EAEB2F50CBB0E3B5C4A
+
+02:\
+0BC31C063F43B3ADE2CD633D554913339071D6EBED5FD665FC5DD7D47B80721A\
+976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\
+0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\
+0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\
+EC5CC4228C3C70EE8F35::\
+228BAA85062F10DCC9D99A23D340BC4B9E463D8AB86A6781A6D2143564303E2D\
+C78772BF68449BE1E2711A68D5A15CF04A23573FB3870454308F583BBB5F2467\
+069EF1395431E70F91BD56D846DC8DB2E88AB3D26A9770660B87A76D6C3575DE\
+512BAFA8A0B901AD15B7D8E8BE2F176A182D16A9609F19A4298416245873175805
+
+02:\
+0BC31C063F43B3ADE2CD633D554913339071D6EBED5FD665FC5DD7D47B80721A\
+976C3B14FBD253F0F988C354725289F2897D7FB62C5C74AF7D597A1E22AAFBA1D3:\
+0F816BF0ADD559AFDA38B008E4087F6A38B575C56FFF453056EAAAB3381C9552\
+0969546F954D458D48E44850938B1DB471CF4B40AFC47E067FB5BCE67BA98BE8D7:\
+FEF5EE07C74118DA30B9::\
+2637E16E2599B6EC2F4728C73D3B29F483C2B881F1E1969C426027605EF080E9\
+B17D258D5E1EBC6472A2501E04CF19C144537FCB38A1DA00D948EBD39FA11322\
+D9230B62E2C12AEDB366BD85A2089588A8D52E941FD986D89828A342B83438A9\
+60B6FD87E9AD025AD75A692AA9DFEA873A9467B42D84879E85C5D11EFAB347FBED
+
+02:\
+FA880A456F9C205A26E02C3357536531DEC150BE0EF8747F69EA30D987FF7DD8\
+9E9A1075EBD39F04FA495BD26D8408A8DE69113A9FBB52F20713D1D046A76B47\
+8CF77C46454A7AFDA2EF418F63FAF67C947D898BCA109F3275999E8F2E60E2C0\
+EEC133FF69E71A2D396632670B52D8EA03F7589D8144AB580B1D3E60EFA1280B:\
+BADCC718DD2D761C4893C4831D56ADA30FC5C7C148D473BEDF7615B7E821B92F\
+319676CE278349F1309FB3D264C1A22BDE71B221354C7A4D31117B3EC3C9D480\
+2E0A26BD8EC05D28B6502C65F35C687AF7F8396B963ED029A2C5AE38DD7C5C96\
+2A953C113C0F590957AB19A6E2AFDA6DB84F22C0C31AE243DEBD2920FBE9FBDF:\
+15E7B7B7ED0F176B6799::\
+39FF4B5FA50AE498F3C91A655E6865840D1FC401EE02DBC8460A59DEB8816E66\
+80F712B7BAF8D4DC11A3B54BF906BE698306F0449BB43F3F223B944D930A1A3C\
+718E8A9E2EEDEC5A07AB817C26A80CC2A2EE2846A597EAB8A999D38DB9849016\
+6F2574524038BBDF24B4E4622C843210C6B94987638C6976562EA9727385B152\
+614C18349BD54AD95DE33D5354954B505E5259CCDA47E3CECEF3154F6E5481E5\
+36BAB568146A0BFCB66573714A7BA7ABE0385115720687F33D9C6EF6BB60272F\
+1272CF349990E3A2FBCCE180B730792101089B164AE5A001F5263F7493AF148D\
+6E0953E311AD12E4202D35F96DD30885663B5101F9B05675FCD2FCC4FCC4DDFF
+
+02:\
+FA880A456F9C205A26E02C3357536531DEC150BE0EF8747F69EA30D987FF7DD8\
+9E9A1075EBD39F04FA495BD26D8408A8DE69113A9FBB52F20713D1D046A76B47\
+8CF77C46454A7AFDA2EF418F63FAF67C947D898BCA109F3275999E8F2E60E2C0\
+EEC133FF69E71A2D396632670B52D8EA03F7589D8144AB580B1D3E60EFA1280B:\
+BADCC718DD2D761C4893C4831D56ADA30FC5C7C148D473BEDF7615B7E821B92F\
+319676CE278349F1309FB3D264C1A22BDE71B221354C7A4D31117B3EC3C9D480\
+2E0A26BD8EC05D28B6502C65F35C687AF7F8396B963ED029A2C5AE38DD7C5C96\
+2A953C113C0F590957AB19A6E2AFDA6DB84F22C0C31AE243DEBD2920FBE9FBDF:\
+B36724C92954C38D0288::\
+3C8CD3614555568BBECA99174B7B203D0BC6FABE9E6FFE0C41EB4D9A2C601D23\
+93CA1E01B7D7E99337758AC914C9F151311E5AE6708DAF1D8C825DA471652C6E\
+13A8FE5802D7AE097BFC899A4EC8CA235B5982B9058C53AAD52823ACF692290E\
+B8823C126635AB0BBF101C2B3149AB16183FA2DBB049DDB99C5E83723E4D4693\
+CA3A08588AA868C677D42ABDAA6586EF192391D276C5E5AF0763ACCA6293F062\
+50C51FDC2AD369CD44EB5F654E98761C881DDEC08E795FFB229B20522349B071\
+4059E18B7B23A48875EAB12ED3F0A011D3A985DD7384B0046F39FA6C1A331F3D\
+4C5125100BA58666935C68A7A10849D9C74850BAB82AE15EC950A283F3E7DAD8
+
+# Format: e:n:message:signature
+[RWVA/EMSA2(SHA-1)]
+02:\
+E5EB47BC1F82DB3001FAAEABC5BBE71B7D307B431889AC10255262281EC5F5AF\
+8A790BD7BBEC5EFFFA442CF2C3FD5CA4778763B9D15AEAC0B9B71BDB13DA8272\
+7F4967AC685975F8FF05A763C864D100B7CC1142102AA2DD343EA1A0AB530255\
+195C3A6400ECAB7B27EFF9B01EF6D37381FA6FB5401347F195354396772E8285:\
+2A51DF4AF88613D91A37:\
+6FF18F4471E1A8F850C910A181A9F28E69AACD8E8126969605E000A853197541\
+AF9047E5D17315BF062B9CD8DF91196F0343285D9E31D5C72560C156782B6D0E\
+5AF8F06D7DCDD8CABEC01B2438C168C40C21F6A8794648361BD2AEE13573A49E\
+CA07A7EED97C0B9C5B1E508869E4CFD5FE1771924B1CF5A4BFF7D4379E5CD59F
+
+02:\
+E5EB47BC1F82DB3001FAAEABC5BBE71B7D307B431889AC10255262281EC5F5AF\
+8A790BD7BBEC5EFFFA442CF2C3FD5CA4778763B9D15AEAC0B9B71BDB13DA8272\
+7F4967AC685975F8FF05A763C864D100B7CC1142102AA2DD343EA1A0AB530255\
+195C3A6400ECAB7B27EFF9B01EF6D37381FA6FB5401347F195354396772E8285:\
+1CF8DDD95D780A89D7CF:\
+539C266B0313E0E256ED98EEF13E6AE64CED90C160A4999B3D47CBDA5285DAB0\
+E0678C0E079CE9B8EB23E10EDFACFC19A80EEBB8F38ED5B5D6C8A988AB8CEC40\
+A5A5BA102F75586167EAB6D5BF0CE8FF30C656895800F6F1B37D69FBBAF9055F\
+7505DBEB537C0F986A1B5F0270DC12A640FFCB626F9763FDCFEFA1208C104003
+
+02:\
+E5EB47BC1F82DB3001FAAEABC5BBE71B7D307B431889AC10255262281EC5F5AF\
+8A790BD7BBEC5EFFFA442CF2C3FD5CA4778763B9D15AEAC0B9B71BDB13DA8272\
+7F4967AC685975F8FF05A763C864D100B7CC1142102AA2DD343EA1A0AB530255\
+195C3A6400ECAB7B27EFF9B01EF6D37381FA6FB5401347F195354396772E8285:\
+F6959926E6D9D37D8BC0:\
+249E1066542618CE0D236A7174708F801E7AB257931E9967A65C483ED66FB585\
+98F99B6664AF0EAE221E2A6B271D7D17875ED02BF7FE35AA0786023858521CB7\
+9FEE0D134D9DDA609B0270FC9804BB6BF74AD90AE11EB339353533DC0D5A69E6\
+B8758212B86024ED563767EA5D9B59655E0B8CC21244F720BA4ED663BF668E3A
+
+02:\
+B660EB18786256C993EBC6DCB5892EAC342F6D91229B73DC5D04F1AFB9BB0DD4\
+EB0B48895F514B4C9AFEAF86E91226F2299126D37528CE374E89CC312C06F47C\
+81112BF5CA60FFC33B98318E04A17627269F1AF461B6CB40F3BE03B0113FB2D8\
+404E154C7191306B36FD3EFA73C784AD9189115D0BB1BD82B850D000E7CC8D2035:\
+2C9EA313EACF2C5DA43A:\
+1FEFF88814BB53E447E1E955AC8F1AF597C15C3866033E337AFBAB8627306F2E\
+C1276621FF2176C89323CE32EA20F6AEC2CC271F1ED749408B2A3E43A23A44D6\
+A3F38DCDDCAB696B239110AA7ECF12C6681B0E97E6FFF1B72F4F6D796BF82B94\
+50AB8B3D28CA9D220BDF84ACCEA1DA5EDA0B470C3A82BBDD77B4C2723297608BD4
+
+02:\
+B660EB18786256C993EBC6DCB5892EAC342F6D91229B73DC5D04F1AFB9BB0DD4\
+EB0B48895F514B4C9AFEAF86E91226F2299126D37528CE374E89CC312C06F47C\
+81112BF5CA60FFC33B98318E04A17627269F1AF461B6CB40F3BE03B0113FB2D8\
+404E154C7191306B36FD3EFA73C784AD9189115D0BB1BD82B850D000E7CC8D2035:\
+0B9554FFE4F6ADAB2C76:\
+095952F24D9FBEF3A93A932865F4BDBB522CF24EBE153CE4BBB24CF301A1C7B5\
+1FE47B94F8F8B211CBC5A926FF6BAF9A6BBF7E15975D2DCCB95EF01AB7E64168\
+7870B0D01FC18B6B16FE17D3FC82931FBBCD4FD18C7F9588CEE8491876D72F98\
+F2E7EEA90C12907210D6859053ADC7178B87BF8B4826954D6986FE761E71E1B7EA
+
+02:\
+B6DEE7375BF4385043B3CC2AC5CACBC14AD11A17574738DD2BD84D2D1E6C74E1\
+6066C2A5C35BC3B87839858AFB5EE5E8ABFAB408F38772866F6F833F39FAB248\
+3A2C34ED55AD7098F9F63D4EC70B7950F02DAAAAB10781A0008F993C4027E381\
+6BFD45C52F59452A7B28873513DCE415A84FC8BC06601567F91EC41647DA2304\
+5B6E01E24516724ACC02947AD5AA2DBA4D952BC4F49D18ADA0B0F7CC5D488814\
+B921C0BC2B33D8828D80130DF7D79B0992CEC40D3BC7217D4A4DFF3699345E44\
+DAC968575194845AA7B60DCF3C712D9B0A384824C3579B40DBA265457D50F69F\
+02A140884D89B7FDEE9F0A787E76A37C58C92CF2D3818C72097D41B3FAA7AA95:\
+00AA5515CDAE5CD0F0DC:\
+30EECA6B48D796552F5A6A3C11F28D730FA077422CAAB34FDEB879AE0F71DF21\
+330E2F3BE5BF3A8CA372EBCD3DFA7C81B3398C31B0972D0B857926CB39732351\
+AACEB8276D52B9D82F9C245FA0F1CF49E785A2BC00FF27FBCF777F84D05BEF17\
+FCC0505820B029AC8F0CE17D2469372CE47E1428BB941004FE170EF87163E072\
+98EFFCC1BFA7E7CB1F572C340CAA075A5962A15B69CE937BC7EFB492F501FC88\
+CBF0119C351C8498782091EF6EFB19120195E5FF51DF86F90E90FAEB225AA2EE\
+43AB4E8358101C0348C7E3859B9DEBA19464C74B74AC48A0B73FC8D2E7F8033E\
+86208F0792B6E5B6DE36C99DEF604949811D1671EF6B0A4781B4E7A0A72AD855
+
+02:\
+B6DEE7375BF4385043B3CC2AC5CACBC14AD11A17574738DD2BD84D2D1E6C74E1\
+6066C2A5C35BC3B87839858AFB5EE5E8ABFAB408F38772866F6F833F39FAB248\
+3A2C34ED55AD7098F9F63D4EC70B7950F02DAAAAB10781A0008F993C4027E381\
+6BFD45C52F59452A7B28873513DCE415A84FC8BC06601567F91EC41647DA2304\
+5B6E01E24516724ACC02947AD5AA2DBA4D952BC4F49D18ADA0B0F7CC5D488814\
+B921C0BC2B33D8828D80130DF7D79B0992CEC40D3BC7217D4A4DFF3699345E44\
+DAC968575194845AA7B60DCF3C712D9B0A384824C3579B40DBA265457D50F69F\
+02A140884D89B7FDEE9F0A787E76A37C58C92CF2D3818C72097D41B3FAA7AA95:\
+B8E2FB9EAE22FB2C0021:\
+416D33F8C213CF81F805F54FC1D4E7C6A588A0965F1C9CAEEA1D41452E20935A\
+AF2D30F957584B56621035430212A428E27A2F687CA9DBB596C19864AE692EF7\
+BBA730F3D70CC2DDE15AB71E1E350C0C316EFA1A831ACD1441598B112482487D\
+F72F58ED318182C7CD0906FE39C5655BF1313F29A15D60A6178CBF600C7FBFF8\
+994840ED649C3C4026A463B3EA39C692B7D112B128BE49E1E32D4A7FF8D45132\
+83D8DCD9CCB8FB7300BE0BDD4C44DAA2F7049B3AD83437093E623442AC69B489\
+11CDA21E95E0775041F67F6E6AE01DCE646AEC20908E7C1B693600FE41ABA85A\
+C0C778641E46C419083E41773C749DB3E1BD8FD764E271860D2D7F8E11BD6AB3
+
+02:\
+B6DEE7375BF4385043B3CC2AC5CACBC14AD11A17574738DD2BD84D2D1E6C74E1\
+6066C2A5C35BC3B87839858AFB5EE5E8ABFAB408F38772866F6F833F39FAB248\
+3A2C34ED55AD7098F9F63D4EC70B7950F02DAAAAB10781A0008F993C4027E381\
+6BFD45C52F59452A7B28873513DCE415A84FC8BC06601567F91EC41647DA2304\
+5B6E01E24516724ACC02947AD5AA2DBA4D952BC4F49D18ADA0B0F7CC5D488814\
+B921C0BC2B33D8828D80130DF7D79B0992CEC40D3BC7217D4A4DFF3699345E44\
+DAC968575194845AA7B60DCF3C712D9B0A384824C3579B40DBA265457D50F69F\
+02A140884D89B7FDEE9F0A787E76A37C58C92CF2D3818C72097D41B3FAA7AA95:\
+8C8C306A629373BAE647:\
+0E9A00045FFD399D9DA9D0D7E543CF9FFD098BC23E72DD7763A64F22C7F0479C\
+E866E31438B8F7DE31A18F35AF419BED6C67BE1540614D3310DD24F019E14FCC\
+3AF73743F4C143D4B79CDF35C752A300F0A8251CCFF4AAF18785C533A7DF1A20\
+AFE6770DEBD1B8BA2C83B2E345A04F833CD173E998FF9840C2F8A370FFDCFF5F\
+D95CBD71B25FC9972192470FD145975344F64C2F6D68CB3513F48F9FC070021B\
+EE8F6A4282D098C44DF655CE415E89B97994AE3ABE85986C7EE0AC348EF2A4F5\
+2D102EA80836E77E81AD3678803E53C83CF2F30D2D4950FB6B038CCB3F2690A9\
+381EB34D6C09E88C090AB05E28047DC490EB8A1282FEB38E82FB0B18309284C4
+
+02:\
+B6DEE7375BF4385043B3CC2AC5CACBC14AD11A17574738DD2BD84D2D1E6C74E1\
+6066C2A5C35BC3B87839858AFB5EE5E8ABFAB408F38772866F6F833F39FAB248\
+3A2C34ED55AD7098F9F63D4EC70B7950F02DAAAAB10781A0008F993C4027E381\
+6BFD45C52F59452A7B28873513DCE415A84FC8BC06601567F91EC41647DA2304\
+5B6E01E24516724ACC02947AD5AA2DBA4D952BC4F49D18ADA0B0F7CC5D488814\
+B921C0BC2B33D8828D80130DF7D79B0992CEC40D3BC7217D4A4DFF3699345E44\
+DAC968575194845AA7B60DCF3C712D9B0A384824C3579B40DBA265457D50F69F\
+02A140884D89B7FDEE9F0A787E76A37C58C92CF2D3818C72097D41B3FAA7AA95:\
+FA95400C2B14E064F76A:\
+3F67F9DBEB88E6AD057BEDC3D97030555A908867EC578A6CA572137CB61C2103\
+6AADE6DDC5592EC7CCB6B263E51B4C886A51904C858040E493D64B9ACE5BAA50\
+C4A66D04ACCDFE0039D8541C4363DEFFCF93BDF5F5CC1FB64855D956B5EFD42D\
+4C9B96B9CBAA97A32F02AAB307674E53404E6836DB5C96B59572ADBFD1113B87\
+608ACE6D0898CB02E35575CC28D38A9FF8C1C4AD36BAA991DEFAB533F0A6C9C2\
+F0F0815F1D659ED576E5DB18494A54B6817D9E34A134F3B9A0F1E8C77FC204B6\
+EE087C0445A7036C935117E338D092F6E1FF4DF7605525C409456A5195233A17\
+6B29B2FD8FB2808D0412FCA0541B2BB6800BD8BB9DC9DC25230166071E8D961E
+
+# Format: KEY:message:k:sig:passphrase
+[DSA/EMSA1(SHA-1)]
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBGDBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIKioqKioqKioCAggA\
+AgEYMBQGCCqGSIb3DQMHBAgqKioqKioqKgSB0C1Q0dDyQ+/aB6Rid4iU+Kytf/dl\
+y0cmCXyXGWwZhoc0fqq9FwUyoxDFkZgpdYCgInJvW52O5kkgAAYYZdBSziQU4E7n\
+I6KUeZDYDqJU6VgkK9V1k4JoBKS13L68NwLawvXS+iDcSUoV3C591ynOVMeGsMgv\
+FLhGimZW7KaqaUVnqfcHuKp8UfboW6aqrjknltDeHixpTOduOsTzJUrxGMM/o/iV\
+BKSYqmkNrJmNIq0kqOyYBvxgwsfYO3cBPkB5gVBK1qtlg/gwsAA/sDOqyLU=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E:\
+868788898A8B8C8D8E8F9091929394959697989A:\
+19F24178D7369B619E566C5256C49EA648B68CC22C1999EFC24BD22471563EC1\
+5435356577466CAD:lrbbmq
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBmTBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIhoeIiYqLjI0CAggA\
+AgEYMBQGCCqGSIb3DQMHBAiOj5CRkpOUlQSCAVCe8zFeu43ErHj8bV0SwfCflqCh\
+WsKecYnHronPutGoumfIOc3vAOsm+H7MdBv7RI8VYcoSd7ccVKCrbrxT7sYpHw7H\
+2gxq4I3IUDjDRr/IcuDCzztP5fm5dcuIgs5qDZdqphYo4L1BNs4XLphK4E1RqW6T\
+UfNHUzrY1Rh26x8HRgd1Zr7O+J1A2ZvlopHIpwT6Byb1SQBiwvI2S3P63yPeqDZy\
+s8wDfcL8+xbpKu8qVN4/D33vQh4F6Ptmdv0xXJuQUij820h+LcFhj+0xRmUae9PB\
+dp8ykyAS5QB+29j2R5YXR93ANtH9q6uAWeRPv08XryEl9WBQy2h6vPOM2NNJJAhw\
+V5rx1HHa+NLJHPaSsTtgiXEC4/9HeMRNIRpwm/aaYyUtx8Y8zamXNf5sfs/RIp5Z\
+n2XIqLzaahgk+xm5C+pqqMAclBkLhT4iX4GvcE0=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E:\
+DBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEF:\
+4B4471C82B030F2C2115B65309DF23A8B6AE1EEAE0C4AF91DAD7CFA7D3DFC6B2\
+5D5FE99E7FE4BF62:cdarzowkkyhid
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBmTBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQI29zd3t/g4eICAggA\
+AgEYMBQGCCqGSIb3DQMHBAjj5OXm5+jp6gSCAVA3igMQIZIcNy49pBMJeSd/a6q0\
+oICNlYtfNlACbx6K23do+QjlwjgUzUkhpBWzVVNzSxNI7mUgqcFOF7OrBNQWldl3\
+F940k5OrNU0GZCPhZLIT3cIpkiyXSN+DGpMTH5pis+g5f2IG2TKgTz+fVyZ39qUC\
+Be+9sbTVElrF5eYjpMsGzgZW8t33hHH5hvpiXjCqKl49IApI/56EoATwYV/JHJRI\
+sC4m4M+8zYyXHJRiUMnLFgEZK+8M9S8jQf/tXtmT7Ua4ddc3XAhhSJ5zeRupLSI1\
+KEyKjq9T0uf3snhslzw7Vk6XRiUQS9I+QGnfXfW2ZLLji2gA54K/C+yC+UaM2yrV\
+HipE6cWA7f/uWQH/Hn9Al5vjWnY/Vb0WHx54lYVps9Mlaga5vIQcFsxrTS1ZQvHw\
+bygjEqFWhZNCSDQjvvFnelOqKOoq6cYcWmfwSeQ=\
+-----END ENCRYPTED PRIVATE KEY-----:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E:\
+A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B8:\
+76EC77EFBCE0F6B01C1AA676ADC3AC6409950FB79EC0DD25E6A76CE85447715F\
+91AB563454FE3242:scdxrj
+
+-----BEGIN PRIVATE KEY-----\
+MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAP795cm2680csLqzJLxt8vzriDGR\
+5cPejI7Sa3BtZNF9JkBLExBeClf891HGVhmc59HI7CSkVwKycD/HXXmNE6VCm4Ju\
+FmT5ENfw3OERv7Wac7sI9PenVT8qc3vfVi0lRcSvx9vXlfqNEEJBWIPV+s03NZLv\
+AAOKv0WQF0B6TtIRAhUA1wYYSyBGcR6bjdb2mt7KjxgCNtMCgYBO9ZCSK5GnL8Lo\
+Mz2/fQnl+/Gtu8REi6ZiwPDrMhjS/7DsLq9eL8OFzZAh85q0rGzVe0d2tow0bm6d\
+DYINiLcmiuH1TwRqYYvOecg2Ek3K/+w76b4An8IY/vtvg/9nx1izTuhyEhG7RZr3\
+yV9bc6caqfPjcIppb6FZ5ikOeTBR0wQXAhUAwi5MTj9OW+mLNUQQUTiUFOy+ZMs=\
+-----END PRIVATE KEY-----:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E:\
+A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B9:\
+22E16319CB7FCC90CA03D66B1550FBEB6121AB426E1AE3618A3F8A65C0457A91\
+E1E80D6EB35C8277:
+
+-----BEGIN PRIVATE KEY-----\
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBANsWdaItyazuSLhac0WrnmYSEKcO\
+ydCRzbSxSvp/QNn46SVucs4UdyCm+YqGchYVdL4MGLNu4H/VXW4D5vU/206YEPm5\
+sqLj0zba9/hohpwb+vHTg9Ak/EX/E+mr8z28TeHkg3LRX18EclzHjKe/zl7r0WlS\
+MbOz27LP4f5uKBUTAhUAyr5cJPSqLKo/EFDJsuzXb1KFgg0CgYEAxY953m2fa6IF\
+vcOJtSpk8KLe/8ZsGbugnFHBaHz+QWt+2sJauf/eTh2hyi48wEmWsAmyI2Jz64u5\
+WrXdJG6Y0DhcwJhbKts5wbztDIL3NAWxuppyGd89dJubaWElqyat81bQtIf7IuLB\
+KgXoL1Ci6BznryfA7cuv3ZPe5aefsgoEFgIUM6rqDcBQGunu3douZ54MG5I7Ve0=\
+-----END PRIVATE KEY-----:\
+426C696E672D426C696E672E2053686F75746F75747320746F20744F332D6833\
+723320616E64206C306E2E20416E64207468652052656E64657A766F75732E:\
+9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB1:\
+033A7684B382E2D2DE424111A110A7A326BA2158AED4BAC034815B8D3CDE92B2\
+D71A5CE03092079C:
+
+-----BEGIN PRIVATE KEY-----\
+MIIBOQIBADCCARoGByqGSM44BAEwggENAnkAwD9dAnTwxHobWWmnm8IVsVZuKY8w\
+cjg4YwWmib0iv+wvwhiKon2XNhbtErdg9uqnTPXJJ5dYAVf1cq11jKidgW37g0P+\
+J046VzuAdGjtWaxqcP8KuqBPIu72NK8c6Q2q59LYYS023XY/pvEf5JRSkmk38bgY\
+CK0pAhUAsPZ+YCHrRD4mQrzJXv3dtmWJumcCeQCwP26D/4ElPV4uQ9QilY5wcprT\
+ZzTGSzXTb8WAFHTT89dJjlwqQpAdIiBKrJmyKfWTEpqWtVMr8ugcGhdA1HjOzYTD\
+hsD2kOIYFfuKXmP68902Mpak+WbjsnLaJF4KfC9PrzUL/6ZGF+YSFexN0KvP1rCo\
+eno7RrEEFgIUHmzIejm5tPDB8oEZD9WD+5zm7Hs=\
+-----END PRIVATE KEY-----:\
+49206F6674656E20646F207468696E6773204920656E6A6F7920617420746865\
+2074696D652C20627574206C61746572206665656C2064697367757374656420\
+77697468206D7973656C6620666F7220656E6A6F79696E67:\
+8788898A8B8C8D8E8F909192939495969798999B:\
+4AF54C9F782C3B4B1D5000985F684B64D5EF030F7952FEEFA06475487BAA979D\
+AF382E53BE6C4D5A:rcby
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBiTBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIh4iJiouMjY4CAggA\
+AgEYMBQGCCqGSIb3DQMHBAiPkJGSk5SVlgSCAUC8VXV4fX+c+kMB1JpVinAEo/XN\
+U9LzjtAS6C4hUUV5VZQHKNKp8HiOdc65BWrpLOPc72kuNAgb+KjYunVWSCD6k7pX\
+Tm1XHIhbm54dsLynwY/F5jiNcSVKP0115E+WuJ5A4ps6sO0mk/UMzmH6IMmmNeK/\
+pmqK+Gcw63tYchYNXoY6gYAlEHlxF0QijPw2mV93Jl+pxWEwFvkttGmtPCBwCXLx\
+AdNRy9B4RSeaNaAMcALM0X/IrEx3owhoV9LAs8fUViJlVlI3BuVNofXCXeMU2vxv\
+Ax8d3H+CECKAMbtyGL8tBmVE0HKd5ubpjGQpHBW9egaagwSNvQFiXJKAUm9ST1uA\
+4iZgRW0sOEOyNNgWUbxUoI+OYmcDiMbGBzv2JeO/yVFQolmgzflqlE6L3JJ6yqc6\
+y6wZBPcO7I4uLnzuIQ==\
+-----END ENCRYPTED PRIVATE KEY-----:\
+49206F6674656E20646F207468696E6773204920656E6A6F7920617420746865\
+2074696D652C20627574206C61746572206665656C2064697367757374656420\
+77697468206D7973656C6620666F7220656E6A6F79696E67:\
+9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B2:\
+00F04C3A7E9D31CC7C76BAA9246F5A0BFC3B552BC3593C856C5AF7E7E7B2224C\
+05445802A7D726C6:cdyg
+
+-----BEGIN PRIVATE KEY-----\
+MIIBOQIBADCCARkGByqGSM44BAEwggEMAnkAtqJA6Mv/8I9ZVRd/288VFQUCcTPA\
+qkAfIn9ZP0aUqDJfRuchnUFrOWkzp0QUTA0eFVMwt3T+R2iL7Rp7HwFbAXLictS1\
+SzGX2CSCgOS4xGDYb8H7s6n/U4twEdQQfRsqKu4Z+gSdpfZStfFKZ0dYA9skEhI8\
+m7NPAhUAnoE2PuOpzxxrKPJtMLBvcW3m46cCeB6j1vT7dpPk4RV8L79QL7S5aJsn\
+5uK9HR3mIdntB2OXTm67qD+pHbVZuYfhrtrM97e72jopd/diGOlwZ0h0iL9xklxq\
+NvSlcuvRWCrlXk4NsJnUGm+fY6YUnWWuyhVVW/rLdD8xwkqP/us3TBdzN6Hhwk1J\
+oB9JKAQXAhUAlmo1ft2RX6ivJhmvitzUcFwvvOQ=\
+-----END PRIVATE KEY-----:\
+49206F6674656E20646F207468696E6773204920656E6A6F7920617420746865\
+2074696D652C20627574206C61746572206665656C2064697367757374656420\
+77697468206D7973656C6620666F7220656E6A6F79696E67:\
+838485868788898A8B8C8D8E8F90919293949597:\
+01224EAC2D585D92840280C76FB57306222E42800075D2AB872F08A8709651A2\
+219B1E7FAF242103:
+
+# Format: KEY:message:DER_sig
+[DSA_VA/EMSA1(SHA-1)]
+-----BEGIN PUBLIC KEY-----\
+MIHwMIGoBgcqhkjOOAQBMIGcAkEAp7fQiSIN41Jmp5D6sTiK5uZqM+NRrtZHVPwP\
+gicmBY7jLGKeSK7CNlaPTVkgKeQ04p7YCyLfMWk33vMYiAndOwIVAOoV8IwGiIXb\
+Rcm44dWRfdsOJI8BAkBUtk78F7Kf8X7/5eapEczOy4i8h8F0QkYQp7CZVONaPi3T\
+i2HA64tp3zM/z1WEEmO6wC4I5UrY9a84ckwLIwp8A0MAAkAS1f/NjG3z1z7Fhx7x\
+koG5Oitf7m9ER3YzYJEe/vQ1mtDcgiNnAV33SOCz02jfaFr7+H3AdI5KzDXTB8HB\
+2sQw\
+-----END PUBLIC KEY-----:\
+00BF86875B7DE45A29680AD78B41CF13BA70DA1DFB8500:\
+302C02147FF68E7723C6D6718D4B5BFD04069D4F86F48A1402147E78482F2BF0\
+37283BDE610C957E75CCFB5E1785
+
+-----BEGIN PUBLIC KEY-----\
+MIIBUTCB6AYHKoZIzjgEATCB3AJhANh0wGx4pOKnBg64l80gNBxTm0ql7BlotR9A\
+jFdGqVBK9BZTU7sqGRSgQx4WLiLvJZB9VRmYo0pBWd7/YKS/yufwytojoirhXhz/\
+IG5KkKbUZI+uWnFUFD+8YBiJo7hYtwIVANVZFYUPbGdHhTuhnGII8o33i3yHAmAr\
+nFyiH8nbC3hVOFq/ba0ftJ1HD/gRIKIhdjJP+BmDb9epR/45W8dgvPwZr8NCix4G\
+iJhaDt3B5ozEsFVtG2Wguk9tONZocCQByx48+tP0ELWhfHvsSv+gMrd+AeVzg34D\
+ZAACYQCmvNmEahHpA348XBaXHK9qVJIm7JIS9v1Zx7w10UUSe9fha2BKH+DCirfL\
+HVD5L1Ll3mJVJH/j+uO1PMZu5Sbuw7SDN/fNSMnpU/0krR8eZ65B3Strd3tM/vQ3\
+fS083Gc=\
+-----END PUBLIC KEY-----:\
+E58DEDE156818EFCDDC72022EEB5D457CF25032BC6:\
+302E0215009BB427CCD68D7269D3692A29489026F9AFA71745021500AAC0B52E\
+5C8BDEFD0E7B3F81189C50CA8C46A3E1
+
+-----BEGIN PUBLIC KEY-----\
+MIIBtjCCASsGByqGSM44BAEwggEeAoGBAMtC1tIjltuwKtWprTwYrEpO5ClbyUvd\
+BTIvUuYLrAaai7mGCSXbGRBXAHPS4hLQjUPZ7JuWYiLA2/WEttUP0Ai8P+oGsMKX\
+DIP31KifdwNHa3jckrPS1mMgA2xVDm/nIM07HxquQ3mXuM3YJ8Di47yqvlAoOeZP\
+e8fgPLe76zPJAhUAwy/14/bLpyDtp3898V+kSbHKb+ECgYBHUenqYLWd/ZNUXWCo\
+hihbT2FmS8kxCjiVsqhAd1YfXe+KyPKR+N5r2qfwoN87L/7jNO6Mm90T+OxEsfKu\
+HZMBAwwOXN54eGBjiJhQYAAryMQuwFV8KICbgOG8FyJDUjo9P6qaqmezV1ibqqsr\
+SVqHE6BjEgqU7T7ee6JbhdHWyQOBhAACgYAJDkq1oVGgIE+HdMGjj1LPclk51Euk\
+Fd1GMt+RLxB7Yt6Ism0txDoBE/aTbIi/b2bNCShn0y+Sr8+KT/6kYElwIfN9y1ZZ\
+mFlp+idxV25J7VpcMnSwlkaFuP+gmPkesXImQafs1NAgMvbLtAqmARO8OX3bO3o6\
+fz7eifelYX+8dQ==\
+-----END PUBLIC KEY-----:\
+EAD985D13D2A1217AD620068A2CF985F031F37BD22:\
+302D02144CEAA8139F1A477CB91B77B9B20CD66F13291B0402150082191AD5BC\
+88067D833F7DB0629527B1A19EF36F
+
+# The reason for these tests it to make sure that EMSA1 shifts the hash over
+# properly (because the 192-bit Tiger hash is bigger than the smaller q).
+[DSA/EMSA1(Tiger)]
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBCDBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIg4SFhoeIiYoCAggA\
+AgEYMBQGCCqGSIb3DQMHBAiLjI2Oj5CRkgSBwErzYywRqfwW9IxzqzsovFjnZK0Z\
+KNpUiGOk4CJxENZd0/qt6ap3AaspM9u9xsfhO6WOK5eDimQDpN+lBsqhrKbmErWK\
+9ngRAE3/vj6DlO5RHn01E57fr+aQE1kigjhHaNPwAYZXEKlBqS1SxSYd26LlwcjT\
+JrRqblCY4cBjCBGtzvVJK3escwTELNTZGgTr4X0A3sX4jCs/b/+MRt67cfb1SYOI\
+hmojiK/EqJ978yCZu8YPtQFo68Vq/RTuaHvUEA==\
+-----END ENCRYPTED PRIVATE KEY-----:\
+54686973206973206D6F73746C792061207465737420666F7220454D5341312028736563\
+6F6E64207465737429:C40DA376ACBB379890ACDFB021E02A:\
+041A7C1033F50A295DA0C4D436BD612466FB65ECE1357D4770BF93413F2F:\
+lorellnmpapq
+
+-----BEGIN ENCRYPTED PRIVATE KEY-----\
+MIIBEDBDBgkqhkiG9w0BBQ0wNjAeBgkqhkiG9w0BBQwwEQQIxA2jdqy7N5gCAggA\
+AgEYMBQGCCqGSIb3DQMHBAiQrN+wIeAqKgSByLDSSPDO/Ck1yLY91WOlFZzkM+jZ\
+P4jSwPOiJljd7+2i7+zBAe2LCkVyQZ+WMsScjNVvmYvmP9wucmMnj98XdpZuXScd\
+1GLkFurNB6MFJqW/jKUURrHWEwkIZiUlKVObnDyMdAk6PS/xpfRkDdQfqIvCTsyf\
+X5uscHniJlAfqUMAsiMUGUgyunrZj63DVpoP89mj4E6Ep6WuSmjF48QwbAHuYPBs\
+gwCpLRTCgr8EBF0WtZT+V4RzTmAG1qYyYEV0wdpiG0d5Pn7M\
+-----END ENCRYPTED PRIVATE KEY-----:\
+492077616E7420736F6D65207069652E:8182838485868788898A8B8C8D8E90:\
+6DD27F32F0012698CECB2D8BE550ED662111608A6586A481CC7E2E4C5CB4:\
+khopkmcoqh
+
+-----BEGIN PRIVATE KEY-----\
+MIG6AgEAMIGhBgcqhkjOOAQBMIGVAkAA8HR2W1fHj8t8G9/BzpO5z1Ea5YnMTwMS\
+/ozvaNrdRuRf+RuNGAEer1deRluO3BrQlknECrK+0BxpzfPT51qPAg8m1F08NAua\
++OtE3W4FMysCQAC+p3SjytVnkwVRSkxKcdSsbBv9NbW+TGQrxWE6KqfRoxN/Tov8\
++iZbtXywoSMLpPjP+oi/LQQtJTV7B07mRwQEEQIPJIiuAFmX4/IH2oOwMoAZ\
+-----END PRIVATE KEY-----:\
+54686973206973206D6F73746C792061207465737420666F7220454D534131:\
+25ECC0ED4CE7118A72D133704D002A:\
+14593FBF63EAC64976987524044D8B11AB9A95B4B75A760FE22C45A3EFD6:
+
+# NR Format: p:q:g:y:x:message:k:output
+[NR/EMSA1(SHA-1)]
+# Trickiness: in some of these, we put a leading 0 digit on the nonce (k). This
+# is to work around iteractions between the way we generate the random numbers
+# inside the particular algorithms, the way that we 'fix' the RNG so it
+# produces the output we want, and the sizes of some of the numbers (usually
+# off bit sizes, eg not a multiple of 8). It's a horrible hack. I wish I could
+# figure out a better way of doing this...
+FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE\
+01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E17:\
+962EDDCC369CBA8EBB260EE6B6A126D9346E38C5:\
+DE0B54EFABF297087EE623D5CA5588C64828EF4FDE4FFBAE1ECD2006776B05B1\
+1B81EA3CDE9BC3964C1687C5325BF43D7CCEFA0D0A86BE5DFFDDD0D1143DCD75:\
+D057B29DA96809BDC761F3210E467BBA5931B3C406581B268121FA5625C2F850\
+8B95ABC87CB061A8C32FA04E67397762F69A23ED42ABE051BD761DED4BD61582:\
+78E2D47D180E4EADD866235F5CFE0E487E862226:\
+FCABA2CF434AC8DCFCEC:\
+91F1D3A9C129D91120EA3F6486A079AA695AB632:\
+44EC399FAA3853B7F7313FCCB3A30B82B20A18C45E53188FC58B0E3C141A0851\
+BAEA0A7723C71A94
+
+DC523995E25A96ABE93502691F3411D3A6C19AAC218404B476913794A81EA8E7\
+8C3F8A60E6A05C151C61430743C19B4F1BA140EAAFB0235F93E83CF2995FF0F3:\
+BC1624A28732743BBE9B1A2B320CA31EF4A127456547ACFF:\
+829D8EE7A7221DC83F22F85FB5FC955E4D1E30563151D87AA82F1466E379A991\
+3351026B996C05413B01AB6E1AA83A8B3A30F0BFF50E118F0806A59209B3DB91:\
+8F8340D8E87FCFDE0BA81B45003DA97B7FDD21B4C1F256463507E56CA0F0FD25\
+FBA142C93E23AACAA89289379B953FA55B3E143164A035E470104A9A984B083A:\
+4CCBC8427B955CE5D0263D682AC2B8BF7861ED6226B848F8:\
+5075752E:A876034938F576056B00569E4706963C8B28D23E03AEABE2:\
+3097CCDF824E2BB33089DAA042551335625D9802A2BDE54C10810881157C8DC3\
+7E2ADC8195251FBE040B919D56512F57
+
+19A61288F2865F83256E77DBD8D651E6481A3DBFFD5F76777ACFC8C7F7F67BBF\
+112ABE08CF39A751295EAE6D388DA7D469CD312DA63C024304948A6C6AEC9732D:\
+1ACDF5C523995E25A96ABE93502691F3411D3A6CB:\
+50438F2395561269EE8DB64D7AB5602F3BA1544BB997A33CC5090B24B0911872\
+377669726D11BFCA63922CC669DB9D4B87D031079D10990012FFCFC54BBC8068:\
+DF49BE748682A13BC2EDB80D5E4C793E429F6F5F1F042A18ED8515529AB2F1B2\
+1E0F9E824C3F6C65FA04DB99E3D8C6A1DE6E052EEBFDF98F5655A58680A964F7:\
+16226B848F79E4E38E49D072AEEAE3AF4C3E1CF6B:\
+5075752E:019E4706963C8B28D23E03AEABE27C7B294EEC2337:\
+006AAA75DD2B3A7AE867D2DA3581D04AE2AAA5905C0074F8C1507136682A93A2\
+3A89504DC0FEA5603946
+
+2AC218404B476913794A81EA8E78C3F8A60E6A05B71066EDE730E7CEC8993A6E\
+6296EA8DFBBC7D46615122FB2F836005517F32C1DF25ABCE53CAC404E95E72675:\
+1ACDF5C523995E25A96ABE93502691F3411D3A6CB:\
+65052FC9728732E830ABDDC1AF7F1DAFB410BF1FB02A5414D718DDF0A867B8F1\
+C22EF2654B66C4EC538F34A4BAEE73981F86D07366EB672D2EEECFC347EA4674:\
+29F696C36E3BDF9B3945A031481EA7CF153ACAB0B689CAB7B799FFA9B5042929\
+234AE9C64D72690FDA8932E7C9AA808ED242E5E06AC68279544CA0B0BDC21F7F:\
+120FEB207F73754A9A42CD019FD2AC263476AF3CE:\
+5075752E:019540EEBCCFFBC202BB81AD78F1E046F4D4597F53:\
+013D9A09041BA0E9DD2ECE20C5042F5442DD14C8F00113A3C080CB2B8FCC156D\
+33E7FB8966032FE1570D
+
+C7ACDF5C523995E25A96ABE93502691F3411D3A6C19AAC218404B476913794A8\
+1EA8E78C3F8A60E6A05B71066EDE730E7CEC8993A6E6296EA8DFBBC7D4661512\
+2F23F635FF988E284E3018C2C5347734940F7A0B045A5C9A61288F2865F83256\
+E77DBD8D651E6481A3DC0CE0373D9A1EC8FC785D39DBF228112FB58056F7B0E9:\
+C1624A28732743BBE9B1A2B320CA31EF4A127459D:\
+92EC521C2E2C415DF4DE9675A934648149CB0DB1BDC2B11A59D276B1408DA81E\
+D2070E5A311EFD6D7A01B1D327331A7D5C830B781B9CC08D385EAB22AECFC558\
+3052C387ADD3F5FBEC04C1240BD3F48CC2482334F58606C0EC62DEAEEBFF0AC3\
+BC4ED688EA0E27DCE1FCA166CF67741D1FC0EBD7F19E10554C5218C0A5FA7BB0:\
+C0F8288391AC019CC4CFD7DEB3D85ECBCEE4386A4655E9FE68AB66B30098C7B4\
+8601B106B3EEA4F5D71995BB0FDFA27870B83ECF6F7EE4842B2C623367AF864E\
+0439A3D1125D7E697B085ED98AB85981D4C72BF10B2E2DDE9FD6D53D29D68AB2\
+DD87122F58EB8C8E9C52E2C1E346A192F12CCB472CD54DAF600E0E93EE06DA19:\
+64E6970384247DDE2C94701DEE2BD4255785BCA10:\
+5075752E:0AF20FE4162B721067160E55F9BC980AAC8A51BFCC:\
+05B325CB3BAC1A189B132F8F88DB1389958604305104AB71A2C77D8A9C902655\
+9C2E1765D44A81A1178B
+
+1ACDF5C523995E25A96ABE93502691F3411D3A6C19AAC218404B476913794A81E\
+A8E78C3F8A60E6A05B71066EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F2\
+3F635FF988E284E3018C2C5347734940F7A0B045A5C9A61288F2865F83256E77D\
+BD8D651E6481A3DBFFEC15AEB9410B3CB207A15FB0737509DFACD160A39DC3:\
+C1624A28732743BBE9B1A2B320CA31EF4A127459D:\
+9C78F55BBBF7C3B8AC9EE5F94F3DD9A20A521F933FB57A035CF27659EC01BC859\
+D1DE6F187791E92DD4F6F547707B7DB7586678E7DCC58F08897E3E552F2BB2ECC\
+61F4F06F4685F382DB34EB23ED93BF22FC7FC2E9C0A4151344CD22AD014B0ABFD\
+C715A199E4EE599F09967E07282624F6F520FE79752B94FD6B32A1BEA8D6D:\
+4C9421E17B605A89976C7274DA20BD5BB94DEAEBF07CB926B4D33C9B9C1E5939E\
+4BC1DB1BDA3CD1CD7828F17456666D243CB05DF5C02B430B25D41EB5E6CC466E6\
+7A5AC7D89EE3830690E3590588EA0CAD1883E299D2B9984B9234C6A49194BE1BA\
+31D5CD8F744177064622E696318B4C15AC1C94854F63473F695F2F517807F:\
+69E4706963C8B28D23E03AEABE27C7B294EEC2338:\
+47656E6B696B656E67617220466C61726521:\
+0A9A8513912E5A2AA2375A50A53E505C0F8D4D0A7F:\
+082B6655BB32ED12D90CA95B8DDCBE36DA1DF3C96F009F88917FCB93F04D6198D\
+438A1EF1FB732914332
+
+3ACDF5C523995E25A96ABE93502691F3411D3A6C19AAC218404B476913794A81EA\
+8E78C3F8A60E6A05B71066EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F23F\
+635FF988E284E3018C2C5347734940F7A0B045A5C9A61288F2865F83256E77DBD8\
+D651E6481A3DC0091CB01E4ECF2CE88F83F8CE4E39290A544519A92FAFF:\
+3C1624A28732743BBE9B1A2B320CA31EF4A1274569:\
+1CC1C87EDAF647CBD7356D6B162BC027C549063734D50446C9FD5DF04EE59547BC\
+B4022D7BD4784DDD0C890B3D17357E1C679BF2BF5688B647982816D63E1CE6254D\
+551211B03D7547B72D734152499257C0E8D45C33B192B62280D365B921881E644A\
+A31C11888EBAAF02791415F433C5635AF09A8FAC366797F40D18365576B:\
+E43E4F1FDD4D7C26D80916ED6A8E5748A4F900B2F6042E1FD2A42B55240258BEAC\
+FD494DFD669CEACD659F8DBBC7649ECBBF1B2DECDD1BE41142BC8A420E05F7A92E\
+3E23DCF021E8363E7027A0B896A456FE087A4CF5AFEBF5702FC8E64B82AE9369CF\
+BEBB174A7080F6911D4D03677671A7011DFB18B1E2B807FF1ECDACE6B9:\
+169E4706963C8B28D23E03AEABE27C7B294EEC2338:\
+47656E6B696B656E67617220466C61726521:\
+2A9A8513912E5A2AA2375A50A53E505C0F8D4D0A7F:\
+34CD8EEF38DE00C87C2281ADEA5A597E85AFB8BDB42F59C80618D6EDB7361EF766\
+74C0D535B31BDA3A9A
+
+7ACDF5C523995E25A96ABE93502691F3411D3A6C19AAC218404B476913794A81EA\
+8E78C3F8A60E6A05B71066EDE730E7CEC8993A6E6296EA8DFBBC7D46615122F23F\
+635FF988E284E3018C2C5347734940F7A0B045A5C9A61288F2865F83256E77DBD8\
+D651E6481A3DC00A927480187FDEA61E094D4DBCCD2A60F4B5E9F613829:\
+3C1624A28732743BBE9B1A2B320CA31EF4A1274569:\
+74C4E94AFFBFD290B2F15EF802B81F51A1F4C872687FE373BC410C9CAC231F8AE6\
+9F0D48921AB3497334E5D692E6DCF5F8A7A64C571E1DFFE0D4361CD3EE6B74FED9\
+5AFF2C67C616B1D6C9A072973B33510D86CD64080388D757ECE5DF8BAD1D4DA42F\
+021A35C5A7225591470AC32F8699772AE9562FDAD76F811F3131FAF9259:\
+3C9A8741FBBF7AC5A245F138922CD64EE798B62AA99931D050A71650D12B3FFBEF\
+E1AA95450A6DCFD526D9BE866089BD400FD2D6F4921533F5BB10FDC559C67FAEE8\
+4C75A8A611A57D83E69E26991E2B3F9B1224B61BECAB77D249F5F83DF42B284E3C\
+89565EB5D875573A61066275D3A8D2C90897CDA7DC4D02CA0AFF4A14DB5:\
+169E4706963C8B28D23E03AEABE27C7B294EEC2338:\
+47656E6B696B656E67617220466C61726521:\
+2A9A8513912E5A2AA2375A50A53E505C0F8D4D0A7F:\
+3255F933B90A659F32A2CEBDAD6C3465A494A87D350255D303139C95B0B60D3258\
+A060B4510B0F26B22A
+
+C537448C630CDBA7C285B31E420F2BEA827EC72309E3D707251350BAFA3DB9FAAA\
+889769A43A2B48A08B46D18842BDA591EE3FDF95A3E3D6A2137BB273E2FB7632C5\
+D7F620122DBED2574A5C9F6F34123132A3A1A6F7C5E105C129375A3733245580C3\
+659A11D4FBA7D50C116FE2D9BA950D6E03A0D20FA083056B38B3A3000C3:\
+2C0094AEAA23065124FC9C8ED04E1006D9403F4BB9:\
+834E982235B6DB4EF6EC52025C56C3A5BB4533BBB83F99C2BD12A200A0FCEC8840\
+94075F74F9D7BD5E4C1F4FA719E082EAC7F4C8A7AC5799F9F614C974E4C84A0487\
+AACA50CB2D7ED3A1FDE75D5147D8EA9654BB2E0D19C807188A64A5B4FAF05A52DD\
+AE1EAFA74146E28A1BC61B8C57192CC404D139F760DD3943E94B547930C:\
+470421750B0C8EF53949D4474F8DE8ADE8CCBF57FB1BB29238968074D9D703286A\
+E7BB845F8BAF54C865FCBF89AC0668F7941A2EEF751D9E477543133CB5BA4FEAE1\
+59A877ADC3D590ED0AD0EBA0D0AC1134B7B1BBCCCAE4B26E1452C0A9308B476DAC\
+D13B3BBAF3B7764BE5C2D9805DBD0640CF2D82FAABB58A4C4F1322E11D9:\
+2B9C9338848ACEB05F7C4F412F401C769616D48324:\
+49276D206A757374206C656164696E67206D79206C696665206F66207175696574\
+206465737065726174696F6E2E:\
+2B51BC665CF466B2CEC3DCA92F6D8F0F02F6A4F05E:\
+26DA0260F10D5C283D85A29399B341384B295B01EE2B2BF011377942FE9DA24B07\
+1B87D83E4167B0B5C8
+
+1E9FFA630130BC80BC709C3FCA6F819848DA96CC300AE868236F4AE5F93ED150B3\
+7FF1DF910C28996364F2E737E574811F85DCEC79AFF30B76C4415E742A2519D596\
+ED1227EF561CEBCE6BC029A10B71BE3C88DA1486774B985F5AE5CA97B3ABF3CBDE\
+F7C35402BE0029AC89BEEB2E3BAA596D913B046168E38F02291023BAE525:\
+2BE48B895976B2E8C34B129EB01DD76697C0C16829:\
+C4AB3CB5A673050E19379A28C6A044AD1E85FB66C4D52DFB640B1ACC103D31242D\
+68B19E11F0058F6507E9582094393B43160EF231CF73588CB6B02C4884898EA886\
+DC2EBF9C85E0FA567464D649C17562A15E5CA5A6E8E2F93CC30454AB3DA0D5DEAF\
+833F78B734ED3374AB5FFB9A110DA42C27AD87762EFEB112EBC88B103E3:\
+14707CF4838E01CD359472ACDA71737D51D0BEBC61D0F825275265E42EACA744D4\
+587249D54F901C0BD4F64B0879D4035EC9EDB40C222A15C7113701F8096D6E5CAA\
+3288CA411C7C8DB6B923E933CB297760ECE68EAD0A9CF22CCA855448717399A8E5\
+94DA9925D0CE334BC8434C32CAA225026F03443FD0B74499F3D82127E830:\
+1902ECD8813827AE27FA8033C1DE6A65093BBA1469:\
+49276D206A757374206C656164696E67206D79206C696665206F66207175696574\
+206465737065726174696F6E2E:\
+260FE1BF1BC190EB4014A860AD06DAACF0E62B5C2D:\
+073B5E19E15868A062940B6904BC19083869FECF5E0FAA319A9FD3D414F405D16F\
+11D8EC0EE01B489277
+
+33752A90D9CB3CE0672B72DDC545B97314D990EA3B6B86BB493F1256737CC3EEE6\
+1B1390F29E5E6A733998ED28B04527E05A19EE0994795318587ADDD8FC45C6A0E3\
+B8D83FE78BBDDE6C8BF74BF1A11A1785CB13F894B99E536AB152F5CC6DDBE4DF0A\
+E0B3323085AD6C851D18AC2C6C7A5D9F6F5F6297049C9943F9A9C050DD4B:\
+3B67337DCC5D5318D237B3CC48D05E60B7CFBA17CB:\
+4085148908A5902F01579635FE4BA536F3C5FA00B458A178A2A487D8ADDB0BB4F0\
+6DB1D740975F937FDF4D368444F85E210FD2576242DD0FCA58B3EE0595AA85BBB3\
+73D72B5E03C2C26B6C9AAB1C2D29669AE586347649A011F7428E05F727DB6AF5F2\
+5DF9338D668866E48014F0AE18B84675DB2A1BC9358D1613EB1DBFE2263:\
+24C4791E394B5A015AF827BB0638ED99C394AE67A913A21A04EDD2DEC49166BE7D\
+15CB82DBC0A64AF31C0EDA89B1E7FCEA26F421931AC663215B71516E406EB2677B\
+A4C48C759EC28623833ECE3B2836EBE4FD2405A93695C6C15D8D87ADC8F34162BE\
+B0C2030D59417C8B7275076C1DD64B278051A4813DCF815CFF3325D0BC5A:\
+15DFFDB80E7F4698D43771C5F4ADE8C9CD4DFA9832:\
+49276D206A757374206C656164696E67206D79206C696665206F66207175696574\
+206465737065726174696F6E2E:\
+2C6C5DDC20577082E4711D5F1327B0A8EEAA166617:\
+2AB302E2CFF9D76ADF6B8B348621D5E9A3D8D68F982DF65DFC1E84A31C40C1501C\
+367752E42743FD967A
+
+6A4F538DD1BDFB47B448BB75B0B01837973251C2F2CE4D0C9075685333998DA6A2\
+07B9E5F6624B3F80009877842D334A8D23422AF7D74465A98608BF34390B66C1ED\
+36C83D3EB047DEFCBC62679BBE7D966CB9801CEA54BCA7D88D8511CC4B16A2BF4C\
+9724AA861AD69737FC86ACBAD6D7B3CA756C2C3BD07001741071F60C367F:\
+380DC2F4A7A781B34B0182939CCFAA95F837AAE5FD:\
+4EF29DC07DAEB84A86C077853672D2B37BC8B068923861685ABD55A95BAF109443\
+EFF1B8B14A3B8713E095DB5CCEB6BB52D90EB136699CD017A98F77DB536410B447\
+C70CA8AF4B940D957E68EC0BBE3415C496CB70DD95CBF1F4E63C789EB06DB4548F\
+0B073C95DFFABAE82FDBFDB740D188FC94298857D2EEA9BE482ECF228C51:\
+339533E7F3414DE16F4F01A63E2E8705956A63921433B6D01CBF87D2CB7FE174FE\
+AC1C11856344B017BD123642CFC91EF3B7403F79E88F1CA8EE5B4CCE4C6FD18F89\
+03849C722407D7B864AFC6D81D04A40A9578D004D3E9E4A8BC0DAE6D7BA15EA57D\
+60F486AEBC187343F299DB3CCD1602D70291EE1836C08D28723B9F0AF472:\
+13ABB2B93794CB0F4058A4FDB9B266E5AC74681017:\
+44616D6E20697420776F6D616E21204D616B65206D6520612070696521:\
+23AEAF18FB8F0D808218A587F86C16B16AA5DFA48E:\
+07D6C64CF9FF00D7B8D9191C160ABF50D61E3B90281C06D436B4CBDB6CB380E84A\
+0D0AAB183A11E527BD
+
+# ElGamal format: p:g:x:y:message:nonce:ciphertext
+[ElGamal/Raw]
+C2742F0AB4664BDDE65B66471C32BBD5A383491C1C8FE71A7525B5C301B1CAE7\
+A48317D2ABE8C078CEE424899FEC4D876891BCF3E401E4BF339E27C1ACB97E39\
+83ECFB81E1C74093E8206CC794DD180E5B646EB1D195455092859F981FDB3C39\
+47B179FD9DA4C96A1F716570149B0E5E91AFE7168F4B5B92797B1E374AED6097:\
+D:3571A939ADCC0E0A61F8FE6720372DA9FB130C33757B101BED87CF677B77F94:\
+380BF24E9D162C61E95E2E84EDC0F9E56EADF564F5BE33D7A46BC4E0BBCF9151\
+5129E2A547583E576154A216AC035C11523111F877A4B56EE4C459ED645C63DC\
+52D4131D865DD4BA8D057F9FC1EB77352A13037CA23BC2BDE49794B3AB5A611F\
+D106ADC74D9F48FEC91DB1EC77AE70EC9408EA0E750D1CA4B2E437E4233F3E32:\
+02AD1D776D591520E4D8BEF8B21CC2F54FB4EB788E52ECEBE13564435DA66284\
+D51A6A6696E615EF599786CE4CBEFAFF066E0A1CD8868454EB5CE0CA99241B29\
+E1D1492CF2712C2C101B3F3779034683AD8271098C2E3FBAA83901A97D9645FA\
+5815AF79F4F638ECBE09020003F434D708914899C668F34830E70F4CAF0803:\
+0A5842A8D0C1B07E5DE6FD3E0C6B1108523D4D35417F:\
+5B99F58B48F3D473327075F2FF4EEA3C8C1FEB0B241F042864610D6FC512A81F\
+431A965724195DB71C3B84B6B9F1DFAE0DAE60E7CDA957703D10FCCDA45CDD0E\
+F8C8F76AA4F51F3EDAD8E5085B97D69523A3EAC89D67CDFDDCF0A30491A98BE2\
+FD6C5E69C3A2C95300B9DB4EDF2111E7613EF7B2CA430D0CFFBDECF6A7BE592A\
+853B404B6910C48A0204ED3430691E766FBAF21A428B9F833C5932C053C616EE\
+B59850150A22331A8FB5AF2065B595E4F08881B1DB7CB85A28A33F4449890739\
+679CCAA431A9205210995BEA68759B475BE4183A975C9D042FBBEDF589AB6AF0\
+17D7523B2CC90CD63526BC584F1E9EF42ABAAA9238987D7F73B94E323C6AADFD
+
+FE25EB971E3488A92A4BE75E51050B0824E69B18AC433B5AE7DE98EBCCE8AAA6\
+301237489ABD17A52EA9759AEC87D0E90F7766D64096A49CA99EFBEC82049898\
+06F5C49479FCB6CE8B881BC28F19732F0325786E7DAC54F8C216B6C84562C88F:\
+5:CC4D3B878DB91C340CEBA8495CB5F703ED90AB24BD793E4470125CC:\
+4B722A9E2DC991CEEA1D596586D245EB9B8129515AD66688CEFDBF84FDFF8C19\
+4A2D2BCB2AA82C47CA9FBB3FFB86BFC5CB4676B4DC4A2FF006AC3D578010C9FA\
+E140822DBF9DC26CCCE1701B8CF08740ADEBA1CB94056FB33FA2E88DE84CD477:\
+02C1ED6A171875F055809F12BC61829961CC740935C6DCC468FA663E8D1A7DE9\
+E0555E3EA99476436743FC5C76D3E041055FAEB7641907F8E2F1F94061B22E72\
+B7CD39EDD7A6367828CCDC000301CEA7D91CB1E8A3E20DC85FAA23EF6D08E6:\
+F42F854C10C9DD14A6712594A31326A1FD2CF5:\
+9E47FB001BDDB12F2D8E0FA5501A7EAC1B185FDFC7D2FF3E4461B0D75D626F51\
+56DEDD4D25F13C6C1F5F9A1F916058045705F5E82F748E9B6F0DC95D572B8DC2\
+770159092EECA13946F0522FE2A859705009B615818A1B4F98E8DD38CF00DE74\
+6ABD5F3852D93F8D9299DE18EB763F11E41A8B9660C5F056538EED431BB8E219\
+9D9012F50C7FBEF5AAD35ECCD7F141CD9AC6553315A2699D6718F50EBDCEAE62\
+A11ACC466E8533EDBAF13C15B5532B323EBF283B108F892DBFCEA21231DFD548
+
+FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE\
+01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E17:\
+DE0B54EFABF297087EE623D5CA5588C64828EF4FDE4FFBAE1ECD2006776B05B1\
+1B81EA3CDE9BC3964C1687C5325BF43D7CCEFA0D0A86BE5DFFDDD0D1143DCD75:\
+841CBF70BC6E95C7E5ABAE60DC6538EE:\
+12C0A0D25B072D8698FD929B8EA219874E4EB6A7FB7D7EB5857A246235D70F6C\
+950118914598E62ACC2EE8E061B560A1FE272B9CA163A7C134E1D6767910ECD:\
+47E586A7E7D98C116A6F553F652E57BF:\
+BEF5E7EFAA76C52A8ECEE604EDAFD31B:\
+CD70DE085B0C586B4E64097EA3AB4CE0B60A71B0F640FE4468F4F940412EDBD\
+D9035EEC602530CFF81B2CDC35805264A866E4689DDBADC3438575B6337118B\
+B23A5AB7710F85F2A4E1E0DBEC5652FEF73C868747ECB7043BA08241A0879A2\
+DC588D3EC14ED552E62B1B111646FF4DFA9050754240A46A840EA5EB1D97712F2BB
+
+FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE\
+01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E17:\
+DE0B54EFABF297087EE623D5CA5588C64828EF4FDE4FFBAE1ECD2006776B05B1\
+1B81EA3CDE9BC3964C1687C5325BF43D7CCEFA0D0A86BE5DFFDDD0D1143DCD75:\
+AA3837AF7A7ECF6DB7E0B702A054363C:\
+74349C465B92635C1692BB6F2932E06C1BDF3FC81E78DEBD661BB1DBF1FAC1DC\
+C24EA052A119CFD272CCA2BE1E6BDF4579A7D69C739E8A412D4AACDDFE9EDFB5:\
+74BC8D009250F4CD2E08BC556EE01449:\
+A2951BE393736E39E9D209FE978C7546:\
+6D6ED1C6E519C628CACC7981A5BBE487F6E013B26448D711911698CEEAA4F746\
+182A716602183A746FC35B022BD7B27EF079F7164309653D148D0CE91907FF6C\
+4A9001A0CCA2A0A163F3F93200C2E40A957919CB84AC35B928E026F1827E6D4A\
+9B986B592BE39861538414D5EA6980248FD3C3C0CDEE372F392D5AC46DB8EEFB
+
+FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE\
+01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E17:\
+DE0B54EFABF297087EE623D5CA5588C64828EF4FDE4FFBAE1ECD2006776B05B1\
+1B81EA3CDE9BC3964C1687C5325BF43D7CCEFA0D0A86BE5DFFDDD0D1143DCD75:\
+8FAF3D43EA4C7EEEFB9C08807D90B160:\
+F9AD56F050A9FBF969A0A7D2A56BE409BA0EFCF23CCED06980E5A8965EBC6C30\
+08858AA845370F56C1BAB31177C2BB76DBFA9E04FE89DCCEA67BCED6C55ADD8F:\
+01AFE1A93EDB9CD3E3715523C952478D:\
+9500DDCD404618F64A2063BC19941A6E:\
+0636C3F1C63C54CAB4B48B6EF0ECBFF00BA6AB70DF4DB6266D0785351B37279D\
+41D957D16CAB48C64035DCB2A1CD75BAC298C8ECAE8057D87071EADAA5DA6E2B\
+69B5F353B5753F7E24DA81ABAD40059CD73CFA6E78CAB1C7DA418D55E5DBD42F\
+A4F2B876A25B4AF63588C80E0DB11E8BAB1531960E951C08C1A68C8FAE0DA87C
+
+E9E642599D355F37C97FFD3567120B8E25C9CD43E927B3A9670FBEC5D8901419\
+22D2C3B3AD2480093799869D1E846AAB49FAB0AD26D2CE6A22219D470BCE7D77\
+7D4A21FBE9C270B57F607002F3CEF8393694CF45EE3688C11A8C56AB127A3DAF:\
+DEEE9EF5ED1516CE7E695E672B8CEE45E6CD7B36E0E6385F894BA86163F6F3E6\
+C6D4E8A81146D4017DEFDD71CBD90FA0247659B88B7CC1C894F48269FD4F1AAC\
+0A30538DFF6B3FC76CFB131C9E7965B58858AB0A43B557335912A8AA547F9568:\
+FF4FD921EDD9618570ADA5C59C2A01ABBB9A51:\
+BDF5D785E7621256CAEB307A92AED0BCBC34B6ABCC568C200D413585AEF1E686\
+9C60E87001A664A8FF8645C3F79E1667BC2769D82605C3B1AB1A0DC2734AE831\
+32652544275F5C59CCA355BAA02D9DB3796A6B6CCECC14BD85B02A2C18EC7EC8:\
+58E72BD0F04B11:\
+EF07721FF6B28A8A3B4EBC95C16B13A83649B7:\
+C7B6ACADBBCFD3A34EDA31CE9CA7F7889FBB2DF5C6C25793EB974591BF0EDE93\
+637B6A95E8075BDB2A987039D92487665465C98AAD0C123FA00BB9736170E780\
+69AA32DFBEB07099A0B7D439AA807A2D3D6F9F913EBC673F9F8CD5D3C0E9DD0D\
+988EAC4D8204928C2DA8ECD1FA3A598FCBFFEF5017DB8542D123CF69E8C92EB9\
+56F10DC995AE6B6564967D5C12A07BA35607C54CC3F10A36FF3603DD7CC14906\
+64610002977CE8C4A4EFFBD1421C902D4D8DFF81D014E1AB55F239E0F2FD28AB
+
+E9E642599D355F37C97FFD3567120B8E25C9CD43E927B3A9670FBEC5D8901419\
+22D2C3B3AD2480093799869D1E846AAB49FAB0AD26D2CE6A22219D470BCE7D77\
+7D4A21FBE9C270B57F607002F3CEF8393694CF45EE3688C11A8C56AB127A3DAF:\
+DEEE9EF5ED1516CE7E695E672B8CEE45E6CD7B36E0E6385F894BA86163F6F3E6\
+C6D4E8A81146D4017DEFDD71CBD90FA0247659B88B7CC1C894F48269FD4F1AAC\
+0A30538DFF6B3FC76CFB131C9E7965B58858AB0A43B557335912A8AA547F9568:\
+B3BF90978FB3EF96E40F2AE8260F42B908EE1E:\
+578C33240691D5351BCDF2C727BEDF8C4B956EB32520ED93DB034D00EF69C44E\
+523639DCE55E09631D8EB6C6D6760CE10C510AA68847B7CEED43A3749F653B5B\
+2BAE4B07F95F85DA8F058F8DA2A0D07A2F0C5B009E63C06B638FA1B43CE7F7A9:\
+C37AA41207A357DBCCFBE93DC45C5BD91D29FD29CBA29B26AC437A9B560C3BEA:\
+A36338E4D7815E6A4B178E951BEF073C6D5A7F:\
+D824C94623313298600CC20203F8A40006CAFCFC8F883C99AC09DBAE4B95E6DB\
+9FB5737E24D9D7E39B603893076BC81A2BC0C0D608B32B353972B57066535DAA\
+C49E3F7F2A0E243618EEE01C5AB3AFAE1D55E3A1DB33CF713E5187AD51D55144\
+B1A108354ECA651E55F85F253FE73C1C15FA5EDDDA47467BD0425F09E3C41565\
+48E71896659C618B84FD72BA176E2DEEECD8B15F2C05F870697EA464B8827374\
+2BD6ECBA5164424F34EBB9E13E31683A16712901818C7E5F502720FBCB075EA1
+
+E9E642599D355F37C97FFD3567120B8E25C9CD43E927B3A9670FBEC5D8901419\
+22D2C3B3AD2480093799869D1E846AAB49FAB0AD26D2CE6A22219D470BCE7D77\
+7D4A21FBE9C270B57F607002F3CEF8393694CF45EE3688C11A8C56AB127A3DAF:\
+DEEE9EF5ED1516CE7E695E672B8CEE45E6CD7B36E0E6385F894BA86163F6F3E6\
+C6D4E8A81146D4017DEFDD71CBD90FA0247659B88B7CC1C894F48269FD4F1AAC\
+0A30538DFF6B3FC76CFB131C9E7965B58858AB0A43B557335912A8AA547F9568:\
+EE639A2B80F4FBBB96B82A0DA6ACF23124A1A1:\
+5D13E05491C00E0FAE1245BFE0E374F2753CBF1926352FB4180F11D740A2F6BC\
+8486C0E0F52D2990773ACFE01CD4AE6F428D55092FF33144C2D9F37692BC1230\
+89D9E77ED393C495ACBEAE7A9E927F4AF1D0E845D2EE93E733BCD0D50268A47:\
+36FDC0501B44AF:\
+832BC01DB63F958D47B6962AEAA74C0831A6AB:\
+62E46CDF100BADF4419215256BEC8427DD0388D1B60B5A8675532C0934351BA0\
+036AF58032AB6C4DB829F1A0C8217FBF2CB9C10A5C60FF285919BCAF238E89FB\
+AA4771CAD13D4A69AB2C1FFF0A44D2F9287F1E70D58210AE859074B3969EE800\
+A9D1507BA48582BD1E03CC234B0CB11408BE0932763EDC99CA4BEC6E496A4522\
+37F920972C629714EA2F1FF212460C23B66DB56BC73E94743D32D2CD3536A17A\
+136F56D7F7C24E3B8F102F48BBB21633279D3E584E71DC37B436104CA69A6BB3
+
+FD7F53811D75122952DF4A9C2EECE4E7F611B7523CEF4400C31E3F80B6512669\
+455D402251FB593D8D58FABFC5F5BA30F6CB9B556CD7813B801D346FF26660B7\
+6B9950A5A49F9FE8047B1022C24FBBA9D7FEB7C61BF83B57E7C6A8A6150F04FB\
+83F6D3C51EC3023554135A169132F675F3AE2B61D72AEFF22203199DD14801C7:\
+469603512E30278CD3947595DB22EEC9826A6322ADC97344F41D740C325724C8\
+F9EFBAA7D4D803FF8C609DCD100EBC5BDFCFAD7C6A425FAEA786EA2050EBE983\
+51EA1FDA1FDF24D6947AA6B9AA23766953802F4D7D4A8ECBA06D19768A2491FF\
+B16D0EF9C43A99B5F71672FF6F0A24B444D0736D04D38A1A1322DAF6CDD88C9D:\
+A0A2CF6E5C2C3157078FE232D88778DD7A864507FEF:\
+23020176F56436414B28AA4246433075433AC50C81C803275AB4BFB132D8A42A\
+27B69E40D9A219F36546801348E0191E7CEA23AA70B7EDBD52A44D0FA48946F9\
+0211186E58DAD6C7D2E9207379F31FEF083224FDE665576AC0A1EF193CE23FE0\
+8DB42715CE27A6E00DE4F373F92A221759C1E318161302ADC3CE9F1229290D46:\
+DF72B687F62AFEA3A51195EE876E4C87708F7ABB8D2D5DD72B68256DAC6D:\
+0B333C9C486C5F3A96F37D00133ADD18113376C9BE76:\
+4156CF437A39C415B212AAA34C9AACAFA3F3113F53BB75E0BD3D759089E21754\
+EF89B4BA1A8B37E5EDA13F8A2F87D16F03F3B6FE19A5CF799B17D83F7B5E9A22\
+5F324AAD7D46E80A1DAFCA337A3F500930A7831D1F3785763EB9A6994063CED0\
+33177E1CA2770B751B3053C1445ADFEAED790E49E4685A05B9563D1EF32BD321\
+971D541B525D648EA7C8741D8FA7E46293D46A0F4345BE73EA4FAF1E4C16BCBE\
+11C53BA0FCBA2975BD37F11FE5ADA8731CAED3C403EA6E43AE47ADAA7E284334\
+04AD3ADE6AA8E12BFC374BADAAFB167F3AAF91DC6F8398003E5F8528E8D4773F\
+800D48C8EDDAEDD72A3870E97679F946CE27FB692BC11677757A28F3899A3DA8
+
+FD7F53811D75122952DF4A9C2EECE4E7F611B7523CEF4400C31E3F80B6512669\
+455D402251FB593D8D58FABFC5F5BA30F6CB9B556CD7813B801D346FF26660B7\
+6B9950A5A49F9FE8047B1022C24FBBA9D7FEB7C61BF83B57E7C6A8A6150F04FB\
+83F6D3C51EC3023554135A169132F675F3AE2B61D72AEFF22203199DD14801C7:\
+469603512E30278CD3947595DB22EEC9826A6322ADC97344F41D740C325724C8\
+F9EFBAA7D4D803FF8C609DCD100EBC5BDFCFAD7C6A425FAEA786EA2050EBE983\
+51EA1FDA1FDF24D6947AA6B9AA23766953802F4D7D4A8ECBA06D19768A2491FF\
+B16D0EF9C43A99B5F71672FF6F0A24B444D0736D04D38A1A1322DAF6CDD88C9D:\
+B81133CD81461728FBE2D40682850CBC1176BBF24D9:\
+650BDDC18070CC54F0DC4DFBBF4B3144749D7D219E4122E27092FB005F82612D\
+39B652486DFF5B628FBE626B54D70FC5F3C11E5E4C7CCB5CBC78E528AC70E740\
+302FA043581A55A93EBB7143E807C056748702353A65715E39A86F3F1F90FD00\
+FBBB817D7C48A465A1DBC8DE5D8CDCE259D129D02EB673A4181B9CC88B7636A6:\
+F73BB7E5C8A5619380:\
+0AD9527B09EAD1E59B4A1CAF58C861B69A856AB8AA80:\
+C9881464A37749949D66D75CD9B7A8ACAD33DD1FAC7561F684E9CB5343D2ED15\
+969D7EDB4135518B50F0FEC9A9559C1D5E44DAB42C14BBDE2D2711EA4D02D7F2\
+7D1A9BCFEC9E8B73FA64BA3C54707FDDE7D5BE695E17FB9D259FB576FD4E57D6\
+6C8F727DC236E2A6E9FD01709D34B8D09F7DD3890F003EBE616042B4E0A8A00F\
+6C3F34DE7E002FE72A84AF8D014D64E8CD08B9B56CC3A6BBE6F966B92105A92C\
+5ABF4F2BF735670622F6213FE9739FAD65692E1C0EBF708A47E18600A22972A5\
+A3DA0F22D11C581D46F734151A083FF757E961351EB183B467A859FBB9ED1DAC\
+396FA405701FD6E3A62EB126E93648C3C6DFA9C4DBF3C005880F4799F66B310E
+
+# DH format: p:g:privkey:pubkey:finalkey:keylen
+# where privkey is our private key, pubkey is the other users public key, and
+# keylen is the output size we want (often this is ignored; if it's not there,
+# keylen=0 is assumed)
+
+# Raw: Use the straight output of DH as the key (bad idea in practice)
+[DH/Raw]
+813E0E814BEE676DBD3D9D28ED73D36735D21FF6457236F68D3D6145560C0FAB:02:\
+66277A816EEEF66675319C2AEBF2E8D6154EE359370E8E1B194AAA1B9A20FABC:\
+3B4C5FEFBA6AC0A402C6AE132540B7312C93DCB3259530F3A45F7A2C408C920D:\
+5D9A64F9E54B011381308CF462C207CB0DB7630EAB026E06E5B893041207DBD8
+
+8732EC631F04F7AE57F66AD4A481AB4462AE26400348AC764D679311C41C5EF6\
+5BF618A6E0742A27D59A18868FC7A131DFF158C83ADA310EFA493CB86CC2966B:02:\
+0AAA1D96792CE097CD533208550433ECDAECF557F1DB669A5A0ADE4284B5272C\
+12D46FEA0E9A549B28130CBBB76C36C9122BBD0AA3D3D1C055731DA91F28A99E:\
+675F1A653994E03B986BA4FA13A2B51C4493B310EBFA5EDE77D493CD243FEDCF\
+FFBE9731D3E50A4586EB405FBAFE446E71EB7DF638C1ED43EE3DE69A7363BB61:\
+65F79BCC47862E02DDE775B8FC7B1D0CBA094B753E502D49A446868768\
+1F178CEE98016210E136E80255FC8FDECC4D38D91EBC82C94B17652BDC7569AC383F39
+
+FAD40DCD165ACBDA7D4BB0FA4830F5B27A27D9A01A66A60BB177CC31CED51DBE\
+9B269227BED5BCDD18E217A98D9BE4E55D0498717AB21A4BC1A32BD32D7BB6B3:02:\
+8A2264FE1D57CE13B9D16448C25626CB4A5E254A9A158DEC352C2CF36864F986\
+2021AFAAFDB8F5FBB51282A19A2251C91AF08173E71EED2B2BA7BD3378F3355F:\
+2B86E1EBADFBB7F10C9807602F90EB2BBFE9D77FDFA743777B8CC212892E54DB\
+D01CA7F4023EEF2A56BA9277778A80BC27EC86298E22030469A0EF3D49B57C3E:\
+290BF0265BAAD40A5853BAF3CC18B315982FF282C82D7332DA6A8826E789330D\
+875F29F57D9A622DB7DDF156CF4440EDB8455BC32859FA2A178D42528FA64136
+
+95A2F3D72B3D394EFDE4C055EF6C6E4E7A598242D0F2D2F9F31A2BB5191D7CB4\
+7FDFBDE16BC277BEEBBE02079632F2374CFCF4F9719C154DF8A9BAE52A8D7127:05:\
+2B600D6C9CF358D21D41E0DEE2B3C81520FC617420F63B2ADD9E64D2B13954B1\
+AB117B40B6A1EDA56237DA1ED34DF9643FA471C2B4AFB5A00455DE9A0FBAF399:\
+6A097559AEA851EB6DB23A0D45A5060F32F50961BBBEF3D22A01B4EC229E651C\
+932958088814DFF54E9647FAAABEB555EA966542C24F28980B2A47A902798B55:\
+4ED3B2ED6B3E8446D8E1C3D2BCA00FB939464874BB6750BDE5F5DACFE9F81959\
+7E96F6B1DBA27C785553383AE87188019734A160B6BA5396760B88EC1F2A0E92
+
+86B7815320710E1415DC26FC566F64866BD5AE7FD8DA39F42CFD3533C80B4E37\
+402557B45D027EBDB8BBBFE66769942408E2FB00A9433597BB20B9312A9F84A7\
+F767F7A5851A35F1A4C2A89AD1DC977F45689183C9836C96AA5DA075CFF03419\
+B45B885D83DCC4C0E3FEE66E76212CCCA1382FE314E4846EA0BEB29772FA625B:02:\
+21716E2202D31407E8471E0575465FAC1D309A30C90C9FA498F1718BA4047E7A\
+831E85E0E358C847CA4DC9DE47F007279D4BB22107889E5B7BE0D02F8519D585\
+2A1DCFD54F0AED08906797D9382BBD6F7B4712850F8981E855D6A6769807722B\
+7D93FEF6B822533C2A51CEF857AB9359A36AE6A3B7035AB6C0B7B4660953DAB9:\
+07BC618157B3FD72B2D80494B73AA7A5E5F40BF4A5537E4FD878D3CB6C9B0D70\
+D6A3CB3B35BE49259E7BFCFCBE9FE133B0133924A8CAFB4317005165416F7343\
+42F1593C71854B696ABFEA7E3AABBE99F1ABC745AF0E56AF283DEB81CDD91F26\
+B1FAF1EDE40D97B1E3370339841AA28A99A638DCA7958631BD6ED0BE6A470525:\
+2B6D9504C1D7ACAD9652CF79A6A0630EA9D19C197E908E992BC318BE2867FAE3\
+C1AD5BE83E6E4AA1CBE0347774038F20ACD790DEA82B2A5862BF21FA4A1AB464\
+AE985CA8AC4E5076AD0843E144C1305759BA047446A3A7F2426BE0C724F26900\
+9B54447B6A970876E5E4C613356805014D6060039C081AFB046863CA9BE9C848
+
+# The primes and generators in the next three are from RFC 2412: "The OAKLEY
+# Key Determination Protocol"
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF:02:\
+70F70628FC92FFAB93039B31EFC65E760121EA6632F9D37189767CE01D4A7C5F\
+782022DB71857281E270A7AAAD68467C2825635FC198208F749A5BF25C444D12\
+74F6F760E068FE11A7B7FAADC154EBE77DFBD2F9A399BF1710C75291E6B33E53:\
+35F4FE8E20A94672FECC2F8C24597541E7A1EDBF76C0D0A92FDC6E99CA016F4A\
+3F315E42A5CFAF0A50541E420F2ABB632A2609336077CB8E0320CAAD94796478\
+8B26954B847E08B1AE08FC3D2D0F9DCD449A890B2E4448E4B2D106DFA887FB61:\
+1835BAAC22790A32874BAD6465BBFA22BEA8A8FFF9847814273311E715FFED51\
+5AFEFAFBDB88F5F6059A874B8ECA325553D2399B36BDAF703E23D9BA426B440A\
+B9B3232319E82F60651B5D9610FF5F62D9676AB0CC691DAD9373E14407515B06
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED\
+EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF:02:\
+A71FB45046F3E7058521C35F08200AF51A0193D68776BABC6F5571BCF092A77D\
+D44E7B4E5AA450A7C4FD142DF648C03BA1C6944941B3A5C2F2515177B23CFC01\
+09825B85029798C6D3EF8C46D9C85A71558AF8CAA411B270EA3FDDD7D3586784\
+DF92CCFAD908096A0FB647B18A62D7E4AEDAA26D9F4E1247BB208232FA9EFB9C:\
+51F0590A0593A41182A1E132E68E33D28F67CE0BF42C6BEFF057EB10255BB78D\
+0BA2517603700FFBEE570EA1591F56468EA7AEAFBE03B10D3B7A04271B94F819\
+0031DADD2D852F8778D9A88486C89EF3C5FF4F478D4E21660A0B1542FB58FE82\
+FF89FD8E10334A455C937EA11FBE28A8188C1DA05B014FAC2A28A273AA517082:\
+78E5A35AEBE11E2A6EE2AC7CF250BB6D14D4194E4B4F863388B403A6D4F77179\
+2399B005B60876A2B54F38B10E80D7FABD5CA0260DA7F49D3C8BC319EAB0DCE9\
+8DB256D55A3D286FB4A92D426908121A48FBE08BCAFBB2CCBD79CF2422ADC0BF\
+7FD6D32BBD7179CC92C5B6F3A0A66F75521119B054C9C890A5508FB82DFCF947
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED\
+EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05\
+98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB\
+9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF:02:\
+4E83BC69DEB2E98884E5BEACD0331AD07869BC0CB3025B4882670A9AF4FF1F62\
+8FE59526733B16B43D90D976EF55BE00A95C7846F447374451565D6470373096\
+C93448F390EBE47E63F22F1840AD1E006F09A85B75EB69DCA9D3D823F9D3F32D\
+81A03DB69CE3A9D35B7999B3F1F692F795805411762570D247B55F02EB64A3C9\
+CDE4EDF05BB008BE68863FA5A01E7BAC582B189A6C5D845E1216C91F2152B708\
+DAB6F985EF5E220C86D2B5CD50739F6A8F6E86527072777EB3940E8F12FDB8FF:\
+3F11982BD3DFBFFCDB49F3B4E401A004C42DB40DB314990413064C5B63D6E0D1\
+E1A5178FAB51AF92AE6B7184DDD06F76B6EF9366247A8CD5ABBE13C61468BFCD\
+BA7CD147EA543D567433E691EFBE80DDBBED90CD2F606EE4C36E568AA00EFDC7\
+8CC2D6F8F98C09E781B120421BF98A8EEB2A1064D93085105307A46CAC09B27B\
+4D1FDD6E3000574FA348D2632865D7958BF64A3A858A8605370F73DD82A1D79F\
+66071E312328BFB4D965BC51044DB4F981C00E23128AA00ABC3F908A2690E0:\
+142195F7212A66E8E79E6CBCBB092107C38051B998A46110A759B2DD35DB9371\
+68AB11CE2AF35F8C9263C585FAE7FFF37B9080F65B6AF33A983D8177455F9D90\
+5ACADB57DBFF67A27D4947C999A2B5CAD13BEDAF05BB2A197654740F54C932D8\
+4580F6B954F57C0A42317CC77036346CB8FB3BB07A72497C74BE7A454AA98BCD\
+458F85B323119565C650AE6F884BAD489BFE34B4A7116412E5FA6920355DCA65\
+24110068A5BFA93E1CACB6A9A3B4FF47A760107AE212279D86C1A333AAC0E7BE
+
+[DH/KDF2(SHA-1)]
+B842DBEC0BBC87979604EA9E14FEA8FB0DCB4BB09653621A7363A54A9DE9332B\
+1D878344D9D98BB06FD14C79315C7B097A7CEAAF4B0F66A422ADDFFF200CA78B:3:\
+7036B197651B364DFF16DCABAE5C6D:\
+9AA69B0066B495822A5586AF3FC19933E5EBF46B715B90DFBBD5393F58926AB3\
+8D02834A54E06798315558C7E274A193D5D9360AC855DA792BFCFE7FC635E213:\
+EDE06CF771:05
+
+C5344A976F327A107D669D4835946362AC3CC1B1198770826CE684958E70B288\
+E5FD065BD2368CB172391B8D046DB93FB1C3ACC0103435EBE8A75C706F63B8E3:3:\
+EFF15251EAB928852C16CA1517E1DC:\
+4772265D1FDB3FC3F2FFB5DFE863FE8D93E871D5B20D697A49BE130DB9B0561E\
+B118B8E8513CC9A6C07CA9647363CEDBF5C0AFDEF41AF7D6BC0F0E6BFAD50672:\
+02F0A9B8677D7874494627C1AE8B1507:16
+
+B9E01426AE646FF40980427636195AAA04DB2D9FC12ECDB4398812D1AE99B885\
+0396A2D6B0CFCFED532DA21A6DC58A491B75833985AF38D97727F44EFC8B2DB7:2:\
+E0E9E13CEE9C43CAE541A8ECD0FDAE:\
+9E549B7F385537D7CE2E0F332D6F98E5865DCA0E6C633B110CFAAB832B4EF75A\
+62617B58C33F9F4D0D957FB0218CB9363C2C6CC4C8DFCD9FDC35D401A69382E1:\
+6F6B153DC35648A59C2A43398318F90CC1015C:19
+
+6591F4A4899EE64DCADDE9E5ABF3A9BC409857F4F7372435F4A45C27E5B0C2CE\
+3E6E35D9FE555B49B80BC978D1B4E7EAFAF7C93A08FB3D9A48C59C9BC596C720B:3:\
+BAF42B613C37B6FB6409D33D9B89DB:\
+C275194FE458D0ED562103E3FE7765AF9639B1C826BD329A60028013B8EE48245\
+487A91EE6B221D29DD30D17FF0C35B55C3CA435BE482EED716A60D266D350A7:\
+5A70601B0668BA303F8FBFC90FBA82B9D589BD586C576B414A6AF17F9B386C7020:33
+
+# DLIES format is p:g:priv1:priv2:message:ciphertext
+
+# p and g are DH parameters
+# priv1 is the private key of the party encrypting the message
+# priv2 is the private key of the party decrypting the message
+
+# The underlying SVDP is Diffie-Hellman
+[DLIES/KDF2(SHA-1)/HMAC(SHA-1)/16]
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED\
+EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF:2:\
+A6963780ACB9D2C5C410D502AE60F027A807AB5BBE5:\
+88EF9E0354C67E9EB781A8BE95DD281A215CA1DCFD3:\
+AB5BBE0D:\
+538F9C9CAC3EEB460B6D40B4AC331EBD3E2F3065E515177F47A083D1AC71533B\
+F3B2931F52D71A99CA0804A633E1948F3B286453EA6CF0DD83C6DD1D2BD93B20\
+F4942D9679CFDE5856DD81E152E1E5ADD023324B945CE68425B025AE5D0CF86C\
+0D33244A60AF6045BD57018FFE5F84A9BF82193242FF32A64691586AAA298FE5\
+31CF06A56412DFEC3AD1F50FF8CD296310E5BB4D06E15AB0
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED\
+EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF:2:\
+C2D89AA7566998A9E90E22F9244C84F68B55473594C:\
+AF719F4ACF99CD35BB3B71F0DCBF27F6A4268D91264:\
+C43BB390:\
+C04F6BD6D1BFBDE74E775FB391A29B2D6FB7EE84C13D2061291DBA8708E406B0\
+A6788F69F7DFEBE4CA35B31917EACD7D36CDBEBDCC51567ADF3F287F57592A0F\
+73E1C990B807E0A67ACAE3F07361DF123C59E0A95CFCA9DEB3C7CCDC47C925F9\
+75AF0948B3DE9EC1E34EED30391FD4080D77DD07F091E3D5D89BC158A96485B2\
+8477AA95D62EFB9FA1D2B44A38A698F81C9518355BAE8B74
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF:2:\
+B8BBACE15066DF21FC2ADF8F2FB47776D98716F5:\
+EB2EDB317A29CE6BD580D1BBDBDA5585450D9B7B:\
+3B06E0705DC9DBA971AA624393984D5B:\
+2AB9B180CEF08E761EDB4D7B7C538FBA0FD37BACE9416789A0DD6551F2DDC602\
+5C76A663F1AAD5000EC03418A6220ABA6D3DC5EA82D7340E2FFCB5665AD3A222\
+3CDFF9C39889CBE31E44CD31BCFDCEFCF2A9916FD39E2720A7B826F7E6998F73\
+4F251C71DC970AF3FB12949C14AA759966733BFC976CAD0BE71FC5DBE285200E\
+75647C62
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF:2:\
+B2A1040661E071F702CB2190ACAF3CC532FE1DC2:\
+8A9B563FD9A12356EC7851943CF453AF7236A596:\
+DD92A05E19BBAD4A33CEFFA0FA2727E9:\
+3F0300C53C0BB02A3EF2EFCC751EE5D98AE991730C1C2FE39D11A74D32D892AD\
+63A9EECA09BBBE606FB426E03BBD480FD224E09712BB85FE649D543CBC23113A\
+39F9102C65D31DF330ADF233735C1D60D1BCDE22744392D2D9DE50393984F276\
+A33DD85F763ED1226B88DF1662554AD27820F66A995FE1481189A2B8C3071D0C\
+32EE9960
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF:2:\
+C56BAF8FAC2AB023B2995F5958D5E929C7501555:\
+9F48260F8B6FF09E0F71B97EFA50E2469F316C3D:\
+174E756AF8FFB51990BF3C69688D3A7F0B388F2BCE62A095BC12CD6DA2C2AD65:\
+B99BBBC64F6320060200E6FFE7D1FE6E5EEA79DF142111AF88D377037BD91863\
+41B7A7A27F2AE8BB77282B8EA13D821DD77186412CA3B9B5E1650A0D20687B1C\
+8D556FD7D547D475F71BBD7D6417311F535A9A6D95CEA8AFD1146B1A1741828E\
+8AD46B058507A67111CB62132350EEAC1212D90535677855E17B1DA9DC4CE790\
+C4B917B1359123226FE62DCCE5475721F09CEA23
+
+FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74\
+020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437\
+4FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF:2:\
+F54BB009FFFFD728677F76CFF2B1BDF05F24226C:\
+F6F5DFFCEA9F09A784C15BEACBDE88C0F58D19F7:\
+75DAD921764736E389C4224DAF7B278EC291E682044742E2E9C7A025B54DD62F:\
+C591E27A2C12742A959652F5F341F558CA0C7DAF2E6B5ACE32DCAAF459553BA2\
+3EF0235EAFD86A7F2D70587239D858484E5CD36122C2B9F6E410C7A9C307B2A2\
+A084BB1B634A15AC9F09E38EAF421D14C5A07B6EB5EDE6915E8DE9D3D9D01DBD\
+8822FBD79BA7FF3DF921B5451BBD9A12AB41FD4DAB829599BC2736B23753063C\
+0C5FFCBA7DB06DE26D3C441D126FC1A46531F593
diff --git a/botan/checks/timer.cpp b/botan/checks/timer.cpp
new file mode 100644
index 0000000..c42aaa4
--- /dev/null
+++ b/botan/checks/timer.cpp
@@ -0,0 +1,51 @@
+#include "timer.h"
+#include <iomanip>
+
+Timer::Timer(const std::string& n, u32bit e_mul) :
+ name(n), event_mult(e_mul)
+ {
+ time_used = 0;
+ timer_start = 0;
+ event_count = 0;
+ }
+
+void Timer::start()
+ {
+ stop();
+ timer_start = get_clock();
+ }
+
+void Timer::stop()
+ {
+ if(timer_start)
+ {
+ u64bit now = get_clock();
+
+ if(now > timer_start)
+ time_used += (now - timer_start);
+
+ timer_start = 0;
+ ++event_count;
+ }
+ }
+
+std::ostream& operator<<(std::ostream& out, Timer& timer)
+ {
+ //out << timer.value() << " ";
+
+ double events_per_second_fl =
+ static_cast<double>(timer.events() / timer.seconds());
+
+ u64bit events_per_second = static_cast<u64bit>(events_per_second_fl);
+
+ out << events_per_second << " " << timer.get_name() << " per second; ";
+
+ std::string op_or_ops = (timer.events() == 1) ? "op" : "ops";
+
+ out << std::setprecision(2) << std::fixed
+ << timer.ms_per_event() << " ms/op"
+ << " (" << timer.events() << " " << op_or_ops << " in "
+ << timer.milliseconds() << " ms)";
+
+ return out;
+ }
diff --git a/botan/checks/timer.h b/botan/checks/timer.h
new file mode 100644
index 0000000..48d6b68
--- /dev/null
+++ b/botan/checks/timer.h
@@ -0,0 +1,50 @@
+
+#ifndef BOTAN_BENCHMARK_TIMER_H__
+#define BOTAN_BENCHMARK_TIMER_H__
+
+#include <botan/types.h>
+#include <ostream>
+#include <string>
+
+using Botan::u64bit;
+using Botan::u32bit;
+
+class Timer
+ {
+ public:
+ static u64bit get_clock();
+
+ Timer(const std::string& name, u32bit event_mult = 1);
+
+ void start();
+
+ void stop();
+
+ u64bit value() { stop(); return time_used; }
+ double seconds() { return milliseconds() / 1000.0; }
+ double milliseconds() { return value() / 1000000.0; }
+
+ double ms_per_event() { return milliseconds() / events(); }
+ double seconds_per_event() { return seconds() / events(); }
+
+ u64bit events() const { return event_count * event_mult; }
+ std::string get_name() const { return name; }
+ private:
+ std::string name;
+ u64bit time_used, timer_start;
+ u64bit event_count, event_mult;
+ };
+
+inline bool operator<(const Timer& x, const Timer& y)
+ {
+ return (x.get_name() < y.get_name());
+ }
+
+inline bool operator==(const Timer& x, const Timer& y)
+ {
+ return (x.get_name() == y.get_name());
+ }
+
+std::ostream& operator<<(std::ostream&, Timer&);
+
+#endif
diff --git a/botan/checks/validate.cpp b/botan/checks/validate.cpp
new file mode 100644
index 0000000..8fb2251
--- /dev/null
+++ b/botan/checks/validate.cpp
@@ -0,0 +1,310 @@
+/*
+ Validation routines
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <cstdlib>
+
+#include <botan/filters.h>
+#include <botan/exceptn.h>
+using namespace Botan;
+
+#include "validate.h"
+#include "common.h"
+
+#define EXTRA_TESTS 0
+#define DEBUG 0
+
+namespace {
+
+u32bit random_word(Botan::RandomNumberGenerator& rng,
+ u32bit max)
+ {
+#if DEBUG
+ /* deterministic version for tracking down buffering bugs */
+ static bool first = true;
+ if(first) { srand(5); first = false; }
+
+ u32bit r = 0;
+ for(u32bit j = 0; j != 4; j++)
+ r = (r << 8) | std::rand();
+ return ((r % max) + 1); // return between 1 and max inclusive
+#else
+ /* normal version */
+ u32bit r = 0;
+ for(u32bit j = 0; j != 4; j++)
+ r = (r << 8) | rng.next_byte();
+ return ((r % max) + 1); // return between 1 and max inclusive
+#endif
+ }
+
+}
+
+Botan::Filter* lookup(const std::string&, const std::vector<std::string>&,
+ const std::string& = "All");
+
+bool failed_test(const std::string&, std::vector<std::string>, bool, bool,
+ const std::string&, std::string&,
+ Botan::RandomNumberGenerator& rng);
+
+std::vector<std::string> parse(const std::string&);
+void strip(std::string&);
+Botan::SecureVector<byte> decode_hex(const std::string&);
+
+u32bit do_validation_tests(const std::string& filename,
+ RandomNumberGenerator& rng,
+ bool should_pass)
+ {
+ std::ifstream test_data(filename.c_str());
+ bool first_mark = true;
+
+ if(!test_data)
+ throw Botan::Stream_IO_Error("Couldn't open test file " + filename);
+
+ u32bit errors = 0, alg_count = 0;
+ std::string algorithm;
+ std::string section;
+ std::string last_missing;
+ bool is_extension = false;
+ u32bit counter = 0;
+
+ while(!test_data.eof())
+ {
+ if(test_data.bad() || test_data.fail())
+ throw Botan::Stream_IO_Error("File I/O error reading from " +
+ filename);
+
+ std::string line;
+ std::getline(test_data, line);
+
+ const std::string MARK = "# MARKER: ";
+
+ if(line.find(MARK) != std::string::npos)
+ {
+ if(first_mark)
+ first_mark = false;
+ else if(should_pass)
+ std::cout << std::endl;
+ counter = 0;
+ section = line;
+ section.replace(section.find(MARK), MARK.size(), "");
+ if(should_pass)
+ std::cout << "Testing " << section << ": ";
+ }
+
+ strip(line);
+ if(line.size() == 0) continue;
+
+ // Do line continuation
+ while(line[line.size()-1] == '\\' && !test_data.eof())
+ {
+ line.replace(line.size()-1, 1, "");
+ std::string nextline;
+ std::getline(test_data, nextline);
+ strip(nextline);
+ if(nextline.size() == 0) continue;
+ line += nextline;
+ }
+
+ if(line[0] == '[' && line[line.size() - 1] == ']')
+ {
+ const std::string ext_mark = "<EXTENSION>";
+ algorithm = line.substr(1, line.size() - 2);
+ is_extension = false;
+ if(algorithm.find(ext_mark) != std::string::npos)
+ {
+ is_extension = true;
+ algorithm.replace(algorithm.find(ext_mark),
+ ext_mark.length(), "");
+ }
+
+#if DEBUG
+ if(should_pass)
+ std::cout << "Testing " << algorithm << "..." << std::endl;
+ else
+ std::cout << "Testing (expecing failure) "
+ << algorithm << "..." << std::endl;
+#endif
+ alg_count = 0;
+ continue;
+ }
+
+ std::vector<std::string> substr = parse(line);
+
+ alg_count++;
+
+ if(should_pass &&
+ (counter % 100 == 0 || (counter < 100 && counter % 10 == 0)))
+ {
+ std::cout << '.';
+ std::cout.flush();
+ }
+ counter++;
+
+ bool failed = true; // until proven otherwise
+
+ try
+ {
+ failed = failed_test(algorithm, substr,
+ is_extension, should_pass,
+ section, last_missing, rng);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ }
+
+ if(failed && should_pass)
+ {
+ std::cout << "ERROR: \"" << algorithm << "\" failed test #"
+ << alg_count << std::endl;
+ errors++;
+ }
+
+ if(!failed && !should_pass)
+ {
+ std::cout << "ERROR: \"" << algorithm << "\" passed test #"
+ << alg_count << " (unexpected pass)" << std::endl;
+ errors++;
+ }
+
+ }
+ if(should_pass)
+ std::cout << std::endl;
+ return errors;
+ }
+
+bool failed_test(const std::string& algo,
+ std::vector<std::string> params,
+ bool is_extension, bool exp_pass,
+ const std::string& section,
+ std::string& last_missing,
+ Botan::RandomNumberGenerator& rng)
+ {
+#if DEBUG
+ std::cout << "Testing: " << algo;
+ if(!exp_pass)
+ std::cout << " (expecting failure)";
+ std::cout << std::endl;
+#endif
+
+#if !EXTRA_TESTS
+ if(!exp_pass) return true;
+#endif
+
+ const std::string in = params[0];
+ const std::string expected = params[1];
+
+ params.erase(params.begin());
+ params.erase(params.begin());
+
+ if(in.size() % 2 == 1)
+ {
+ std::cout << "Can't have an odd sized hex string!" << std::endl;
+ return true;
+ }
+
+ Botan::Pipe pipe;
+
+ try {
+ Botan::Filter* test = lookup(algo, params, section);
+ if(test == 0 && is_extension) return !exp_pass;
+ if(test == 0)
+ {
+ if(algo != last_missing)
+ {
+ std::cout << "WARNING: \"" + algo + "\" is not a known "
+ << "algorithm name." << std::endl;
+ last_missing = algo;
+ }
+ return 0;
+ }
+
+ pipe.reset();
+ pipe.append(test);
+ pipe.append(new Botan::Hex_Encoder);
+
+ Botan::SecureVector<byte> data = decode_hex(in);
+ const byte* data_ptr = data;
+
+ // this can help catch errors with buffering, etc
+ u32bit len = data.size();
+ pipe.start_msg();
+ while(len)
+ {
+ u32bit how_much = random_word(rng, len);
+ pipe.write(data_ptr, how_much);
+ data_ptr += how_much;
+ len -= how_much;
+ }
+ pipe.end_msg();
+ }
+ catch(Botan::Algorithm_Not_Found& e)
+ {
+ std::cout << "Algorithm not found: " << e.what() << std::endl;
+ return false;
+ }
+ catch(Botan::Exception& e)
+ {
+ if(exp_pass || DEBUG)
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return true;
+ }
+ catch(std::exception& e)
+ {
+ if(exp_pass || DEBUG)
+ std::cout << "Standard library exception caught: "
+ << e.what() << std::endl;
+ return true;
+ }
+ catch(...)
+ {
+ if(exp_pass || DEBUG)
+ std::cout << "Unknown exception caught." << std::endl;
+ return true;
+ }
+
+ std::string output;
+
+ if(pipe.remaining())
+ {
+ /* Test peeking at an offset in Pipe/SecureQueue */
+ u32bit offset = random_word(rng, pipe.remaining() - 1);
+ u32bit length = random_word(rng, pipe.remaining() - offset);
+
+ Botan::SecureVector<byte> peekbuf(length);
+ pipe.peek(peekbuf, length, offset);
+
+ output = pipe.read_all_as_string();
+
+ bool OK = true;
+
+ for(u32bit j = offset; j != offset+length; j++)
+ if(static_cast<byte>(output[j]) != peekbuf[j-offset])
+ OK = false;
+
+ if(!OK)
+ throw Botan::Self_Test_Failure("Peek testing failed in validate.cpp");
+ }
+
+ if(output == expected && !exp_pass)
+ {
+ std::cout << "FAILED: " << expected << " == " << std::endl
+ << " " << output << std::endl;
+ return false;
+ }
+
+ if(output != expected && exp_pass)
+ {
+ std::cout << "\nFAILED: " << expected << " != " << std::endl
+ << " " << output << std::endl;
+ return true;
+ }
+
+ if(output != expected && !exp_pass) return true;
+
+ return false;
+ }
diff --git a/botan/checks/validate.dat b/botan/checks/validate.dat
new file mode 100644
index 0000000..675e1af
--- /dev/null
+++ b/botan/checks/validate.dat
@@ -0,0 +1,45951 @@
+# Main Botan validation file
+
+# This has test vectors for block ciphers in ECB mode, stream ciphers, hash
+# functions, MACs, KDFs, S2K algorithms, encoders/decoders, and block cipher
+# modes (CBC, CTS, CFB, OFB, CTR, and EAX)
+
+# MARKER: Block Ciphers
+
+# Block cipher format is plaintext:ciphertext:key
+
+[AES]
+# From the AES documentation for Rijndael
+506812A45F08C889B97F5980038B8359:D8F532538289EF7D06B506A4FD5BE9C9:\
+00010203050607080A0B0C0D0F101112
+
+5C6D71CA30DE8B8B00549984D2EC7D4B:59AB30F4D4EE6E4FF9907EF65B1FB68C:\
+14151617191A1B1C1E1F202123242526
+
+53F3F4C64F8616E4E7C56199F48F21F6:BF1ED2FCB2AF3FD41443B56D85025CB1:\
+28292A2B2D2E2F30323334353738393A
+
+A1EB65A3487165FB0F1C27FF9959F703:7316632D5C32233EDCB0780560EAE8B2:\
+3C3D3E3F41424344464748494B4C4D4E
+
+3553ECF0B1739558B08E350A98A39BFA:408C073E3E2538072B72625E68B8364B:\
+50515253555657585A5B5C5D5F606162
+
+67429969490B9711AE2B01DC497AFDE8:E1F94DFA776597BEACA262F2F6366FEA:\
+64656667696A6B6C6E6F707173747576
+
+93385C1F2AEC8BED192F5A8E161DD508:F29E986C6A1C27D7B29FFD7EE92B75F1:\
+78797A7B7D7E7F80828384858788898A
+
+B5BF946BE19BEB8DB3983B5F4C6E8DDB:131C886A57F8C2E713ABA6955E2B55B5:\
+8C8D8E8F91929394969798999B9C9D9E
+
+41321EE10E21BD907227C4450FF42324:D2AB7662DF9B8C740210E5EEB61C199D:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+
+00A82F59C91C8486D12C0A80124F6089:14C10554B2859C484CAB5869BBE7C470:\
+B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+7CE0FD076754691B4BBD9FAF8A1372FE:DB4D498F0A49CF55445D502C1F9AB3B5:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+
+23605A8243D07764541BC5AD355B3129:6D96FEF7D66590A77A77BB2056667F7F:\
+DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+12A8CFA23EA764FD876232B4E842BC44:316FB68EDBA736C53E78477BF913725C:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE010002
+
+BCAF32415E8308B3723E5FDD853CCC80:6936F2B93AF8397FD3A771FC011C8C37:\
+04050607090A0B0C0E0F101113141516
+
+89AFAE685D801AD747ACE91FC49ADDE0:F3F92F7A9C59179C1FCC2C2BA0B082CD:\
+2C2D2E2F31323334363738393B3C3D3E
+
+F521D07B484357C4A69E76124A634216:6A95EA659EE3889158E7A9152FF04EBC:\
+40414243454647484A4B4C4D4F505152
+
+3E23B3BC065BCC152407E23896D77783:1959338344E945670678A5D432C90B93:\
+54555657595A5B5C5E5F606163646566
+
+79F0FBA002BE1744670E7E99290D8F52:E49BDDD2369B83EE66E6C75A1161B394:\
+68696A6B6D6E6F70727374757778797A
+
+DA23FE9D5BD63E1D72E3DAFBE21A6C2A:D3388F19057FF704B70784164A74867D:\
+7C7D7E7F81828384868788898B8C8D8E
+
+E3F5698BA90B6A022EFD7DB2C7E6C823:23AA03E2D5E4CD24F3217E596480D1E1:\
+A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+BDC2691D4F1B73D2700679C3BCBF9C6E:C84113D68B666AB2A50A8BDB222E91B9:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+
+BA74E02093217EE1BA1B42BD5624349A:AC02403981CD4340B507963DB65CB7B6:\
+08090A0B0D0E0F10121314151718191A
+
+B5C593B5851C57FBF8B3F57715E8F680:8D1299236223359474011F6BF5088414:\
+6C6D6E6F71727374767778797B7C7D7E
+
+3DA9BD9CEC072381788F9387C3BBF4EE:5A1D6AB8605505F7977E55B9A54D9B90:\
+80818283858687888A8B8C8D8F909192
+
+4197F3051121702AB65D316B3C637374:72E9C2D519CF555E4208805AABE3B258:\
+94959697999A9B9C9E9FA0A1A3A4A5A6
+
+9F46C62EC4F6EE3F6E8C62554BC48AB7:A8F3E81C4A23A39EF4D745DFFE026E80:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+
+0220673FE9E699A4EBC8E0DBEB6979C8:546F646449D31458F9EB4EF5483AEE6C:\
+BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+B2B99171337DED9BC8C2C23FF6F18867:4DBE4BC84AC797C0EE4EFB7F1A07401C:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+
+A7FACF4E301E984E5EFEEFD645B23505:25E10BFB411BBD4D625AC8795C8CA3B3:\
+E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+F7C762E4A9819160FD7ACFB6C4EEDCDD:315637405054EC803614E43DEF177579:\
+F8F9FAFBFDFEFE00020304050708090A
+
+9B64FC21EA08709F4915436FAA70F1BE:60C5BC8A1410247295C6386C59E572A8:\
+0C0D0E0F11121314161718191B1C1D1E
+
+52AF2C3DE07EE6777F55A4ABFC100B3F:01366FC8CA52DFE055D6A00A76471BA6:\
+20212223252627282A2B2C2D2F303132
+
+2FCA001224386C57AA3F968CBE2C816F:ECC46595516EC612449C3F581E7D42FF:\
+34353637393A3B3C3E3F404143444546
+
+4149C73658A4A9C564342755EE2C132F:6B7FFE4C602A154B06EE9C7DAB5331C9:\
+48494A4B4D4E4F50525354555758595A
+
+AF60005A00A1772F7C07A48A923C23D2:7DA234C14039A240DD02DD0FBF84EB67:\
+5C5D5E5F61626364666768696B6C6D6E
+
+6FCCBC28363759914B6F0280AFAF20C6:C7DC217D9E3604FFE7E91F080ECD5A3A:\
+70717273757677787A7B7C7D7F808182
+
+7D82A43DDF4FEFA2FC5947499884D386:37785901863F5C81260EA41E7580CDA5:\
+84858687898A8B8C8E8F909193949596
+
+5D5A990EAAB9093AFE4CE254DFA49EF9:A07B9338E92ED105E6AD720FCCCE9FE4:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+
+4CD1E2FD3F4434B553AAE453F0ED1A02:AE0FB9722418CC21A7DA816BBC61322C:\
+ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+5A2C9A9641D4299125FA1B9363104B5E:C826A193080FF91FFB21F71D3373C877:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+
+B517FE34C0FA217D341740BFD4FE8DD4:1181B11B0E494E8D8B0AA6B1D5AC2C48:\
+D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+014BAF2278A69D331D5180103643E99A:6743C3D1519AB4F2CD9A78AB09A511BD:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
+
+B529BD8164F20D0AA443D4932116841C:DC55C076D52BACDF2EEFD952946A439D:\
+FCFDFEFF01020304060708090B0C0D0E
+
+2E596DCBB2F33D4216A1176D5BD1E456:711B17B590FFC72B5C8E342B601E8003:\
+10111213151617181A1B1C1D1F202122
+
+7274A1EA2B7EE2424E9A0E4673689143:19983BB0950783A537E1339F4AA21C75:\
+24252627292A2B2C2E2F303133343536
+
+AE20020BD4F13E9D90140BEE3B5D26AF:3BA7762E15554169C0F4FA39164C410C:\
+38393A3B3D3E3F40424344454748494A
+
+BAAC065DA7AC26E855E79C8849D75A02:A0564C41245AFCA7AF8AA2E0E588EA89:\
+4C4D4E4F51525354565758595B5C5D5E
+
+7C917D8D1D45FAB9E2540E28832540CC:5E36A42A2E099F54AE85ECD92E2381ED:\
+60616263656667686A6B6C6D6F707172
+
+BDE6F89E16DAADB0E847A2A614566A91:770036F878CD0F6CA2268172F106F2FE:\
+74757677797A7B7C7E7F808183848586
+
+C9DE163725F1F5BE44EBB1DB51D07FBC:7E4E03908B716116443CCF7C94E7C259:\
+88898A8B8D8E8F90929394959798999A
+
+3AF57A58F0C07DFFA669572B521E2B92:482735A48C30613A242DD494C7F9185D:\
+9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+3D5EBAC306DDE4604F1B4FBBBFCDAE55:B4C0F6C9D4D7079ADDF9369FC081061D:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+
+C2DFA91BCEB76A1183C995020AC0B556:D5810FE0509AC53EDCD74F89962E6270:\
+C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+C70F54305885E9A0746D01EC56C8596B:03F17A16B3F91848269ECDD38EBB2165:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA
+
+C4F81B610E98012CE000182050C0C2B2:DA1248C3180348BAD4A93B4D9856C9DF:\
+ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+EAAB86B1D02A95D7404EFF67489F97D4:3D10D7B63F3452C06CDF6CCE18BE0C2C:\
+00010203050607080A0B0C0D0F101112
+
+7C55BDB40B88870B52BEC3738DE82886:4AB823E7477DFDDC0E6789018FCB6258:\
+14151617191A1B1C1E1F202123242526
+
+BA6EAA88371FF0A3BD875E3F2A975CE0:E6478BA56A77E70CFDAA5C843ABDE30E:\
+28292A2B2D2E2F30323334353738393A
+
+08059130C4C24BD30CF0575E4E0373DC:1673064895FBEAF7F09C5429FF75772D:\
+3C3D3E3F41424344464748494B4C4D4E
+
+9A8EAB004EF53093DFCF96F57E7EDA82:4488033AE9F2EFD0CA9383BFCA1A94E9:\
+50515253555657585A5B5C5D5F606162
+
+0745B589E2400C25F117B1D796C28129:978F3B8C8F9D6F46626CAC3C0BCB9217:\
+64656667696A6B6C6E6F707173747576
+
+2F1777781216CEC3F044F134B1B92BBE:E08C8A7E582E15E5527F1D9E2EECB236:\
+78797A7B7D7E7F80828384858788898A
+
+353A779FFC541B3A3805D90CE17580FC:CEC155B76AC5FFDA4CF4F9CA91E49A7A:\
+8C8D8E8F91929394969798999B9C9D9E
+
+1A1EAE4415CEFCF08C4AC1C8F68BEA8F:D5AC7165763225DD2A38CDC6862C29AD:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+
+E6E7E4E5B0B3B2B5D4D5AAAB16111013:03680FE19F7CE7275452020BE70E8204:\
+B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+F8F9FAFBFBF8F9E677767170EFE0E1E2:461DF740C9781C388E94BB861CEB54F6:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+
+63626160A1A2A3A445444B4A75727370:451BD60367F96483042742219786A074:\
+DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+717073720605040B2D2C2B2A05FAFBF9:E4DFA42671A02E57EF173B85C0EA9F2B:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE010002
+
+78797A7BEAE9E8EF3736292891969794:ED11B89E76274282227D854700A78B9E:\
+04050607090A0B0C0E0F101113141516
+
+838281803231300FDDDCDBDAA0AFAEAD:433946EAA51EA47AF33895F2B90B3B75:\
+18191A1B1D1E1F20222324252728292A
+
+18191A1BBFBCBDBA75747B7A7F78797A:6BC6D616A5D7D0284A5910AB35022528:\
+2C2D2E2F31323334363738393B3C3D3E
+
+848586879B989996A3A2A5A4849B9A99:D2A920ECFE919D354B5F49EAE9719C98:\
+40414243454647484A4B4C4D4F505152
+
+0001020322212027CACBF4F551565754:3A061B17F6A92885EFBD0676985B373D:\
+54555657595A5B5C5E5F606163646566
+
+CECFCCCDAFACADB2515057564A454447:FADEEC16E33EA2F4688499D157E20D8F:\
+68696A6B6D6E6F70727374757778797A
+
+92939091CDCECFC813121D1C80878685:5CDEFEDE59601AA3C3CDA36FA6B1FA13:\
+7C7D7E7F81828384868788898B8C8D8E
+
+D2D3D0D16F6C6D6259585F5ED1EEEFEC:9574B00039844D92EBBA7EE8719265F8:\
+90919293959697989A9B9C9D9FA0A1A2
+
+ACADAEAF878485820F0E1110D5D2D3D0:9A9CF33758671787E5006928188643FA:\
+A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+9091929364676619E6E7E0E1757A7B78:2CDDD634C846BA66BB46CBFEA4A674F9:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA
+
+BABBB8B98A89888F74757A7B92959497:D28BAE029393C3E7E26E9FAFBBB4B98F:\
+CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+8D8C8F8E6E6D6C633B3A3D3CCAD5D4D7:EC27529B1BEE0A9AB6A0D73EBC82E9B7:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+
+86878485010203040808F7F767606162:3CB25C09472AFF6EE7E2B47CCD7CCB17:\
+F4F5F6F7F9FAFBFCFEFE010103040506
+
+8E8F8C8D656667788A8B8C8D010E0F0C:DEE33103A7283370D725E44CA38F8FE5:\
+08090A0B0D0E0F10121314151718191A
+
+C8C9CACB858687807A7B7475E7E0E1E2:27F9BCD1AAC64BFFC11E7815702C1A69:\
+1C1D1E1F21222324262728292B2C2D2E
+
+6D6C6F6E5053525D8C8D8A8BADD2D3D0:5DF534FFAD4ED0749A9988E9849D0021:\
+30313233353637383A3B3C3D3F404142
+
+28292A2B393A3B3C0607181903040506:A48BEE75DB04FB60CA2B80F752A8421B:\
+44454647494A4B4C4E4F505153545556
+
+A5A4A7A6B0B3B28DDBDADDDCBDB2B3B0:024C8CF70BC86EE5CE03678CB7AF45F9:\
+58595A5B5D5E5F60626364656768696A
+
+323330316467666130313E3F2C2B2A29:3C19AC0F8A3A3862CE577831301E166B:\
+6C6D6E6F71727374767778797B7C7D7E
+
+27262524080B0A05171611100B141516:C5E355B796A57421D59CA6BE82E73BCA:\
+80818283858687888A8B8C8D8F909192
+
+040506074142434435340B0AA3A4A5A6:D94033276417ABFB05A69D15B6E386E2:\
+94959697999A9B9C9E9FA0A1A3A4A5A6
+
+242526271112130C61606766BDB2B3B0:24B36559EA3A9B9B958FE6DA3E5B8D85:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+
+4B4A4948252627209E9F9091CEC9C8CB:20FD4FEAA0E8BF0CCE7861D74EF4CB72:\
+BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+68696A6B6665646B9F9E9998D9E6E7E4:350E20D5174277B9EC314C501570A11D:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+
+34353637C5C6C7C0F0F1EEEF7C7B7A79:87A29D61B7C604D238FE73045A7EFD57:\
+E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+32333031C2C1C13F0D0C0B0A050A0B08:2C3164C1CC7D0064816BDC0FAA362C52:\
+F8F9FAFBFDFEFE00020304050708090A
+
+CDCCCFCEBEBDBCBBABAAA5A4181F1E1D:195FE5E8A05A2ED594F6E4400EEE10B3:\
+0C0D0E0F11121314161718191B1C1D1E
+
+212023223635343BA0A1A6A7445B5A59:E4663DF19B9A21A5A284C2BD7F905025:\
+20212223252627282A2B2C2D2F303132
+
+0E0F0C0DA8ABAAAD2F2E515002050407:21B88714CFB4E2A933BD281A2C4743FD:\
+34353637393A3B3C3E3F404143444546
+
+070605042A2928378E8F8889BDB2B3B0:CBFC3980D704FD0FC54378AB84E17870:\
+48494A4B4D4E4F50525354555758595A
+
+CBCAC9C893909196A9A8A7A6A5A2A3A0:BC5144BAA48BDEB8B63E22E03DA418EF:\
+5C5D5E5F61626364666768696B6C6D6E
+
+80818283C1C2C3CC9C9D9A9B0CF3F2F1:5A1DBAEF1EE2984B8395DA3BDFFA3CCC:\
+70717273757677787A7B7C7D7F808182
+
+1213101125262720FAFBE4E5B1B6B7B4:F0B11CD0729DFCC80CEC903D97159574:\
+84858687898A8B8C8E8F909193949596
+
+7F7E7D7C3033320D97969190222D2C2F:9F95314ACFDDC6D1914B7F19A9CC8209:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+
+4E4F4C4D484B4A4D81808F8E53545556:595736F6F0F70914A94E9E007F022519:\
+ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+DCDDDEDFB0B3B2BD15141312A1BEBFBC:1F19F57892CAE586FCDFB4C694DEB183:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+
+93929190282B2A2DC4C5FAFB92959497:540700EE1F6F3DAB0B3EDDF6CAEE1EF5:\
+D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+F5F4F7F6C4C7C6D9373631307E717073:14A342A91019A331687A2254E6626CA2:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
+
+93929190B6B5B4B364656A6B05020300:7B25F3C3B2EEA18D743EF283140F29FF:\
+FCFDFEFF01020304060708090B0C0D0E
+
+BABBB8B90D0E0F00A4A5A2A3043B3A39:46C2587D66E5E6FA7F7CA6411AD28047:\
+10111213151617181A1B1C1D1F202122
+
+D8D9DADB7F7C7D7A10110E0F787F7E7D:09470E72229D954ED5EE73886DFEEBA9:\
+24252627292A2B2C2E2F303133343536
+
+FEFFFCFDEFECED923B3A3D3C6768696A:D77C03DE92D4D0D79EF8D4824EF365EB:\
+38393A3B3D3E3F40424344454748494A
+
+D6D7D4D58A89888F96979899A5A2A3A0:1D190219F290E0F1715D152D41A23593:\
+4C4D4E4F51525354565758595B5C5D5E
+
+18191A1BA8ABAAA5303136379B848586:A2CD332CE3A0818769616292E87F757B:\
+60616263656667686A6B6C6D6F707172
+
+6B6A6968A4A7A6A1D6D72829B0B7B6B5:D54AFA6CE60FBF9341A3690E21385102:\
+74757677797A7B7C7E7F808183848586
+
+000102038A89889755545352A6A9A8AB:06E5C364DED628A3F5E05E613E356F46:\
+88898A8B8D8E8F90929394959798999A
+
+2D2C2F2EB3B0B1B6B6B7B8B9F2F5F4F7:EAE63C0E62556DAC85D221099896355A:\
+9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+979695943536373856575051E09F9E9D:1FED060E2C6FC93EE764403A889985A2:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+
+A4A5A6A7989B9A9DB1B0AFAE7A7D7C7F:C25235C1A30FDEC1C7CB5C5737B2A588:\
+C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+C1C0C3C2686B6A55A8A9AEAFEAE5E4E7:796DBEF95147D4D30873AD8B7B92EFC0:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA
+
+C1C0C3C2141716118C8D828364636261:CBCF0FB34D98D0BD5C22CE37211A46BF:\
+ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+93929190CCCFCEC196979091E0FFFEFD:94B44DA6466126CAFA7C7FD09063FC24:\
+00010203050607080A0B0C0D0F101112
+
+B4B5B6B7F9FAFBFC25241B1A6E69686B:D78C5B5EBF9B4DBDA6AE506C5074C8FE:\
+14151617191A1B1C1E1F202123242526
+
+868784850704051AC7C6C1C08788898A:6C27444C27204B043812CF8CF95F9769:\
+28292A2B2D2E2F30323334353738393A
+
+F4F5F6F7AAA9A8AFFDFCF3F277707172:BE94524EE5A2AA50BBA8B75F4C0AEBCF:\
+3C3D3E3F41424344464748494B4C4D4E
+
+D3D2D1D00605040BC3C2C5C43E010003:A0AEAAE91BA9F31F51AEB3588CF3A39E:\
+50515253555657585A5B5C5D5F606162
+
+73727170424140476A6B74750D0A0B08:275297779C28266EF9FE4C6A13C08488:\
+64656667696A6B6C6E6F707173747576
+
+C2C3C0C10A0908F754555253A1AEAFAC:86523D92BB8672CB01CF4A77FD725882:\
+78797A7B7D7E7F80828384858788898A
+
+6D6C6F6EF8FBFAFD82838C8DF8FFFEFD:4B8327640E9F33322A04DD96FCBF9A36:\
+8C8D8E8F91929394969798999B9C9D9E
+
+F5F4F7F684878689A6A7A0A1D2CDCCCF:CE52AF650D088CA559425223F4D32694:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+
+2D33EEF2C0430A8A9EBF45E809C40BB6:DFF4945E0336DF4C1C56BC700EFF837F:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C
+
+6AA375D1FA155A61FB72353E0A5A8756:B6FDDEF4752765E347D5D2DC196D1252:\
+1E1F20212324252628292A2B2D2E2F30323334353738393A
+
+BC3736518B9490DCB8ED60EB26758ED4:D23684E3D963B3AFCF1A114ACA90CBD6:\
+3C3D3E3F41424344464748494B4C4D4E5051525355565758
+
+AA214402B46CFFB9F761EC11263A311E:3A7AC027753E2A18C2CEAB9E17C11FD0:\
+5A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+02AEA86E572EEAB66B2C3AF5E9A46FD6:8F6786BD007528BA26603C1601CDD0D8:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394
+
+E2AEF6ACC33B965C4FA1F91C75FF6F36:D17D073B01E71502E28B47AB551168B3:\
+969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+
+0659DF46427162B9434865DD9499F91D:A469DA517119FAB95876F41D06D40FFA:\
+B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0
+
+49A44239C748FEB456F59C276A5658DF:6091AA3B695C11F5C0B6AD26D3D862FF:\
+D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+66208F6E9D04525BDEDB2733B6A6BE37:70F9E67F9F8DF1294131662DC6E69364:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C
+
+3393F8DFC729C97F5480B950BC9666B0:D154DCAFAD8B207FA5CBC95E9996B559:\
+0E0F10111314151618191A1B1D1E1F20222324252728292A
+
+606834C8CE063F3234CF1145325DBD71:4934D541E8B46FA339C805A7AEB9E5DA:\
+2C2D2E2F31323334363738393B3C3D3E4041424345464748
+
+FEC1C04F529BBD17D8CECFCC4718B17F:62564C738F3EFE186E1A127A0C4D3C61:\
+4A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+32DF99B431ED5DC5ACF8CAF6DC6CE475:07805AA043986EB23693E23BEF8F3438:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384
+
+7FDC2B746F3F665296943B83710D1F82:DF0B4931038BADE848DEE3B4B85AA44B:\
+868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2
+
+8FBA1510A3C5B87E2EAA3F7A91455CA2:592D5FDED76582E4143C65099309477C:\
+A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0
+
+2C9B468B1C2EED92578D41B0716B223B:C9B8D6545580D3DFBCDD09B954ED4E92:\
+C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+0A2BBF0EFC6BC0034F8A03433FCA1B1A:5DCCD5D6EB7C1B42ACB008201DF707A0:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFC
+
+25260E1F31F4104D387222E70632504B:A2A91682FFEB6ED1D34340946829E6F9:\
+FEFE01010304050608090A0B0D0E0F10121314151718191A
+
+C527D25A49F08A5228D338642AE65137:E45D185B797000348D9267960A68435D:\
+1C1D1E1F21222324262728292B2C2D2E3031323335363738
+
+3B49FC081432F5890D0E3D87E884A69E:45E060DAE5901CDA8089E10D4F4C246B:\
+3A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+
+D173F9ED1E57597E166931DF2754A083:F6951AFACC0079A369C71FDCFF45DF50:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374
+
+8C2B7CAFA5AFE7F13562DAEAE1ADEDE0:9E95E00F351D5B3AC3D0E22E626DDAD6:\
+767778797B7C7D7E80818283858687888A8B8C8D8F909192
+
+AAF4EC8C1A815AEB826CAB741339532C:9CB566FF26D92DAD083B51FDC18C173C:\
+94959697999A9B9C9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0
+
+40BE8C5D9108E663F38F1A2395279ECF:C9C82766176A9B228EB9A974A010B4FB:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBEC
+
+0C8AD9BC32D43E04716753AA4CFBE351:D8E26AA02945881D5137F1C1E1386E88:\
+2A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+
+1407B1D5F87D63357C8DC7EBBAEBBFEE:C0E024CCD68FF5FFA4D139C355A77C55:\
+48494A4B4D4E4F50525354555758595A5C5D5E5F61626364
+
+E62734D1AE3378C4549E939E6F123416:0B18B3D16F491619DA338640DF391D43:\
+84858687898A8B8C8E8F90919394959698999A9B9D9E9FA0
+
+5A752CFF2A176DB1A1DE77F2D2CDEE41:DBE09AC8F66027BF20CB6E434F252EFC:\
+A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+A9C8C3A4EABEDC80C64730DDD018CD88:6D04E5E43C5B9CBE05FEB9606B6480FE:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDC
+
+EE9B3DBBDB86180072130834D305999A:DD1D6553B96BE526D9FEE0FBD7176866:\
+1A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+
+A7FA8C3586B8EBDE7568EAD6F634A879:0260CA7E3F979FD015B0DD4690E16D2A:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354
+
+37E0F4A87F127D45AC936FE7AD88C10A:9893734DE10EDCC8A67C3B110B8B8CC6:\
+929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+3F77D8B5D92BAC148E4E46F697A535C5:93B30B750516B2D18808D710C2EE84EF:\
+464748494B4C4D4E50515253555657585A5B5C5D5F606162
+
+D25EBB686C40F7E2C4DA1014936571CA:16F65FA47BE3CB5E6DFE7C6C37016C0E:\
+828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+4F1C769D1E5B0552C7ECA84DEA26A549:F3847210D5391E2360608E5ACB560581:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBC
+
+8548E2F882D7584D0FAFC54372B6633A:8754462CD223366D0753913E6AF2643D:\
+BEBFC0C1C3C4C5C6C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA
+
+87D7A336CB476F177CD2A51AF2A62CDF:1EA20617468D1B806A1FD58145462017:\
+DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8
+
+03B1FEAC668C4E485C1065DFC22B44EE:3B155D927355D737C6BE9DDA60136E2E:\
+FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+
+BDA15E66819FA72D653A6866AA287962:26144F7B66DAA91B6333DBD3850502B3:\
+18191A1B1D1E1F20222324252728292A2C2D2E2F31323334
+
+4D0C7A0D2505B80BF8B62CEB12467F0A:E4F9A4AB52CED8134C649BF319EBCC90:\
+363738393B3C3D3E40414243454647484A4B4C4D4F505152
+
+626D34C9429B37211330986466B94E5F:B9DDD29AC6128A6CAB121E34A4C62B36:\
+54555657595A5B5C5E5F60616364656668696A6B6D6E6F70
+
+333C3E6BF00656B088A17E5FF0E7F60A:6FCDDAD898F2CE4EFF51294F5EAAF5C9:\
+727374757778797A7C7D7E7F81828384868788898B8C8D8E
+
+687ED0CDC0D2A2BC8C466D05EF9D2891:C9A6FE2BF4028080BEA6F7FC417BD7E3:\
+90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABAC
+
+487830E78CC56C1693E64B2A6660C7B6:6A2026846D8609D60F298A9C0673127F:\
+AEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA
+
+7A48D6B7B52B29392AA2072A32B66160:2CB25C005E26EFEA44336C4C97A4240B:\
+CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8
+
+907320E64C8C5314D10F8D7A11C8618D:496967AB8680DDD73D09A0E4C7DCC8AA:\
+EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+
+B561F2CA2D6E65A4A98341F3ED9FF533:D5AF94DE93487D1F3A8C577CB84A66A4:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324
+
+DF769380D212792D026F049E2E3E48EF:84BDAC569CAE2828705F267CC8376E90:\
+262728292B2C2D2E30313233353637383A3B3C3D3F404142
+
+79F374BC445BDABF8FCCB8843D6054C6:F7401DDA5AD5AB712B7EB5D10C6F99B6:\
+44454647494A4B4C4E4F50515354555658595A5B5D5E5F60
+
+4E02F1242FA56B05C68DBAE8FE44C9D6:1C9D54318539EBD4C3B5B7E37BF119F0:\
+626364656768696A6C6D6E6F71727374767778797B7C7D7E
+
+CF73C93CBFF57AC635A6F4AD2A4A1545:ACA572D65FB2764CFFD4A6ECA090EA0D:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C
+
+9923548E2875750725B886566784C625:36D9C627B8C2A886A10CCB36EAE3DFBB:\
+9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA
+
+4888336B723A022C9545320F836A4207:010EDBF5981E143A81D646E597A4A568:\
+BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8
+
+F84D9A5561B0608B1160DEE000C41BA8:8DB44D538DC20CC2F40F3067FD298E60:\
+DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+C23192A0418E30A19B45AE3E3625BF22:930EB53BC71E6AC4B82972BDCD5AAFB3:\
+F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314
+
+B84E0690B28B0025381AD82A15E501A7:6C42A81EDCBC9517CCD89C30C95597B4:\
+161718191B1C1D1E20212223252627282A2B2C2D2F303132
+
+ACEF5E5C108876C4F06269F865B8F0B0:DA389847AD06DF19D76EE119C71E1DD3:\
+34353637393A3B3C3E3F40414344454648494A4B4D4E4F50
+
+0F1B3603E0F5DDEA4548246153A5E064:E018FDAE13D3118F9A5D1A647A3F0462:\
+525354555758595A5C5D5E5F61626364666768696B6C6D6E
+
+FBB63893450D42B58C6D88CD3C1809E3:2AA65DB36264239D3846180FABDFAD20:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C
+
+4BEF736DF150259DAE0C91354E8A5F92:1472163E9A4F780F1CEB44B07ECF4FDB:\
+8E8F90919394959698999A9B9D9E9FA0A2A3A4A5A7A8A9AA
+
+7D2D46242056EF13D3C3FC93C128F4C7:C8273FDC8F3A9F72E91097614B62397C:\
+ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8
+
+E9C1BA2DF415657A256EDB33934680FD:66C8427DCD733AAF7B3470CB7D976E3F:\
+CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+E23EE277B0AA0A1DFB81F7527C3514F1:146131CB17F1424D4F8DA91E6F80C1D0:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304
+
+3E7445B0B63CAAF75E4A911E12106B4C:2610D0AD83659081AE085266A88770DC:\
+060708090B0C0D0E10111213151617181A1B1C1D1F202122
+
+767774752023222544455A5BE6E1E0E3:38A2B5A974B0575C5D733917FB0D4570:\
+24252627292A2B2C2E2F30313334353638393A3B3D3E3F40
+
+72737475717E7F7CE9E8EBEA696A6B6C:E21D401EBC60DE20D6C486E4F39A588B:\
+424344454748494A4C4D4E4F51525354565758595B5C5D5E
+
+DFDEDDDC25262728C9C8CFCEF1EEEFEC:E51D5F88C670B079C0CA1F0C2C4405A2:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C
+
+FFFE0100707776755F5E5D5C7675746B:246A94788A642FB3D1B823C8762380C8:\
+7E7F80818384858688898A8B8D8E8F90929394959798999A
+
+E0E1E2E3424140479F9E9190292E2F2C:B80C391C5C41A4C3B30C68E0E3D7550F:\
+9C9D9E9FA1A2A3A4A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8
+
+2120272690EFEEED3B3A39384E4D4C4B:B77C4754FC64EB9A1154A9AF0BB1F21C:\
+BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+ECEDEEEF5350516EA1A0A7A6A3ACADAE:FB554DE520D159A06BF219FC7F34A02F:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4
+
+32333C3D25222320E9E8EBEACECDCCC3:A89FBA152D76B4927BEED160DDB76C57:\
+F6F7F8F9FBFCFDFE00010203050607080A0B0C0D0F101112
+
+40414243626160678A8BB4B511161714:5676EAB4A98D2E8473B3F3D46424247C:\
+14151617191A1B1C1E1F20212324252628292A2B2D2E2F30
+
+94959293F5FAFBF81F1E1D1C7C7F7E79:4E8F068BD7EDE52A639036EC86C33568:\
+323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+BEBFBCBD191A1B14CFCEC9C8546B6A69:F0193C4D7AFF1791EE4C07EB4A1824FC:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C
+
+2C2D3233898E8F8CBBBAB9B8333031CE:AC8686EECA9BA761AFE82D67B928C33F:\
+6E6F70717374757678797A7B7D7E7F80828384858788898A
+
+84858687BFBCBDBA37363938FDFAFBF8:5FAF8573E33B145B6A369CD3606AB2C9:\
+8C8D8E8F91929394969798999B9C9D9EA0A1A2A3A5A6A7A8
+
+828384857669686B909192930B08090E:31587E9944AB1C16B844ECAD0DF2E7DA:\
+AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+BEBFBCBD9695948B707176779E919093:D017FECD91148ABA37F6F3068AA67D8A:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4
+
+8B8A85846067666521202322D0D3D2DD:788EF2F021A73CBA2794B616078A8500:\
+E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8FAFBFCFDFE010002
+
+76777475F1F2F3F4F8F9E6E777707172:5D1EF20DCED6BCBC12131AC7C54788AA:\
+04050607090A0B0C0E0F10111314151618191A1B1D1E1F20
+
+A4A5A2A34F404142B4B5B6B727242522:B3C8CF961FAF9EA05FDDE6D1E4D8F663:\
+222324252728292A2C2D2E2F31323334363738393B3C3D3E
+
+94959697E1E2E3EC16171011839C9D9E:143075C70605861C7FAC6526199E459F:\
+40414243454647484A4B4C4D4F50515254555657595A5B5C
+
+03023D3C06010003DEDFDCDDFFFCFDE2:A5AE12EADE9A87268D898BFC8FC0252A:\
+5E5F60616364656668696A6B6D6E6F70727374757778797A
+
+10111213F1F2F3F4CECFC0C1DBDCDDDE:0924F7CF2E877A4819F5244A360DCEA9:\
+7C7D7E7F81828384868788898B8C8D8E9091929395969798
+
+67666160724D4C4F1D1C1F1E73707176:3D9E9635AFCC3E291CC7AB3F27D1C99A:\
+9A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+E6E7E4E5A8ABAAD584858283909F9E9D:9D80FEEBF87510E2B8FB98BB54FD788C:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4
+
+71707F7E565150537D7C7F7E6162636C:5F9D1A082A1A37985F174002ECA01309:\
+D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+
+64656667212223245555AAAA03040506:A390EBB1D1403930184A44B4876646E4:\
+F4F5F6F7F9FAFBFCFEFE01010304050608090A0B0D0E0F10
+
+9E9F9899ABA4A5A6CFCECDCC2B28292E:700FE918981C3195BB6C4BCB46B74E29:\
+121314151718191A1C1D1E1F21222324262728292B2C2D2E
+
+C7C6C5C4D1D2D3DC626364653A454447:907984406F7BF2D17FB1EB15B673D747:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C
+
+F6F7E8E9E0E7E6E51D1C1F1E5B585966:C32A956DCFC875C2AC7C7CC8B8CC26E1:\
+4E4F50515354555658595A5B5D5E5F60626364656768696A
+
+BCBDBEBF5D5E5F5868696667F4F3F2F1:02646E2EBFA9B820CF8424E9B9B6EB51:\
+6C6D6E6F71727374767778797B7C7D7E8081828385868788
+
+40414647B0AFAEAD9B9A99989B98999E:621FDA3A5BBD54C6D3C685816BD4EAD8:\
+8A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+
+69686B6A0201001F0F0E0908B4BBBAB9:D4E216040426DFAF18B152469BC5AC2F:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4
+
+C7C6C9C8D8DFDEDD5A5B5859BEBDBCB3:9D0635B9D33B6CDBD71F5D246EA17CC8:\
+C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2
+
+DEDFDCDD787B7A7DFFFEE1E0B2B5B4B7:10ABAD1BD9BAE5448808765583A2CC1A:\
+E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6F8F9FAFBFDFEFE00
+
+4D4C4B4A606F6E6DD0D1D2D3FBF8F9FE:6891889E16544E355FF65A793C39C9A8:\
+020304050708090A0C0D0E0F11121314161718191B1C1D1E
+
+B7B6B5B4D7D4D5DAE5E4E3E2E1FEFFFC:CC735582E68072C163CD9DDF46B91279:\
+20212223252627282A2B2C2D2F30313234353637393A3B3C
+
+CECFB0B1F7F0F1F2AEAFACAD3E3D3C23:C5C68B9AEEB7F878DF578EFA562F9574:\
+3E3F40414344454648494A4B4D4E4F50525354555758595A
+
+CACBC8C9CDCECFC812131C1D494E4F4C:5F4764395A667A47D73452955D0D2CE8:\
+5C5D5E5F61626364666768696B6C6D6E7071727375767778
+
+9D9C9B9AD22D2C2FB1B0B3B20C0F0E09:701448331F66106CEFDDF1EB8267C357:\
+7A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+
+7A7B787964676659959493924F404142:CB3EE56D2E14B4E1941666F13379D657:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4
+
+AAABA4A5CEC9C8CB1F1E1D1CABA8A9A6:9FE16EFD18AB6E1981191851FEDB0764:\
+B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2
+
+93929190282B2A2DC4C5FAFB92959497:3DC9BA24E1B223589B147ADCEB4C8E48:\
+D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6E8E9EAEBEDEEEFF0
+
+EFEEE9E8DED1D0D339383B3A888B8A8D:1C333032682E7D4DE5E5AFC05C3E483C:\
+F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+
+7F7E7D7CA2A1A0AF78797E7F112E2F2C:D593CC99A95AFEF7E92038E05A59D00A:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C
+
+84859A9B2B2C2D2E868784852625245B:51E7F96F53B4353923452C222134E1EC:\
+2E2F30313334353638393A3B3D3E3F40424344454748494A
+
+B0B1B2B3070405026869666710171615:4075B357A1A2B473400C3B25F32F81A4:\
+4C4D4E4F51525354565758595B5C5D5E6061626365666768
+
+ACADAAABBDA2A3A00D0C0F0E595A5B5C:302E341A3EBCD74F0D55F61714570284:\
+6A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+
+121310115655544B5253545569666764:57ABDD8231280DA01C5042B78CF76522:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4
+
+DEDFD0D166616063EAEBE8E94142434C:17F9EA7EEA17AC1ADF0E190FEF799E92:\
+A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2
+
+DBDAD9D81417161166677879E0E7E6E5:2E1BDD563DD87EE5C338DD6D098D0A7A:\
+C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6D8D9DADBDDDEDFE0
+
+6A6B6C6DE0EFEEED2B2A2928C0C3C2C5:EB869996E6F8BFB2BFDD9E0C4504DBB2:\
+E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+B1B0B3B21714151A1A1B1C1D5649484B:C2E01549E9DECF317468B3E018C61BA8:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C
+
+39380706A3A4A5A6C4C5C6C77271706F:8DA875D033C01DD463B244A1770F4A22:\
+1E1F20212324252628292A2B2D2E2F30323334353738393A
+
+5C5D5E5F1013121539383736E2E5E4E7:8BA0DCF3A186844F026D022F8839D696:\
+3C3D3E3F41424344464748494B4C4D4E5051525355565758
+
+43424544EAD5D4D72E2F2C2D64676661:E9691FF9A6CC6970E51670A0FD5B88C1:\
+5A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+55545756989B9A65F8F9FEFF18171615:F2BAEC06FAEED30F88EE63BA081A6E5B:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394
+
+05040B0A525554573C3D3E3F4A494847:9C39D4C459AE5753394D6094ADC21E78:\
+969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2
+
+14151617595A5B5C8584FBFA8E89888B:6345B532A11904502EA43BA99C6BD2B2:\
+B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0
+
+7C7D7A7BFDF2F3F029282B2A51525354:5FFAE3061A95172E4070CEDCE1E428C8:\
+D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+38393A3B1E1D1C1341404746C23D3C3E:0A4566BE4CDF9ADCE5DEC865B5AB34CD:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C
+
+8D8C939240474645818083827C7F7E41:CA17FCCE79B7404F2559B22928F126FB:\
+0E0F10111314151618191A1B1D1E1F20222324252728292A
+
+3B3A39381A19181F32333C3D45424340:97CA39B849ED73A6470A97C821D82F58:\
+2C2D2E2F31323334363738393B3C3D3E4041424345464748
+
+F0F1F6F738272625828380817F7C7D7A:8198CB06BC684C6D3E9B7989428DCF7A:\
+4A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+89888B8A0407061966676061141B1A19:F53C464C705EE0F28D9A4C59374928BD:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384
+
+D3D2DDDCAAADACAF9C9D9E9FE8EBEAE5:9ADB3D4CCA559BB98C3E2ED73DBF1154:\
+868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2
+
+834EADFCCAC7E1B30664B1ABA44815AB:1946DABF6A03A2A2C3D0B05080AED6FC:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+
+D9DC4DBA3021B05D67C0518F72B62BF1:5ED301D747D3CC715445EBDEC62F2FB4:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+A291D86301A4A739F7392173AA3C604C:6585C8F43D13A6BEAB6419FC5935B9D0:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+4264B2696498DE4DF79788A9F83E9390:2A5B56A596680FCC0E05F5E0F151ECAE:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+EE9932B3721804D5A83EF5949245B6F6:F5D6FF414FD2C6181494D20C37F2B8C4:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+E6248F55C5FDCBCA9CBBB01C88A2EA77:85399C01F59FFFB5204F19F8482F00B8:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+B8358E41B9DFF65FD461D55A99266247:92097B4C88A041DDF98144BC8D22E8E7:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+
+F0E2D72260AF58E21E015AB3A4C0D906:89BD5B73B356AB412AEF9F76CEA2D65C:\
+18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+
+475B8B823CE8893DB3C44A9F2A379FF7:2536969093C55FF9454692F2FAC2F530:\
+40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+688F5281945812862F5F3076CF80412F:07FC76A872843F3F6E0081EE9396D637:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+
+08D1D2BC750AF553365D35E75AFACEAA:E38BA8EC2AA741358DCC93E8F141C491:\
+90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+8707121F47CC3EFCECA5F9A8474950A1:D028EE23E4A89075D0B03E868D7D3A42:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+E51AA0B135DBA566939C3B6359A980C5:8CD9423DFC459E547155C5D1D522E540:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+
+069A007FC76A459F98BAF917FEDF9521:080E9517EB1677719ACF728086040AE3:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+
+726165C1723FBCF6C026D7D00B091027:7C1700211A3991FC0ECDED0AB3E576B0:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+
+D7C544DE91D55CFCDE1F84CA382200CE:DABCBCC855839251DB51E224FBE87435:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+
+FED3C9A161B9B5B2BD611B41DC9DA357:68D56FAD0406947A4DD27A7448C10F1D:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+
+4F634CDC6551043409F30B635832CF82:DA9A11479844D1FFEE24BBF3719A9925:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+109CE98DB0DFB36734D9F3394711B4E6:5E4BA572F8D23E738DA9B05BA24B8D81:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+4EA6DFABA2D8A02FFDFFA89835987242:A115A2065D667E3F0B883837A6E903F8:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+
+5AE094F54AF58E6E3CDBF976DAC6D9EF:3E9E90DC33EAC2437D86AD30B137E66E:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+764D8E8E0F29926DBE5122E66354FDBE:01CE82D8FBCDAE824CB3C48E495C3692:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+3F0418F888CDF29A982BF6B75410D6A9:0C9CFF163CE936FAAF083CFD3DEA3117:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+
+E4A3E7CB12CDD56AA4A75197A9530220:5131BA9BD48F2BBA85560680DF504B52:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+
+211677684AAC1EC1A160F44C4EBF3F26:9DC503BBF09823AEC8A977A5AD26CCB2:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+
+D21E439FF749AC8F18D6D4B105E03895:9A6DB0C0862E506A9E397225884041D7:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+
+D9F6FF44646C4725BD4C0103FF5552A7:430BF9570804185E1AB6365FC6A6860C:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+0B1256C2A00B976250CFC5B0C37ED382:3525EBC02F4886E6A5A3762813E8CE8A:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+B056447FFC6DC4523A36CC2E972A3A79:07FA265C763779CCE224C7BAD671027B:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+5E25CA78F0DE55802524D38DA3FE4456:E8B72B4E8BE243438C9FFF1F0E205872:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+
+A5BCF4728FA5EAAD8567C0DC24675F83:109D4F999A0E11ACE1F05E6B22CBCB50:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+814E59F97ED84646B78B2CA022E9CA43:45A5E8D4C3ED58403FF08D68A0CC4029:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+15478BEEC58F4775C7A7F5D4395514D7:196865964DB3D417B6BD4D586BCB7634:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+253548FFCA461C67C8CBC78CD59F4756:60436AD45AC7D30D99195F815D98D2AE:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+FD7AD8D73B9B0F8CC41600640F503D65:BB07A23F0B61014B197620C185E2CD75:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+06199DE52C6CBF8AF954CD65830BCD56:5BC0B2850129C854423AFF0751FE343B:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+
+F17C4FFE48E44C61BD891E257E725794:7541A78F96738E6417D2A24BD2BECA40:\
+18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+
+9A5B4A402A3E8A59BE6BF5CD8154F029:B0A303054412882E464591F1546C5B9E:\
+40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+79BD40B91A7E07DC939D441782AE6B17:778C06D8A355EEEE214FCEA14B4E0EEF:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+
+D8CEAAF8976E5FBE1012D8C84F323799:09614206D15CBACE63227D06DB6BEEBB:\
+90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+3316E2751E2E388B083DA23DD6AC3FBE:41B97FB20E427A9FDBBB358D9262255D:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+8B7CFBE37DE7DCA793521819242C5816:C1940F703D845F957652C2D64ABD7ADF:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+
+F23F033C0EEBF8EC55752662FD58CE68:D2D44FCDAE5332343366DB297EFCF21B:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+
+59EB34F6C8BDBACC5FC6AD73A59A1301:EA8196B79DBE167B6AA9896E287EED2B:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+
+DCDE8B6BD5CF7CC22D9505E3CE81261A:D6B0B0C4BA6C7DBE5ED467A1E3F06C2D:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+
+E33CF7E524FED781E7042FF9F4B35DC7:EC51EB295250C22C2FB01816FB72BCAE:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+
+27963C8FACDF73062867D164DF6D064C:ADED6630A07CE9C7408A155D3BD0D36F:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+77B1CE386B551B995F2F2A1DA994EEF8:697C9245B9937F32F5D1C82319F0363A:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+F083388B013679EFCF0BB9B15D52AE5C:AAD5AD50C6262AAEC30541A1B7B5B19C:\
+F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+
+C5009E0DAB55DB0ABDB636F2600290C8:7D34B893855341EC625BD6875AC18C0D:\
+20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+
+7804881E26CD532D8514D3683F00F1B9:7EF05105440F83862F5D780E88F02B41:\
+48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+
+46CDDCD73D1EB53E675CA012870A92A3:C377C06403382061AF2C9C93A8E70DF6:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+
+A9FB44062BB07FE130A8E8299EACB1AB:1DBDB3FFDC052DACC83318853ABC6DE5:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+2B6FF8D7A5CC3A28A22D5A6F221AF26B:69A6EAB00432517D0BF483C91C0963C7:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+1A9527C29B8ADD4B0E3E656DBB2AF8B4:0797F41DC217C80446E1D514BD6AB197:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+
+7F99CF2C75244DF015EB4B0C1050AEAE:9DFD76575902A637C01343C58E011A03:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+
+E84FF85B0D9454071909C1381646C4ED:ACF4328AE78F34B9FA9B459747CC2658:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+
+89AFD40F99521280D5399B12404F6DB4:B0479AEA12BAC4FE2384CF98995150C6:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+
+A09EF32DBC5119A35AB7FA38656F0329:9DD52789EFE3FFB99F33B3DA5030109A:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+61773457F068C376C7829B93E696E716:ABBB755E4621EF8F1214C19F649FB9FD:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+A34F0CAE726CCE41DD498747D891B967:DA27FB8174357BCE2BED0E7354F380F9:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+856F59496C7388EE2D2B1A27B7697847:C59A0663F0993838F6E5856593BDC5EF:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+
+CB090C593EF7720BD95908FB93B49DF4:ED60B264B5213E831607A99C0CE5E57E:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+A0AC75CD2F1923D460FC4D457AD95BAF:E50548746846F3EB77B8C520640884ED:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+2A2B282974777689E8E9EEEF525D5C5F:28282CC7D21D6A2923641E52D188EF0C:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+909192939390919E0F0E09089788898A:0DFA5B02ABB18E5A815305216D6D4F8E:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+777675748D8E8F907170777649464744:7359635C0EECEFE31D673395FB46FB99:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+717073720605040B2D2C2B2A05FAFBF9:73C679F7D5AEF2745C9737BB4C47FB36:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+
+64656667FEFDFCC31B1A1D1CA5AAABA8:B192BD472A4D2EAFB786E97458967626:\
+18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+
+DBDAD9D86A696867B5B4B3B2C8D7D6D5:0EC327F6C8A2B147598CA3FDE61DC6A4:\
+40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+5C5D5E5FE3E0E1FE31303736333C3D3E:FC418EB3C41B859B38D4B6F646629729:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+
+545556574B48494673727574546B6A69:30249E5AC282B1C981EA64B609F3A154:\
+90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+ECEDEEEFC6C5C4BB56575051F5FAFBF8:5E6E08646D12150776BB43C2D78A9703:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+464744452724252AC9C8CFCED2CDCCCF:FAEB3D5DE652CD3447DCEB343F30394A:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+
+E6E7E4E54142435C878681801C131211:A8E88706823F6993EF80D05C1C7B2CF0:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+
+72737071CFCCCDC2F9F8FFFE710E0F0C:8CED86677E6E00A1A1B15968F2D3CCE6:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+
+505152537370714EC3C2C5C4010E0F0C:9FC7C23858BE03BDEBB84E90DB6786A9:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+
+A8A9AAAB5C5F5E51AEAFA8A93D222320:B4FBD65B33F70D8CF7F1111AC4649C36:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+
+DEDFDCDDF6F5F4EB10111617FEF1F0F3:C5C32D5ED03C4B53CC8C1BD0EF0DBBF6:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+BDBCBFBE5E5D5C530B0A0D0CFAC5C4C7:D1A7F03B773E5C212464B63709C6A891:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+8A8B8889050606F8F4F5F2F3636C6D6E:6B7161D8745947AC6950438EA138D028:\
+F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+
+A6A7A4A54D4E4F40B2B3B4B539262724:FD47A9F7E366EE7A09BC508B00460661:\
+20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+
+9C9D9E9FE9EAEBF40E0F08099B949596:00D40B003DC3A0D9310B659B98C7E416:\
+48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+
+2D2C2F2E1013121DCCCDCACBED121310:EEA4C79DCC8E2BDA691F20AC48BE0717:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+
+F4F5F6F7EDEEEFD0EAEBECEDF7F8F9FA:E78F43B11C204403E5751F89D05A2509:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+3D3C3F3E282B2A2573727574150A0B08:D0F0E3D1F1244BB979931E38DD1786EF:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+B6B7B4B5F8FBFAE5B4B5B2B3A0AFAEAD:042E639DC4E1E4DDE7B75B749EA6F765:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+
+B7B6B5B4989B9A95878681809BA4A5A6:BC032FDD0EFE29503A980A7D07AB46A8:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+
+A8A9AAABE5E6E798E9E8EFEE4748494A:0C93AC949C0DA6446EFFB86183B6C910:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+
+ECEDEEEFD9DADBD4B9B8BFBE657A7B78:E0D343E14DA75C917B4A5CEC4810D7C2:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+
+7F7E7D7C696A6B74CACBCCCD929D9C9F:0EAFB821748408279B937B626792E619:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+08090A0B0605040BFFFEF9F8B9C6C7C4:FA1AC6E02D23B106A1FEF18B274A553F:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+08090A0BF1F2F3CCFCFDFAFB68676665:0DADFE019CD12368075507DF33C1A1E9:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+CACBC8C93A393837050403020D121310:3A0879B414465D9FFBAF86B33A63A1B9:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+
+E9E8EBEA8281809F8F8E8988343B3A39:62199FADC76D0BE1805D3BA0B7D914BF:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+515053524645444BD0D1D6D7340B0A09:1B06D6C5D333E742730130CF78E719B4:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+42434041ECEFEE1193929594C6C9C8CB:F1F848824C32E9DCDCBF21580F069329:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+EFEEEDECC2C1C0CF76777071455A5B58:1A09050CBD684F784D8E965E0782F28A:\
+A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6
+
+5F5E5D5C3F3C3D221D1C1B1A19161714:79C2969E7DED2BA7D088F3F320692360:\
+C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE
+
+000102034142434C1C1D1A1B8D727371:091A658A2F7444C16ACCB669450C7B63:\
+F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516
+
+8E8F8C8DB1B2B38C56575051050A0B08:97C1E3A72CCA65FA977D5ED0E8A7BBFC:\
+18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E
+
+A7A6A5A4E8EBEAE57F7E7978CAD5D4D7:70C430C6DB9A17828937305A2DF91A2A:\
+40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+
+8A8B888994979689454443429F909192:629553457FBE2479098571C7C903FDE8:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E
+
+8C8D8E8FE0E3E2ED45444342F1CECFCC:A25B25A61F612669E7D91265C7D476BA:\
+90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+
+FFFEFDFC4C4F4E31D8D9DEDFB6B9B8BB:EB7E4E49B8AE0F024570DDA293254FED:\
+B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+
+FDFCFFFECCCFCEC12F2E29286679787B:38FE15D61CCA84516E924ADCE5014F67:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+
+67666564BAB9B8A77071767719161714:3AD208492249108C9F3EBEB167AD0583:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+
+9A9B98992D2E2F2084858283245B5A59:299BA9F9BF5AB05C3580FC26EDD1ED12:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+
+A4A5A6A70B0809365C5D5A5B2C232221:19DC705B857A60FB07717B2EA5717781:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+
+464744455754555AF3F2F5F4AFB0B1B2:FFC8AEB885B5EFCAD06B6DBEBF92E76B:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+
+323330317675746B7273747549464744:F58900C5E0B385253FF2546250A0142B:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+
+A8A9AAAB181B1A15808186872B141516:2EE67B56280BC462429CEE6E3370CBC1:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+
+E7E6E5E4202323DDAAABACAD343B3A39:20DB650A9C8E9A84AB4D25F7EDC8F03F:\
+F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E
+
+A8A9AAAB2221202FEDECEBEA1E010003:3C36DA169525CF818843805F25B78AE5:\
+20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+
+F9F8FBFA5F5C5D42424344450E010003:9A781D960DB9E45E37779042FEA51922:\
+48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E
+
+57565554F5F6F7F89697909120DFDEDD:6560395EC269C672A3C288226EFDBA77:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+
+F8F9FAFBCCCFCEF1DDDCDBDA0E010003:8C772B7A189AC544453D5916EBB27B9A:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+
+D9D8DBDA7073727D80818687C2DDDCDF:77CA5468CC48E843D05F78EED9D6578F:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+
+C5C4C7C6080B0A1588898E8F68676665:72CDCC71DC82C60D4429C9E2D8195BAA:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+
+83828180DCDFDED186878081F0CFCECD:8080D68CE60E94B40B5B8B69EEB35AFA:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+
+98999A9BDDDEDFA079787F7E0A050407:44222D3CDE299C04369D58AC0EBA1E8E:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+
+CECFCCCD4F4C4D429F9E9998DFC0C1C2:9B8721B0A8DFC691C5BC5885DBFCB27A:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+
+404142436665647B29282F2EABA4A5A6:0DC015CE9A3A3414B5E62EC643384183:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+
+33323130E6E5E4EB23222524DEA1A0A3:705715448A8DA412025CE38345C2A148:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+
+CFCECDCCF6F5F4CBE6E7E0E199969794:C32B5B0B6FBAE165266C569F4B6ECF0B:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+
+BABBB8B97271707FDCDDDADB29363734:4DCA6C75192A01DDCA9476AF2A521E87:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+
+C9C8CBCA4447465926272021545B5A59:058691E627ECBC36AC07B6DB423BD698:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+
+050407067477767956575051221D1C1F:7444527095838FE080FC2BCDD30847EB:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+
+00000000000000000000000000000000:0EDD33D3C621E546455BD8BA1418BEC8:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:C0CC0C5DA5BD63ACD44A80774FAD5222:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:2F0B4B71BC77851B9CA56D42EB8FF080:\
+20000000000000000000000000000000
+
+00000000000000000000000000000000:6B1E2FFFE8A114009D8FE22F6DB5F876:\
+10000000000000000000000000000000
+
+00000000000000000000000000000000:9AA042C315F94CBB97B62202F83358F5:\
+08000000000000000000000000000000
+
+00000000000000000000000000000000:DBE01DE67E346A800C4C4B4880311DE4:\
+04000000000000000000000000000000
+
+00000000000000000000000000000000:C117D2238D53836ACD92DDCDB85D6A21:\
+02000000000000000000000000000000
+
+00000000000000000000000000000000:DC0ED85DF9611ABB7249CDD168C5467E:\
+01000000000000000000000000000000
+
+00000000000000000000000000000000:807D678FFF1F56FA92DE3381904842F2:\
+00800000000000000000000000000000
+
+00000000000000000000000000000000:0E53B3FCAD8E4B130EF73AEB957FB402:\
+00400000000000000000000000000000
+
+00000000000000000000000000000000:969FFD3B7C35439417E7BDE923035D65:\
+00200000000000000000000000000000
+
+00000000000000000000000000000000:A99B512C19CA56070491166A1503BF15:\
+00100000000000000000000000000000
+
+00000000000000000000000000000000:6E9985252126EE344D26AE369D2327E3:\
+00080000000000000000000000000000
+
+00000000000000000000000000000000:B85F4809F904C275491FCDCD1610387E:\
+00040000000000000000000000000000
+
+00000000000000000000000000000000:ED365B8D7D20C1F5D53FB94DD211DF7B:\
+00020000000000000000000000000000
+
+00000000000000000000000000000000:B3A575E86A8DB4A7135D604C43304896:\
+00010000000000000000000000000000
+
+00000000000000000000000000000000:89704BCB8E69F846259EB0ACCBC7F8A2:\
+00008000000000000000000000000000
+
+00000000000000000000000000000000:C56EE7C92197861F10D7A92B90882055:\
+00004000000000000000000000000000
+
+00000000000000000000000000000000:92F296F6846E0EAF9422A5A24A08B069:\
+00002000000000000000000000000000
+
+00000000000000000000000000000000:E67E32BB8F11DEB8699318BEE9E91A60:\
+00001000000000000000000000000000
+
+00000000000000000000000000000000:B08EEF85EAF626DD91B65C4C3A97D92B:\
+00000800000000000000000000000000
+
+00000000000000000000000000000000:661083A6ADDCE79BB4E0859AB5538013:\
+00000400000000000000000000000000
+
+00000000000000000000000000000000:55DFE2941E0EB10AFC0B333BD34DE1FE:\
+00000200000000000000000000000000
+
+00000000000000000000000000000000:6BFE5945E715C9662609770F8846087A:\
+00000100000000000000000000000000
+
+00000000000000000000000000000000:79848E9C30C2F8CDA8B325F7FED2B139:\
+00000080000000000000000000000000
+
+00000000000000000000000000000000:7A713A53B99FEF34AC04DEEF80965BD0:\
+00000040000000000000000000000000
+
+00000000000000000000000000000000:18144A2B46620D32C3C32CE52D49257F:\
+00000020000000000000000000000000
+
+00000000000000000000000000000000:872E827C70887C80749F7B8BB1847C7E:\
+00000010000000000000000000000000
+
+00000000000000000000000000000000:6B86C6A4FE6A60C59B1A3102F8DE49F3:\
+00000008000000000000000000000000
+
+00000000000000000000000000000000:9848BB3DFDF6F532F094679A4C231A20:\
+00000004000000000000000000000000
+
+00000000000000000000000000000000:925AD528E852E329B2091CD3F1C2BCEE:\
+00000002000000000000000000000000
+
+00000000000000000000000000000000:80DF436544B0DD596722E46792A40CD8:\
+00000001000000000000000000000000
+
+00000000000000000000000000000000:525DAF18F93E83E1E74BBBDDE4263BBA:\
+00000000800000000000000000000000
+
+00000000000000000000000000000000:F65C9D2EE485D24701FFA3313B9D5BE6:\
+00000000400000000000000000000000
+
+00000000000000000000000000000000:E4FC8D8BCA06425BDF94AFA40FCC14BA:\
+00000000200000000000000000000000
+
+00000000000000000000000000000000:A53F0A5CA1E4E6440BB975FF320DE6F8:\
+00000000100000000000000000000000
+
+00000000000000000000000000000000:D55313B9394080462E87E02899B553F0:\
+00000000080000000000000000000000
+
+00000000000000000000000000000000:34A71D761F71BCD344384C7F97D27906:\
+00000000040000000000000000000000
+
+00000000000000000000000000000000:233F3D819599612EBC89580245C996A8:\
+00000000020000000000000000000000
+
+00000000000000000000000000000000:B4F1374E5268DBCB676E447529E53F89:\
+00000000010000000000000000000000
+
+00000000000000000000000000000000:0816BD27861D2BA891D1044E39951E96:\
+00000000008000000000000000000000
+
+00000000000000000000000000000000:F3BE9EA3F10C73CA64FDE5DB13A951D1:\
+00000000004000000000000000000000
+
+00000000000000000000000000000000:2448086A8106FBD03048DDF857D3F1C8:\
+00000000002000000000000000000000
+
+00000000000000000000000000000000:670756E65BEC8B68F03D77CDCDCE7B91:\
+00000000001000000000000000000000
+
+00000000000000000000000000000000:EF968CF0D36FD6C6EFFD225F6FB44CA9:\
+00000000000800000000000000000000
+
+00000000000000000000000000000000:2E8767157922E3826DDCEC1B0CC1E105:\
+00000000000400000000000000000000
+
+00000000000000000000000000000000:78CE7EEC670E45A967BAB17E26A1AD36:\
+00000000000200000000000000000000
+
+00000000000000000000000000000000:3C5CEE825655F098F6E81A2F417DA3FB:\
+00000000000100000000000000000000
+
+00000000000000000000000000000000:67BFDB431DCE1292200BC6F5207ADB12:\
+00000000000080000000000000000000
+
+00000000000000000000000000000000:7540FD38E447C0779228548747843A6F:\
+00000000000040000000000000000000
+
+00000000000000000000000000000000:B85E513301F8A936EA9EC8A21A85B5E6:\
+00000000000020000000000000000000
+
+00000000000000000000000000000000:04C67DBF16C11427D507A455DE2C9BC5:\
+00000000000010000000000000000000
+
+00000000000000000000000000000000:03F75EB8959E55079CFFB4FF149A37B6:\
+00000000000008000000000000000000
+
+00000000000000000000000000000000:74550287F666C63BB9BC7838433434B0:\
+00000000000004000000000000000000
+
+00000000000000000000000000000000:7D537200195EBC3AEFD1EAAB1C385221:\
+00000000000002000000000000000000
+
+00000000000000000000000000000000:CE24E4D40C68A82B535CBD3C8E21652A:\
+00000000000001000000000000000000
+
+00000000000000000000000000000000:AB20072405AA8FC40265C6F1F3DC8BC0:\
+00000000000000800000000000000000
+
+00000000000000000000000000000000:6CFD2CF688F566B093F67B9B3839E80A:\
+00000000000000400000000000000000
+
+00000000000000000000000000000000:BD95977E6B7239D407A012C5544BF584:\
+00000000000000200000000000000000
+
+00000000000000000000000000000000:DF9C0130AC77E7C72C997F587B46DBE0:\
+00000000000000100000000000000000
+
+00000000000000000000000000000000:E7F1B82CADC53A648798945B34EFEFF2:\
+00000000000000080000000000000000
+
+00000000000000000000000000000000:932C6DBF69255CF13EDCDB72233ACEA3:\
+00000000000000040000000000000000
+
+00000000000000000000000000000000:5C76002BC7206560EFE550C80B8F12CC:\
+00000000000000020000000000000000
+
+00000000000000000000000000000000:F6B7BDD1CAEEBAB574683893C4475484:\
+00000000000000010000000000000000
+
+00000000000000000000000000000000:A920E37CC6DC6B31DA8C0169569F5034:\
+00000000000000008000000000000000
+
+00000000000000000000000000000000:919380ECD9C778BC513148B0C28D65FD:\
+00000000000000004000000000000000
+
+00000000000000000000000000000000:EE67308DD3F2D9E6C2170755E5784BE1:\
+00000000000000002000000000000000
+
+00000000000000000000000000000000:3CC73E53B85609023A05E149B223AE09:\
+00000000000000001000000000000000
+
+00000000000000000000000000000000:983E8AF7CF05EBB28D71EB841C9406E6:\
+00000000000000000800000000000000
+
+00000000000000000000000000000000:0F3099B2D31FA5299EE5BF43193287FC:\
+00000000000000000400000000000000
+
+00000000000000000000000000000000:B763D84F38C27FE6931DCEB6715D4DB6:\
+00000000000000000200000000000000
+
+00000000000000000000000000000000:5AE3C9B0E3CC29C0C61565CD01F8A248:\
+00000000000000000100000000000000
+
+00000000000000000000000000000000:F58083572CD90981958565D48D2DEE25:\
+00000000000000000080000000000000
+
+00000000000000000000000000000000:7E6255EEF8F70C0EF10337AAB1CCCEF8:\
+00000000000000000040000000000000
+
+00000000000000000000000000000000:AAD4BAC34DB22821841CE2F631961902:\
+00000000000000000020000000000000
+
+00000000000000000000000000000000:D7431C0409BB1441BA9C6858DC7D4E81:\
+00000000000000000010000000000000
+
+00000000000000000000000000000000:EF9298C65E339F6E801A59C626456993:\
+00000000000000000008000000000000
+
+00000000000000000000000000000000:53FE29F68FF541ABC3F0EF3350B72F7E:\
+00000000000000000004000000000000
+
+00000000000000000000000000000000:F6BBA5C10DB02529E2C2DA3FB582CC14:\
+00000000000000000002000000000000
+
+00000000000000000000000000000000:E4239AA37FC531A386DAD1126FC0E9CD:\
+00000000000000000001000000000000
+
+00000000000000000000000000000000:8F7758F857D15BBE7BFD0E416404C365:\
+00000000000000000000800000000000
+
+00000000000000000000000000000000:D273EB57C687BCD1B4EA7218A509E7B8:\
+00000000000000000000400000000000
+
+00000000000000000000000000000000:65D64F8D76E8B3423FA25C4EB58A210A:\
+00000000000000000000200000000000
+
+00000000000000000000000000000000:623D802B4EC450D66A16625702FCDBE0:\
+00000000000000000000100000000000
+
+00000000000000000000000000000000:7496460CB28E5791BAEAF9B68FB00022:\
+00000000000000000000080000000000
+
+00000000000000000000000000000000:34EA600F18BB0694B41681A49D510C1D:\
+00000000000000000000040000000000
+
+00000000000000000000000000000000:5F8FF0D47D5766D29B5D6E8F46423BD8:\
+00000000000000000000020000000000
+
+00000000000000000000000000000000:225F9286C5928BF09F84D3F93F541959:\
+00000000000000000000010000000000
+
+00000000000000000000000000000000:B21E90D25DF383416A5F072CEBEB1FFB:\
+00000000000000000000008000000000
+
+00000000000000000000000000000000:4AEFCDA089318125453EB9E8EB5E492E:\
+00000000000000000000004000000000
+
+00000000000000000000000000000000:4D3E75C6CD40EC4869BC85158591ADB8:\
+00000000000000000000002000000000
+
+00000000000000000000000000000000:63A8B904405436A1B99D7751866771B7:\
+00000000000000000000001000000000
+
+00000000000000000000000000000000:64F0DAAE47529199792EAE172BA53293:\
+00000000000000000000000800000000
+
+00000000000000000000000000000000:C3EEF84BEA18225D515A8C852A9047EE:\
+00000000000000000000000400000000
+
+00000000000000000000000000000000:A44AC422B47D47B81AF73B3E9AC9596E:\
+00000000000000000000000200000000
+
+00000000000000000000000000000000:D16E04A8FBC435094F8D53ADF25F5084:\
+00000000000000000000000100000000
+
+00000000000000000000000000000000:EF13DC34BAB03E124EEAD8B6BF44B532:\
+00000000000000000000000080000000
+
+00000000000000000000000000000000:D94799075C24DCC067AF0D392049250D:\
+00000000000000000000000040000000
+
+00000000000000000000000000000000:14F431771EDDCE4764C21A2254B5E3C8:\
+00000000000000000000000020000000
+
+00000000000000000000000000000000:7039329F36F2ED682B02991F28D64679:\
+00000000000000000000000010000000
+
+00000000000000000000000000000000:124EE24EDE5551639DB8B8B941F6141D:\
+00000000000000000000000008000000
+
+00000000000000000000000000000000:C2852879A34D5184E478EC918B993FEE:\
+00000000000000000000000004000000
+
+00000000000000000000000000000000:86A806A3525B93E432053C9AB5ABBEDF:\
+00000000000000000000000002000000
+
+00000000000000000000000000000000:C1609BF5A4F07E37C17A36366EC23ECC:\
+00000000000000000000000001000000
+
+00000000000000000000000000000000:7E81E7CB92159A51FFCEA331B1E8EA53:\
+00000000000000000000000000800000
+
+00000000000000000000000000000000:37A7BE002856C5A59A6E03EAFCE7729A:\
+00000000000000000000000000400000
+
+00000000000000000000000000000000:BDF98A5A4F91E890C9A1D1E5FAAB138F:\
+00000000000000000000000000200000
+
+00000000000000000000000000000000:4E96ACB66E051F2BC739CC3D3E34A26B:\
+00000000000000000000000000100000
+
+00000000000000000000000000000000:EE996CDD120EB86E21ECFA49E8E1FCF1:\
+00000000000000000000000000080000
+
+00000000000000000000000000000000:61B9E6B579DBF6070C351A1440DD85FF:\
+00000000000000000000000000040000
+
+00000000000000000000000000000000:AC369E484316440B40DFC83AA96E28E7:\
+00000000000000000000000000020000
+
+00000000000000000000000000000000:0A2D16DE985C76D45C579C1159413BBE:\
+00000000000000000000000000010000
+
+00000000000000000000000000000000:DA3FDC38DA1D374FA4802CDA1A1C6B0F:\
+00000000000000000000000000008000
+
+00000000000000000000000000000000:B842523D4C41C2211AFE43A5800ADCE3:\
+00000000000000000000000000004000
+
+00000000000000000000000000000000:9E2CDA90D8E992DBA6C73D8229567192:\
+00000000000000000000000000002000
+
+00000000000000000000000000000000:D49583B781D9E20F5BE101415957FC49:\
+00000000000000000000000000001000
+
+00000000000000000000000000000000:EF09DA5C12B376E458B9B8670032498E:\
+00000000000000000000000000000800
+
+00000000000000000000000000000000:A96BE0463DA774461A5E1D5A9DD1AC10:\
+00000000000000000000000000000400
+
+00000000000000000000000000000000:32CEE3341060790D2D4B1362EF397090:\
+00000000000000000000000000000200
+
+00000000000000000000000000000000:21CEA416A3D3359D2C4D58FB6A035F06:\
+00000000000000000000000000000100
+
+00000000000000000000000000000000:172AEAB3D507678ECAF455C12587ADB7:\
+00000000000000000000000000000080
+
+00000000000000000000000000000000:B6F897941EF8EBFF9FE80A567EF38478:\
+00000000000000000000000000000040
+
+00000000000000000000000000000000:A9723259D94A7DC662FB0C782CA3F1DD:\
+00000000000000000000000000000020
+
+00000000000000000000000000000000:2F91C984B9A4839F30001B9F430493B4:\
+00000000000000000000000000000010
+
+00000000000000000000000000000000:0472406345A610B048CB99EE0EF3FA0F:\
+00000000000000000000000000000008
+
+00000000000000000000000000000000:F5F39086646F8C05ED16EFA4B617957C:\
+00000000000000000000000000000004
+
+00000000000000000000000000000000:26D50F485A30408D5AF47A5736292450:\
+00000000000000000000000000000002
+
+00000000000000000000000000000000:0545AAD56DA2A97C3663D1432A3D1C84:\
+00000000000000000000000000000001
+
+00000000000000000000000000000000:DE885DC87F5A92594082D02CC1E1B42C:\
+800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C749194F94673F9DD2AA1932849630C1:\
+400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0CEF643313912934D310297B90F56ECC:\
+200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C4495D39D4A553B225FBA02A7B1B87E1:\
+100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:636D10B1A0BCAB541D680A7970ADC830:\
+080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:07CF045786BD6AFCC147D99E45A901A7:\
+040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6A8E3F425A7599348F95398448827976:\
+020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5518276836148A00D91089A20D8BFF57:\
+010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F267E07B5E87E3BC20B969C61D4FCB06:\
+008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5A1CDE69571D401BFCD20DEBADA2212C:\
+004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:70A9057263254701D12ADD7D74CD509E:\
+002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35713A7E108031279388A33A0FE2E190:\
+001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E74EDE82B1254714F0C7B4B243108655:\
+000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:39272E3100FAA37B55B862320D1B3EB3:\
+000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D6E24C659FC5AEF712F77BCA19C9DD0:\
+000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:76D18212F972370D3CC2C6C372C6CF2F:\
+000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B21A1F0BAE39E55C7594ED570A7783EA:\
+000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:77DE202111895AC48DD1C974B358B458:\
+000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:67810B311969012AAF7B504FFAF39FD1:\
+000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C22EA2344D3E9417A6BA07843E713AEA:\
+000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C79CAF4B97BEE0BD0630AB354539D653:\
+000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:135FD1AF761D9AE23DF4AA6B86760DB4:\
+000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D4659D0B06ACD4D56AB8D11A16FD83B9:\
+000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F7D270028FC188E4E4F35A4AAA25D4D4:\
+000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:345CAE5A8C9620A9913D5473985852FF:\
+000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4E8980ADDE60B0E42C0B287FEA41E729:\
+000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F11B6D74E1F15155633DC39743C1A527:\
+000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9C87916C0180064F9D3179C6F5DD8C35:\
+000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:71AB186BCAEA518E461D4F7FAD230E6A:\
+000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C4A31BBC3DAAF742F9141C2A5001A49C:\
+000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E7C47B7B1D40F182A8928C8A55671D07:\
+000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8E17F294B28FA373C6249538868A7EEF:\
+000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:754404096A5CBC08AF09491BE249141A:\
+000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:101CB56E55F05D86369B6D1069204F0A:\
+000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:73F19BB6604205C6EE227B9759791E41:\
+000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6270C0028F0D136C37A56B2CB64D24D6:\
+000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A3BF7C2C38D1114A087ECF212E694346:\
+000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:49CABFF2CEF7D9F95F5EFB1F7A1A7DDE:\
+000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:EC7F8A47CC59B849469255AD49F62752:\
+000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:68FAE55A13EFAF9B07B3552A8A0DC9D1:\
+000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:211E6B19C69FAEF481F64F24099CDA65:\
+000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:DBB918C75BC5732416F79FB0C8EE4C5C:\
+000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:98D494E5D963A6C8B92536D3EC35E3FD:\
+000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:C9A873404D403D6F074190851D67781A:\
+000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:073AEF4A7C77D921928CB0DD9D27CAE7:\
+000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:89BDE25CEE36FDE769A10E52298CF90F:\
+000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:26D0842D37EAD38557C65E0A5E5F122E:\
+000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:F8294BA375AF46B3F22905BBAFFAB107:\
+000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:2AD63EB4D0D43813B979CF72B35BDB94:\
+000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:7710C171EE0F4EFA39BE4C995180181D:\
+000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:C0CB2B40DBA7BE8C0698FAE1E4B80FF8:\
+000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:97970E505194622FD955CA1B80B784E9:\
+000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:7CB1824B29F850900DF2CAD9CF04C1CF:\
+000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:FDF4F036BB988E42F2F62DE63FE19A64:\
+000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:08908CFE2C82606B2C15DF61B75CF3E2:\
+000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:B3AA689EF2D07FF365ACB9ADBA2AF07A:\
+000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:F2672CD8EAA3B98776660D0263656F5C:\
+000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:5BDEAC00E986687B9E1D94A0DA7BF452:\
+000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:E6D57BD66EA1627363EE0C4B711B0B21:\
+000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:03730DD6ACB4AD9996A63BE7765EC06F:\
+000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:A470E361AA5437B2BE8586D2F78DE582:\
+000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:7567FEEFA559911FD479670246B484E3:\
+000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:29829DEA15A4E7A4C049045E7B106E29:\
+000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:A407834C3D89D48A2CB7A152208FA4ED:\
+000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:68F948053F78FEF0D8F9FE7EF3A89819:\
+000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:B605174CAB13AD8FE3B20DA3AE7B0234:\
+000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:CCAB8F0AEBFF032893996D383CBFDBFA:\
+000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:AF14BB8428C9730B7DC17B6C1CBEBCC8:\
+000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:5A41A21332040877EB7B89E8E80D19FE:\
+000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:AC1BA52EFCDDE368B1596F2F0AD893A0:\
+000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:41B890E31B9045E6ECDC1BC3F2DB9BCC:\
+000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:4D54A549728E55B19A23660424A0F146:\
+000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:A917581F41C47C7DDCFFD5285E2D6A61:\
+000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:604DF24BA6099B93A7405A524D764FCB:\
+000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:78D9D156F28B190E232D1B7AE7FC730A:\
+000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:5A12C39E442CD7F27B3CD77F5D029582:\
+000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:FF2BF2F47CF7B0F28EE25AF95DBF790D:\
+000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:1863BB7D193BDA39DF090659EB8AE48B:\
+000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:38178F2FB4CFCF31E87E1ABCDC023EB5:\
+000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:F5B13DC690CC0D541C6BA533023DC8C9:\
+000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:48EC05238D7375D126DC9D08884D4827:\
+000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:ACD0D81139691B310B92A6E377BACC87:\
+000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:9A4AA43578B55CE9CC178F0D2E162C79:\
+000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:08AD94BC737DB3C87D49B9E01B720D81:\
+000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:3BCFB2D5D210E8332900C5991D551A2A:\
+000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:C5F0C6B9397ACB29635CE1A0DA2D8D96:\
+000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:844A29EFC693E2FA9900F87FBF5DCD5F:\
+000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:5126A1C41051FEA158BE41200E1EA59D:\
+000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:302123CA7B4F46D667FFFB0EB6AA7703:\
+000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:A9D16BCE7DB5C024277709EE2A88D91A:\
+000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:F013C5EC123A26CFC34B598C992A996B:\
+000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:E38A825CD971A1D2E56FB1DBA248F2A8:\
+000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:6E701773C0311E0BD4C5A097406D22B3:\
+000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:754262CEF0C64BE4C3E67C35ABE439F7:\
+000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:C9C2D4C47DF7D55CFA0EE5F1FE5070F4:\
+000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:6AB4BEA85B172573D8BD2D5F4329F13D:\
+000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:11F03EF28E2CC9AE5165C587F7396C8C:\
+000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:0682F2EB1A68BAC7949922C630DD27FA:\
+000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:ABB0FEC0413D659AFE8E3DCF6BA873BB:\
+000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:FE86A32E19F805D6569B2EFADD9C92AA:\
+000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:E434E472275D1837D3D717F2EECC88C3:\
+000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:74E57DCD12A21D26EF8ADAFA5E60469A:\
+000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:C275429D6DAD45DDD423FA63C816A9C1:\
+000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:7F6EC1A9AE729E86F7744AED4B8F4F07:\
+000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:48B5A71AB9292BD4F9E608EF102636B2:\
+000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:076FB95D5F536C78CBED3181BCCF3CF1:\
+000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:BFA76BEA1E684FD3BF9256119EE0BC0F:\
+000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:7D395923D56577F3FF8670998F8C4A71:\
+000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:BA02C986E529AC18A882C34BA389625F:\
+000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:3DFCF2D882AFE75D3A191193013A84B5:\
+000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:FAD1FDE1D0241784B63080D2C74D236C:\
+000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:7D6C80D39E41F007A14FB9CD2B2C15CD:\
+000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:7975F401FC10637BB33EA2DB058FF6EC:\
+000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:657983865C55A818F02B7FCD52ED7E99:\
+000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:B32BEB1776F9827FF4C3AC9997E84B20:\
+000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:2AE2C7C374F0A41E3D46DBC3E66BB59F:\
+000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:4D835E4ABDD4BDC6B88316A6E931A07F:\
+000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:E07EFABFF1C353F7384EBB87B435A3F3:\
+000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:ED3088DC3FAF89AD87B4356FF1BB09C2:\
+000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:4324D01140C156FC898C2E32BA03FB05:\
+000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:BE15D016FACB5BAFBC24FA9289132166:\
+000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:AC9B7048EDB1ACF4D97A5B0B3F50884B:\
+000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:448BECE1F86C7845DFA9A4BB2A016FB3:\
+000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:10DD445E87686EB46EA9B1ABC49257F0:\
+000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:B7FCCF7659FA756D4B7303EEA6C07458:\
+000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:289117115CA3513BAA7640B1004872C2:\
+000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:57CB42F7EE7186051F50B93FFA7B35BF:\
+000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:F2741BFBFB81663B9136802FB9C3126A:\
+000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:E32DDDC5C7398C096E3BD535B31DB5CE:\
+000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:81D3C204E608AF9CC713EAEBCB72433F:\
+000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:D4DEEF4BFC36AAA579496E6935F8F98E:\
+000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:C356DB082B97802B038571C392C5C8F6:\
+000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:A3919ECD4861845F2527B77F06AC6A4E:\
+000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:A53858E17A2F802A20E40D44494FFDA0:\
+000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:5D989E122B78C758921EDBEEB827F0C0:\
+000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:4B1C0C8F9E7830CC3C4BE7BD226FA8DE:\
+000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:82C40C5FD897FBCA7B899C70713573A1:\
+000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:ED13EE2D45E00F75CCDB51EA8E3E36AD:\
+000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:F121799EEFE8432423176A3CCF6462BB:\
+000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:4FA0C06F07997E98271DD86F7B355C50:\
+000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:849EB364B4E81D058649DC5B1BF029B9:\
+000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:F48F9E0DE8DE7AD944A207809335D9B1:\
+000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:E59E9205B5A81A4FD26DFCF308966022:\
+000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:3A91A1BE14AAE9ED700BDF9D70018804:\
+000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:8ABAD78DCB79A48D79070E7DA89664EC:\
+000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:B68377D98AAE6044938A7457F6C649D9:\
+000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:E4E1275C42F5F1B63D662C099D6CE33D:\
+000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:7DEF32A34C6BE668F17DA1BB193B06EF:\
+000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:78B6000CC3D30CB3A74B68D0EDBD2B53:\
+000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:0A47531DE88DD8AE5C23EAE4F7D1F2D5:\
+000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:667B24E8000CF68231EC484581D922E5:\
+000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:39DAA5EBD4AACAE130E9C33236C52024:\
+000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:E3C88760B3CB21360668A63E55BB45D1:\
+000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:F131EE903C1CDB49D416866FD5D8DE51:\
+000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:7A1916135B0447CF4033FC13047A583A:\
+000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:F7D55FB27991143DCDFA90DDF0424FCB:\
+000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:EA93E7D1CA1111DBD8F7EC111A848C0C:\
+000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:2A689E39DFD3CBCBE221326E95888779:\
+000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:C1CE399CA762318AC2C40D1928B4C57D:\
+000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:D43FB6F2B2879C8BFAF0092DA2CA63ED:\
+000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:224563E617158DF97650AF5D130E78A5:\
+000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:6562FDF6833B7C4F7484AE6EBCC243DD:\
+000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:93D58BA7BED22615D661D002885A7457:\
+000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:9A0EF559003AD9E52D3E09ED3C1D3320:\
+000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:96BAF5A7DC6F3DD27EB4C717A85D261C:\
+000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:B8762E06884900E8452293190E19CCDB:\
+000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:785416A22BD63CBABF4B1789355197D3:\
+000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:A0D20CE1489BAA69A3612DCE90F7ABF6:\
+000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:700244E93DC94230CC607FFBA0E48F32:\
+000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:85329E476829F872A2B4A7E59F91FF2D:\
+000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:E4219B4935D988DB719B8B8B2B53D247:\
+000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:6ACDD04FD13D4DB4409FE8DD13FD737B:\
+000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:9EB7A670AB59E15BE582378701C1EC14:\
+000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:29DF2D6935FE657763BC7A9F22D3D492:\
+000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:99303359D4A13AFDBE6C784028CE533A:\
+000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:FF5C70A6334545F33B9DBF7BEA0417CA:\
+000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:289F58A17E4C50EDA4269EFB3DF55815:\
+000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:EA35DCB416E9E1C2861D1682F062B5EB:\
+000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:3A47BF354BE775383C50B0C0A83E3A58:\
+000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:BF6C1DC069FB95D05D43B01D8206D66B:\
+000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:046D1D580D5898DA6595F32FD1F0C33D:\
+000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:5F57803B7B82A110F7E9855D6A546082:\
+000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:25336ECF34E7BE97862CDFF715FF05A8:\
+000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:ACBAA2A943D8078022D693890E8C4FEF:\
+000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:3947597879F6B58E4E2F0DF825A83A38:\
+000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:4EB8CC3335496130655BF3CA570A4FC0:\
+000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:BBDA7769AD1FDA425E18332D97868824:\
+000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:5E7532D22DDB0829A29C868198397154:\
+000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:E66DA67B630AB7AE3E682855E1A1698E:\
+000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:4D93800F671B48559A64D1EA030A590A:\
+000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:F33159FCC7D9AE30C062CD3B322AC764:\
+000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:8BAE4EFB70D33A9792EEA9BE70889D72:\
+000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:E35A6DCB19B201A01EBCFA8AA22B5759:\
+8000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5075C2405B76F22F553488CAE47CE90B:\
+4000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:49DF95D844A0145A7DE01C91793302D3:\
+2000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E7396D778E940B8418A86120E5F421FE:\
+1000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:05F535C36FCEDE4657BE37F4087DB1EF:\
+0800000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D0C1DDDD10DA777C68AB36AF51F2C204:\
+0400000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1C55FB811B5C6464C4E5DE1535A75514:\
+0200000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:52917F3AE957D5230D3A2AF57C7B5A71:\
+0100000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C6E3D5501752DD5E9AEF086D6B45D705:\
+0080000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A24A9C7AF1D9B1E17E1C9A3E711B3FA7:\
+0040000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B881ECA724A6D43DBC6B96F6F59A0D20:\
+0020000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EC524D9A24DFFF2A9639879B83B8E137:\
+0010000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:34C4F345F5466215A037F443635D6F75:\
+0008000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5BA5055BEDB8895F672E29F2EB5A355D:\
+0004000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B3F692AA3A435259EBBEF9B51AD1E08D:\
+0002000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:414FEB4376F2C64A5D2FBB2ED531BA7D:\
+0001000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A20D519E3BCA3303F07E81719F61605E:\
+0000800000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A08D10E520AF811F45BD60A2DC0DC4B1:\
+0000400000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B06893A8C563C430E6F3858826EFBBE4:\
+0000200000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FFEE26AE2D3929C6BD9C6BEDFF84409:\
+0000100000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4D0F5E906ED77801FC0EF53EDC5F9E2B:\
+0000080000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B6EC00119AD8B026DCE56EA7DEFE930:\
+0000040000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:69026591D43363EE9D83B5007F0B484E:\
+0000020000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:27135D86950C6A2F86872706279A4761:\
+0000010000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35E6DB8723F281DA410C3AC8535ED77C:\
+0000008000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:57427CF214B8C28E4BBF487CCB8D0E09:\
+0000004000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6DF01BF56E5131AC87F96E99CAB86367:\
+0000002000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3856C5B55790B768BBF7D43031579BCF:\
+0000001000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1E6ED8FB7C15BC4D2F63BA7037ED44D0:\
+0000000800000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E1B2ED6CD8D93D455534E401156D4BCF:\
+0000000400000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EFBCCA5BDFDAD10E875F02336212CE36:\
+0000000200000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0B777F02FD18DCE2646DCFE868DFAFAD:\
+0000000100000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C8A104B5693D1B14F5BF1F10100BF508:\
+0000000080000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4CCE6615244AFCB38408FECE219962EA:\
+0000000040000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F99E7845D3A255B394C9C050CBA258B1:\
+0000000020000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B4AFBB787F9BCFB7B55FDF447F611295:\
+0000000010000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AE1C426A697FAF2808B7EF6ADDB5C020:\
+0000000008000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7572F92811A85B9BDD38DEAD9945BCAE:\
+0000000004000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:71BC7AA46E43FB95A181527D9F6A360F:\
+0000000002000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5542EF2923066F1EC8F546DD0D8E7CA8:\
+0000000001000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6B92317C7D623790B748FDD7EFC42422:\
+0000000000800000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FE7C097E899C71EF045360F8D6C25CF:\
+0000000000400000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4ECE7EE107D0264D04693151C25B9DF6:\
+0000000000200000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FD6AE687CBFCA9E301045888D3BB9605:\
+0000000000100000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:476B579C8556C7254424902CC1D6D36E:\
+0000000000080000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4133CBCDFDD6B8860A1FC18665D6D71B:\
+0000000000040000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3B36EC2664798C108B816812C65DFDC7:\
+0000000000020000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:364E20A234FEA385D48DC5A09C9E70CF:\
+0000000000010000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4A4BA25969DE3F5EE5642C71AAD0EFD1:\
+0000000000008000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E42CBAAE43297F67A76C1C501BB79E36:\
+0000000000004000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:23CEDEDA4C15B4C037E8C61492217937:\
+0000000000002000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A1719147A1F4A1A1180BD16E8593DCDE:\
+0000000000001000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AB82337E9FB0EC60D1F25A1D0014192C:\
+0000000000000800000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:74BF2D8FC5A8388DF1A3A4D7D33FC164:\
+0000000000000400000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D5B493317E6FBC6FFFD664B3C491368A:\
+0000000000000200000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BA767381586DA56A2A8D503D5F7ADA0B:\
+0000000000000100000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E8E6BC57DFE9CCADB0DECABF4E5CF91F:\
+0000000000000080000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3C8E5A5CDC9CEED90815D1F84BB2998C:\
+0000000000000040000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:283843020BA38F056001B2FD585F7CC9:\
+0000000000000020000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D8ADC7426F623ECE8741A70621D28870:\
+0000000000000010000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D7C5C215592D06F00E6A80DA69A28EA9:\
+0000000000000008000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:52CF6FA433C3C870CAC70190358F7F16:\
+0000000000000004000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F63D442A584DA71786ADEC9F3346DF75:\
+0000000000000002000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:549078F4B0CA7079B45F9A5ADAFAFD99:\
+0000000000000001000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F2A5986EE4E9984BE2BAFB79EA8152FA:\
+0000000000000000800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8A74535017B4DB2776668A1FAE64384C:\
+0000000000000000400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E613342F57A97FD95DC088711A5D0ECD:\
+0000000000000000200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3FFAEBF6B22CF1DC82AE17CD48175B01:\
+0000000000000000100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAFD52EFA15C248CCBF9757735E6B1CE:\
+0000000000000000080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7AF94BC018D9DDD4539D2DD1C6F4000F:\
+0000000000000000040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FE177AD61CA0FDB281086FBA8FE76803:\
+0000000000000000020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:74DBEA15E2E9285BAD163D7D534251B6:\
+0000000000000000010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:23DD21331B3A92F200FE56FF050FFE74:\
+0000000000000000008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A69C5AA34AB20A858CAFA766EACED6D8:\
+0000000000000000004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3F72BB4DF2A4F941A4A09CB78F04B97A:\
+0000000000000000002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:72CC43577E1FD5FD14622D24D97FCDCC:\
+0000000000000000001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D83AF8EBE93E0B6B99CAFADE224937D1:\
+0000000000000000000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:44042329128D56CAA8D084C8BD769D1E:\
+0000000000000000000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:14102D72290DE4F2C430ADD1ED64BA1D:\
+0000000000000000000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:449124097B1ECD0AE7065206DF06F03C:\
+0000000000000000000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D060A99F8CC153A42E11E5F97BD7584A:\
+0000000000000000000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:65605B3EA9261488D53E48602ADEA299:\
+0000000000000000000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C5E5CAD7A208DE8EA6BE049EFE5C7346:\
+0000000000000000000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4C280C46D2181646048DD5BC0C0831A5:\
+0000000000000000000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5DD65CF37F2A0929559AABAFDA08E730:\
+0000000000000000000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:31F2335CAAF264172F69A693225E6D22:\
+0000000000000000000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3E28B35F99A72662590DA96426DD377F:\
+0000000000000000000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:570F40F5D7B20441486578ED344343BE:\
+0000000000000000000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C54308AD1C9E3B19F8B7417873045A8C:\
+0000000000000000000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CBF335E39CE13ADE2B696179E8FD0CE1:\
+0000000000000000000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9C2FBF422355D8293083D51F4A3C18A9:\
+0000000000000000000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5ED8B5A31ECEFAB16C9AA6986DA67BCE:\
+0000000000000000000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:627815DCFC814ABC75900041B1DD7B59:\
+0000000000000000000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9EF3E82A50A59F166260494F7A7F2CC3:\
+0000000000000000000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:878CD0D8D920888B5935D6C351128737:\
+0000000000000000000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E44429474D6FC3084EB2A6B8B46AF754:\
+0000000000000000000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EBAACF9641D54E1FB18D0A2BE4F19BE5:\
+0000000000000000000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:13B3BF497CEE780E123C7E193DEA3A01:\
+0000000000000000000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6E8F381DE00A41161F0DF03B4155BFD4:\
+0000000000000000000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35E4F29BBA2BAE01144910783C3FEF49:\
+0000000000000000000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:55B17BD66788CEAC366398A31F289FFB:\
+0000000000000000000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:11341F56C0D6D1008D28741DAA7679CE:\
+0000000000000000000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:4DF7253DF421D83358BDBE924745D98C:\
+0000000000000000000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAE2EE651116D93EDC8E83B5F3347BE1:\
+0000000000000000000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:F9721ABD06709157183AF3965A659D9D:\
+0000000000000000000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:19A1C252A613FE2860A4AE6D75CE6FA3:\
+0000000000000000000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:B5DDB2F5D9752C949FBDE3FFF5556C6E:\
+0000000000000000000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:81B044FCFFC78ECCFCD171AAD0405C66:\
+0000000000000000000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:C640566D3C06020EB2C42F1D62E56A9B:\
+0000000000000000000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:EA6C4BCF425291679FDFFD26A424FBCC:\
+0000000000000000000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:57F6901465D9440D9F15EE2CBA5A4090:\
+0000000000000000000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:FBCFA74CADC7406260F63D96C8AAB6B1:\
+0000000000000000000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:DFF4F096CEA211D4BBDACA033D0EC7D1:\
+0000000000000000000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:1EE5190D551F0F42F675227A381296A9:\
+0000000000000000000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:F98E1905012E580F097623C10B93054F:\
+0000000000000000000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:E7D43743D21DD3C9F168C86856558B9A:\
+0000000000000000000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:632A9DDA730DAB67593C5D08D8AC1059:\
+0000000000000000000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:E084317000715B9057BC9DE9F3AB6124:\
+0000000000000000000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:61F9EF33A0BB4E666C2ED99101919FAB:\
+0000000000000000000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:6DC1D68A11834657D46703C22578D59A:\
+0000000000000000000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:53AC1548863D3D16F1D4DC7242E05F2C:\
+0000000000000000000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:E82CD587A408306AD78CEAE0916B9F8C:\
+0000000000000000000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:0FD2D40EA6AD17A3A767F0A8600D6295:\
+0000000000000000000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:AD84CC8255ADB39DFCA23F92761AE7E9:\
+0000000000000000000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:F4F20CF7D51BEE7DA024A2B11A7ECA0B:\
+0000000000000000000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:5057691B85D9CE93A193214DB0A016B6:\
+0000000000000000000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:0F58C960876390BDEF4BB6BE95CAA1EE:\
+0000000000000000000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:9A3E66EEBC21BC0BD9430B341EF465FA:\
+0000000000000000000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:20415035F34B8BCBCB28ABF07F78F0D4:\
+0000000000000000000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:AC89FC7BA10479EBF10DE65BCEF89B3C:\
+0000000000000000000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:068FA75A30BE443171AF3F6FEB1A20D2:\
+0000000000000000000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:50E02F213246C525A8C27700CA34B502:\
+0000000000000000000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:227DA47D5A0906DB3AB042BB0A695FB6:\
+0000000000000000000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:8663AC30ED12514F1DE46777F4514BFC:\
+0000000000000000000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:A987D4BC12E1DE9F4B6DF43567C34A8B:\
+0000000000000000000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:6D5A0370F599ACA605F63B04E5143D0C:\
+0000000000000000000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:9809266E378B07B7AFDB3BAA97B7E442:\
+0000000000000000000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:8F753252B30CCCACE12D9A301F4D5090:\
+0000000000000000000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:032465F6C0CE34D41962F561692A1AFF:\
+0000000000000000000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:C50E9AD5BEB8F3B00821DD47FF8AC093:\
+0000000000000000000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:9C6FEA3D46268D54A6829B2AD25BB276:\
+0000000000000000000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:0FD8575E87706F561343D7B3A41E044A:\
+0000000000000000000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:BEE9BEB3739540D88CBCE77925F0A114:\
+0000000000000000000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:D24EAEE7FFFBAC3D6F26C2DCE0DCDE28:\
+0000000000000000000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:47771A90398FF0F7FA821C2F8F5E1398:\
+0000000000000000000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:4639741B6F84B135AD118C8249B64ED0:\
+0000000000000000000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:8EE5505EC85567697A3306F250A27720:\
+0000000000000000000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:7C8A19AC1AEFBC5E0119D91A5F05D4C2:\
+0000000000000000000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:5141B9B672E54773B672E3A6C424887B:\
+0000000000000000000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:B5A2D3CD206653C6402F34FB0AE3613D:\
+0000000000000000000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:0F5BD9408738231D114B0A82753279A3:\
+0000000000000000000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:FEF033FF4268EA487FC74C5E43A45338:\
+0000000000000000000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:A3EDC09DCD529B113910D904AD855581:\
+0000000000000000000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:AB8FBB6F27A0AC7C55B59FDD36B72F1C:\
+0000000000000000000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:EEA44D5ED4D769CC930CD83D8999EC46:\
+0000000000000000000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:6972276803AE9AA7C6F431AB10979C34:\
+0000000000000000000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:86DEAA9F39244101818178474D7DBDE9:\
+0000000000000000000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:88C6B466EA361D662D8D08CBF181F4FE:\
+0000000000000000000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:91AB2C6B7C63FF59F7CBEEBF91B20B95:\
+0000000000000000000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:2DFE6C146AD5B3D8C3C1718F13B48E01:\
+0000000000000000000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:C7CFF1623451711391A302EEC3584AAA:\
+0000000000000000000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:089FE845CC05011686C66019D18BE050:\
+0000000000000000000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:08C8410B9B427211A67124B0DCCEAD48:\
+0000000000000000000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:8D91592F5566085254784606334D7629:\
+0000000000000000000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:3298FEAAF2E1201D6299FF8846639C97:\
+0000000000000000000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:C497CB9F0BDFE0EFC8C2F3F90760AA72:\
+0000000000000000000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:2788AFD046E0309CBE4424690DA2AB89:\
+0000000000000000000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:E9891707F25EF29FEE372890D4258982:\
+0000000000000000000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:DB041D94A23D45D4D4DCED5A030CAF61:\
+0000000000000000000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:FFAFDBF0ECB18DF9EA02C27077448E6D:\
+0000000000000000000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:2DAAA42A7D0A1D3B0E4761D99CF2150A:\
+0000000000000000000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:3B7A54CB7CF30ABE263DD6ED5BFE8D63:\
+0000000000000000000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:EEFA090174C590C448A55D43648F534A:\
+0000000000000000000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:9E15798731ED42F43EA2740A691DA872:\
+0000000000000000000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:31FBD661540A5DEAAD1017CFD3909EC8:\
+0000000000000000000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:CDA9AE05F224140E28CB951721B44D6A:\
+0000000000000000000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:0C5BC512C60A1EAC3434EFB1A8FBB182:\
+0000000000000000000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:AA863610DEEEEB62D045E87EA30B59B5:\
+0000000000000000000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:6AC2448DE568D279C7EEBE1DF403920C:\
+0000000000000000000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:E2011E3D292B26888AE801215FD0CB40:\
+0000000000000000000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:E06F3E15EE3A61672D1C99BADE5B9DBE:\
+0000000000000000000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:BB7027F0548CF6712CEB4C7A4B28E178:\
+0000000000000000000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:061EC21FB70FADBDF87C3BD2AE23825B:\
+0000000000000000000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:4C21F26FE94ABBAC381352375314C3EB:\
+0000000000000000000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:F7CEE6DD99909C2B569EEDA61ED8942E:\
+0000000000000000000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:CE98C4A876C65E4CCB261EBB1D9DF7F5:\
+0000000000000000000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:A5491881CF833C3604ABC08044F402AC:\
+0000000000000000000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:A1BA16E64CCCB3087D57A768507B0BFC:\
+0000000000000000000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:D55951E202D2949EBD3BE43120C738BF:\
+0000000000000000000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:EBB8E43069E69F450EFEC65DCD52B7FD:\
+0000000000000000000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:2B292135663B4AA5ABFE9423D57E7EE9:\
+0000000000000000000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:E91BF974B3BE3AD966249D8655292A85:\
+0000000000000000000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:384365998EAA9562236CC58F6ADF9610:\
+0000000000000000000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:C2E997012AA3D4D8D359C9A947CBE69F:\
+0000000000000000000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:F49421204148BA213BE87E2D5C22B0BF:\
+0000000000000000000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:82ED0ED9953AA92E4DF30929CA65C00F:\
+0000000000000000000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:291EB1D11653C8479437C74A977F5106:\
+0000000000000000000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:BCB997B1939B8983ABD550D6025683E3:\
+0000000000000000000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:1FBA2592C6F489775CAADA71F9B983E9:\
+0000000000000000000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:969F66F217AF1A3DB9E41C1B29039824:\
+0000000000000000000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:A54BB7D6B17E423AC0A7744C19073CB8:\
+0000000000000000000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:B0AC6E6578D1021F47DCF9748A32EAD5:\
+0000000000000000000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:B87B361C3B7B194C77A4358D4669153E:\
+0000000000000000000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:46A133847F96EAA8282A799DC8899D58:\
+0000000000000000000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:2265EC3A9F2D5C9547A091CC8CFB18EA:\
+0000000000000000000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:54CBF3A6FC4FE56D426117AA1FFD1DDE:\
+0000000000000000000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:5312877CCEAB6CFB0905394A370A8003:\
+0000000000000000000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:7190BD6EC613FE38B84ECFE28F702FE4:\
+0000000000000000000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:D1FA5B9CA89A43B04C05F0EF29EF68CD:\
+0000000000000000000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:808285751548ED934FD1056D2D9AE8BA:\
+0000000000000000000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:2758DEF3E7B95A9AE89777BE64D5A6CF:\
+0000000000000000000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:07D81F87DB3E0ACC82B01E08FB22F3C1:\
+0000000000000000000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:8DA250E5553D650711A75EE1CB4FD1C7:\
+0000000000000000000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:A93D946BD0E87F32719DF5F158CEE669:\
+0000000000000000000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:03945236EC2A4D4EAF30B8ABEB54330D:\
+0000000000000000000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:11CC35301F24B79DDE31AEA2D1354F88:\
+0000000000000000000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:E73715B3E8D9A290F44AE6FFBF247E5D:\
+0000000000000000000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:7345E07732B71CB158BBF64CCA5C5B96:\
+0000000000000000000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:6E128F296D24705A1924FD9B70C4ED04:\
+0000000000000000000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:95A789776F036783FBD330947083F54F:\
+0000000000000000000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:360DEC2533EA4AA2E3E54FD3DE2906EB:\
+0000000000000000000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:E68EFD7FECF4D601EA22727BD764965B:\
+0000000000000000000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:9065C64A8BFF44AC33EDBB611CF83D7B:\
+0000000000000000000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:8F33C8DF2A7A51CE8090E8F123BC3723:\
+0000000000000000000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:807F391FFBA8291BA625623210F99018:\
+0000000000000000000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:5E8B3F3A701522CE5CAA761C929D6292:\
+0000000000000000000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:3BA404DC38735A78289E3809E8364835:\
+0000000000000000000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:D23BEDBAD229F8305DC425B6B759DCC9:\
+0000000000000000000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:44880F21CF5913040AE376AEE2A10AD8:\
+0000000000000000000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:9BC98E29D057C0E828C3B5CCE69256C1:\
+0000000000000000000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:B293CC7A975DA141A68279368057CC41:\
+0000000000000000000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:8D60FB87ACD91385B313BE5F1D7BD30F:\
+0000000000000000000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:2C8E56132D70291B303C48FDF75543CD:\
+0000000000000000000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:D1F80035B826791F6CE4E59B7DB1BB0D:\
+0000000000000000000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:42CE6224FC36469339A133DD08173BD4:\
+0000000000000000000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:61817155EA41BCBA2AF7F06AE7CBF585:\
+0000000000000000000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:D1923A9866068D2EF5FB77D57C3315B6:\
+0000000000000000000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:B37CBDB5D719F49691CA968EF2E84140:\
+0000000000000000000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:EC974E653A055D7F8F22171030F68E1D:\
+0000000000000000000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:DDE5D3B9AAD9C32213BB3675A822499C:\
+0000000000000000000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:D3B6E9216EA1AE57EB1C628A3C38AB78:\
+0000000000000000000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:82C99ECC69472B7E96324B042AE8B87A:\
+0000000000000000000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:97144DC5338C43600F84439C0AA0D147:\
+0000000000000000000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:400AC4A0BBADA1DB2121EB144C7E5209:\
+0000000000000000000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:EFD9D550EB419ED278F4885A490AB54C:\
+0000000000000000000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:2AB7816E149B7C0404C88A8857793670:\
+0000000000000000000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:5B591DFF9E8DEE15BAD24C025DBCA481:\
+0000000000000000000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:0C06633E30721C3749F49AD8CBF2B754:\
+0000000000000000000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:96D6D31A41B5123B2035FD91A921D4CA:\
+0000000000000000000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:E7F6C34D86668BC2805CA7793C5E86AD:\
+0000000000000000000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:F46DFF5FF500D6879C4D3E45CF0CF0F3:\
+0000000000000000000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:60D842D9C61DA7495C116197B7CECBBE:\
+0000000000000000000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:D45B24EDB673353EBDF248B8FA06B67A:\
+0000000000000000000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:119EAEBCC165D0BD02C0D35DC82EF992:\
+0000000000000000000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:E673143680414ADA301D0ED34626B9FE:\
+0000000000000000000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:6B6CFE160A6263631B292F879EEFF926:\
+0000000000000000000000000000000000000000000000000000000000000001
+
+80000000000000000000000000000000:3AD78E726C1EC02B7EBFE92B23D9EC34:\
+00000000000000000000000000000000
+
+40000000000000000000000000000000:45BC707D29E8204D88DFBA2F0B0CAD9B:\
+00000000000000000000000000000000
+
+20000000000000000000000000000000:161556838018F52805CDBD6202002E3F:\
+00000000000000000000000000000000
+
+10000000000000000000000000000000:F5569B3AB6A6D11EFDE1BF0A64C6854A:\
+00000000000000000000000000000000
+
+08000000000000000000000000000000:64E82B50E501FBD7DD4116921159B83E:\
+00000000000000000000000000000000
+
+04000000000000000000000000000000:BAAC12FB613A7DE11450375C74034041:\
+00000000000000000000000000000000
+
+02000000000000000000000000000000:BCF176A7EAAD8085EBACEA362462A281:\
+00000000000000000000000000000000
+
+01000000000000000000000000000000:47711816E91D6FF059BBBF2BF58E0FD3:\
+00000000000000000000000000000000
+
+00800000000000000000000000000000:B970DFBE40698AF1638FE38BD3DF3B2F:\
+00000000000000000000000000000000
+
+00400000000000000000000000000000:F95B59A44F391E14CF20B74BDC32FCFF:\
+00000000000000000000000000000000
+
+00200000000000000000000000000000:720F74AE04A2A435B9A7256E49378F5B:\
+00000000000000000000000000000000
+
+00100000000000000000000000000000:2A0445F61D36BFA7E277070730CF76DA:\
+00000000000000000000000000000000
+
+00080000000000000000000000000000:8D0536B997AEFEC1D94011BAB6699A03:\
+00000000000000000000000000000000
+
+00040000000000000000000000000000:674F002E19F6ED47EFF319E51FAD4498:\
+00000000000000000000000000000000
+
+00020000000000000000000000000000:292C02C5CB9163C80AC0F6CF1DD8E92D:\
+00000000000000000000000000000000
+
+00010000000000000000000000000000:FA321CF18EF5FE727DD82A5C1E945141:\
+00000000000000000000000000000000
+
+00008000000000000000000000000000:A5A7AFE1034C39CCCEBE3C584BC0BE05:\
+00000000000000000000000000000000
+
+00004000000000000000000000000000:4FF5A52E697E77D081205DBDB21CEA39:\
+00000000000000000000000000000000
+
+00002000000000000000000000000000:209E88DC94C9003000CE0769AF7B7166:\
+00000000000000000000000000000000
+
+00001000000000000000000000000000:5DEE41AF864CB4B650E5F51551824D38:\
+00000000000000000000000000000000
+
+00000800000000000000000000000000:A79A63FA7E4503AE6D6E09F5F9053030:\
+00000000000000000000000000000000
+
+00000400000000000000000000000000:A48316749FAE7FAC7002031A6AFD8BA7:\
+00000000000000000000000000000000
+
+00000200000000000000000000000000:D6EEE8A7357A0E1D64262CA9C337AC42:\
+00000000000000000000000000000000
+
+00000100000000000000000000000000:B013CA8A62A858053E9FB667ED39829E:\
+00000000000000000000000000000000
+
+00000080000000000000000000000000:DF6EA9E4538A45A52D5C1A43C88F4B55:\
+00000000000000000000000000000000
+
+00000040000000000000000000000000:7D03BA451371591D3FD5547D9165C73B:\
+00000000000000000000000000000000
+
+00000020000000000000000000000000:0E0426281A6277E186499D365D5F49FF:\
+00000000000000000000000000000000
+
+00000010000000000000000000000000:DBC02169DD2059E6CC4C57C1FEDF5AB4:\
+00000000000000000000000000000000
+
+00000008000000000000000000000000:826590E05D167DA6F00DCC75E22788EB:\
+00000000000000000000000000000000
+
+00000004000000000000000000000000:34A73F21A04421D9786335FAAB49423A:\
+00000000000000000000000000000000
+
+00000002000000000000000000000000:ED347D0E0128EE1A7392A1D36AB78AA9:\
+00000000000000000000000000000000
+
+00000001000000000000000000000000:EE944B2FE6E9FC888042608DA9615F75:\
+00000000000000000000000000000000
+
+00000000800000000000000000000000:9E7C85A909EF7218BA7947CFB4718F46:\
+00000000000000000000000000000000
+
+00000000400000000000000000000000:811AE07A0B2B1F816587FA73699AE77D:\
+00000000000000000000000000000000
+
+00000000200000000000000000000000:68466FBF43C2FE13D4B18F7EC5EA745F:\
+00000000000000000000000000000000
+
+00000000100000000000000000000000:D20B015C7191B219780956E6101F9354:\
+00000000000000000000000000000000
+
+00000000080000000000000000000000:5939D5C1BBF54EE1B3E326D757BDDE25:\
+00000000000000000000000000000000
+
+00000000040000000000000000000000:B1FDAFE9A0240E8FFEA19CE94B5105D3:\
+00000000000000000000000000000000
+
+00000000020000000000000000000000:D62962ECE02CDD68C06BDFEFB2F9495B:\
+00000000000000000000000000000000
+
+00000000010000000000000000000000:B3BB2DE6F3C26587BA8BAC4F7AD9499A:\
+00000000000000000000000000000000
+
+00000000008000000000000000000000:E0B1072D6D9FF703D6FBEF77852B0A6B:\
+00000000000000000000000000000000
+
+00000000004000000000000000000000:D8DD51C907F478DE0228E83E61FD1758:\
+00000000000000000000000000000000
+
+00000000002000000000000000000000:A42DFFE6E7C1671C06A25236FDD10017:\
+00000000000000000000000000000000
+
+00000000001000000000000000000000:25ACF141550BFAB9EF451B6C6A5B2163:\
+00000000000000000000000000000000
+
+00000000000800000000000000000000:4DA7FCA3949B16E821DBC84F19581018:\
+00000000000000000000000000000000
+
+00000000000400000000000000000000:7D49B6347CBCC8919C7FA96A37A7A215:\
+00000000000000000000000000000000
+
+00000000000200000000000000000000:900024B29A08C6721B95BA3B753DDB4D:\
+00000000000000000000000000000000
+
+00000000000100000000000000000000:6D2182FB283B6934D90BA7848CAB5E66:\
+00000000000000000000000000000000
+
+00000000000080000000000000000000:F73EF01B448D23A4D90DE8B2F9666E7A:\
+00000000000000000000000000000000
+
+00000000000040000000000000000000:4AD9CDA2418643E9A3D926AF5E6B0412:\
+00000000000000000000000000000000
+
+00000000000020000000000000000000:7CAEC8E7E5953997D545B033201C8C5B:\
+00000000000000000000000000000000
+
+00000000000010000000000000000000:3C43CA1F6B6864503E27B48D88230CF5:\
+00000000000000000000000000000000
+
+00000000000008000000000000000000:44F779B93108FE9FEEC880D79BA74488:\
+00000000000000000000000000000000
+
+00000000000004000000000000000000:9E50E8D9CFD3A682A78E527C9072A1CF:\
+00000000000000000000000000000000
+
+00000000000002000000000000000000:68D000CBC838BBE3C505D6F814C01F28:\
+00000000000000000000000000000000
+
+00000000000001000000000000000000:2CB2A9FEC1ACD1D9B0FA05205E304F57:\
+00000000000000000000000000000000
+
+00000000000000800000000000000000:01EB2806606E46444520A5CC6180CD4B:\
+00000000000000000000000000000000
+
+00000000000000400000000000000000:DAA9B25168CC702326F217F1A0C0B162:\
+00000000000000000000000000000000
+
+00000000000000200000000000000000:3E07E648975D9578D03555B1755807ED:\
+00000000000000000000000000000000
+
+00000000000000100000000000000000:0B45F52E802C8B8DE09579425B80B711:\
+00000000000000000000000000000000
+
+00000000000000080000000000000000:659595DA0B68F6DF0DD6CA77202986E1:\
+00000000000000000000000000000000
+
+00000000000000040000000000000000:05FF42873893536E58C8FA98A45C73C4:\
+00000000000000000000000000000000
+
+00000000000000020000000000000000:B5B03421DE8BBFFC4EADEC767339A9BD:\
+00000000000000000000000000000000
+
+00000000000000010000000000000000:788BCD111ECF73D4E78D2E21BEF55460:\
+00000000000000000000000000000000
+
+00000000000000008000000000000000:909CD9EC6790359F982DC6F2393D5315:\
+00000000000000000000000000000000
+
+00000000000000004000000000000000:332950F361535FF24EFAC8C76293F12C:\
+00000000000000000000000000000000
+
+00000000000000002000000000000000:A68CCD4E330FFDA9D576DA436DB53D75:\
+00000000000000000000000000000000
+
+00000000000000001000000000000000:27C8A1CCFDB0B015D1ED5B3E77143791:\
+00000000000000000000000000000000
+
+00000000000000000800000000000000:D76A4B95887A77DF610DD3E1D3B20325:\
+00000000000000000000000000000000
+
+00000000000000000400000000000000:C068AB0DE71C66DAE83C361EF4B2D989:\
+00000000000000000000000000000000
+
+00000000000000000200000000000000:C2120BCD49EDA9A288B3B4BE79AC8158:\
+00000000000000000000000000000000
+
+00000000000000000100000000000000:0C546F62BF2773CD0F564FCECA7BA688:\
+00000000000000000000000000000000
+
+00000000000000000080000000000000:18F3462BEDE4920213CCB66DAB1640AA:\
+00000000000000000000000000000000
+
+00000000000000000040000000000000:FE42F245EDD0E24B216AEBD8B392D690:\
+00000000000000000000000000000000
+
+00000000000000000020000000000000:3D3EEBC8D3D1558A194C2D00C337FF2B:\
+00000000000000000000000000000000
+
+00000000000000000010000000000000:29AAEDF043E785DB42836F79BE6CBA28:\
+00000000000000000000000000000000
+
+00000000000000000008000000000000:215F90C6744E2944358E78619159A611:\
+00000000000000000000000000000000
+
+00000000000000000004000000000000:8606B1AA9E1D548E5442B06551E2C6DC:\
+00000000000000000000000000000000
+
+00000000000000000002000000000000:987BB4B8740EC0EDE7FEA97DF033B5B1:\
+00000000000000000000000000000000
+
+00000000000000000001000000000000:C0A3500DA5B0AE07D2F450930BEEDF1B:\
+00000000000000000000000000000000
+
+00000000000000000000800000000000:525FDF8312FE8F32C781481A8DAAAE37:\
+00000000000000000000000000000000
+
+00000000000000000000400000000000:BFD2C56AE5FB9C9DE33A6944572A6487:\
+00000000000000000000000000000000
+
+00000000000000000000200000000000:7975A57A425CDF5AA1FA929101F650B0:\
+00000000000000000000000000000000
+
+00000000000000000000100000000000:BF174BC49609A8709B2CD8366DAA79FE:\
+00000000000000000000000000000000
+
+00000000000000000000080000000000:06C50C43222F56C874B1704E9F44BF7D:\
+00000000000000000000000000000000
+
+00000000000000000000040000000000:0CEC48CD34043EA29CA3B8ED5278721E:\
+00000000000000000000000000000000
+
+00000000000000000000020000000000:9548EA34A1560197B304D0ACB8A1698D:\
+00000000000000000000000000000000
+
+00000000000000000000010000000000:22F9E9B1BD73B6B5B7D3062C986272F3:\
+00000000000000000000000000000000
+
+00000000000000000000008000000000:FEE8E934BD0873295059002230E298D4:\
+00000000000000000000000000000000
+
+00000000000000000000004000000000:1B08E2E3EB820D139CB4ABBDBE81D00D:\
+00000000000000000000000000000000
+
+00000000000000000000002000000000:0021177681E4D90CEAF69DCED0145125:\
+00000000000000000000000000000000
+
+00000000000000000000001000000000:4A8E314452CA8A8A3619FC54BC423643:\
+00000000000000000000000000000000
+
+00000000000000000000000800000000:65047474F7222C94C6965425FF1BFD0A:\
+00000000000000000000000000000000
+
+00000000000000000000000400000000:E123F551A9C4A8489622B16F961A9AA4:\
+00000000000000000000000000000000
+
+00000000000000000000000200000000:EF05530948B80915028BB2B6FE429380:\
+00000000000000000000000000000000
+
+00000000000000000000000100000000:72535B7FE0F0F777CEDCD55CD77E2DDF:\
+00000000000000000000000000000000
+
+00000000000000000000000080000000:3423D8EFC31FA2F4C365C77D8F3B5C63:\
+00000000000000000000000000000000
+
+00000000000000000000000040000000:DE0E51C264663F3C5DBC59580A98D8E4:\
+00000000000000000000000000000000
+
+00000000000000000000000020000000:B2D9391166680947AB09264156719679:\
+00000000000000000000000000000000
+
+00000000000000000000000010000000:10DB79F23B06D263835C424AF749ADB7:\
+00000000000000000000000000000000
+
+00000000000000000000000008000000:DDF72D27E6B01EC107EA3E005B59563B:\
+00000000000000000000000000000000
+
+00000000000000000000000004000000:8266B57485A5954A4236751DE07F6694:\
+00000000000000000000000000000000
+
+00000000000000000000000002000000:669A501E1F1ADE6E5523DE01D6DBC987:\
+00000000000000000000000000000000
+
+00000000000000000000000001000000:C20C48F2989725D461D1DB589DC0896E:\
+00000000000000000000000000000000
+
+00000000000000000000000000800000:DE35158E7810ED1191825D2AA98FA97D:\
+00000000000000000000000000000000
+
+00000000000000000000000000400000:4FE294F2C0F34D0671B693A237EBDDC8:\
+00000000000000000000000000000000
+
+00000000000000000000000000200000:087AE74B10CCBFDF6739FEB9559C01A4:\
+00000000000000000000000000000000
+
+00000000000000000000000000100000:5DC278970B7DEF77A5536C77AB59C207:\
+00000000000000000000000000000000
+
+00000000000000000000000000080000:7607F078C77085184EAA9B060C1FBFFF:\
+00000000000000000000000000000000
+
+00000000000000000000000000040000:9DB841531BCBE7998DAD19993FB3CC00:\
+00000000000000000000000000000000
+
+00000000000000000000000000020000:D6A089B654854A94560BAE13298835B8:\
+00000000000000000000000000000000
+
+00000000000000000000000000010000:E1E223C4CF90CC5D195B370D65114622:\
+00000000000000000000000000000000
+
+00000000000000000000000000008000:1CBED73C50D053BDAD372CEEE54836A1:\
+00000000000000000000000000000000
+
+00000000000000000000000000004000:D309E69376D257ADF2BFDA152B26555F:\
+00000000000000000000000000000000
+
+00000000000000000000000000002000:740F7649117F0DEE6EAA7789A9994C36:\
+00000000000000000000000000000000
+
+00000000000000000000000000001000:76AE64417C297184D668C5FD908B3CE5:\
+00000000000000000000000000000000
+
+00000000000000000000000000000800:6095FEA4AA8035591F1787A819C48787:\
+00000000000000000000000000000000
+
+00000000000000000000000000000400:D1FF4E7ACD1C79967FEBAB0F7465D450:\
+00000000000000000000000000000000
+
+00000000000000000000000000000200:5F5AD3C42B9489557BB63BF49ECF5F8A:\
+00000000000000000000000000000000
+
+00000000000000000000000000000100:FB56CC09B680B1D07C5A52149E29F07C:\
+00000000000000000000000000000000
+
+00000000000000000000000000000080:FF49B8DF4A97CBE03833E66197620DAD:\
+00000000000000000000000000000000
+
+00000000000000000000000000000040:5E070ADE533D2E090ED0F5BE13BC0983:\
+00000000000000000000000000000000
+
+00000000000000000000000000000020:3AB4FB1D2B7BA376590A2C241D1F508D:\
+00000000000000000000000000000000
+
+00000000000000000000000000000010:58B2431BC0BEDE02550F40238969EC78:\
+00000000000000000000000000000000
+
+00000000000000000000000000000008:0253786E126504F0DAB90C48A30321DE:\
+00000000000000000000000000000000
+
+00000000000000000000000000000004:200211214E7394DA2089B6ACD093ABE0:\
+00000000000000000000000000000000
+
+00000000000000000000000000000002:0388DACE60B6A392F328C2B971B2FE78:\
+00000000000000000000000000000000
+
+00000000000000000000000000000001:58E2FCCEFA7E3061367F1D57A4E7455A:\
+00000000000000000000000000000000
+
+80000000000000000000000000000000:6CD02513E8D4DC986B4AFE087A60BD0C:\
+000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:423D2772A0CA56DAABB48D2129062987:\
+000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:1021F2A8DA70EB2219DC16804445FF98:\
+000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:C636E35B402577F96974D8804295EBB8:\
+000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:1566D2E57E8393C19E29F892EA28A9A7:\
+000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:883C878FED70B36CC09D040F9619DD19:\
+000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:06734593A974965790E715594FC34AA9:\
+000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:F19B389948D9A45534E5BD36C984134A:\
+000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:D8410DFC14FA6D175EC968EA8CAC514C:\
+000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:7E6C6EBB4029A177CF7B2FDD9AC6BB7A:\
+000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:4B51DD4850DC0A6C3A46D924003D2C27:\
+000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:2E510A9D917B15BE32A192B12A668F23:\
+000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:88F6F79962B0FB77FEA8E7C632D3108E:\
+000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:A3A35AB1D88DAF07B52794A0F065383A:\
+000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:DC6CC878433E2B3BB193049A4ECBFC53:\
+000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:EFCD3763EB7B1A415938248A9A5B4FD5:\
+000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:AB7E9FB9A66DBE5BB44854F07D9015EE:\
+000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:8B8E9D3365F8F6743ECF7E33E99255A4:\
+000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:54D37B4F176FF3D8F6AFC866066D8572:\
+000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:E83310889480FBF3C00342E3126D0D02:\
+000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:D321AB2511F92F098174AA2DE6E85DA2:\
+000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:D8E3F40B1112D5149D58C481DFA9983F:\
+000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:2454C4E0806639DDF19854D6C68054AD:\
+000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:A5506D410F7CA32F3955DD79D9D09418:\
+000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:7908EE40677699568A7DC1AA317C7E4E:\
+000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:B4B7B29DD43B2F5CF765E25192273982:\
+000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:92AFE9668159BEFFE2A86F8503260164:\
+000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:5C36A232FBA6D187A84657AD4028B18F:\
+000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:A2E994DFAB3A798DF8F54F6DA87E58E2:\
+000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:6CDAB10A72ADF77D71D0765BAAE95631:\
+000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:9FE3C801BCAAF7BB800F2E6BF3278E21:\
+000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:B459D90D9A6C392E5493BC91CF5A0863:\
+000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:0518A9FA5007F6787E0FB4E5AC27D758:\
+000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:BED9795415D28599700ED7952384A963:\
+000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:F0140421173D60251EF6CAB0229B1B50:\
+000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:460EB4652B3F6779EA28CB11B37529ED:\
+000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:C4283D351C960A6AC13CD19CCF03AE38:\
+000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:6815A10047B2C834A798EBDCC6786C75:\
+000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:99BA19F0CDD5990D0386B32CE56C9C4C:\
+000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:DE76F62C61E07915162DA13E79679DEC:\
+000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:DD0325D6854803D06D1D2277D5FB8D67:\
+000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:580B71A41DE37D6FAC83CCB0B3BB1C97:\
+000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:E9B1AB470A1B02EF0FF5E6754A092C96:\
+000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:8590620F5AF5993B7410282F4126BC1F:\
+000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:8D4914D2F1B22B2E268E66E532D29D7C:\
+000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:FD826CE48E62C5E30867044B86BA4B56:\
+000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:100E7B831C9F35FA1271F5F1316C6FCF:\
+000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:0A2DD0C17F68B996AA96C007003D0B31:\
+000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:C95F68C57E06B0A2E1F623C83C5D80BF:\
+000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:571CAFC92C7C8A5EC54C0741E186905C:\
+000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:22514353E95312C112255E1EED0B2DF6:\
+000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:791A8BF462BD17580BD9152C6D11C6C5:\
+000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:5882A0178D548F84A165DB809C60DC28:\
+000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:3CE4A90EED4458CA6039E42DDADB71C3:\
+000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:D3CBAB261207A16BE2751E77044FD7C9:\
+000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:24E32B698A7B32217093628B01F424AB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:9F6AFC0AF27CF565110C77E3C24F4F5B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:E088AA5CDA20EF267BB039B00C72C45B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:5CF1018B7E0BA1775601C2E279900360:\
+000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:3B1A7388B89FB9416AD8753CF5AF35D2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:137FA4ED00AFCD9F5D8BC0D14BD5837A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:806F5C9B663559BB56F234881E4A3E60:\
+000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:8069A449152292DF2DE8642992C632B6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:37C6CF2A1ABD1B1F1922B46C7B4A280D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:7A2835260E5A0AA2B5DC301800EC8438:\
+000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:EE81FAF2F9058213FFCACF281CB8509E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:57F22D93C37129BA331FDBA38E005A1E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:EC798782E87B7D9F780CC3C3A46519B5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:43EA28497F5D40E3A4744FA2EDAA42DE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:91F004E7DEBF41B3414DD8C5C317372C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:C249EAE54E7B4DF43B938C1B4CC28314:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:32C289D7EEFB99D2F17AD7B7D45FE1EC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:A675FB2E8DDBF810CEF01CF2B728CD2B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:A418AAAB6E6921CC731AA8A349386080:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:2E2B0F44863E67D9B0215C4ABD60417F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:F0AF7CB19E911D481F6426DAEFDD2240:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:CB1304DAAA2DF6878F56AC2E0F887E04:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:B1B70A7E6A0CD1916D9B78BEA19084AE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:0CDE9F9BE646A5FCE3436B794A9CFC65:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:68C7946D476A0A36674B36AFD7E5DF33:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:48770159A07DD8DFFF06C80105F8D57C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:665E62801B3260E3C45BD3BE34DFDEBE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:4159C1F686BFBE5B0E50BDB0DA532B69:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:6333100A5A4AD917DC2D4E78A04869A3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:866A4519AB1D199F25886B89D0539ACC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:EC0CFD37E4CBC7E8BE385283F7AEA75A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:CA2F383AACCA0810AA13F3E710621422:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:1D0EEF6870444F950937831EC0A55D98:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:37839B35ED6801E7670496D479A95017:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:02317C8C7098C4F94AB867AC7A49DD8D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:FFB4CB4E3F7F8BF3367EBD43236518B4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:36BEDEF1E4AA3E4A40A305741713FCBF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:B2DFE3C4870269C1E3FEEC39161540D9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:147EF2518AD45DA0026056ECBF6A3DFA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:027A75E4DE635790E47ACE90D7928804:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:C4CF3CCB59BF87D0AFBD629F48CFBB7B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:35165C93F564C97E1C32EF97E8151A87:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:449DE37F7D5A1BBD628ABBE7E061701D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:B1D45EAF218F1799B149BAD677FE129F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:BE08AC6DB6BD0583AA9D2ABC71C73DCD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:BCC835BD3DF1A79E4C7C145B899A5C25:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:3D311EA611FF5AF371301C58A8E9912D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:A5A1BEA594ACC7CA80F09EA5ADDB5C71:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:0F09492429FE7222D6CD8190D9F2FFBF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:816D2220A16B8AAEE71364FD43636C6F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:D7E8702408419ED73191B107EAF75A0B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:9B170EFB1E235B433C78E276BEA082F0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:03BBECC5598AE974430F29395522F096:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:DB53517766C0E8CF42059607CBA89380:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:2E2AF4B7931F0AEFFAC5471148A5BB97:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:C872C0408266403B984F635FF5683DE4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:15DCF750B0E3A68AD1F4EFD07E8967B4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:B41092048E9E6A749F6FD8CE515A23A3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:4DA9267D62507994312BD5C99ADDE730:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:9E2FCA6D1D626E9C6A924EBF7DBF618A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:E092E8D7EF2C2465AEFB2493C3063590:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:1C0E58DA37D1068378A88DBE2EDE4E10:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:19063F854232B8509A6A3A6D46809959:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:447FB09E54EFA285F7530F25C4EA0022:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:F6ABE86321BE40E1FBFDAFED37CC1D9B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:4E8506CD006666341D6CF51F98B41F35:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:53995DE0009CA18BECAFB8307C54C14C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:2006BF99F4C58B6CC2627856593FAEEA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:2DA697D2737CB30B744A4644FA1CBC6E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:47A22ACDB60C3A986A8F76ECD0EA3433:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:FDAA17C2CDE20268FE36E164EA532151:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:98E7247C07F0FE411C267E4384B0F600:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:CD33B28AC773F74BA00ED1F312572435:\
+000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:DDC6BF790C15760D8D9AEB6F9A75FD4E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:C7098C217C334D0C9BDF37EA13B0822C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:60F0FB0D4C56A8D4EEFEC5264204042D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:73376FBBF654D0686E0E84001477106B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:2F443B52BA5F0C6EA0602C7C4FD259B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:75D11B0E3A68C4223D88DBF017977DD7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:779B38D15BFFB63D8D609D551A5CC98E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:5275F3D86B4FB8684593133EBFA53CD3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:1CEF2074B336CEC62F12DEA2F6AB1481:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:1AEF5ABBAD9D7160874578DCD8BAE172:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:46C525DB17E72F26BF03216846B6F609:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:E24411F941BBE08788781E3EC52CBAA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:83A3DEDD1DD27018F6A6477E40527581:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:B68F8A2CDBAB0C923C67FC8F0F1087DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:649944A70C32BF87A7409E7AE128FDE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:2846526D67387539C89314DE9E0C2D02:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:A9A0B8402E53C70DD1688054BA58DDFD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:4A72E6E1B79C83AC4BE3EBA5699EED48:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:B0E36B867BA4FF2B77D0614B0E364E4C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:49B57DE141F6418E3090F24DDD4014B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:A6C0D5B9797258E1987AC5F6CD20146D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:426CF4BDCAA369175965D26E7C71EEA2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:E27F484CE54BC99BC1A52BDA3B518A26:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:D16D186284C7E6EE64B8104E0EF20BA5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:6431F8538AD54E1E044A9F71F8EF556B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:ECD57CEB451D27EB96C55B2042257E8E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:4F0F188DC911B1954AFBC734C9F68872:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:B54DEF0337626B65614E81EDFDE620F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:6655D8074CAE0B90B0D3A3FE72D4D9DB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:C6B74B6B9EB4FC0C9A237DB1B616D09A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:D7B5D076EA56EC2B20791D7AD51CCF8F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:FE160C224BF003CE3BDDC90CB52ED22C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:5E00DA9BA94B5EC0D258D8A8002E0F6A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:09AC6DCFF4DACFF1651E2BA212A292A3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:B283617E318D99AF83A05D9810BA89F7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:0B5F70CCB40B0EF2538AE9B4A9770B35:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:43282BF180248FB517839B37F4DDAAE4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:DDBD534C8B2E6D30A268F88C55AD765B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:A41A164E50EC2D9F175E752B755E0B5C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:37BFF99FF2F7AA97779E4ADF6F13FB10:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:9BA4F7BD298152903A683C4CEC669216:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:5FB750C7CE10DE7B4504248914D0DA06:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:3E748BFA108E086F51D56EC74A9E0FB9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:31D4E56B99F5B73C1B8437DF332AFB98:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:9DC6717B84FC55D266E7B1D9B5C52A5F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:8EF8BA007F23C0A50FC120E07041BCCD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:C58F38E1839FC1918A12B8C9E88C66B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:B695D72A3FCF508C4050E12E40061C2D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:5D2736AD478A50583BC8C11BEFF16D7A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:DF0EACA8F17847AD41F9578F14C7B56B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:E5AA14AD48AD0A3C47CC35D5F8020E51:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:11BE6C8F58EBD8CEF1A53F591A68E8CE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:ECFE7BAFCBF42C1FEE015488770B3053:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:E552649F8D8EC4A1E1CD6DF50B6E6777:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:521C0629DE93B9119CDB1DDC5809DDEA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:CB38A62A0BAB1784156BA038CBA99BF6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:76CCEE8AAACD394DE1EEF3DDA10CB54B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:6AFF910FA1D5673140E2DB59B8416049:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:064A12C0EF73FB386801BF4F35F3120D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:2240E374929D5B1BB8FF0FFDDDF640EC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:D4BA15C904C7692185DE85C02052E180:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:1714A315AB0166728A44CD91D4AE9018:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:6C970BDD9F0E222722EA31A1D12DD0AD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:F5956EDF02BD36A401BBB6CE77C3D3FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:0CA11F122CCD7C259DC597EED3DF9BC4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:50109AB4912AD2560B206F331B62EB6C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:DBE7C91A4175614889A2D4BEFD64845E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:0D3322853A571A6B46B79C0228E0DD25:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:96E4EE0BB9A11C6FB8522F285BADDEB6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:96705C52D2CFCE82E630C93477C79C49:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:C50130AED6A126149D71F3888C83C232:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:4816EFE3DEB380566EBA0C17BF582090:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:0390857B4C8C98E4CF7A2B6F3394C507:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:422E73A02025EBE8B8B5D6E0FA24FCB2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:3271AA7F4BF1D7C38050A43076D4FF76:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:D2074946F0D37B8975607BFC2E70234C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:1A509194C1270AB92E5A42D3A9F8D98B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:512438946360CCC4A5C6D73F6EED7130:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:98CFCDEC46EBEA1A286B3004F2746A0D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:A1CF369949677A3AF3D58E3EABF2741B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:D84C2E1A0E4A52166FA8FF6889D1E5E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:4AD91CCEEF60119B5078FD162D2735DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:2860793D818E97AAFF1D339D7702438D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:6F9068BE73364AE250D89D78A6C9CE6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:024FC3FEF4883FEB1A8DD005305FECCE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:08A61FE0816D75EA15EB3C9FB9CCDED6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:449C86DFA13F260175CE39797686FFA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:4FFFFC29A59858E1133F2BFB1A8A4817:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:19425D1F6480B25096561295697DC2B7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:31974727ECDD2C77C3A428FC3A8CB3FC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:A57CD704B3C95E744D08DF443458F2F5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:486D8C193DB1ED73ACB17990442FC40B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:5E4DBF4E83AB3BC055B9FCC7A6B3A763:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:ACF2E0A693FBBCBA4D41B861E0D89E37:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:32A7CB2AE066A51D2B78FC4B4CFCB608:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:677D494DBB73CAF55C1990158DA12F14:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:082A0D2367512ADF0D75A151BFBE0A17:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:5E5BB7337923C482CE8CBA249E6A8C7D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:D3001BA7C7026EE3E5003179530AFCFC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:46EC44F8931E629FE8FD8961312EDDE1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:C5F8ECD79C7B30E81D17E32079969310:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:5B8AD6919E24CAEBCC55401AEE0C9802:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:C2302B7E701B5CC7F8B29E3516DBBFA6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:A1D04D6A76F9F7A94D49FAA64A87F244:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:7FB6F92D35B5CB6C631600EDB9E860BA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:B2EF7078BCFACE07AEEC3F9B48830EB3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:F475A7493D24C7036E53390374C378B3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:B36802AC987377A37BD8EADC97C57D60:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:ADDCD3D19689C4DDC738CE5F69DC9505:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:0DAF8CA22884915403C0F0BB1F4BD74F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:4AF36BAE2660503B3248E4685059FD05:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:7D5631814DD8E917D97A0D514C743971:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:BC3352500FC0CBB9DB5B5F6B491C1BE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:6A4A30BA87E87AF65C90AEB7AFEDC76B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:77E6125897668AC8E73E8C79A6FF8336:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:3FA9D39104EBB323C7AAAA248960DD1E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:FAD75AD76AB10ADC49036B250E229D39:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:2FACAA5FE35B228A16AC74088D702EC4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:88B6CBCFDFEF8AD91720A1BB69A1F33E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:C7E9D250998632D444356242EF04058D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:B14DAD8D3D9153F46C0D3A1AD63C7A05:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:60ABA678A506608D0845966D29B5F790:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:482DC43F2388EF25D24144E144BD834E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:1490A05A7CEE43BDE98B56E309DC0126:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:ABFA77CD6E85DA245FB0BDC5E52CFC29:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:DD4AB1284D4AE17B41E85924470C36F7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:CEA7403D4D606B6E074EC5D3BAF39D18:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:530F8AFBC74536B9A963B4F1C4CB738B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+
+
+
+# From FIPS 197
+00112233445566778899AABBCCDDEEFF:69C4E0D86A7B0430D8CDB78070B4C55A:\
+000102030405060708090A0B0C0D0E0F
+00112233445566778899AABBCCDDEEFF:DDA97CA4864CDFE06EAF70A0EC0D7191:\
+000102030405060708090A0B0C0D0E0F1011121314151617
+00112233445566778899AABBCCDDEEFF:8EA2B7CA516745BFEAFC49904B496089:\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+
+506812A45F08C889B97F5980038B8359:D8F532538289EF7D06B506A4FD5BE9C9:\
+00010203050607080A0B0C0D0F101112
+5C6D71CA30DE8B8B00549984D2EC7D4B:59AB30F4D4EE6E4FF9907EF65B1FB68C:\
+14151617191A1B1C1E1F202123242526
+53F3F4C64F8616E4E7C56199F48F21F6:BF1ED2FCB2AF3FD41443B56D85025CB1:\
+28292A2B2D2E2F30323334353738393A
+A1EB65A3487165FB0F1C27FF9959F703:7316632D5C32233EDCB0780560EAE8B2:\
+3C3D3E3F41424344464748494B4C4D4E
+3553ECF0B1739558B08E350A98A39BFA:408C073E3E2538072B72625E68B8364B:\
+50515253555657585A5B5C5D5F606162
+67429969490B9711AE2B01DC497AFDE8:E1F94DFA776597BEACA262F2F6366FEA:\
+64656667696A6B6C6E6F707173747576
+93385C1F2AEC8BED192F5A8E161DD508:F29E986C6A1C27D7B29FFD7EE92B75F1:\
+78797A7B7D7E7F80828384858788898A
+3E23B3BC065BCC152407E23896D77783:1959338344E945670678A5D432C90B93:\
+54555657595A5B5C5E5F606163646566
+79F0FBA002BE1744670E7E99290D8F52:E49BDDD2369B83EE66E6C75A1161B394:\
+68696A6B6D6E6F70727374757778797A
+DA23FE9D5BD63E1D72E3DAFBE21A6C2A:D3388F19057FF704B70784164A74867D:\
+7C7D7E7F81828384868788898B8C8D8E
+E3F5698BA90B6A022EFD7DB2C7E6C823:23AA03E2D5E4CD24F3217E596480D1E1:\
+A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6
+BDC2691D4F1B73D2700679C3BCBF9C6E:C84113D68B666AB2A50A8BDB222E91B9:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2
+BA74E02093217EE1BA1B42BD5624349A:AC02403981CD4340B507963DB65CB7B6:\
+08090A0B0D0E0F10121314151718191A
+B5C593B5851C57FBF8B3F57715E8F680:8D1299236223359474011F6BF5088414:\
+6C6D6E6F71727374767778797B7C7D7E
+
+FEC1C04F529BBD17D8CECFCC4718B17F:62564C738F3EFE186E1A127A0C4D3C61:\
+4A4B4C4D4F50515254555657595A5B5C5E5F606163646566
+32DF99B431ED5DC5ACF8CAF6DC6CE475:07805AA043986EB23693E23BEF8F3438:\
+68696A6B6D6E6F70727374757778797A7C7D7E7F81828384
+7FDC2B746F3F665296943B83710D1F82:DF0B4931038BADE848DEE3B4B85AA44B:\
+868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2
+8FBA1510A3C5B87E2EAA3F7A91455CA2:592D5FDED76582E4143C65099309477C:\
+A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0
+2C9B468B1C2EED92578D41B0716B223B:C9B8D6545580D3DFBCDD09B954ED4E92:\
+C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE
+0A2BBF0EFC6BC0034F8A03433FCA1B1A:5DCCD5D6EB7C1B42ACB008201DF707A0:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFC
+25260E1F31F4104D387222E70632504B:A2A91682FFEB6ED1D34340946829E6F9:\
+FEFE01010304050608090A0B0D0E0F10121314151718191A
+C527D25A49F08A5228D338642AE65137:E45D185B797000348D9267960A68435D:\
+1C1D1E1F21222324262728292B2C2D2E3031323335363738
+3B49FC081432F5890D0E3D87E884A69E:45E060DAE5901CDA8089E10D4F4C246B:\
+3A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+D173F9ED1E57597E166931DF2754A083:F6951AFACC0079A369C71FDCFF45DF50:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374
+8C2B7CAFA5AFE7F13562DAEAE1ADEDE0:9E95E00F351D5B3AC3D0E22E626DDAD6:\
+767778797B7C7D7E80818283858687888A8B8C8D8F909192
+AAF4EC8C1A815AEB826CAB741339532C:9CB566FF26D92DAD083B51FDC18C173C:\
+94959697999A9B9C9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0
+40BE8C5D9108E663F38F1A2395279ECF:C9C82766176A9B228EB9A974A010B4FB:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBEC
+0C8AD9BC32D43E04716753AA4CFBE351:D8E26AA02945881D5137F1C1E1386E88:\
+2A2B2C2D2F30313234353637393A3B3C3E3F404143444546
+1407B1D5F87D63357C8DC7EBBAEBBFEE:C0E024CCD68FF5FFA4D139C355A77C55:\
+48494A4B4D4E4F50525354555758595A5C5D5E5F61626364
+
+E51AA0B135DBA566939C3B6359A980C5:8CD9423DFC459E547155C5D1D522E540:\
+E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506
+069A007FC76A459F98BAF917FEDF9521:080E9517EB1677719ACF728086040AE3:\
+08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E
+726165C1723FBCF6C026D7D00B091027:7C1700211A3991FC0ECDED0AB3E576B0:\
+30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556
+D7C544DE91D55CFCDE1F84CA382200CE:DABCBCC855839251DB51E224FBE87435:\
+58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E
+FED3C9A161B9B5B2BD611B41DC9DA357:68D56FAD0406947A4DD27A7448C10F1D:\
+80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6
+4F634CDC6551043409F30B635832CF82:DA9A11479844D1FFEE24BBF3719A9925:\
+A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE
+109CE98DB0DFB36734D9F3394711B4E6:5E4BA572F8D23E738DA9B05BA24B8D81:\
+D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6
+4EA6DFABA2D8A02FFDFFA89835987242:A115A2065D667E3F0B883837A6E903F8:\
+70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596
+5AE094F54AF58E6E3CDBF976DAC6D9EF:3E9E90DC33EAC2437D86AD30B137E66E:\
+98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE
+764D8E8E0F29926DBE5122E66354FDBE:01CE82D8FBCDAE824CB3C48E495C3692:\
+C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6
+3F0418F888CDF29A982BF6B75410D6A9:0C9CFF163CE936FAAF083CFD3DEA3117:\
+E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E
+E4A3E7CB12CDD56AA4A75197A9530220:5131BA9BD48F2BBA85560680DF504B52:\
+10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536
+211677684AAC1EC1A160F44C4EBF3F26:9DC503BBF09823AEC8A977A5AD26CCB2:\
+38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E
+D21E439FF749AC8F18D6D4B105E03895:9A6DB0C0862E506A9E397225884041D7:\
+60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586
+D9F6FF44646C4725BD4C0103FF5552A7:430BF9570804185E1AB6365FC6A6860C:\
+88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE
+0B1256C2A00B976250CFC5B0C37ED382:3525EBC02F4886E6A5A3762813E8CE8A:\
+B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6
+B056447FFC6DC4523A36CC2E972A3A79:07FA265C763779CCE224C7BAD671027B:\
+D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE
+5E25CA78F0DE55802524D38DA3FE4456:E8B72B4E8BE243438C9FFF1F0E205872:\
+00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526
+A5BCF4728FA5EAAD8567C0DC24675F83:109D4F999A0E11ACE1F05E6B22CBCB50:\
+28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E
+814E59F97ED84646B78B2CA022E9CA43:45A5E8D4C3ED58403FF08D68A0CC4029:\
+50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576
+15478BEEC58F4775C7A7F5D4395514D7:196865964DB3D417B6BD4D586BCB7634:\
+78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E
+
+# From the 'official' Blowfish vectors (mostly by SSLeay, aka OpenSSL)
+[Blowfish]
+0000000000000000:245946885754369A:0123456789ABCDEF
+0000000000000000:4EF997456198DD78:0000000000000000
+0000000000000000:F21E9A77B71C49BC:FFFFFFFFFFFFFFFF
+004BD6EF09176062:452031C1E4FADA8E:584023641ABA6176
+0123456789ABCDEF:0ACEAB0FC6A0A28D:FEDCBA9876543210
+0123456789ABCDEF:7D0CC630AFDA1EC7:1111111111111111
+0123456789ABCDEF:A790795108EA3CAE:1F1F1F1F0E0E0E0E
+0123456789ABCDEF:C39E072D9FAC631D:E0FEE0FEF1FEF1FE
+0123456789ABCDEF:FA34EC4847B268B2:0101010101010101
+01A1D6D039776742:59C68245EB05282B:7CA110454A1A6E57
+0248D43806F67172:1730E5778BEA1DA4:07A1133E4A0B2686
+02FE55778117F12A:CF9C5D7A4986ADB5:49E95D6D4CA229BF
+059B5E0851CF143A:48F4D0884C379918:0113B970FD34F2CE
+072D43A077075292:7A8E7BFA937E89A3:4FB05E1515AB73A7
+0756D8E0774761D2:432193B78951FC98:0170F175468FB5E6
+1000000000000001:7D856F9A613063F2:3000000000000000
+1111111111111111:2466DD878B963C9D:1111111111111111
+1111111111111111:61F9C3802281B096:0123456789ABCDEF
+164D5E404F275232:5F99D04F5B163969:37D06BB516CB7546
+1D9D5C5018F728C2:D1ABB290658BC778:018310DC409B26D6
+26955F6835AF609A:D887E0393C2DA6E3:04689104C2FD3B2F
+305532286D6F295A:55CB3774D13EF201:1C587F1C13924FEF
+3BDD119049372802:2EEDDA93FFD39C79:07A7137045DA2A16
+42FD443059577FA2:353882B109CE8F1A:04B915BA43FEB5B6
+437540C8698F3CFA:53C55F9CB49FC019:49793EBC79B3258F
+480D39006EE762F2:7555AE39F59B87BD:025816164629B007
+51454B582DDF440A:A25E7856CF2651EB:3849674C2602319E
+5CD54CA83DEF57DA:B1B8CC0B250F09A0:0131D9619DC1376E
+6B056E18759F5CCA:4A057A3B24D3977B:1F08260D1AC2465E
+762514B829BF486A:13F04154D69D1AE5:43297FAD38E373FE
+FFFFFFFFFFFFFFFF:014933E0CDAFF6E4:0000000000000000
+FFFFFFFFFFFFFFFF:51866FD5B85ECB8A:FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF:6B5C5A9C5D9E0A5A:FEDCBA9876543210
+
+0123456789ABCDEF1111111111111111:7D0CC630AFDA1EC72466DD878B963C9D:\
+1111111111111111
+
+FEDCBA9876543210:CC91732B8022F684:57686F206973204A6F686E2047616C743F
+
+424C4F5746495348:324ED0FEF413A203:\
+6162636465666768696A6B6C6D6E6F707172737475767778797A
+
+FEDCBA9876543210:F9AD597C49DB005E:F0
+FEDCBA9876543210:E91D21C1D961A6D6:F0E1
+FEDCBA9876543210:E9C2B70A1BC65CF3:F0E1D2
+FEDCBA9876543210:BE1E639408640F05:F0E1D2C3
+FEDCBA9876543210:B39E44481BDB1E6E:F0E1D2C3B4
+FEDCBA9876543210:9457AA83B1928C0D:F0E1D2C3B4A5
+FEDCBA9876543210:8BB77032F960629D:F0E1D2C3B4A596
+FEDCBA9876543210:E87A244E2CC85E82:F0E1D2C3B4A59687
+FEDCBA9876543210:15750E7A4F4EC577:F0E1D2C3B4A5968778
+FEDCBA9876543210:122BA70B3AB64AE0:F0E1D2C3B4A596877869
+FEDCBA9876543210:3A833C9AFFC537F6:F0E1D2C3B4A5968778695A
+FEDCBA9876543210:9409DA87A90F6BF2:F0E1D2C3B4A5968778695A4B
+FEDCBA9876543210:884F80625060B8B4:F0E1D2C3B4A5968778695A4B3C
+FEDCBA9876543210:1F85031C19E11968:F0E1D2C3B4A5968778695A4B3C2D
+FEDCBA9876543210:79D9373A714CA34F:F0E1D2C3B4A5968778695A4B3C2D1E
+FEDCBA9876543210:93142887EE3BE15C:F0E1D2C3B4A5968778695A4B3C2D1E0F
+FEDCBA9876543210:03429E838CE2D14B:F0E1D2C3B4A5968778695A4B3C2D1E0F00
+FEDCBA9876543210:A4299E27469FF67B:F0E1D2C3B4A5968778695A4B3C2D1E0F0011
+FEDCBA9876543210:AFD5AED1C1BC96A8:F0E1D2C3B4A5968778695A4B3C2D1E0F001122
+FEDCBA9876543210:10851C0E3858DA9F:F0E1D2C3B4A5968778695A4B3C2D1E0F00112233
+FEDCBA9876543210:E6F51ED79B9DB21F:F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344
+FEDCBA9876543210:64A6E14AFD36B46F:F0E1D2C3B4A5968778695A4B3C2D1E0F001122334455
+FEDCBA9876543210:80C7D7D45A5479AD:\
+F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566
+FEDCBA9876543210:05044B62FA52D080:\
+F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677
+
+# First one is from RFC 2144. The rest were done with OpenSSL and bits taken
+# from /dev/urandom
+[CAST-128]
+0123456789ABCDEF:238B4FE5847E44B2:0123456712345678234567893456789A
+0D5ED4BF2C101A00:851769123481EEBD:51D35D2CFC978231CC8D404C05F20778
+D6AA8EAE1E559AAE:C7FAFAFC64204DDE:3148F2F7A5EC9832C918B3FCE3A882D4
+F2504FFBB8970532:6371C64A362D2A06:23CA10AC5007672EAAC2A652A1033051
+4B1E9D8F450B7342:9CC2B912173553F3:69698114EB6B0C7DA021394E8294BA81
+26D7BA5E58E367FC:A2D1FCB23EDBE861:E29067C7B82F2BB5787A95961C4B145B
+960370DF205DF0C9:E1F5DCA58544FE69:724096996EA7E796847CC954DDB02F21
+3E16104523173535:EF4B1D186287F9E4:C44CD3B7C176A89B849AEC9D1A834D25
+6AB0B4F6FBDFE766:273B54BDF2B5588C:F5A1E7B8DF1852E0A12E150665812CE1
+76300E213C3F9D73:6C51876F5EA9CE03:1BCBC553F08BA5AE3DC87E3A08D720A5
+22A5191C0722F0D8:F1E19892EE7A4E51:0265563A752CB548404FEBA1C7231FA7
+D20430D1B98AE949:79E576FC40F1DC98:9C553CF85065EC9EFE0A6526070DF766
+1C7401D639A47971:BD2172A2ED5F5C02:1895E906311E100D6F189B0622248BC3
+B8591CA50C7E763D:573F3DB3C43731FA:616A2B2C30F26B1386CD8B1E9E15D77E
+CDA3984E06CC637A:2525D6596ACE9CD1:14422858FA163B7C5267FF819773CE1D
+5B5A603C9C090115:3729DAB86CB1CCF7:172E65C14E746EE6203025E94171D520
+9F9881CA42D7024C:9C3C573D7B958521:3E9FB858087C4E937A408EC1352482B1
+4A5C46FD61058258:2A1E5FD727F67F13:A32E8B1498839F6017802758076B0BFC
+EBBB828350790FDA:78FC70F88D1622ED:E303C6052387C310524721A2E461E89A
+5097EDFFDFC0CA5B:3ABDD3B9A69C7330:3B3DE3DA709304F69F1DD00F00A05064
+8F950AE00DD2F279:2C62AFD2C641CCE8:C36EC561C6E005B5FC5F03F2A90B097E
+D23B8A5E996E263D:31A202CC0F9FB2B7:202F39862076420EA9DF9DECCDC507AB
+8D953359228A4C76:AA454DE10B7A6863:CCD6F6AAEEB788E928CECF99440BBF07
+D2E9C19314726F4D:B744FAB9846F35E4:017779EA29084F30B867FDDFF56A2158
+F4C032C960A5B463:EDA7B0739A0638EE:CE44271A18D709DCC62648F709C1CBE2
+81A0FD9AA423ED36:C3CCCC1389F1D712:B9F0598CFA6D4F92294C4BA43ED360F2
+B7E0072AE1CBEE65:AEF33EEDCCC2E47F:5A6C06E02E3D5177D26F0D63DF839057
+F5810D9F1D639F82:A7A88EFA33ACF56E:547DF75C2FCFF20C1ED3A77AF1AD66E8
+984A16BE2CD649AC:444FC61F5CAB5A14:9CC9412E02C03D423E055D340BC74460
+8BC57E1C4D4DB959:6AAFD5AD02B48AAD:D2E4D28086A37BF2927C9477C8184907
+E79C0E003AE33C71:DCD139EFE59F5B1B:AFE83744D296834750A5AEC59C1FA546
+5E8EB11FF48AE593:947A1A1472AF838E:B933E959F7D492EACA22E7DF1C179C79
+FD9072FAB981B8AA:57A9C621EF5BE045:6DC4F66D0812A820134C3F61E398195E
+53515B1ABC74C9FB:C87A6000F80DADAF:4FA0C134D50DDCAE2FA8828479149C61
+1086DE79B6DC0C18:102FFA93ECBB99CF:7A6ECA7EAAF393694A32AF561FF7E056
+351228904431D12A:DC8B4548DA69C92D:42400F970D5E6E38DE297B365C0704D3
+889F00F0EC62610F:3AEC2335A78EC8F9:50D77ED75F69D9FD89C0B58A5374CC8E
+05CC553B50019A76:7A3F48D2954FB957:321E02B40C3F7D9D55A5135620685DC8
+D30DBA7A648B2CE9:242C1509768F5F9E:DA1CA8F596F04697592CE210752FD08D
+1917132061B5B572:28FDDE7607EBE08D:9C56B69695DB96CEDBF1133386D13768
+8420D1986EBBABFC:EAACBF83A093CB44:9F79CA83F4FDCCACA166BF18BF1B0CC2
+
+# From my AES CD, I'm guessing
+[CAST-256]
+00000000000000000000000000000000:66918B620F075819CDE620469D5F39B8:\
+80000000000000000000000000000000
+00000000000000000000000000000000:C842A08972B43D20836C91D1B7530F6B:\
+2342BB9EFA38542C0AF75647F29F615D
+00000000000000000000000000000001:4DBF11C2CA26D5A712578A5C18E8487B:\
+00000000000000000000000000000000
+00000000000000000000000000000000:1B386C0210DCADCBDD0E41AA08A7A7E8:\
+2342BB9EFA38542CBED0AC83940AC298BAC77A7717942863
+80000000000000000000000000000000:D64AD4962DCF990CB9EB1BEF19A21B98:\
+000000000000000000000000000000000000000000000000
+00000000000040000000000000000000:0154FF22D769EB57AE14D7ECDD60C1D8:\
+000000000000000000000000000000000000000000000000
+80000000000000000000000000000000:D64AD4962DCF990CB9EB1BEF19A21B98:\
+0000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000001:4DBF11C2CA26D5A712578A5C18E8487B:\
+0000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000:41C30E3025A7E66F6AE733DFDC861341:\
+0000000000000000000000200000000000000000000000000000000000000000
+00000000000000000000000000000000:4F6A2038286897B9C9870136553317FA:\
+2342BB9EFA38542CBED0AC83940AC2988D7C47CE264908461CC1B5137AE6B604
+
+0000000000000000000000000C9B2807:963A8A50CEB54D08E0DEE0F1D0413DCF:\
+2342BB9EFA38542C0AF75647F29F615D
+000000000000000000000000EE356B0F:B25683CD9188DB9307F8A1236B53DE86:\
+2342BB9EFA38542CBED0AC83940AC298BAC77A7717942863
+000000000000000000000000B2E9D805:AAB348855CAC0DC7BDF2FA02757A2154:\
+2342BB9EFA38542CBED0AC83940AC2988D7C47CE264908461CC1B5137AE6B604
+
+[DES]
+059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE
+4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF
+666F7220616C6C20:893D51EC4B563B53:0123456789ABCDEF
+68652074696D6520:6A271787AB8883F9:0123456789ABCDEF
+5CD54CA83DEF57DA:7A389D10354BD271:0131D9619DC1376E
+0756D8E0774761D2:0CD3DA020021DC09:0170F175468FB5E6
+1D9D5C5018F728C2:5F4C038ED12B2E41:018310DC409B26D6
+480D39006EE762F2:A1F9915541020B56:025816164629B007
+26955F6835AF609A:5C513C9C4886C088:04689104C2FD3B2F
+42FD443059577FA2:AF37FB421F8C4095:04B915BA43FEB5B6
+0248D43806F67172:868EBB51CAB4599A:07A1133E4A0B2686
+3BDD119049372802:DFD64A815CAF1A0F:07A7137045DA2A16
+16393BCDD6560506:9966ADCFC53BF968:0A3FDDC8350AFF39
+DC7FC6CF0358ECC0:A47A7485661F7085:10DD6DCD5C89E151
+305532286D6F295A:63FAC0D034D9F793:1C587F1C13924FEF
+F786D02413C574FC:54C160D369F62AE3:1EB00767BDEE584E
+6B056E18759F5CCA:EF1BF03E5DFA575A:1F08260D1AC2465E
+905EA29AEEA26E07:2292E9AEBEE6A4B6:28EE445D8A21C534
+164D5E404F275232:0A2AEEAE3FF4AB77:37D06BB516CB7546
+51454B582DDF440A:7178876E01F19B2A:3849674C2602319E
+68FF9D6068C71513:84595F5B9D046132:3CDE816EF9EF8EDB
+762514B829BF486A:EA676B2CB7DB2B7A:43297FAD38E373FE
+437540C8698F3CFA:6FBF1CAFCFFD0556:49793EBC79B3258F
+02FE55778117F12A:5A6B612CC26CCE4A:49E95D6D4CA229BF
+1F508A50ADB3D6E2:470204969876604A:4BB53ECFEFB38DDE
+072D43A077075292:2F22E49BAB7CA1AC:4FB05E1515AB73A7
+004BD6EF09176062:88BF0DB6D70DEE56:584023641ABA6176
+5AA1D62806AE0EAD:6DB0F280FEF2B564:5F2B51F59E781D9C
+7E1B1C6776833772:EB11CD3C72F7E90E:699C920D7CE1E0B1
+5DBFB47C5F471136:9C8B904D4D772BE7:7AC2FDEEE4C79746
+01A1D6D039776742:690F5B0D9A26939B:7CA110454A1A6E57
+4DE2F0926CF598D7:BA107655991DF529:7FC92C3098ECF14A
+F45E6819E3108559:F0C76BA556283B2F:9AB645E268430854
+51D4EAAAC6D76553:BF3C6E8FD15BA861:A6B0AE88F980011A
+6A89626EA8038511:1067B36913CBCC47:BAFEBAFAFEAEEAFF
+7B0313C0D3A866F9:E49E15E4F46F10E9:BB2420B5FEE5A6A1
+9D4A44AEFCE79965:77B2ECC9278E9714:BEBAFBEABAFFEAAF
+59BCDFC253424CB5:0A50ABBBCD07061A:C38C6F20230D9ED5
+D6C059A85EE2B13E:25977533635BEB5B:C6F974504D954C7E
+F9E4821DFCAA5466:48EC3A79399E9A00:CB959B7FFD94F734
+35E8554BAD60FB29:993A3AF0BC0D77A4:CFB23034323CD19A
+9F97210D75B7E6DF:4729E3396E57AE4E:D4D861035745F2C8
+FFFFFFFFFFFFFFFF:B5CE4F28FDEB21E8:E36972FC4BEC7587
+323837024123C918:7F28BF28ADFA1CF0:E91A71A7ED5EB0EF
+37DFE527086AF0A0:5F53C6C87760256E:EBBBBAEBFBBEFABA
+20678F45B5B8AC00:7CC8ECF2638CC808:EBBEEEAEBBBBFFFF
+78481ED0C5A7C93E:4CA3A08300EA6AFC:FBEAFFEEFFEEABAB
+E2CCD415AC25412A:BD85B3B659AB7276:FD8A675C0ED08301
+CCCC5BDFD9029507:DA57553D7D55775F:FFFFFFFFFFFFFFFF
+0000000000000000:23083A3CA70DD027:D5D44FF720683D0D
+0100000000000000:6F353E3388ABE2EF:D5D44FF720683D0D
+
+95F8A5E5DD31D900:8000000000000000:0101010101010101
+95F8A5E5DD31D900:8000000000000000:0000000000000000
+DD7F121CA5015619:4000000000000000:0101010101010101
+2E8653104F3834EA:2000000000000000:0101010101010101
+4BD388FF6CD81D4F:1000000000000000:0101010101010101
+20B9E767B2FB1456:0800000000000000:0101010101010101
+20B9E767B2FB1456:0800000000000000:0001010101010100
+55579380D77138EF:0400000000000000:0101010101010101
+6CC5DEFAAF04512F:0200000000000000:0101010101010101
+0D9F279BA5D87260:0100000000000000:0101010101010101
+D9031B0271BD5A0A:0080000000000000:0101010101010101
+424250B37C3DD951:0040000000000000:0101010101010101
+B8061B7ECD9A21E5:0020000000000000:0101010101010101
+F15D0F286B65BD28:0010000000000000:0101010101010101
+ADD0CC8D6E5DEBA1:0008000000000000:0101010101010101
+E6D5F82752AD63D1:0004000000000000:0101010101010101
+ECBFE3BD3F591A5E:0002000000000000:0101010101010101
+F356834379D165CD:0001000000000000:0101010101010101
+2B9F982F20037FA9:0000800000000000:0101010101010101
+889DE068A16F0BE6:0000400000000000:0101010101010101
+E19E275D846A1298:0000200000000000:0101010101010101
+329A8ED523D71AEC:0000100000000000:0101010101010101
+E7FCE22557D23C97:0000080000000000:0101010101010101
+12A9F5817FF2D65D:0000040000000000:0101010101010101
+A484C3AD38DC9C19:0000020000000000:0101010101010101
+FBE00A8A1EF8AD72:0000010000000000:0101010101010101
+750D079407521363:0000008000000000:0101010101010101
+64FEED9C724C2FAF:0000004000000000:0101010101010101
+F02B263B328E2B60:0000002000000000:0101010101010101
+9D64555A9A10B852:0000001000000000:0101010101010101
+D106FF0BED5255D7:0000000800000000:0101010101010101
+E1652C6B138C64A5:0000000400000000:0101010101010101
+E428581186EC8F46:0000000200000000:0101010101010101
+AEB5F5EDE22D1A36:0000000100000000:0101010101010101
+E943D7568AEC0C5C:0000000080000000:0101010101010101
+DF98C8276F54B04B:0000000040000000:0101010101010101
+B160E4680F6C696F:0000000020000000:0101010101010101
+FA0752B07D9C4AB8:0000000010000000:0101010101010101
+CA3A2B036DBC8502:0000000008000000:0101010101010101
+5E0905517BB59BCF:0000000004000000:0101010101010101
+814EEB3B91D90726:0000000002000000:0101010101010101
+4D49DB1532919C9F:0000000001000000:0101010101010101
+25EB5FC3F8CF0621:0000000000800000:0101010101010101
+AB6A20C0620D1C6F:0000000000400000:0101010101010101
+79E90DBC98F92CCA:0000000000200000:0101010101010101
+866ECEDD8072BB0E:0000000000100000:0101010101010101
+8B54536F2F3E64A8:0000000000080000:0101010101010101
+EA51D3975595B86B:0000000000040000:0101010101010101
+CAFFC6AC4542DE31:0000000000020000:0101010101010101
+8DD45A2DDF90796C:0000000000010000:0101010101010101
+1029D55E880EC2D0:0000000000008000:0101010101010101
+5D86CB23639DBEA9:0000000000004000:0101010101010101
+1D1CA853AE7C0C5F:0000000000002000:0101010101010101
+CE332329248F3228:0000000000001000:0101010101010101
+8405D1ABE24FB942:0000000000000800:0101010101010101
+E643D78090CA4207:0000000000000400:0101010101010101
+48221B9937748A23:0000000000000200:0101010101010101
+DD7C0BBD61FAFD54:0000000000000100:0101010101010101
+2FBC291A570DB5C4:0000000000000080:0101010101010101
+E07C30D7E4E26E12:0000000000000040:0101010101010101
+0953E2258E8E90A1:0000000000000020:0101010101010101
+5B711BC4CEEBF2EE:0000000000000010:0101010101010101
+CC083F1E6D9E85F6:0000000000000008:0101010101010101
+D2FD8867D50D2DFE:0000000000000004:0101010101010101
+06E7EA22CE92708F:0000000000000002:0101010101010101
+166B40B44ABA4BD6:0000000000000001:0101010101010101
+0000000000000000:95A8D72813DAA94D:8001010101010101
+0000000000000000:0EEC1487DD8C26D5:4001010101010101
+0000000000000000:7AD16FFB79C45926:2001010101010101
+0000000000000000:D3746294CA6A6CF3:1001010101010101
+0000000000000000:809F5F873C1FD761:0801010101010101
+0000000000000000:C02FAFFEC989D1FC:0401010101010101
+0000000000000000:4615AA1D33E72F10:0201010101010101
+0000000000000000:2055123350C00858:0180010101010101
+0000000000000000:DF3B99D6577397C8:0140010101010101
+0000000000000000:31FE17369B5288C9:0120010101010101
+0000000000000000:DFDD3CC64DAE1642:0110010101010101
+0000000000000000:178C83CE2B399D94:0108010101010101
+0000000000000000:50F636324A9B7F80:0104010101010101
+0000000000000000:A8468EE3BC18F06D:0102010101010101
+0000000000000000:A2DC9E92FD3CDE92:0101800101010101
+0000000000000000:CAC09F797D031287:0101400101010101
+0000000000000000:90BA680B22AEB525:0101200101010101
+0000000000000000:CE7A24F350E280B6:0101100101010101
+0000000000000000:882BFF0AA01A0B87:0101080101010101
+0000000000000000:25610288924511C2:0101040101010101
+0000000000000000:C71516C29C75D170:0101020101010101
+0000000000000000:5199C29A52C9F059:0101018001010101
+0000000000000000:C22F0A294A71F29F:0101014001010101
+0000000000000000:EE371483714C02EA:0101012001010101
+0000000000000000:A81FBD448F9E522F:0101011001010101
+0000000000000000:4F644C92E192DFED:0101010801010101
+0000000000000000:1AFA9A66A6DF92AE:0101010401010101
+0000000000000000:B3C1CC715CB879D8:0101010201010101
+0000000000000000:19D032E64AB0BD8B:0101010180010101
+0000000000000000:3CFAA7A7DC8720DC:0101010140010101
+0000000000000000:B7265F7F447AC6F3:0101010120010101
+0000000000000000:9DB73B3C0D163F54:0101010110010101
+0000000000000000:8181B65BABF4A975:0101010108010101
+0000000000000000:93C9B64042EAA240:0101010104010101
+0000000000000000:5570530829705592:0101010102010101
+0000000000000000:8638809E878787A0:0101010101800101
+0000000000000000:41B9A79AF79AC208:0101010101400101
+0000000000000000:7A9BE42F2009A892:0101010101200101
+0000000000000000:29038D56BA6D2745:0101010101100101
+0000000000000000:5495C6ABF1E5DF51:0101010101080101
+0000000000000000:AE13DBD561488933:0101010101040101
+0000000000000000:024D1FFA8904E389:0101010101020101
+0000000000000000:D1399712F99BF02E:0101010101018001
+0000000000000000:14C1D7C1CFFEC79E:0101010101014001
+0000000000000000:1DE5279DAE3BED6F:0101010101012001
+0000000000000000:E941A33F85501303:0101010101011001
+0000000000000000:DA99DBBC9A03F379:0101010101010801
+0000000000000000:B7FC92F91D8E92E9:0101010101010401
+0000000000000000:AE8E5CAA3CA04E85:0101010101010201
+0000000000000000:9CC62DF43B6EED74:0101010101010180
+0000000000000000:D863DBB5C59A91A0:0101010101010140
+0000000000000000:A1AB2190545B91D7:0101010101010120
+0000000000000000:0875041E64C570F7:0101010101010110
+0000000000000000:5A594528BEBEF1CC:0101010101010108
+0000000000000000:FCDB3291DE21F0C0:0101010101010104
+0000000000000000:869EFD7F9F265A09:0101010101010102
+0000000000000000:88D55E54F54C97B4:1046913489980131
+0000000000000000:0C0CC00C83EA48FD:1007103489988020
+0000000000000000:83BC8EF3A6570183:10071034C8980120
+0000000000000000:DF725DCAD94EA2E9:1046103489988020
+0000000000000000:E652B53B550BE8B0:1086911519190101
+0000000000000000:AF527120C485CBB0:1086911519580101
+0000000000000000:0F04CE393DB926D5:5107B01519580101
+0000000000000000:C9F00FFC74079067:1007B01519190101
+0000000000000000:7CFD82A593252B4E:3107915498080101
+0000000000000000:CB49A2F9E91363E3:3107919498080101
+0000000000000000:00B588BE70D23F56:10079115B9080140
+0000000000000000:406A9A6AB43399AE:3107911598090140
+0000000000000000:6CB773611DCA9ADA:1007D01589980101
+0000000000000000:67FD21C17DBB5D70:9107911589980101
+0000000000000000:9592CB4110430787:9107D01589190101
+0000000000000000:A6B7FF68A318DDD3:1007D01598980120
+0000000000000000:4D102196C914CA16:1007940498190101
+0000000000000000:2DFA9F4573594965:0107910491190401
+0000000000000000:B46604816C0E0774:0107910491190101
+0000000000000000:6E7E6221A4F34E87:0107940491190401
+0000000000000000:AA85E74643233199:19079210981A0101
+0000000000000000:2E5A19DB4D1962D6:1007911998190801
+0000000000000000:23A866A809D30894:10079119981A0801
+0000000000000000:D812D961F017D320:1007921098190101
+0000000000000000:055605816E58608F:100791159819010B
+0000000000000000:ABD88E8B1B7716F1:1004801598190101
+0000000000000000:537AC95BE69DA1E1:1004801598190102
+0000000000000000:AED0F6AE3C25CDD8:1004801598190108
+0000000000000000:B3E35A5EE53E7B8D:1002911598100104
+0000000000000000:61C79C71921A2EF8:1002911598190104
+0000000000000000:E2F5728F0995013C:1002911598100201
+0000000000000000:1AEAC39A61F0A464:1002911698100101
+
+# Vectors randomly generated using OpenSSL
+
+0CEB1136A85AD37A:9CE3A1058A483F55:309A4B21A2067196
+9BBBD2F50EC248A8:7694CA89548B0A3B:CA61DEF25C51A5A0
+FF82E00A54C33870:ADF2C2D3F57C12EC:054F6AC2C779D51A
+3E33A822C3C3573A:91481544C1349FD2:AB28E5763F23361A
+8BB2EC62E042C9BF:62F0E53062A010B9:A9C631D31852201F
+4844511C42049973:C7265CA05D9F3253:3D90CADF843BBA1B
+38F11633A3766D10:66D55E36CCE18435:B6006A2C549DEA94
+746BC597A7501FF0:0032D9CA6E094980:070A848D67D7701C
+FA5F22A6A7DDBB8B:91ECEFD28E217506:A12AE6006E8F8D37
+8D3D08E33FBB298D:CF132CE973D16AA3:9998A725FB90FDE4
+397CA570B07AF49E:4C2959260E6C27DC:F111F3AFD4602715
+6ACFBFF2962511A9:2D325409EF2CD744:EF97EA242CCBAC00
+EB5167B434A4595A:483EA80264F0DCF6:9080E3410BFCDB73
+E72EDA1F8AE27EB9:0E4AF25FBDD5A85E:8A37156BE5515D5D
+B0F7D48AA74DD638:7F6747AEF2C9EAC9:DF09A6387CFE9A6B
+334A69684C8B728A:6717F2AD848DEAF7:B4FCAFFB540653E5
+A78C724DA4DC969D:AC6A97ECE16A8892:183972A45732379A
+4310191D687F40D6:C9B0C9CA84CFC141:979D352937F85083
+F630889FB4B5ED90:6166F3231EC1EAD9:5CEDCE103F7F73C4
+C9C7BFE95A2F77FD:B6C234EAF4A39B1F:4AD1B967A715F5A9
+43E2B87BB55A3038:B9BE452E0E4EA44D:F883F548F16E692A
+42AA788D751F49A5:5302E3BA833E598A:D75198DF25CC1345
+63E22CDF499763C3:70E8BD70BCE301CB:7033D4C5D9B36096
+665976555719E76F:65769A95FB144DE9:76B7EAC1DB819238
+12DD07305BC143DE:A5E73B90A3E75586:76FC0A292121B094
+45A11A91EF86DDA6:6E2C2CC2A2333C88:B775628F1EC6520C
+537FEBCB1219673B:D578B8AA85351F91:65BF73315A05061C
+F5F17039BA37C1C0:3D6A8E5991C3AEBB:E772317D24F6D307
+D0530A774112DC14:307AE98F2B6864D0:461E02D82081CA3A
+A46F062CBB7BFC33:A9D2B0940F0A7F58:08FF3D9BDE9EEA8E
+A47F14BAA946FB7B:4E79EBEFD716D85F:4D92A8AE6F9C6A35
+692A27DA86F2E283:29961C5FD6744638:FB1C7BB97C7ED50C
+74D5CD027725903C:B8A8076072E55000:C9B0558D7C353C5E
+2311E3818223DFA9:17A4E5989E9C9A3D:60D82E111EEEDEA8
+984B849763274BD3:205C2B2AEDB6052D:76DB3E3505FD3A95
+9852C739E74737B7:525CBAD9C2D50EA0:558EF761EEE52DCF
+6C4236CFAEFF63EC:E1AD916DED6850F4:AC340D97D96CF29E
+1A95C43E9C7D5339:B60E5C4C76CE51C6:50F5C29F83C8F2BF
+7DBE4645B2C169F4:285276D256091B2E:C7BF9EB44254ACA6
+841DEAE87A860986:799A5A58E5CE9D59:FE80AB20EAC7AD16
+1529ACE917CA5AB4:AAB07F8FDBDC494E:B012DE369D9B7436
+86462C0AD4003FEC:51310B7C123C64C4:61896A3271D3E2B2
+A67151571BE9AB07:3024667AFF88ADAB:8514D38254A5A55F
+B314608B183F3329:AA966A7A395FFAE7:F607C0CD0FAFCC60
+84B322B129ABACDF:C50F0D6E439E8490:10EEC9E7F07A51D3
+E296E275356AA9A0:B3963851F7DEB2C3:32F4E03E3B10DB42
+4DF2292E321837F6:1D017CE1B3C03380:52205900EE0836E6
+88A2C60FB19E5983:77763644264C8FB8:A481D9B2C7FDA435
+06CA0C88A4347E12:F1FCAEAF30C63870:404025B368276238
+FEFD2DF531FE9112:8F49A08722BB14F0:657486656993AC7B
+
+[DESX]
+94DBE082549A14EF:9011121314151617:\
+0123456789ABCDEF01010101010101011011121314151617
+B83DF91F844FF695:FA942810AC8355C0:\
+E874076EF40EDA62908D12ADF2B7B9ECDA474BF3FEDCDA11
+4EF5D7337D420403:B2C3C73B303BE0D7:\
+2AF5602DA83F821A69C81B1B83EFA70A3B4E3C1D546BF825
+8D3C8F07A610FD51:5712559676CABA44:\
+BEB7DF4A710FACB364183EEBCA3EE934A5B470031CE64A03
+B39949A845EF61C1:3769F87FB393D49F:\
+46312600F8B5F05AFAA080D26672B9C44AF057D694702AB5
+B00E6572A847D27A:6B1C14571BC9EBCE:\
+25A3EAE6D9FB10E86E14032BB652262CD1D7ED74A2BFC75B
+07608C7CB2B11972:CD627B22E13ECCD4:\
+3D5BEA2C2216E30CE961882A593608CB5BA96FC656AF7487
+C2B7BCC1EA18B54A:66EF45BEA20DDAAF:\
+5AD28C1D67C65E4D5F4A9DB38C32827BC6C4FE098996F017
+59004793279BBEFA:F0B6AC1318F01331:\
+8A94FCBF30415180EF79881D32C8C061E4527DE53BF5915D
+
+[TripleDES]
+0123456789ABCDE7:7F1D0A77826B8AFF:0123456789ABCDEFFEDCBA9876543210
+4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF0123456789ABCDEF
+42FD443059577FA2:AF37FB421F8C4095:04B915BA43FEB5B604B915BA43FEB5B6
+AFA4284FCCEAA61A:32527D5701D92B90:4BC59E2C68ACA60767A9A4B623BBBCCC
+50B503A331D5B5CC:E46A59E18B0C41E3:B955BB7861FDE77E7DC6418475457FE1
+3404435D5DF2CB47:644DD68EA73053AE:C0557629EAA72ABD4C102C5DC9CE8B47
+C7D80E955D1B6627:9FE1C5A12CCE6DD9:9EAA94DA916F30092E79DACDCDCC45C0
+BDCBE8929CD0E12F:F2B6430450AB348B:A55279671807D9B71FE62A77341249F8
+4B7A96B7051C64FC:1555F08B2DE690A0:672E20826AD49C3DF7579FAB3752479E
+902F4EDD44EAF3C1:3CE357EBA0FB3E26:0CE61EDE2659B413AB9F717AE4AFAD3E
+39C0F8E4C85CD70D:882DE9B6D0209A58:E878020815AE517CD2808B6571EAC2B4
+F77A1947A921B209:E10DBEE5615F312E:D891CA20919F06A054BA3943C7DABA16
+06D0416E0F0DB7CE:0CEC5D1E59D7E347:4909AED1F94EB77B6CACBCAE2B25689A
+F7BB3A396D73D8A8:F893B6B2A15D3FCE:8B9A5C13B0B118A1EE35EB912866FFA6
+BD35E3134B90CCBC:12A7AF172FD0CA7F:FA7911D664326074B42E2F38E599B288
+E046B7F5707DA4FC:32B6A3FC72C7C480:406903B340B8637928FDE8058BDD6710
+58EB1DC16C482213:A6C6234A8BBAA116:37A2B53E2AF8F6C9A73B39F919D969DE
+4BD0F4854297FBDE:F4AB771861457DC6:711F2CECDB92B2E201DFEFA79FA7BA2F
+
+42FD443059577FA2:AF37FB421F8C4095:\
+04B915BA43FEB5B604B915BA43FEB5B604B915BA43FEB5B6
+736F6D6564617461:18D748E563620572:\
+0123456789ABCDEF5555555555555555FEDCBA9876543210
+7371756967676C65:C07D2A0FA566FA30:\
+0352020767208217860287665908219864056ABDFEA93457
+0123456789ABCDE7:DE0B7C06AE5E0ED5:\
+0123456789ABCDEFFEDCBA987654321089ABCDEF01234567
+0123456789ABCDE7:7F1D0A77826B8AFF:\
+0123456789ABCDEFFEDCBA98765432100123456789ABCDEF
+4115E551299A5C4B:F7A0822FC310686C:\
+1EF743A68D629F68A5E3136C36AD7953A835CF849BB4EC3C
+D5AB44E0FE46E1B5:02AED9BF72ECA222:\
+B7D560BE49C3936728EF0BF57B602D2EB7E5C631DD7F753E
+B4077DFDB721D88C:F76ABA838B1C4372:\
+D2D98706E9AB867647D244BDCDBCD5EF8B4DBC9CF4F35493
+890E98AB385FA1A1:187087C77790C3B2:\
+153B963004101D12683E8F87116001B8C5526475510B5036
+02D5DA6D5F247CD2:89FC7DF1E7913163:\
+45E4275DCCC5D8B5A27993C16D9960CA939C023E2763216A
+5AF9E5A3525E3F7D:8FCC7A8BC337E484:\
+F6C2474B33934EA76E6C841D9B1E86E37189095A895A3E5A
+12864DDE8E694BD1:5B4DDE8F000A5A9B:\
+5B4F6D3185EFBAE97D58ED9CC75E2BAE655D2CEFB2DD09CD
+0123456789ABCDE7:C95744256A5ED31D:\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
+68652074696D6520:6A271787AB8883F9:\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
+4E6F772069732074:3FA40E8A984D4815:\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
+
+94A8A0655AF71024:A427AA4C6234817E:\
+C9B6D82EF93DD4C7AC365AB2D9280EB39DD92C0CE3F72BDE
+2881AE1EF7DC8DE2:5C009647DE419151:\
+704A6378B5C72C3F1617B97508777FACF8E2205C66D29279
+462EC3631C8C0DA9:52E8D6E3F54404C3:\
+9D5DF5B9222F4E04197A0E194AFBD4BA0225D1472F925076
+941F85F14CC3E9F8:3FE08C51BC513AD9:\
+8374C4173F715AA127877D3BEFB8C0B2FF5987E12B112FD9
+99A30F38CE575814:5C02AECC12404AB6:\
+CD5BCCEC928C04E91E4CFC715E10E029E01F870FB98E7B34
+69F80C7EAF46CBAD:9FF8BCB5707A0ED9:\
+59345A37BE821AA78E0BD97259C54BEBB1F644B78B1FD310
+62522184CE03EFF7:0E98911465E30E76:\
+E3C22C1AAAAF0FBF61A170BC24361F274B404E36C8F1794A
+DED10258F58DAA03:2CD2D1F377C13A53:\
+C0E492C873EFE871E534A2A30600418D636C3FC76C4E9EA6
+AFC190AF21D37A39:E7B312CCC287374C:\
+DC80FA652BBB01186C6CFDDF55E109808F6CCEC99DEE3633
+8A206F645001553B:B824E9E801940B83:\
+276B5FC5C5255AE2484114EAC33CD228A7BEAA9487D9A729
+2095D9F03C7EC366:537201E0D3FFCECE:\
+70890F38A3A6744162356109589DC20ABF2D3AD8E989A77F
+D51A8F5310D314DE:7EE4FEA9B78CB899:\
+86164AB6C13CA0AD6B35EEDDDE102428C822C22DB1326661
+B0317287CC8D536B:118293DE51E43D00:\
+98D2D51E2916D25237DAFC6B5CFBB5AED7CCD916BF243004
+A8BF0F3A57822AFE:9FD4F7B0500C0F53:\
+BBA72F7362A8E3BA6EE190C4E0AC25560BB0DF1097F94C13
+C16B7EAD2367C87D:9FE31F892EB7E617:\
+6F9DD25B6ACAB7019A548B6B0E1AA35AFEF95D89DB20FB11
+C5E3D11391C7875B:0B5BC8B430785004:\
+1670F96FC4D670CF3BEC580AE1735FE3DFB3E0377FEC16C8
+CCCBFFFAB48110DB:08E145136C8112C4:\
+3B55AC7156436FCA1D639BC33541F91AD0BE7525C3D0E823
+039391950AC5937C:5251FDDBD6E2E70D:\
+D24A2A7340C974E68265C4DFACE67041852889ADDF1216AF
+41BD298935B10395:228EDD3DA5B00098:\
+777EAD928BFB661003A4E0F0920CD161A2C03963C816F1F3
+FFC524C0B0F48806:092D1465E01D9356:\
+6335EA2F228A811B7B70AE47BF13F8D456A717BC2AC1F301
+2E499BC53CFEB666:87B59F9BD6ADE17C:\
+EFACE1D2899E742C6A65EB523447B6001E2FE3DB1D6BD904
+8250B551ADAEE699:A286D77E36481FA8:\
+DA0BB6DD13B7707C674C72DD1A7C1B3FD03B13832C8CFC13
+F48717AE3466F0F5:403CB3AFDA050BFB:\
+0F6997BD4AFACC4E2228180FA60A683D13C6E237325BC671
+8308D7DDC9BE043C:08FF7FB8D322FE1E:\
+77790E57117F767476AE9E623A839D1B5B596623CB193C08
+DA0EDCDC26C81F71:5E54344C7E8CF8A0:\
+1A34BA494ADC8ED74B6AD1EDAF317DA506FBDA7A0D0DD40C
+
+[GOST-28147-89(R3411_94_TestParam)]
+
+# The test vectors included in Crypto++ 5.6.0
+0DF82802B741A292:07F9027DF7F7DF89:\
+BE5EC2006CFF9DCF52354959F1FF0CBFE95061B5A648C10387069C25997C0672
+
+1354EE9C0A11CD4C:4FB50536F960A7B1:\
+B385272AC8D72A5A8B344BC80363AC4D09BF58F41F540624CBCB8FDCF55307D7
+
+6693D492C4B0CC39:670034AC0FA811B5:\
+AEE02F609A35660E4097E546FD3026B032CD107C7D459977ADF489BEF2652262
+
+99E2D13080928D79:8118FF9D3B3CFE7D:\
+320E9D8422165D58911DFC7D8BBB1F81B0ECD924023BF94D9DF7DCF7801240E0
+
+D1E787749C72814C:A083826A790D3E0C:\
+C9F703BBBFC63691BFA3B7B87EA8FD5E8E8EF384EF733F1A61AEF68C8FFA265F
+
+D4C05323A4F7A7B5:4D1F2E6B0D9DE2CE:\
+728FEE32F04B4C654AD7F607D71C660C2C2670D7C999713233149A1C0C17A1F0
+
+8742D9A05F6A3AF6:2F3BB84879D11E52:\
+35FC96402209500FCFDEF5352D1ABB038FE33FC0D9D58512E56370B22BAA133B
+
+F86506DA04E41CB8:96F0A5C77A04F5CE:\
+D416F630BE65B7FE150656183370E07018234EE5DA3D89C4CE9152A03E5BFB77
+
+# Generated by OpenSSL's gost89.c and GostR3411_94_TestParamSet
+# This implementation was written by CryptoCom who is a Russian
+# company active in standardizing GOST usage in the IETF, etc
+
+66320DB73158A35A:4732FE56B7854AF7:\
+67C6697351FF4AEC29CDBAABF2FBE3467CC254F81BE8E78D765A2E63339FC99A
+
+3E017E97EADC6B96:4CDDBE526625E368:\
+255D051758E95ED4ABB2CDC69BB454110E827441213DDC8770E93EA141E1FC67
+
+75D8BE6189F95CBB:4FD8C167F5C05C76:\
+8F385C2AECB03BFB32AF3C54EC18DB5C021AFE43FBFAAA3AFB29D1E6053C7C94
+
+14735AC55E4B7963:DFCD9EFC3FA9BAFB:\
+A8990F95B1EBF1B305EFF700E9A13AE5CA0BCBD0484764BD1F231EA81C7B64C5
+
+0BE11A1C7F23F829:E0BB12ECA3001350:\
+3B706424119E09DCAAD4ACF21B10AF3B33CDE3504847155CBB6F2219BA9B7DF5
+
+167241EC4441196D:2361B9315757145A:\
+FA7F444FD5D2002D294B96C34DC57D297ED55FDA3214D99BD79F7A0EF8972DF2
+
+2EDD19A28A1D950C:0B4CB6EE4CDBC46E:\
+8DAF30DA74AD04F28263CCB577A6504E45CB5C3D628A2F79FC706540B27EAD3F
+
+634BCA6A5D11B73A:990D426E1415B346:\
+8161C1F80712474CDDA3893F2DB8B829291D69DB9C161ACAF3336C7D51018AD2
+
+E9E4E1E217ED0467:83F7B229D74D5068:\
+B5407AE2F9320C225075FDEC8C17B67F4A22FD9B24876D87D238F13049A86AFE
+
+40140A581D78BB49:D48ADCE9AE2DF9A7:\
+620153EE18096E622B6BFE4FF26BD6C4A3C8F4ED705FEB5943CC3B5AB93FC11C
+
+[GOST-28147-89(R3411_CryptoPro)]
+
+167241EC4441196D:A4BA7733087BF46B:\
+FA7F444FD5D2002D294B96C34DC57D297ED55FDA3214D99BD79F7A0EF8972DF2
+
+2EDD19A28A1D950C:9F5F0C9271672126:\
+8DAF30DA74AD04F28263CCB577A6504E45CB5C3D628A2F79FC706540B27EAD3F
+
+634BCA6A5D11B73A:68E44CBA27E3B0C3:\
+8161C1F80712474CDDA3893F2DB8B829291D69DB9C161ACAF3336C7D51018AD2
+
+E9E4E1E217ED0467:0B9B79E1AFE9D61F:\
+B5407AE2F9320C225075FDEC8C17B67F4A22FD9B24876D87D238F13049A86AFE
+
+40140A581D78BB49:5C960D01D404702D:\
+620153EE18096E622B6BFE4FF26BD6C4A3C8F4ED705FEB5943CC3B5AB93FC11C
+
+705616C1D3DE72D4:C934D4A3CDF6725C:\
+3AD1D828517CC8B001F0CA84010B3A0968AF11272336DE5A91A7AD69B49E7EEE
+
+EBEF9233826BE3C4:E29B5234B9903B4B:\
+CE3C58CF4893D9B042EAD76520B5C0B15C6D1A100B99FF7BEF153DC2F4AF96C2
+
+87826FF76C95C3C3:ABDC9E8C2A556516:\
+55BA2A7570EA26CC5741DD62DADCDEC9F11B8CE5CA22A8B5113AE993A5CC58FA
+
+35FC60B2FFDA201E:391DD791413EAF33:\
+D6A025B07C037A6E1E0653E828FB9E3A3587CDDA5325D4DAA743D113D995D6AF
+
+3BE742AA8B844EB7:06798A7B621A4F7F:\
+E07306086FA442A42B107F7F355359DD972BF070C0C71FF5C37FA7C259C7E039
+
+[IDEA]
+D53FABBF94FF8B5F:1D0CB2AF1654820A:729A27ED8F5C3E8BAF16560D14C90B43
+848F836780938169:D7E0468226D0FC56:729A27ED8F5C3E8BAF16560D14C90B43
+819440CA2065D112:264A8BBA66959075:729A27ED8F5C3E8BAF16560D14C90B43
+6C2E3617DA2BAC35:1569E0627007B12E:729A27ED8F5C3E8BAF16560D14C90B43
+0808080808080808:F5DB1AC45E5EF9F9:9D4075C103BC322AFB03E7BE6AB30006
+0102030405060708:97BCD8200780DA86:3A984E2000195DB32EE501C8C47CEA60
+05320A6414C819FA:65BE87E7A2538AED:006400C8012C019001F4025802BC0320
+0000000100020003:11FBED2B01986DE5:00010002000300040005000600070008
+0102030405060708:540E5FEA18C2F8B1:00010002000300040005000600070008
+0019324B647D96AF:9F0A0AB6E10CED78:00010002000300040005000600070008
+F5202D5B9C671B08:CF18FD7355E2C5C5:00010002000300040005000600070008
+FAE6D2BEAA96826E:85DF52005608193D:00010002000300040005000600070008
+0A141E28323C4650:2F7DE750212FB734:00010002000300040005000600070008
+050A0F14191E2328:7B7314925DE59C09:00010002000300040005000600070008
+0102030405060708:3EC04780BEFF6E20:0005000A000F00140019001E00230028
+0000000000000000:0001000100000000:00000000000000000000000000000000
+D5D5D5D5D5D5D5D5:75F7C7005EA47839:D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5
+4A4A4A4A4A4A4A4A:759A3CB94586706D:4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+0000000000000000:AA553A5DEC50E4A4:00000000000000040000000000000000
+0000000000000001:0013FFF500120009:00000000000000000000000000000000
+
+# Test vectors taken from ARIB STD-T63-35.203 V6.0.0
+[KASUMI]
+EA024714AD5C4D84:DF1F9B251C0BF45F:2BD6459F82C5B300952C49104881FF48
+D3C5D592327FB11C:DE551988CEB2F9B7:8CE33E2CC3C0B5FC1F3DE8A6DC66B1F3
+62A540981BA6F9B7:4592B0E78690F71B:4035C6680AF8C6D1A8FF8667B1714013
+
+# Checked against Crypto++ 2.3, so we're compatible with somebody, at least.
+[Luby-Rackoff(SHA1)]
+1112131415161718191A1B1C1D1E1F2021222324\
+25262728292A2B2C2D2E2F303132333435363738:\
+2015B3DB2DC49529C2D26B1F1E86C65EC7B946AB\
+127503CB92F07C0DD4ECD3D7700F31FA0268D381:\
+00112233445566778899AABBCCDDEEFF
+
+00112233445566778899AABBCCDDEEFF10213243\
+5465768798A9BACBDCEDFE0F2031425364758697:\
+84ACC1578337453D0F94FE2A09EAAE844B2BDE24\
+0F6D6225A0AD87EB3773BC29C2B85B51FD068674:\
+00112233445566778899AABBCCDDEEFF0123456789ABCDEFFEDCBA9876543210
+
+[MARS]
+F94512A9B42D034EC4792204D708A69B:225DA2CB64B73F79069F21A5E3CB8522:\
+CB14A1776ABBC1CDAFE7243DEF2CEA02
+
+4DF955AD5B398D66408D620A2B27E1A9:A4B737340AE6D2CAFD930BA97D86129F:\
+86EDF4DA31824CABEF6A4637C40B0BAB
+
+93A953A82C10411DD158860838874D95:4FA0E5F64893131712F01408D233E9F7:\
+D158860838874D9500000000000000000000000000000000
+
+1344ABA4D3C44708A8A72116D4F49384:458335D95EA42A9F4DCCD41AECC2390D:\
+FBA167983E7AEF22317CE28C02AAE1A3E8E5CC3CEDBEA82A99DBC39AD65E7227
+
+00000000000000000000000000000000:DCC07B8DFB0738D6E30A22DFCF27E886:\
+00000000000000000000000000000000
+
+DCC07B8DFB0738D6E30A22DFCF27E886:33CAFFBDDC7F1DDA0F9C15FA2F30E2FF:\
+00000000000000000000000000000000
+
+33CAFFBDDC7F1DDA0F9C15FA2F30E2FF:62D0D531FD18BAC77177CEB2395EF18F:\
+00000000000000000000000000000000
+
+62D0D531FD18BAC77177CEB2395EF18F:FC444017478822797D800F790622D77B:\
+00000000000000000000000000000000
+
+FC444017478822797D800F790622D77B:D584ED203C50582BCBF74B0469417EDC:\
+00000000000000000000000000000000
+
+D584ED203C50582BCBF74B0469417EDC:7134D3EF595D573FE88E18CE5CB2E612:\
+00000000000000000000000000000000
+
+7134D3EF595D573FE88E18CE5CB2E612:9172072F22CFC72234A7697D73412DB9:\
+00000000000000000000000000000000
+
+9172072F22CFC72234A7697D73412DB9:06B0DDCAAE6EA44BD0C509CE2BC838AC:\
+00000000000000000000000000000000
+
+06B0DDCAAE6EA44BD0C509CE2BC838AC:77512E7A4A90D6D5CD66637DEEF1FD52:\
+00000000000000000000000000000000
+
+77512E7A4A90D6D5CD66637DEEF1FD52:8BC4E466ABE0E2F8FD76019B8237F36E:\
+00000000000000000000000000000000
+
+8BC4E466ABE0E2F8FD76019B8237F36E:77D40822866C0DD51E0594AA81E5F1B5:\
+00000000000000000000000000000000
+
+77D40822866C0DD51E0594AA81E5F1B5:B8AB0608C7976E1D8F57B2BA493C7503:\
+00000000000000000000000000000000
+
+B8AB0608C7976E1D8F57B2BA493C7503:ED4AFE77CE3A2F8C00D0A5E4FDF23426:\
+00000000000000000000000000000000
+
+ED4AFE77CE3A2F8C00D0A5E4FDF23426:1B52C34EDB3826E2BF564E4E3A8C9FA6:\
+00000000000000000000000000000000
+
+1B52C34EDB3826E2BF564E4E3A8C9FA6:AE7E643A355B4847D4F1DBD126518993:\
+00000000000000000000000000000000
+
+AE7E643A355B4847D4F1DBD126518993:3E144191008102E869184D9714BAE7CF:\
+00000000000000000000000000000000
+
+3E144191008102E869184D9714BAE7CF:89ABFA208A52F85CA60F296CE99FC97A:\
+00000000000000000000000000000000
+
+89ABFA208A52F85CA60F296CE99FC97A:FA092A3DD37EF94837715BBC72C9008F:\
+00000000000000000000000000000000
+
+FA092A3DD37EF94837715BBC72C9008F:8A2288E53B2F0DD376ED385911BB4BB9:\
+00000000000000000000000000000000
+
+8A2288E53B2F0DD376ED385911BB4BB9:0CD12B0AEC2BA1C57F06E268A4BF5966:\
+00000000000000000000000000000000
+
+0CD12B0AEC2BA1C57F06E268A4BF5966:0B86524D05D0963C1BDF538290156686:\
+00000000000000000000000000000000
+
+0B86524D05D0963C1BDF538290156686:79031361A2E423A7C4D1613C3873C0A0:\
+00000000000000000000000000000000
+
+79031361A2E423A7C4D1613C3873C0A0:DD66BC447E835A9F426D0A2267850461:\
+00000000000000000000000000000000
+
+DD66BC447E835A9F426D0A2267850461:4294DCCF31F54E693179449F25B514CC:\
+00000000000000000000000000000000
+
+4294DCCF31F54E693179449F25B514CC:0A402C1A0F2EB568EDB7252AFDA4192B:\
+00000000000000000000000000000000
+
+0A402C1A0F2EB568EDB7252AFDA4192B:FFACF106A37C74D17009E2566E611BE0:\
+00000000000000000000000000000000
+
+FFACF106A37C74D17009E2566E611BE0:99E058DA9540E6B5C5A869CB9204010B:\
+00000000000000000000000000000000
+
+99E058DA9540E6B5C5A869CB9204010B:8D616AB19B75842DC5EF102CE4BB2A51:\
+00000000000000000000000000000000
+
+8D616AB19B75842DC5EF102CE4BB2A51:06C7C640672895C3CCFD52DB2CD9D51B:\
+00000000000000000000000000000000
+
+06C7C640672895C3CCFD52DB2CD9D51B:EB2B67E27ABCB5C06DA3D3EECEC8A25B:\
+00000000000000000000000000000000
+
+EB2B67E27ABCB5C06DA3D3EECEC8A25B:62EC35DC05A0BA40FE5D33A0B974C152:\
+00000000000000000000000000000000
+
+62EC35DC05A0BA40FE5D33A0B974C152:A4CB55D7881ACC44F868C8BCFE098091:\
+00000000000000000000000000000000
+
+A4CB55D7881ACC44F868C8BCFE098091:5CEE73CEBCAA22DF78C8C9FB8A47E5D3:\
+00000000000000000000000000000000
+
+5CEE73CEBCAA22DF78C8C9FB8A47E5D3:62FCD19C3AC4370A4CC58AA619B0EA2F:\
+00000000000000000000000000000000
+
+62FCD19C3AC4370A4CC58AA619B0EA2F:3583E618DAC3CE4347FD0E8AE6D6F5E9:\
+00000000000000000000000000000000
+
+3583E618DAC3CE4347FD0E8AE6D6F5E9:2B307B42E0B9EF2D2EC3EEA07D339A87:\
+00000000000000000000000000000000
+
+2B307B42E0B9EF2D2EC3EEA07D339A87:29A212AF4220054975D7C2AE9242AFA8:\
+00000000000000000000000000000000
+
+29A212AF4220054975D7C2AE9242AFA8:67D5BD878FF66CDB33A4DD07EB634F91:\
+00000000000000000000000000000000
+
+67D5BD878FF66CDB33A4DD07EB634F91:53944CA7C3BBBBE32C9BA9D8A8B765D6:\
+00000000000000000000000000000000
+
+53944CA7C3BBBBE32C9BA9D8A8B765D6:9213B43D06D0AB7ECCC5CA751C5DBAA8:\
+00000000000000000000000000000000
+
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:97778747D60E425C2B4202599DB856FB:\
+000000000000000000000000000000000000000000000000
+
+97778747D60E425C2B4202599DB856FB:885C6C280610DA436936E3C5AEEB9512:\
+000000000000000000000000000000000000000000000000
+
+885C6C280610DA436936E3C5AEEB9512:749935A9971B7060043018F95329A530:\
+000000000000000000000000000000000000000000000000
+
+749935A9971B7060043018F95329A530:05F0D089DE79801B3BE3D3D1361628DD:\
+000000000000000000000000000000000000000000000000
+
+05F0D089DE79801B3BE3D3D1361628DD:35F8044736D1FF4142460E4E72610700:\
+000000000000000000000000000000000000000000000000
+
+35F8044736D1FF4142460E4E72610700:B7028947854FE0C670E1E7416C2803DC:\
+000000000000000000000000000000000000000000000000
+
+B7028947854FE0C670E1E7416C2803DC:D4F8A703F24F7E0AC5807EADADCA8CC9:\
+000000000000000000000000000000000000000000000000
+
+D4F8A703F24F7E0AC5807EADADCA8CC9:77F1D30164CD2984C52ACEC02CAE2CD9:\
+000000000000000000000000000000000000000000000000
+
+77F1D30164CD2984C52ACEC02CAE2CD9:CE509EEFF43FB5C22A9756B023573775:\
+000000000000000000000000000000000000000000000000
+
+CE509EEFF43FB5C22A9756B023573775:B9D5ACCA79E9719979DA1E657C391F07:\
+000000000000000000000000000000000000000000000000
+
+B9D5ACCA79E9719979DA1E657C391F07:9E3B2E46FC6E2D71D46AF0D5CF36B456:\
+000000000000000000000000000000000000000000000000
+
+9E3B2E46FC6E2D71D46AF0D5CF36B456:D8104637E81C52CCEFB0AFE87F4BAF85:\
+000000000000000000000000000000000000000000000000
+
+D8104637E81C52CCEFB0AFE87F4BAF85:C7F9AF5B41E9EB5387DB1D122E483F0E:\
+000000000000000000000000000000000000000000000000
+
+C7F9AF5B41E9EB5387DB1D122E483F0E:D7ACF96A441BB267B591FBCEECB0494F:\
+000000000000000000000000000000000000000000000000
+
+D7ACF96A441BB267B591FBCEECB0494F:DA2234B06D83F32064A78AD3C5303D73:\
+000000000000000000000000000000000000000000000000
+
+DA2234B06D83F32064A78AD3C5303D73:70EF6DCDD349CD7F1D1A0EB3CB18C8C7:\
+000000000000000000000000000000000000000000000000
+
+70EF6DCDD349CD7F1D1A0EB3CB18C8C7:DA093FB2C0F00258D8D9F216C91C0C9C:\
+000000000000000000000000000000000000000000000000
+
+DA093FB2C0F00258D8D9F216C91C0C9C:26EAEEAE8FBE4835E5C43CBF3249CBB6:\
+000000000000000000000000000000000000000000000000
+
+26EAEEAE8FBE4835E5C43CBF3249CBB6:35692A1CC8E9FBB99DEE2AD149EE7F33:\
+000000000000000000000000000000000000000000000000
+
+35692A1CC8E9FBB99DEE2AD149EE7F33:6929CAD6052F809A2850D7E754C11C8D:\
+000000000000000000000000000000000000000000000000
+
+6929CAD6052F809A2850D7E754C11C8D:5F4E499D26ED1D290D9A187FB7B7FB14:\
+000000000000000000000000000000000000000000000000
+
+5F4E499D26ED1D290D9A187FB7B7FB14:BC5B30B2BAE077710A9DF5686794965F:\
+000000000000000000000000000000000000000000000000
+
+BC5B30B2BAE077710A9DF5686794965F:41661F98160A6556815A15B1C1C2E080:\
+000000000000000000000000000000000000000000000000
+
+41661F98160A6556815A15B1C1C2E080:EC2E71697E742ABDBB5FE516E50DBAD5:\
+000000000000000000000000000000000000000000000000
+
+EC2E71697E742ABDBB5FE516E50DBAD5:CB104FF2203633E97573D308923C7AE9:\
+000000000000000000000000000000000000000000000000
+
+CB104FF2203633E97573D308923C7AE9:C47B77D5FAD3535CFAE0BE60B48C741E:\
+000000000000000000000000000000000000000000000000
+
+C47B77D5FAD3535CFAE0BE60B48C741E:BCA5C36E33821A60CAF6E2DA72956C5E:\
+000000000000000000000000000000000000000000000000
+
+BCA5C36E33821A60CAF6E2DA72956C5E:B780AA350F6EFB3B805E505A2D32249F:\
+000000000000000000000000000000000000000000000000
+
+B780AA350F6EFB3B805E505A2D32249F:8857D872D91FE8937E292C8948C0AF24:\
+000000000000000000000000000000000000000000000000
+
+8857D872D91FE8937E292C8948C0AF24:4FCF851C845CBD7D7C528F55B8E84662:\
+000000000000000000000000000000000000000000000000
+
+4FCF851C845CBD7D7C528F55B8E84662:BDDEE7D374D810E3658670F46054F99B:\
+000000000000000000000000000000000000000000000000
+
+BDDEE7D374D810E3658670F46054F99B:16A4F2C3A95B296FBB7F8DEC6F70A9D0:\
+000000000000000000000000000000000000000000000000
+
+16A4F2C3A95B296FBB7F8DEC6F70A9D0:2583F970ED6970C6D0963015D67217B6:\
+000000000000000000000000000000000000000000000000
+
+2583F970ED6970C6D0963015D67217B6:0E7BB2CDF9CD553709D2BE4E9497D2F3:\
+000000000000000000000000000000000000000000000000
+
+0E7BB2CDF9CD553709D2BE4E9497D2F3:A6D82EE721AAF1BA1BC3EBD8C75ABA9F:\
+000000000000000000000000000000000000000000000000
+
+A6D82EE721AAF1BA1BC3EBD8C75ABA9F:C1211304A35315EC827DAE80B3F29BBB:\
+000000000000000000000000000000000000000000000000
+
+C1211304A35315EC827DAE80B3F29BBB:4F0842F2D9EA5CD1AB743A8626DA6BE7:\
+000000000000000000000000000000000000000000000000
+
+4F0842F2D9EA5CD1AB743A8626DA6BE7:BF39E62B863AFFFAD3DEE960962E03AE:\
+000000000000000000000000000000000000000000000000
+
+BF39E62B863AFFFAD3DEE960962E03AE:147C3CB084958D3FBB9D4223D3126BF3:\
+000000000000000000000000000000000000000000000000
+
+147C3CB084958D3FBB9D4223D3126BF3:6E76BEF9304B115EFC1C9002FBB848A0:\
+000000000000000000000000000000000000000000000000
+
+62E45B4CF3477F1DD65063729D9ABA8F:0F4B897EA014D21FBC20F1054A42F719:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0F4B897EA014D21FBC20F1054A42F719:9A4D42A7F27D42E542286ACF6650CF8A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9A4D42A7F27D42E542286ACF6650CF8A:5E5F71257B5156C075FDC4BCBE996527:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5E5F71257B5156C075FDC4BCBE996527:5A8112FB681B184766069A229BC0E1B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5A8112FB681B184766069A229BC0E1B6:2169853AD199721728B2F41FF6C3F316:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2169853AD199721728B2F41FF6C3F316:FD3954D96EF5B4078F5C301BAF15A3DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FD3954D96EF5B4078F5C301BAF15A3DE:DB1F3D03E0012505E354B2F4D7C7A255:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DB1F3D03E0012505E354B2F4D7C7A255:375CECE4E897512373B86A82A6A660D5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+375CECE4E897512373B86A82A6A660D5:4CDA1DDDD8849D47609D7D9803FD67D6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4CDA1DDDD8849D47609D7D9803FD67D6:20A6C90C54A118487C173AE3166EF219:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20A6C90C54A118487C173AE3166EF219:F4A0164DFC1F38E967F3DDE74B7B0CAD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F4A0164DFC1F38E967F3DDE74B7B0CAD:638D1B47820C0FD0A1BFA5FB05AE9087:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+638D1B47820C0FD0A1BFA5FB05AE9087:CDE141CD9E784912B6BEFD62003FE253:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CDE141CD9E784912B6BEFD62003FE253:84276E8EB17CB38307F3ACFE9480A771:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+84276E8EB17CB38307F3ACFE9480A771:27BA4090E1929A7E65D0C5078039A677:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+27BA4090E1929A7E65D0C5078039A677:264E4F150552D0D5F81583635189EED1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+264E4F150552D0D5F81583635189EED1:F052005B58BE2C8981575BA5C31D812C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F052005B58BE2C8981575BA5C31D812C:807E73C57A18CA88CA0F58C2FFD06394:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+807E73C57A18CA88CA0F58C2FFD06394:C317C6C0411947887DFCE0A9B2270B5F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C317C6C0411947887DFCE0A9B2270B5F:8ACD4164453A4C1C0DACBC8C2ED0896C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8ACD4164453A4C1C0DACBC8C2ED0896C:2BA5D280D05FBAF78A8B55BF5FD8D343:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2BA5D280D05FBAF78A8B55BF5FD8D343:DDF70B8350ED845F6D875B0C85961D39:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DDF70B8350ED845F6D875B0C85961D39:039FD445F0A6D65698D5146D498C8BDB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+039FD445F0A6D65698D5146D498C8BDB:22AE4D552D09558DEEEFC9518C01F4E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+22AE4D552D09558DEEEFC9518C01F4E2:D5947EA67A7BD88DA577A28254EE44EF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D5947EA67A7BD88DA577A28254EE44EF:22698C92691EE76CAD72880F577EFEC3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+22698C92691EE76CAD72880F577EFEC3:10ECA6E5E499742DDEC48434B767EBA1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10ECA6E5E499742DDEC48434B767EBA1:3D97E93A44C2CB1CE9AF5770A4BD1A34:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3D97E93A44C2CB1CE9AF5770A4BD1A34:F89C438D5311FC8235C632629CE1F3A0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F89C438D5311FC8235C632629CE1F3A0:4114C623ADF6DB0958FFA2DC27A2A828:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4114C623ADF6DB0958FFA2DC27A2A828:980089430C89563A5510DF5196E07040:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+980089430C89563A5510DF5196E07040:1D1FEFBD55AA23487CD2DEC4D370302D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1D1FEFBD55AA23487CD2DEC4D370302D:73A8AAE732EF445F3462353181168B23:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+73A8AAE732EF445F3462353181168B23:1D8116306AF7D70FE419226F35251687:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1D8116306AF7D70FE419226F35251687:84EFA8A595B06C91A5A083440DAF5B50:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+84EFA8A595B06C91A5A083440DAF5B50:630EECD4A8A957A610765E01A1D07C45:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+630EECD4A8A957A610765E01A1D07C45:825A47AD6FCE09FEDB5D8F07DE6A2707:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+825A47AD6FCE09FEDB5D8F07DE6A2707:0C472D25510DD0592B5130FB4272DECA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0C472D25510DD0592B5130FB4272DECA:3DA22A91B605A540E474383672C8D06C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3DA22A91B605A540E474383672C8D06C:9A1C14309E4B246C9E7B485A7F41D046:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B3E2AD5608AC1B6733A7CB4FDF8F9952:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:8655D5CCAF76A3A8AA09841F04689465:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:F611F21A70C0AB5FB3D52AD5E8196E09:\
+20000000000000000000000000000000
+
+00000000000000000000000000000000:6676D02EAE3EE58FA396BE40A3A6A234:\
+10000000000000000000000000000000
+
+00000000000000000000000000000000:786E147E5D66764A16DFE1DCB10F3F13:\
+08000000000000000000000000000000
+
+00000000000000000000000000000000:FDDBC84DA51496AD1CA2B7013B93FFA8:\
+04000000000000000000000000000000
+
+00000000000000000000000000000000:B5A0BB3A8E7FEAC192B7BF8080E2CC81:\
+02000000000000000000000000000000
+
+00000000000000000000000000000000:9A4802E8BF4426467617E9A44072EB76:\
+01000000000000000000000000000000
+
+00000000000000000000000000000000:BE279F4EE696EC5B07820A1066F110CD:\
+00800000000000000000000000000000
+
+00000000000000000000000000000000:4BBB919E52C258960549FAE9DD5FF524:\
+00400000000000000000000000000000
+
+00000000000000000000000000000000:6B077B5DE4C9961DC6E11053662E3CFB:\
+00200000000000000000000000000000
+
+00000000000000000000000000000000:755358499858F166C9DEAF2E79B3EDA3:\
+00100000000000000000000000000000
+
+00000000000000000000000000000000:632644AA2ACB4FB3214E9E5BFF57D4D8:\
+00080000000000000000000000000000
+
+00000000000000000000000000000000:DD3F06DD5A90BD7EA3F4B1BFB56E4ABB:\
+00040000000000000000000000000000
+
+00000000000000000000000000000000:B2FB07551FD5B549C857020356B99D45:\
+00020000000000000000000000000000
+
+00000000000000000000000000000000:5DE9EF4627A3EB6FD3920C322ECE9FAB:\
+00010000000000000000000000000000
+
+00000000000000000000000000000000:A8D37D0254E1C908AAD02631B614A0C6:\
+00008000000000000000000000000000
+
+00000000000000000000000000000000:91372C769C1E64DE0FDDC1C63436B623:\
+00004000000000000000000000000000
+
+00000000000000000000000000000000:4F8FF5063FFF638497733E1526EE27BD:\
+00002000000000000000000000000000
+
+00000000000000000000000000000000:5157ECB5597AC6A8D761E97517C65C0F:\
+00001000000000000000000000000000
+
+00000000000000000000000000000000:117B9349CFFD2066452CC0FE204C18A5:\
+00000800000000000000000000000000
+
+00000000000000000000000000000000:AE0AF51926529A3F354F7585578F6439:\
+00000400000000000000000000000000
+
+00000000000000000000000000000000:B2723B8D2D61497DBF44FF9D70E48C0E:\
+00000200000000000000000000000000
+
+00000000000000000000000000000000:464B3EB2A0F8A394DA239E0D0D62EDE2:\
+00000100000000000000000000000000
+
+00000000000000000000000000000000:AA03D30E1CE0E91DC360B1E538017F05:\
+00000080000000000000000000000000
+
+00000000000000000000000000000000:B1EDF5E18160BF8E16F386D999BF65BE:\
+00000040000000000000000000000000
+
+00000000000000000000000000000000:85F1BDD358B23675328841103F1DCE65:\
+00000020000000000000000000000000
+
+00000000000000000000000000000000:38DEA42C35E5758C7C5CCF451936DFCB:\
+00000010000000000000000000000000
+
+00000000000000000000000000000000:E484E7CB2D35D5AE92939B06864A0E6B:\
+00000008000000000000000000000000
+
+00000000000000000000000000000000:53B7E22F63F4D8AAC66D148619A7691D:\
+00000004000000000000000000000000
+
+00000000000000000000000000000000:0042A8EDB756329533D82ED13386E648:\
+00000002000000000000000000000000
+
+00000000000000000000000000000000:44BBDB223AFCC69EB69C5D07AF10E5D8:\
+00000001000000000000000000000000
+
+00000000000000000000000000000000:C5B1739AF4C0AE459BF11144132D0979:\
+00000000800000000000000000000000
+
+00000000000000000000000000000000:151BBFAECB027BAB90C8DA3E4743F033:\
+00000000400000000000000000000000
+
+00000000000000000000000000000000:376786816F319B96A19B134143952FE5:\
+00000000200000000000000000000000
+
+00000000000000000000000000000000:3E94AC897203461EFD9EED441F66AE9F:\
+00000000100000000000000000000000
+
+00000000000000000000000000000000:61A93766162F0B01EDC84D47B1D4ECAA:\
+00000000080000000000000000000000
+
+00000000000000000000000000000000:B21FA9D0AC731750F15B47FFF2BC4030:\
+00000000040000000000000000000000
+
+00000000000000000000000000000000:BDE8813E0E4EAE6CECCBC4C6BD10C610:\
+00000000020000000000000000000000
+
+00000000000000000000000000000000:50A5AE30DC3432F3060EE3628B274FFB:\
+00000000010000000000000000000000
+
+00000000000000000000000000000000:E3DA95B76AD9E29F0B3F14DD33C670AC:\
+00000000008000000000000000000000
+
+00000000000000000000000000000000:969DC8A583DED13E53042450FA4BE8FA:\
+00000000004000000000000000000000
+
+00000000000000000000000000000000:D7CB0D2F9BFF048CBD8CBD8452361611:\
+00000000002000000000000000000000
+
+00000000000000000000000000000000:E056677749114108153C6AC262EC0396:\
+00000000001000000000000000000000
+
+00000000000000000000000000000000:E5572F1812044977D4309B8D675CAE48:\
+00000000000800000000000000000000
+
+00000000000000000000000000000000:F00C1AB95B5CE3D3ACC2162E7A7F0262:\
+00000000000400000000000000000000
+
+00000000000000000000000000000000:AB33C3682E0C1BFA627F4932AE4AAD94:\
+00000000000200000000000000000000
+
+00000000000000000000000000000000:EE5B68820CB978CAACA22B1D590E31CF:\
+00000000000100000000000000000000
+
+00000000000000000000000000000000:8ACACFB9E872873E315D84657613756B:\
+00000000000080000000000000000000
+
+00000000000000000000000000000000:75CD1E528E5B6DB21BC8E44E70E5ECFA:\
+00000000000040000000000000000000
+
+00000000000000000000000000000000:3195CE6F460654E6FC00672755A5B7C3:\
+00000000000020000000000000000000
+
+00000000000000000000000000000000:8ACC17F3EDF59AA02DBBA93F27AD11D0:\
+00000000000010000000000000000000
+
+00000000000000000000000000000000:DD82C41281BE711F7E5DCDCDC6CBBF6F:\
+00000000000008000000000000000000
+
+00000000000000000000000000000000:971ABFC0649C9ABE7DE583799F31DD9D:\
+00000000000004000000000000000000
+
+00000000000000000000000000000000:9CD8E45DE9909A8146956F2B581AE664:\
+00000000000002000000000000000000
+
+00000000000000000000000000000000:095314A316B4DB9CE6F2CDDEC59ECE89:\
+00000000000001000000000000000000
+
+00000000000000000000000000000000:B626E1C40D644E2E72370CA4A3528576:\
+00000000000000800000000000000000
+
+00000000000000000000000000000000:002E4294BD6DDE3E3BFFB0CF5A5A7D4B:\
+00000000000000400000000000000000
+
+00000000000000000000000000000000:DA89C327F041BEBDB09E835ED2A2DDBE:\
+00000000000000200000000000000000
+
+00000000000000000000000000000000:9BC999880C14C9358CA89C435B1FDB00:\
+00000000000000100000000000000000
+
+00000000000000000000000000000000:D0C92CFF98EB228C6C19B405E6EFEE77:\
+00000000000000080000000000000000
+
+00000000000000000000000000000000:FAE5C83332BB176704F0E73B27442C0C:\
+00000000000000040000000000000000
+
+00000000000000000000000000000000:DC9FB83F80E56CAF1DB807B5921927E8:\
+00000000000000020000000000000000
+
+00000000000000000000000000000000:6FBB39934CC2627EE4F93343F50EB9D4:\
+00000000000000010000000000000000
+
+00000000000000000000000000000000:02A31EDEF8DEA2DE3307748BF4DC1C54:\
+00000000000000008000000000000000
+
+00000000000000000000000000000000:8C433C3D2005B30996ADA41F896436AC:\
+00000000000000004000000000000000
+
+00000000000000000000000000000000:ED04C68D4D73C6EE193E0FC9E2CBD1B0:\
+00000000000000002000000000000000
+
+00000000000000000000000000000000:515E01A6F25A4F1B2B57B27DECBFF195:\
+00000000000000001000000000000000
+
+00000000000000000000000000000000:30A07996E5C40C41786FC75B9C56325B:\
+00000000000000000800000000000000
+
+00000000000000000000000000000000:279C94707B0732D210DA7B619158825A:\
+00000000000000000400000000000000
+
+00000000000000000000000000000000:07552A95AC44BB11CD34428C858FD19F:\
+00000000000000000200000000000000
+
+00000000000000000000000000000000:BA67FC2E51DA92EA19079B237B42C9D8:\
+00000000000000000100000000000000
+
+00000000000000000000000000000000:40387C974070B484E0DBAAFD5ADA0243:\
+00000000000000000080000000000000
+
+00000000000000000000000000000000:3BF99A29B17D84BE5F8DC315616061F8:\
+00000000000000000040000000000000
+
+00000000000000000000000000000000:D4EF00C794D337961FD9E3B5AF7A67A5:\
+00000000000000000020000000000000
+
+00000000000000000000000000000000:1C77C28A6CBF3CBB24F2686ED3A408E2:\
+00000000000000000010000000000000
+
+00000000000000000000000000000000:F93568CD7CBA7A6E9B9DD7144F1D4ABB:\
+00000000000000000008000000000000
+
+00000000000000000000000000000000:C3BCD1F7F268E2806CCF0498C85D2E3E:\
+00000000000000000004000000000000
+
+00000000000000000000000000000000:2FD2F0DEB5DBF7EB3B9050042E56A9A9:\
+00000000000000000002000000000000
+
+00000000000000000000000000000000:2150DEB8C7C6327227A772031FF64047:\
+00000000000000000001000000000000
+
+00000000000000000000000000000000:3E8B4B1CBB877B6F612BFB391043CFC3:\
+00000000000000000000800000000000
+
+00000000000000000000000000000000:2376F56DFEB40C9348D758CA068C2127:\
+00000000000000000000400000000000
+
+00000000000000000000000000000000:AABB351CA9BDCDACCD8E966766FF1C59:\
+00000000000000000000200000000000
+
+00000000000000000000000000000000:212EF966B6CEECC65B5B0AE6A9DAA099:\
+00000000000000000000100000000000
+
+00000000000000000000000000000000:99C95AC67935AE473E2EF3907DDCE5B3:\
+00000000000000000000080000000000
+
+00000000000000000000000000000000:125DC68286DB1F81E6CD3D0C9EF8B922:\
+00000000000000000000040000000000
+
+00000000000000000000000000000000:CC55D94C0102A12D87454DB8BA8E654C:\
+00000000000000000000020000000000
+
+00000000000000000000000000000000:3F1E089ACAD719F7DB9292A770038475:\
+00000000000000000000010000000000
+
+00000000000000000000000000000000:EC4D155D404F72B4BE88D1E17C345822:\
+00000000000000000000008000000000
+
+00000000000000000000000000000000:276F8AECA95C7F65CD95B77680955548:\
+00000000000000000000004000000000
+
+00000000000000000000000000000000:7D78CE850C26BB18B8631CDFF0A5E597:\
+00000000000000000000002000000000
+
+00000000000000000000000000000000:6345692D62E879A058F342D5226A036D:\
+00000000000000000000001000000000
+
+00000000000000000000000000000000:E19D5A2899061B7B5537EA6DF0390FE8:\
+00000000000000000000000800000000
+
+00000000000000000000000000000000:4FAB8BB80E979853052BA0B19EF8521D:\
+00000000000000000000000400000000
+
+00000000000000000000000000000000:E84EE11321AF1C0AE6430C4F600270B4:\
+00000000000000000000000200000000
+
+00000000000000000000000000000000:73048F29C44F0953DFCC6B5380D36977:\
+00000000000000000000000100000000
+
+00000000000000000000000000000000:16280B84B187AE90E25121AB297620FA:\
+00000000000000000000000080000000
+
+00000000000000000000000000000000:FAAE881E9FA9DCA876B668CCAFA12B6A:\
+00000000000000000000000040000000
+
+00000000000000000000000000000000:46A73C4A4516E1E0BE2140E175A7225F:\
+00000000000000000000000020000000
+
+00000000000000000000000000000000:01C71A7B0BD6410894C9234A4250ABB4:\
+00000000000000000000000010000000
+
+00000000000000000000000000000000:EA8CEF3C1E8EF94D4A17A4D4C1C28C32:\
+00000000000000000000000008000000
+
+00000000000000000000000000000000:13BB356657B36C0D023047B324443468:\
+00000000000000000000000004000000
+
+00000000000000000000000000000000:B14DCC5250036260131B3D92B1B26C18:\
+00000000000000000000000002000000
+
+00000000000000000000000000000000:261E07BADC6E4BBB0EAD9ECCAE179821:\
+00000000000000000000000001000000
+
+00000000000000000000000000000000:1D40D508EB8878251EC5C01D8E9949BB:\
+00000000000000000000000000800000
+
+00000000000000000000000000000000:735BDCA8DF0C58679161E99BED3B8D3E:\
+00000000000000000000000000400000
+
+00000000000000000000000000000000:49C907F757494623F8E8519F4A5D13A0:\
+00000000000000000000000000200000
+
+00000000000000000000000000000000:AB858C224E5A3ADDF5A7549A98EEAF94:\
+00000000000000000000000000100000
+
+00000000000000000000000000000000:7C7A62A1DBF206572A323682E0441458:\
+00000000000000000000000000080000
+
+00000000000000000000000000000000:7461D6F4D609F8BCA9CAB4EB559C71C3:\
+00000000000000000000000000040000
+
+00000000000000000000000000000000:2F646495150F4F9CA06B77281C1150FD:\
+00000000000000000000000000020000
+
+00000000000000000000000000000000:A0C27498F797D6A9F513640AFE6CC316:\
+00000000000000000000000000010000
+
+00000000000000000000000000000000:8D511A840453125335AB8DF8C64FA8E8:\
+00000000000000000000000000008000
+
+00000000000000000000000000000000:9E64465740D81CCB74713A144F636985:\
+00000000000000000000000000004000
+
+00000000000000000000000000000000:804499E6C6E8790988747009D3B3C66D:\
+00000000000000000000000000002000
+
+00000000000000000000000000000000:59EBC223BAC60B13198C9AF47066274E:\
+00000000000000000000000000001000
+
+00000000000000000000000000000000:CCA216CC095954AFD3DE594C91A26310:\
+00000000000000000000000000000800
+
+00000000000000000000000000000000:06FF525F42EFF20A548DA1B7DCD1FFF8:\
+00000000000000000000000000000400
+
+00000000000000000000000000000000:B2F1FD473FCA588111E6EB9DCE82CFA9:\
+00000000000000000000000000000200
+
+00000000000000000000000000000000:557307573D2E5225AD6EDADDF1FCAB68:\
+00000000000000000000000000000100
+
+00000000000000000000000000000000:CA159F81D155071BDCA701174C69184D:\
+00000000000000000000000000000080
+
+00000000000000000000000000000000:41491AE31AB75E3ACA41B1A2CB75C1D9:\
+00000000000000000000000000000040
+
+00000000000000000000000000000000:C3B4B9419C0E19D4A851C2DAD2954268:\
+00000000000000000000000000000020
+
+00000000000000000000000000000000:6E3DD6DF183B80A0FF5D2D0A4B25A2C8:\
+00000000000000000000000000000010
+
+00000000000000000000000000000000:EC69E1BD0815AE6C83876B75E58A7EB6:\
+00000000000000000000000000000008
+
+00000000000000000000000000000000:8F5766DE11517F63A60459B1EDC32D44:\
+00000000000000000000000000000004
+
+00000000000000000000000000000000:8A74C64985345925D8A6AB8E6A0D3589:\
+00000000000000000000000000000002
+
+00000000000000000000000000000000:F65B8E5EAF04B33AD5FCF1B14874E059:\
+00000000000000000000000000000001
+
+00000000000000000000000000000000:FD04E0B77403BBDC72A370240B45B92D:\
+800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CB0B4AC08E20385D31CF468B52B356E2:\
+400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C39B63B4A8F7BF5C3CC61141584DE462:\
+200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C63F433FF98BEE849D75D0F0402C9273:\
+100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9433992C094CDBEC06199B0517970B5D:\
+080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FA8B068AD3C2C32F99EF1A4F76C409AF:\
+040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:014617D6109068C39137EE0CC522163E:\
+020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:41B87685C649AD72C32D9390C23CF34B:\
+010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6836281F31AA9120DC144E26074491EC:\
+008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C4163CB0CA1315C3D0115D495E0FF701:\
+004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F0B8F3585636D2785FF619523C4365B9:\
+002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6E1740E818B450955C6B7612DBBA0DAE:\
+001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:192A2FAAC85794EB20E43645E2E1B749:\
+000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5CA4011E7024A4978B58E1DFA9278625:\
+000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:498152C714A2CEFD692AC99DB90CDDBD:\
+000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DEB3A9FEB22886C511A057AB858BB4DD:\
+000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D60466B1EA5C1C7A5DDFDA049A685B50:\
+000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:62A0EE49A6333815350E9C9CD7CB24D2:\
+000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3AE70846AFDCC299B32EB9DE118070B8:\
+000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5118414720E424364E15B5EDC8E64559:\
+000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:42F9E38F7FB493D6048C63F804F5AD62:\
+000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:71043DAA3CF78997D9965DE84B150FA6:\
+000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:55B0DF5816DD16D2EB5CDDC5478D0652:\
+000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CA853E905496251FF856259149FB5CCA:\
+000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BEF7C892708F0369378EA80C0EB9DD4A:\
+000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3E7D986D91BEE75E597999C3E7372F06:\
+000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8877D8DAF98680C7EC03C870BAFB66F9:\
+000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:493B8E5D02D01A6C98DDF4D016F4932D:\
+000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E372455C9A44DCD5AEA803A276B2C5C3:\
+000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:92FCA63F71BCD0C950231E104D833246:\
+000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1630F75A2F31B1998725D849CC2ADA9A:\
+000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E3B636FC5BE0F05A036AEDF4DE7154BD:\
+000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DBC8BD2D128A11715152306E19C9D1F9:\
+000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AEFB45876EE3B0025A2D26A7A20E2A72:\
+000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C7F1370CD98539026B8FD0968F7A8247:\
+000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D09CC037CDFD06ECAC142630A599C4F:\
+000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:94C29805153DB7FE4834BD261F0CA87E:\
+000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:B509BAF1EAB92764F8085764968CD111:\
+000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:E6ECD9CCAF93F302250A90E3C083C22E:\
+000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:1419D2C7A7A8F7AB5D78B327770EE8F7:\
+000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:984FA23C883200CFA802FCBF1DE752A2:\
+000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:003BFBA6334DEDFF7A3652DFDC73D04A:\
+000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:B21EC3CCD1303B81744348C64B5E5984:\
+000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:58557001247E8AFE91399042E723751B:\
+000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:0EF33C5A09600898D9FFE6AF5A06C2B6:\
+000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:AA0E866FEE8227BF6A8FDA4B318920AB:\
+000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:839A0DA3DB2718EEBB917B4CE37D23BF:\
+000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:BA3292A8130B2708EEBC5B2478B52C17:\
+000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:49B2A8F2FC9639B5918176993D96646A:\
+000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:21967CDE8F85ED1600F359F376CD18CA:\
+000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:6CCA94D43AB4B3A82FA4E514D928E644:\
+000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:3C76EAC404CF1E23B0A159C919A60206:\
+000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:F9DE0E78E8CC16D3A99D7642DEA13DB0:\
+000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:5B74643F1DEA8CA49078E4BF54B856CA:\
+000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:0E07FE27FBFAB005FF7EF334C3320736:\
+000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:477810CB11FC7E68144960AAD5372A64:\
+000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:A638D2171A231AFF384C97A7E9EFF6B6:\
+000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:9EA186F9AA6BE6D395E92474CCB9CAA3:\
+000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:7F6A295094E5512EDEA0B7206B977270:\
+000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:2DD07726A9333391A6EB41F4859A1627:\
+000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:515847FB17843E42C936A6201DF28563:\
+000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:35B29379EABD877B458FC4A4FB532931:\
+000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:B986149A6E871ACD8E3E1E5F5928C889:\
+000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:84D0A488FB56ADB915B553B2EDDBCC41:\
+000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:63B2B5A4D51E076D673044C71DC68B02:\
+000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:F388AD195E35B2892E586B830D728440:\
+000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:8FA923E8949678F76205CF4CBE07FF2F:\
+000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:ACCF2708E75B4CF48E45B641B81C1F41:\
+000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:0A7C295579AD4296447B7E56EB719ED3:\
+000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:06572AAB88739B2BDEE8E1E9CCA22883:\
+000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:2CF0CA3DB58CDC62890D386B07A4145F:\
+000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:CEFAEB3CEAA5959FAB15E884D46E9F09:\
+000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:57EB477F0573D6C75E45EE8606B5A2B6:\
+000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:C55F45149DE0FD18F2588B2B9F54CC22:\
+000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:ABCA7BE4CCC597AD8783C24EAB8BF17D:\
+000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:702F3D046E8651BF40D6A5914D8AC8B5:\
+000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:2C6424E1EF097C8FB44138C8A5160AE7:\
+000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:3F0E8296D93C233CBBE22623CCB66A52:\
+000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:D828348AFD520F98ED31F0B9FA4C48B1:\
+000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:BA7A4AA5F32D16DF08ABAA63E72F8BAD:\
+000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:9211FA0B1161E094BE702157D4CAFC73:\
+000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:1A4D5C52FDDEE81374295341F950055D:\
+000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:9544A653B635734B0FBC84E6C64B1AD5:\
+000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:8B7E7EE1A74570F35183E15D05114BD0:\
+000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:6567CE30F21EE879D60359CEE9AD3EC0:\
+000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:E5078C9B9B7572A60822A44150C6A4F4:\
+000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:51DFF3FE97481F08F6D5B66480AEE6D5:\
+000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:E84E478B15FB1BCD50E3CA9936FE9E01:\
+000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:FC614E54348A78E28ADB5DFB11130ADC:\
+000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:0F872CF9F54CE981ED17E41B23ED616C:\
+000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:AFCC9646ED78283BD19092853223F347:\
+000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:35D5A827B175D776F8F90F30F41A1C4B:\
+000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:B55980544140E694FCDFCE7C251C121C:\
+000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:244C4A55D5EEC8BD55C4F0D295ED2541:\
+000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:B3700314BD37894991C2FD4355B26845:\
+000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:43F3C6FFB517CD6E8EE1AEFCAA6FDE06:\
+000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:0F1A3E34821335E4EC22D404155192C2:\
+000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:22C59B22CC6A1E0EA313346F461324CD:\
+000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:2A90EF00D977A82EBDF6681F33D7DC1C:\
+000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:4B36176A8C174A635BF96A5B46BCF54C:\
+000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:E344C5213246712CAA2A056A6EE1868F:\
+000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:8F75D3C2ABBF84F3AA5E1734D6CC76A6:\
+000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:2258F75A5FC2B667DD0B28039CEA784C:\
+000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:D74F3EA90D02FC4908FDDCBE5849152E:\
+000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:0DCD8607E57390DD609717338591B205:\
+000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:594419C26F408B721F82ACCAC2DF1D5B:\
+000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:12D0F6A150858F64F0C88061CE592C11:\
+000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:5351E750DE5C9322AFA2885FB83C623B:\
+000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:7C120675A918C2C728149D332A196586:\
+000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:CDCA42B4E3ED64C2D37812847D7377CC:\
+000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:E4B73F8C0D9A40A67ACB9837CF8006DB:\
+000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:A863A13ED52E8BFD6652FEE291837B1D:\
+000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:64F9790C0BBD5C234FFADF0037485BB1:\
+000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:37A8AA3E38B937D92E1E41EC5E157FE0:\
+000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:F84D2A60A99BA9C17848BFBFBFEA0271:\
+000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:01AD547F2E1A713AC0B3D3E332A044A6:\
+000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:ED06A9B6EB5E24DF2CDA83564080AE93:\
+000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:3682650D35D3247471F3EB10A173479D:\
+000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:E3BD985B5B7C83F841F2F2A37A2974B3:\
+000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:EEA30254CF0FD6379A7203FC2328EEB6:\
+000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:4F2C052C360DA20FF826DFA98429AAA5:\
+000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:5F4CE32E4D55F0EB15799A3C46E1C40A:\
+000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:2EBE1C941F8247BBA3E85A04BA10B27C:\
+000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:9F41738ADB0CD8B4DD048527FCCFC23B:\
+000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:0E9F502FEE59A16CC5CEEDC82FD98E1A:\
+000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:56DC540BBAFB42B9817B4D464993DBCE:\
+000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:7421D3EB41769680565DD67683FE6737:\
+000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:777D08A4999E79A97CDBAFA5B6C33D12:\
+000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:4F3145690B092FAEDEBC672FE0ABC1EC:\
+000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:C221E4ABE2DD5ABA26DC29B6F3E421C6:\
+000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:EC48948223D3086FA730F6F81C103E8B:\
+000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:38B03357B1A0719A4E04FC3725B66400:\
+000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:A9458E67FD55DFB7F5D43344D7B8D994:\
+000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:C82BBCFE8E647A4915E578BB6BB410EC:\
+000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:27DA68521E57EFBC401640232896ABC7:\
+000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:DD6C4A6784C293F1D6B334731298C043:\
+000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:C2C4A691BD77C60869E6C030E357B7DF:\
+000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:EDA41EF6E7863F1A7D718E31A7D0AB0F:\
+000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:7915CF01D36808B875E1561FB88ECF2D:\
+000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:033826639ABFCBA709DEECD8F32306D5:\
+000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:B7CE1348B2832FABD58542A59319C947:\
+000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:479E3B195B3F9BE75AA2D0931F179495:\
+000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:6B9E7F0C5050E8CD232722C33261135D:\
+000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:063F64EDD05343702B76BE045A9D1DDD:\
+000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:E1AE2D5667E440C0A44EF9CC91AA10CC:\
+000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:A64A692A55AF5D1C99794707BA00E670:\
+000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:B975AC5AFA03D77D7361AACFF32E1B39:\
+000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:267A1379C257776BE4CA75C8B1A59EF6:\
+000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:ED392DDA2AD879B58405B41FAA7A56A1:\
+000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:4DECF57B85B75F1A78431A972CC873F6:\
+000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:5F9D95B7F415376A6665BDF645E5C6AC:\
+000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:5929FF53CC9876F923C6D19D3D101F18:\
+000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:D6CF5F18474D3A44D0BE029EE879E6FA:\
+000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:8860A98873A8DBFFDC4D7835F3D59BB7:\
+000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:4B506DF2FF9DA5672F55624AFE5374E8:\
+000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:B4D6692D5AAE39519C0AAB97597A5521:\
+000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:7185FA267D3926EA0804F07A91398C37:\
+000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:8C3BD232227C1C1B214186A603D85115:\
+000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:5300AFD8D507A60ACB0907B4D3E3D2B0:\
+000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:D8A16D32AE71F991EE2C1C19153B146D:\
+000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:32B3F26C1415BF7F82B6A637843F4C21:\
+000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:E416420B5F736F39328D36181992A720:\
+000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:619918287897135AD5516BA12A0FC6D7:\
+000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:69830C559F08DDCEEB6F83900DC14626:\
+000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:BB451FB76A7B1FE65E0332DE6E6712A3:\
+000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:AF2DE55E1EFFAF00EBF4EAEE45B29A4C:\
+000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:CA31B9A81450A198A073A299C7DF14C9:\
+000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:4FF7E9FADFCFFBB2DD3F23214B407180:\
+000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:B8BC9344751D34B0BFE353E5F3A9E309:\
+000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:4589951B936D1948299548D199E0612F:\
+000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:61B33E9A6A14F21B12D00832385F9BCA:\
+000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:652B66FBC2B192ACA177D4C16ACB1E3F:\
+000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:81A252288A18D4E4EC1F919FE34BD4C8:\
+000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:4D38323769C7AEFBF838F51A57E21C0E:\
+000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:C07D35D5788A04FEEBA6A337453DEFCA:\
+000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:6692591964FF5304D877DDE631E55AC2:\
+000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:1792F89A673DFE67A04BAC230317BFD3:\
+000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:0EC45273FAA59A4C6AA56C0BDF9DC1C4:\
+000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:273575F8DB870005ED51F0F1FB962A35:\
+000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:D9EDC0E324D69F3CAB465E3F63AC4CD3:\
+000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:647B9C834502295B5D46AE962ABD9059:\
+000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:3C8B932E1E8C1E9FD4629AF03D16D717:\
+000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:9FD433DAE0C3B5C35C7CA5468B4AF8DE:\
+000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:916E8226F1925A4C7E0056E8951B4609:\
+000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:A53FCF269CF194C323B2C2A5B82571E2:\
+000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:51C6D510F3053D502D141C99FBB28618:\
+000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:040E54E63CCF8E5D6EE6A27EEDCC02AB:\
+000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:DE90BD5F4C96E4F52EC9200D9E298DCD:\
+000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:87233EAEFC125F7C6E1FE329CC415520:\
+000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:71B61DD72D4FBD96542E73A5E5BD7CA5:\
+000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:F5F6E1B6215062A2547C1A7C84EB8E86:\
+000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:2DD740E5E0E0CBE72EBDF2808410D55F:\
+000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:EA4FCDBA1EB0C533938AA9FA32B740F3:\
+8000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B8E6D5134AB08E553AD5785B33D66111:\
+4000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2D7805B2B86764E8FC3DD6E2EFB1532D:\
+2000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B9449A4D8C53639D0A6751DB3695B325:\
+1000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B2C6850F1AAAF7CD2E9B3FC1F5433FDC:\
+0800000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7D124E20CE475B66BEA88399FF95C8C0:\
+0400000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D5F5ED2CDEC8D3043BD0C58238AF2820:\
+0200000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:051135A86EADA21353CB5FFD7A58408E:\
+0100000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FEF406FC9C405AFB959C796E4ED0AF0D:\
+0080000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:52DA5222BB9974AE66CC9BB77E1F15E8:\
+0040000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F5DC2C5F98AF6CF4BCC23ECEEAF213AD:\
+0020000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:09DF90DE791250ACBE170DC643780CF2:\
+0010000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3FA812132A21BEB83162C33B28CC242C:\
+0008000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CEE571785850DD567A75D9E244660C66:\
+0004000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:642BB005B38790E518E53A53373C2474:\
+0002000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E3EBE5FA1C748BCB125602F8B7911FAE:\
+0001000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C863C98E1C09C28B4A05B5FBCE64DF28:\
+0000800000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B4BAB3A731F8CCD8A09A5D3AFF77BE60:\
+0000400000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1A3FC4F1DE42F1AC5DA5F88701E6F292:\
+0000200000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FF43862813E9F1CFEF044F4B8CFED265:\
+0000100000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8F2785A7E28C1910580BBFD989A7F0D3:\
+0000080000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:26059027035B43615A7996D19FED9D42:\
+0000040000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8CD8416F37E3BA1B5D6D0838F6B6E604:\
+0000020000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BB0BD60CD950DE5E0B9AAF78FF9A30DB:\
+0000010000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B99C1D4F98B68E8CD7495D16F3260D7D:\
+0000008000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4F1A4F8D20456CFE0EF0E39DE6C71B9C:\
+0000004000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F453DB1AB45A6F5834F9908E1A15D4F7:\
+0000002000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DA25287B7CD050E9B3E2074ED3B49FCF:\
+0000001000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAB2AE0FF7C4902697DE88ED7F2FA06C:\
+0000000800000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:ABE6F6C9D29A58B985A91782EE28CF3E:\
+0000000400000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5C59FBE090DB3D75D7A5A8FD76F8A3DB:\
+0000000200000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DCA806B1D0BAFCEAB015EC19A3E5C7FA:\
+0000000100000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1BA870E6D62FEB16E6C2AA1128AE5ABA:\
+0000000080000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FE91367D4C178DD313C6AB7F3D5149A:\
+0000000040000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BFE27CB1B52150E0636A81473148B018:\
+0000000020000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F79BE17022979D01E3AFFB3499556DC4:\
+0000000010000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A2F2B772060C53A539B5A3FE4C935171:\
+0000000008000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DB97947A8B14B3E3859068A0288285F6:\
+0000000004000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1FD086FE698C5E092A8E0C9EE527714A:\
+0000000002000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8ADAB79B444DDDF86B8D53D2A9112881:\
+0000000001000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C36CEC9730A74CE94CF2EA5C7B0EC3ED:\
+0000000000800000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:033629A0675A45A11BE7924137D711EC:\
+0000000000400000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D5C22EF288E7D2D04BC04B57B702A03F:\
+0000000000200000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1FD290A5EB2E278C6396625034EB268C:\
+0000000000100000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:05C35E0CB6D27E6E9D680368B2ABA9B5:\
+0000000000080000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B0194CDF7510FE98EDF9464259378FAF:\
+0000000000040000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:043729754E5B1F63408F62742E5F2765:\
+0000000000020000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:24A2746042EC7970E8AB59589AD63775:\
+0000000000010000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7BDEF0A2EF8B637C4C3C5D001BAB5F85:\
+0000000000008000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0221B515A1559D96E9C3CBFB929E96A9:\
+0000000000004000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7E975026E5771D90EDA081B72C0BC77C:\
+0000000000002000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7C7F9F98B4739C9774F84E75E5B30A95:\
+0000000000001000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A4E176B7C98D76BC6662BBB3E606BA9C:\
+0000000000000800000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7FDBDA5910B26D8D3FE42987B09430C0:\
+0000000000000400000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7B134F40F8E10D8287B8E6FC0BDE45E8:\
+0000000000000200000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CF3C98CC0CAFB2935385C0B5D8F07857:\
+0000000000000100000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB71BA47019735DA4082D68A1A587BDB:\
+0000000000000080000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E9D45576FC1A56DAFB48ABFB90A1DE4B:\
+0000000000000040000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AE9408DC1A007CA9C13F2F9D12FC4F71:\
+0000000000000020000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B407201A6A44CB236468709B181BCA23:\
+0000000000000010000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:06E1A40D4F7534E24538D26802AF9E98:\
+0000000000000008000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3468992A9D6F274286611D1E5DB327BA:\
+0000000000000004000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:635748DEDCB4E65B76E818D09994D19A:\
+0000000000000002000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C2A0DACC741E90029F16CDA81BEB8D0C:\
+0000000000000001000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D20B9853FC98ED3FCFA4C3B9781352D3:\
+0000000000000000800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:869B106388046F6F5F9AE5ADC1F23BC2:\
+0000000000000000400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4F9BF7227D943B80C97B2FED132098FE:\
+0000000000000000200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7232A96D275C409349A0382BAE576274:\
+0000000000000000100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:ADAF9B3E14B8CC101A2F143B373517B7:\
+0000000000000000080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:813E38DF25E4356EAFC7ECEB75270FD4:\
+0000000000000000040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:46D6957C76223046E232EEBB661CCE59:\
+0000000000000000020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1714E3EDD2A7BFE4FC35D4B6034E4184:\
+0000000000000000010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:445ED35901D4608FAC3BCD59E685E77C:\
+0000000000000000008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:236F86A3A59F563611C9A1A9C8DF045C:\
+0000000000000000004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FC0739E82EF130E533C77FA15BD85B57:\
+0000000000000000002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EDC81185A966066433F1B19BE7659080:\
+0000000000000000001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9D0ED59542D4851F7812B29640739765:\
+0000000000000000000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4BA903B83FD4A443564723403BD7D431:\
+0000000000000000000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5DA2CD3D64EDCB29588F02BFED3D575B:\
+0000000000000000000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E66697B697E8881555F5B358A2EB7628:\
+0000000000000000000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7DE9B3320A7872088B1417AAC4E841ED:\
+0000000000000000000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:236D82828CE9A9471B51DDCDA350C542:\
+0000000000000000000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CF250F09887F0B9300FF865810A2E03F:\
+0000000000000000000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0103157DB999DF64D6C6DACB16F15F78:\
+0000000000000000000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EA918B3C7929C992E6F0D7B0DD6B8A59:\
+0000000000000000000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB853888B1D95F9C7BB7630231C9108E:\
+0000000000000000000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:46E63459DCC0514DD200BF82B6AEEA0B:\
+0000000000000000000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:19051C0A056D4B56DFF08C52FBBD4547:\
+0000000000000000000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:055240C320AC09978BE4EC0EE9E40123:\
+0000000000000000000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E0D04118BAD95366416C6D715507646B:\
+0000000000000000000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:888C70E963419AA6446123CD9685252C:\
+0000000000000000000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E060A32AF3CD8A525C60A8EB4BEB5B24:\
+0000000000000000000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:36A235722A72A5BD05896B74EBB39E35:\
+0000000000000000000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:665A781CF1F7839FA4E7EF66F5B47D45:\
+0000000000000000000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8156E976338FB48ED3E469F1485EAA06:\
+0000000000000000000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BA853DF1B7622D17A549624B234082F8:\
+0000000000000000000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3A411EF75149822F0C4E998587BA0CAD:\
+0000000000000000000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EA33525A7CC7C74340773389A764513E:\
+0000000000000000000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E007DDE8158568CF80C470745E455EEE:\
+0000000000000000000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C140AE31D6B8AB675539344B9D857A89:\
+0000000000000000000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8C86266079ABCEE926A5EF6F80F50308:\
+0000000000000000000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:CD77B23315E31DF96FABD6E427184F9F:\
+0000000000000000000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:A72E93628614A603E59ECC5C766A639B:\
+0000000000000000000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:00EE192F18F06F5799B9593DE71B2FBE:\
+0000000000000000000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:A79378A27F39485A2A6757A953DE8D63:\
+0000000000000000000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:38353F1349680DF284CF7D59272D435B:\
+0000000000000000000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:0960EF878BE3F63CB8A25AFDEE9272F8:\
+0000000000000000000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:CB52EEC84DD320FB74A13DF2D4AF5B64:\
+0000000000000000000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:89525CFDCCC1A572987EEEC44507942D:\
+0000000000000000000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:894183826F3CD163F2BDCE8FD123BCBD:\
+0000000000000000000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:152FAB85782DD050EF29C8C7E95C5941:\
+0000000000000000000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:6C8CC544D1E6B9B8ACEB723A6E903710:\
+0000000000000000000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:9D1DCFEFD9CAEB5934AA93278F8E0988:\
+0000000000000000000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:86473616CFE39825E9F93B4A5D1518F0:\
+0000000000000000000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:3EC955C39DC4442411A578115482A331:\
+0000000000000000000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:117C11E5DAFA73A4CBA2E599582DF463:\
+0000000000000000000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:371B4F0F917CDC7F028CF90072EA6C0C:\
+0000000000000000000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:F6EAC5AC916431427022EE688D4E8248:\
+0000000000000000000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:5E7787153D1C5E94A860600D0FE0F695:\
+0000000000000000000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:44888E6DD958A843AF2143DA81986196:\
+0000000000000000000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:F3B940BFEFF393BFDAF0C435D262961C:\
+0000000000000000000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:40781DABC58A81B11FAA4039E6F73345:\
+0000000000000000000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:7685B120BD850BD6D7A618E023D42BA0:\
+0000000000000000000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:8088416E7FEDB30B1883DF50E29CD4D1:\
+0000000000000000000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:B0C9ED5257B103131AB5DBECC16D1547:\
+0000000000000000000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:01C8B821C4683B586CD8096A0DC4FDAA:\
+0000000000000000000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:4CA16F058B3AE1E2B3774E3DF99087CA:\
+0000000000000000000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:620D06B8EFBFDD1EE274D5EAE42B8F0E:\
+0000000000000000000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:34CF934F88C0D631B3D80BE0A5671B11:\
+0000000000000000000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:F8AB4045BD0CD95486B921B7430E74A0:\
+0000000000000000000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:96ECEC4088D81E2EF27D74A96E2614DC:\
+0000000000000000000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:EB0152474310B99F0F8F0DFD6D67962C:\
+0000000000000000000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:74DA68DA599D7DD37918F24F7654DC4D:\
+0000000000000000000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:F766AD686EB2BAF2950974F78968F510:\
+0000000000000000000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:A2D18CF5C770587E19DBD6FFEBD52FAE:\
+0000000000000000000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:DDADE16C2B9E78715FC281197149E4F0:\
+0000000000000000000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:79931CFAC3FD4F540E53905538B5E122:\
+0000000000000000000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:93F88DDDE5004BD8998CDB7A1BD1EE4D:\
+0000000000000000000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:011A413B2CC8E56A94A5C6D3932B3C3B:\
+0000000000000000000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:C509B737BBC749EE466ADF8142F52B28:\
+0000000000000000000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:514332276B9E9299F9F722B63752B0A8:\
+0000000000000000000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:D9F3A75F94986D0A1AB14258934C21D1:\
+0000000000000000000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:6FE84CDC49C9A8A55D85EA1A1D5C0DD9:\
+0000000000000000000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:0C85C65BD9DE393D2FEA3BE5AC7BAB67:\
+0000000000000000000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:904C7F2E8084FC10D59480C3DE1CB1A4:\
+0000000000000000000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:52C696236B4B7EE6B03B8876DEA8DD45:\
+0000000000000000000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:A0D46DAEA95CB4968F62BD9B3F8075A8:\
+0000000000000000000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:51BE75B32A05384D2A2E08CB1EAB5F63:\
+0000000000000000000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:1123151EB432831D2C65A90ED1D0A429:\
+0000000000000000000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:A26350A8FF6C10FCBA736D46FC26BF69:\
+0000000000000000000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:FF85BEF6CF6674FA5EE40EC9FB9052FF:\
+0000000000000000000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:6ED96DB33AB981AF27894AC436CB4D62:\
+0000000000000000000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:B38DE9B3C4D6D128101B02FDD05E3BF8:\
+0000000000000000000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:11E05766EBB66AB211E2D9653EF3144D:\
+0000000000000000000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:F6A196E085116E5BC21732A2EF9ACAF4:\
+0000000000000000000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:BC2A6753CA41E306A0500E97B38D8A9A:\
+0000000000000000000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:773A687B1FC97918943C1B66EF693354:\
+0000000000000000000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:C6E2112CCDBD821D2B9068B285C5192B:\
+0000000000000000000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:EA69C8E28021801EE9A14809848D781F:\
+0000000000000000000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:6290745CD4CB62DE172F8AB30966EB57:\
+0000000000000000000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:1051EE4C389B96B1365B417C74EFBF10:\
+0000000000000000000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:52B6F3EE6655128999EEE3831E708D76:\
+0000000000000000000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:5BDE19A1D741ECE40CE98CD02F02AD75:\
+0000000000000000000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:36EF5E803A68F6AC20D92FB14E2AFDF5:\
+0000000000000000000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:B3E1E30B78FBBCA07F065A422D33410B:\
+0000000000000000000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:5FA0E6C8E6C1FCD613975A18348484CB:\
+0000000000000000000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:B74E4A2406EEB2AB836AED857754A612:\
+0000000000000000000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:52EBF44DB69347A22DF8CA0ABAE3D668:\
+0000000000000000000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:986B7B05D1E9639779D034047FC3B780:\
+0000000000000000000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:1846AF7EB612C5C356DAF4FE42108444:\
+0000000000000000000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:22AD41F78567C6D5C2266486404168DC:\
+0000000000000000000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:73409A5B03D08BCEE496F7255417DEC5:\
+0000000000000000000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:32C47FAEB48DA7847B3C5B063153B049:\
+0000000000000000000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:5514F66B91C06AD15BE581AA99F5961B:\
+0000000000000000000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:38AF52E0648030498BA94D0BBF819B8A:\
+0000000000000000000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:91D48EEE9A769F0753C6A6DC1037405D:\
+0000000000000000000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:2CA3F3F2BB2332984A97E5274462E7AF:\
+0000000000000000000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:806EE4C1C6432102E40A21F03222B0E1:\
+0000000000000000000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:E8BBDC90505FE81AB2024274BB2FA258:\
+0000000000000000000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:307920977ADAD0EEDEBA2CB8AF83D3CE:\
+0000000000000000000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:6B0A17013DFAAD05442FA8B298043438:\
+0000000000000000000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:BA6EC60065FA6C9679D7E47FC1B85479:\
+0000000000000000000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:F1AA580B5E904BED235ACE85C0E009D0:\
+0000000000000000000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:9092A797F7024CC218B4A3575F4F7D63:\
+0000000000000000000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:CF404B154F2A8388DA9ED1E93AC78894:\
+0000000000000000000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:1B32215E25E3EB15FE4BED2F2F31281E:\
+0000000000000000000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:999B92E27EC161089F45DB53D036C8F0:\
+0000000000000000000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:B2F7DBFD67DBC260A7CFCD9C90FEF16F:\
+0000000000000000000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:7BD9AA3B08F103C796EE8023EF474F0A:\
+0000000000000000000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:483121AF85F36EA159BE2EB5802FBF21:\
+0000000000000000000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:AE2788C2115CB466713687AB06FE5E46:\
+0000000000000000000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:ADE758D100ABEEB7BA80BF257781494D:\
+0000000000000000000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:6DF30205652926EB339833F2EDD8472E:\
+0000000000000000000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:031E86B2AD4D83A4A19BCAF191F9B65A:\
+0000000000000000000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:F605CCC9E46B1792EA2F0B4124924F42:\
+0000000000000000000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:A70E3286C50B8DD8306109AB59119510:\
+0000000000000000000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:6922EEA4B8AE7BFECE899009848A33DA:\
+0000000000000000000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:1DD856F5453D1D61860E48035BFDADC7:\
+0000000000000000000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:9AE9BEC5D195B32BD52623EF21CF2AA3:\
+0000000000000000000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:C89ADA0E7DF448DE2155DB7C3E3EAAF2:\
+0000000000000000000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:0D176C6E373B2A3B3408AD24BE258365:\
+0000000000000000000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:8C2E48AF6FE6305B58EF5B950061E93C:\
+0000000000000000000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:2E81D19464919FFB1886E81C46AEDE37:\
+0000000000000000000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:7169BEE79D4DCC57F771A43AA0A80EF1:\
+0000000000000000000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:425223474892BA95538DAFF58F3DD0D3:\
+0000000000000000000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:B2650BF17E26E9A4F6484DD2992517D9:\
+0000000000000000000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:71936A21362F80ECCED8FC955FF159F3:\
+0000000000000000000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:E09665C274E582FFD6BCD0663BD6EA12:\
+0000000000000000000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:3E8D36D10E6AB4454154A226B7D6E50E:\
+0000000000000000000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:5D008338DDD66164591A9B98B23323CA:\
+0000000000000000000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:6BC5ACE2FA017CCC5CD0A8E88AF73B28:\
+0000000000000000000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:C115E4646FC054C50C2BBEC7C20C94F7:\
+0000000000000000000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:2CEB602F3C61BE94AF96FD012BB3190C:\
+0000000000000000000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:5A04F68F56580702891E4ECF6C600C92:\
+0000000000000000000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:D6A0DC0D5FB91B6478B9A1AAA586431B:\
+0000000000000000000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:E38BB33BF982D61BB2CD980BFCE4C2BF:\
+0000000000000000000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:B47BF164959077E378396A175020AC95:\
+0000000000000000000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:CC5CEE68ABBFDC2DFE32FD3A1E433932:\
+0000000000000000000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:A8180BBB689F29A560296FF24C785DC4:\
+0000000000000000000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:DCCBE0BB943D3B772010A08C11E82763:\
+0000000000000000000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:0439C5D8BB8BDD7FCB3A3281BD8A3A3F:\
+0000000000000000000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:2864CEAE94E09933190479BEA2515040:\
+0000000000000000000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:2AFF33A00C93057FE56EDCBBB65987BB:\
+0000000000000000000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:38C6B37E80EC873DE0A0ABEB9803438F:\
+0000000000000000000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:1D9428E92329672C0E902F6AA6AFC874:\
+0000000000000000000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:2AB8CC1998977DF208C97B2D0DC86C54:\
+0000000000000000000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:2E42C343E7E489916E2F2C0AD2AFFFB1:\
+0000000000000000000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:571C17477C9FB6C334718983E0B25859:\
+0000000000000000000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:3ABAD289F84A4B75412C82D8AD9BD739:\
+0000000000000000000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:E91C1A5E57DD295A7F4AC1687F6B8DB6:\
+0000000000000000000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:60CEAEC342165320652D7ED13FDAC05A:\
+0000000000000000000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:DA854CEC00C19BB97F7D8292ABAEB5BB:\
+0000000000000000000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:6BC45EBD7172512E5F6D51C60E271ACF:\
+0000000000000000000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:6604FAE8ECBC741D0F46D90AA235CAF6:\
+0000000000000000000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:5F95FA50CF7CDD4B619DCB8D6E0B7873:\
+0000000000000000000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:C98C198A5A988E2911302C22BFDC4890:\
+0000000000000000000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:4B5818505B80DA67A206BF3107DF2B4C:\
+0000000000000000000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:B2EA813634A26DC5894BFC4BB070E147:\
+0000000000000000000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:B6DDED10D2E8B13D7C758692C844017B:\
+0000000000000000000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:F2DC2468DF800E237C026F968CC3AAE2:\
+0000000000000000000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:EBCCE81109DCF1B9793AB60BD062F033:\
+0000000000000000000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:1BC015DC9E1B9DBB68293EB93D65088F:\
+0000000000000000000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:F718F0FC2A276D6CBB7A2BD59BBC3DB0:\
+0000000000000000000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:D89BE6BDD07222EF8297FDD246C3DA09:\
+0000000000000000000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:7013B55968A743157C4959DE2068AC57:\
+0000000000000000000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:758199FCB16B8ADF9B1350A02B10B735:\
+0000000000000000000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:29D38DC5215AA1F3CAEC044C8B472696:\
+0000000000000000000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:F5E1BCA4497ED2B1D871B5877C5BE3A8:\
+0000000000000000000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:C7388535D265CBFCEDE6423CC29F33A4:\
+0000000000000000000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:84992BD0280C4CDF8B1587D42AA63605:\
+0000000000000000000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:197E91D0F0261D975BA1F6FAA7983E51:\
+0000000000000000000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:644BDF2B1508CFF2E8D791DADC5D4BD6:\
+0000000000000000000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:D7BB8C6C07F21F648CE87A17A0589334:\
+0000000000000000000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:B6718CB65E557AF3C25D03770AD6B1FA:\
+0000000000000000000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:F32E30ADD384B71F7254A15B4042E1F6:\
+0000000000000000000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:B5C218F26198EE763B863EDA24446609:\
+0000000000000000000000000000000000000000000000000000000000000001
+
+80000000000000000000000000000000:D962EFEBA75817BF6ED24BBBB5B7820D:\
+00000000000000000000000000000000
+
+40000000000000000000000000000000:639B9F07305BCC1D2E64CE3D1671304A:\
+00000000000000000000000000000000
+
+20000000000000000000000000000000:33ACF35AF3FF94B4C0A59C9035C99E79:\
+00000000000000000000000000000000
+
+10000000000000000000000000000000:C18D6444EE8DEAECC4697D021B9694D2:\
+00000000000000000000000000000000
+
+08000000000000000000000000000000:37DDA7DC913E6253679EB4A1906AE47C:\
+00000000000000000000000000000000
+
+04000000000000000000000000000000:1DED0AB726E2358CCB57451EB5A1711A:\
+00000000000000000000000000000000
+
+02000000000000000000000000000000:BFB43CD34EEC7C0A34CD77759E1396CE:\
+00000000000000000000000000000000
+
+01000000000000000000000000000000:607C0F5FB6A489AED3D3238FB0C51D37:\
+00000000000000000000000000000000
+
+00800000000000000000000000000000:0EBFB100FBBA1A66319743F846383323:\
+00000000000000000000000000000000
+
+00400000000000000000000000000000:8ECA01741C7622FB9EB41FD9826EEA32:\
+00000000000000000000000000000000
+
+00200000000000000000000000000000:BC7CABCFE201ECE01A42C2F4C49C1237:\
+00000000000000000000000000000000
+
+00100000000000000000000000000000:6DD5E5FFF9A41C637553AC4873E118F6:\
+00000000000000000000000000000000
+
+00080000000000000000000000000000:009DFBAA196DF5257E6F48F3310DDD58:\
+00000000000000000000000000000000
+
+00040000000000000000000000000000:9A41BD1783AFB149865D341334D8DA3D:\
+00000000000000000000000000000000
+
+00020000000000000000000000000000:9D3A9D9EA90505D970CA6C1FB39CBE11:\
+00000000000000000000000000000000
+
+00010000000000000000000000000000:35495878D00360B50D980A6C7B193F2F:\
+00000000000000000000000000000000
+
+00008000000000000000000000000000:81D74A81C7F5A5316314B02C6DB4BAA6:\
+00000000000000000000000000000000
+
+00004000000000000000000000000000:4B0B95251D8737013E01F73B71DBEBFE:\
+00000000000000000000000000000000
+
+00002000000000000000000000000000:8793996649604702198290E258A151DF:\
+00000000000000000000000000000000
+
+00001000000000000000000000000000:99F161837DF7F24E3748C2BBCD71417F:\
+00000000000000000000000000000000
+
+00000800000000000000000000000000:305049B5511EA8FBD5C36AB3E62E59EE:\
+00000000000000000000000000000000
+
+00000400000000000000000000000000:89BF8940DD39B51B35E70F62137AE5EA:\
+00000000000000000000000000000000
+
+00000200000000000000000000000000:301847CD9DA64B1BFD9E781056457761:\
+00000000000000000000000000000000
+
+00000100000000000000000000000000:04B0F6A6C8BE9C4A771701DA1F2BD512:\
+00000000000000000000000000000000
+
+00000080000000000000000000000000:91898CFEE3784B0299A655391057081E:\
+00000000000000000000000000000000
+
+00000040000000000000000000000000:6515031342504BAC93832D74B18DE5F9:\
+00000000000000000000000000000000
+
+00000020000000000000000000000000:D98ED2EEACB67C0FFDDA9724C309DF25:\
+00000000000000000000000000000000
+
+00000010000000000000000000000000:4F963C1680E07CA4DD7C3759F848D2CC:\
+00000000000000000000000000000000
+
+00000008000000000000000000000000:B51D85DC8C8F5A7EA15EFBEDBCBFC9E4:\
+00000000000000000000000000000000
+
+00000004000000000000000000000000:F7C45BC3FA262A837C670776238C767E:\
+00000000000000000000000000000000
+
+00000002000000000000000000000000:5E912791AC2F572389999FD369EC8E37:\
+00000000000000000000000000000000
+
+00000001000000000000000000000000:7E8C9BA80ADC579747B1E4616D7EC9B3:\
+00000000000000000000000000000000
+
+00000000800000000000000000000000:BF99640F187DB0C2944B959050B62F6D:\
+00000000000000000000000000000000
+
+00000000400000000000000000000000:C5E61399609A0BE02A916D48A8A64C63:\
+00000000000000000000000000000000
+
+00000000200000000000000000000000:07B4116F41B82767CB72E2E64CC046E3:\
+00000000000000000000000000000000
+
+00000000100000000000000000000000:AB696B5F4E7ABDFCEC1D2DEDAC05E2A0:\
+00000000000000000000000000000000
+
+00000000080000000000000000000000:50654EE25CF9E493B0B7138EE74BC166:\
+00000000000000000000000000000000
+
+00000000040000000000000000000000:BDA01373F42BFC2B0F723366A46E1FF1:\
+00000000000000000000000000000000
+
+00000000020000000000000000000000:AE25CD3DF7FC7BB8A2E645EBD79D2A29:\
+00000000000000000000000000000000
+
+00000000010000000000000000000000:644664257BFAD3A0CF16D683A026A72A:\
+00000000000000000000000000000000
+
+00000000008000000000000000000000:3AD0281E1F1225280383D5B7A3E90B04:\
+00000000000000000000000000000000
+
+00000000004000000000000000000000:23F2882568F472EBC1B519122823441C:\
+00000000000000000000000000000000
+
+00000000002000000000000000000000:8DE047245D62895A7E5852CEE8379A4F:\
+00000000000000000000000000000000
+
+00000000001000000000000000000000:21ADF95994B6FEC5DA6FC40FEA782D79:\
+00000000000000000000000000000000
+
+00000000000800000000000000000000:F2834B5587D63C382DBC397101EBB64F:\
+00000000000000000000000000000000
+
+00000000000400000000000000000000:884C3D3850DC3EFFEAA0DB8785BEC5E5:\
+00000000000000000000000000000000
+
+00000000000200000000000000000000:71AB2DB59AE3AAF781DAB5CAD1007975:\
+00000000000000000000000000000000
+
+00000000000100000000000000000000:7793380505B20B6CDA1A2CEB6AF6D76D:\
+00000000000000000000000000000000
+
+00000000000080000000000000000000:6A986D4B71CC337450CA165B110414AB:\
+00000000000000000000000000000000
+
+00000000000040000000000000000000:EEC535764784A680C2852BD4B00ED6AC:\
+00000000000000000000000000000000
+
+00000000000020000000000000000000:431A4B03918BD1A65D3523D63C7CBCA9:\
+00000000000000000000000000000000
+
+00000000000010000000000000000000:6E657880D84A51B2241109E82B2A7EEE:\
+00000000000000000000000000000000
+
+00000000000008000000000000000000:B4D163CFD4279B1F9DA0E1FC8616940C:\
+00000000000000000000000000000000
+
+00000000000004000000000000000000:552143C6F2B0A0AB82B2AD487BD74DF4:\
+00000000000000000000000000000000
+
+00000000000002000000000000000000:A8CED7B931A5AD407DDEF7F4510DBA70:\
+00000000000000000000000000000000
+
+00000000000001000000000000000000:55BB234ED4164A9CC028C9C9DADA8A06:\
+00000000000000000000000000000000
+
+00000000000000800000000000000000:0576F9792BA215C89BE0C86D8B3E84B6:\
+00000000000000000000000000000000
+
+00000000000000400000000000000000:C117C7A4AF79DEECC8C18E8138BD4F78:\
+00000000000000000000000000000000
+
+00000000000000200000000000000000:92FC2FDE8E99F5ECF5DFFB2B005C3790:\
+00000000000000000000000000000000
+
+00000000000000100000000000000000:F3C94469F9B4166B76A7DA55FC45EE2B:\
+00000000000000000000000000000000
+
+00000000000000080000000000000000:4C3A60421F79015B99A9B928477CC451:\
+00000000000000000000000000000000
+
+00000000000000040000000000000000:ED6A1AF53574213F41812E8F5D41536B:\
+00000000000000000000000000000000
+
+00000000000000020000000000000000:AF39A2A89D48B0A2F519B39F3DD4A7E9:\
+00000000000000000000000000000000
+
+00000000000000010000000000000000:7F75ED2F965C9ED280CFA16B934E81D9:\
+00000000000000000000000000000000
+
+00000000000000008000000000000000:B92C3EEB72B6BFD288E1F38D64248E93:\
+00000000000000000000000000000000
+
+00000000000000004000000000000000:6FE1E1883D78ADF9FD415265A539D61C:\
+00000000000000000000000000000000
+
+00000000000000002000000000000000:D5ABB34FC2D207FB0F8DF60DA81B9661:\
+00000000000000000000000000000000
+
+00000000000000001000000000000000:751327283356553AF48AB6ED21DCE7C5:\
+00000000000000000000000000000000
+
+00000000000000000800000000000000:B826F4F7B5C5DF743C87EE73119D71FF:\
+00000000000000000000000000000000
+
+00000000000000000400000000000000:ACC2FA1CBD0FA5F8AAF147396AA72EF1:\
+00000000000000000000000000000000
+
+00000000000000000200000000000000:F9F02491D78EA3B140D368CA71F0D6D4:\
+00000000000000000000000000000000
+
+00000000000000000100000000000000:A414990595D6E5E3C657B3190A1AE3C6:\
+00000000000000000000000000000000
+
+00000000000000000080000000000000:478FCFBDB52A6CDA402217483E26604F:\
+00000000000000000000000000000000
+
+00000000000000000040000000000000:DE5E798198E306A2FF47F4F2DB7B3E2F:\
+00000000000000000000000000000000
+
+00000000000000000020000000000000:B42E74D15CA26D9CC358A5E2B1F9DD70:\
+00000000000000000000000000000000
+
+00000000000000000010000000000000:2800BCF67B76D76F7D0070950A85A20C:\
+00000000000000000000000000000000
+
+00000000000000000008000000000000:808F9BE49A31AD5D0A62094A55372D64:\
+00000000000000000000000000000000
+
+00000000000000000004000000000000:DAA7291D3A3289EAD026121F8CE16151:\
+00000000000000000000000000000000
+
+00000000000000000002000000000000:93D7139BC6A67316FFAFEC2ACC89D245:\
+00000000000000000000000000000000
+
+00000000000000000001000000000000:15D1444811E90AD554E50973F32B8AD6:\
+00000000000000000000000000000000
+
+00000000000000000000800000000000:636FF061A2FCA2EAA8DFD3A195E8BA4F:\
+00000000000000000000000000000000
+
+00000000000000000000400000000000:A2FBB57034BCF5E89E1495C216A44917:\
+00000000000000000000000000000000
+
+00000000000000000000200000000000:7B370D533113C91233BBDC73B14B121F:\
+00000000000000000000000000000000
+
+00000000000000000000100000000000:F21BC7D2EB7541EB3F0B40394FA064C7:\
+00000000000000000000000000000000
+
+00000000000000000000080000000000:BAAD725D1BEBC934FEC792D158163DD5:\
+00000000000000000000000000000000
+
+00000000000000000000040000000000:ED50A592E0D2DE126BC97FD8DAD20919:\
+00000000000000000000000000000000
+
+00000000000000000000020000000000:11DB39B92B98A4719FE345FC44082787:\
+00000000000000000000000000000000
+
+00000000000000000000010000000000:43B1AA58C190006D5EA3F6B708B90509:\
+00000000000000000000000000000000
+
+00000000000000000000008000000000:8A19FB44B5962288640F48B27286904A:\
+00000000000000000000000000000000
+
+00000000000000000000004000000000:C19B0558E72BABB1B9275EE8B48B9017:\
+00000000000000000000000000000000
+
+00000000000000000000002000000000:587D8A04B1958388D69F26E4106D8232:\
+00000000000000000000000000000000
+
+00000000000000000000001000000000:B53EB6177E1BC1C083E743878F476003:\
+00000000000000000000000000000000
+
+00000000000000000000000800000000:A42E251AF82C03E4ADB9E5872AD8F7B2:\
+00000000000000000000000000000000
+
+00000000000000000000000400000000:E2585AE29C6054CBDA85B6AA00D88C90:\
+00000000000000000000000000000000
+
+00000000000000000000000200000000:3F6364A00BDCF925C6D62BA15DF56234:\
+00000000000000000000000000000000
+
+00000000000000000000000100000000:6ECB0E56F218E4D1E790C34BBBCA06B8:\
+00000000000000000000000000000000
+
+00000000000000000000000080000000:02ACC5470DD8D223ECB12339750D3BC0:\
+00000000000000000000000000000000
+
+00000000000000000000000040000000:D67A590C0AB3B3E47406D19DB9F0A21F:\
+00000000000000000000000000000000
+
+00000000000000000000000020000000:2B5CF7D06148DF6448016FB40FBF9F53:\
+00000000000000000000000000000000
+
+00000000000000000000000010000000:4D635C044E9ACA243BA1F68268789D41:\
+00000000000000000000000000000000
+
+00000000000000000000000008000000:0118FE9B311429CC06F01AA150D1FF08:\
+00000000000000000000000000000000
+
+00000000000000000000000004000000:1E8AB1853E0D2F0E9FD49FE5285611AD:\
+00000000000000000000000000000000
+
+00000000000000000000000002000000:E521BDB90371FAEC980E1EAC85C10137:\
+00000000000000000000000000000000
+
+00000000000000000000000001000000:E2B8BB4A2EDF3DA04F6934EEF903DF17:\
+00000000000000000000000000000000
+
+00000000000000000000000000800000:75528623E760DD71612DA5F9374EC616:\
+00000000000000000000000000000000
+
+00000000000000000000000000400000:1FCEBEA2DDEDF905D645E1A03E2584EF:\
+00000000000000000000000000000000
+
+00000000000000000000000000200000:4AC71EB7EBDA9AD47531FCAB0D34FA5A:\
+00000000000000000000000000000000
+
+00000000000000000000000000100000:0458B8910A076F39CAAE517F5E3E4D59:\
+00000000000000000000000000000000
+
+00000000000000000000000000080000:F5D01E6C7FA961F6AA1B94FFBFA59672:\
+00000000000000000000000000000000
+
+00000000000000000000000000040000:652473292C5C5764658F8E1FF91B21F8:\
+00000000000000000000000000000000
+
+00000000000000000000000000020000:05D5357FD61285F1B9FC19EB2BBF01C8:\
+00000000000000000000000000000000
+
+00000000000000000000000000010000:2D379505C15DD6C1AD7544CB375720E1:\
+00000000000000000000000000000000
+
+00000000000000000000000000008000:D5918DFA1A722206C89E7B5D518BB28D:\
+00000000000000000000000000000000
+
+00000000000000000000000000004000:30C3BBEC945657A6EC5B9222BC36DB0B:\
+00000000000000000000000000000000
+
+00000000000000000000000000002000:041305F2248F1FD0EC6181B4D6B619D3:\
+00000000000000000000000000000000
+
+00000000000000000000000000001000:C275B6410A77513E4F33C21F9BC11924:\
+00000000000000000000000000000000
+
+00000000000000000000000000000800:EECA71E0036A80BBAAAE62400EA1A237:\
+00000000000000000000000000000000
+
+00000000000000000000000000000400:1025F24952D1691730DAD7CAF09C32C0:\
+00000000000000000000000000000000
+
+00000000000000000000000000000200:FB7830146AC03E32BE6D03A4AE839E97:\
+00000000000000000000000000000000
+
+00000000000000000000000000000100:A91E3D5B9DDC4F0315E718B4C190CBA9:\
+00000000000000000000000000000000
+
+00000000000000000000000000000080:79FBBF61CB27651FBA333B9FFAF60F31:\
+00000000000000000000000000000000
+
+00000000000000000000000000000040:FF598CBF22746883F86DAD6D679DC85E:\
+00000000000000000000000000000000
+
+00000000000000000000000000000020:FA0ED9A5406FC13E532FDB74988A9554:\
+00000000000000000000000000000000
+
+00000000000000000000000000000010:36DEA77F6832D3C81776801AFF839069:\
+00000000000000000000000000000000
+
+00000000000000000000000000000008:262855946EE434D4F0DF924BAB0311BE:\
+00000000000000000000000000000000
+
+00000000000000000000000000000004:01FF81B0107BEFA8427260954C7CD50C:\
+00000000000000000000000000000000
+
+00000000000000000000000000000002:61DF2C54CDF545F8E774D50C8FF59752:\
+00000000000000000000000000000000
+
+00000000000000000000000000000001:45F21B1FD1099CB36C64435337BAB3E3:\
+00000000000000000000000000000000
+
+80000000000000000000000000000000:4433FCCBF2D4AA14783835D0968BB7A6:\
+000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:D565448D0753F08C6108B10CCEB4F213:\
+000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:1F2B7678DB0B0C33F2F5531FCB71D97E:\
+000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:8025160E9E0DF83CAC559816D3BA4AEA:\
+000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:A0F5D4524C743641214BD088EE9A4A0F:\
+000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:A2981925C529529B068FC1109A509836:\
+000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:AF60EDCB3C0FE50E4FE093509C1A87F6:\
+000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:6F475AF136CC10485515C95773A74AD2:\
+000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:6E09A8F5626CE2364668F8254F192E5A:\
+000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:5DE55C749F91D9392A87CA423F00FF95:\
+000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:4CD217660FCE3BD43999AC8353503118:\
+000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:94B45B0665BCB3FC486CFD980546E934:\
+000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:F924999F0213FE2DE932D1D072FBD38B:\
+000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:B64F96119ED3F9FD37A826E7A48C4F94:\
+000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:63E59879D0A422CD030E51727F379CC0:\
+000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:62B160854BBA6DB3EB960EDF53A60663:\
+000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:39A8147579540CC5A1F32F87768A4E3B:\
+000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:1B201066BC1D0173089BD0346C57630C:\
+000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:2818D6897E7AF26CF08409C1BBCDA8FC:\
+000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:8BCE5EE56402A19BB29979A05AB3EFF8:\
+000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:4F8B1F65E7CE872E514B53BE8DE8759A:\
+000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:3145B8EBF046F533D5378BBDF9C9E4F8:\
+000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:49E18ADC2929D19B61389C698DCEE532:\
+000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:BC7C0A8FDBEB8B63608F0BEF9C1E396F:\
+000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:89F15AD40BB43B2284B3563F2C974023:\
+000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:BB60A7897D5F438651EE13C02B5AA790:\
+000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:946FB4349CE2935BE1CCE99A2A01A6C9:\
+000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:90EA5937B4E393E34B4E60C787B33E2F:\
+000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:C5884097BC796E63B3046CB031919D15:\
+000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:06DC71C7CB99EF0B2EA4379CE5451E81:\
+000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:8A85BC61EAF50F065CB769B48243E51B:\
+000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:482E708D7AAA9637674AE923E2128BB5:\
+000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:1977127839A3FD886B5ACF2753A28D9F:\
+000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:39A993ED3ED7F4A1557FF18ADFE55CCD:\
+000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:8995CF677F032B100EF2FBA632AA4D67:\
+000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:B54C94BC29029F9DC78BAE0908B543C9:\
+000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:CD0A7D015E352D8B27687ED66B45C64D:\
+000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:F4E89BBAAA6DCB96952662F88DB0A60D:\
+000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:37FA1912B2636F3982A768C5208267B3:\
+000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:C5F27B0B8B93C4F693510EDAB0560073:\
+000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:EAD47638DF1D0AB1D3441D5B77A7459D:\
+000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:A9198F0441AAA6B84DB891AF859145E0:\
+000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:99604EEF14A27550AA1F58510BC6C745:\
+000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:133CE0B0F01E22DB16B51F6074A570E0:\
+000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:6E2503C056B37957BC00249175B6A829:\
+000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:8076A054B269283F5063CF9EDAFF721E:\
+000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:6ADC87C1A40ABF8DA9FF4DA863C4AAA1:\
+000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:676953B542456DDD155467F7F6E51C2A:\
+000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:441D72C0FB4A79E4451B9B0D3571E1E4:\
+000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:642DC2A4A84229406ADFE681FD1D2F51:\
+000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:CA1DF7DBF4163F601ED11216767E8C79:\
+000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:F8EBCE557E084052E74A5DEB45439D6A:\
+000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:589606504D2BBC4A85507D61AD1AE6E1:\
+000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:5627DFEFE159A8FEF32FDC29321CC705:\
+000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:BFC074B43DD81ED778082FB83AAB8D8D:\
+000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:6DF74B1434C13343CAE51F38BABDF4BF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:1C9B11549C831CE68C7CE061F1CCFCEE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:31D07F177D35A6EE067C75C5B1F3D728:\
+000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:D4B7FA191B9414FF3D293BC76C2E12A6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:9D7AA5550DAE2B1B7D608147009DFE2B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:5266FA9AB29440558FB71EDA1B43BFBA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:2CF722D01CB1EAE802C78FB22AF095B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:B3C02698C56AB6D3EFCB90AC81CBD787:\
+000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:FBF4F2DC7FD1A9F6D4C8B8BFA3AA81FB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:32D300D0B845E26F7A0505AAB453E0B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:EAA724538478C450FE5E893DFD206D5B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:346E15BA10E1B15D2DE2A862C8BAB645:\
+000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:67E87A345284D00742FF8E0D6C67C677:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:D9FF605AF934D4EA36BB4D4678D250A5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:C6BAAD911C8D06461FEB1C8FD73A1163:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:AFE155824F95065479A7326AF6FFAD5C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:DAFA519AB33BC01A665BD43D7B578716:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:AB1A3C2AEA2AB0873FCE9B193AC3CE26:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:DB4E325C5F0C6A2A80A97FB53629CA42:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:AA0B63CE9363BCDC1840FE6DF3EEF598:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:564F6ED396958B6CD1C5156F30F12BD3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:59CAEE5DD9D6D8A17DCD5761F285ACCD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:4CAC1BC4EBF467854A15DDBC9410E30E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:9D432A8BC205B2DAE6ED10E5D2573DB5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:A1B2A6D98E8331CA5D2605C5053AE8D8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:CD3676661A44F4509EFBFFB4ED5AD60D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:0E367EE025F2FF821D5F0B89FCECFFA9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:5F60D9B6A93F1F1B531A9D26C7465114:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:E5753FFD3DF072BCD07292484E9AF749:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:25F43090C51DFE3C48DB6F391B489669:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:AE817F28DEE664D2B9739BF93AA73B1E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:F1D08CAFE3F5E56C18237E777C731DDD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:6ECFB7B90D05650F97B5D6D7F677ECE9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:FEA1BF5FD0BCFA04E0D906B4C5F8C51A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:0739D17249C17E813B7716212E4E32F3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:81AA866868D538D53194B5B5D7014BD0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:E3CC87289C585148267231499BADA0F0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:2016EF8808F2B5C38B0F790C5A81E9F7:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:7F06EC5E639B36CD7482E5D3568DD54E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:9A066E0A89EDFF5F26F00F8CC76710B7:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:49A6ED8109D54E6628CD4F6418B788D4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:4C3F149C3D7A196B8F61AFF5691950FB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:85B54F82B4586B3396C2200DFF3B26CC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:705B756847815F1D0DA8D55A45F91BF5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:4C81CA819469B5A80EB6AF78BB91570D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:5D057D02E17129A43E0B68D9425917CA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:E472655E64E637CCD7D1FD3D46970F34:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:05B3391A2CABBED3F1AE0EBAEF6D61B3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:96D1DAD8F5083314D8185517614E2E3B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:B4054DBFE0DB6487C90505273A5FF3B1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:4E766330F2C22059E59B5C8972AA2AFC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:78AB8FC7997E2B63B59DC80F4F560D95:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:059181B7493B3D66B61CC663B58D7860:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:4149CD202F19C2BBF631FC2BA8FFDF41:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:6465A8757C3E9E5D9A98EEF1CEE37324:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:06A7F1D391336FFBEA9986A82BAFFD02:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:6204BFF718C247F7A909C4FD4CB6444D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:4B815F5F654E7C6E9B135D14773BF419:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:D18FBE3FAACC1722641E66DB74220E98:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:6E473DD470E74E9066FE07297434D8A4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:E6FD048EB622EE77A092E1818472C477:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:2DCD5664A1151BF563F25E86B69767E4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:3455215DFA380B77C931C262A38B01EE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:7470C0914B4AA37DB90DCDD87A253D94:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:CB15F18A9A66397EAC67FAC2BA875EE5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:5F273D6F25D09AFE351CE02016E18218:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:CA995621063500658C47AAD5C89BE0FE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:70724F68B3D09917AB7286449BCC71F3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:10769D43746A1DBFB7CEEDD1EB9EBB0E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:87F113ABDF184062224235392A20AF11:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:7D237E25D34FEC04FC635884B1342EC3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:435B4DA29136AAA1275EF16F5394A235:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:70051777D259550440C9BB7884DFFBFA:\
+000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:7DEC45D013733A2FC3ACB05AC5EDCDA0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:A0CEAF180B51BFD4781D46CD10160457:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:498CEEDE242280926B1583FB4A2F9073:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:39E60B423F54786849C6E0BA2AF6BDD3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:CA6680EA57E0FE1628DC26EA79C948EA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:CA14A0AF4CF3D1C3615204EB95F216CC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:2D5A5029679E795D4F49CF1E7AA525FF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:5AAD27C9EABDAAD2296718BB0118871E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:80CA60282018A1DD71762D84750EB459:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:E2250B330EC2C407295F2A1BC8B33330:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:210CEBA6B53AC0DE78757CDC785C6A35:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:053FC841A2E3D6037B34CB9C7CCC0CFB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:DED4DA1EFC0FCF248E9DA7885CA54A32:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:BAE5DF7B5CB001EFCB26C5AA2DD2588D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:9DD5C8DC680CC10FAF75B19331ED9FCD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:D348D0D2E64F7C6B3EBC0844EA93A77E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:E3AEE8A29AD4A08D979F08F030650A24:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:272797A77F83C01290E213B511A1659E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:B2E84007CACDA6638F4391ACCC8DD245:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:EAA21531B492A737DDCB7EF2D8D4022A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:0DCF4259CFB5D0DEFA7C1DD26C5AE728:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:1B3596ABDAB6FE10E574A0505AE5EC1F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:0B07CA48F49D189E2E343D83D54784A1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:BB4977183CE7D829F90C1A4A0C0AD921:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:A30AAD2751895E667AF64C24F127EE00:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:1D407E4971F586E8BAFD780411DAB446:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:287E1CBFA05A25B90B94B0D1769DB4BE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:FEEE919F6634BFDEFD6950CA84FE7DDE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:DEBC950100E5BDB2B972D96B110CAAFB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:7E2B207B3204FF65ABD0E286E8FCFD88:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:E46FA1ACDA975397F893DA874257B063:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:48B472378DDB8297A1E70DB24B3B5784:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:51E73F78E9E3DF78C460BD1D1D6F9D02:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:A140D05B56E36B690DE8E5CC7CA2DA96:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:4775063A5B2DB92E0A97A975DFD161AD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:AD6913069340B8B88A42F09975A03E96:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:CE03AA97EC230AF5130F7B49CF11F749:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:CE235004F77A37CA2405AB272AE1F278:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:0207B9546C956A9B96FC6FF8D8B25FF9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:72284643B100DFEDAB7243D372000289:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:2B97D40D51A9C400AC8F72285CB9D947:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:16DEF3EF31FB9E0A9E11FE5DBD10FF6D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:B8C5BEAB5058E1F8F31AC2537DFC2A04:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:96240AFD00164E5BA929C470CC2EDFCD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:8255F69C848F0601DFA944E7DAA07B03:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:31D19233EB697EC50C087C6761658C22:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:0E267CDC580C17C21F207BB6A14A2A61:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:84F60557F8302489621586BC45B52D1D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:C6D5B38F47BB5298C521E41B9B722B44:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:384D3E44D70F9FD1783D7B86DC7C0B79:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:542B27EBC9FA37FA8CECF14E73545CB6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:04B5915863477F621C976F47ED7A6242:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:571E6627E25993D157D7306937A0F62F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:A256299F34E93EBEC69E04CFFF3476A0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:F202A1227405A4CDFC9308819B189FCB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:F99B66FEB8E9FFA89164A8EC1B8F1C85:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:3C70D7CD09111B15069F54809724F1B0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:B88FDCFD41AD34AE92091D31E90C585C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:2A80BE073D50FCF2B7FA44A39F777AE1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:65F620832AD465A2AA6A14129F382DEE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:A4518AD23FA96370D83BD3B2FBAA54C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:22AB117786B312AD84C9C2CAF1E2C2CF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:33C719DCCF25FCF76916B80C632ADD00:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:7D95F59DB32ECC39D00DA9DF113AA2EF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:376278196B5EE68F2B57B51B4D07A849:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:F6EBAD4990425CD9BBF97D5AC51D33DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:2C64F1A0EB9601E7B5A29E9237040E39:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:0D6E4B7D38620761D65CCDDE9EDDB24F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:FB954442EDC07197FAE86E9A0D714903:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:4B2CC93726DEE48282FA27816FEDC5D6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:75EBA30DFEE4BE2CEFAF7D097D08BE4E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:90A9750293D227B3F75839A1B1B72A1D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:EA6A6BADD96680C06A0F3FF72A89A3B9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:027957EFFC5F8D54F5E31DEFA4EA5B1C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:689E796B7CA20D52ABCA6E02DFF2FA19:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:D0894BC5EC6BB6548C2DEF7D271C5A84:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:B3AD04752FE8B3CED3BC0C721CFFA017:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:75EBEAA918EE7713AB6B555911A8895B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:4507EAC65B6F8825147535212B810659:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:488887A888AD9C4208981298C32C8802:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:8516A2448258784F9CE88A4DF07E12BB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:34C35EAEF661E815B02FAE1D82A5C6FC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:88927ABABC4DCDBE547729DC8486C912:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:E3F2B4AD45A40E8F61A1A002EBB1A6B4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:7B8C8A12DFFF1B31E9BBBC9AB1BF191E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:12896559E9F9818A45895A850949641F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:0ABC2B5B0BE224FCC494D1EF9930663E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:1975B8F3DBFEF1B3F68150526EFDFD9A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:531360071C6EDFCE4194DD34F282687A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:D7D44699A83FAA21673C244155E57276:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:1AECF6542049C8ADAE288158FAB8797B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:EB40D7F5FADCE30126B34463B1FCFB43:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:FEFA8ED45925FD4F51AA06EADD1D08CE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:7E36A1A7FC162B85AAC263DCA957F534:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:E5C330087D678D159C00C27CBBDC9F61:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:8F56044BB6E9321DADC1F21A70F1E8C5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:8714D0D553AD80DDCABE3E9DB67CFE11:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:B72D92FFF02A78AC4682ABAF141D77C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:9550FBBFD4A34816E2FD792AC339D49D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:84981AB5DFBE8422A2086D0E5E470254:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:7BD5A92C5957B09FA5AA9F1A34E17943:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:B603FAB9ED51424992A737BBC1E910D6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:2E396DFC0B28E28353C2F97BA982C13D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:D4CC605A1C64E8A98592A8CD05AAFED0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:26C58B071D9116B0123CB99734CFAAF2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:3C9D6B460A2364020F55A70E41B5B2E5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:40569C782ACA0CB05042D0F54967545B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:7340B7EB0B49722A28D0F06056D8878C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:8FA7508A26413C633B77FC418AE0EE80:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:4EA014A1F02840246644548A9C09629D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:B44678D49E3F80D998A94CB542CFBF83:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:756FEB41FE20E403C5C1715AB9D0E58A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:F061519982CD7D2C1451CB2BCA567F21:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:43B291C8A4BBF59612F896EF8DE8C801:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:8512D67DA5F121630DF707E1B87901A3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:1CE9CE4393434F7A0BCD3F4424B95575:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:8DEE20BD926E0AEA8F5163FCF8D594E5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:B504027202FA9A205A36ACFF47E22CB5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:3B88E059888E28B7E61F2602A5361A4D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:264BE9E31092B5F5FAE3C90A8544E036:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:82ED5DDBF256FB53432873A896699723:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:AE8D4DC3B948546E1F0DB6173A7DA5D2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:01CD700F9FAAD9182FADAA2E62B9814C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:000C12107A21E608CFCC1285E1057373:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:3FCD4604A02D1142032433FF551F0F23:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:D049B0BD078583621E4841BC9F53B11F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:BAAEF3F9A301A25EE35FE6D6C054E06C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:5A991DB3C1149C0C16A523B8FC413C8D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+
+
+# First 2 vectors from an expired Internet Draft (which is what I used to
+# implement the code). The rest are from NESSIE.
+[MISTY1]
+0123456789ABCDEF:8B1DA5F56AB3D07C:00112233445566778899AABBCCDDEEFF
+FEDCBA9876543210:04B68240B13BE95D:00112233445566778899AABBCCDDEEFF
+
+0A0A0A0A0A0A0A0A:DAD2CFFB201C00DF:0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A
+0B0B0B0B0B0B0B0B:EBCF435B23CFB4C9:0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+0C0C0C0C0C0C0C0C:92E00981E5350015:0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+0D0D0D0D0D0D0D0D:CD70199048ADB686:0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D
+0E0E0E0E0E0E0E0E:ACAD6C19AE66EB41:0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E
+0F0F0F0F0F0F0F0F:4ECFE751E0E6A16F:0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
+1010101010101010:C7A91953216F1B61:10101010101010101010101010101010
+1111111111111111:0227EB3422109682:11111111111111111111111111111111
+1212121212121212:5B88EB8714B2CE08:12121212121212121212121212121212
+1313131313131313:E325B133AB02C021:13131313131313131313131313131313
+1414141414141414:93A4074EE9C38AE3:14141414141414141414141414141414
+1515151515151515:15AB85B70F337868:15151515151515151515151515151515
+1616161616161616:7EFD6E05D384512F:16161616161616161616161616161616
+1717171717171717:C1E46E7B54BAD271:17171717171717171717171717171717
+1818181818181818:956504E0F372D380:18181818181818181818181818181818
+1919191919191919:667C8BB548330E81:19191919191919191919191919191919
+1A1A1A1A1A1A1A1A:1F8787DF7582DCD0:1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A
+1B1B1B1B1B1B1B1B:47F4EAF5BA82C610:1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+1C1C1C1C1C1C1C1C:0F772431C6E54F3C:1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
+1D1D1D1D1D1D1D1D:51CF4361B3EF3EAC:1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D
+1E1E1E1E1E1E1E1E:7AC52498328C66BE:1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E
+1F1F1F1F1F1F1F1F:9C4E0F782BBBD830:1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F
+
+8181818181818181:2FFAF44121E4F834:81818181818181818181818181818181
+8282828282828282:4EED79D6916AA112:82828282828282828282828282828282
+8383838383838383:12B62B3C7FCAA24B:83838383838383838383838383838383
+8484848484848484:F7FAF70C7E4ED8B7:84848484848484848484848484848484
+8585858585858585:C58EC8FEE9DD45CF:85858585858585858585858585858585
+8686868686868686:A6159BD7C1E24B82:86868686868686868686868686868686
+
+FFFFFFFFFFFFFFFF:651F3092AFA551D0:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+[Noekeon]
+# From the Nessie reference code
+00000000000000000000000000000000:BA6933819299C71699A99F08F678178B:\
+00000000000000000000000000000000
+
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:52F88A7B283C1F7BDF7B6FAA5011C7D8:\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+52F88A7B283C1F7BDF7B6FAA5011C7D8:5096F2BFC82AE6E2D9495515C277FA70:\
+BA6933819299C71699A99F08F678178B
+
+[RC2]
+# First three came from RFC 2268, the rest were randomly generated by OpenSSL
+FFFFFFFFFFFFFFFF:278B27E42E2F0D49:FFFFFFFFFFFFFFFF
+1000000000000001:30649EDF9BE7D2C2:3000000000000000
+0000000000000000:2269552AB0F85CA6:88BCA90E90875A7F0F79C384627BAFB2
+
+D8886B78E580404D:90748F6F07EF2836:1D
+FE9C2CDD8C027870:EC184E6CEC40D9F5:5049
+A7E13BC9F22C595B:67A28EB51250764E:C4F82F
+7177755D3F54A920:62A6F69BFE164A05:9190277A
+D9DCB373FD4ABCB3:B80190D7B249614B:481B0F86EA
+4B138DDE007975AD:7FD56A6AA67F6C83:499825B0D117
+971F30AF097B7350:5DFC9E205A2D14B8:4920D4274A62EA
+F95DCF9157489637:4AC1643B949984EA:405F1C56CEFE4013
+1026140C4E7301D1:283EB71029EDE89A:AD6AF2DC8463BAB7C6
+36773B9B092E5FB1:FE60654754ADA82B:3BB04A71CB0D23A7DFCB
+CBB90C2F7F42158C:30CFDEFED10675CC:0A6CC3F130AFD069222EEC
+B07CDC0A13DD350A:3B050F6208CC43CE:6A9DB0629A46CA98E9F99450
+C0B69D0AD97D154E:BBA1918C34881835:200BCA0DCF0497C3DBF9A025D8
+649B5F71F3B3BDBA:349369793550565D:7C5DD0AC485AD056C57F4B15ABE7
+30B3ED77DBECDF2F:25174AD01E0BE2BC:65D6250D40CEDA1CB7A3CE29414ED4
+E5D64497786FB2D7:BAE8FA177F46151C:56B594BB2938E08B9504D189AD39EADB
+2009AF9845F4D0E1:4508CBDEAC304883:48E5FB1C74186717F17C9B7EA8F40827
+8D7BF299E1DD2710:D5C504FF23ADE3A2:2E7C56B9A41B512817B702615EBA38A0
+66E588E1E54E69FA:FB599477D9EF7C14:68229077C5E04998A73CAC26265BC454
+3526264FB3AAD439:789C2F4906D4DD94:B2851A27F152B3B8D21FE19FE080DE93
+51F9D8B75E99850A:992215897C1C4D4E:A63FACCE8ED417ADDBE36262E334C934
+7643ADF384C7D876:280FBCA90127A9B7:68A2CD033B11F329BBF0E952FBDDADEF
+61649CC1BB265F04:C04617D4C7F4688B:6562CAA391B7AD91F6F953860C142D53
+7027B6111FE67F27:526E8225707ED477:97FF0C4C1D58254DE89140EECFF8A15B
+450500AFA05B83ED:5E55E20A0D0E3226:FDA85236CFEEFF046973CF46C182B41C
+51E3A05332220E12:05B42A4CC45321EB:2F1810D1FCFC98C847DA1D21BCA75712
+
+# Again, test vectors courtesy of our friends OpenSSL and /dev/urandom.
+# Except the first few; I think they're from RFC 2040
+[RC5(12)]
+0000000000000000:21A5DBEE154B8F6D:00000000000000000000000000000000
+21A5DBEE154B8F6D:F7C013AC5B2B8952:915F4619BE41B2516355A50110A9CE91
+F7C013AC5B2B8952:2F42B3B70369FC92:783348E75AEB0F2FD7B169BB8DC16787
+2F42B3B70369FC92:65C178B284D197CC:DC49DB1375A5584F6485B413B5F12BAF
+65C178B284D197CC:EB44E415DA319824:5269F149D41BA0152497574D7F153125
+
+9E1916F381491CCE:172A7A0BA70282E9:C0
+B97800C223082F9F:B5B1708AF59CCAD4:DBEC
+F39054061481EB24:64CC1E0066FCA2AA:DA735B
+7622BA5D3D51D560:FFCB9EA21917C3DE:0656F579
+A15418BC11B2F0E1:B52821179E5CB9B9:A59FB3DA35
+73B02BE42685EA56:308C21EFE81621EA:32594FCCFFEE
+8CD5121F09DB7DFA:70921F59F5CD29AD:80E92B27999910
+532955C8EEBC75CF:CBFBB1E0A1A693F2:925498B73A9CAED6
+BC8B5CF722EEBCAC:F233FBDDC09D9561:3C379D8B11F23CC0F9
+EFABA1B87E0236FE:A573453E1BF7B74B:AED34B49E719D6157F93
+5248601C102C10C0:D96D76C05F5E4478:729B301AFAAB8FCADBEE25
+EF6671A5A29EDEF8:9EC6407003B827B1:982644C13B1AA070437C1144
+5EF9939F903D5AD3:8D9D5B5D12448231:3BADA3BBA56BF23EF64E0D208B
+FEF8CD62F9DC8D1E:8FAF5F9D6A4A0A7B:BDD77CE81D8AF0B50ABE418F45F7
+C330D9BDC20D794D:0F74E03240C58D70:4AB4A9A4A31B700ECCB0FF23441F82
+502E1C61223F5522:86CC15281600FA7D:3668476363B42815FF575A65006DAC49
+62ECF065C5723856:5F8E3E9341B32B71:AEE7D59BFFC7FD4A2932C937C7277A2830
+CF8DDCB5035B3CC1:2D688A1A2A8DCA18:3A1CCFABC9F8C46F96FB8B58D02A1F9EC514
+D595EBBAFE479CCC:8AE450DB2A9A7C37:834BC680E250D2A3B5B2D5B03FF14F2F65E412
+9F24230CB25BC86E:EE922AA0AC2EB904:39A787D483A6E52FAEF9FBD2EC3CDF81A39495DA
+EE68DE3FEEC31750:E71038E4AB9F475F:DD7ECA8D1145431F60F2B749FB576F82011BB65005
+9464C68A5E6FCE5C:54534C495295FEE4:51FEB601EDA05F5D3D903FA957E6E06B81E640E6DFBE
+A91EACB2C38F78EC:997EBFE794F83F65:\
+0EF8C830DDE1838F1554195CAE006E69DD050C255B17FC
+170D65C9396BFAE0:3B21E9B59F37FF96:\
+5C47BF0F8E6D0E7A445188E361E4A76A9C48CD9738791293
+D5961EA7B7C02063:15C33DA775B4154B:\
+44822C91949958ADAF7E938395113A4BCE343D39C30B3CBE70
+2C9A50C06A12E865:F060DD9CDBEA5738:\
+284FE5889A02AC1C83F9D1C62AC15AEAA08532EB478447B7A599
+780A3BD50CF78B15:D263CFB83966D499:\
+37F29AA9FDF4758489AD07C168965A73DB335049BDE60400BC19A7
+39EBCCE8CD770C35:BF040B7D806BEDA5:\
+8ED81E58E34274D0B72318A14812D1E50D117437B1F303AC72F75057
+E823EB34847F1551:489177CA2F6E7189:\
+AE591161BDC88AD08FF582EBEDB93A172C235E08E244AACA2F433CF1A5
+3C4DB181401E588C:E2CCD84073236831:\
+D1464349DB7C4D43777B3A44B4DC611C1F4DCCEF296D7A6E38443C773D60
+128787704DDA4240:6BE471CF49A4C1CE:\
+1234D3D3AFB98F7D24D63E3A829D7EBA96A16B516638B79F59F38FD6C75766
+28FE4812E9137CFB:18B5499EF0C1F9B4:\
+FAC10D2B235098D973E8E81997EC9189197DAFE989E4B3A18E6D3C0150BF48CE
+725F91D74F3F3C66:F398FC47F4FEA520:\
+4780C11A3CD65D21435AAEC988609495A4DEF6C8FFF6AAE1B26C70BC6C336F73
+
+4C706FD69646BA98:5B9A776AEAD6304A:\
+ED7E67F4D658C34693F0962687DB46628587EA2D35DB81C1129F00FA69833E1B
+3361F4771047397D:DED25E1BD3872DD0:\
+5DB32571B70E3A66FEAD8ACC3F0C4F3A2A6E41A8ACF3D94E73EA0F91176FC3DB
+D840360511EB9840:D95E6398EC528F68:\
+674C6060F45869214A7AA9BF0FA8F54AFCA92D06A0366EA8C4FEF4C8E79A53CB
+DBBC3D4D45847930:74A00B919BE23D16:\
+FB0A5141B81EDEAC27DEA6D4789083AA487B7D830E0041E1E2D167A1355BD858
+5FF081C8F197D3ED:48305C0741ECBED9:\
+291FF645CA077953ECE2EF2AE8EA10A127E6D2A1DF4582A5A7B513227C8294C8
+30B8BAE80C26B18D:57F443D4060FAC4D:\
+A967EC9902F212F1D2D6645AB7C81F0DD1BF4439C131AABD7B8233836615F9F4
+E75EBB4AA43E6C45:A29B91450C2A637E:\
+0A30C331D6015E8A0F64E33994263741D996435CFBA3253CBD64B03A5E000310
+B53DD82028EBB35E:39718235AC88956E:\
+1B5E8C38D611847842ACE7CB7CCEDDF152F5043141B462E4704E729C57404D1D
+
+# All random OpenSSL-generated vectors; not one is in any way official. :)
+[RC5(16)]
+1CA702F26A04AF21:8105DD6EDD4051FB:2B
+78195A51EF592AFF:89055B0265E67032:0957
+5BB2A022E7EDCCBF:94AD2F68A2D3E83C:698855
+3B8B7A2F20DA627F:CB4B25A4A493287F:F62251DF
+C450CB97E69F2E94:77644E7454A72221:CB8CE363E0
+B7057F70F43A993B:E411E3023FCA87FC:1FE3BBD63969
+BE9976C68D70D0AA:FDBA816DB72A874C:F9EACED56552BD
+6D340411F05E3B31:F58D02EEB481AFB6:BB0C6E15883513C7
+B3844D3B7CAF9F3D:21133B09AABC3C07:3312EEB8E2B619738A
+2FBA65761241EAD7:99D16F970CF37B73:9CD7B7EAA3C7C0F2A962
+8B1DC2A2D8E02FC3:4643C45523471F25:347469C239C728FC135965
+A372047B4271030F:731303538F359918:3001E738EC0D082C1A80D84F
+4E666F689DB1FF6E:AE11B65FD7E4AB67:7BFF831DE2C51FD9426AB7424A
+5D440679051B3A6D:2B4BE8A815F9A35D:3DADAB349343D1CFA3009B49ABE1
+E461164D61914F95:32CF5B9FC95C48CA:D967EE11872B8C04EE0C4BCEE700EB
+4AB29FEF7BB5FC5C:2518AA1C85B4600C:32F94338D7D70B4A5537FAEE03730745
+53D49E42AB3AC1FC:02419E4BFDBF550E:1D158F49A2D6878739C61FE6D2E37C11E9
+F99F9DD38CED0DB1:58E4BD6BBAE8565B:95EC4B43FC098B966E151F1B94EDC28D846A
+4263C4FE2AB9B990:D267474CE38E6E9C:414326FF6F61C54E2932B56ABADB2496DEBB80
+375AEE48D204DEED:61600764332D10C0:B99CA2E96FB0C85A8633010AA6EC8C3DC6CC0EF8
+02B884BC12569B3F:86B0ED3E4CB4759F:1C4C076CA04C611316AA5D71659F163428479D929B
+8AF5B9C53FDAE8B2:37091EFCD093D1D6:EA42742CF00A91F7CD9C63650EF450D20E34732A420C
+9C42CAEEA47E2A06:BC1D42AFBE2CB8E5:\
+BEBE3CB5B711C83E150F2DA7A864AE63CF336D9E0EE282
+DD4B4CABDD5D5E35:31076D5D6EA4DE13:\
+3A0603293C5F5A1CCF9DB9337DCA010F243B29A6A2EB3455
+597699EDD1B4DD7D:95FA85725C0AE0DE:\
+00752D67E4E1CCC4ABC7C50B3188181FE664EABF7ED476BC3E
+5E2DEED62635DB75:828E88B5D91A7DB4:\
+23B5163E359A7FE8BBD3704F1EA98B712A15FB6FA6D8BFC3AF0E
+041BBDF41357E288:2FE24A38A1AE4D61:\
+041C609CFA10BAFD30D34D986B762A959146E7DEE3481DF8A8C70D
+E8D46EFBAB44EF65:BA01FBBCF2FE39D6:\
+4CD0194425DF24845BABFB6895BAA18F45C395E8BADC196F36403C30
+0A382E03FB85CFCC:571B98B3E9710D58:\
+7D7CC7017CF9DA5A74E8A7F2D36E5CC016710C43A9CB3C0B9DFB771EED
+A3D86E1D88602802:EBBB0C7614414D7C:\
+CBA9B751F404F861E1DA95FFC2D11C686F84D8508D9A1743E5B9A006DA8B
+017E4B4EFEF05D71:3EE25FA34042CDE6:\
+28967E8AEBD065D3B5ED27158F953512035515ED3B388E2DA336E9705F16D4
+
+9AD01B01AFEA67C0:249B074FC69E1042:\
+3257D40C6B4EBDF8CAEC563CFE94201E1A843B31F2C9B720FC58C8214B7E2C2B
+1EE20108D1089F69:28FA504AB46349D7:\
+4120A9CA90A38A4E16E8323E6B9CB1D2CBA0594253AE578A1A64518B32ABCB20
+306786E25C18C9F0:76A525501E857BE5:\
+246F010FB9F2DDD99412824C602C7FB48C9F6A3B81688A4404E1F5EA21296599
+D0FCF3DC590D5A53:91A9699905107EEA:\
+754D9753401A56E2096D71C30102B885159CF5CE7305D93020ECE035869E0BC7
+83D2C97FFECD78A2:95FE3BD241FE9E5F:\
+534F366548F16D3825EDD61EAD00EF650DDC8E040B7955F68D240691AC34F840
+2D7F3F25DE4C0F05:31BD01CB7BA808E4:\
+3B2CCDDFC5371E5F2FF9E119E0E13B730193E563296865BADA20781A2E0FFE2D
+140AF01EB286A1DE:098B274A3F2D50EA:\
+DED645862D8B88517F26EC729B8538BB6CE46D869E6D568A20DDC4D253E70749
+DB58306587587FFD:20E71B55168E5ACD:\
+D3C38159C3DB49A62E2369BF4BFEAF9EBDAF8E19B6FE9CB579E52C083FF70AB2
+0A55DD3E3A425245:1489079C596FB1BB:\
+2C15C8A0354DCA1FAF296FBF3FD8E64FD7B9C65EF2EA65B6E216943A551A2CFA
+37EC03CAA189CBAE:99FB7B05635AB5AA:\
+8777192F49C195BAACCFF2096964683CFCF0009B2C57477B759F57B1C32C07F9
+
+[RC6]
+# From the RC6 AES submission package
+80000000000000000000000000000000:F71F65E7B80C0C6966FEE607984B5CDF:\
+00000000000000000000000000000000
+
+40000000000000000000000000000000:8CF4A482491CD207289D810C2BB29930:\
+00000000000000000000000000000000
+
+20000000000000000000000000000000:80EF45D42327E3AED39CD45C4E3E6197:\
+00000000000000000000000000000000
+
+10000000000000000000000000000000:F28D8DF12AC0837A0919254980B674F9:\
+00000000000000000000000000000000
+
+08000000000000000000000000000000:9FB984DCBA5B0BDFFCFD97B02B648800:\
+00000000000000000000000000000000
+
+04000000000000000000000000000000:46F7091CD30CCCF570AFC116F8446492:\
+00000000000000000000000000000000
+
+02000000000000000000000000000000:77B517AA59EC7D3381188936BDEACCBD:\
+00000000000000000000000000000000
+
+01000000000000000000000000000000:40D5D97CFFDC390AC35C2734F44CF9FF:\
+00000000000000000000000000000000
+
+00800000000000000000000000000000:B5A6B7C92EFCB55D349B63066AC1E009:\
+00000000000000000000000000000000
+
+00400000000000000000000000000000:152F0F5EA10FAFD0E63494C5FBDCC469:\
+00000000000000000000000000000000
+
+00200000000000000000000000000000:61F669BF2B32CD27CF6278392C988510:\
+00000000000000000000000000000000
+
+00100000000000000000000000000000:53A63CEE35DF00C73577B9255F55C855:\
+00000000000000000000000000000000
+
+00080000000000000000000000000000:6E46B92E23344321A19321DF136CE9C5:\
+00000000000000000000000000000000
+
+00040000000000000000000000000000:22F1261FAB993350F6ED41DA5D69B9B8:\
+00000000000000000000000000000000
+
+00020000000000000000000000000000:0901BC0A1DB5CC87CDA91EF5F5FF46BC:\
+00000000000000000000000000000000
+
+00010000000000000000000000000000:2EE65B377C16BE9517BA12F63189DE64:\
+00000000000000000000000000000000
+
+00008000000000000000000000000000:74BD6FAA83668952E2D546A66B7A8243:\
+00000000000000000000000000000000
+
+00004000000000000000000000000000:08FB4817F040B54E995B722C483C399E:\
+00000000000000000000000000000000
+
+00002000000000000000000000000000:5630614200E248D1644B58E3694D8BA6:\
+00000000000000000000000000000000
+
+00001000000000000000000000000000:659A3A27C9F3B0BBC65FC4C15D19051E:\
+00000000000000000000000000000000
+
+00000800000000000000000000000000:FF3B39DCB459EE4FFAFCAC8C7331A6BE:\
+00000000000000000000000000000000
+
+00000400000000000000000000000000:19F0727A66BD056DCB5541EDE14B4662:\
+00000000000000000000000000000000
+
+00000200000000000000000000000000:D0DE4B5B30A294C8A3838B70387C93B6:\
+00000000000000000000000000000000
+
+00000100000000000000000000000000:37BDB0A854686484E5EB52239D6C16C4:\
+00000000000000000000000000000000
+
+00000080000000000000000000000000:3CC7113F6E6833C9BFB4EE07371488A5:\
+00000000000000000000000000000000
+
+00000040000000000000000000000000:A56737C45AC4DBF2417243C2E3B40133:\
+00000000000000000000000000000000
+
+00000020000000000000000000000000:B0A5C817B1E2C307A4BBF8258DF5F41B:\
+00000000000000000000000000000000
+
+00000010000000000000000000000000:F2112329EFA070476BD515679C887FC6:\
+00000000000000000000000000000000
+
+00000008000000000000000000000000:1AD2023CEC89B9436D03CCB9893C21C2:\
+00000000000000000000000000000000
+
+00000004000000000000000000000000:6BA3E774FCDD02379C6CF2F7BF28B914:\
+00000000000000000000000000000000
+
+00000002000000000000000000000000:A2F8638B0A4014F0641A3CB8A13B5ED9:\
+00000000000000000000000000000000
+
+00000001000000000000000000000000:877FEDF7CACCBF0BD7BB5BB236BA96D5:\
+00000000000000000000000000000000
+
+00000000800000000000000000000000:C9298A9A01C1F276E2E1E04226BF3D5C:\
+00000000000000000000000000000000
+
+00000000400000000000000000000000:4E01DB16789DE364085416DE25871A59:\
+00000000000000000000000000000000
+
+00000000200000000000000000000000:FD3B5DA07D0054DD10FFB79440AB3A00:\
+00000000000000000000000000000000
+
+00000000100000000000000000000000:A2508E8BD26E2FB9944C27F04D60FAA0:\
+00000000000000000000000000000000
+
+00000000080000000000000000000000:E9A43055D71335545A6A514F08B868BB:\
+00000000000000000000000000000000
+
+00000000040000000000000000000000:587D5B71730D0B59BFBC0A93675B32F3:\
+00000000000000000000000000000000
+
+00000000020000000000000000000000:90076413F890E8FFF04F1031C779C91F:\
+00000000000000000000000000000000
+
+00000000010000000000000000000000:FAC9F46E9A1346646EE5C7CED45A84B9:\
+00000000000000000000000000000000
+
+00000000008000000000000000000000:471F0738C4F4937E4253161F28086803:\
+00000000000000000000000000000000
+
+00000000004000000000000000000000:A76F843041C4AED8241850B316D252A3:\
+00000000000000000000000000000000
+
+00000000002000000000000000000000:5C5FD0334332A39924DB0CC7F0867C2E:\
+00000000000000000000000000000000
+
+00000000001000000000000000000000:07B6EDDEF27EE890EBC8FFA187D84438:\
+00000000000000000000000000000000
+
+00000000000800000000000000000000:11BB0F2DC24461F5E70D2830ED8A7463:\
+00000000000000000000000000000000
+
+00000000000400000000000000000000:0AB1A99B63CB8E07290AC60D0A4F1FF3:\
+00000000000000000000000000000000
+
+00000000000200000000000000000000:A26B0AFC4D55E7D61518C54E7C1BED01:\
+00000000000000000000000000000000
+
+00000000000100000000000000000000:50C8C2B68E06CFCB98785E5AD3D5B09D:\
+00000000000000000000000000000000
+
+00000000000080000000000000000000:ACA305D5D0D1E74FC51AC8C92A72FEA7:\
+00000000000000000000000000000000
+
+00000000000040000000000000000000:5AF970E570BC1652C82FB4B0945D5410:\
+00000000000000000000000000000000
+
+00000000000020000000000000000000:00C224433138C1A4BD60571AA35580BC:\
+00000000000000000000000000000000
+
+00000000000010000000000000000000:4EBE79726DAAF4702B075A5898B26075:\
+00000000000000000000000000000000
+
+00000000000008000000000000000000:8109EE81B1679CEC42DB80D9530AD2F6:\
+00000000000000000000000000000000
+
+00000000000004000000000000000000:403B11B8181D460E9AC0172CBE6DD45F:\
+00000000000000000000000000000000
+
+00000000000002000000000000000000:CDE78E92B5A84717AD9B4162E3B14BFA:\
+00000000000000000000000000000000
+
+00000000000001000000000000000000:A173D6BEBAA05EC54A47C7E554415963:\
+00000000000000000000000000000000
+
+00000000000000800000000000000000:EF31AD6CBFA7857ACF0C28294BDEF8B8:\
+00000000000000000000000000000000
+
+00000000000000400000000000000000:209A30C46E41540C7B0AC8C4822DA253:\
+00000000000000000000000000000000
+
+00000000000000200000000000000000:AF770103EC57EBEB913C83D99F58B6AC:\
+00000000000000000000000000000000
+
+00000000000000100000000000000000:17D0C179EF34DE7F8EC7698A5371EC00:\
+00000000000000000000000000000000
+
+00000000000000080000000000000000:E0285A3F97607250CDB89BF92CBD1F41:\
+00000000000000000000000000000000
+
+00000000000000040000000000000000:D76BA3CE5E4DC974D4803ADB9F821A57:\
+00000000000000000000000000000000
+
+00000000000000020000000000000000:B66579D4159CF0B0114011C0298EBDA3:\
+00000000000000000000000000000000
+
+00000000000000010000000000000000:B9761796C787B51852E4C3130B8B662D:\
+00000000000000000000000000000000
+
+00000000000000008000000000000000:D5C638801B97A1C2584ED42132F44109:\
+00000000000000000000000000000000
+
+00000000000000004000000000000000:E54A021B145B7B7761487BCDFD0B032F:\
+00000000000000000000000000000000
+
+00000000000000002000000000000000:3EB3AFE73582EFAB0396108B5E0CDEEC:\
+00000000000000000000000000000000
+
+00000000000000001000000000000000:463E10507A26B708A1DFF3763276F5C9:\
+00000000000000000000000000000000
+
+00000000000000000800000000000000:0EEBF8D85AE19EB24C810CEF565FA77B:\
+00000000000000000000000000000000
+
+00000000000000000400000000000000:86CA894EEFD1CEAAEA70E00CD14645F6:\
+00000000000000000000000000000000
+
+00000000000000000200000000000000:989B0FC1FFE4BA6F7CC0F1EDEEB5B932:\
+00000000000000000000000000000000
+
+00000000000000000100000000000000:42916ED17877E58933D3D8CEDA8DD7B3:\
+00000000000000000000000000000000
+
+00000000000000000080000000000000:88C0369158F2FEFFB4CF14130CE10B3B:\
+00000000000000000000000000000000
+
+00000000000000000040000000000000:DB8976E1DDA56553340236F47F8E9CEF:\
+00000000000000000000000000000000
+
+00000000000000000020000000000000:C6207672C411F088ACAD20814C66254A:\
+00000000000000000000000000000000
+
+00000000000000000010000000000000:A792CF60F44A15D63FB293F9FCF879AC:\
+00000000000000000000000000000000
+
+00000000000000000008000000000000:8F733746F91273D97ADA41D3A7D5A9E3:\
+00000000000000000000000000000000
+
+00000000000000000004000000000000:5DA8F191833E6198689710D5A03EE262:\
+00000000000000000000000000000000
+
+00000000000000000002000000000000:D6DB9CEB7E821F6DF4CB1E99105E07AA:\
+00000000000000000000000000000000
+
+00000000000000000001000000000000:05F308FFAEA3E1E754974435CE0B77C3:\
+00000000000000000000000000000000
+
+00000000000000000000800000000000:73B8639AAD53AFA1B24165E0C9FD397E:\
+00000000000000000000000000000000
+
+00000000000000000000400000000000:AF45FDC65FD5F153E29A8D5032650AAD:\
+00000000000000000000000000000000
+
+00000000000000000000200000000000:A8BB045FB5B867E85FCAD328E13756C9:\
+00000000000000000000000000000000
+
+00000000000000000000100000000000:DD053128C46C78C4414CE3234C16AEB3:\
+00000000000000000000000000000000
+
+00000000000000000000080000000000:B0C82152D1D9E21D7C3F33E1FC9B4D68:\
+00000000000000000000000000000000
+
+00000000000000000000040000000000:11B56480D5C718A77A1BEA30CC3A53CF:\
+00000000000000000000000000000000
+
+00000000000000000000020000000000:92C99F843674DED7F20A258C57253726:\
+00000000000000000000000000000000
+
+00000000000000000000010000000000:63B218D069CE9CAF52EF97614BDACFF9:\
+00000000000000000000000000000000
+
+00000000000000000000008000000000:76096721043A016C095D95DD02980289:\
+00000000000000000000000000000000
+
+00000000000000000000004000000000:87AF16066939B8C4D90E242917DB05CF:\
+00000000000000000000000000000000
+
+00000000000000000000002000000000:F7E0C931B7204308AB5020F106BBA0EF:\
+00000000000000000000000000000000
+
+00000000000000000000001000000000:C697B3602711749580713737729E7049:\
+00000000000000000000000000000000
+
+00000000000000000000000800000000:AF314640B147719EC1B4ABE27CDB58F5:\
+00000000000000000000000000000000
+
+00000000000000000000000400000000:B67DAC5BF73AF7546D2FDC3BC142708D:\
+00000000000000000000000000000000
+
+00000000000000000000000200000000:AC53D20E3C06FF82DE52470BCCE1B283:\
+00000000000000000000000000000000
+
+00000000000000000000000100000000:7D65047AF522F01856FDD83A9AAA147A:\
+00000000000000000000000000000000
+
+00000000000000000000000080000000:709D6454033E3FCF8962CAD39B0DC4BD:\
+00000000000000000000000000000000
+
+00000000000000000000000040000000:7B8058E46789EF51D18700511D20CB70:\
+00000000000000000000000000000000
+
+00000000000000000000000020000000:738088C404D8850041AD6B690CC6B65A:\
+00000000000000000000000000000000
+
+00000000000000000000000010000000:7DFDFD55B53D4CD704F96CF93311AFC4:\
+00000000000000000000000000000000
+
+00000000000000000000000008000000:1DBE62C57AF741D9F2FBF9A340E772C9:\
+00000000000000000000000000000000
+
+00000000000000000000000004000000:E7349BAB7CB458736436943DB0CC411D:\
+00000000000000000000000000000000
+
+00000000000000000000000002000000:64E229BF2AF893510358CB0DBEF7E97F:\
+00000000000000000000000000000000
+
+00000000000000000000000001000000:4C632CF8C75AD0DDE8316A7B35F871CC:\
+00000000000000000000000000000000
+
+00000000000000000000000000800000:2517115CB13E681F0EEA2206C26AD5C4:\
+00000000000000000000000000000000
+
+00000000000000000000000000400000:8ED5E9D7005D980B078E7F58B47E591E:\
+00000000000000000000000000000000
+
+00000000000000000000000000200000:8DBCD253443534B2B8BC698A03166ABE:\
+00000000000000000000000000000000
+
+00000000000000000000000000100000:02F34EAB6CC1DBC8809F3D0EB80FA493:\
+00000000000000000000000000000000
+
+00000000000000000000000000080000:47E5B71162F75B84D7A699A31FFA29DE:\
+00000000000000000000000000000000
+
+00000000000000000000000000040000:B6C1EA2B410D1704058E905EB967C503:\
+00000000000000000000000000000000
+
+00000000000000000000000000020000:4383238CE44E30ECDFC90A70EA4C9E96:\
+00000000000000000000000000000000
+
+00000000000000000000000000010000:9314DFBB44D530768B159DAABCBD439F:\
+00000000000000000000000000000000
+
+00000000000000000000000000008000:12D7C80912C299C4F668278FA494D580:\
+00000000000000000000000000000000
+
+00000000000000000000000000004000:49FB1EACCA3B1743E15014010E9963DF:\
+00000000000000000000000000000000
+
+00000000000000000000000000002000:0DF48D3B128AA63496DBE0CD11083495:\
+00000000000000000000000000000000
+
+00000000000000000000000000001000:13240392854D6290A4BE08999843105B:\
+00000000000000000000000000000000
+
+00000000000000000000000000000800:3D4B8705340C3225CE5A724917BA92B4:\
+00000000000000000000000000000000
+
+00000000000000000000000000000400:425DCCF406AD46F2F565BBBC72FE234B:\
+00000000000000000000000000000000
+
+00000000000000000000000000000200:88C09509CBB95339726C196E63346418:\
+00000000000000000000000000000000
+
+00000000000000000000000000000100:90724430636A3DB610F25332BE2FEBE6:\
+00000000000000000000000000000000
+
+00000000000000000000000000000080:044B4FAED3EA17338630E828B9960CA7:\
+00000000000000000000000000000000
+
+00000000000000000000000000000040:4A59243AEB65BAA4F7432498FD87EF62:\
+00000000000000000000000000000000
+
+00000000000000000000000000000020:4324DF8817589D894674B3F311256E9F:\
+00000000000000000000000000000000
+
+00000000000000000000000000000010:0527269F9FA9E9CC01A03CFA59FD3854:\
+00000000000000000000000000000000
+
+00000000000000000000000000000008:96CA56F9EFAA393F521679E0B6ACF231:\
+00000000000000000000000000000000
+
+00000000000000000000000000000004:DA7A328F8A5BF03DD42BC52DEC5C4B15:\
+00000000000000000000000000000000
+
+00000000000000000000000000000002:5FE3D4C46DB294523166AB46208E0711:\
+00000000000000000000000000000000
+
+00000000000000000000000000000001:2519B9240C21C1F980FB722AD8CB793E:\
+00000000000000000000000000000000
+
+80000000000000000000000000000000:A600B72AAC4DFB5271DC45F563FAE428:\
+000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:A7B1D7CBFBAB741B41744FF9100529B4:\
+000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:D9AAAA866BAB0D68AFFC39CF9888B8C6:\
+000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:32B0048A204036E1B45DE285E87E57B8:\
+000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:7267FEE7E04ACEB47C8FCC4096720484:\
+000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:FF0C22F756C2F5EBDC6610F085D74383:\
+000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:A6264FBCB2926C6181AA6F5551244B2F:\
+000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:D3A5B8FB3CBAA98419D394BB4C66B9D7:\
+000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:F9FE5D1BA274021F041023CD9AC20399:\
+000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:7307F7DEBBEFD911B0B590A0667E093D:\
+000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:4D8A3B987A1E66E72B3FFA520DDD57BB:\
+000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:0F444C0A7334947DBCB43D72F897E72F:\
+000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:448F29B848D7CFDA617D8A64AC518B0C:\
+000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:261B4EA7CD31F46C4FBF684395ED7FB8:\
+000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:25FA5AD347C57047749B15B97FE8ABE6:\
+000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:F7E13200EBA3F6E8E9F37B092B907961:\
+000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:9C934B121791B35AFE509A0D5A04BBF2:\
+000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:3C0F9D40F9608091CDFD831DD6D215EA:\
+000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:97D7D2AF2F635D43E536E0A5AA18C61E:\
+000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:1E41EB291C07ECF0908D49A9CBFAB57E:\
+000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:C9CCEB56AF06C494582F2C966EEEFD07:\
+000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:4B21E0D2942CCD21501F698ACA866BD0:\
+000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:BA0DC6ACC50486AD389EF65B5677DE19:\
+000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:EB80DE49F3D5605D9C3CE426EC80FAFD:\
+000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:D6984153BF67512062F876966BD190F3:\
+000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:AC789910F3458D59C5090BE936C6682A:\
+000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:5D64A268407F791DBDAFD0E5C6399A64:\
+000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:2B4F25AC69BA3AD941BBD4E1ECC75E79:\
+000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:FB943544937F3A34DFA0548C0257CE53:\
+000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:125A04339B61FA79FA3757576EC4FAA1:\
+000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:160B88277AC4C81603BD37ECA4FD73DC:\
+000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:4D65B09355F893E26C85E85955767604:\
+000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:1EE56A4AB4811DC3B17401CBAA8F5A15:\
+000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:6214728772DBD2CDA3124BA8BA2ABF38:\
+000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:328B60EDD6FD150934A30100286E07B5:\
+000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:2C976B076409056EA7489C7658BB34B9:\
+000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:D592EBBA861BBCC369DA99F832B0A773:\
+000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:E6F48FB373724153FFFC51758527C6E8:\
+000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:6C397B0BF5992740BD6A787F16BD511C:\
+000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:2CA57FEE77351E747799C8855780C63F:\
+000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:194C42AA377D361BBDF283693171FFDB:\
+000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:61832D4C637CCE219D2FBB36ACF7992E:\
+000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:945D2B20B9FD48F1961D04DBBA1708B5:\
+000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:EC152810AA2771AA5E871949BF12B6F1:\
+000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:E87712941A7EE80510D53509311196B7:\
+000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:776820A0500F2D90D4DF36F50C395674:\
+000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:64958DB0758C1E80FCFCBB9FC6195E6D:\
+000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:37F27D1D918D463B0668A470DE898AB9:\
+000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:AA71549A4B290289C7060D76FF5A20BC:\
+000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:95EF0C6213EB7CF56186D76BFA617174:\
+000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:2F6A4BD794419F9F34CFD0FED825B6CD:\
+000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:882C2B9E19854367479F0EE25D086F4E:\
+000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:D246FD18C625C1846741544EC4CE60B6:\
+000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:9EAF5A8C5673BE9F488D5C7B6521BD8C:\
+000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:9E7A685F738CB391FAE6ED184087630C:\
+000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:5E0AC39E49825B2424C7263AA8824232:\
+000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:0B06C4805E20BC990E601E5610A1BEAD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:78A99615E809CA88F6F6C6E9AFA532FF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:9ACF5CC740AA37663000C89C5F8EE8D8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:35D76EBA8F59CA6A78FC2942AC5F7F43:\
+000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:39AD4C9AE2B4D46EF693303B54B53546:\
+000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:EA0833009C96171EAA2BFDEF50DEE473:\
+000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:868A8E86F525E50D3FF33A094A3AE119:\
+000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:3DBB9A366A2A3A660F027191B3613B95:\
+000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:E4CDE1FC6D811CDC25328CDAC8D0AD2B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:332010FB6E39F82F00DC1FF6B6F8CFE6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:00293BFE5BB3DA2D3652D4E06EE361B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:9BC99B26E0114669EFE218BF014A15AA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:43C358B6DAB480D0EAEB96DCE57E5B85:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:9842333B8E9FCEC35A8779CCCA7D025A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:5A47529DB0D103DCC34D2ADD3A19C53F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:8F705A89D4C6EE7E27A14792EC49B652:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:6D4B9905F05096B23D6C13565588F012:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:23DDD34E8598F013C0559B3312341DBA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:7B5AE9F49ACC68F2FEECB2823C3868A9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:09F8EED21EB8EE33C02B90637EF24E6B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:00A2E8DB0417F61EAABAD6E9BF13E4BC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:CF5DB5AA31599EEDB5A3143E08D23672:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:E09B69B9C0E3365C0EDA54AB3310A5AC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:33650F826366AEC9A09D7D038708737D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:E84A1EE9A00BA66952B24A6E6AD0C002:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:11B1E0969380A0A24E876D6470872796:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:D88FCA95FA29C35FDCD9467715F102D7:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:A78B86EF0E6959C08F70C810AF8E99CD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:A83E4F27E34360C8033CBC304EBBDF0C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:0AA5B4F05A0B42358ABF19F6E55F66D2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:5C2AC2588982E3CCE99994101FC0A21A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:60A3E107674A0B7F7B931C6EC35BC747:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:123D266844DFFF63DA93C4D806325660:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:08170908422DCB46EEB046F3D7E4AE3A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:13754D93DC4807807A9535388553FB47:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:DFA9741DD3883E39FED5716A706A65EC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:CA5C3DCA7BE84DCBE33BF5238EA3F4B0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:6EBEED89B297D6918FA5CEAB7A0E985E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:3F79AB2119DEBCC44675E340C25B7D85:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:A7739DE45E6051EBBDC2F0365859BEE0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:CEA0C2B3C653B7553605BACCFDD62DF8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:7F9742EEE96193CA8981739712F73045:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:F0103101F4EC92C0CB48145FF34CF51F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:55A8A3B02951558F343C160E7F86288D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:3F9206DB4F3083E8F6EEC33CFE2C1BBF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:F012723B2F08A28A5E24BB959FA5EFDD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:1A28919DB3AB4A53D5A0E1E566982DF7:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:E17C960B43B7E926C83DF749C6A5532F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:16DF63CFB77D31CC782C0ED3190136AD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:1643D697AC4075EC6FE609472FA4C678:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:AD76BF6119FFC36369980D3466CF6570:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:554E53F64D99F89A5BAA7FD5B70E0BD1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:BDC10FF10FA5E3A41B096C870666DECB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:6B12E2408646228502972EA7580B05E1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:B9583810806D5A491B2F69FFF2D2A327:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:E8E9F4A50B834DDEF307503AECD8A3BC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:D7F4A1C7F7954E789BD61007866FFA80:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:953D7D0FD6DDD25CA25FA23C9322339F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:CD4E607B4324CEC7372DE19CEA5AEF78:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:9B5C29709E0F0E586383EAB29E884009:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:28B822B70E7430E44182C2BBAED4D88D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:D2325AF7325642138C355BC4ACAF938F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:F4D1A000EC3A370B5A6386355CEE010C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:F9D198D9FDC650AFA72320AD4826506B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:5024595BEB4DAA2239D495BB023757EA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:8A6CDA8F518CA2FB0A860C5567C60104:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:D6D90C40B07164436453E8312A633109:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:3E73330AE10DF1B8B81D9CA72221E192:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:5029AE60BF118AA69E47B235C3551490:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:7299F32614EA0BD98D2375CA643EC47F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:DF4A7B804A4D3A13113529C509F8BAF6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:3EFC3791618B7D832BFA6AE030C09122:\
+000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:30F5C183F6C81A72F39B618B086CC2DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:DB11AFAAB4946101911DF90AFED8AC0D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:1487FC298DBDA9C520CC5851B17D4079:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:2321D38ACCAAEA5DBA682E7BDCE095AB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:C4DB11197AE15CF9DFE7D0F3457EC94C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:1054BFF1A1564172460A0194B57EBE6C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:2340568047F06139D03FE0A3C75CDBF1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:3FA18912A1C05E244663BD9A9B5D4046:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:7220FA3179267839BB03569E43056BE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:C7D49A32A6B93D1323EFD7B99FC0A5F7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:C30D9FFB19F2090109AD40FDAB73176B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:54CA1E1FD38713CD454A07339385739F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:034516E874272A5A325EB9D54831B6F7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:42650A58269E311A3B4F7BC414D1488A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:8D4916888A02DC18E1EE95B005C58E18:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:B192C07FB927170DF62D6C44819BCD6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:973C835241ED02CBE39699AF2FFC150A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:F9630817124B0787237D76697D66341F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:51E98EC760A328E35B8D77289726AFC3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:FC2E80BE856AE38BE0682E8C273616AE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:A440C29E6F4D6C3540D6C8DB6B02DE4F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:E04312CB849684A440114B40C242F1E0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:2186FC5F5947AAF6626DCAAFFFB47829:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:D357AAA0B4548EB23E9CF1B5D33487C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:02239634F2A7CB81D1CACA279659C637:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:2EF92962D2F7D0A4B075992C3F8FA9C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:F197F67C65438532F17DDBE41F87BA17:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:6A9387BE237C03056921A9F85AB7A394:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:5BE801A4767AD211AF20B295E4EB9F72:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:D38007A33C45B295D06FA99660E8C6E4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:C87746C9F5405E9BBBB53D17544AD016:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:142BB703DC8B4E870165F987B94A3D06:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:3C25BD8199CD580D684BD7EC53601EED:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:283CC22E28A7E48B9FB34F5454A1EB92:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:BE6FA799CE3E6BB239EE35FEF2744A14:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:99BF63EEB37E1C7E8686B28A0F13E120:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:01308C588EC24E97B75A1D32F8C3E770:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:F820CB9552F6800049E51037DD238E7B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:BBC26F6098B0F4D2235FC139041EB78F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:836E3B15AA777DEA46606FCC7C2FAB65:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:AAB58970926FE6CFC4017F23FB44C287:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:1DEEF417C2192D50694D1DF67F960E6E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:4E4EA43FAD14AF207C311D98A1DB4B24:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:E0731CEF0FAF7AE36B4FCB9E1AB95488:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:C6FF60796386126058694CAA35BFF163:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:AEA22D742BA1919C43E0A42719B1A9C8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:843793D2EF2427D745B9B35BC0AD0555:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:3C805CED7CBDEF4F896113D95D4BD975:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:5157A8B222432635BEBD29BDAA9C490B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:D7A88C8E82EB2F2BB827E56F33E7B1C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:DA55FBE256EF08F565A70D870B969B27:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:951F6F33FD34701F7C79FC94EFB119CF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:BE2BD92D9F3DBFD3225B7488FFEC09C1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:3C560897DF4AC5F3C33818E2597E90B0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:52C4110C36C90E3A54921B3F1AAB66C0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:9DCED6AECC426A4DFB6B648490A7D002:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:F2631BD62B10761B923DD415ADCCC59B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:2B1E1C0D54367440A122D31058057A42:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:544C870FBF43AB7CFCF114E00B05D974:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:1E8B06D5FDF11BF70AD8F8748F7F6C33:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:582BE6419DB732C646B80E8C8966C7CC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:2AB0AEAAF06EAD0BA24CCDD46BCAC4D2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:32ABA6C20CFFB3D81A4D3288BF4BDFB1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:AB8F8FB0A91662A4E3C54C395BDD6711:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:F154670ADDE837119060F4ECE9D7B636:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:64CE436BCC7AAC1DE95D6CECC28C46C2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:17A6371CFEAD87CBB6A545D9F9973155:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:532AC851EF076F571D6B1C9418D7E2E9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:8CA057121128472C01EF7F6EC39EC63F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:283DF89A06A93492543BCA4D5DB109E9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:2A07389C26321F9F7AF46897D80E3CCF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:1473BBE037060B30273908A495C2F622:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:C937D109334A404B55CEE675092A2D2C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:0CAA09146104F478E231268F03EA4FB9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:7FCA0541DC09F947145B69C93E0E382F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:16739ED42CEF90CA03B686FF13A29A6C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:911BB934A7D6ED03A5AF9DF7A28E8129:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:3974614212BA6A30AC9541B7776CC29B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:8D17F86E8423398AB06E739B112048FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:76A0AC6091D6DAF57C303E02D5AE8F97:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:98C8AD3C3AB0EFB14DF2C96EC4A5923C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:3AF0B1C79917659CF8E5B91D4ED31ED3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:0F6C180C0D449B35A3C7026E513DA0D9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:646F2B75831CA1CB950B5CC79F320F6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:2877CB6CFED0900A25FE65367B8DF5DC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:5122F1C85198E03E269D90BDA811A8AD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:7FEC2A1C88A6E72D22FE71B513B1C34D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:1176120721DC2C20A1ED31F1572ECBB8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:932B4B9980CF29A3EC9B982A2C0215CE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:BFE6D2C8354E83D26AEF557E2AD1C2EF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:FE4C742734F30C62964D5917C5B63723:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:1663275B61F3FACEB365D56D8B51AE33:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:32EB39C865C149CF81E27D8AE0A91BDB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:0229846F9F8150006A27D62E60A762DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:B88BACF0AFFAA2C5CAAC4C7036785A74:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:C61820350B4DAF92077DB18B2563C050:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:D4ABF17AA49B24F71DD5151339951D1B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:D7C632D6C753246A176B659DBCEF61D8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:1F34C055C434A025ADD592A5397D2D35:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:C399CB8A665E35A23F660C2F8C3D8FE9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:09E11B6D984BD70089CB2360448A4B60:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:E243F7445FCCF52878F8B83BE492EABA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:389F39873BDF652BC4F9043E30AD7CE0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:0669295AA4EA970860CF675D6469F765:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:35C5F9A85171DC889BFD5332E6C8E0D7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:E07600A31EA2F2F781EBC12A3DDC936E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:FB4CBEC86740711F59995673EB73ADE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:E572F84C3AEFB9DFCE042B39E68EA160:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:A87AB39149865D45B1E43D35D8C65001:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:4E5215E398BD5D0F7223348581D18158:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:2524BA2E297D0D2B26797441A7CDB01E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:3DCE8EB2F6FBDBB7A33A26FF6485D4AE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:28EC64C3D0C3AA145F21F4067322573B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:EC6E0084F98693A0D3AD1E4790716ACE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:F09BD8B4646FBAC5556B4F0B816B35EB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:9CC8722245E3CD23DF490353DCACC9E0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:C73465C832CC907D4F79035E67F9AE29:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:F311B9CF73CF5A8FAFB9DBEECC67B9E1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:56494DBCF09A6019B1C6CEE3DB0C844B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:0364CB9DAF55D765BC5CCD46B58FA718:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:4DAFE2AAED6E49C98A7B8B979C32E6DB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:2F5BECD180A9449CE7A1ECCCB34057B1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:1C8B0DF1D643B9376B3E40B847850DFD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:674A46D61796154EC5DE8EC7EDA4BD3A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:8F111A48A7C598EFF1CBCB43414A7791:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:CBD9C99FB47C9518151222D6F8B07446:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:D449C5BE9B01257543932AF7B8777F69:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:283D43A1CEA6187A31581D1606BB8B7A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1AD578A02A08162850A15A1552A17AD4:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:912E9CF1473035A8443A82495C0730D3:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:3D3E851A80ABAF221761931747473048:\
+20000000000000000000000000000000
+
+00000000000000000000000000000000:96CFC0510819EEB7FCDF2CC7BEABEF77:\
+10000000000000000000000000000000
+
+00000000000000000000000000000000:FB787268EC3C583A3685973B861AEF8D:\
+08000000000000000000000000000000
+
+00000000000000000000000000000000:2AE927525C73250D954B619EDAC718BE:\
+04000000000000000000000000000000
+
+00000000000000000000000000000000:00298D1DB6C6DA02E28E49C63B4A5795:\
+02000000000000000000000000000000
+
+00000000000000000000000000000000:7E32F418910C9AC8701292B5F96346F3:\
+01000000000000000000000000000000
+
+00000000000000000000000000000000:9FC6C21A562A049AD320EAA0D43C1998:\
+00800000000000000000000000000000
+
+00000000000000000000000000000000:7A0BD66C361D641DFD313CBE23F69A57:\
+00400000000000000000000000000000
+
+00000000000000000000000000000000:C2E2CAD226964597A98C388B27127EA1:\
+00200000000000000000000000000000
+
+00000000000000000000000000000000:B7F4837AC6F1F808D8EBBF1D08077FB4:\
+00100000000000000000000000000000
+
+00000000000000000000000000000000:0495E1AEDA7A9EC9ACBF38FE41CB08FA:\
+00080000000000000000000000000000
+
+00000000000000000000000000000000:E001020E1D0C05BE072695F3F48F07B2:\
+00040000000000000000000000000000
+
+00000000000000000000000000000000:608CE7A12C9EEC348FF674FB9F8D1972:\
+00020000000000000000000000000000
+
+00000000000000000000000000000000:916BEC60955C1A3540B4C245F4D3B94B:\
+00010000000000000000000000000000
+
+00000000000000000000000000000000:B2B91EC4EFE12CD4EDDA71ED52B278B1:\
+00008000000000000000000000000000
+
+00000000000000000000000000000000:0CA46CF5275313AB3D9494A5BB7D786A:\
+00004000000000000000000000000000
+
+00000000000000000000000000000000:E679B7C6F661AE52BA5199EC24D4E542:\
+00002000000000000000000000000000
+
+00000000000000000000000000000000:043FAB3A991B3FEC872AC747640731CB:\
+00001000000000000000000000000000
+
+00000000000000000000000000000000:EF8C38151A67B9A51E0935BBA14D9E22:\
+00000800000000000000000000000000
+
+00000000000000000000000000000000:2D4515423CFCF372B5632C2879A71267:\
+00000400000000000000000000000000
+
+00000000000000000000000000000000:2420A9327B9D2426C19F755BC3D8BD88:\
+00000200000000000000000000000000
+
+00000000000000000000000000000000:2151D88643EE81D8D23B44D22E2B0D65:\
+00000100000000000000000000000000
+
+00000000000000000000000000000000:AEFA6F32E963CB2D4D89E673B503DDAC:\
+00000080000000000000000000000000
+
+00000000000000000000000000000000:43DBE4D6B1BA3F05F16D73B2F80A12DF:\
+00000040000000000000000000000000
+
+00000000000000000000000000000000:ED8C9B25558CAD4EF9469364BE97CA30:\
+00000020000000000000000000000000
+
+00000000000000000000000000000000:BDE5B1DC5053F94670599CBE6845604B:\
+00000010000000000000000000000000
+
+00000000000000000000000000000000:4529434499884BE7C4E6D009F3D5353E:\
+00000008000000000000000000000000
+
+00000000000000000000000000000000:B3D4C642173189B9295912E860CF6880:\
+00000004000000000000000000000000
+
+00000000000000000000000000000000:651F1B1629535AD03D5C296D560FDE1F:\
+00000002000000000000000000000000
+
+00000000000000000000000000000000:8A380594D7396453771A1DFBE2914C8E:\
+00000001000000000000000000000000
+
+00000000000000000000000000000000:395FE0214AC536428C86737514B6237F:\
+00000000800000000000000000000000
+
+00000000000000000000000000000000:ACEFAC47A7AB6E635EA9F85EF74DEFF3:\
+00000000400000000000000000000000
+
+00000000000000000000000000000000:8C208E26E96D9DFA248010D8C1CFDB3B:\
+00000000200000000000000000000000
+
+00000000000000000000000000000000:D3AE8AE99B3A84C3721EAA57C8EB17B1:\
+00000000100000000000000000000000
+
+00000000000000000000000000000000:40D8DA37A8A6591A203F2A38AB05A08D:\
+00000000080000000000000000000000
+
+00000000000000000000000000000000:F0580D0B864E8C03638A33499B36C9A5:\
+00000000040000000000000000000000
+
+00000000000000000000000000000000:10F19634C2D1006B0C208AA303065B0F:\
+00000000020000000000000000000000
+
+00000000000000000000000000000000:7D43298935D0AF6DB498542752666C99:\
+00000000010000000000000000000000
+
+00000000000000000000000000000000:456AD1F19D18900B4F85EB64E06DF643:\
+00000000008000000000000000000000
+
+00000000000000000000000000000000:08C83A53955102F6E60C2CB0F6C02443:\
+00000000004000000000000000000000
+
+00000000000000000000000000000000:351C1035006BC7475DF60694859BB491:\
+00000000002000000000000000000000
+
+00000000000000000000000000000000:BB47464DFF62381AD4A93684D00A817F:\
+00000000001000000000000000000000
+
+00000000000000000000000000000000:514AC91B28081BD0E0CAE22D766257DF:\
+00000000000800000000000000000000
+
+00000000000000000000000000000000:7758C19B083A62E6F2CAAD2B4C3DF4DC:\
+00000000000400000000000000000000
+
+00000000000000000000000000000000:46B352EAC71542E417619E0360221673:\
+00000000000200000000000000000000
+
+00000000000000000000000000000000:648D51C6F9522FE38108BBFD34015F22:\
+00000000000100000000000000000000
+
+00000000000000000000000000000000:DCD800CC104B9C098AB4B931C7538F00:\
+00000000000080000000000000000000
+
+00000000000000000000000000000000:E40601C1632937FA769C58BE63DEB056:\
+00000000000040000000000000000000
+
+00000000000000000000000000000000:BC968175089F3864C81124A55AA445EC:\
+00000000000020000000000000000000
+
+00000000000000000000000000000000:05479ACFA5A7C6BC89FE432D8D25A366:\
+00000000000010000000000000000000
+
+00000000000000000000000000000000:8DDF91E221B4C2043C079F5F0ED63EA7:\
+00000000000008000000000000000000
+
+00000000000000000000000000000000:66C47E3E339FFD404A61547E54ED0F7F:\
+00000000000004000000000000000000
+
+00000000000000000000000000000000:3D622A36A3375D2EFFF3B49363F25755:\
+00000000000002000000000000000000
+
+00000000000000000000000000000000:C2E42DDC662F226D09908E2CFDD03D32:\
+00000000000001000000000000000000
+
+00000000000000000000000000000000:3221BC8032E72E0DE7580480A99DFD7D:\
+00000000000000800000000000000000
+
+00000000000000000000000000000000:C65A142D036E99D1A4DA370D964A8A44:\
+00000000000000400000000000000000
+
+00000000000000000000000000000000:E9C03F4840645726563582AA30464D1E:\
+00000000000000200000000000000000
+
+00000000000000000000000000000000:93C2F8237D526E910F007FA0CF0608A8:\
+00000000000000100000000000000000
+
+00000000000000000000000000000000:6F3A45184B87581E98B7B0D873F8B315:\
+00000000000000080000000000000000
+
+00000000000000000000000000000000:D3569BAB0FDD360451E113895B39D0E2:\
+00000000000000040000000000000000
+
+00000000000000000000000000000000:4002FF10DDB6FCB6669AE3FED696B2EC:\
+00000000000000020000000000000000
+
+00000000000000000000000000000000:B265C44F675800A3B498FFA91C440654:\
+00000000000000010000000000000000
+
+00000000000000000000000000000000:092E77F2537EE742D627EA8628E473E9:\
+00000000000000008000000000000000
+
+00000000000000000000000000000000:441859995F05E1C06D118CFFB389C9CE:\
+00000000000000004000000000000000
+
+00000000000000000000000000000000:844480BB205810808DC1F87C2B5281E9:\
+00000000000000002000000000000000
+
+00000000000000000000000000000000:4B2E7C3B31CFC0CA5B51EA589DFFC9AC:\
+00000000000000001000000000000000
+
+00000000000000000000000000000000:D55D552EA89C267FF3B0AF688CF00D78:\
+00000000000000000800000000000000
+
+00000000000000000000000000000000:6AD19E9DD39381C8A02F3CC6F60C8048:\
+00000000000000000400000000000000
+
+00000000000000000000000000000000:271ED37DB771414743EB781B2B315841:\
+00000000000000000200000000000000
+
+00000000000000000000000000000000:ED0A833C87FE6CDC56E021BCD3099508:\
+00000000000000000100000000000000
+
+00000000000000000000000000000000:6DBE8FEEB66CF747FFEC4E6D3D2D6BB0:\
+00000000000000000080000000000000
+
+00000000000000000000000000000000:79460469EFEA89FA576B526B17709D4E:\
+00000000000000000040000000000000
+
+00000000000000000000000000000000:5C3C35EC3D15CFAE719221549293A6AC:\
+00000000000000000020000000000000
+
+00000000000000000000000000000000:607106E18F8C8A6E725AF44A491D891A:\
+00000000000000000010000000000000
+
+00000000000000000000000000000000:1C22A5627309A238E2CE5A39BE370243:\
+00000000000000000008000000000000
+
+00000000000000000000000000000000:FB6D4F017D84E9B74C2A59204A2EA0D6:\
+00000000000000000004000000000000
+
+00000000000000000000000000000000:B66A30712DB3BD6B580678BDA72CC5B5:\
+00000000000000000002000000000000
+
+00000000000000000000000000000000:59C93B2A53BE699840E29D78ACF05DE0:\
+00000000000000000001000000000000
+
+00000000000000000000000000000000:AD37DFE5DCBB5A50228537BF24ED0159:\
+00000000000000000000800000000000
+
+00000000000000000000000000000000:C9FAB85DCB8DA12A7C9416B267F21486:\
+00000000000000000000400000000000
+
+00000000000000000000000000000000:EC797A0F6EBED4C257BC7FC1D7BD0100:\
+00000000000000000000200000000000
+
+00000000000000000000000000000000:629D633D7A7C345A3A3CF66565E298E1:\
+00000000000000000000100000000000
+
+00000000000000000000000000000000:859D400CC95F29E7131561F4D7E4DD12:\
+00000000000000000000080000000000
+
+00000000000000000000000000000000:932CFF2E8A828C61BA537E186F559E93:\
+00000000000000000000040000000000
+
+00000000000000000000000000000000:62FA5692938CB84279C7E399BA10E08D:\
+00000000000000000000020000000000
+
+00000000000000000000000000000000:50321207B2A375B12F4630F3F1909B08:\
+00000000000000000000010000000000
+
+00000000000000000000000000000000:63978A72D0ACAF85676EAA2D1EE01F3C:\
+00000000000000000000008000000000
+
+00000000000000000000000000000000:20721CCA68AE0451687D82534A360173:\
+00000000000000000000004000000000
+
+00000000000000000000000000000000:9223A844EAB1CA5D3A43EBC4C5CF01C8:\
+00000000000000000000002000000000
+
+00000000000000000000000000000000:70E162CC61AC398CF4D9DBE62FD653CE:\
+00000000000000000000001000000000
+
+00000000000000000000000000000000:082CED7A4969FD3C8131BF9AE57754DB:\
+00000000000000000000000800000000
+
+00000000000000000000000000000000:169070D4658D94C12041D14EC60A2B0A:\
+00000000000000000000000400000000
+
+00000000000000000000000000000000:960E45070B5BA767F1A3117851ECF9DA:\
+00000000000000000000000200000000
+
+00000000000000000000000000000000:4AAAA999C2421953E3607CA202D4C1DE:\
+00000000000000000000000100000000
+
+00000000000000000000000000000000:E4B97E5B2BA83D2038B5D08EB792F92F:\
+00000000000000000000000080000000
+
+00000000000000000000000000000000:ECBC7F9C422FC676152CC7E40391D730:\
+00000000000000000000000040000000
+
+00000000000000000000000000000000:55EBABC43A33305FB82B39A88A737FFF:\
+00000000000000000000000020000000
+
+00000000000000000000000000000000:C1BDA064749B2B7A9E9378137462F800:\
+00000000000000000000000010000000
+
+00000000000000000000000000000000:BDDD0163E4CEAC2C614ABDA9EBE15F3D:\
+00000000000000000000000008000000
+
+00000000000000000000000000000000:B767CF0E6717B409743AE41C56A2054D:\
+00000000000000000000000004000000
+
+00000000000000000000000000000000:AD897CFAED8FBBD9A3006F7EB2A7C601:\
+00000000000000000000000002000000
+
+00000000000000000000000000000000:2929929D821D010A1A30E9CF4415F809:\
+00000000000000000000000001000000
+
+00000000000000000000000000000000:0C861D39741060051855648B385708B5:\
+00000000000000000000000000800000
+
+00000000000000000000000000000000:4BA018EA1AFF5C0A9CF368592B08FD34:\
+00000000000000000000000000400000
+
+00000000000000000000000000000000:4377CD44B655A0ABC40E5B9D3A480EC6:\
+00000000000000000000000000200000
+
+00000000000000000000000000000000:2F604E94C9CD1DCB730AB0AF407FEDBD:\
+00000000000000000000000000100000
+
+00000000000000000000000000000000:44A3514094941B7E497BCFE0D746BA48:\
+00000000000000000000000000080000
+
+00000000000000000000000000000000:1235A968A7D12BA7042E7E63A897DBED:\
+00000000000000000000000000040000
+
+00000000000000000000000000000000:0BA061C7AD274E004B2E06D3D5FC784D:\
+00000000000000000000000000020000
+
+00000000000000000000000000000000:E0DB8CE28D1C2F6B692B230A7AB0CB44:\
+00000000000000000000000000010000
+
+00000000000000000000000000000000:ED4BBD535080655AF3F4D71709B1B8D5:\
+00000000000000000000000000008000
+
+00000000000000000000000000000000:92D183FBE0BD07A0884EBD1963A193BE:\
+00000000000000000000000000004000
+
+00000000000000000000000000000000:995BB9E75386C99DA3038C3C6340C838:\
+00000000000000000000000000002000
+
+00000000000000000000000000000000:4914DA6C7A8E1AB8297A9D280DE576F9:\
+00000000000000000000000000001000
+
+00000000000000000000000000000000:6415185D85078CE80F46C6E09EDB8B78:\
+00000000000000000000000000000800
+
+00000000000000000000000000000000:8B2908466F8BD3C1C3A4A5EAFCC0FF92:\
+00000000000000000000000000000400
+
+00000000000000000000000000000000:425BF2FCF5DD8B0013773F9A0DC09B0D:\
+00000000000000000000000000000200
+
+00000000000000000000000000000000:9AC35220BE56E453B73CD887B299D06E:\
+00000000000000000000000000000100
+
+00000000000000000000000000000000:41900EF8223D019F1BC3E8EA68FC763C:\
+00000000000000000000000000000080
+
+00000000000000000000000000000000:9D294A574144109A9C6DE8E90EE517B6:\
+00000000000000000000000000000040
+
+00000000000000000000000000000000:4146D6BB7AE455D93EAF43753C7AE693:\
+00000000000000000000000000000020
+
+00000000000000000000000000000000:4155B7D12FD12F96FD39C576FDD41422:\
+00000000000000000000000000000010
+
+00000000000000000000000000000000:1AF1E634B06211668CE2410D5EDCA968:\
+00000000000000000000000000000008
+
+00000000000000000000000000000000:815739510622BFE08EEE06B772368524:\
+00000000000000000000000000000004
+
+00000000000000000000000000000000:E2F7D8411181A21B02C1466E750056C2:\
+00000000000000000000000000000002
+
+00000000000000000000000000000000:13095792D8B1D771378839C912CA3C41:\
+00000000000000000000000000000001
+
+00000000000000000000000000000000:8301730C7D5FEFC416BEEC1104C51E36:\
+800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F7EF83BDD4C3D5B30E805C351DB87200:\
+400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A236EB8595FDF9239C658D58342EF566:\
+200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:236397EB9EEDA5EA8BF4A42864A5A39F:\
+100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:21C3DD416D64F6055C8C3977EEFB4652:\
+080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:59128F63BD9D834C3EECA5A5299417D1:\
+040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0F95FA4C48DE95391B45A460B92B22BF:\
+020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5073FABD5FA03D153108B9A5F2128C78:\
+010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B83872427919126F2C976D45872B7596:\
+008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:73F8E6C4181758AFA29945E970C8F854:\
+004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B72DC39B9A72EFFA047E3657B1F02B1B:\
+002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:081F1C50BF964CCC01949363A1A1C76C:\
+001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D4A2AB8B904BE542386CC2342AC354D6:\
+000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BC94C45B53BB5281BFF16F7BC7CCD26E:\
+000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7D976240134D43279AB809A3EC1BAB8E:\
+000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BE18D342080322DBBCEDBB83C7F11CA5:\
+000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D1359D29060E0003C78066A900C90C00:\
+000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FD0A7E670B7E9B57C913D38E4649715E:\
+000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C9DFB5B1CB3E079CFC027E67DA61EC2A:\
+000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:10FDD69900FBC470499EDF0AFF655430:\
+000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:565721A361F5F0EB44366DEC1D6841BE:\
+000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:07AD173E39A769D345277F4CFD16BBA8:\
+000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8E89B6B70A10D1866ED4D139A0E6565C:\
+000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:88A431DD4CBBD94778AE53A36EE246DE:\
+000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F4C8E31B64506E9BDE6BB682DBCEF50A:\
+000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5B0E256E4EAB25AEC08CD2CE5547334D:\
+000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EDBAA578C13D7D215057EAD4F03B9E1C:\
+000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7EA37DB8EB1B362E370A43DF1ADB2F0A:\
+000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B7C67AE8F749C4EFB7418788D369DEC:\
+000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:34D3A7E87A4B1B3FAC60672A3D82F40D:\
+000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4FE628152A1D46CF6DA78D5F17255877:\
+000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3460A571D035B6DA52AA8E59702B79C0:\
+000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CA2375E2E96AB28C7FC3E61B6561B07C:\
+000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7E33319A69017428DDBD979D3F6982C6:\
+000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:49DA8B8AD80A6BBA1003FF6B8D06E3D8:\
+000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CCE4C841B39187943DCCA5EB8BBF1221:\
+000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3B42FA9129BF36F87E445589460A19BD:\
+000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:3E397A22C64A8C09B5B59A9D397B0A96:\
+000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:159AB9C871FB3EB373A94721E9F0743A:\
+000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:9C2DECEEFEDF2475C26EFFEA3A0E2920:\
+000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FCC4399113E6BF62A23F657BEF97224:\
+000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:2FCA4167B034D9EDAC4E12828B911600:\
+000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:3F9434872C4E49EB8718EDB8896CFF2E:\
+000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:8168025815D16028078007C9E1370331:\
+000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:F0FBF790B49553EC3963805CC2F6AA7E:\
+000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:951C45D26A548A9A6152CCBC00D3C6FA:\
+000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:845DCC97B1F8CD3254D2B29A59C7AE41:\
+000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:6694A168D387E4FB3291A376B938136D:\
+000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:9569359A00659B9645565857398C982F:\
+000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:417C97D7F56216FFEBE64A73F8D81168:\
+000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:8C46288B3314B9E1BC91E3C901C784A8:\
+000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:8EB78926977246F186274D88A4B0E6B3:\
+000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:51E819059AB0325A2DF7F8CF49A54353:\
+000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:56A59894FC1972B03D66D6C43688138B:\
+000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:CB772637B59AD2330ACC8CC2FA7A338B:\
+000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:1E3759E5BBE19EA0F66FBB0702F07440:\
+000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:2112CFD246447D95F1A6BFF65A044121:\
+000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:8A7E580BAC4406B297E12B472C2748E3:\
+000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:349ABE7C34357C7C719BD48AB62DF95C:\
+000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:5EDB9089B865DAC899854DACE9DBBDBC:\
+000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:C82372837C0B459699779683785CE09C:\
+000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:B26532F7C0FDFF76BFADD7178E7A2A7A:\
+000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:965F80C599BF6AA85CA2199C785EDAF1:\
+000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:8434DFE0C8717514FB0F8A4FF46930B6:\
+000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:10D701937E2944C7B48BAA32DA64C6A5:\
+000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:9A401E466C3686609B7B92FC6C57EA3B:\
+000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:E3442053C50265AEBEFD327633E449B1:\
+000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:7DF5EC480DEFA928687A35116989A7E2:\
+000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:EB2D38038A867146E3999D3E4DACE2BD:\
+000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:AE420A68558A2A50085331D8C46D7685:\
+000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:049B78384DE81BB815C48CC565DC1029:\
+000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:38EDCB5D37E043621F1EB80C78E40657:\
+000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:928C462D2AE8B7B45C252D0CAE80B34C:\
+000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:B3AD5D661D6DACFD57C214FDB9384491:\
+000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:9785657218402C1F3D1A40E73B015359:\
+000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:302355F21D129456A3EC58CD4C74D334:\
+000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:7322A935E1F65E2F341F778D0A55DAC0:\
+000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:7EEEF0009743F18E1E08F5CB02CFA104:\
+000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:82FA95B00BA5C8D71CB372895E91F7AD:\
+000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:44E308A9BAE6315936931C0D6F3472A4:\
+000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:A0F7760CB5F12B2F7F7451688DCC6DB3:\
+000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:249CBF1A9027A9D4A049DCC61C100631:\
+000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:AE5191679DB49836EBD11781E1A9E809:\
+000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:6F0F72E56952895F7425A34EB97D0D41:\
+000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:E4C8937EA026250290E85A2AA4B3A338:\
+000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:0D1B7815F62D8C6DB79E9755EB5CC047:\
+000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:3B8DA219500F670D2D32C753F613E646:\
+000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:DC16F91F486975C2762AAEF8E4C66543:\
+000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:7CC222B3C5866AC0F27A60C9D9713981:\
+000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:B7F625FC185B3ACEF820AF59570370FD:\
+000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:8AA59EA7476AFE267D7745A2A5E1D0CB:\
+000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:DDB9E4AA397029E10ED5F1984513280B:\
+000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:C92B81F3061A4ABC6C35D1B0AF2BA410:\
+000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:05F510BA96377001A23093980C02FBCD:\
+000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:A22D14EBC78B338735CA0AAD155B0114:\
+000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:C562318B01D5235CCD4DC3D3A8B10DA0:\
+000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:FA248CAA2F7C4B029054A31917BE9B47:\
+000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:FCC4E2E3C6E5DB8DECBF2493E3A52B9A:\
+000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:C5D23718F33ADC9F8B3B35263E47248A:\
+000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:773E59C9CA8EFD081E1CFD4F3DF4BC16:\
+000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:9A5E5AB516ECEA600952D25684DFF5E9:\
+000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:4EB9B9CC17E48F68423C884D64091022:\
+000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:0CCD75BECA8406EBF53CB0ABB1B46B23:\
+000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:0242108DABD2ED9886E8ABD70AA97B29:\
+000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:C52A6EB2958C995465C4F870F1A8269E:\
+000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:5FD2C7F3C81B013B96EC3ACBB0688175:\
+000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:1E63A0B10B0293A8572FD7749ACB9A53:\
+000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:9E1D466FA752C13AF4296CFFB8566DB2:\
+000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:BA1A69D7AD2869734A4954553D4EF249:\
+000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:EC2E7D615474B0B08D47AFCBE4FD8402:\
+000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:5C295AA2183B5FB9498094DB774244D1:\
+000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:1C5A17D1BE0D9EDCF339DB3D2631F236:\
+000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:CF6E9758B39149E3E29FB66CD58D0976:\
+000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:4F3FF2CAB95F678D85207691BFDAB811:\
+000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:463F1FCDF4A918300A93D7BED72F788B:\
+000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:CA5C88802CF0520C6521B106F4A58977:\
+000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:95C83D16F101B16E82D9DF9108A6805A:\
+000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:F98E0BE43F35A4CD52F93FD0877C1638:\
+000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:3B0D41F3A12DE6BDACFCA225F1344D77:\
+000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:BCB6197992A90A62497B53EC8E7E5857:\
+000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:9CA86B881701310C33F6CB2911ED777E:\
+000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:DDF4EBC89B16643E7B4F0B43AB3FC443:\
+000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:650AA74CDF7C5E92720E02A87ECA8FB2:\
+000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:F44E947B2A18F15189884E55EAC372CD:\
+000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:A4CC79AB8F6ABA941D400B45C32DA248:\
+000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:3C49EE1D3E4D8FD1E5CE9C793511F2E7:\
+000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:49199A91A32424357890F5C8E08E168C:\
+000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:438EBCC76304C4231DCDBDF85A876A85:\
+000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:DD04C176440BBC6686C90AEE775BD368:\
+000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:1DBAE21DF9D10630D8E9BA704AA3A6E2:\
+000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:F46B5DF361FF1A58AD233A2884E9B73B:\
+000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:DBD49C75B6CCA6CCEF0423FF3941922A:\
+000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:2C62774D20D574A487057A24280EBBC9:\
+000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:A6E24FFF68DF51B5613692D4098F7E22:\
+000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:A961B427D5FCD129EE29830DBD2952DD:\
+000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:7F637C136F8A57358DD5229B5E3BC38C:\
+000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:6FC5A39B35D2EF01B808E20C05DB9DDE:\
+000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:95E085E82A0883C8F6C1C83D6F4DF270:\
+000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:BDEE30731D4CD3593E46D9A8222485CC:\
+000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:508B5BB4ECCE303014D5A9ABB47DD30D:\
+000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:047832614B07AEABC28A39D5E72007C9:\
+000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:C1D4B662EE239A6DB9262B23C561B677:\
+000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:E567714DF47D43F1505D318C8D553062:\
+000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:CDF70F29AFD13EC6820D2C126D053DC4:\
+000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:182F2FD0ADC68D8DC72B08AC17E642C1:\
+000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:5DAA43AFBCD59026C0C410072A263673:\
+000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:E0C6DD7A8971A7D21AFAE153F115D658:\
+000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:4ED2DAA970922690D8CDF6CDFDA2E8D3:\
+000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:C1F929B679E007B1DDBBE896CE91C8C5:\
+000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:2323F5569BA740E14E05E0FB0914CE44:\
+000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:875AFCE0522E00712AB29E0E77BA57D2:\
+000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:A6185ECBDEFEB900335BAB38D95D7583:\
+000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:1331B89B377EA2A88A181907300BC50C:\
+000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:FC9D177C5B5D072E041D6C2F9EE6B536:\
+000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:5BCE1EA4FD0CC1EDE325DCEB55790565:\
+000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:937FE02D20FCB72F0F57201012B88BA4:\
+000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:5280E7768E573DC74DB90ABDC10422FE:\
+000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:0995E2D8E83C853C58ECF916E8067C3A:\
+000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:98DF44D404B5BD54CA5D55D08E7F1B12:\
+000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:9FD5F1165CD60FA5229CF03080428664:\
+000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:B4AE95212E3E8FFD6B27D4F0CC079CCA:\
+000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:878BD051874AB0BAC12EA94C60CC2671:\
+000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:3B0F2EF2A0849425063F49E65DF4D3AB:\
+000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:07D4297668485EBBF0F9266C203407E2:\
+000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:C2ECFB79C073BD453BDD2323C77FF80D:\
+000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:5173B04FC7C211CA17161164B79D0AE7:\
+000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:5135A445A721783AACD06930D39F72C4:\
+000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:A511E849B1B75DC94B1D73D957B53D78:\
+000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:42312B67F192D72B73689C712D60EAB7:\
+000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:30C89A160855BC3F339A170B715DD482:\
+000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:8DC19A7A97319A3309B98797A59954FA:\
+000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:D0AA5A8B9DFF98E18281E5FF20CCA3DE:\
+000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:AFA70EF4B45EA22E90108B834019120A:\
+000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:2801C6A5C0547CB988A2137A559D12B0:\
+000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:D791F5709D4AFE0642955F1B072F144E:\
+000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:35BB50E6D59A693709DE9B88CC8581F6:\
+000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:9B58CC95279539C1AF0BBC274A62F5C8:\
+000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:F51803FF4EA1B0F0AFF1C68C5C98CB3A:\
+000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:975B5309F1D3ACE9BA08B3D2D3FCB43E:\
+000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:D53CD9381EA85B0C106C22DA611F7336:\
+000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:393270B47546F1BFE35690ACCAC0FEBD:\
+000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:53E21284948996FC03ED9BCC34B45B61:\
+000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:AD9CA2740670DA740C75703A8859382B:\
+000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:AC9C2960E3061E56D8B9A1CDD3EED010:\
+000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:E5F68B122D15823F131DEA0468977D70:\
+000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:7EB7C6460FE9885BC96AFD4D4B65E90E:\
+000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:409147483ADC22592CA41224D35BB323:\
+000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:AB61745316651F61F4E2CC1DFBF8135C:\
+000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:88977EAD91ECF9C83F33EBE41FB7410C:\
+000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:9DC923136A1882D73CB412C986103481:\
+000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:9914219ED77B8FA772B4B8C53F9AD2FC:\
+000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:B9A0FA2324625650A2052D691E7DE9C3:\
+000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:5172978A58543DE597060983FD799F1B:\
+8000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0F86AECE7ACE09A8EAC0345C935BE91A:\
+4000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8C8D6ACDB23AE4B5BEE4E2C15273286F:\
+2000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:11395D4BFE4C8258979EE2BF2D24DFF4:\
+1000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D50183337FD8B3FAEF06C78B2ECFC40F:\
+0800000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F3969970B4E37D9FFD9BD886200D7C0F:\
+0400000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FF101A14CCB71863E0B51E8583D22760:\
+0200000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0CACB5AB8A51226134656220DBF23228:\
+0100000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BF75C54F53A3F374DC549BE280F6C6E0:\
+0080000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1DC755ED6128DC50826E65632C7672D6:\
+0040000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D7A46C3A378DB6A9C041D7DB1835DE3F:\
+0020000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:175FDB12EFB7E7D950777FE12BAAC953:\
+0010000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1A5C489CB6E0608EADAF3DBFA8B5FD1B:\
+0008000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7FD567FB07007A65CA8D98D4BF66F7F1:\
+0004000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3256E4481641ED28938AD6471414CD04:\
+0002000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A2AD960B437DCD0669681BBBC30F0CF1:\
+0001000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB04B658FA923EA9CD5FB98BE54989DE:\
+0000800000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F3F43741881655CF074E36BD655F420B:\
+0000400000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:637DCF9D891EAD8D85A842BE0DC8261F:\
+0000200000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E663749A2786E3BA3833348A9CE5E7F0:\
+0000100000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:76F0F7C439E25C54A9BC7AEA05640882:\
+0000080000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2CDE682FC40895F1E2464739FAD230DD:\
+0000040000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3242FE919ADFDCE04F163EBE772AD51D:\
+0000020000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CE05F79A80B2947B13BD22EE37FB3F79:\
+0000010000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5345BDE33281A0CB4A899A4F18C57563:\
+0000008000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2E971691DDFD33D36738C08A517B0B44:\
+0000004000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EE144813E2194B18F1593C44932F170F:\
+0000002000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F626C435E30ABA4FA6F6DCA30CC08833:\
+0000001000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8AD30F69BD7446793C36676755D05F57:\
+0000000800000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:56851CB7277CBE4AE9AFF86E5BD49F90:\
+0000000400000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CA864AC764D6B9B9141A08146CFA7F56:\
+0000000200000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:484518D9A3C6CF7B7B92393DBBF78E42:\
+0000000100000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:093F44542B0E41E300C11AE77A48C6C4:\
+0000000080000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D9856ADC56605F70EF069D639C9D977:\
+0000000040000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3FFB2FF7C5457744CABDFB89C0BBA7E8:\
+0000000020000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D8254191931BE754D64F70FE3E226C7:\
+0000000010000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:23F3CC55C460EE949A9934C7E5C06CCB:\
+0000000008000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8739DA7F4A9D821EAA7A349E25741DAA:\
+0000000004000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:73E724C08890501275A0559621526948:\
+0000000002000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4CC6569D4F6207DDB03B232BFA8AA481:\
+0000000001000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:52A6D921AEF99205822B361D8D9DD998:\
+0000000000800000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:970E1899AEEEB7CCD26F854CA25214E2:\
+0000000000400000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D1DEFC8AC21C95160CF71612AAC55A8C:\
+0000000000200000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D8C2A3AD65F16024265714C21B8A70C5:\
+0000000000100000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:55DE20482FAE35A03F0D57B7546EB980:\
+0000000000080000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:81BCA41F11D12EE26326E042E74961AF:\
+0000000000040000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D8D5C30A508436401396224D4E417B5:\
+0000000000020000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FA1ECAB0B3C598C51372A5AAF6E1315:\
+0000000000010000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:945BF2690A9CE9ED8009004039E1E743:\
+0000000000008000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:73618AD5FD3A9740CB92C3F870C772B9:\
+0000000000004000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A7BAB4D0765D66F06FCB85A42D4CF0EE:\
+0000000000002000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2A659EA8BF9EA163976C33A0B7463A56:\
+0000000000001000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4D9D5CC19BF1B2D48EF2CF4CD313D3E3:\
+0000000000000800000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0D7A26F850BDD2A633689367901BC2A4:\
+0000000000000400000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1A1235352EC6CD1A7A1913E77EF7CE4D:\
+0000000000000200000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5FDC541376BAF15D5AC011B9C0B74E75:\
+0000000000000100000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CB8DCB7AD04598E8337747E02A8DF16E:\
+0000000000000080000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2855A6EEA8B20B8B25EDEE37A7D7E976:\
+0000000000000040000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:58B5CD00D833233E718DBEAABCC48E8F:\
+0000000000000020000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6DF58A11F96B67C330ED10FFFB1E6D74:\
+0000000000000010000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8FD74AAB8D136DCF1B398D1174AA343B:\
+0000000000000008000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A81E2F57E80761E361DB1008AC1ABDD8:\
+0000000000000004000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BDD939E7A93F6FECC762E2E3321DFEC7:\
+0000000000000002000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C281060452693278B48AD9076911EC39:\
+0000000000000001000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C06C159EEAFF3CB4B509DB604060F537:\
+0000000000000000800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:757CED2216A9912B5FBFA1E623077E5D:\
+0000000000000000400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9606EDC198F44F955F510FA525E9C80C:\
+0000000000000000200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:ADE8D3FAE7A4651855E053F42FFF7905:\
+0000000000000000100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:398BA679B6C0A63479F0C6FE25614F01:\
+0000000000000000080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB77ECA9DEF62902240E4BF3806F3A64:\
+0000000000000000040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B4313D0A9D34B21F69021A5458680579:\
+0000000000000000020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BDC7C4ED3B989BF8288E8B4ACDE3FEEA:\
+0000000000000000010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:430A2DAFFA822532FD4843DF9CBAF824:\
+0000000000000000008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:16A2DEBA266577150B6DC34995902C99:\
+0000000000000000004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5902382C7675AF5C52A6ADF349454276:\
+0000000000000000002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0D912AA37CFB56223C6ED9E04B3D563F:\
+0000000000000000001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1FD8880BE6A6E51C0C0E9C2866127F7D:\
+0000000000000000000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BC4079EE5CDB86BDD8FAE650E2931D98:\
+0000000000000000000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C52E414FC84C978FAD8CFA103844C306:\
+0000000000000000000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DF6291B74EF77E82A8FB7C207213125F:\
+0000000000000000000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:530424A0F23CD90074F2D672A4FF3A96:\
+0000000000000000000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:83ED777537F5EE3E5769B8A07476A6AB:\
+0000000000000000000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5357341784EAB13F104FBAEFC69B726B:\
+0000000000000000000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6DBACA4C68AD93373CBEB1DB0963F33F:\
+0000000000000000000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EFA128916DF70D852574EC8507625CC8:\
+0000000000000000000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0BD55284AC672E1A2F248FB89C22B514:\
+0000000000000000000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E3222E0E2770496C443ED562ECBFC368:\
+0000000000000000000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6B689B6DB9374E072B45A7807DAAB132:\
+0000000000000000000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3215A725BCFBB120926F8BBCE41FC3EC:\
+0000000000000000000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F2475FE25BEF963862CF66C91DA0250B:\
+0000000000000000000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5E1CC549BB39348529FD279DFE5E1FFC:\
+0000000000000000000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1A8EDD22AA0FE906267DF710DE8DB007:\
+0000000000000000000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EE139CE12F8205D4EECCE6D7FD23B01F:\
+0000000000000000000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FD84D87207D7BE3A79272CC9DF65E1E6:\
+0000000000000000000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CE01B0EEA6BF6D981AFFB07FE1DD164E:\
+0000000000000000000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1BCCA9BD22179B1C941947643FB01F0F:\
+0000000000000000000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:87A581347DF02FF9973A0622DF673804:\
+0000000000000000000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1EDEB75B65B365582AB5AA265037FA55:\
+0000000000000000000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:807DD7E0418803258EF677BA9345CF51:\
+0000000000000000000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:70CE90D345621481A99DC8EE1A62DCD5:\
+0000000000000000000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BB51E835284E0F7B74C053151F07D207:\
+0000000000000000000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:0240317EC3AFA5D4610C545C0D507367:\
+0000000000000000000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:9B77B76CA91662A9CB067267F0560C65:\
+0000000000000000000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:2219ED37D533B05CDC20B16F45D3DBD9:\
+0000000000000000000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:BC5A33AF9E4591BD4CF53B20728C3F85:\
+0000000000000000000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:68628B89F58C20E5195DB795C0A41489:\
+0000000000000000000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:5D177DE234B6288510163F2351750215:\
+0000000000000000000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:6015D7BA2F33B88B2BE0016E022E05FE:\
+0000000000000000000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:2D203E35B97E3B315C17D9F0F80ACDA0:\
+0000000000000000000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:E5800AF9BF96D6B7ED3A2AED899CA456:\
+0000000000000000000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:1163E6F8F1DE919686C138089EFA7986:\
+0000000000000000000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:2180B46E9EAC63A165BE63DAE17889A4:\
+0000000000000000000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:3D751DC36B1046AC808D8275B48697AC:\
+0000000000000000000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:DF022C5EFCEB5D3FE7E72DDF11D16EA3:\
+0000000000000000000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:C706AB7A20E0D038143B78D9D12EC1A4:\
+0000000000000000000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:8AFB006F196B00DAE7F0B36C9E88A3B9:\
+0000000000000000000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:BED70262ED524A5C6A495092E2543993:\
+0000000000000000000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:088A58A7351C7A7AF594035514DE0757:\
+0000000000000000000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:F5DF0BB68AB377B12321365C05480EA8:\
+0000000000000000000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:512DC8D603A7E4C8031D3566F141B233:\
+0000000000000000000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:50342EA0E9E81EC53E3683C8C1471602:\
+0000000000000000000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:8AAB01E320B17FD9945D725F5EA904BA:\
+0000000000000000000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:76FB320065713C165DECBE5DAFDD79BD:\
+0000000000000000000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:A8AD014D22CD8FCC9557438B8228253A:\
+0000000000000000000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:6017A9EB6F3336882FCCEDEC746C62F6:\
+0000000000000000000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:2EDF94990EB0F4BAFE1F5903102FE874:\
+0000000000000000000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:4EC81B0FA8FAE0025AF09D26F1F200EA:\
+0000000000000000000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:AF7F474333E74691E5D01A3A841F8096:\
+0000000000000000000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:28FCE531836F2A255CA19DE6F53841E8:\
+0000000000000000000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:6282A41053316B1A4027488E6F747003:\
+0000000000000000000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:3668527987AC38A3F7C052A20B668F24:\
+0000000000000000000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:4C3473FE666072653E29354F07EF02B5:\
+0000000000000000000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:0A51D7A5B347225798EDE5663940F32F:\
+0000000000000000000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:D3CA3A8821A3D094CF63CF12136A1249:\
+0000000000000000000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:FBC5E4B37A69AD5F21E53F88E55AB95D:\
+0000000000000000000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:CCCAAA0A2DEFD357EE31C2CFEC9D0E8E:\
+0000000000000000000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:93348B5393560AA416C6E6F0C99A58F7:\
+0000000000000000000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:13AC66E49E23A8D3582AA7117F7A8F2F:\
+0000000000000000000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:C403AD02F23055CEE08281E7D0C7EB2A:\
+0000000000000000000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:65DFD53B699B191CE7A6610A405083DC:\
+0000000000000000000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:3D6F7E99F6512553BB983E8F75672B97:\
+0000000000000000000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:92BA0D580A954F8C8494A840F0252AEF:\
+0000000000000000000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:958D8C9141CE21DBD69E19BA1E4F67AA:\
+0000000000000000000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:E508796197F539FCDC917ECAB19507E0:\
+0000000000000000000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:2200A6914A2050E99A55FB3BF20315E4:\
+0000000000000000000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:627C0B2401EE6C095404CD7AA59EA67E:\
+0000000000000000000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:75159B707278DFE6FD8A024B9FF0D5A8:\
+0000000000000000000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:F47982BE40C39306ACF25A120BC1B4E0:\
+0000000000000000000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:01CAABEF85A1E081EA6983079A90EA34:\
+0000000000000000000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:7F473CD21A453BF74CC76184D6F5496F:\
+0000000000000000000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:659442FD57B94862529D3E4C530826FE:\
+0000000000000000000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:88A9140C094A695716A2966B1A8078A0:\
+0000000000000000000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:28CCFC1BB6180AA7373DA1F5A54E47EA:\
+0000000000000000000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:53DFD8CB845FD279B337B52DBBA3CF4C:\
+0000000000000000000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:1BB5B100DFE6BA16983AD4A0F09FD50B:\
+0000000000000000000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:A896AE30D529D4ACFFCF5B763309CD28:\
+0000000000000000000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:F40A1B359A9B6B1197276C71222371F4:\
+0000000000000000000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:9FDE11C9E6CF9A1E9089820FD928767C:\
+0000000000000000000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:7771A5A99B099A2C861D084E790958A2:\
+0000000000000000000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:BE1907AA5CA148A0282850401C48AF71:\
+0000000000000000000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:8E47D50827FD36B62C0D3BD36F863198:\
+0000000000000000000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:81AA1751209F9173258CD1625DB65E07:\
+0000000000000000000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:1EE8FE72574BD819C97A0DEA2A5E0B64:\
+0000000000000000000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:031BA0B3EFCAE9B08793C8107C277A27:\
+0000000000000000000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:34C8DFD0DC4BA5240CA21BF4959EEF6B:\
+0000000000000000000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:C7A4DA0D5892A185D35447DB904511B5:\
+0000000000000000000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:7A8B9982B6C8AE1B5DC02FC1D9AFA2E0:\
+0000000000000000000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:C77E0DFB29402C587C6DD97E0BD09ABA:\
+0000000000000000000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:1AA2FD990BD0B0715B18482088DE0844:\
+0000000000000000000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:31C2D486FDA54BAB4286A02D260918AC:\
+0000000000000000000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:545F5A95E159B5F0DDF544B60F9C28C3:\
+0000000000000000000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:45C84895AF0393588C67D9CDD5E4D7E2:\
+0000000000000000000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:745BF4AF94A92D32FFE44B41AEF39320:\
+0000000000000000000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:13C47C2F92F91D72F34381AC9A81473D:\
+0000000000000000000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:8836D5AA076110FCD5BD66F3BECB39F6:\
+0000000000000000000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:11EDE6F221E96C7515B1256DF055FBC3:\
+0000000000000000000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:4E3BE7D6830703A6185CF0BDBE7F5BE4:\
+0000000000000000000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:6A1ABDA47972CFF536946A1C7D380810:\
+0000000000000000000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:74031DB865D2FC8319A320FFAC4694D8:\
+0000000000000000000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:E1F751F11027548C057075E8D8F880EA:\
+0000000000000000000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:AF24FA74CA96D89088C9018AA60E1D53:\
+0000000000000000000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:0E5214D31B2C9219F6C9686A35F210FF:\
+0000000000000000000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:2A72E2E692463EE8846C94A483C27E25:\
+0000000000000000000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:2B9C3298626F11072D7B1D80B47A841F:\
+0000000000000000000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:7468CAA1A5FFC828BE5A752C33132E90:\
+0000000000000000000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:29C75ADD5EDE2680C169FF9FD9177331:\
+0000000000000000000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:9BA78930CDD3357A2D84A49725902E8F:\
+0000000000000000000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:F190AC4C43E202F925B5FD1E4CA62DD6:\
+0000000000000000000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:5716FB34A1A6B40C35B2BA860F12163E:\
+0000000000000000000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:43B90548889A171E85515AB05EC76856:\
+0000000000000000000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:B4DE6F86875147F5276D584CEC11AFB4:\
+0000000000000000000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:3DA6C1A8937583BF6491B2E9C52081E6:\
+0000000000000000000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:9A54FCD26D9754ADD5F8967EF551EAB0:\
+0000000000000000000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:F0DCFA56A7E41A859276A6F8927B561D:\
+0000000000000000000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:5881A8AE181F16B64CD0C455389F511C:\
+0000000000000000000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:E9F7AD45D9EA9AA4C830B89EEC61C1B5:\
+0000000000000000000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:9118B623A63BFC69A9AAB868D752460B:\
+0000000000000000000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:2D208D46FB2177C243C539FCCD4A1E9D:\
+0000000000000000000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:2A4F52A297F20E428222008D9BE4A23B:\
+0000000000000000000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:EBCFDD28550C9654374590EC4BFD1CDC:\
+0000000000000000000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:FABB99266FC741241F6CFC0CED776A11:\
+0000000000000000000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:FBDEC944B2303E3A08A964E24130D10D:\
+0000000000000000000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:9897E33E6052ABA1F07233BCEF531E32:\
+0000000000000000000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:509DCA41B038225B30D8B7880D52999D:\
+0000000000000000000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:3F70238F99F2AF394C31308D68F1707C:\
+0000000000000000000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:E6FF6426E9025DD6519837F71A6C3636:\
+0000000000000000000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:F222502AEF77C1F21DB79B08F7AB8CA2:\
+0000000000000000000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:C17D2C00477C1AA20B539BE8174E7202:\
+0000000000000000000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:0F7B12AE962AF9C0C8CDCAA288FC6E12:\
+0000000000000000000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:0E740EE58431521A622122AEFB163CE2:\
+0000000000000000000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:CF0B94FECAC6F67070306654FE198449:\
+0000000000000000000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:604EA1D0711ACB8E545C0A88976008F9:\
+0000000000000000000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:71D03D8F6F917FDF5B612180454F3699:\
+0000000000000000000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:A6BCFE7B73EDCE71DB36AF00B01C37EC:\
+0000000000000000000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:93D761851BB991221AE77968459787DD:\
+0000000000000000000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:F117E4D5C88CC1C067C88AE38A5BF1D5:\
+0000000000000000000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:B534328DA555A9B69AC2A5B08E3CE47E:\
+0000000000000000000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:7BDFB785D866B6487790B9F6164F5EBD:\
+0000000000000000000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:5B3BB41E43D02901F5A0231768347B38:\
+0000000000000000000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:917216669DB1600015F2FE7CBDDA0FF4:\
+0000000000000000000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:C79B582FC430C0187D7B1D7B1E79BDB9:\
+0000000000000000000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:B9A43998AED6BB7B79C91BB4C2530F4E:\
+0000000000000000000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:0B24EBDF9A1D129F5E8397AB7412BC74:\
+0000000000000000000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:96D523E4EF1C888C72460DEBA8D58B78:\
+0000000000000000000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:85708C4539C8B06DD787AFDD06A3FE24:\
+0000000000000000000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:67A106762D2F46B7880750BCF987054C:\
+0000000000000000000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:8F46E37371E81C389CA94A8272A14FC8:\
+0000000000000000000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:92DC700C11BBE46DA9559CAA7BA662F0:\
+0000000000000000000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:90D2B52984DA214F392EF4EAC26A04FE:\
+0000000000000000000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:832D440D62996C5BFCB7FAA08DEB4D2C:\
+0000000000000000000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:69B7F725BA2B0539F6B45F2C8495D571:\
+0000000000000000000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:CE78A2AA25F818D87C46367579FAE698:\
+0000000000000000000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:F5E3E4DA4FC90F25F7D6679F076CA32E:\
+0000000000000000000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:F7618B001BC19F0195BD21021D9545B6:\
+0000000000000000000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:D84E1E36E1100913C7AFDBFE5009EDEA:\
+0000000000000000000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:9DB2838E3903829913D2AEE6465202FD:\
+0000000000000000000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:361AFBF61BDB378CCF2B76C01469BAA2:\
+0000000000000000000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:DC4C998046574B4CC447154F663E8EBD:\
+0000000000000000000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:0D890EFA71666BE0A38B423BAD47C90F:\
+0000000000000000000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:F39C444538E646A2BD59B443F68C51D5:\
+0000000000000000000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:9C6D37340E8F5EA22213E17A9F720238:\
+0000000000000000000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:3A23813329F978C1C6C3BE1715011283:\
+0000000000000000000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:CE24D63AFA37E2A659A21CF770109BB4:\
+0000000000000000000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:DF329017478D86B2C360D55BC2B2ADCF:\
+0000000000000000000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:BC5EFA1FBF848776746FD7826656E25C:\
+0000000000000000000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:A3E4185241C566DD2CF8117D4D7699F4:\
+0000000000000000000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:EF7BBDEB18879C11E2979DCC601CB620:\
+0000000000000000000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:FDC76A95F9C87E394F82A787D7406D40:\
+0000000000000000000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:B224E2BECACF6773B9941516195ED06B:\
+0000000000000000000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:B3951D0CF640BB7BD8F3D9948745FF9E:\
+0000000000000000000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:F9C8966E2874F736765B89DA10EF4611:\
+0000000000000000000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:3750F26BAB98833AB30444C0821A594C:\
+0000000000000000000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:D369C2B7C2337D67A87CD5B4EB45D290:\
+0000000000000000000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:F3A44B0F53DCC9F79E1AFA8ABB022C84:\
+0000000000000000000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:6E47C47F3940D369EC703E974AB350B6:\
+0000000000000000000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:1100DE2A57C47C2EB63277537ADE5716:\
+0000000000000000000000000000000000000000000000000000000000000001
+
+# From the NESSIE submission
+01010101010101010101010101010101:EFB2C7DD69614683DAB0BC607036C425:\
+01010101010101010101010101010101
+
+02020202020202020202020202020202:A1AE9D211867538B100BD121BA6A3ADC:\
+02020202020202020202020202020202
+
+03030303030303030303030303030303:8E77797CEC40C34AD3A3230975AE760E:\
+03030303030303030303030303030303
+
+04040404040404040404040404040404:91086B2221C3FC8E254A97B611D83239:\
+04040404040404040404040404040404
+
+05050505050505050505050505050505:95CA7F3CA2269A73B4964BD7A6A3DEA0:\
+05050505050505050505050505050505
+
+06060606060606060606060606060606:BD7EB1B707AA5F801070B9C94F64A5C6:\
+06060606060606060606060606060606
+
+07070707070707070707070707070707:37CE0ADCFAA89DD737CB15193DCBA48E:\
+07070707070707070707070707070707
+
+08080808080808080808080808080808:37B6051557E2E535EE8B4955AC5DCB82:\
+08080808080808080808080808080808
+
+09090909090909090909090909090909:33D6A06EB3B16C0C6078BF56F2966AB2:\
+09090909090909090909090909090909
+
+0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A:521D3B74BA74D29362708CFE62E357AB:\
+0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A
+
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B:CDD5D57C2ABED59CEACAA9352103751F:\
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C:173D2D1CABD12095742C3045EC50899A:\
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+
+0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D:A85D680132CCF78F2918A9698D6431D6:\
+0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D
+
+0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E:C8137067650576081E34565121681374:\
+0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E
+
+0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F:EDC375FEF71B83B2BE5187F82D0180EA:\
+0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
+
+10101010101010101010101010101010:54FD2A83F505EE40F4F6F4F94198ED48:\
+10101010101010101010101010101010
+
+11111111111111111111111111111111:10CC2D64A5306366D8D594B8CDB4FBD3:\
+11111111111111111111111111111111
+
+12121212121212121212121212121212:13E3A82E121BC3CCA5C703FCAC451E22:\
+12121212121212121212121212121212
+
+13131313131313131313131313131313:1D8753BFF6930FA77FD7819F5935C422:\
+13131313131313131313131313131313
+
+14141414141414141414141414141414:A6FF617A5D0395407BEEC3A311A0CBCB:\
+14141414141414141414141414141414
+
+15151515151515151515151515151515:034D4716AC68312E05C9497E9FC9430A:\
+15151515151515151515151515151515
+
+16161616161616161616161616161616:690D68007F51E2E8C9516EF9EE64F85D:\
+16161616161616161616161616161616
+
+17171717171717171717171717171717:EF1396B41E8AF9BD6B2EBDEB7CC1A91B:\
+17171717171717171717171717171717
+
+18181818181818181818181818181818:9A20B52BFC5EB501F027978FBD684A1B:\
+18181818181818181818181818181818
+
+19191919191919191919191919191919:7A1A35FAD281601D522188B546CE1800:\
+19191919191919191919191919191919
+
+1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A:F715BBB8000B577E6EF5D698511E8D03:\
+1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A
+
+1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B:09E83FD6F11C656ACAA1D1FAAF02F086:\
+1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+
+1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C:41561B53A60A9FBB25304169789461BB:\
+1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
+
+1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D:B47BB77008C75F854861994479DA3E7B:\
+1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D
+
+1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E:811CE0CFEB49117D6ED593FBFD5E6CD6:\
+1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E
+
+1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F:C9479F831ECEBCFCB91F99FD6379A962:\
+1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F
+
+20202020202020202020202020202020:FF2C70AB530B889BFF5F3C902DE6209A:\
+20202020202020202020202020202020
+
+21212121212121212121212121212121:695A8754A7A6F18C4F3C6EE9CE0EA103:\
+21212121212121212121212121212121
+
+22222222222222222222222222222222:2E2DFBB0C8BD286E87625F61A2F7D887:\
+22222222222222222222222222222222
+
+23232323232323232323232323232323:CE8E66F871157B0182653B625074CB02:\
+23232323232323232323232323232323
+
+24242424242424242424242424242424:C32823388E5ADBD6AA14186CE0400A4E:\
+24242424242424242424242424242424
+
+25252525252525252525252525252525:EDEA3E4740736BC47A7891609B86CE9E:\
+25252525252525252525252525252525
+
+26262626262626262626262626262626:2B2DDCA5AD969636475196D462F5B2A5:\
+26262626262626262626262626262626
+
+27272727272727272727272727272727:5C46E5F8DD4E7DC61474CB8DFC3E04F0:\
+27272727272727272727272727272727
+
+28282828282828282828282828282828:6670EBB8C7E041121C5C5E449B675FD2:\
+28282828282828282828282828282828
+
+29292929292929292929292929292929:808DC7740040F39A6D3CBFAAC5228A23:\
+29292929292929292929292929292929
+
+2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A:15ECD6020C001F45262A1256AF7B066D:\
+2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A
+
+2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B:C937773A54DC09B0CC52756A7EEEF178:\
+2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B
+
+2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C:B8AB07101FC58ED64BBE203F31F892D4:\
+2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C
+
+2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D:FC429A3B703812E0AAD1A325A23E33DE:\
+2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+
+2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E:C4FFFE21B89FFCC6EC721D49E870ECEC:\
+2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E
+
+2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F:D218CB13BC19296A50B5612A3721C1E2:\
+2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F
+
+30303030303030303030303030303030:573FF72784A1CEBD97FED191A3B979EF:\
+30303030303030303030303030303030
+
+31313131313131313131313131313131:4D44F703C1E1C39C3A2EDF5639394702:\
+31313131313131313131313131313131
+
+32323232323232323232323232323232:50F09502DB7FCF0095E5F8219DCA5A3C:\
+32323232323232323232323232323232
+
+33333333333333333333333333333333:9533F79F724484B169CB32EB7FAD0168:\
+33333333333333333333333333333333
+
+34343434343434343434343434343434:9EB8075BAB79DD8BBF7ECAD69C6B13CE:\
+34343434343434343434343434343434
+
+35353535353535353535353535353535:E5450816410E771677D879F0A6ED86BD:\
+35353535353535353535353535353535
+
+36363636363636363636363636363636:07B20FB465C2F4FABC042A07E3163DEA:\
+36363636363636363636363636363636
+
+37373737373737373737373737373737:26B4CFBE7FDB3B3253E9F5D499DAD6C0:\
+37373737373737373737373737373737
+
+38383838383838383838383838383838:4FD4E8956C0808613A5EA19A9D753800:\
+38383838383838383838383838383838
+
+39393939393939393939393939393939:FA74B3A2F745D440E74851D1C0D8679B:\
+39393939393939393939393939393939
+
+3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A:9D6FC40588769E07EC406A0CEBEC99F2:\
+3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A
+
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B:53602388866685FC37681EBC9BC46F73:\
+3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B
+
+3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C:AB4532B652BDD0FC8ED4034CF3C11A24:\
+3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C
+
+3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D:66EFBCE5A3C3795A50C1A6B999CC3E71:\
+3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D
+
+3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E:1CAC1DEB42C55E3A3FEB261ED2FB3F50:\
+3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E
+
+3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F:31D98EA0E6B439432C3A6BB8E25D600D:\
+3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+
+40404040404040404040404040404040:898FD889A6AA36447C89D8CCC8B4043A:\
+40404040404040404040404040404040
+
+41414141414141414141414141414141:AA74AA28D307802D28EDF73B58BD3BA3:\
+41414141414141414141414141414141
+
+42424242424242424242424242424242:57F1920F30A23C74DA3CD9CF78F4328C:\
+42424242424242424242424242424242
+
+43434343434343434343434343434343:2C30C357FB5A8F9D531CE0F17E1286F3:\
+43434343434343434343434343434343
+
+44444444444444444444444444444444:C6E5EB2B3F9A7744A0128B93A4145A7B:\
+44444444444444444444444444444444
+
+45454545454545454545454545454545:0DBF0AD86C57F7D25A0CE61F6A6148EE:\
+45454545454545454545454545454545
+
+46464646464646464646464646464646:5F64A9BC4359153FF2572195A12F52D3:\
+46464646464646464646464646464646
+
+47474747474747474747474747474747:B6099EE04520977CB7B1DE88E2120FA1:\
+47474747474747474747474747474747
+
+48484848484848484848484848484848:77AE144A7A3883038561F239C5312F09:\
+48484848484848484848484848484848
+
+49494949494949494949494949494949:DF0FE7423AA1CF40C8FD45253817FE33:\
+49494949494949494949494949494949
+
+4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A:CE4E05EC0EE20A8A4B27937B7B8ECED4:\
+4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A
+
+4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B:BAB91404D49876BEE288311BA3C7456A:\
+4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B
+
+4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C:9DC6BCB030F1FBC24ADBF6EA5238E507:\
+4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C
+
+4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D:BFACD02D59B26640B80B1886CD6E7D03:\
+4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D
+
+4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E:2076B2B836A8C545B3C103050E7AFF41:\
+4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E
+
+4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F:653B5B9A9751451C89DF56D79CFD07EF:\
+4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F
+
+50505050505050505050505050505050:7F4060C7776DEED87F7F9B26BEAFA428:\
+50505050505050505050505050505050
+
+51515151515151515151515151515151:B7072058AEF8AA25604ACE1531C81C59:\
+51515151515151515151515151515151
+
+52525252525252525252525252525252:40A0515E8F01E55C60F70E0DAE4A1D31:\
+52525252525252525252525252525252
+
+53535353535353535353535353535353:9805BD832CBCBEE6B439D866F3ED53F9:\
+53535353535353535353535353535353
+
+54545454545454545454545454545454:81334B63525932E8B9342094A8DBB917:\
+54545454545454545454545454545454
+
+55555555555555555555555555555555:59670A6CBA2E729FEDD36389481541A4:\
+55555555555555555555555555555555
+
+56565656565656565656565656565656:84B3279AE90EACB5BF863DC17AE9212E:\
+56565656565656565656565656565656
+
+57575757575757575757575757575757:13F3BDFA7EF33A97F496692361AE6167:\
+57575757575757575757575757575757
+
+58585858585858585858585858585858:080F06D07DC2B4D0B748FA9F28946B0C:\
+58585858585858585858585858585858
+
+59595959595959595959595959595959:72B8521961C711E79AA30616F0B70687:\
+59595959595959595959595959595959
+
+5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A:75082BB9C98676FBB964DBDCD25705A2:\
+5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+
+5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B:C00D2666ED3FAF0F01FEEB01A9883B1B:\
+5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B
+
+5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C:C70DBF746F722EBC18A4F4B115193ED4:\
+5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C
+
+5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D:6283561914D3FABEE1FDD1747515C2D4:\
+5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D
+
+5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E:7AAABB3AE21BBA557AE89A0D9B99816C:\
+5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E
+
+5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F:4010AB7D9F7237DE123450ECA31B0900:\
+5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F
+
+60606060606060606060606060606060:3E4B358F1A26A197BF3B65B0DB4FB7E5:\
+60606060606060606060606060606060
+
+61616161616161616161616161616161:2E9D9D04453C0698FB444CFA3340E0B8:\
+61616161616161616161616161616161
+
+62626262626262626262626262626262:99ABC39983649030A48BAEDA6E718E8A:\
+62626262626262626262626262626262
+
+63636363636363636363636363636363:39478E48FACF3E28870082DFB51A817B:\
+63636363636363636363636363636363
+
+64646464646464646464646464646464:1BCA5B87AFEB4D9090910E02E3040CFD:\
+64646464646464646464646464646464
+
+65656565656565656565656565656565:30B0F7101370BB69E7B20D13050AB876:\
+65656565656565656565656565656565
+
+66666666666666666666666666666666:CC000CAA9DEB82E9766CD98B9DE131DE:\
+66666666666666666666666666666666
+
+67676767676767676767676767676767:AEDA25322DEA94FA8345FD467992B1D8:\
+67676767676767676767676767676767
+
+68686868686868686868686868686868:14D0D8253551FC65B1DE9DB1C3F0AB6A:\
+68686868686868686868686868686868
+
+69696969696969696969696969696969:67D32FDC0CD1AAC1F20E3F5FDFC986C0:\
+69696969696969696969696969696969
+
+6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A:3D8101226BBB3F4FFD40E68EF5F93626:\
+6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A
+
+6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B:684F017186FCC8AC24342CC54BF2FA6C:\
+6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B
+
+6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C:4AD0F6751D4DE121269F0FCCD99EFE68:\
+6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+
+6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D:FDF357681BD91A83E2632698C1525CE0:\
+6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D
+
+6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E:AC2698CD31DE9AC9740F53D467902FCB:\
+6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E
+
+6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F:ED011F6CD9356CBA1E4715D60AB112A6:\
+6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F
+
+70707070707070707070707070707070:724926624439B1C8694571BC103CFCED:\
+70707070707070707070707070707070
+
+71717171717171717171717171717171:C2725BBB0E4945AF08A6A7F1A9AF211A:\
+71717171717171717171717171717171
+
+72727272727272727272727272727272:0ABD84E7FF8FD3F826B4AFBE3AF2B653:\
+72727272727272727272727272727272
+
+73737373737373737373737373737373:404BEFC70C072CAEE758CC3E697E946D:\
+73737373737373737373737373737373
+
+74747474747474747474747474747474:0106FFAEE3A63E7B80004B044F864032:\
+74747474747474747474747474747474
+
+75757575757575757575757575757575:AE43C4368B1FC9B98DB952887C4316B1:\
+75757575757575757575757575757575
+
+76767676767676767676767676767676:FAC2FD894C5AEBC38A45034F38D44075:\
+76767676767676767676767676767676
+
+77777777777777777777777777777777:09831AB86A3DF171F1961A8E9F40BDD0:\
+77777777777777777777777777777777
+
+78787878787878787878787878787878:DFC3FE2EC8C90B113BB11F76F3636E3D:\
+78787878787878787878787878787878
+
+79797979797979797979797979797979:E9B9BB30C6D86061FA1812FF08CBC65A:\
+79797979797979797979797979797979
+
+7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A:0FC606C92CCFE70FEDAAE3DB6C443762:\
+7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A
+
+7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B:85DEC6534601D8B6B11B9060C8A42DF2:\
+7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B
+
+7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C:1250BEB80BC3D145284DF9188CCA5C50:\
+7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C
+
+7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D:318E30C9CCEBCA2A7F546A49052AF9A4:\
+7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D
+
+7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E:49FCFE05AEF655D83155DB617ED581BA:\
+7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+
+7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F:91EF1DED08B8BC59A916B5739195C758:\
+7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F
+
+80808080808080808080808080808080:B5BCEC5D9EC2161530284CD96653C250:\
+80808080808080808080808080808080
+
+81818181818181818181818181818181:3B26ABD6B5688159301921809DF64FB1:\
+81818181818181818181818181818181
+
+82828282828282828282828282828282:DAEA518A364BC404EEDD6903474BB56D:\
+82828282828282828282828282828282
+
+83838383838383838383838383838383:37C8EBDBCE1501AAD18A395AAADCB415:\
+83838383838383838383838383838383
+
+84848484848484848484848484848484:399FB3321F29829924CE72FBE9ED2756:\
+84848484848484848484848484848484
+
+85858585858585858585858585858585:A88E685E95E838E27AC3024370BFE12F:\
+85858585858585858585858585858585
+
+86868686868686868686868686868686:4C56F71EC80909EC98673D808F42321E:\
+86868686868686868686868686868686
+
+87878787878787878787878787878787:4EFA656E3F35C570C8DC4EA5524B436C:\
+87878787878787878787878787878787
+
+88888888888888888888888888888888:808FA06393685AB9143C82CA4B954BE4:\
+88888888888888888888888888888888
+
+89898989898989898989898989898989:D107696CCF562B2CC2901D50E1BFE320:\
+89898989898989898989898989898989
+
+8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A:98CF296ACAFAF704D6C91D1997202E47:\
+8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A
+
+8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B:5A023E5B18861A1FFCCC26F487EBF80F:\
+8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B
+
+8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C:8570554F91C1D8366FF6EC2097F110C3:\
+8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C
+
+8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D:E1CE24B74C513C884992C98DFCF70BFB:\
+8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D
+
+8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E:23F536F1876F44FFB7727D0FAF9F2D70:\
+8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E
+
+8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F:D877DD242B0C7CC05D9600419385A3EF:\
+8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F
+
+90909090909090909090909090909090:2896226A5A298578E2C999AF4F382DE7:\
+90909090909090909090909090909090
+
+91919191919191919191919191919191:B54F6E5FB8F33608A8DFAEAD8EF27B98:\
+91919191919191919191919191919191
+
+92929292929292929292929292929292:45CF4F783116E562F104B107BD3D10F3:\
+92929292929292929292929292929292
+
+93939393939393939393939393939393:93F404FF83D493315E2E9665AC2013C5:\
+93939393939393939393939393939393
+
+94949494949494949494949494949494:1A5664813121482F4DBE1026104D84A8:\
+94949494949494949494949494949494
+
+95959595959595959595959595959595:AEE4A82CE2FF23E91A497269B82530F6:\
+95959595959595959595959595959595
+
+96969696969696969696969696969696:E001B8A93500C4D49F8A9A372A1E8A61:\
+96969696969696969696969696969696
+
+97979797979797979797979797979797:FB23B31999D3D84AFD55600B9EA722CD:\
+97979797979797979797979797979797
+
+98989898989898989898989898989898:9572170C51A1198373B6ADBAB87AE454:\
+98989898989898989898989898989898
+
+99999999999999999999999999999999:65CCAA1321D8CB3CA18462C37DBBE4E1:\
+99999999999999999999999999999999
+
+9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A:3E942B1978B989CAC106E4575E6729A7:\
+9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A
+
+9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B:3E9AA5B6EC22E250368E9806041F6AA2:\
+9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B
+
+9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C:717479032B7D79C5236436D8AE0F3AB5:\
+9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C
+
+9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D:2643B168C234D5E0205E212C5CF669F4:\
+9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D
+
+9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E:A79DE0F9F3BE54CF4B453A1836F7F491:\
+9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E
+
+9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F:CF0836AC18F99D130EE85DE0ACDBE063:\
+9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F
+
+A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0:F12ABC04BB0C7F6F794EF428E57F15FA:\
+A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0
+
+A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1:383E9B4B9D663B8527E6FAB4A7892832:\
+A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1
+
+A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2:432103C74F3C2D68315CDD2831EF8F71:\
+A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+
+A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3:E06519949E2F6E8B00E15CD58054BB4A:\
+A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3
+
+A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4:34A14A8B9E5869C25A9C604300BEC911:\
+A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4
+
+A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5:0FB01A7B7F093C400E2FB08E709F7675:\
+A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5
+
+A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6:51D28B7FDD1C3EA5ED21EBD1D8B7499D:\
+A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6
+
+A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7:3F6FCB543C8771ABFABDD72E0E788FD7:\
+A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7
+
+A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8:045A187E0A7009AB426A78B251CA088E:\
+A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8
+
+A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9:BF28504290089DB7D289785147BD5D9A:\
+A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9
+
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:1297E67DBA4B264248FCDAF3B9E3FE4B:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+ABABABABABABABABABABABABABABABAB:8177E1C48AB5578DBB3C4AA36EEEEF5C:\
+ABABABABABABABABABABABABABABABAB
+
+ACACACACACACACACACACACACACACACAC:97E785AED832ACF1D419DC01219704D4:\
+ACACACACACACACACACACACACACACACAC
+
+ADADADADADADADADADADADADADADADAD:23D059447EDB76B0F9B41006399CC087:\
+ADADADADADADADADADADADADADADADAD
+
+AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE:7320A4A66FE238B9E1A932F9942DCFAA:\
+AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE
+
+AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF:4D8D7376C26FE0AFAA27B61ED1882721:\
+AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF
+
+B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0:DEF37D094186DE7209801C7D2D93F61A:\
+B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0
+
+B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1:536A8AACDB1156AC2E2D7DD0499BFA5F:\
+B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1
+
+B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2:F57A2E78B976A57642DC8BFAFB3480B2:\
+B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2
+
+B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3:88177315699E7AE0D5B4B07046ED5990:\
+B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3
+
+B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4:02F65559B9AA547A5EA54EB6A8E48960:\
+B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+
+B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5:F2F02BC7D56F7594E37DB7DF94C1B9C1:\
+B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5
+
+B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6:2691BEACD805DC3C69B0295A7308CFD8:\
+B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6
+
+B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7:A3A67B09425720C8AAB79DA8F44A8E8A:\
+B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7
+
+B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8:DBC7ABF1DD510B5D3A6BA898670B6361:\
+B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8
+
+B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9:FA1B51E10654E448C32EFCD7A986CAF0:\
+B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9
+
+BABABABABABABABABABABABABABABABA:C63D856771FC45E5102B14B41A79CB7E:\
+BABABABABABABABABABABABABABABABA
+
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB:9030C8326D2B75D1979DC1C3B80796B9:\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+
+BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC:B11A41E18A535F8F3B343135C73A4670:\
+BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC
+
+BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD:BC6F04C2D75634E0054CCE755DE717A7:\
+BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+
+BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE:AAFAD1353CD8C6469751190678362F03:\
+BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE
+
+BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF:9DD8ACCD8D2A504AAE205BAD997F20DE:\
+BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF
+
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0:0FCBA053A6E5DE5D0E6B9395BDE2BD18:\
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0
+
+C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1:E3AD2507E0F6BCDCC3D50728E12BF962:\
+C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1
+
+C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2:0AB51BDC22FFF1458CB4D3D08EDB164C:\
+C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2
+
+C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3:FBF3371047AB698FCFC81442B134AD26:\
+C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3
+
+C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4:D026FC11B7B1BB47B020D7A8320A174B:\
+C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4
+
+C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5:FAE26B00CAD7DD254EDBB84688A846E9:\
+C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5
+
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6:91F547F8129DB5B465DF57F0A03E58FE:\
+C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+
+C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7:AECA4D2C88D33F6A0CEAE619259E3982:\
+C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7
+
+C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8:32AAB72FE2809153140156909B52F414:\
+C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8
+
+C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9:91EDBD3465D1216B3564F094455F0ECC:\
+C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9
+
+CACACACACACACACACACACACACACACACA:4D14F0124000E96F09938906B99415BA:\
+CACACACACACACACACACACACACACACACA
+
+CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB:297F6B5BF3A01B1D87B7B74DF4E9DC2F:\
+CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB
+
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC:BCCE55DCAFF6BB7B4D0CAFD112E87FCD:\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD:D7A1E8E4624689000AD7AFB06982D8FE:\
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD
+
+CECECECECECECECECECECECECECECECE:D59DAF6299A27A5DE36F7090B777673F:\
+CECECECECECECECECECECECECECECECE
+
+CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF:A5ACE3553FB387187CCFF88C3DEE1ED7:\
+CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+
+D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0:2CCF6DD6EBEE7C4A4C5586EBF792AC57:\
+D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0
+
+D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1:695849E45DE312A07C5E8A6C1C20D6B8:\
+D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1
+
+D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2:5E14D156D004D484E040C354F13A8F63:\
+D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2
+
+D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3:E4CD1852605EDC0FF576A8310FED4883:\
+D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3
+
+D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4:BC7EB0533C90715C314362B1FBDC3545:\
+D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4
+
+D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5:AFBDF9336F9CAC06313181937FF1849E:\
+D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5
+
+D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6:B590131983C4E266BDE99D577C493B67:\
+D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6
+
+D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7:90921A3641666DE025E42B1BDC891FBA:\
+D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7
+
+D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8:E3B79B1EC3FA41E7EB3C575ED197588D:\
+D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+
+D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9:5D9B53924BFCB123BEF8F3C5431103F2:\
+D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9
+
+DADADADADADADADADADADADADADADADA:12BB6C3773F42D7AB2BD711C3DA6B1F9:\
+DADADADADADADADADADADADADADADADA
+
+DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB:A0D2449463DDB310E0D4D0B547043FA0:\
+DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB
+
+DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC:B1E70695E833951DA0C4B38CDA067ACD:\
+DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC
+
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD:19AA0D4A04DD8C93935FCB3F39A0D2CD:\
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+
+DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE:98E4BAC98E4B1559B07E3A323D352964:\
+DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE
+
+DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF:4B88F29F1DCB339CEF6C80EF949272BA:\
+DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF
+
+E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0:8F3C7931AC39D8B62C643BB3AC2C731B:\
+E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0
+
+E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1:D620AC385CAA42FD228176995C7EEC61:\
+E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+
+E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2:D99A20E342818B37A21C87F35C19D559:\
+E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2
+
+E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3:0817FC31D13725B3F64790470C883F22:\
+E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3
+
+E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4:945FE4DAEEE2AAA1EFE80022311B1040:\
+E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4
+
+E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5:F5976BFF2CE360F3A75CACB10B1B26E6:\
+E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5
+
+E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6:4D7118A0D1DE4AB7E43765B2E2AE0EE2:\
+E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6
+
+E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7:FC428DC79787BBAC03937C6C0FEDA673:\
+E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7
+
+E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8:6DF3580C31F389C898CC905582BCD920:\
+E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8
+
+E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9:6B74DC42605029718F4D0C060547CC8B:\
+E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9
+
+EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA:B587D402AA54E60DB655B4164847ACA1:\
+EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+
+EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB:16313A473EFCB6D965C5F1426785B472:\
+EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB
+
+ECECECECECECECECECECECECECECECEC:734356F14E8A6C5775A4638BBDFCE111:\
+ECECECECECECECECECECECECECECECEC
+
+EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED:F66FFD7385B4A87A9E2865D70864DAA6:\
+EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED
+
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:FB7FA84127D218FDE6A24CA30379ECCC:\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+
+EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF:4FADBE831B78D6B3C59DCE8B4293BB79:\
+EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF
+
+F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0:DA219657EA1AB63EA46306C2D0B69186:\
+F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0
+
+F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1:34BE2E9CB3C4047884CB291416D037C7:\
+F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1
+
+F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2:384BAAE4DB758555E2DB6E2995E0CAEC:\
+F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2
+
+F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3:7338107A3D9BF3E8C67936E1CB77A22A:\
+F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+
+F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4:217BC7820BB5A9183D95BF7E99180B87:\
+F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4
+
+F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5:56BA9C916AECDC51203CB6BA5FEE8D3B:\
+F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5
+
+F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6:8CCA87B86BEB5CCD11A594F20AD5D1B8:\
+F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6
+
+F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7:CD0230DBA2982BE4F126FB2E80AB2C24:\
+F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7
+
+F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8:A3E46629CF9D1D6DD1A6DE82B86C5934:\
+F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8
+
+F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9:AE18D7C35968E90CECA036CF586EB963:\
+F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9
+
+FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA:3B0261B9DA91346FAD84DD9CC9EC4A37:\
+FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA
+
+FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB:9F3E91301511409E1F997A080F9A9424:\
+FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB
+
+FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC:F1BF5CCE9A7D5FBE759A579640348692:\
+FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+
+FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD:D192CBC80E653C12C647C1EBEB56AE10:\
+FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD
+
+FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE:64F5B3E91B4CC3C35AFB6793FCEC836A:\
+FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE
+
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:EFB109978422E50FDCB05335D050D0D7:\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+
+# From "The RC6 Block Cipher" v1.1 - August 20, 1998
+00000000000000000000000000000000:6CD61BCB190B30384E8A3F168690AE82:\
+000000000000000000000000000000000000000000000000
+
+02132435465768798A9BACBDCEDFE0F1:688329D019E505041E52E92AF95291D4:\
+0123456789ABCDEF0112233445566778899AABBCCDDEEFF0
+
+00000000000000000000000000000000:8F5FBD0510D15FA893FA3FDA6E857EC2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02132435465768798A9BACBDCEDFE0F1:C8241816F0D7E48920AD16A1674E5D48:\
+0123456789ABCDEF0112233445566778899AABBCCDDEEFF01032547698BADCFE
+
+[SAFER-SK(10)]
+A0A1A2A3A4A5A6A7:41246B65F1DC6AFA:01020304050607080000000000000000
+A0A1A2A3A4A5A6A7:5CBD77B03626FE3B:00000000000000000102030405060708
+9091929394959697:9EAA4DF1E0EFF445:00000000000000010000000000000001
+98999A9B9C9D9E9F:4CC14838399E532D:00000000000000010000000000000001
+B9BA26C1B67F9692:75AF0AEF94E54122:053D79C5CFC7E2A3244F888CB0336DBF
+382395FB04EA1FD6:8162DBDC5984CAD0:438C2106DD87C2A0741F66A28D75A962
+0C07884F2D4B7645:64C8047DEBBE6895:8A5CB47F29F8B1C79EFDDC95EAA8DA2A
+FD8CD3214D56917A:3360F9F4A25D0D5A:885588FCDBDDF30BDD55D6AD097594A7
+D2A9B8F6A027F02A:D750587CC46CF3B7:D020D65E6FEF3C7FD60413E04C71F8B1
+18AC5F07FCF872E7:557368277E129BE6:228A5CFEF727066B2E682DC8E40CD629
+4438471711225573:B75E4C4155A67C4F:360495E7E4784CAA34E42C12F125B71A
+5ED88B627B5C899D:B356A077F9DB11DC:850F94815381C03111F45EFEE704AB48
+
+# From RFC 4269; the first vector also matches the one given in the
+# PDF "Test Vectors for Modified SEED", from
+# http://www.kisa.or.kr/seed/seed_eng.html
+[SEED]
+000102030405060708090A0B0C0D0E0F:5EBAC6E0054E166819AFF1CC6D346CDB:\
+00000000000000000000000000000000
+
+00000000000000000000000000000000:C11F22F20140505084483597E4370F43:\
+000102030405060708090A0B0C0D0E0F
+
+83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:\
+4706480851E61BE85D74BFB3FD956185
+
+B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:\
+28DBC3BC49FFD87DCFA509B11D422BE7
+
+[Serpent]
+D29D576FCEA3A3A7ED9099F29273D78E:B2288B968AE8B08648D1CE9606FD992D:\
+00000000000000000000000000000000
+
+2D62A890CEA3A3A7ED9099F29273D78E:717EB02EB81A2E939D54ACA91087112D:\
+00000000000000000000000000000000
+
+D29D576F315C5C58ED9099F29273D78E:0D809C5EE82F477EBA7B956DBB23463B:\
+00000000000000000000000000000000
+
+2D62A890315C5C58ED9099F29273D78E:0F0190D616F5294112FFB7884E8B37F9:\
+00000000000000000000000000000000
+
+D29D576FCEA3A3A7126F660D9273D78E:41BA1B505386B7428B88338188F7E718:\
+00000000000000000000000000000000
+
+2D62A890CEA3A3A7126F660D9273D78E:A3348230BF5CFA552F88D22463D9703A:\
+00000000000000000000000000000000
+
+D29D576F315C5C58126F660D9273D78E:115351622E016BCA26918D17E13225F6:\
+00000000000000000000000000000000
+
+2D62A890315C5C58126F660D9273D78E:7EE4E3F2C46FE52ECBDA044C585717DC:\
+00000000000000000000000000000000
+
+D29D576FCEA3A3A7ED9099F26D8C2871:563A8403FF5309D62370B1DCF5A11EDD:\
+00000000000000000000000000000000
+
+2D62A890CEA3A3A7ED9099F26D8C2871:2F7D73602B70CD2553E44C1D3F170126:\
+00000000000000000000000000000000
+
+D29D576F315C5C58ED9099F26D8C2871:155BBD9BE3A965B345E834718F651CEF:\
+00000000000000000000000000000000
+
+2D62A890315C5C58ED9099F26D8C2871:6CC65E8C5C566E894817350F497816F1:\
+00000000000000000000000000000000
+
+D29D576FCEA3A3A7126F660D6D8C2871:EEFA51FC91FEBB6E9F8CB141CC0EB6AF:\
+00000000000000000000000000000000
+
+2D62A890CEA3A3A7126F660D6D8C2871:3C6F8380CBD3C996167F2F0E90E71B75:\
+00000000000000000000000000000000
+
+D29D576F315C5C58126F660D6D8C2871:6C87EB62A4975356B28DCBF6A64A0BD1:\
+00000000000000000000000000000000
+
+2D62A890315C5C58126F660D6D8C2871:07206D48FE6DBE19D50314B90AC87B83:\
+00000000000000000000000000000000
+
+AA26D561F567520E8AE47528C24C18D7:35706F9B26007071AD8105CFAA1C1E2F:\
+00000000000000000000000000000000
+
+31A2193D9A97FED6922B17AAA6372B74:F7FEAE5CEC4D11477F24E6B200906870:\
+00000000000000000000000000000000
+
+BE5DEBD559E303C9C92B174A5107BBFE:3C0E29E2950F2AC2DACD63DEEB5C7EFA:\
+00000000000000000000000000000000
+
+B626D8F65EDCCDF3AEE475C8A1837722:9FDB9F3B740563D5518287DC981FC9CB:\
+00000000000000000000000000000000
+
+41DDE7C1F1631F5FDED4F42746471BD6:46D4B5A5A86FEC08FE70D18297DCF510:\
+00000000000000000000000000000000
+
+51D238BA86176EFE39E4695AAEB73B52:72DDBE038DA040EBB12C509F5940A212:\
+00000000000000000000000000000000
+
+EA5926CADAD8018962E469BA920CB8BF:DDEB59F02132BE4581FC23EABAA960D6:\
+00000000000000000000000000000000
+
+1EA9062E4D9CEDD5FAD4F4C7990367A4:341D9352E36DFD6E4EAF0F6F439BC8CE:\
+00000000000000000000000000000000
+
+B966E5C5D2277288C61B96A559CC84AF:73A9AB3164FF30350F2DC08E939A104D:\
+00000000000000000000000000000000
+
+B6A6583C5AACFCD6212B0BD8AEF3C6A9:6DF0C2C28F8E2D44468A61278BB6B429:\
+00000000000000000000000000000000
+
+A11DDBD175639341052B0B384678D8D9:4DAE45AE0CAA032FC97CD4D8C57FB83B:\
+00000000000000000000000000000000
+
+352299B71DD880E29D1B96452DB86540:BA8AFCAE22070BC882D3A42B38A09E65:\
+00000000000000000000000000000000
+
+6E5D67CBD2233FD96DD4E85519F8C8FF:BC787554E0C28FE2787025A98E0E09F0:\
+00000000000000000000000000000000
+
+15E936EA422C6CFE751B8AD79DB36621:86B80E7CB3786BCA23C7124354EA541B:\
+00000000000000000000000000000000
+
+CED9A660F5589101511B8A37464C94C9:27F18C72F85905209F5603255B3F4DDD:\
+00000000000000000000000000000000
+
+5992083E0D98A0C436D4E8B529F8C568:EDD2E4CF5B93C4312E5ED4F052C37897:\
+00000000000000000000000000000000
+
+C8069CA67710BEB0973E53F6CF83F5B8:BBAE1F0CD912C15C0D6D531272BE5CDC:\
+00000000000000000000000000000000
+
+209715348597D7935E59FCCDF462573A:538D750947CCE6E77C30A12732210008:\
+00000000000000000000000000000000
+
+F55F291D8B1A23EBBC59744F266F0AF0:DEF3EBA592B3C325CBE4422B28708AE9:\
+00000000000000000000000000000000
+
+B5F454770B8E202D32B69CF3C519564C:8629BE92247614A971C111CBAAC07503:\
+00000000000000000000000000000000
+
+91447D195D011E605F6AD3EDD4FC375F:D591160C54C6980F2FB1289A290FB8C5:\
+00000000000000000000000000000000
+
+39D8DFB5BFAE1EFD70243FA5C3592FD2:DD4E7DF8A2D94C073CE393A5D8F3BCC3:\
+00000000000000000000000000000000
+
+80ADA9A56ED30915F209FC358BD23B13:16EA9B34329DEC0DC264A89531096063:\
+00000000000000000000000000000000
+
+B762E58E9BC97C5B493EF8528DF0817D:81DDE46038411A21D84C46437D655E3C:\
+00000000000000000000000000000000
+
+4163A1972ED201DBF666AB3F1506F316:E3D84AE8D29F438C93FD6F09A7E93E9B:\
+00000000000000000000000000000000
+
+A429DB53BB101C18DCC2E4A1E6CC9F76:EA5A252DFD300488151DFBF42E0E0BDC:\
+00000000000000000000000000000000
+
+D9E13DD7B37EE0096808CC1D4222E646:BE5932C7D8D87A02A6638ADECCFC10B0:\
+00000000000000000000000000000000
+
+4190EB60B88C95F231EC6D7E20CCD8BF:D511BB2C012F08F1DB69B6CEC7BEC9A7:\
+00000000000000000000000000000000
+
+1591F916E4E78577C46B226D0BFF2D18:4FA2AE41F506315E9D47F1538CBBF7DC:\
+00000000000000000000000000000000
+
+2A112D319CADD403DED8F45A858A5864:BA00755699ECBE4DE4F507C11495880A:\
+00000000000000000000000000000000
+
+65A3B7F6A32DB892F14275DD6934953D:EB81259E6EEC5F63DD0B3A4D7A304369:\
+00000000000000000000000000000000
+
+AFB47A94B46DD4070782C7778D0BCAEB:CBDF5E6AA6C4D2D2112C5DA41BF7A998:\
+00000000000000000000000000000000
+
+040F6C0CCF32860A3659483242B7938A:B80F05173C3009141E435A54787D9B11:\
+00000000000000000000000000000000
+
+783C76251AB9E2AF1A7AAE0C103F7022:A4B00C8DE27F64FAE825F68446414CFF:\
+00000000000000000000000000000000
+
+B4CE06347BCC27D88D8F9517511489BA:9EC055EC16A197AAC35C42DAF73EFDC5:\
+00000000000000000000000000000000
+
+1D5F46424382FC14A88D11101713EC27:6D6EAAAADDD78F048D5DE03ADF132344:\
+00000000000000000000000000000000
+
+A7D01D3962F7EE0506ABB0CB05BE3CFD:A29C8E4D019EFD52F5B3A924F78283FB:\
+00000000000000000000000000000000
+
+DF77E42579E404C59D1F2D6282742AA8:21CA94A86C4B89E7D6A31A47EF13153C:\
+00000000000000000000000000000000
+
+7C94C333B3129977B82B602FC6C34DBE:54765313C008E10DE032EF1CAADBA78D:\
+00000000000000000000000000000000
+
+65930D441118388F839C48E87B3E1BA7:52929868115B6062648DE05D79EB026F:\
+00000000000000000000000000000000
+
+33CA3DE47EFBC84D7FE3F5232F61FECF:49CBD717BD816CC9875BBC3F53C47FEB:\
+00000000000000000000000000000000
+
+B4FE9AA29F6DEE99AAA46C6570C7EE94:8F4F803A44EEFB7322536211C9345763:\
+00000000000000000000000000000000
+
+68BE8C46506743BF1B3C8A8826A4A609:6695C1F06CD1B4F465741F4518024AAA:\
+00000000000000000000000000000000
+
+1CC8D6A3BE440FE4405E60C5318EA5C9:BE03C9515368E75890EC686BFE2FF646:\
+00000000000000000000000000000000
+
+D00215D6061EA7A71E11B75A1D26430D:C3E2D4D0E8D0B41C30C8D87C13A49AD3:\
+00000000000000000000000000000000
+
+CDF77148A39069E3BCF653FCE49366C9:4DF17345CF351AA676DD7B49938F7A52:\
+00000000000000000000000000000000
+
+0F99BD50EDF7302DD7856AB5D615ED28:0172427A635F7D98BE4918C5AE2CB716:\
+00000000000000000000000000000000
+
+66B77651ECF45BA521AD382EF3924728:794179D58EA6DBE6C47789543EE4C942:\
+00000000000000000000000000000000
+
+447D7F32776EBC002D2D5BF157B65831:96FFDD0C7A8B148E2A56D23613001F07:\
+00000000000000000000000000000000
+
+2AAB6D16B7D60DCE7F04B82155F24D84:FA241459469101FB4BCEACE6B5400592:\
+00000000000000000000000000000000
+
+E58BB7447F6D10E7A004FBBA0191E9F1:F3789C8F92D55B6F6AA2F15DA3E3360D:\
+00000000000000000000000000000000
+
+DE491798D0F7C403EA23C5BE065ACA64:240734AB5298B82E77547C5598D78F9B:\
+00000000000000000000000000000000
+
+B7E4DFC5707B8BD443C44E60CA4FB33A:C987AE5A52023829ADECAB587EEC9FF7:\
+00000000000000000000000000000000
+
+0F697B4EBA007B17E87D34AA5820BABE:D4F00A5171634F670D9A66641FF418C3:\
+00000000000000000000000000000000
+
+B202A50E105E4C16EFB7E3CEB213D8B9:CEDEA26248AD109772F8FA6CE6840C10:\
+00000000000000000000000000000000
+
+E5F9ED7FE679B4BB49F6CAF8423F4847:BB0CCA155A25E4506AA2872023E3DD42:\
+00000000000000000000000000000000
+
+0EF0B59EE379CF782DF0B241FA0A481C:1558C66C18CDD1BF7FEABC12CA775765:\
+00000000000000000000000000000000
+
+01297B97E8BA8CC43663B8F0587515CF:B9126AD2C22415E0D1DD0C46DFF4FACA:\
+00000000000000000000000000000000
+
+04489483EC2124D4CE0C0D3532104B7E:3EA18AB75E496036A5B39C799223A40C:\
+00000000000000000000000000000000
+
+2CB4E6700F324861F2675CF83D3E46E4:2F2599FCE02040B2B6511E6E0CCC4FF6:\
+00000000000000000000000000000000
+
+79A4343D86C34E6F7FEA9F653E9510E2:9790DFE1ACA13EC9AD806E92925AC60A:\
+00000000000000000000000000000000
+
+C48B333E3A297E4F078917922EB4112C:789BE31FE49273B1B9D23F3266E4E3D4:\
+00000000000000000000000000000000
+
+8972CCBADC5B0506545466096C1D681B:E6B883BF48E1D41DBD59C5A1A5CF0D37:\
+00000000000000000000000000000000
+
+07237CA5F80AFE75C531A1AC3C1AB011:C01C0D59B22FAD158C64FB7D9EB947E2:\
+00000000000000000000000000000000
+
+530FA49A50BEBC8DF5B6551AD9DEA834:4839197697C73DBFFE1EFFA41418F1A8:\
+00000000000000000000000000000000
+
+A37E6DCFD78A9367E0FD779EADD0E662:AD630EB9AC6CEBB004DB1FD6F7498CA1:\
+00000000000000000000000000000000
+
+39B126834F71A6094145AE2C544C99D5:CF5F4208B97871A91F63C34E008E515F:\
+00000000000000000000000000000000
+
+21C00D004653C7C46A48DBD99C58D420:11F9C2167F6C6151B1BD5BE2FBF8F415:\
+00000000000000000000000000000000
+
+1D18D1F2EA9B2175E26F4BBBC6482EC0:C239C8DA7E469B1B360DE30B20CA948C:\
+00000000000000000000000000000000
+
+2248571B13111E356A35583A346B533A:813394500C7B0A98B09360729C4C8990:\
+00000000000000000000000000000000
+
+AC4E8230E1608BC860D3B15CCC3368F6:4C6E93F6A3D8FB4A0B0A84BCABFBA324:\
+00000000000000000000000000000000
+
+9ABFF385FB69343F3155F005D1596C9B:50F442C56402B11FD9D1FB3BD13363BA:\
+00000000000000000000000000000000
+
+52BD6F4E00AF26D08C240999EE8FC068:348D5F27D16C2716257F3AAA15283D5C:\
+00000000000000000000000000000000
+
+E13E6BEC7B8EF6A26CF9EEFFFCB4BB8D:80048BF39DBBCBC3E5F11B523AF6E0AD:\
+00000000000000000000000000000000
+
+5D4DDF9DFD43D9F269875972C5FDCCFE:F68CF795EE3094B23F312CDF347C4024:\
+00000000000000000000000000000000
+
+C921BF10C4CAB3382CE78D35AEF5F36E:89009C9DB4733E7141FDB3212A412A55:\
+00000000000000000000000000000000
+
+0EE30D5BA455F2105A1383E5234B25D6:3A5732BFCACCA7BCAE28BA212E2AE4CA:\
+00000000000000000000000000000000
+
+7F30A307539BAF2BFA49E502F5FDB8C8:4D5F7C864D5A976FE623661D16CBEB36:\
+00000000000000000000000000000000
+
+53DC7D23C91E3A3A993DDA2812406581:C93A2A92366C3C68E968814ED86B9EB3:\
+00000000000000000000000000000000
+
+DBED8AB859453434ACB9E9F00CC077F7:D57191D7507746469BE9F27BAF5341D9:\
+00000000000000000000000000000000
+
+6EE7D04DE056DBEBF6F76D646F5DDDE9:09E07FD8F84AE4909724703908D45358:\
+00000000000000000000000000000000
+
+FAEE35C526B6D55284C50EA16B64BE75:52B5F265E0896C74F9A56962DD186EBF:\
+00000000000000000000000000000000
+
+D1705E0D4414A331C698D0B5E7989F36:3BC372D47BB6298CE06DFE595B21AA6C:\
+00000000000000000000000000000000
+
+FB1B87236E1B410800F4DEE6ECD1B475:EA0BB90C4B1DCB1D3A558FDEB539094F:\
+00000000000000000000000000000000
+
+4DAAE23B2D96FA15733F64DD467B7B0B:FF9A1304937373A6BA1281A6C98A68A2:\
+00000000000000000000000000000000
+
+0F61F575FD7CB6AC4EBC7E71D0F829BC:296A56189308CC6225FE28975AFF009E:\
+00000000000000000000000000000000
+
+6D982DF029336B52CE5366EA1F707506:DE7FF6D41A3E69D6C21237C11BF41744:\
+00000000000000000000000000000000
+
+D5D957B00EF19E7AE697F7BCA7766EE3:FFB2D4E3F9E2EF13969C8C885499D568:\
+00000000000000000000000000000000
+
+FD18E498687DFBEFB5067ECFF123767A:0DAE1FDF0C4BDD0C39F7B920AE9A5A5A:\
+00000000000000000000000000000000
+
+2F147D418659A6B46C6720090BC853AF:EF325356C760D3469E780E8E9F1A4C44:\
+00000000000000000000000000000000
+
+F5BD9A33B96599C94EFD295F22197D8E:D49C47B7CDEE3C8DA1FD9706B9FD1EC4:\
+00000000000000000000000000000000
+
+7D1929516793AC62EB5667DF9230E7B7:916A025A18196132AEFF32BF23E56808:\
+00000000000000000000000000000000
+
+F6F185D1D9E5EF5E681B4E184FC803F0:3DCECA80A345D536020E821D67A4C42F:\
+00000000000000000000000000000000
+
+8DCF813E1D32B6A462980606D5DA6C25:FD658AD24B0381E823217B2CF21F41E4:\
+00000000000000000000000000000000
+
+311E5045D5D9FB6A9D65BE54391CEE38:98A92CBF1276C729261107A77511A3B5:\
+00000000000000000000000000000000
+
+DB40EFC568A20FF65ACB58D46A0089AE:DAE0F812A9360561FE22DC8AB7F308BF:\
+00000000000000000000000000000000
+
+3FBAD200F06A92BAB275AA0FB972FDD5:D024879EC26117A5C5B46447F3462520:\
+00000000000000000000000000000000
+
+20DC7FDC121EAFE9084B3B6A223DAFCC:578341CB5831659ACA48B684404B45A0:\
+00000000000000000000000000000000
+
+3B07F74CD998A7CCE14E4FC9D427E7B3:6E776DF83149BE88CB7C3C3E85C52F1B:\
+00000000000000000000000000000000
+
+6469947C896B34C73AED82A38EFD7F42:C29EC8D5E338F0F928A86D7BA58CFEA9:\
+00000000000000000000000000000000
+
+D26A6C2DEC69974265FF4452ED78F9AC:2F9F52D492D6694BD8D660CD7EF25D08:\
+00000000000000000000000000000000
+
+392B09B430F1BBEF1806301374D5491C:0D5DA605AA771221251247CE79A2170A:\
+00000000000000000000000000000000
+
+51B13ED142E6753C3D22FBA60CD56D7A:CF1774242D11FD50D33651BA798DC586:\
+00000000000000000000000000000000
+
+F2CE749AE7D2A8E88E74EC43F50A6D83:7BF824A096D89F306543AC012F041ED8:\
+00000000000000000000000000000000
+
+48B1659A4894EF28ABD7A17E2BE14507:130F39B7C637E478E8D195DE909C98F9:\
+00000000000000000000000000000000
+
+2055A572782886EDC765497F6EED3860:A2E4F4E46D105904CFCC86C42E961ACD:\
+00000000000000000000000000000000
+
+BE4D786EA252B372FBEC796CA944218D:D252DAD9045BECD279C72E53CB32491E:\
+00000000000000000000000000000000
+
+AB720985752D3CED567366A2D66B5135:14D0B9D509F67CC6808B7CFCB64A180C:\
+00000000000000000000000000000000
+
+2990B16179DFF02E3BE5329204CCE071:941A767F37377743639DF4C048C28CC6:\
+00000000000000000000000000000000
+
+4AF02F69409FFFC5CD3E85912C68E384:26B7C40C96737897958DD86100F3B94D:\
+00000000000000000000000000000000
+
+D5D43ED9513ACC71CC0380B7394DF738:8693A664C7E7546C5A6E23EB2E71CF83:\
+00000000000000000000000000000000
+
+3B9BBA2992308915335F3FA0A0E12A7E:90DD602148161FFDE08D4983310DE0F2:\
+00000000000000000000000000000000
+
+3EABFE15DFA13C3AED5A235D9616573F:1ADFB865A7ED2B588BCD0C346AA75BCD:\
+00000000000000000000000000000000
+
+5357004733F6764F2495D7F602FD022A:F58BBA768C585C74583A71C7ADCBC5F6:\
+00000000000000000000000000000000
+
+C5A1B211FA6D99D16C222B19DBE89806:AFCDD53A8A91AB62D4CA3915C5564473:\
+00000000000000000000000000000000
+
+3E0995AD461831F731F5B5E8FAD4A32D:5FB04B5BA62C0DCDF8267567A166DEAD:\
+00000000000000000000000000000000
+
+AC411EBC593D98A7573F0B03D18AAC71:6FB6C6D44F2E2F8E8D0FE03E639CA510:\
+00000000000000000000000000000000
+
+CDD08D46B811A65FC48C34CE53C59273:869346200E0172F2EBE0FE696CA3206E:\
+00000000000000000000000000000000
+
+53DB8DD086EDC157FD32EAE98974E659:1CD6CF6FBFEB98FAC7DDCD894374B66B:\
+00000000000000000000000000000000
+
+BB380D75D07B8BD9A28F64D3F28FE126:646258E3B266E237572F050B7DD3C021:\
+00000000000000000000000000000000
+
+A8DA4DE3772765676DF3035C5A6834B8:E8B76AC77E9BFFAB29C56A12F57FE5E1:\
+00000000000000000000000000000000
+
+611E145BE9A042495037D07CE05A9C9D:717F5F9EC522FD63B46DE9A1F6CD3DFF:\
+00000000000000000000000000000000
+
+B9EDDBD7DF2571DE135FA8F59E6F5E89:7FB7A904184FC463C453BFF8BC72912C:\
+00000000000000000000000000000000
+
+BC70C6C532A9D8244AD957961652413E:C4AC50B64A9481062AEEA13B014A8C62:\
+00000000000000000000000000000000
+
+9A977CDD70FB7B78F3CA0075A7F310D5:E8EED73C37662A48C6CA2FE299C50CFD:\
+00000000000000000000000000000000
+
+CB1BDEEAC3B70C36FA65C5DF048EC7D6:5118E27A48630ECE2595DCE5C44DB8C1:\
+00000000000000000000000000000000
+
+17C72CA5E39979F512AB6011D12FFE7E:9C88B75ECB151EA0F1F4376C8B1B2897:\
+00000000000000000000000000000000
+
+B27637FDEE19BAB2EF984C20BEE9DDA1:053AECA22ABC1BAD69DF4A41457B7460:\
+00000000000000000000000000000000
+
+242243B52292ADDEEA14D6711A809279:EB1C28238D1B7612FDADC261D8456040:\
+00000000000000000000000000000000
+
+BCB05C0C37CE62E13718A4DC5D621759:BD3E796894AF2B24A2899615B76CE2FF:\
+00000000000000000000000000000000
+
+F1F023BA8CD1278324FDADDF3D445FB4:0339029B1DA61D7EE7B8B774163A3589:\
+00000000000000000000000000000000
+
+89459F7AA6ADD48B6E06AAF1AC94B488:6E460FEC45A03803F3F355C9DF9BE119:\
+00000000000000000000000000000000
+
+8C0EC9B97B507BEDC21F02E8618EF5D1:EA1C2DF3021D879FC96D43FD0E67D653:\
+00000000000000000000000000000000
+
+730E499138F578E5DD6896CD2415E278:237947AF67F07E80E0D2F3657BF80EF6:\
+00000000000000000000000000000000
+
+8747CD711F39542D3ECD9C3EF11EDFCC:F292F6D7289ABC04D56AB7EE165DADCF:\
+00000000000000000000000000000000
+
+EFDBAE4C02A4107E9BF71D14B380ED18:E44920E63171DCC895A0D26073ABC120:\
+00000000000000000000000000000000
+
+A32A5731115EBB36AB0EB2D0435B0CD2:DCE9D7EB5A29646CA29D017D84671F4C:\
+00000000000000000000000000000000
+
+648B7ADA19C5771CCDDE7D7FD8506C02:8BC336B3F819C5B95B5AB298AA5853A5:\
+00000000000000000000000000000000
+
+FDEFA249896CED942F1560A2AD3D139B:F2686F27FB99CCEF669DA54F90EB839D:\
+00000000000000000000000000000000
+
+4CE7F6748F7392F1FFC41F850E6BEB39:8D2143F8CE3DAE97CB36F9297ED0FAAF:\
+00000000000000000000000000000000
+
+289106867C6A9F0046AF56EA694382C2:CE37C384B398767AFA386F923116C295:\
+00000000000000000000000000000000
+
+E8389ADF540B748F3E9C8C553A9163BC:3B6CB9999BD604C41A6B979AFA58DDD5:\
+00000000000000000000000000000000
+
+90EBF973D07E55241F5D435A7582931D:EE539308E76F1F6202769E1BAE8105E3:\
+00000000000000000000000000000000
+
+DA1A98DE32FD428D031A411929DB7504:EEFDB3E1F832574F234D8129A2A7BECE:\
+00000000000000000000000000000000
+
+DB6E1AE2CA58D3BBE82C52BA78EB9132:FB0C6C046B6E469132FC1E6D6467D299:\
+00000000000000000000000000000000
+
+E218EEBE311B476B257DAAC37CB19BF5:069A62FA5C38E1C3F599E1F1D977ACDB:\
+00000000000000000000000000000000
+
+122E5E3D0F9787804FD260AED930EAAE:D62B5083A1A2B3E8B26D38E58875BC8B:\
+00000000000000000000000000000000
+
+6DDF3961CC91F485601683CB28355E6E:9ED29AA0A1F244935003BAE7951F90D8:\
+00000000000000000000000000000000
+
+4B5409AD15C3F64DDF4B4636E17C9EF0:E7E2B8F0E936B4A9C0749F814582D1F1:\
+00000000000000000000000000000000
+
+370AB733167272FCC2D30497CBBD3B18:0FE76FCA68F0E3CA774DA899A3423A81:\
+00000000000000000000000000000000
+
+51816B90928F39AE99B6B8E7158DBCF6:24C9CE99EDE5980D94CB0D93B3CE05DE:\
+00000000000000000000000000000000
+
+FB8CA3CCA3D18BD6D57B94CEDE433940:E07C63764F102CF1E1FE98068B97DBC3:\
+00000000000000000000000000000000
+
+9AA179B7064787F10A64C3CFC4ECE5FA:754FE2C1C97B5108164D0166CE7D71A8:\
+00000000000000000000000000000000
+
+18A7119DBF80C5C4BEE14716D5E69F7B:9A843E069C5564C071A941331A002905:\
+00000000000000000000000000000000
+
+0CF4DCA9009625FED6E6181CE2EE8612:1E1CA36CC5342007172C1261959768C4:\
+00000000000000000000000000000000
+
+FD53D3A5CF0AE84E6CD4F53336903AEB:F39D64F848DF16A5E6F3D03DC459A4DB:\
+00000000000000000000000000000000
+
+4190FAF3D1F5B836F34B6E0D786802B4:30243B37B0AA5D7143F3AEAB57BE46C2:\
+00000000000000000000000000000000
+
+E62ECCCF59A672463BCFBB384B5535C6:4CC047EF63B6D3CD41A5E2E2462570D1:\
+00000000000000000000000000000000
+
+AE41BD59502A0CC6DAE7E9421854F7C4:17892D8679C543B025EE84230BC8B8C2:\
+00000000000000000000000000000000
+
+8F094A8E5134FB06CC1E77D0542AE5F6:CFCD1A77DA12D6C79622EE61C4994F2F:\
+00000000000000000000000000000000
+
+B11E3D28143AF33E2151E20DC9EFDB23:A31237E0F2CB986413E3323557EA1C3A:\
+00000000000000000000000000000000
+
+E9637CE7F9CE8B647E560EEE8249B679:37F2B64F5FAA034E5A80C36E3D0A7AC6:\
+00000000000000000000000000000000
+
+D41B8500710948B58294F5A77391EC36:E12FB1156FCFF78FA862AAF199437E48:\
+00000000000000000000000000000000
+
+0AD9BB60CA674E99F7451383605E6112:A03BC6579A199A2F2E4CDC3353CAD7DF:\
+00000000000000000000000000000000
+
+87BA07D6AE903577E59674C3280D59B3:D2BF2C2DE6F8FD4F879D16F96948226B:\
+00000000000000000000000000000000
+
+92CD3EF1DF2102592B7B934E30971274:3CDC2CEAF4AD7A0E9973117B724136C8:\
+00000000000000000000000000000000
+
+CDC62C36124C52D43864CF072D664410:4B9581DAB0FA33AA0C458E0F33C8F641:\
+00000000000000000000000000000000
+
+A264DEC31ADDA880DB44D3D71C56F947:249D99A653422A9A01E5D6FC627883C9:\
+00000000000000000000000000000000
+
+683D38A1C9416EC1121A5B9853B80B07:0C576DEA6233A44810146E0ED3D91127:\
+00000000000000000000000000000000
+
+02E07632B8E1501FBED252B7491109B5:0AD78847637AD074B143DBA3ABF6A369:\
+00000000000000000000000000000000
+
+6075E57D9CF6038882173A7F1E0B6B3C:54470D4B79E9376E68202C84E7FFAA0E:\
+00000000000000000000000000000000
+
+FC44FFC49644133BA8F38B6B413F9B29:86BE58BB56E46A838E665A087D0AD1F9:\
+00000000000000000000000000000000
+
+51C42552F01FEFDA492F6AB73584850F:482DAB7D2E967D6C3311BB6EB2F31C81:\
+00000000000000000000000000000000
+
+10944915AACC670E23F4ED5CD98060B7:7C5F56D22104F4C73DE80EEF912CD774:\
+00000000000000000000000000000000
+
+2E712621DB2DE5988041135782E613AD:ECDA11FD5472CCB163AC8CA311A5DF73:\
+00000000000000000000000000000000
+
+0E3424038BC7047EDDDF0F3CB39F67CA:53E0F05DF0D4982708585E87D0789DBD:\
+00000000000000000000000000000000
+
+0D94BD2667DDF384170B7CC0B725AF75:996E17E32523578DFF2B760CB49FA31D:\
+00000000000000000000000000000000
+
+DD3E7CBFA877D46641F36CE6119D7CFF:DA019370BCEB7F587FB078D59A948891:\
+00000000000000000000000000000000
+
+42FE27B2956E244C76F1625F22A889B6:3117DFE6E8641573030640CB6F5A9556:\
+00000000000000000000000000000000
+
+2911CCE1311117276FB3B7DF33B55108:F0CCEFB7E412E3C83CCB1C16B275D840:\
+00000000000000000000000000000000
+
+07F139B45971C6A2840A87BC94715F51:44AC477F1E12DAC54F7D9F4AB4D597AE:\
+00000000000000000000000000000000
+
+CDF9F06DEB9BEC8B7D3FCAFEAF215E1A:36BD74FE0E68C6E4D791A526EEE0AF07:\
+00000000000000000000000000000000
+
+F9EDCF2F43AB9BF55BE12A50F1B96367:12E01CAE32687BFADAD694D2B52AAC7E:\
+00000000000000000000000000000000
+
+440233A437679347D8D7E98FC967C278:81F7C43030989F9D5B41E4FAD422EE1C:\
+00000000000000000000000000000000
+
+5BFD6EEDCA5FE8CD57348FFE1128E804:780F4FF8F6DBE3F2F48BC65F0E737831:\
+00000000000000000000000000000000
+
+D59500075A5D6F3412A6F4D6E70421A5:E2317139E45C8A5CF542745B79EB1E98:\
+00000000000000000000000000000000
+
+0B875ADEC58FBC95198C49C9F5FB1767:1CC7DBD69CFDF1108744C12D5B249684:\
+00000000000000000000000000000000
+
+56A7FF028345172C4C2447674C662509:ED35240E15DBE9E0A2F13BAE0471BDB9:\
+00000000000000000000000000000000
+
+A5612F7E740B3B66CEDD046F0A5A1A88:3E563E21742D0210553A9BBB356FAA24:\
+00000000000000000000000000000000
+
+BF49727B6A2B10E7708CCCD4BF24EDD5:33D2A385C1E5C675FCCBCEE0E43F1329:\
+00000000000000000000000000000000
+
+CECF03B03EBCFA19C00056E19495FFBF:F075312AA58C03DF583FA16E730FAF56:\
+00000000000000000000000000000000
+
+A7AF5CBE81D125FF604D583A50B8C00D:C4A6996A7F826F0D7126ECE1CF01E615:\
+00000000000000000000000000000000
+
+67F6C13577041F4BF64F47D4C87DD9B7:C1C4C033CBFAF73A2D0D477C2B32275E:\
+00000000000000000000000000000000
+
+FFD59439BD6B6C022AAB2F40C7ABB76D:E41211B5585A2E17881643C80B2521A3:\
+00000000000000000000000000000000
+
+489D934A474700C49AFA42309C44A29F:7E94137A70C5A5757ABB58977C753626:\
+00000000000000000000000000000000
+
+CC9D4E7E3A40D3E7B82D52FE59C15A28:C2DF7A7DCB4FA5E1BEC3FA0EC9FC06E1:\
+00000000000000000000000000000000
+
+5B94C5125C4DE35E5587A93708E2E748:CAF50E7CE7623CA7970473867D069C5C:\
+00000000000000000000000000000000
+
+79257DD42E664E92177DEF817CF86C93:F162F9C2E0AE24F10ADA56C3AB72C918:\
+00000000000000000000000000000000
+
+4C9FEFCBB009C651D19337B0DE1B71FF:8231DB207B117B719E2C18E35C8EDF61:\
+00000000000000000000000000000000
+
+5C17514070A79F2298252F43EB95240F:D6E1035BB55EFE63DAE750E874122D08:\
+00000000000000000000000000000000
+
+7587363E4FBAB6BAC0A96E2E301E2F9C:BF0E4C121F4D92ADC66A58850D87B336:\
+00000000000000000000000000000000
+
+2F34D0857475621D88F67B4AC932F63F:DC26468C5DB40EB9B69E2B968B6C9BBD:\
+00000000000000000000000000000000
+
+1CC86603D53675CCC0360A362D62AA13:C3C9DCCB758A317630FB54186BEBB710:\
+00000000000000000000000000000000
+
+13E024CF1C4EC5EC12DDFBE451462E9A:DC386958E72F8F51BC13191A5B34F3B4:\
+00000000000000000000000000000000
+
+C9537865387154E4FFA9600D3643ABDC:1305E15912CC66A2B376EAD51CC48648:\
+00000000000000000000000000000000
+
+A0B4CEE79237877C1431AD4CEA5CAD1A:074F192AC9EE825F569FD1674554C3C3:\
+00000000000000000000000000000000
+
+4CAE87180B737168FE61765A2C13F393:ACC37301367543AB4FBE6310858A68EE:\
+00000000000000000000000000000000
+
+73F66077FF86A53A528B7443D15DE894:32AFF7B87AE33CEA4539800A700510AA:\
+00000000000000000000000000000000
+
+CADC2699AB888BAA7C61ABF4CCDE097C:B4FBD33EA3006CCF44514E2DFD6E994D:\
+00000000000000000000000000000000
+
+F9A02333EC078EC9386949BEAEE3E77D:BB3D1AB3F206FE54EA92C9F452735F7F:\
+00000000000000000000000000000000
+
+592D7FC9A5D85637C46DC7A80EA0344B:AFBE7E97575E89299AFD84BB85AFA1DD:\
+00000000000000000000000000000000
+
+27585AF5E51E71F754FE0065C109896F:C15BFBA06F1BE380A4DB959AF9810676:\
+00000000000000000000000000000000
+
+B999BC62DE1F2703CDCCB873176B342C:DC91C862BB49B7D23A01A13C92E0F4BB:\
+00000000000000000000000000000000
+
+990FE45A78668A51DD3A2198DC94E8E8:97C3D586BFD3F6DE6F8F839F3CC9F9DE:\
+00000000000000000000000000000000
+
+E12074137236C60691EC10AE3AC3CEB8:787A51EA74E1060766D4728B07C3AE5E:\
+00000000000000000000000000000000
+
+B1AFE403781D9C75D2D10623D913BC55:241CF4705AED389F6B46D0AC8E797FE9:\
+00000000000000000000000000000000
+
+C25657A5D97B31F96BB7DE1442622248:D5811CC2D865EF53B64E5A7CF59C467C:\
+00000000000000000000000000000000
+
+2E8ADB82E854873F66B1DFC087318433:A09F4AA2E0E51767D051C1FC114E9D30:\
+00000000000000000000000000000000
+
+F68DA1B6489815BC440C3D897A0F853A:36AB29DB1A0E7B295D8F61A56526526A:\
+00000000000000000000000000000000
+
+18ACD883A6BD96CA32C7579981CAF789:92DD5D2080CF51484C93ADE891361EF5:\
+00000000000000000000000000000000
+
+B0C3AEA8F19EAFB8FD7E986EC6FA3266:4F207BFC5E10812C827B13777360E6AC:\
+00000000000000000000000000000000
+
+5E2D15D529FCE2A605E7CA372BD1B33B:C5E89179B2D955D740866AEA628F9C27:\
+00000000000000000000000000000000
+
+B6527DE3B567C10C10709CB44801789B:11E9B1353CCCDDFCCC63D14674F20709:\
+00000000000000000000000000000000
+
+6C7C9922FE4E48A3DC85D4672A5064E5:44C1528E8555388AF8B21E74078E9C15:\
+00000000000000000000000000000000
+
+BAA1457430B8D5D3BF7E12AE9BE3FDD0:3BB8312ACB386EC82150C59BE2CCED37:\
+00000000000000000000000000000000
+
+C210ECB8699792F39E7CCCBDB9671A24:90543622D6642AB3A24D7B31AD96152F:\
+00000000000000000000000000000000
+
+3DF1FF376D026324BB657FECA2A03AC5:CFA51C14006B922AAE044051BF4CC446:\
+00000000000000000000000000000000
+
+7470247B84F34BFE5B9F388FF30C7649:78FA69F113F617A4EF68699C28B6514E:\
+00000000000000000000000000000000
+
+E4413068106FE78F7C5BD3223AB22F9B:D8F8E4217C642BA8AE8A91D49DDD7A8E:\
+00000000000000000000000000000000
+
+95DCCB623977758D63621B6D6F9EE9EE:46FD7A6DE88C7607D9F2B0DE2CD366DC:\
+00000000000000000000000000000000
+
+92B11A8AE5474A5FA0969A4B205FF0FA:A4D66D791EE8D4894FDF61BEC36F9A77:\
+00000000000000000000000000000000
+
+81F5CA98D085E7F3EEB8B7EC9A7587D5:26E14F3BFC53B8247C829E29AAF36978:\
+00000000000000000000000000000000
+
+FCB53FCAFCD1B14ABBB8DDA290A295C4:B0DF814B15FB6F0AA321E44A322C8CDE:\
+00000000000000000000000000000000
+
+DEA998B86C1AE2AC866DBAB93AEF5AD1:1DA3F40C119AF23D85E434ACD90BCE50:\
+00000000000000000000000000000000
+
+0884D66B4E154E3CD5A13384A181F229:1DE817E7AFB8B87698C86285633027F6:\
+00000000000000000000000000000000
+
+65512F9F2F937A058172B0B255A67B67:8308565021CE65DA96CBEFABAFDB03E2:\
+00000000000000000000000000000000
+
+D166E04AB120B82AD72B63243F9857C3:C5D055C3792C34A2C0830F174EF60F4E:\
+00000000000000000000000000000000
+
+81B86BCD54B212E09D94ED7A6053D136:697642EE1D288AD0E0004F7CDE0D11B9:\
+00000000000000000000000000000000
+
+B27258323A5CB9997B729799B2DF709F:FC4F383D27CDA4AF3DE9962DE95A9C9A:\
+00000000000000000000000000000000
+
+BC9E6A0F55ABB6AC49F8A41B8F2DFFA2:34CBAF03126E517DE3F851A505A2995F:\
+00000000000000000000000000000000
+
+891E3708A695636C791A7954B2263075:08461134E1B40126FC24D3BF0DF1E743:\
+00000000000000000000000000000000
+
+FC48B079D9649987B24A15F9E0A3E00F:2BDD51F61CDEB752E07A4AD3AE3D7FBD:\
+00000000000000000000000000000000
+
+2034B9788B8AFAB21791389E1ABC01D9:658E89F1B0F1EC177855A8DA60EAE99F:\
+00000000000000000000000000000000
+
+F974D4DEE825FE43C97ECE434B4D2885:A0FB5361050AF4D2236AF62C0BC73D78:\
+00000000000000000000000000000000
+
+B611BBE6722CF09DB817A04B2E047909:FD6A9802E511A1C8D89447CBC18438D0:\
+00000000000000000000000000000000
+
+27212C758C0A0DA224131CECF3FCDD37:C47C31032D5D6E5D81634367B4AD06BE:\
+00000000000000000000000000000000
+
+595066C1FF549B917C318676A408DEDD:8FFAD5759EF79843A30BF236D3BC81E4:\
+00000000000000000000000000000000
+
+91A284663826FE81E6D615B870BC5EC6:9D5AE4A39CAC235A5E732761F2C33B10:\
+00000000000000000000000000000000
+
+BDA05A5C43C64FAD2F8D5D980AB8E682:9EEA78142CC9453D3589FDBABC2FDA68:\
+00000000000000000000000000000000
+
+840D3899332A3089F213B71356AB50F0:F8DC249385A0AD72AA2D7E2BE22C088C:\
+00000000000000000000000000000000
+
+6DDEAF850B8DE1D95B17538ED3B1257A:0D05DC4CF2879722AB30EC1C651F27CA:\
+00000000000000000000000000000000
+
+433CBB6339EFEF9C73AF53A947AF1695:0DE8E406EECEC22E6319E164C71EF908:\
+00000000000000000000000000000000
+
+1C437E29DCC4F4B06B7E3E35CB989CFC:B1661E31685AEC6E05A759E29BC8F221:\
+00000000000000000000000000000000
+
+9C3B693D9826980B8512C357CFDF1B41:2558229759A3A835E99B60F457BD9C23:\
+00000000000000000000000000000000
+
+C073EA45C292185CD446767F1E885C0B:BFB3FAA751C802F63A4E88D5B075EDFF:\
+00000000000000000000000000000000
+
+517ABC892B0F7E341D31952AD76B4F0F:8362B9BE129084442BADAB1E1937C661:\
+00000000000000000000000000000000
+
+BBC92940F2DAF0C3AEBF4187F57136A7:32A3B0F226F0442161FFFCE8B130EFFF:\
+00000000000000000000000000000000
+
+4DF202C89337B3476B725B6EA0854046:D398608144210678B768791182ED5A93:\
+00000000000000000000000000000000
+
+A53098F2C8BD8222D8D1B437344C5B30:263B4FFB812546C2547CF19EB0751289:\
+00000000000000000000000000000000
+
+A470D019D0A22DC6AD220E4CCEFBB6BE:03D99CD24B403EBAF4D56BFF5BF180D7:\
+00000000000000000000000000000000
+
+6E577625743EB0874AE21B8355CA0D81:0469204FD9B02B490E9B1CC4EFB4D83B:\
+00000000000000000000000000000000
+
+395EF2B04C035E1E966003CFE6599B1B:BDB2A2C17E50B034777A04E107264F31:\
+00000000000000000000000000000000
+
+7B07AC9AABE733D9865F2D1E586C40A4:2B0785EA30561102C79AF30C095ABE1D:\
+00000000000000000000000000000000
+
+51ABD478A711854204F64B6881F76852:C771AAB5D264A1E6E8AE7CC19F00D4E6:\
+00000000000000000000000000000000
+
+57DB85FDFA9DFD533A6987A3FAD322A7:CC388408802856093A6C11BE5290581F:\
+00000000000000000000000000000000
+
+C4E5BFB3E17AD60B5A5829014820B5C5:2E3269861EA631CDB2383C29D4D506A2:\
+00000000000000000000000000000000
+
+4829C08DBFB9059FF867E9DF9A703D27:D15BAB5E15235503A5D8C795C96CE704:\
+00000000000000000000000000000000
+
+2C4CEC15D7F8C6A4B240F67A33BDA4BB:21567729EA6C8DD3EC43DC715167C6CD:\
+00000000000000000000000000000000
+
+7AD911480D5819AC796825B394F59957:7822F4F8946068FFB9124EA563A8BF1F:\
+00000000000000000000000000000000
+
+423B4B359B1FB480187686E67A236B5B:B846A438131E0B4C5D239CAA95064058:\
+00000000000000000000000000000000
+
+7BC28B5D37150A879F378EF1BD7D1EA0:8469A91626AB6D5356BA6891919B61E3:\
+00000000000000000000000000000000
+
+CFEB7408AD592ED2D6C5A697EF23EF66:BE31A1248B97A5ADFF4B66C555B50402:\
+00000000000000000000000000000000
+
+EBDAB6F971A393F2F06DB086A48FA53F:7C729F296DBAC0EC710639A1B14D2222:\
+00000000000000000000000000000000
+
+2565D77254F3627F767EFB1CF14269DA:F0CF793A693B57EBBEDC7ECBE6472444:\
+00000000000000000000000000000000
+
+D1C2D5E6589B714A1945271DE12A81BA:B6DF513288A4DED5CE147BEF740FFAEF:\
+00000000000000000000000000000000
+
+3A4583DE24164F317C5A1A93B9305402:491D13F5238037889DEE07B607E21DC9:\
+00000000000000000000000000000000
+
+ACB28C12990D69408E6021499156CCF0:2156CCFA4FB525F384E4C73335189422:\
+00000000000000000000000000000000
+
+AEB020A13AB7ED94FBF69BE0AB407678:B2E8D35C8C0AE750A343AC9E64D11287:\
+00000000000000000000000000000000
+
+2D9F0E92AEBBA0117AD2C3287BA51187:DA6AD4DFE5884A1ECB2EB6BB95BD036F:\
+00000000000000000000000000000000
+
+55306BD6170500DBF2732E3FACF7C698:862B27C7CDEF0373E27E924BAA8552AE:\
+00000000000000000000000000000000
+
+79505474B2EDC21FCE061DA97167DC76:9E4193947309A7167ABE371B7051E049:\
+00000000000000000000000000000000
+
+73A093E22E3CB8671BA64C0EE14AC3CB:CCEFE03CE2EA144E50976F18BAF1B354:\
+00000000000000000000000000000000
+
+D0501BDB4D423F058D06D2105FEE293C:A4988B0B18EC938244DCB35C82BE3EED:\
+00000000000000000000000000000000
+
+023E136719CB97F52CDBEE3089394F62:AFF56FC36889B2EB49035F1218CD847E:\
+00000000000000000000000000000000
+
+48EC313A173DC1C99079251ADCE3B7D3:3ACB20C17A5FACAC7F1B1BBFAFAF3E30:\
+00000000000000000000000000000000
+
+2352B804B425F689995BB40A6FB33A04:A1DC974297F042A6ED4403AA5A344BCD:\
+00000000000000000000000000000000
+
+E61C4C2AE973E6D6AD1CFC376E369B98:BC67FEC8D78DBF170F5A646072911204:\
+00000000000000000000000000000000
+
+0571F553FC3559FE0B72598DCA3C8684:79A7DAB3EEB1A4F8C70CAB9D8AEF16CA:\
+00000000000000000000000000000000
+
+4B01043AE8459456522F50A67DBD752F:DDF39B3663B310031C90C5A8C366DD2F:\
+00000000000000000000000000000000
+
+C0793DC7F42F64CEA0FA90B9F95A8B2B:45579EC1B6FB2121C1943547FB846ABB:\
+00000000000000000000000000000000
+
+B8C74F4C943A9CAC6C9A78E1824EC318:F8A2465668526210660C10A140ADFBBE:\
+00000000000000000000000000000000
+
+EAB4FCD6326E0391BBAAB3C29527CDD9:ED54FF83DEBD9D4E2B4B6580FAA9DE09:\
+00000000000000000000000000000000
+
+470AFEF36697D24C06982FF4331AFF26:5EF558685DE9AA79856D7A7059FC48AF:\
+00000000000000000000000000000000
+
+350CD1B0E4AB2B41DBEAD22397F9272C:ED71E97B759F9A361D5893FA91A66AFD:\
+00000000000000000000000000000000
+
+B847B4B1DAC15B83B7E7CF4836742CB8:C7471FEAD8C9368076E47018C3033109:\
+00000000000000000000000000000000
+
+785115A2B6F073597A37DA4F2031C94D:33A86ABE68E69A42BE5565104833B20A:\
+00000000000000000000000000000000
+
+4B20B005906093B2C01D99473056A74B:5C7098151542379A4DE40DFC04C46D24:\
+00000000000000000000000000000000
+
+DFC6D2C78186F1BDD8A54CB2515837E6:6347D893780909693882E89D5D79263D:\
+00000000000000000000000000000000
+
+393A041CA6555C4A53AAE66B5AEA4200:14F25D790263B1364E9128E730ED5B1F:\
+00000000000000000000000000000000
+
+14DD5281E350E0805853C94BD9016AAC:6A3F4B41E35727F7A50CAC5F55A6AA56:\
+00000000000000000000000000000000
+
+21EC9D29F9CFCBD4981EF5C69A12F057:866EC808A008ABAACB5475763CA00AD7:\
+00000000000000000000000000000000
+
+9F2D5E03E6B12849107717FB1BC16025:018BDA98D7601F0531607DE8BB4CCF1B:\
+00000000000000000000000000000000
+
+160B4F410FF5EE520FC768FF484F21AA:C4B17C980D4D4718FAE5586B908D41D2:\
+00000000000000000000000000000000
+
+82DE5A5F07149CFE150905E6F9786AC1:3E824827A39B6219CFF1C3ED52CDCDD9:\
+00000000000000000000000000000000
+
+3E5DE770A898C7DD4120B0CE207CC089:50219CA05A510433481D6D12E36BD4D6:\
+00000000000000000000000000000000
+
+4E13E9B2E1CCFCA49DA3A6D8D85D5245:D44E0C864E5E538C2D1FB62E63512F69:\
+00000000000000000000000000000000
+
+B40580746E450E2E0EED4A9B7F104E83:D1EAA4CE78B40BEC8E505AFEB992B304:\
+00000000000000000000000000000000
+
+C48EE7B9A0AFA7519BB606968869DF17:7CEE0F216823CFEB5087DEE426BCDDEE:\
+00000000000000000000000000000000
+
+0E177D4B50286A120A5ECF0969AA069D:36011D7266887FD904C95921488512C8:\
+00000000000000000000000000000000
+
+BD0431A51ECBCB80220B3BBDB13B5732:F826B9EF289CABEFE753E90346D727B7:\
+00000000000000000000000000000000
+
+7D007D5A6A2F26680458BE5C345E08A8:E798CE8B9B0BDF637DB2D3162EA2D3AB:\
+00000000000000000000000000000000
+
+891DDB587CEEAE3F6F5F6D470C9667BB:CB09FA09ADBB747CB29EA2FF5E5C9792:\
+00000000000000000000000000000000
+
+AC95F9EBB80B0E5994E0BACEBDFFB56D:966D3A3B90FEDD37C2CD616304F90C81:\
+00000000000000000000000000000000
+
+CD723A1E9EBA8A9FB1D0F6D544953AAE:17294A27F2DB0F6501C95B669CF726AF:\
+00000000000000000000000000000000
+
+C3FF8EFA00F672EEFC63F752CBD7D136:1EC5F82A3F4F49A6E44557A9A8297EF6:\
+00000000000000000000000000000000
+
+8B4A66F04202B64A112D733F79A91CEF:E4DB812D84FF9B6B4314A21AA756F7E0:\
+00000000000000000000000000000000
+
+DA250D691E273D62227B024768962F1D:5886F7436189C242A9C422F0BB572EF1:\
+00000000000000000000000000000000
+
+F0BAB5E01B892AC144743983F6E8D566:B9528FD6EA14018AA38AB00009D10226:\
+00000000000000000000000000000000
+
+B89DC4BDB7D7F6757144960C86634754:0D19223B03ED7F99033160FF246C84E5:\
+00000000000000000000000000000000
+
+EBE504EC3BC160485B7CE65EA2A19785:880C1B4FFFD70736E8BD518ECE5B17EA:\
+00000000000000000000000000000000
+
+2FCD1A4986E31A98361B90B4E74E7475:930C22171DAD582B85CEED022AF43D16:\
+00000000000000000000000000000000
+
+14873B831B719DB9901CAB9FF563A851:2313DA90A38D6C59FEF0894DA350CF58:\
+00000000000000000000000000000000
+
+A473DA95CB0B4C244699D8DFB4C2DE8F:45DB7B9E5FCA9A440F530DFE85AF64BB:\
+00000000000000000000000000000000
+
+027A8941207C3630ACCF39EFB26A80A3:52C9F6F83608D31015D10CC7EF7C144D:\
+00000000000000000000000000000000
+
+33DE5CAC12F645367076B88306388990:7DAB9967790C06A87F33888372568FC7:\
+00000000000000000000000000000000
+
+92D8177CD2FCB399FCA7452284FC7748:43DE770DCD53EFEE430C76428474CBAA:\
+00000000000000000000000000000000
+
+DD201A0D1654D3483B8953F87D0E48C7:EF3E3A528E851DCD493DFD8F823E4364:\
+00000000000000000000000000000000
+
+DAE0E891214688020D99E6CD00DE4C01:347E7C0C421FE54A8C8CD27B8665321E:\
+00000000000000000000000000000000
+
+EA9BD3F71C846DCA01001F562E76989F:0B4E96149B5E626A93C975A402193846:\
+00000000000000000000000000000000
+
+3295F4905FD6722814D2933E226CDE48:71DC22BE06655F3B953379E3FE2B377E:\
+00000000000000000000000000000000
+
+5819F527AA6C571EE35EF99F05300881:97D6108F2679638278EF8C99C7A7FC06:\
+00000000000000000000000000000000
+
+00B34FCC58B29046CB519EDCE34A5BCB:123ECFFED7975F1FEC75D6EDB904E663:\
+00000000000000000000000000000000
+
+B6D79518E3D17CC84FA44C5F951834B7:A5950E42996C2C09567AF382325E23CC:\
+00000000000000000000000000000000
+
+25FBFAF468DEA60D982F23C50E6FD9FE:248DB0FFBC9F4501C122007BF395427F:\
+00000000000000000000000000000000
+
+21C0F5D729E9799FDDC7353568EC3FFD:4BD385DD0D2D3B9FA44AC799355355B7:\
+00000000000000000000000000000000
+
+C273D81BA6A15FAE72C08FC06BF95C1E:A52497BF1F74F58FBAB8B64431E8C3BE:\
+00000000000000000000000000000000
+
+395450944A685821818603DA1B9F1BC0:0E96C89302DC1981B90EA546DAD5FAA5:\
+00000000000000000000000000000000
+
+14616A135522A7C35B2534580606A204:97A1547D2C4668B3598ABA7865DBD33A:\
+00000000000000000000000000000000
+
+AE4F32993A77A53EA6687BFA3A83CFDA:817215D2F46916D13B5B6862CD13ECDD:\
+00000000000000000000000000000000
+
+86BA6D9579C903BB160A7A4AC18DBF31:909DFD858826F1F00CB6EEEB1CAF9DA8:\
+00000000000000000000000000000000
+
+6BE21799427582127E942B4D34461E04:5FFCD94BC401F32F827791EA980609F3:\
+00000000000000000000000000000000
+
+8496B480BF89717FD1819B0AA53CC33C:95BE56001901C98C595393455399F0D8:\
+00000000000000000000000000000000
+
+FA70BA75B820F851DF973160BFB07C9B:75259AA8E1AE7CDBF6AED6B3E068929D:\
+00000000000000000000000000000000
+
+00DFB0623FE65356B04FDDC1B28289D1:B87A487B4ADD0222754510189DBFEE89:\
+00000000000000000000000000000000
+
+AF4676B327402F8F6C61A047DCCD434F:852014F8BFC2BDD51F16CD8D083B0EF9:\
+00000000000000000000000000000000
+
+C6C342C67C699603ED3CDC5A7DE9BA55:C442DE6F7FC76EBDF529D198DAA68509:\
+00000000000000000000000000000000
+
+7902D25C9FA2A0A5932E4FC70BFC2C27:FC4326CAB1549370D95F9D4B0E8F85AD:\
+00000000000000000000000000000000
+
+BD681CF631503024FD6241A1F3BAE7F0:1B9C959CDF8AD16245264F5E4A9E319D:\
+00000000000000000000000000000000
+
+3503193D1F3252DFF9AC83311C763700:D07C6880E968DEBD2941C4FEF1D2251F:\
+00000000000000000000000000000000
+
+0492643AC9969F4460C1FC0804A4619F:D4E92987DEFF3CCCDE33C8B590122B6E:\
+00000000000000000000000000000000
+
+FA9A1D95EAEDB684909E9F683E69FCB9:108D34BC88CD8D59E8486FDF82FA62EF:\
+00000000000000000000000000000000
+
+22564DFD262798164A2939BFFDCEB281:06B77B0D8FDCDCC3586C1CA2502626ED:\
+00000000000000000000000000000000
+
+45F93E6EFA2EFD9A0C71EE9285EFA29D:2E2D5BB4037B2E2FDDA09D8BE9F4EAFB:\
+00000000000000000000000000000000
+
+806873410FD9DD61A715E277F08BA4C0:83F7323F69379CC15B75C23BF236221B:\
+00000000000000000000000000000000
+
+77F3A397DD6079EF077C2A8565AA980C:98EDDE96A3C905129A6D5E398AA9D73F:\
+00000000000000000000000000000000
+
+44F8CFB955F7171EFB8DEF067E2D673A:EC80B9B03CBEFBB70F33D3170C606671:\
+00000000000000000000000000000000
+
+AF94A4F2482B49FF677E75E559A3BC29:9B7F527280418569953F83AAA6D94800:\
+00000000000000000000000000000000
+
+54FD46CC08BEA6D09F4F8CCB2FE62864:C0CEFD5BE629252F9CF37C0EC16C1755:\
+00000000000000000000000000000000
+
+21BAC32D30F1DE944D1F5275FACEDF47:D0737904989C17ACD06A5F9A5DBD48EB:\
+00000000000000000000000000000000
+
+B1D9D5644A5D66BC8E51E5BF6E90E338:D8F948251535FCD67A0CDFB2F0E0258F:\
+00000000000000000000000000000000
+
+3B9C3639E11FAF597A40A8D13CCC27CB:5C144E59D0C09671EC3CAB5A0CE39392:\
+00000000000000000000000000000000
+
+AAD39B21BD9C45D92DD8B03F8ADF8295:063A2EB89956EEF09BC4A57DD23D6A77:\
+00000000000000000000000000000000
+
+198816B1AAC8BD77E416606A77DC6998:240AEA2F55274B8A80198B8758B733C1:\
+00000000000000000000000000000000
+
+612083F9D31C0AE6CDDFDE9E7421F1E5:21986590C1F285694603769D3AF6D7E0:\
+00000000000000000000000000000000
+
+C0EE1A1F02820CA8EBBFF11B78855C5C:77E8A31F8AA17DE52DA7CB0D1C0E61F2:\
+00000000000000000000000000000000
+
+57167699F08E77A6B075EA4D9988D384:6A3F8EDEE484A2C4CF375ECA4F0ABE8A:\
+00000000000000000000000000000000
+
+5C5B9F6DD482F121F6B7EDA76BC98D64:8043E71AAAB12504944BE7149558755A:\
+00000000000000000000000000000000
+
+9F7051BF58E623116C3A9982140AEFB5:F838E64CD3C5A8578246D5B6665004E0:\
+00000000000000000000000000000000
+
+EDE3AB4922717E465A2BB8BF98464CB0:863BDF8DB9344C685C6C25AF1D95537D:\
+00000000000000000000000000000000
+
+1DD33935C51869A29D6DC8B7B62DB731:6639463A8E9FF3EC2988D64C2791242E:\
+00000000000000000000000000000000
+
+181A77E8054E8180F503D0501B479A48:7A37ECBF8705A4D58576CAFFA4F4E7BB:\
+00000000000000000000000000000000
+
+58246965C1554A72E20BA7C61A52E3BE:18509EB535EB4CBF20026872A4F6862F:\
+00000000000000000000000000000000
+
+3FBC39E715EE2B54022D9FCB33E07995:3C80350C1EEE381E2069AC95ED8009A2:\
+00000000000000000000000000000000
+
+FA5BE2C6C03C878B520502B6D24FC80D:E0E69BE51245C8EDD65CC4CF714C9446:\
+00000000000000000000000000000000
+
+6C037028C56B4BA67FC37C32A8F9A80E:28B5349E4A4C92157BC0205A7F47C588:\
+00000000000000000000000000000000
+
+E9BA61E5B601690936348FC4258AC830:4CA1FE7B0A3E84E71C54DCCDBC606367:\
+00000000000000000000000000000000
+
+9435CBBF42A71716C4A74208CD0769D5:EA6043518C041C3AB12D14864D9B707B:\
+00000000000000000000000000000000
+
+7FFD7CF31F0E4B34FA6622E8DA4C6EBD:EAFF664EDE5BFA29021E0DB91EE522CC:\
+00000000000000000000000000000000
+
+5D995FEDC45CD61D83F1BB40DA911AB1:803BB0CDC8C8F63DF714BD906AFDCD10:\
+00000000000000000000000000000000
+
+216018840FF6B12272E6E9ABC014B037:2662B6DE572DFC8E654F528BCDC25B96:\
+00000000000000000000000000000000
+
+8A64E9D30422E7EB189885ABD947EB10:E41903DF1CC561A16EF2D1ACD8FC67DF:\
+00000000000000000000000000000000
+
+E8A317FAF7BA8191E4AE5DF588EFB0A4:6848773A5F6A0CB4014EBDD7243C626C:\
+00000000000000000000000000000000
+
+610A7A480A667E50ECC3921DC2487868:C353E8C4B8781BF0B38E5714F5D56D03:\
+00000000000000000000000000000000
+
+4DD3385F15F88D8E1D9FD368F550C7DA:DAAADFC4A39AC95A2A63CB17E0BEC906:\
+00000000000000000000000000000000
+
+6E5DD5F8B67658FC703EBC8048C8C99E:F5935C19F405DF2F9FC7FAFA93028DBE:\
+00000000000000000000000000000000
+
+6DA0C2E3B1E9852AF9F7F19707CBBC23:3AEFA41D48FC7B0A75EC269C1D5EC39D:\
+00000000000000000000000000000000
+
+DA49E4D68C12D599B55E9BF0DA4CB219:3AE5405F74A0A1BB9C587B535FA84068:\
+00000000000000000000000000000000
+
+F928FFEBA72BEDB77511765BDA6CD09B:71AFC5F59B95266F50DC494937A12423:\
+00000000000000000000000000000000
+
+2548AF21AEEF8DFE3FF04DDF8B5B405A:E5B7287515DE852442E24D983A492AFD:\
+00000000000000000000000000000000
+
+0DF7A17E3291AA86F4402E4FEEA5C611:C95A329A8D0C765919D8AC2658374D72:\
+00000000000000000000000000000000
+
+D82CD8AB2BCD70DAB76C334B62FD46DC:64042CE2997637FD2501FA2275D094E4:\
+00000000000000000000000000000000
+
+4B3AAC33855B8C2B67F298A99550066D:265D7119DC9EB745253F62C5B71E4BFF:\
+00000000000000000000000000000000
+
+EF4DFC627069CF6E4F90F6605B9D7A72:F1FCDB6D6922794847BD591B395A6803:\
+00000000000000000000000000000000
+
+4F401C4E26E5A7EBAEEB7C0B47CF770F:3381E7818CB696D62A72D3709296419B:\
+00000000000000000000000000000000
+
+CBCE84F167FC5EFB3E9FB589DA7DEA76:45B39802476C6AD971B70D6DEE9EC64E:\
+00000000000000000000000000000000
+
+429887390F9849375EA60D25BC41B4A6:4E5542591DD991B333CA1FA550368AE0:\
+00000000000000000000000000000000
+
+59CCBA357AED070D53E97C07432F3FF2:77DB690B1FD2149F4C61E6CEC1967FCB:\
+00000000000000000000000000000000
+
+F8B071CB7617A7AC837632B2E0393B47:20704383926600B03B22647D311A48E5:\
+00000000000000000000000000000000
+
+9C5E9C47A7DE9438906878A1969E556D:C9AD815DF2EE5D6705F53E5FB57C4A8B:\
+00000000000000000000000000000000
+
+335B50784CFBCF5EC5592470D8779CEA:A8D4489612DFED5F1E06A057DAC16D4E:\
+00000000000000000000000000000000
+
+D5D3BFD6E8DC346925D458768045E7FF:B8B48D5A3D41D025F4BB4D0590FD8AAD:\
+00000000000000000000000000000000
+
+06CFD19EB8ACA85331941A4C7F3BBF49:CEA1EB1D90A4CC5333EFB7EC0985278A:\
+00000000000000000000000000000000
+
+4BD937898ED831811FA7EFE0885E41F9:7FA882D5AB9253E40897D9A02F634B8B:\
+00000000000000000000000000000000
+
+64CC47590F6288969950876FAB92B506:E56FC52CB8680995DFCAC872C03198EB:\
+00000000000000000000000000000000
+
+6875E36276E349CFCB56DF8E8F3F3A77:831207645E69DCF55F2EB06E7920ACBA:\
+00000000000000000000000000000000
+
+5AB3E0CD4A7CCD85EB017E01D2A9E41C:1487AE58CD0547B8CDAC543ABD7A167F:\
+00000000000000000000000000000000
+
+D6194FB4E11083575F1A321B1DE7C36B:90FA45F0B592E717B7FE674FDEAFD09C:\
+00000000000000000000000000000000
+
+6B44AF3816BB543D52A72C8419247EC7:B27A4DC5B007C97A34A5A71E3F9948AA:\
+00000000000000000000000000000000
+
+0C34F5F71974696A870143913E300002:AD09BF00D24EE0B36CC244DD2BBD3416:\
+00000000000000000000000000000000
+
+9714F33B633228BD25873FDD8A748687:468D78EC6C9DB6331996A7148D7B8D0E:\
+00000000000000000000000000000000
+
+B655B88BDEE3C192CA7E94C115155400:E6FF459DABE888DF3B8E3B0A4E03CD1B:\
+00000000000000000000000000000000
+
+2E10337DDCC5AB4D9A47A7E11EE28819:5523C37014F6663C466549508680AD2B:\
+00000000000000000000000000000000
+
+91DC264E08F890E673DA508130B22132:1F5A4FBEE2294C1E9AD13226CA316C8B:\
+00000000000000000000000000000000
+
+5A961589B16BB11F43228C265A41F4F0:C41F0C276AF8840C1E40F7CDE2C9E703:\
+00000000000000000000000000000000
+
+9279B9E8010A5D5A636A690F480689C1:0C0FE02E45C512FCFBE86186077B880C:\
+00000000000000000000000000000000
+
+588FBCF959D31348507A315577077299:DADDB24A58CE1913C7E050BFBD6DB060:\
+00000000000000000000000000000000
+
+2B7D25F58492426C7ED9676A234DAA73:EC6F70F88767324589B114D49A3D0435:\
+00000000000000000000000000000000
+
+86265091666FA3CB492A6D0B89134FA7:1132BD6B7C2E314329B8C41B3591088F:\
+00000000000000000000000000000000
+
+1D930835D9E22CBB1DC2B32D760B5212:B0FDC9C797ADFC372A32C90E780A18AA:\
+00000000000000000000000000000000
+
+99488407CD0E84B85BD54A4208D9E74A:2D702A81CA33FC44E78423F7CA3579CC:\
+00000000000000000000000000000000
+
+2A2D29555BD65B655F4C351B6CA77F9F:AEAEA1C6D2752DEB743828BE4FD5164E:\
+00000000000000000000000000000000
+
+4130B6271FF1AC8B2E80D7358BC0010A:4A93D8F4A10503D03B61D028142B7317:\
+00000000000000000000000000000000
+
+78BBC849A8E335A3C50F03ACFDB40A0C:CFC2F763D9A43797D7B554B31818B00D:\
+00000000000000000000000000000000
+
+15F7DD0F5AAB45D18CE3FC22E2E0D7A7:B53C28497405CC58DB87E5B036D7A09F:\
+00000000000000000000000000000000
+
+B70975EBBFF142F85BF7A7C46FA969FD:B1F6FF9DA37954AC1CE21F87130DE8E9:\
+00000000000000000000000000000000
+
+682F741F13133286E864170D3423F016:406918CEB508D45A0BF1DAE0936AB561:\
+00000000000000000000000000000000
+
+3FA4581C08D59B03776031143357AC6B:27E92647DD1A9B830FACFB746A8EA4A3:\
+00000000000000000000000000000000
+
+D8BAEF6AC40C0656D5E9D99AB7F422F0:3BBB779C4310EC11923976AC5ADA20F2:\
+00000000000000000000000000000000
+
+18C8BFE83B9C5E73E17EA3CB0FFE35F3:31A3694FAA9166C155CF659E222B6CD8:\
+00000000000000000000000000000000
+
+02178D030AA8FB92095B8D773750BB29:1B56685208E68A64CB98C2EB8FD269E6:\
+00000000000000000000000000000000
+
+C4CFCF7F00A5890089F3E2E6D4A71B4A:33A0170AFE4B9054A68646C79D5F7E06:\
+00000000000000000000000000000000
+
+7B3DAD4BEC66EBEAEA116A09F1C7810E:34FA87844A31FEE5E4BC5A45B2025FFA:\
+00000000000000000000000000000000
+
+E6B59BD0BE313076624A7F27B431D394:A8FD8E9567EA205B33BA60B7FD3713F1:\
+00000000000000000000000000000000
+
+C806EDD853EABF4ABA609D2302B5A4A4:9FCEE6BAAA491D95905D114A21EA0586:\
+00000000000000000000000000000000
+
+530C29591F1EB65C53B66621D815294D:43C79D90E33D1D2B5790B515D202C79D:\
+00000000000000000000000000000000
+
+45480830977917AD000A73B062730761:D8FCA5649A8DDF403409C7B20E49EF30:\
+00000000000000000000000000000000
+
+3C73226C97B0B6A6F199C5B9EA4936F9:244CA0E37F5CA9ABAEF1E316016B0273:\
+00000000000000000000000000000000
+
+759A68CB477B3C4677B591E4490F6F66:DADC95A4CF085B656FB8A247270C6CBD:\
+00000000000000000000000000000000
+
+31295A526C3ABDEDA7CD2B4C4EAC18AF:D8FF5475210EB64CE418EBB062A2AC9C:\
+00000000000000000000000000000000
+
+90E6839484DB6BAB6ABD1A1C4B3F5097:E0B100775EBE4EE6CDE976AF97F7E67C:\
+00000000000000000000000000000000
+
+A77E0B16C5C8AC7DCAC28EF2A377C749:2326C55E35CB224F2916B76D25DAB006:\
+00000000000000000000000000000000
+
+473DE39D6CBED119488590D147A050DE:D45FE4E35DD7E7E8F9C1BE95A3E9AB99:\
+00000000000000000000000000000000
+
+8EDEBB741BE502D3D71F6EB76588D43D:6C85C0C1989880CD89519E5D0F24D2D4:\
+00000000000000000000000000000000
+
+BD77E505D265E0694E18F0DD27614AFC:95345EADB67814C36CB333178F1E6385:\
+00000000000000000000000000000000
+
+FFBDD477A86FA149AABF241A6875F2BF:F7978D6E572A04C5301B4784E96E85C5:\
+00000000000000000000000000000000
+
+878FD448E7DD0A988F3E14BA24A873C7:F5D13F5045698167AC816AD85D08CB68:\
+00000000000000000000000000000000
+
+4724D176D8301A560D9F629C43EF0631:CDCA92D92C0C13944D85AAF6342EE16C:\
+00000000000000000000000000000000
+
+92DDE5DCCF0B92737200C96A7FC2980C:984340AE315F1E35ED7B4D64E7C2109C:\
+00000000000000000000000000000000
+
+D0D5CDFD07003A970D866E9AEBCE49B2:D29523676BFF8722E8E7D4E27ECB7BDF:\
+00000000000000000000000000000000
+
+16D71101E006335AE4EA841B01EDF8EC:9DC42A4574CF4689B1A579B6058A72B1:\
+00000000000000000000000000000000
+
+57263798FAFFB2D1937ED13E9F75F6A6:63D7927C182B59693C7619502C7F09A6:\
+00000000000000000000000000000000
+
+1E06BC75D5473C2E2E214B794722D8EB:FF4445966B84099830C2C4AF3D16C2B3:\
+00000000000000000000000000000000
+
+5B0873294D3044BFC3547C58AA7EDFE4:293FE32A6E13E78417E60C2AC673E908:\
+00000000000000000000000000000000
+
+48B51CD888F14526A701EA3B7686A926:C600CE6D9925A7F29CBDEA5F86EB3968:\
+00000000000000000000000000000000
+
+54DD519813388689F773FA12DBF09E37:7988CC0311DB4DB779342F1CD9C69CB1:\
+00000000000000000000000000000000
+
+7DFC43D180470BFAB6970E619CDF4489:1E2BF65651E3D2F4FC43E6B8E60C2EDB:\
+00000000000000000000000000000000
+
+ED3A0A72AFD441AE48CA0E80F5CAFA99:BBC9EEC98F2F3EB38CE8C3A534AE08FC:\
+00000000000000000000000000000000
+
+9AA5D6C7CFA410FB74D753D3C329D5F6:C90111B9CB525A91F9EAFD987357934B:\
+00000000000000000000000000000000
+
+A254B55BE1A577D34CFAC4967C67E3EE:632D34BE39094B67B3A5CD0651294626:\
+00000000000000000000000000000000
+
+9FBE68B5013190B559D8488D1D18EEC3:E564E92FC5724970CAFE238F39498DA2:\
+00000000000000000000000000000000
+
+3D0E0B9BDC3613B8818CE559748EB180:E682F9AA990E90424FB62BEEB9A87669:\
+00000000000000000000000000000000
+
+23504A5F517D06CFBD6A6CD35A7C6F53:7B95F58B6C101AC54526A1C844D2233C:\
+00000000000000000000000000000000
+
+C3A79D45029979CAAE2B80944CB46381:1E067070C2DFE6FDA961250EBB0904DB:\
+00000000000000000000000000000000
+
+C47FCAC34AD3B94C3C14B1B05E4C4E8C:A661F602ED2B08E4A67605608AFC8485:\
+00000000000000000000000000000000
+
+30E235BBE9548847BC9FFFCB356DCAE5:B2E14131FF6A7043B944DD4C299F9AD6:\
+00000000000000000000000000000000
+
+309CECD7E237BF2BDA45F780B2106414:A2B8FF6B6A4F6C8AD3E5ACEAACE028E4:\
+00000000000000000000000000000000
+
+76D0AF5DF7E20CC6462A16826EB2A65C:58621016906E05D0644A1315F117707B:\
+00000000000000000000000000000000
+
+FE8372E4F0E4E733B16F7284C9928C2C:CD96F8F422D51EFB6451D1C8BC039464:\
+00000000000000000000000000000000
+
+B01E5DB74E62A0115812DD8CD93B8823:B2EAA3CA7F51B22456A9DA1DD31F63E4:\
+00000000000000000000000000000000
+
+2EE4409B33787E6C88625E25C66B693F:103044B5227E28AA2C33D537D69165CC:\
+00000000000000000000000000000000
+
+3F23DF226924DD9E3426035EFF30F285:4D9FDA109583D3611B560CBA61E4CC9B:\
+00000000000000000000000000000000
+
+96F02851CC614DE4560AD8DB80237601:104B264BA70B885E1BA6A8150EA83B1B:\
+00000000000000000000000000000000
+
+CA428A790029D7F4AD63E19CEAFABEB1:FF9D67EC4DD1ABB5ACD03567298F5A3D:\
+00000000000000000000000000000000
+
+F461D29B4120E93DA0E59C89A01CDFC1:6F3C9F8E5DC2D724436F3236C6616D33:\
+00000000000000000000000000000000
+
+654A6C8DC762FCA2B308F7CD8A8FB066:7ACAA703CDAA690F749A0BEB9E4B871B:\
+00000000000000000000000000000000
+
+B037B6F04D8F2F9478AB4A206EAAE041:DD3410E458F7F7B58EB1E491C39CDF84:\
+00000000000000000000000000000000
+
+641739E7AC8221F13A6430283CCA424D:279F7F9E6F090C5CAC5B17EAC662AD38:\
+00000000000000000000000000000000
+
+2634969CE81073EF9A69FE3B71936057:8061C87922DD5CDBD3AC6E37391F52C2:\
+00000000000000000000000000000000
+
+BBCFEC986F23B9697354BB39A8481DD5:EF453D6F902687D29B9C6AC8394F9229:\
+00000000000000000000000000000000
+
+DB2C55A7BB7D0C67BEBACFA60239FF5E:054788911085F32DE12FE3C0D6A2A5C7:\
+00000000000000000000000000000000
+
+4DDBE332134ECB725A9450E5BF5CB187:37F645A215E8350746108086F428F64A:\
+00000000000000000000000000000000
+
+256FDA74A1F7DDC78A0735AC5BF4B8EC:37F645A215E83507B9EF7F790BD709B5:\
+00000000000000000000000000000000
+
+496F0D60F09C3322F2AC1414CD32834C:37F645A2EA17CAF8B9EF7F790BD709B5:\
+00000000000000000000000000000000
+
+4DEBBD2461C99EDD3BB3C3CBF415DA07:C809BA5D15E8350746108086F428F64A:\
+00000000000000000000000000000000
+
+D1B3A0FCE628A7653B62E11724FF534F:C809BA5DEA17CAF8B9EF7F790BD709B5:\
+00000000000000000000000000000000
+
+DC77BDEC8DB018A61688F61EC5DA3F72:C809BA5D15E83507461080860BD709B5:\
+00000000000000000000000000000000
+
+6F878A0A25A34ADB37459BA9AA864169:C809BA5DEA17CAF846108086F428F64A:\
+00000000000000000000000000000000
+
+C97D56C65C479B6A3C98032FCB30D327:37F645A2EA17CAF8461080860BD709B5:\
+00000000000000000000000000000000
+
+CA7D368A299F613C8793C8B197C5B4AB:37F645A2EA17CAF8B9EF7F79F428F64A:\
+00000000000000000000000000000000
+
+C81B7DDC7F57D9D5E4782FDB7FF24DC3:C809BA5D15E83507B9EF7F79F428F64A:\
+00000000000000000000000000000000
+
+2ED61014612B71DED403559BAB7B3582:C809BA5D15E83507B9EF7F790BD709B5:\
+00000000000000000000000000000000
+
+75E6A753077E01A99AE22C1641FFCE50:C809BA5DEA17CAF8461080860BD709B5:\
+00000000000000000000000000000000
+
+B6405E813236600DC256134B92542CBE:37F645A215E83507461080860BD709B5:\
+00000000000000000000000000000000
+
+2009F95CF623369018B643B06C8E3012:37F645A2EA17CAF846108086F428F64A:\
+00000000000000000000000000000000
+
+7D03DB38DCE478EB8D3EF1E78C0388D5:37F645A215E83507B9EF7F79F428F64A:\
+00000000000000000000000000000000
+
+F9165467CB794721F028CBE1ADAD3183:C809BA5DEA17CAF8B9EF7F79F428F64A:\
+00000000000000000000000000000000
+
+D29D576FCEABA3A7ED9899F2927BD78E:130E353E1037C22405E8FAEFB2C3C3E9:\
+000000000000000000000000000000000000000000000000
+
+2D62A890CEABA3A7ED9899F2927BD78E:AA2F3365C15EBDC02F2C4468BCB4E950:\
+000000000000000000000000000000000000000000000000
+
+D29D576F31545C58ED9899F2927BD78E:1B4F0CF494AB7C5D850B8F88A025E5AF:\
+000000000000000000000000000000000000000000000000
+
+2D62A89031545C58ED9899F2927BD78E:B98DD45724870D7B3B0532D9D07EE7AD:\
+000000000000000000000000000000000000000000000000
+
+D29D576FCEABA3A71267660D927BD78E:CFFFA1BB54F8229F54E8B3D9E34710E1:\
+000000000000000000000000000000000000000000000000
+
+2D62A890CEABA3A71267660D927BD78E:86C1ADC8B236AF043A118F13EBEEF15E:\
+000000000000000000000000000000000000000000000000
+
+D29D576F31545C581267660D927BD78E:9064AA652AF016DD80AE3B3791502F63:\
+000000000000000000000000000000000000000000000000
+
+2D62A89031545C581267660D927BD78E:131984E1FEEEBE8862E406E12B6D8CD9:\
+000000000000000000000000000000000000000000000000
+
+D29D576FCEABA3A7ED9899F26D842871:D2E19BADECC2105CC8BF847075785184:\
+000000000000000000000000000000000000000000000000
+
+2D62A890CEABA3A7ED9899F26D842871:9DD896881D2AA0A0B3F8D6C7BD057588:\
+000000000000000000000000000000000000000000000000
+
+D29D576F31545C58ED9899F26D842871:416FC2C9B866CDC518476481F94D438A:\
+000000000000000000000000000000000000000000000000
+
+2D62A89031545C58ED9899F26D842871:0AC42C6E7CB6A77F6F63A0660175C274:\
+000000000000000000000000000000000000000000000000
+
+D29D576FCEABA3A71267660D6D842871:6E281CBD633696F0209E9C7326E49555:\
+000000000000000000000000000000000000000000000000
+
+2D62A890CEABA3A71267660D6D842871:CB9B1CAD03C62AEDC359CC64CA0D8F85:\
+000000000000000000000000000000000000000000000000
+
+D29D576F31545C581267660D6D842871:206369617D077201588ACF59463FC393:\
+000000000000000000000000000000000000000000000000
+
+2D62A89031545C581267660D6D842871:7558A3AD44F85079E3FF9E60FE30D652:\
+000000000000000000000000000000000000000000000000
+
+2AA28347376F4408FB7A29AEF0D05657:85B06641EF0DB99D153D9A9C9AEA1B24:\
+000000000000000000000000000000000000000000000000
+
+C3364F3FA909A07410B75D8AE5BB65D0:BDB9EF83D8EB4ECB7C89FC7D491E5172:\
+000000000000000000000000000000000000000000000000
+
+4CD9A151AAFB1BCB7BB75D6A9399FF7A:582C1174BA7B9FC276BF780A9A93567A:\
+000000000000000000000000000000000000000000000000
+
+47B292F6AC508B53EF7A294E630D3322:FFF0E8A57D5FC4D34678DC62E95A226E:\
+000000000000000000000000000000000000000000000000
+
+B3CDED6131EF45D99F48B827F4D95FD6:8C59577DC6B0C80FC97DD6E4D3DBFF88:\
+000000000000000000000000000000000000000000000000
+
+D3447EBA470D665E8B7A33FC6FAF33F2:3DC9513EF47DC38E2154DA643544CC51:\
+000000000000000000000000000000000000000000000000
+
+29493048AAD0130BE07A331C9390F63B:0FA6A8CF364435CC213F54F8773C87BE:\
+000000000000000000000000000000000000000000000000
+
+DC3F5CACCC00BB778B48B8C79A196520:4826FD43F7F116D9201891F553FD556A:\
+000000000000000000000000000000000000000000000000
+
+48F2A141203F740C7485CC0318D4982D:C20C38D1E7E25E25ED990326A1797488:\
+000000000000000000000000000000000000000000000000
+
+C4B646BEA922A87460B747D86F6F802D:FE5C4361C70143F52C66A8E766692C87:\
+000000000000000000000000000000000000000000000000
+
+2389837737FFDDC174B74738F662CEDF:3222B40C6BAC43150FC753F1E6EE3793:\
+000000000000000000000000000000000000000000000000
+
+45329BB7AED08A421F85CCE36C2629E0:0F83C029C9B964789CA6668006F79DF8:\
+000000000000000000000000000000000000000000000000
+
+2CC9394921BF75DDEF48A2751976987D:CD1702934609E17DE4DAE5188596E763:\
+000000000000000000000000000000000000000000000000
+
+D66F7EEA40266E5E0485D6511F2F2021:DA6D2243BBBA3199169C51CA80B03BE6:\
+000000000000000000000000000000000000000000000000
+
+BC4DE44037D4D5011085D6B1F4C0CE4F:30B9CDB6F185ED17DACAC0C4A377594B:\
+000000000000000000000000000000000000000000000000
+
+DB145C3CCE80BA668448A295686689CC:B981920A5773E47347EAD2A82041F08A:\
+000000000000000000000000000000000000000000000000
+
+251F428D867649A818246A6A5A89501C:15FF894626A6F8C6C9508A171BC1C661:\
+000000000000000000000000000000000000000000000000
+
+A41144E37C63D88B89A8A4C961EAF166:A64D2728DD4CB4723C19326B293DEEBA:\
+000000000000000000000000000000000000000000000000
+
+CFBD07846AFD2BA8E1AD63697DFAD335:7897147055D06DBA61866021D876D126:\
+000000000000000000000000000000000000000000000000
+
+4D93A6438527BE295F94487DD084505E:F0363408AF7BF5BB057CC80E10954D2A:\
+000000000000000000000000000000000000000000000000
+
+0855984A5B6C6C2E3ECEA329356575C3:161059A0D9DE6230B51EAA19BDC84CE9:\
+000000000000000000000000000000000000000000000000
+
+7E979A12FBBFF7FBD96860F0FC64CE27:977C5DAFEA87FC36E92333151AB63C61:\
+000000000000000000000000000000000000000000000000
+
+2088DC2D3E22E480ECFD9A6C76BA2AF7:E7DEF1020109FA00053579B665DDE397:\
+000000000000000000000000000000000000000000000000
+
+B9A8E6AA4E2C99159690D6D204EBEFF0:9E9A02C1952FD2F4C2BE158C10718654:\
+000000000000000000000000000000000000000000000000
+
+E8E06F34C44498900254EFD4F5C99D83:159A90193D7479E0203A929D701C421D:\
+000000000000000000000000000000000000000000000000
+
+1ACE901C77B74E96ECE1462369D7F0B4:F2906FD2C3373B7F0FAC2213131067EF:\
+000000000000000000000000000000000000000000000000
+
+4BF18736FB7021F610E4D7B76CF09F7C:D50E7103A0B29E33EB28D4C843F9557B:\
+000000000000000000000000000000000000000000000000
+
+A76F8B6EB992AE14212A5C2C8809D314:76CC8905AE4B4BE31992E6CDD3F7EA81:\
+000000000000000000000000000000000000000000000000
+
+10DC23B443D51E8F5B5D2F5CFEF9FBB3:A6E61F6CCFF0B2437B5BAB2688A73CEA:\
+000000000000000000000000000000000000000000000000
+
+0F7FFE39F36C8983C922E3704005792F:0D9B7AC709073EDEB0B1A5FAD45DB084:\
+000000000000000000000000000000000000000000000000
+
+8B564AA20FC6488302124D039EDA47BB:7FE01A5559DA077ABF385C8B4319B018:\
+000000000000000000000000000000000000000000000000
+
+EA57D4B949E192A51D6414FCC8315C21:99450709D21B61589509EEE8A1C526E0:\
+000000000000000000000000000000000000000000000000
+
+6108BC56C4CF3BFAEA642E8CCEDD31D2:3040BA7E08D60C8E771B97E250DA4413:\
+000000000000000000000000000000000000000000000000
+
+F1D159B48C2F6C238CB3D003AB0A5415:4A347C9EEBBBB7E28E41005AD5BD24FC:\
+000000000000000000000000000000000000000000000000
+
+DD99B08C18904D3811F2744AA644D76D:D7EBD7E0AA443E92279BA4E1192DD91D:\
+000000000000000000000000000000000000000000000000
+
+F0BF4544145EFB3231E6E6F6CA175912:97F37A9A6FF5101A7FE95F2678DAB6BE:\
+000000000000000000000000000000000000000000000000
+
+9F7B7744EEA8DF923366EE86AE497E69:50191B99DD8B691B2C17C26D98885E5B:\
+000000000000000000000000000000000000000000000000
+
+6177CA790CC736AAF8251290C2E9E43A:1717E23B04BFC70516E37A850454418F:\
+000000000000000000000000000000000000000000000000
+
+E2A7016FF930F70A8C8FDF25F762FD3D:D416724A7A3F4F81288D068797744CC7:\
+000000000000000000000000000000000000000000000000
+
+DCA2BC2308B05927DC6AAED1026B3CEE:318C4B212A74330C9D61F4D852D5C593:\
+000000000000000000000000000000000000000000000000
+
+B6379A7CE597E1295E4354D972B803E0:AF63C3F2FB2065A8C31A755038F2311B:\
+000000000000000000000000000000000000000000000000
+
+20BB84964CEA329371C8D6C19B7BBB79:B63FA7A265E7C7E5140B486B424257B2:\
+000000000000000000000000000000000000000000000000
+
+757D5E6A90375777C0592A1F16582FE0:87A64BABED1F66786FD3E56154FC6DDF:\
+000000000000000000000000000000000000000000000000
+
+B6857322EEB6DCFDA73DE5D43084B7A7:00C805A381A39058F9D427B9DC8960D0:\
+000000000000000000000000000000000000000000000000
+
+588AA36DDF8829787F5F0945D5A02C3D:1ABE11DC97F23734109997AF3849F545:\
+000000000000000000000000000000000000000000000000
+
+CA831237C45F4E8B8A98BE757DC21106:BE727CDD9C8B5027079C75C6DD5D2011:\
+000000000000000000000000000000000000000000000000
+
+C497A25D8F03792631E27277393126F9:A29DBEF99AB979FED40C265BF868EBA8:\
+000000000000000000000000000000000000000000000000
+
+A2B91FE5763FF97A4E9499F53F451D78:19B56E4B04C7B06B96CB5ABD6627E469:\
+000000000000000000000000000000000000000000000000
+
+ECA39A1D3B9D8EBC98EB34CDE71D03D7:D34A3718F58614D409633113C7739F18:\
+000000000000000000000000000000000000000000000000
+
+440045B4B13351971BC409404163D96B:8DD3A711A1D3335A40F499461FFD1ECB:\
+000000000000000000000000000000000000000000000000
+
+D631221F472CEF76BBA73CB2364EDD57:4AE664EE759660FD647AD11E2B5FF593:\
+000000000000000000000000000000000000000000000000
+
+635066186DB6086FBF2A4D1C7CF85DB7:3E71A02D9C753FFD8C58928A4560ECE0:\
+000000000000000000000000000000000000000000000000
+
+22924658C1BAC38B196F4852A1C35B1E:8FABCD731E720D0F464BFAF7313CC1D3:\
+000000000000000000000000000000000000000000000000
+
+AECD1159645242EB40231C45299B02EE:779288EF5750161A8E9948110C27D783:\
+000000000000000000000000000000000000000000000000
+
+AC622AAC79017DFDA35CF4602C049C7B:28A10079A7B447A0DE8894F37B1BDB51:\
+000000000000000000000000000000000000000000000000
+
+AE75A80D6CE8CFFB41D50E09EE65C822:0FABA3FD30BE980728B74B2BE0FF3543:\
+000000000000000000000000000000000000000000000000
+
+B507365EE27C856FF499D825F3DD57D1:494C5A82A6599FF269D028051D8E4677:\
+000000000000000000000000000000000000000000000000
+
+268E8157AEFB28F3F5A402922A5B08B0:B2913443BF4AB448CE42C297ED78018F:\
+000000000000000000000000000000000000000000000000
+
+B03EF1E97D2A85DEFE6E90EBDD13F37A:E3878C6C42A16C388E55C4732B038416:\
+000000000000000000000000000000000000000000000000
+
+5279D8401CD4C4AB27EAA22BABDA41DA:721EDA4C877B3C3611A9DA63AF911187:\
+000000000000000000000000000000000000000000000000
+
+F2DEAE70705494F49E30168A4EF5638A:461B74D6D552DF6DF118ACF76393FAE5:\
+000000000000000000000000000000000000000000000000
+
+61A08772900C83DE53749BA15ADFF518:6C491853745F4DB0C60D22DDDA608C1D:\
+000000000000000000000000000000000000000000000000
+
+9D3929D6A80F57E8117E5B48FEDCC826:BAF62E1A26F7C78A7CB9DAC0E13A30FE:\
+000000000000000000000000000000000000000000000000
+
+F85E31DDB8119F09A45EC30DB408DF05:59F7FE1CF6A3D7970E86574A619C516B:\
+000000000000000000000000000000000000000000000000
+
+20966FEB0CE93ABD78B24A971821FC88:87447915C9F4D8418B2A2CD727B2F8CD:\
+000000000000000000000000000000000000000000000000
+
+811450001E41F56394B9396743E3AF5F:9A460C28AA950C3D051A1F4EC1395CFE:\
+000000000000000000000000000000000000000000000000
+
+56E3EC3B5A911A0793244F86CA729575:BDBECBA37F3ED6B2D80CD257A498344F:\
+000000000000000000000000000000000000000000000000
+
+E81CAD94E521E9587A2D34669DD6C1AE:2D3FDF1C7C9F289D9ABAF6ECAE097CD4:\
+000000000000000000000000000000000000000000000000
+
+CF979E26135DF59109720CA19BF3B9E0:1A5A43E548E0AF0391BADDFB01B47491:\
+000000000000000000000000000000000000000000000000
+
+988BB4391697D4E693CC56185111ECF2:4973A5292E8BD63B1ECEA06851E439E4:\
+000000000000000000000000000000000000000000000000
+
+3DB27FFFA1DBF9E3E653B788D193EA35:A6FC7C9F947EA17AAE4AD69543134E18:\
+000000000000000000000000000000000000000000000000
+
+8BEBAF0A458CFBA90DE4FD329CE63109:63371B4D2428C76F8AF15BFD9826926D:\
+000000000000000000000000000000000000000000000000
+
+4FB2853762D073FE806557B78C43A7D1:F2D1D1382F2AD7E282E35EDB448E37C7:\
+000000000000000000000000000000000000000000000000
+
+F20AFEFE0129D6F3BFDBD788607ED22C:E63EA278E9B563297E28FC4B7B9E9433:\
+000000000000000000000000000000000000000000000000
+
+0039D613D42DD869852E44126EBF9E37:6BFC746FC94BDA3001563D9DFAFC8DF5:\
+000000000000000000000000000000000000000000000000
+
+D56E96E8B632A136C0755ABBE4EB8BD5:FDBCAAF131A5B6BDCB44E5C0EBFAA95E:\
+000000000000000000000000000000000000000000000000
+
+387B2F9C8170A96FBC39C799FBD10AD1:DB5A7AF7DFD5325816F179F3D4C3BB5E:\
+000000000000000000000000000000000000000000000000
+
+A7D65BC6962E99557AE83A96D567CFE9:3697BCB9CA432CF0FBDF8D29828D4776:\
+000000000000000000000000000000000000000000000000
+
+3DBA3171F0DA3FE61B8F8D8D816D5BC8:00FA60B941E72EE4ABD7EDA5383BAFED:\
+000000000000000000000000000000000000000000000000
+
+7016B5A26F566A0CB68113E7A54BBBEB:FB2534D13C44CF6473951E2396BD58D6:\
+000000000000000000000000000000000000000000000000
+
+7F7D76163F7950DB54F16AF542DECEDB:74D872081B6416D5B9ADF355BBC4E906:\
+000000000000000000000000000000000000000000000000
+
+E01F64B3E818C3571FC763F021595967:C3936315C0A5FFF0AE1F1743CFB9E798:\
+000000000000000000000000000000000000000000000000
+
+9F8A86DDE688776ED80FC3D6E027263B:06E080332D9615AC4B38436898467388:\
+000000000000000000000000000000000000000000000000
+
+4E4E722951A5D8398E2B24F5AF54BD9E:2FA6664CA53746DA02BA0A19AC6C7D7F:\
+000000000000000000000000000000000000000000000000
+
+54082FD1EFC1377E65C3584BFBAEBA17:C51BB0BD10E1D5525C8A301F7986CA40:\
+000000000000000000000000000000000000000000000000
+
+D685123436C51E2F904585E72A558536:003BBBD56A684F05FAC588BEE6103107:\
+000000000000000000000000000000000000000000000000
+
+CDBB0B021BD09745B6E3765DA81D7BB7:DF25CE6873E63365EC17B1E4F71713AB:\
+000000000000000000000000000000000000000000000000
+
+D8BB6CB4C5EC462A7040D05761A821CF:1EF3FAF8757B5864A66392F43ED39C07:\
+000000000000000000000000000000000000000000000000
+
+F2637A24ED6B1F3C6EF73083E4930011:39B487DE02F1603CE782716764699656:\
+000000000000000000000000000000000000000000000000
+
+8EC4C1D2904C081A3B862C1515D0A283:2DB7FC96FA3D8A2B699FF9743E98B14B:\
+000000000000000000000000000000000000000000000000
+
+CC976840C38ED63DEA1FB489261AB22D:28822ED55A22A29250F4A907A7773241:\
+000000000000000000000000000000000000000000000000
+
+D10AA53F75B4D56E23E43543ACB2D3D9:73DB1D32049070D84F3292441541384C:\
+000000000000000000000000000000000000000000000000
+
+42FAA774A6DB89F1422568D285750740:DE2D4B4F521C16F51D35B8E6C439890D:\
+000000000000000000000000000000000000000000000000
+
+E8AE2A5BD6F41780D4B78F5A7415BA59:6B83483EFC57408D6208286C8AED37B1:\
+000000000000000000000000000000000000000000000000
+
+0C6F220776A021AAFEDD1A5C1DB181CA:AD8FA2C34414A132F8073EBA3AE01C60:\
+000000000000000000000000000000000000000000000000
+
+674367222CF0E6BFD42D6E904F713DC5:D3C5B5122DDA26BAC7060BF154FD60BE:\
+000000000000000000000000000000000000000000000000
+
+F19CCE49F2AEA18319BAC29EAFC488CE:D73936AEF70D532E6C3270DB25058A4A:\
+000000000000000000000000000000000000000000000000
+
+A02A4E2E535E32179BD3F4D688608736:A98D0271136AF568324BB8D0E92340C5:\
+000000000000000000000000000000000000000000000000
+
+D4415FF1F2CD21C9CDCE175A238DA910:8124ACE84AB38E910FDED0F6752B5FAB:\
+000000000000000000000000000000000000000000000000
+
+23FDE6972BD5D652976B1979D5E0D2D5:E43483B9CD70F3DCA6C839FEB194A087:\
+000000000000000000000000000000000000000000000000
+
+6FC7112407890BEE9B1E58BBF5B19975:BACB0D14AF9E54B2A7C629AEFA64DD1C:\
+000000000000000000000000000000000000000000000000
+
+B63A8BF5D34915873DD16A95AECAF26C:302FCA7B0EDB37847638E24CA5808A3D:\
+000000000000000000000000000000000000000000000000
+
+D3FE2ACCDFFCDFF50165F67CC09A1D9A:2780C756862629A8C4E2629FD8E466D9:\
+000000000000000000000000000000000000000000000000
+
+254E34BE13C63EE93A24883136AFC0C1:B960C333FB15DB2C6580553B13C23AD1:\
+000000000000000000000000000000000000000000000000
+
+035302572B10D5C1B241C87F2D913DCA:9C0933C24C086E48DFD3F419590BBE92:\
+000000000000000000000000000000000000000000000000
+
+3EC84DA124E166438536E49B5C267091:6150B4873F1CBC7A6E9056F9D95076A6:\
+000000000000000000000000000000000000000000000000
+
+8D472DAA240C21E278E342DC3268E561:AC5C5E7CF34D7865C3851E663FCE23DC:\
+000000000000000000000000000000000000000000000000
+
+1EAB4C77EC179FBF9886F9A6858BD9F1:BD0526FB9929EBFF0B573EB93A940D32:\
+000000000000000000000000000000000000000000000000
+
+8F25610DE1E324C8C0B9A91124340FBF:94C5E9A383766B03C22D577741BADAE0:\
+000000000000000000000000000000000000000000000000
+
+B881A04004053C745AEE2A972265F896:CD3AC08893681BC57374BF3B2F14886F:\
+000000000000000000000000000000000000000000000000
+
+9B6E88AF654C8F52EB441B32813E0F67:6CA75A746D588111CDF5AA42860FD7A1:\
+000000000000000000000000000000000000000000000000
+
+08F16B4A01B2B6E4D3FB678AF52944CA:ADFCF161051EDC05C3850A42DC4B8C0F:\
+000000000000000000000000000000000000000000000000
+
+4B06EDC67571EA79C1186766AEA4539E:FD98A23A6A872F2C2FE88071536E4F41:\
+000000000000000000000000000000000000000000000000
+
+12F8F459A9A93DCE3EB6216820CCA233:D87C6BDCC6489B73BC826A54D3ACD17F:\
+000000000000000000000000000000000000000000000000
+
+848A797493A75023D7EE5D9C96E1D956:8A22AA964363CB8F63E42EC7B7A549D3:\
+000000000000000000000000000000000000000000000000
+
+35315C163A9127E505462C6E1C1D7890:6D86A01BB28C174BB8A9E14BCCD1B0FE:\
+000000000000000000000000000000000000000000000000
+
+695D6C7903BAE992AD6949AB85F5A65F:F93A2EF60CF4AC550C723E72644BDFAD:\
+000000000000000000000000000000000000000000000000
+
+6032DC62A65400CB70CAC882A17B5E95:97EA0E405C1FCE63DF66BB3C23560A0E:\
+000000000000000000000000000000000000000000000000
+
+5C94B77B9EF22A4F3DFB5407E8C381AD:2DEA5CBE120630FA88DA6D46D288635E:\
+000000000000000000000000000000000000000000000000
+
+F95F347A4D7A5C292620B07318BFF803:B387D8D91C6478BCA022A658FF4DB0EB:\
+000000000000000000000000000000000000000000000000
+
+9577B41BE7D1A8587E3E27A1389DC9FB:ED74B4EB542C5B3A0D760299E69E5EC3:\
+000000000000000000000000000000000000000000000000
+
+3DF28E3798BD98984F6DB950D6A1F948:8052BA88E81C87D8CF2CA22550A63B02:\
+000000000000000000000000000000000000000000000000
+
+AB2773E217A7A6A6859698D5D393B2DB:474A37DE739FFCCF31897B4B66B8C892:\
+000000000000000000000000000000000000000000000000
+
+060203EFD452FE6E4B9D29861F9B4562:472C3FA987FBB35DF3AF43C75E721E51:\
+000000000000000000000000000000000000000000000000
+
+31995CCFFE329932F121EF8BA410A4FD:436B187F3A7D51E2036DC53E517F1777:\
+000000000000000000000000000000000000000000000000
+
+A53625472349DE047005DAF198953590:960F173B6EEA02CAC4EC3651B2FC47DB:\
+000000000000000000000000000000000000000000000000
+
+8EACBB7BE93D3070B0FA7CABB3045DA8:EC276626BF1B0C436AB5276471372D14:\
+000000000000000000000000000000000000000000000000
+
+A965390450D42F7B74316A1EB1FCC329:C1488FFBBAA5C85DE16E98BC343660DE:\
+000000000000000000000000000000000000000000000000
+
+36E2AF37370B07EE5DB106B49D5C966B:86CC23C3B66ECDB59580BEE1853D61B8:\
+000000000000000000000000000000000000000000000000
+
+BE36B7425D6D812A9D655320D09EC22E:74B4C41C28D26D9D1C0CF16403EDEFE2:\
+000000000000000000000000000000000000000000000000
+
+67E19E7A5E0E26A0023DE95AF1B8B4BF:1BAA2706D5EE6C5BD1DF8291978C6EE7:\
+000000000000000000000000000000000000000000000000
+
+0148F25E6860D5FD6DB4FF4A10C41920:EEC71F999D856B480FDC9524D4C298DB:\
+000000000000000000000000000000000000000000000000
+
+8CC2AE04A5292E56074FB6AE2109DF46:6FF3AFEB3C79A2B2B19B7936A6B81600:\
+000000000000000000000000000000000000000000000000
+
+20D8712AE3DA248760736A180B30BEC6:74E4C190E3BDCE13483FB05A6B8FF5C5:\
+000000000000000000000000000000000000000000000000
+
+28291211012AF1AEA64D60E24A575673:849CC6B59E21442804A0E5ED1A01037D:\
+000000000000000000000000000000000000000000000000
+
+C34EC4029E4F5E93439331CA923C2864:D1746E215BF29A66A432C5223C060D83:\
+000000000000000000000000000000000000000000000000
+
+D7B54854F36F44DB71546494C405DEB8:C4D45430420585B661C4F43DFF5F0551:\
+000000000000000000000000000000000000000000000000
+
+1225585CD18C7ED26A1CE1576A4283B4:7502910B1835ADC0A724DAF5516308D3:\
+000000000000000000000000000000000000000000000000
+
+E3D02564C06455E162626EBCDBEC43EE:11DA0573D7D34A586DA61A7A5C10849F:\
+000000000000000000000000000000000000000000000000
+
+A9ED28B26B20D83CF33A97ADB8D181E6:B47F3027D742CA4C9BCF77AA141BA2C3:\
+000000000000000000000000000000000000000000000000
+
+D142B008C4764EAA88741D0DB54FEF8E:DDF748FD2373918FA25C4FE5D6E12656:\
+000000000000000000000000000000000000000000000000
+
+E568167CDC7D3BEBB3807039E34E10E2:BDB5EAC47BE80B077ED50625611EBD18:\
+000000000000000000000000000000000000000000000000
+
+7323AC95F39146CFDF6AA6BB8E9ACF90:F1E53F5E1B0AD9848DB4E3C3D3741263:\
+000000000000000000000000000000000000000000000000
+
+BA541AA170450D7C45F8D23FD587E34F:19331E5217357CB4DEBAA80AA5B44D92:\
+000000000000000000000000000000000000000000000000
+
+E603E348D083C0F0D0188E0E820BF797:2D691AEBFD51C5D26B13E33EAEE3B39A:\
+000000000000000000000000000000000000000000000000
+
+5AD31409A42464B3F085A2DD5A6FC292:63E8E939E52066EC0E4E074FE60D90CC:\
+000000000000000000000000000000000000000000000000
+
+D9C52B6DCC49BB59B9C3BD13FC88D018:A7563FD915814534A1963662BC900EC0:\
+000000000000000000000000000000000000000000000000
+
+3014518A77A1D8F9D103327F2BCDBE6B:59D93945A6467D215044EC49945B78AF:\
+000000000000000000000000000000000000000000000000
+
+5D4F53FCD6D41EA616F140C12B9E41CF:E8D7F3AA8DFC265001CEFB78733DF426:\
+000000000000000000000000000000000000000000000000
+
+E30ACA76182B1334FE2A4F5AF0C30BA5:C868972B54F73779BF62CDFC25722AD2:\
+000000000000000000000000000000000000000000000000
+
+A04A0A22C20E262C1B6485E406E65994:32A175FD6789524837157A176F40EFFB:\
+000000000000000000000000000000000000000000000000
+
+B6110B7A92475C3B366C403450488061:88DAE0307CCE2C38EE584F7149BFEF73:\
+000000000000000000000000000000000000000000000000
+
+8C5DF59EDDB12710BA47507F6768F113:D44C9FA99132D411EDE37ECC252588D8:\
+000000000000000000000000000000000000000000000000
+
+17C385D013346587A677DD56DA0CDFED:C10C3EABB30C69F9CD9554936FDE40D2:\
+000000000000000000000000000000000000000000000000
+
+6E43A132D96EC1F7DFEEBA445FE716D7:911BF5A6631536B39D1FA011F9FE1E73:\
+000000000000000000000000000000000000000000000000
+
+EA2733E8A42B18E0E57A85ABFFECA103:1747BF3F04B97A431D63AB6130B7E344:\
+000000000000000000000000000000000000000000000000
+
+57CD8F9A4ECCD9884243F834D9967BCF:8F33B6E4C39738C7D4FAC92D93D52228:\
+000000000000000000000000000000000000000000000000
+
+6623207CF0803C1BFA605D269A003C64:8534BE7C6BCA0155FCF418CCCB5AC81E:\
+000000000000000000000000000000000000000000000000
+
+76568B603BAC1CD646C34E61A638D7B7:53F6786EE1504317243EEA24CB5DA9E9:\
+000000000000000000000000000000000000000000000000
+
+841E33C6C4F92AF4443A43EC49243068:FD32E3EC516B77437B4517778BE90D90:\
+000000000000000000000000000000000000000000000000
+
+1097C11A9ECF04D2DE9F8F8994E0BAED:143401E20D3E6D97DFDDCA7A8DA456B0:\
+000000000000000000000000000000000000000000000000
+
+8D520BE244CA4260ECF38B81C428E1ED:701B82F492B01FC3F56A102072A66FB6:\
+000000000000000000000000000000000000000000000000
+
+A09BE54496E26257925A3F8B737A77C4:D2276D31749C2F4A79C1ADA50D242D2E:\
+000000000000000000000000000000000000000000000000
+
+AE1463F6200666D99837D4C3458E29F7:4BEC3FE34560EE2F3FB88C1B19928D71:\
+000000000000000000000000000000000000000000000000
+
+870AFEA6425FA0477F3758F9AC81B5BF:3B9A6B224CCD2A34B3CFFA8F20A32B33:\
+000000000000000000000000000000000000000000000000
+
+452857F43E0EF30BBA8DF975B92C67CA:650B79ED8814D9D5B9F40DB20B6E54FF:\
+000000000000000000000000000000000000000000000000
+
+3EA662143061F27044295712919D8CFF:3FF60CF2D0F12F3069959A17FD2FA52C:\
+000000000000000000000000000000000000000000000000
+
+3710720E6BCC9D67B51A990020E50E9A:AB064628EAFEFD04B7D483507A3D5F27:\
+000000000000000000000000000000000000000000000000
+
+CECD711FA3B66CEA1639E7DB0A36CB5B:219C9187FFD71770C717E3CC872A410F:\
+000000000000000000000000000000000000000000000000
+
+1A06CF5B4E4D9C055D017DBBFFB17493:DB2B632CED6EF0CA69B0DBF90CFDEC3F:\
+000000000000000000000000000000000000000000000000
+
+C9403D0FC547D44DB2A12BC26E549B12:34746770542734BD56CC54C3BA77DE05:\
+000000000000000000000000000000000000000000000000
+
+69E6239629F6BAB3ACAA41D3CF63AE2F:68ABC2D6D0155ACF7398751A4263FFE1:\
+000000000000000000000000000000000000000000000000
+
+CDF3A23AED45A5CC0977FC492D78D769:0155284B425712C5662BA85DD1AA9C00:\
+000000000000000000000000000000000000000000000000
+
+38947A6BCB9EEB2349CC7982CC988A3B:487705205D9C054B278A1A77154DC444:\
+000000000000000000000000000000000000000000000000
+
+D21A1763007D050CDDB3D3000CDA18DD:E4BDBAA0BD0799643147BE9A72C2C28E:\
+000000000000000000000000000000000000000000000000
+
+D86E349D4F8BACC0CD204D86485AF372:690C9CD71586F0E707A6747CDCE14BD9:\
+000000000000000000000000000000000000000000000000
+
+2F3A9E1E90111694A5D874B72A725627:485BB4E6C8EADCC1DC8F33CC83C56DF7:\
+000000000000000000000000000000000000000000000000
+
+BF6397D9E8C5D0F7D537D17CDD094C56:5DC5509BE381271A892F73AD2B17459E:\
+000000000000000000000000000000000000000000000000
+
+0C8EEF7E5C26A11E13F3B332C78240E9:FE7F7B03809161699B20C91AC71388F0:\
+000000000000000000000000000000000000000000000000
+
+3708A3370D457D498BE3B36C6628C450:5ECD46E61E9EE1504928AF23DE58B417:\
+000000000000000000000000000000000000000000000000
+
+7A984BD4A80E2495C7A64107DBD1E5D8:529EC6E2DF4B601050BDAB98466FCD47:\
+000000000000000000000000000000000000000000000000
+
+E00C27A4F32C3C1FD220FD3B7B2E7251:DE00F2AA4BC9B34A187780D1D6998873:\
+000000000000000000000000000000000000000000000000
+
+C9EED5E1F515E97E393E00476F291ECE:81369529646A657A4C6BF7BDAB9D2780:\
+000000000000000000000000000000000000000000000000
+
+D91189059CAA6B0C4E95E7485D7A73AA:F6D1EC1368832C038AF24FF17C523D8E:\
+000000000000000000000000000000000000000000000000
+
+B0824A7A86F5EFCEBFC3EFBAD4445FE2:E4122EA5B2375D306C7A86C5486F6AD5:\
+000000000000000000000000000000000000000000000000
+
+7FEF47A756D245B1B5E1CC43EB9D961F:537822C6708654C63740F2EF1DFA1B57:\
+000000000000000000000000000000000000000000000000
+
+714B564D133054E286CCF3F7B4DDA373:D611B6FA3C70454B618CE723D70DB96A:\
+000000000000000000000000000000000000000000000000
+
+67EEC672093ECB5C0067565FF315B57D:BCDDB2993D6694EA14CBD3DBA5D72054:\
+000000000000000000000000000000000000000000000000
+
+EB34AD41058C53C01C4F1357F7CA0540:C25E1CEF2DDDCD4C6E8CBD363BC7A49C:\
+000000000000000000000000000000000000000000000000
+
+087BC6FC60B82B16F51BFC19F52DB265:406B498631B18D08880E75470D9D9356:\
+000000000000000000000000000000000000000000000000
+
+7D505F278F68130DBDD769F310960455:0E4A4B6FB1DB995A4F38A8F91824CD14:\
+000000000000000000000000000000000000000000000000
+
+53C5BBF9DDB235003D075E57FF1A1001:FE704DB9E2020E715AD69FF9E92F8786:\
+000000000000000000000000000000000000000000000000
+
+43E15279B9CEEEAA90EAD7CD9D491D5E:7B4DC664B034F4FFFB324C1514702B35:\
+000000000000000000000000000000000000000000000000
+
+0BC5E3D2B2D18CCBA1B122FAB906F4EA:54E1A5104006ECB27ACC0FC355A5C0E8:\
+000000000000000000000000000000000000000000000000
+
+2A41F1E81307DE4FD56408A9C7865FE1:7D0B9B0FBA0CCFFE60DAE48078CE4DFF:\
+000000000000000000000000000000000000000000000000
+
+7BF72B9F29F6738A149EEE9CC66042CA:B8C05E2EAEC1B4A3ABF9505BB4ACAA46:\
+000000000000000000000000000000000000000000000000
+
+9907CA6C2944F659DD209F90797EB7C6:606D2B529277284D69232AE77B475024:\
+000000000000000000000000000000000000000000000000
+
+478E732A754522C881C15883B0BBCDE9:B232CF742761574EA99453D7C9B54862:\
+000000000000000000000000000000000000000000000000
+
+4A9EB2F326F83A0F93F41B21AE4F49A6:354E0630938D10ED31D9AA7F57440CA2:\
+000000000000000000000000000000000000000000000000
+
+8C7B36A4E87368511D3D3C578CF95240:53F1C55253D2A5B7024C28E666A57FEA:\
+000000000000000000000000000000000000000000000000
+
+EE2A1F5575784C3553DBB21540B7553B:8E8C8768B7E2D430CC2DAE11A2247D8A:\
+000000000000000000000000000000000000000000000000
+
+BBE9A1EBB77CBCA4B5BA650CC8E1882A:A13BFC5603FA258281D8AC945F4314FB:\
+000000000000000000000000000000000000000000000000
+
+0304ED5D3AE4E9AB51A67C14291B0E4C:17C0BB89D285E07C97640A8FE6027341:\
+000000000000000000000000000000000000000000000000
+
+E8EE60340D4881CEE9870133578B723D:DAF1AB5368D5BD5F6B52EA89940605C4:\
+000000000000000000000000000000000000000000000000
+
+15F20EB4BB374CF9FFD0ECF1379A6309:D3D5F60355EB5FFFA9216B6073C66FDF:\
+000000000000000000000000000000000000000000000000
+
+03B59445DC995E511D14CB27B611D8F4:D34A2B72F1864FDEFF58425442A0A3D8:\
+000000000000000000000000000000000000000000000000
+
+E5DE46FCC7ACA6EAFE41E83B8AEFB33B:52040C8FC70CE166EAF34CDCF654ED43:\
+000000000000000000000000000000000000000000000000
+
+C6DEA79ECF12FD33EA7CA9C0AA3C2E59:9C5702F759F6C92836FA2C0490080A6B:\
+000000000000000000000000000000000000000000000000
+
+CFDD2F3012EA2BF447FCCDD24FFA8869:C33F590E882873038349ED33E8F22B7D:\
+000000000000000000000000000000000000000000000000
+
+8BFE4AF3B7D8DB7660514B9669F8D464:A8320F0F729C8A8DDCFDB5C208A6630D:\
+000000000000000000000000000000000000000000000000
+
+301958CC9E63DEDDD5E7E1C3C8AC792E:9F5D597E1EA73AAE8F53E58CE4301030:\
+000000000000000000000000000000000000000000000000
+
+EDD8C0F63717866059C1CE22F8D01F26:4CEEF2B0933EEABA49A102EEB6E4402B:\
+000000000000000000000000000000000000000000000000
+
+5E8BC57A7204DD62C2BF28C9B4C37417:58C5773E59A396896ED815A6127F841A:\
+000000000000000000000000000000000000000000000000
+
+256F18961916ED383CE6FA8BC6F2B7CB:7A803EBFE417C354BBFC308AEEB8FC95:\
+000000000000000000000000000000000000000000000000
+
+754166EF6D6231A5CC838C394FFA6FF1:4B51C7505E98DE6C9DAE5843E589EDE6:\
+000000000000000000000000000000000000000000000000
+
+569C792FCBB2ED89420A51A9289D7323:D450508E9143A3E14ED4D72CC12160F0:\
+000000000000000000000000000000000000000000000000
+
+F74D7BCE63019F55E33D92C7FA132BA0:A8F126B576C79AE85A26303EC70ACDFA:\
+000000000000000000000000000000000000000000000000
+
+1DEB7CF9F5FA1E3BC818BB54D9721D9D:9113F881F7474428BF23A8984219A4BD:\
+000000000000000000000000000000000000000000000000
+
+2EF52D3CBEA2E2CB03D0B848E7C07D80:DA15834C6EF22C8958294E66E6196119:\
+000000000000000000000000000000000000000000000000
+
+3B27817D9E57B4E70ADB97A43B005317:CE976989A33D1A02A0EEA2246997AFCE:\
+000000000000000000000000000000000000000000000000
+
+5E28CE24DA41AA55156AAF4D0D4BDA42:32AE2CB879873928327488298B64F536:\
+000000000000000000000000000000000000000000000000
+
+8D331AC09D25385F4490A7F3719863ED:9976380787393589CEAD1800FABFE078:\
+000000000000000000000000000000000000000000000000
+
+D5B056B768B04D47359793DA9F0ACF1F:EAD5B4F1EFA30013B303ECD50493E54B:\
+000000000000000000000000000000000000000000000000
+
+322B8A0EC75069EFF4EBA07CEEEB342F:1A94F65D67A6A435C5EA28F1D46BC0D9:\
+000000000000000000000000000000000000000000000000
+
+4B4A22563C0A57DC4736D574190E1AFE:D84C3B70EF9D3B471C689BDE6D8EFE82:\
+000000000000000000000000000000000000000000000000
+
+F1D917CB22016EE46F4219603DA737ED:4AD2B98E504299732EE814E93D69475A:\
+000000000000000000000000000000000000000000000000
+
+74DA216E6125B35F68D710AAD1DD6775:7BBD944B232616BD9DE40A985BDAEA2E:\
+000000000000000000000000000000000000000000000000
+
+292C602001EB4D371203B1E93227F836:8C4013B2AF75B3C155D7120DB0934428:\
+000000000000000000000000000000000000000000000000
+
+734683C7FBC228A7EB1F1B67F29D5CF0:951DC7BB2239C3B830843FE3CDA7CA34:\
+000000000000000000000000000000000000000000000000
+
+7847476D0ED3DDB46203EBDC73BB0FF7:60B5491007F5253FAD1BDCDFAAAC98BD:\
+000000000000000000000000000000000000000000000000
+
+81CD86C3C82714205F4C06384878D4FB:585EBD953D2F584B82788287E99D263E:\
+000000000000000000000000000000000000000000000000
+
+E65472A6D482655AD2A5B1D3B8B247F5:40D1910F18DA68DCCB577C0651573748:\
+000000000000000000000000000000000000000000000000
+
+27706EE3BF8C5B11892AFE89FB77530F:80112C6A37C0DD301AACFC660B411099:\
+000000000000000000000000000000000000000000000000
+
+99582047A954472C79F081EBD92AD60F:294B94E01056C6E1DECF70D3EC0A0B02:\
+000000000000000000000000000000000000000000000000
+
+7ED1ED318F1942243580EA94C5E40C15:480986DE5D85BD9FEBA09F9D074C9BB1:\
+000000000000000000000000000000000000000000000000
+
+C4399BB80B44FF8B9791B952262ABBF0:0BB435634EC3C4E63EA1D4AF3819D635:\
+000000000000000000000000000000000000000000000000
+
+AA9774F621357C574956D06FA4FB0DFC:089670B247DAA022AF8E63CDCC252F3B:\
+000000000000000000000000000000000000000000000000
+
+A2D7F2C0B96C888383470D746D8C3D72:71C6023943714AB97C4F66D6ADE4B5C5:\
+000000000000000000000000000000000000000000000000
+
+60BBE793A6CBBF092ECF3F2DFF9C58E7:914B0150537160F4A49FCDE81AA32A5A:\
+000000000000000000000000000000000000000000000000
+
+CDCA44CFB68D9397FB45692CFA7FE92A:01CD4B3A51B8542166478BC6535DA067:\
+000000000000000000000000000000000000000000000000
+
+201D8598327C81D3C91B1894FA97DC2A:E4F60F8E55978A6792589FB4C58FD61E:\
+000000000000000000000000000000000000000000000000
+
+3073CB477A05DC7305625B2D8B89F37C:750DCF9CC3B820A99226E27A67F0B9D4:\
+000000000000000000000000000000000000000000000000
+
+8B0D43826ACA0F5ECD9AC42B24B23595:2BEA1CF96CA436FC33EA573260C56A29:\
+000000000000000000000000000000000000000000000000
+
+CE1EF0456D99D285B8DB31EABDF12754:9A26AFECE78B58FD937B0CABF518350E:\
+000000000000000000000000000000000000000000000000
+
+6A5F54938B1A3FD41C10C854C8E04A44:405DE78B8BA1013E025F0C66CD8DB322:\
+000000000000000000000000000000000000000000000000
+
+925CCB833E2BB24C56DCD6971E50DA44:A7B1C50C8A1DE13694BE770DEFA447E0:\
+000000000000000000000000000000000000000000000000
+
+72CE5E0A8D2EFEF16855E3F1844FD13C:53177B6A61F2C5B98F2ED3E6EC195629:\
+000000000000000000000000000000000000000000000000
+
+A7A3974CE115F4D92CEDBDCB6C0850BC:3DC31176F7BFF544F98B50D1FF0EB338:\
+000000000000000000000000000000000000000000000000
+
+6EB0181E23642427F498B5BBC87A0FF3:F7887B1A95F202918295D6DBA328DBE0:\
+000000000000000000000000000000000000000000000000
+
+112DB5BFD7108A6E2D51B883F0C6700A:35EC6F1B98376F6CFD98B0DB3DB63295:\
+000000000000000000000000000000000000000000000000
+
+EE9CB8FF31C6106F54468D56264B5A67:FA2A11C86EC2BD433BDC062294D5D479:\
+000000000000000000000000000000000000000000000000
+
+9269DB3D3EB516D02452109D537511A0:70C709A5F6DA5E546AA42781D389BA4C:\
+000000000000000000000000000000000000000000000000
+
+04797C87F169EED791FA03BC6529CCBC:DFBA39236536C7B33F5C186742897F44:\
+000000000000000000000000000000000000000000000000
+
+30DCEEE9F96719F94CDA6D4447DDA5ED:6BE2E27BB85093A71E3208B22D9B4EB9:\
+000000000000000000000000000000000000000000000000
+
+DEEC871FEDE7BEF4E5924A35F7C1473E:2D189653936AEB37F0222E96B205FD36:\
+000000000000000000000000000000000000000000000000
+
+14D91B1E40E6EF6C0D47B18CF1820459:E428FBD6A451527D8E254B032A85ABD2:\
+000000000000000000000000000000000000000000000000
+
+F50744F84E3C68FC80883F5F7CD4F473:12D9ADAC936643E44C75765EE860E156:\
+000000000000000000000000000000000000000000000000
+
+BD37910AB3475FC22A6C5AC0277D6684:22EBADE6B7550CFAF53B369490420120:\
+000000000000000000000000000000000000000000000000
+
+4A9EB13B7BBB14632B1FA37006139022:1B0568ECB78BF78E17891E99D3FF6685:\
+000000000000000000000000000000000000000000000000
+
+A1F6367ECC2AD8DEC620DA653D6D4AC3:B72DC0A98DC7545798B9A09774127A7C:\
+000000000000000000000000000000000000000000000000
+
+1FFCA2F556D07C7F0125B1E63811FBF6:620B4E671AC5ECA7780C114F8A3B5834:\
+000000000000000000000000000000000000000000000000
+
+28EF3A37D33B9BBFB94DA9C27CD74C8F:8DFB3F06170CCF3FB628A1131B7C55D7:\
+000000000000000000000000000000000000000000000000
+
+3504348BF82F0E8D12784206732B7EAB:9395207A7F3D76727E08650635A50E8D:\
+000000000000000000000000000000000000000000000000
+
+649B9B03B4FA72E015C6318C78DBFE6C:1C7F7A1E78612D4B57AEE7A97E026D99:\
+000000000000000000000000000000000000000000000000
+
+5E5D242061750A2E3AD7CF68A18F53E0:92BCA6EE74F863BD58AAE46966FF0195:\
+000000000000000000000000000000000000000000000000
+
+0BEAC3380DE66C16C118E94A7E98632C:D707ECAF8DA45A032FD2B92EC02BF809:\
+000000000000000000000000000000000000000000000000
+
+100C0B29ACBDC1DCE5BF94F647132C8E:D7D4BB2EE07EC7ABD29408BB29C3E52A:\
+000000000000000000000000000000000000000000000000
+
+E4C40EABADEA4081D339B98217B89F4E:068477FE3113C4E706161C7BE173109F:\
+000000000000000000000000000000000000000000000000
+
+79201EFA18BA2872F67DB637435DA21B:E73ED140C42FE2121BE039F36F24B353:\
+000000000000000000000000000000000000000000000000
+
+F0AE4C2DC0FD756D97E9D4FE2F9F4CF2:2472A6AA7ED6F70D2179043A4E37C671:\
+000000000000000000000000000000000000000000000000
+
+6C18AA9A75DCFCD80EE4490529461EA0:95818C326367FD55674DB6C721DCC315:\
+000000000000000000000000000000000000000000000000
+
+73C0E36EDF00088CF693EAE05DE118B6:44BAE149894A3B8D680988B2441FDD1E:\
+000000000000000000000000000000000000000000000000
+
+C20558F78C1E2D2AB5898C50B7C5B5CF:6631895DA9C9B985C8268CE75B8DBD35:\
+000000000000000000000000000000000000000000000000
+
+7A2DBE3457C46A63ABBFE7E3C6AA00FD:A95F5D0F337851A3349D159E70EE958E:\
+000000000000000000000000000000000000000000000000
+
+9FB3015058C61098BBC919A7DC369728:0B3EDDE3D3C9F33C98F2561C38A24AFE:\
+000000000000000000000000000000000000000000000000
+
+8446AA6E305837711CB5B77589BE700E:9CF33FCA164676B2503F4EAA6DB82427:\
+000000000000000000000000000000000000000000000000
+
+63ACC114B985F5E162E74C6A0D5489A4:4502AF98B2F3C453EB84DB4816CF86BA:\
+000000000000000000000000000000000000000000000000
+
+1FB274A798A9DE040500989BD0DAA450:5122BAB4ADF7B99D018247C17EDE37B7:\
+000000000000000000000000000000000000000000000000
+
+0B75B6E38F803AFA2E185825452E7CB9:8053D0C508ED36FDD78BE6A2E156C68B:\
+000000000000000000000000000000000000000000000000
+
+502998BD920539E6C9457CEB7ABCC2B0:630A85FE40269FDE57BE0A91230F14F9:\
+000000000000000000000000000000000000000000000000
+
+D15498EEC5A204E75ABD92296759B2E7:1DFBDF5987C38B34D70EC1F9F09DC244:\
+000000000000000000000000000000000000000000000000
+
+74CE162AA4400EEFBE2F9452F190C925:89A0188B43870472AE7BD89F1DC9DE4D:\
+000000000000000000000000000000000000000000000000
+
+9BF6D9402DAAA02EB0D70ED5686A2897:F080B9C597F6AE853556F9088765307F:\
+000000000000000000000000000000000000000000000000
+
+66104EF16B83A3C24630AA15999CF795:465BED1DF34D70D6666BA9CAEF77E5F8:\
+000000000000000000000000000000000000000000000000
+
+2C7518563817B2302055448AC1E236A4:29228B582D6C9BF2F5FD64AF68801645:\
+000000000000000000000000000000000000000000000000
+
+B840A56E78F0CD9C491FBFC2A008C0B1:741E572D70820BF764DFC3EB64F58DB5:\
+000000000000000000000000000000000000000000000000
+
+366C45C25B098271DE2BA33B761CA2DA:93730B17CF28E0B7FA833BE560433D26:\
+000000000000000000000000000000000000000000000000
+
+DFC28B998E7D650ACE708662715DE551:070744AD0E21FBF5344EA22396FE3BFA:\
+000000000000000000000000000000000000000000000000
+
+AB8D9F6AF9FC1B293D1EF3D4459C17F0:873A852D49296F2493CD56AC374FBD59:\
+000000000000000000000000000000000000000000000000
+
+CF8A7D1F67264C8F0CBB81B7F22F5284:A0688DD48E462A1B75F34425536C270A:\
+000000000000000000000000000000000000000000000000
+
+3911525195F0A35484618596EA0B23CD:9B1B36125ED888A57FAE5BDEB53ACFE5:\
+000000000000000000000000000000000000000000000000
+
+5DB02CC6EEF7E128DAA849EEB1BE9A7F:95404D7CCA9EB1C2F720BF6CC74826A8:\
+000000000000000000000000000000000000000000000000
+
+CBB260B85AB0E75F4396FC3F6C7B8DC9:2B702A4E613758D8EADD8E17DA9C0E68:\
+000000000000000000000000000000000000000000000000
+
+73C7C371EE0D7EEBBDA62B2D8B47ED02:C6B9E0F5E943685FD1FD739E9EEF6747:\
+000000000000000000000000000000000000000000000000
+
+928C48F1AB2E39BC0ED7395841AA55D5:6EE0B71022F864D82F177058C2AFD1F0:\
+000000000000000000000000000000000000000000000000
+
+9B73A4CB141AE76D1A4AF02EE02F5623:11D9E2FA35491C034FC28D278F81C741:\
+000000000000000000000000000000000000000000000000
+
+F98FF8E931078D572588D3A23BA9A65D:69408F1E703ECEF45C60B576DA8A8E93:\
+000000000000000000000000000000000000000000000000
+
+D697E66D3E394658B477F5D94E9AC272:C3E21C1C90F1BFF4BA3BA1FC806C50C5:\
+000000000000000000000000000000000000000000000000
+
+7B5D2AD95D1278790DE3E61EA79683C0:BAAD9EF7F34F2D09E4F24F8FFBDAD242:\
+000000000000000000000000000000000000000000000000
+
+2FABE699379719F903C55B243E270154:88768EB6AEBB3221DEB456CB581672C8:\
+000000000000000000000000000000000000000000000000
+
+A1D567D19DB1F8CDE682025AEAA99DE4:EA16B62DE42D02CD64AA5286D7058E2A:\
+000000000000000000000000000000000000000000000000
+
+31B9406E90742402C18E4EFC6D49C43A:C33EAB3109805CC528E06CA92DF1CE82:\
+000000000000000000000000000000000000000000000000
+
+DC5CC861CDB8565EA74C5B81D04E3FFF:95581016D9D878454F3B29BB72282CAA:\
+000000000000000000000000000000000000000000000000
+
+92D735CAAA20120B2545530FBD841976:AF352F902D964BC93C52DDE45F36813B:\
+000000000000000000000000000000000000000000000000
+
+81AC34A2E341F62C479FCDFBC85570D3:D35E2834DAEF034C122439AA75EDE6FD:\
+000000000000000000000000000000000000000000000000
+
+DB6CA5A00935E081B0DE14F9489E56F5:C0B207F61BCC815E44671E76556BE222:\
+000000000000000000000000000000000000000000000000
+
+6795C4731AB1B7A9BD1367C5FA6D24E0:F2F48C694E4D4C561237F2E446E48CD6:\
+000000000000000000000000000000000000000000000000
+
+503D1E8C00F32DD24666B40AADF21635:6CAB8D56A573C231E4083E062509331F:\
+000000000000000000000000000000000000000000000000
+
+9B34D2D7E4F84FDADCD221C818398D9D:3F6211A4F97C7D07DE3069A3AF0B2F7C:\
+000000000000000000000000000000000000000000000000
+
+9A6AAA25CD55632A8D1364765F054228:FCEE710DB225421305683F6DA8A14498:\
+000000000000000000000000000000000000000000000000
+
+51BB73F367B4789C50EE27A7FECDCAC4:89DC658FB152C89E533873028E82F386:\
+000000000000000000000000000000000000000000000000
+
+38E2FB18AEF954A977CE17B61420AFE8:F2F090E1D924600B3F2852160F8FBFFA:\
+000000000000000000000000000000000000000000000000
+
+40E1F27DC23EB87A38D33A9D7DEA6B57:0BA7974ADFABBC749AAB019F1FF0FA22:\
+000000000000000000000000000000000000000000000000
+
+69237F4FA6B874C950F44E2ED8EDE5E2:E8BE1E5DF9FCF083C5C80F5C0C927350:\
+000000000000000000000000000000000000000000000000
+
+E529151F5FEDB46E9F150E39FF9095F6:9516D575A3FA911065F308AA45957E61:\
+000000000000000000000000000000000000000000000000
+
+3921C4781E145F4867D1E8F134DF7355:DEDAB21C05B199DA1E0C0E1D7CC17F61:\
+000000000000000000000000000000000000000000000000
+
+AFFC9793843506A048E65104A559CFA4:43C466A47766F7AE27D9E8250B04D617:\
+000000000000000000000000000000000000000000000000
+
+D7CC61BAB163D793C1C9A6C4266BF004:B0E2AB3CF69FD19EFA5BFA9587AEF29D:\
+000000000000000000000000000000000000000000000000
+
+A0D64ECF3F000B7478C9FB6C20CD576C:2C0A893A4F331ED2D738446AF038ECCA:\
+000000000000000000000000000000000000000000000000
+
+141964E6278C1ECB067DFF46B8D80C15:D89E32E065DA6FC65BDF38A15626CEC4:\
+000000000000000000000000000000000000000000000000
+
+72568E2FAF72EFE69E5EEDDBD415F1CD:3A9DE9497BD9C0E8A7933581709C2F86:\
+000000000000000000000000000000000000000000000000
+
+2309A9E1B063BEA563AE44FB1D11763E:2C68D638E01CC717CB3095F8769F6330:\
+000000000000000000000000000000000000000000000000
+
+5B8786E22A5109D189F5155471148639:F54BDA0C2F70CA852BC5A9DC48E74DE3:\
+000000000000000000000000000000000000000000000000
+
+14B31DFD7489D68488A8A2EC6A9B28C2:2E4110267CC09B86849976EC36FD9545:\
+000000000000000000000000000000000000000000000000
+
+72D8F97A40E78FDBFB9DDE7D94694F3E:2C010E0A06A15338F76A37A5EDA6E7AE:\
+000000000000000000000000000000000000000000000000
+
+7CFB6BEA9ABFE0B5C486504AB7AB7C7E:1495DDAA1CF53478613C5A7FBCC4D21A:\
+000000000000000000000000000000000000000000000000
+
+8E22872352AFBE50799766FBD74672FE:DA8894CF60FB487AD2FA856049B4A339:\
+000000000000000000000000000000000000000000000000
+
+9ADEC67160B3E7A54CBB3118CDB24016:ACD872C37F74E4D8C9DCB67560A2C626:\
+000000000000000000000000000000000000000000000000
+
+AF35888791EA802A0DF92286893B6653:2E2D305D853B870400402D50B36AF1AA:\
+000000000000000000000000000000000000000000000000
+
+30401704726D8B873D4D2435CB008F42:1744071A7A0B587AAFC7FB447D249B9C:\
+000000000000000000000000000000000000000000000000
+
+2E60C63BF001FEA2FECC57D93E9FE7A6:83B5901B7B71025C8D0FE54EB35828C3:\
+000000000000000000000000000000000000000000000000
+
+3950402C43051C4904DEEC57F504FC4D:9A9C91030126FB9F9F9AF1BEE01506C8:\
+000000000000000000000000000000000000000000000000
+
+F5454A8EBE04708570F9B2317DBBA71C:170B64FD20891245085B8E1B21E73A83:\
+000000000000000000000000000000000000000000000000
+
+3E03AF195C3829650043A0F643CAEC4F:A593253D4144356A93B77777BB062ED0:\
+000000000000000000000000000000000000000000000000
+
+2FECCD73C296BB4E5D6D7FACF2F07663:A59DCF75D21391DAB42977618A30807D:\
+000000000000000000000000000000000000000000000000
+
+E3A600FC8F0C9BB15DDFE8E4D36D0B6B:F2E3DA77CFDC4F914913D370AFC46475:\
+000000000000000000000000000000000000000000000000
+
+65FAE4018301DF82E78273D60FA8BC1C:B48220811F1497381AC7ACF1FAE6A1C3:\
+000000000000000000000000000000000000000000000000
+
+513F515D31466F0A01332F6D8D733E9F:056E78208EFDC0272956971EE29EAB50:\
+000000000000000000000000000000000000000000000000
+
+281AD7F41EB19451BC978B6C125026B1:DF6D20D993094000464BDA7DA2AFEDB5:\
+000000000000000000000000000000000000000000000000
+
+97A75E3919FBF5107E55E37B81FC45A0:CC052A8B64E199030F6D620427C379E4:\
+000000000000000000000000000000000000000000000000
+
+B501F0B968BFF14070DFE2DF6298FF0C:0A53785F9A58D9FFB7A01C6E6DDA7BB1:\
+000000000000000000000000000000000000000000000000
+
+672B7E9933053E6ABA4712214D1278D0:4CE10611AC92C9998E6044099E2BFBC0:\
+000000000000000000000000000000000000000000000000
+
+C8EE21B9E260A72153A6938F31A127F8:7FEDF8389CC1F013F350B2BCCC6046EC:\
+000000000000000000000000000000000000000000000000
+
+61F6FE223D11D88FBADA99ACACB7FA25:A834288BFD1FEB7432F94E97E7B69D89:\
+000000000000000000000000000000000000000000000000
+
+F79DD7A31FB11644A38E8D006BAF4B62:9E949C299CDF820845FB3B06E85EFFD9:\
+000000000000000000000000000000000000000000000000
+
+7328E5C1ABE226EB229AD784F26E299E:57E21FE31459A01DB1A05230C3DC75EA:\
+000000000000000000000000000000000000000000000000
+
+9AD91A8354BCE0E632CF9C62C95AFF7E:F304CB96B9347492E5D70527C2B11ACB:\
+000000000000000000000000000000000000000000000000
+
+606BF2DE00C40ABA8ED77992EFA05C1E:DE27FBAD11FCB0992CACDD7B6BCA810E:\
+000000000000000000000000000000000000000000000000
+
+F81DFE4D27CFD077F105905D47D5BADF:E8F978AD0451B0A02DF946CBAB82EF5B:\
+000000000000000000000000000000000000000000000000
+
+D7201D9F6407C9383CA4535D688C61EA:DC49220DB183147B3918ABA9CE72B834:\
+000000000000000000000000000000000000000000000000
+
+AE34D39246875745FC00139CB4A564C6:83A946D5D727FFD83A6485D8E61E5CFB:\
+000000000000000000000000000000000000000000000000
+
+6D3F60DB30BC83F0FDE7DD3E21E0CAC8:9EFC2DB219DC063E887A54F9B7B81DD9:\
+000000000000000000000000000000000000000000000000
+
+5FA122F7957554393E97F89E98C7847C:E93AE44D82029938684ABE78DDBFB2D9:\
+000000000000000000000000000000000000000000000000
+
+07F249A729186C8A0558A62188772C74:E0A8A1619EE653EAE22E41DEDB1E4553:\
+000000000000000000000000000000000000000000000000
+
+244DF5F8502E3C12A37F28BB9F2CD24D:B189B0FFD6BC957D95A9A91B4E2E4BCB:\
+000000000000000000000000000000000000000000000000
+
+2A0C5C6B721B1010C9FDBC02B053BED9:3D9E27A119B6693128AFAC171E46B926:\
+000000000000000000000000000000000000000000000000
+
+AF6449E79628453F1DD77EB0857CADED:C150CF167A16F8F367D5D90E89C09DB1:\
+000000000000000000000000000000000000000000000000
+
+36BF3D3D0A63CD8AE037FFE06889C29F:C708DAB79E5B99B97676A39EB1BC8C89:\
+000000000000000000000000000000000000000000000000
+
+9DDDC7CB9B49B7075FE8D987F16AC153:DF01A9D14E08BF79F8C8B776F07F11AA:\
+000000000000000000000000000000000000000000000000
+
+48CAB5B512E2AEBA252845F24DA62FFB:066BD47805684B25217AAE164E1B59B3:\
+000000000000000000000000000000000000000000000000
+
+905FB46046C869B609C0C92943C1D22C:951A9225FA7A02680866539F73953A49:\
+000000000000000000000000000000000000000000000000
+
+6C027C762F6C9B9C0C3EBDE341238154:D4CDDD6C60DB9CF0815D48EB8C4D1BB3:\
+000000000000000000000000000000000000000000000000
+
+55488B44AF25E48F8002618985748EEB:C47006D8E3ABEF6DA6844C25C3DA8E5F:\
+000000000000000000000000000000000000000000000000
+
+B6E76A99FB42AB0DEC2F64CA4119434C:1AC91773E3C74B1AD2CEE5C1B73FF762:\
+000000000000000000000000000000000000000000000000
+
+FEE6CE4F8F3473E5D53ADC2514573DF1:C05EBE4CA1556875E88963737052A6A1:\
+000000000000000000000000000000000000000000000000
+
+BB4404D0A1E08F698567D378D635ACFC:310D5B8AA72771FAEE774429A2E30D34:\
+000000000000000000000000000000000000000000000000
+
+CBECDA615EE251D55D88AED51A7396C2:005F978045B1C78F2C9CA70BD740AFD3:\
+000000000000000000000000000000000000000000000000
+
+216DDCBA6D7CFBDD704C88573AF3F539:CD5540951B363A8FBDF9E93C07C8B071:\
+000000000000000000000000000000000000000000000000
+
+32DF83737E24CF91823B1F444111F6DC:0A79A5601F7FCAEC1DFEDD8C5D6517BD:\
+000000000000000000000000000000000000000000000000
+
+75060574E3BD1829C1F7CF663CCA1519:404CD7A5AAE2AC614FBE46931040C028:\
+000000000000000000000000000000000000000000000000
+
+793C8015C6E8E72E56C13561FD6E724A:6F8FC5142A5E63B38B3CCC1934284FE5:\
+000000000000000000000000000000000000000000000000
+
+56417631D25FB77C8D31D1575FF069AC:11F8FE61E550FEB615970C2AB8ECCAC0:\
+000000000000000000000000000000000000000000000000
+
+E99EFADE32414801A624E62C62C28FCC:C3C7D21CB5A94B8614DE00CE1B7A9DC2:\
+000000000000000000000000000000000000000000000000
+
+EC4566488387F51E0B509476670E83D6:191E27160A8A8475ACFD683F80DF89C5:\
+000000000000000000000000000000000000000000000000
+
+B2AB44DE9321FE39A4DCBDE624578893:54D0B5AAAE4629FE22EDAC6BE38B9B9E:\
+000000000000000000000000000000000000000000000000
+
+063D84A689AABA4F20C38265401497E1:181EAFA411D7D022A5AFF1C1C212146F:\
+000000000000000000000000000000000000000000000000
+
+745D52CC6B6724A03B1402D936BE3B7A:52624A4310A885F6F32BCE889812634A:\
+000000000000000000000000000000000000000000000000
+
+DE9C438C39CFAF705449EBE35BCC589F:FAC2134E1485CB8C7ADD700772A7E5F0:\
+000000000000000000000000000000000000000000000000
+
+67CAE47F0EAB98431E79565F6AD72FF9:1D77938B41CB3EBDCB2E972C23814361:\
+000000000000000000000000000000000000000000000000
+
+190E8E93E5EAD47C94FB6D4410710A40:5E0495D4DBB66892CE35E4AD8080DDFE:\
+000000000000000000000000000000000000000000000000
+
+1F4C0C3D81E34FC56D45D33A491C2AA8:B3356A3EC0C1D308CEA5B5973E78B7CD:\
+000000000000000000000000000000000000000000000000
+
+16F1E59BBCF8322F6B0880C77E0B3AD6:42275296C51FCA8E244BB17C1EB2ACBC:\
+000000000000000000000000000000000000000000000000
+
+95BF7A5EC2029FDB6C51C40407395862:E92D9E263F650E222E90F0E59B2AEFA8:\
+000000000000000000000000000000000000000000000000
+
+F4B0AB203C3C741A527E6B25C0F89B8F:0B09F057772F30EB5F7C0C777CD14CE7:\
+000000000000000000000000000000000000000000000000
+
+9422B9FFCA4204AD7DDC56DF5C80ED5E:B2835EECC60F78F7B14588A8FD6069F2:\
+000000000000000000000000000000000000000000000000
+
+0756858E5C3829E8F3C328C6B4E3E1CC:7F56E94897ACC5D0F60CF899FC4A98F5:\
+000000000000000000000000000000000000000000000000
+
+5C8E0338CE66CFB584307A626FA4527B:D3819C5E8A9B85C86281FB7D835B7503:\
+000000000000000000000000000000000000000000000000
+
+524CAB3F0BCAE900B7DC16839B241B61:CD71C2A15B1A5B37DA95763CF68E05D8:\
+000000000000000000000000000000000000000000000000
+
+74B3CC8FEEC75C97A94EEBDA55B8B16A:A2703E0DEC3649AFAB35157E7484A43C:\
+000000000000000000000000000000000000000000000000
+
+33C6D143B8E9D1F06D1339B86CF61591:BA98BC1E73D8E0B7AFA5F2BDF5755B95:\
+000000000000000000000000000000000000000000000000
+
+EC3DF67F0136BA492F33AE0DB8FCB598:F23C047EA741E9FE948A56D8CD3D050D:\
+000000000000000000000000000000000000000000000000
+
+EAA6AA8AE56FD97D6BD6A22CA1250287:D0B414653510A3EC079E38806F87F643:\
+000000000000000000000000000000000000000000000000
+
+52C3399AE7244A4A7C2F2CDB8F371753:819E2216C7E18C2557CBFD688C17305E:\
+000000000000000000000000000000000000000000000000
+
+AB61C1BEC7E3B2790B43D64E53E48B18:A3E8D62480544EA1643BD7FF5404E40F:\
+000000000000000000000000000000000000000000000000
+
+B08CB946F4201AC88F721B850A5B3CB5:ABAF89346ECE6F72C054C82D1D440C38:\
+000000000000000000000000000000000000000000000000
+
+B5786F5DBA379E835224508F11E87B69:93BC3706B91E27EF0CFCBDE69C2559F1:\
+000000000000000000000000000000000000000000000000
+
+40B89D11E03992DC28F90E0CA7949B75:6153A846AEF149D02F8D1EBD0D492F75:\
+000000000000000000000000000000000000000000000000
+
+3371D59814185FB77AB6C990CAAB3BE6:9B4039BE6A0953CBCC1D7FF0C7E73BCC:\
+000000000000000000000000000000000000000000000000
+
+8BE18C0E0C9C5A94948BE1F1C7353C46:283A4944BFA598A114B3BF601B68B823:\
+000000000000000000000000000000000000000000000000
+
+3A55F569D34407976540A728FE4D7840:F3DC2926970112F59FE3A40A3F8FD470:\
+000000000000000000000000000000000000000000000000
+
+92E46A94F8180683A850126F5857F4C6:E246163EBC3F740A288F6105F4F22B97:\
+000000000000000000000000000000000000000000000000
+
+CBBE214BB2504BEA8BF54D4123465715:D5A46FACE3B1D97AC16DB73B3BE3EC3A:\
+000000000000000000000000000000000000000000000000
+
+4B95E574D0BE514238BA4DFCC06535B2:055C146C457B2ECFAF18D244D5400D31:\
+000000000000000000000000000000000000000000000000
+
+B89E3644479A3540073EF40E0F090019:F2C9DC621653315ABE6A627ABF40F24D:\
+000000000000000000000000000000000000000000000000
+
+4A5D02C4799C8C26F1FA7F715EFBB800:B2F714BC4B21FEDBD79054A507775EF5:\
+000000000000000000000000000000000000000000000000
+
+A9D5720391D7ED3B2A23094662FFDD5B:951C0FFF6981E9B1B4C792B4A81AAB7C:\
+000000000000000000000000000000000000000000000000
+
+CF5B1C437A54DD6F29D6F589D26D13D6:6C9FB40B31372C1DA4468C0EE559257F:\
+000000000000000000000000000000000000000000000000
+
+8F548C2248B76EB8CC4DD0272B93D532:56DEA9C72D8E2325A9AA42E29A3270DD:\
+000000000000000000000000000000000000000000000000
+
+E09C2E4DF75ACFFC3B8E880AC1F01FCC:D1CD44336BCD0928C4A9616D16379B56:\
+000000000000000000000000000000000000000000000000
+
+FB1C12B77C30E6DE6DE97CE8D8D913FC:6947499CC1C807290167A693560002AF:\
+000000000000000000000000000000000000000000000000
+
+127D02E20E973573296A5C82CDC83404:410374320F1B4AC6FE745C5973FEC5A1:\
+000000000000000000000000000000000000000000000000
+
+91D02F2862F596944FFB92C74EB07BF3:1A7B5A06628C5871E684A2080ED903DD:\
+000000000000000000000000000000000000000000000000
+
+6A46FA0A795B4A9E7AA998526376127E:2186A2F79A90DB5601A4BDAC7F055A92:\
+000000000000000000000000000000000000000000000000
+
+35C4EF822C59ECA05DE6CFF2780BD44A:3D6BC6771061B7D45C60335A9DB19E55:\
+000000000000000000000000000000000000000000000000
+
+EA374673B5E6A56004A029F45137ADA7:C19D85F934D8AEFA589489736A76DFC5:\
+000000000000000000000000000000000000000000000000
+
+4E3A751A0EB53250C90A572D39B30FCB:6AC263B51493303AD36284D872F3941B:\
+000000000000000000000000000000000000000000000000
+
+E581C99FDE13BAC81780AD1BF416A2ED:6967E6479E599B1BC18645C961557BF1:\
+000000000000000000000000000000000000000000000000
+
+288BD3489BFE7596F58218A0AB1A73E7:6AFC72E6A27C640F2E52528E9CD2591D:\
+000000000000000000000000000000000000000000000000
+
+64B69B2977852C6BBAC03750900356C9:0AC56FF8773D5AF3420974B16AE2AF14:\
+000000000000000000000000000000000000000000000000
+
+2F1B45AF1428E9742ABB21D019ECB5AC:ADEA58D721F2398FD4C06BF0F0727505:\
+000000000000000000000000000000000000000000000000
+
+49320C39A1BC3BE5AD09E3E9E120513A:8CC627E3557D252B45D08DE6B6896E48:\
+000000000000000000000000000000000000000000000000
+
+55D76389493096F7D6197B7F8B6DF193:9857385C7D044284A3219004666E0EA7:\
+000000000000000000000000000000000000000000000000
+
+2A27D235903911F331DB639B75C0D712:9B98F50C0ECF24CC1D86C9673D8A083F:\
+000000000000000000000000000000000000000000000000
+
+419D7555072CC127A4471A05CFB19CC0:67FF3F3267642FD12B4C2889078613D1:\
+000000000000000000000000000000000000000000000000
+
+9FD6F61B1665F5AC5AAC2FFF89BF92FE:37866C10AF2D0594C42B936AD5266A4A:\
+000000000000000000000000000000000000000000000000
+
+BB090A45B89E261664A6122AFF274007:82DE14AB89CDD323CADA9E38567E3089:\
+000000000000000000000000000000000000000000000000
+
+157BB4035D9D9014CF88B9E934A7B8BD:19C07DD91509033BD3DD978781873EBA:\
+000000000000000000000000000000000000000000000000
+
+A8870F1B8C1D5D85484117F4C6AC4530:2347879BF12456873B80EE906110B8B8:\
+000000000000000000000000000000000000000000000000
+
+908C16F16AAAD352AE911C197192719C:2C2745EBE83EABB93D0A920D07BE0DB2:\
+000000000000000000000000000000000000000000000000
+
+1653D7F835D83859EC694970707CC095:BCF6DF6D1EEAD65E05BBE987CFFD3702:\
+000000000000000000000000000000000000000000000000
+
+0DE06413C85A15D5D8947AD534B2B696:7287E1CD26D1EE3CA342009AF49756EE:\
+000000000000000000000000000000000000000000000000
+
+3B543E3D80D1EAF921CC68CA776239F6:BE313F5923BC9889B3860BCFAB775453:\
+000000000000000000000000000000000000000000000000
+
+672218755E587021EF7B02B7BCC30A61:E1ED846BEA255A1AF1B92EAC79B9CC10:\
+000000000000000000000000000000000000000000000000
+
+811D93DE4A4BBD9414820BC1AC1B1D15:18CE61828267E31A11F44B359F5137AE:\
+000000000000000000000000000000000000000000000000
+
+66B96FBE50A59E0D613B86DE5017D5B1:BC46D6CC0344D2F8509C24B6BD961C7B:\
+000000000000000000000000000000000000000000000000
+
+EEE81506AA7CC547B01464EC138A2243:717D1A1B155A403FFDF7CEF95A0F3704:\
+000000000000000000000000000000000000000000000000
+
+A08B5A609A311639984749D2C3F17B66:0D9C67C97883478626649FD699984E37:\
+000000000000000000000000000000000000000000000000
+
+64D1AAD4D2F48E1253CCB198DA194FBE:B4C733307E59EB660B0A6F8154ED99C0:\
+000000000000000000000000000000000000000000000000
+
+4589C65EF87C151B68906023145F257A:80E66CD1BE95CB7352142568839F97B1:\
+000000000000000000000000000000000000000000000000
+
+C8AC7D6611C15A08D8850A6409175296:C93BAB0F83F23EADE7A01C0C1C4B924A:\
+000000000000000000000000000000000000000000000000
+
+68AA5E6050AF889A0489CAB2B21485E5:7AA6C6697016001A666928C97EEEE3F5:\
+000000000000000000000000000000000000000000000000
+
+A1158411888B7ACF4BC31E9DD67D787A:2498B680478226FA74B2880E485DA409:\
+000000000000000000000000000000000000000000000000
+
+214C17577623146613245C15C2B49493:4BA8DE835393DD25A42ED04F69B4C2C7:\
+000000000000000000000000000000000000000000000000
+
+C9D85D545FB2F7D9AC22D8161178F590:163A9559BEAE1A2F3DD42672099F725F:\
+000000000000000000000000000000000000000000000000
+
+ECD0DFF95F9AFAC0FE2C5A95543E6567:AEC277D9AA85F6221D9ECC3C55514020:\
+000000000000000000000000000000000000000000000000
+
+81F92762F3C9A78E25202DEBD990B79D:EAB0B505DF3FD415181D2389B7E9CB7C:\
+000000000000000000000000000000000000000000000000
+
+36B9CA495A26B676C5A73115E4FF2D1E:ED36B0A23E7A11F171A1FD6041901C0A:\
+000000000000000000000000000000000000000000000000
+
+933836CD34DAE3CE8667A2C314ECBFD2:F52CC9AE0294245C5785FA75F7CD565F:\
+000000000000000000000000000000000000000000000000
+
+547BE19FEAE346CD3C232B03CA1A5FE3:BB506E47BBD9BEEBE794A888D3CCA4B4:\
+000000000000000000000000000000000000000000000000
+
+3224DA0BF7369941B581C1991B0434F4:83F1AEFE1874155EBEB71D3BF28196DA:\
+000000000000000000000000000000000000000000000000
+
+BBF274F554349AC9464BD0701CBE3C01:08747CBB4CE827BB8D7125B51F7D6B51:\
+000000000000000000000000000000000000000000000000
+
+0335215F4E7DE6C6844D5F4ABB08FF8E:753D67B79C27B62F66CAE343120FF8C8:\
+000000000000000000000000000000000000000000000000
+
+0E798B0937AADC31E5F4B1059BE7317D:D28E3F2EE5CEA4AC47B479435CB879DB:\
+000000000000000000000000000000000000000000000000
+
+B7C8F5010674F177A867996E62143129:803B810C554A684442737B08747A7B09:\
+000000000000000000000000000000000000000000000000
+
+3C82EE0C8AA57B1A2809A653DFC34EE3:DDF2B574C748E259D0B60E2E7296F5B3:\
+000000000000000000000000000000000000000000000000
+
+245EAFB34BF4A2DE65D2AE9E02282DA8:367A33838C4E1D75EF86882F13F456C3:\
+000000000000000000000000000000000000000000000000
+
+82BBE96F7A512752B34873CE91BE3A12:D80CA3A1104B1BF33C78A4126CA44D5E:\
+000000000000000000000000000000000000000000000000
+
+017359FCC78CDB959AF03170515DB2A0:30B7EE3A4EB1B90FB4F773004894A1C9:\
+000000000000000000000000000000000000000000000000
+
+FBE1BA1C4C9E9266219E290CA482204A:23C853980380C75EE387D499EBDC704E:\
+000000000000000000000000000000000000000000000000
+
+7A5D60B558F7BD79506EA361867D82DD:CEC694480EA0FE02FBCA486A38D2A28F:\
+000000000000000000000000000000000000000000000000
+
+F6E1A13C90CB990C8F98044A14153C63:5DBA1D0AD1846EA0DF7572D9796EF6DE:\
+000000000000000000000000000000000000000000000000
+
+BE618966B8BB4C5161F16E614BB0685E:50511C6F323AA75B27D26AF37C96AA44:\
+000000000000000000000000000000000000000000000000
+
+3430CBCDD6B31EC832674C365313412A:2EC7B023DAB88616A4069732083ACB96:\
+000000000000000000000000000000000000000000000000
+
+B736C160AAB874D2FEAA7CEFE95067FD:B7B0662681E21B41B0211A4C347410A1:\
+000000000000000000000000000000000000000000000000
+
+E76003121CD25AF053388E29F5CA6F36:936E6955F7EF756AB1C6DC0510158338:\
+000000000000000000000000000000000000000000000000
+
+895F077285060573E7E66A0C610E1A6D:A3B7E3A9424D60A1CB63B445A4EF0C4F:\
+000000000000000000000000000000000000000000000000
+
+E6EE0CBF63758F0C58F7FE5B148BB755:68EC11D4896B18797DCD1BFBD91851B4:\
+000000000000000000000000000000000000000000000000
+
+54077665477046E8886AD6E46DFEC14A:EC98D4903AD222137CD3C9449508940B:\
+000000000000000000000000000000000000000000000000
+
+33DEC99C9A886FE526909F940883E559:9364AB8B76D6AF8E7EABE315EA9063ED:\
+000000000000000000000000000000000000000000000000
+
+A1E7C5A9D7C2FFBE20CB4DC98727945B:113D49B50A78202134B0C13EEF987C86:\
+000000000000000000000000000000000000000000000000
+
+9C1DE13B101A9B72BB5625717A02E6E5:6C93D650BD87DFEF03563CF268EFC950:\
+000000000000000000000000000000000000000000000000
+
+41CA06F619236D40739E3200E2AB1387:11470B6E8E0BA5340322BC3F17273EB6:\
+000000000000000000000000000000000000000000000000
+
+FD432B900CF8CC44492A491722D20F89:DE117E6E44548F9CB5D419C8100343F6:\
+000000000000000000000000000000000000000000000000
+
+7EEC086D6EF264233130020BD4678FBD:6EB1B6AB75C0DFCE7AE826D8EFEC745F:\
+000000000000000000000000000000000000000000000000
+
+243F6735A4F71D6B0161589E98367741:5B40A381C52F55424C1903E2A6C0A612:\
+000000000000000000000000000000000000000000000000
+
+39B2D6E42C80C5A188540586F0065DCD:EDBF0C2671F1DADC8737F93FDB17FBE9:\
+000000000000000000000000000000000000000000000000
+
+BC9838D89EE5D90B5FA7E5811B588D53:26967E5C460F2571B5DD1381EFE9B451:\
+000000000000000000000000000000000000000000000000
+
+9CABC3BF9C9FA7E16C4632FF8A07209B:9069D1FB3BD87893CA2C66FA10174B8F:\
+000000000000000000000000000000000000000000000000
+
+F6B613AC53E11B62FF73D1F15D946399:EECA346E8823823C821E6E8010418BE1:\
+000000000000000000000000000000000000000000000000
+
+6212297702FA172A0B7C0F60D0536029:154A8C133987DAC7C829C62FEFADBC28:\
+000000000000000000000000000000000000000000000000
+
+B06732B03AA1E215930EE18FE970CC8B:167D74C63CEB050B4F14B1CEDC25C642:\
+000000000000000000000000000000000000000000000000
+
+E4D63CD417596F627FB4EE54E27FD338:167D74C63CEB050BB0EB4E3123DA39BD:\
+000000000000000000000000000000000000000000000000
+
+473DBEF5C2FDE2774B2858166DDDF9FE:167D74C6C314FAF4B0EB4E3123DA39BD:\
+000000000000000000000000000000000000000000000000
+
+62E1D3103459521F0F479B9115A6D66C:E9828B393CEB050B4F14B1CEDC25C642:\
+000000000000000000000000000000000000000000000000
+
+E1341D2FBC279ABCD4EFF8898DADC3D7:E9828B39C314FAF4B0EB4E3123DA39BD:\
+000000000000000000000000000000000000000000000000
+
+8B45F9AA3FC0589FA05364CE5F5D2F1B:E9828B393CEB050B4F14B1CE23DA39BD:\
+000000000000000000000000000000000000000000000000
+
+BAC8FADDB63387F8927E816010E0C506:E9828B39C314FAF44F14B1CEDC25C642:\
+000000000000000000000000000000000000000000000000
+
+02D554DE3674CCED1D337A873B77F5AE:167D74C6C314FAF44F14B1CE23DA39BD:\
+000000000000000000000000000000000000000000000000
+
+A647F5EC14A07189E9F75F937669C276:167D74C6C314FAF4B0EB4E31DC25C642:\
+000000000000000000000000000000000000000000000000
+
+4A6C0DBF87CDBDE1392E198E5F9C54F9:E9828B393CEB050BB0EB4E31DC25C642:\
+000000000000000000000000000000000000000000000000
+
+FD812C0AFD3E15E40CFF9A6CBD0A0BAE:E9828B393CEB050BB0EB4E3123DA39BD:\
+000000000000000000000000000000000000000000000000
+
+0E41AE2781D439F0671744D4A4BB6A9F:E9828B39C314FAF44F14B1CE23DA39BD:\
+000000000000000000000000000000000000000000000000
+
+AC335553D40961A3387BD2D2BFA6EDB3:167D74C63CEB050B4F14B1CE23DA39BD:\
+000000000000000000000000000000000000000000000000
+
+E39AC2845BBBE8EDD743205ED7DF1DB6:167D74C6C314FAF44F14B1CEDC25C642:\
+000000000000000000000000000000000000000000000000
+
+AA7F44B5D845906C835C65AE12A044D9:167D74C63CEB050BB0EB4E31DC25C642:\
+000000000000000000000000000000000000000000000000
+
+E3E1B65693171906DB775EC7E4CAE204:E9828B39C314FAF4B0EB4E31DC25C642:\
+000000000000000000000000000000000000000000000000
+
+D095576FCEA3E3A7ED98D9F29073D78E:B90EE5862DE69168F2BDD5125B45472B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890CEA3E3A7ED98D9F29073D78E:A3E17E2DF4EA6F41B2017E37023F202A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576F315C1C58ED98D9F29073D78E:FD2951E466110BC6F4816EBF968CDD01:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890315C1C58ED98D9F29073D78E:C36EE750C51192B0C85D5BB2584AE062:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576FCEA3E3A71267260D9073D78E:86069E27F65F454C6E3F7E9097DCEFAA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890CEA3E3A71267260D9073D78E:00FA885A8854844C970338841CA2E24D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576F315C1C581267260D9073D78E:A18A399A0AA2FD20EAA740A0CB6145B5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890315C1C581267260D9073D78E:3D79E39A79CC14D97147F3D172F66BB1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576FCEA3E3A7ED98D9F26F8C2871:1D34FC93E24880F5AA52896494590502:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890CEA3E3A7ED98D9F26F8C2871:9B9FE52195C3DF04ABF49E88AE46AA80:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576F315C1C58ED98D9F26F8C2871:439C0750227D7CA832DDB24102C7AFE6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890315C1C58ED98D9F26F8C2871:498BDBB479E9AD3E0C9EFA977827A7E3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576FCEA3E3A71267260D6F8C2871:A276C04597DAFB6459A1483051B6A74C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890CEA3E3A71267260D6F8C2871:4D4D78002EDB3AA6DEF37E114AAC4C9E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D095576F315C1C581267260D6F8C2871:3AB14921E0F755A63DB9F7DF82030E6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F6AA890315C1C581267260D6F8C2871:5984934E048E623F6F1F6E846F655CF2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BCA391A780641EAADE755440D55B7C79:8A23D955A8EA12C9C49CB6C87772D56D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+66B9589D9B8BDA10A7B61F08F1BE4ABC:07D9508924FC120A8C9FA3298FEB102E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F95A83752C766787DCB61FE8029EDAFC:BF79657FE10E1D40DAB5107AEC3902A1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E4BFB5F01F5AE8D5DA7554A0E6841386:B0B5503E111AEBC1222FD6CE80FC95C0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3644C76F916C379DAA45F4C5455B5E3C:1B33D206D927E2E504E1E09A2913EBAA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+524C7C18D2890A182C794072D8AC1AB4:18F0F5819A31A3634925AFC4204A292B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9D422AA2BE5665A757794092849EF859:7ECB8B26799C72C688138B0303F5AE3D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+49B56E8A5D8FECD5AE45F425AE96438E:465911E4D18055AC9CBCB179AF8CF563:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FB7281A7A7B11AAAD386BF8D0F51AC43:17AA2A72EFAE82D9E6DBA3F7ABDC5E1A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E1B971981BABD8D055BA0B3AEC65A383:1B97AEA16862EC3A8BFA2B6CDFF42C0A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B68B93750474B78F51BA0BDA506BF539:9A81D6B18847AABAB201BC773C9578E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+63BF9C151852C102A886BF6D7BA005A6:F1F1EC24882931369E45DA6FBDC72944:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+19420367B3B9339D5849E0F70F79A5F1:D5E43C42C34FE1280CCDB69F1E73B1D2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+42647EEA57A908D8218AABBFAAA02783:4BB5A2BB9A00F6132F9301E068076067:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BD44EEAA9454B5AF258AAB5F4143FC6B:3A379C7CAD8635724825D2D35DE4D95E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5E9D6C985887C5022349E0175B6581A6:D6CD8A324A74397331E7C7913BDDC40D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FEA66253C13150CCA139B2A3914AF942:617F156CB641731508E0C2C24F30AF8B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FC0B8D5D7C9744BA7954677CB0A27072:600DE4F0FA8EA6DE1BA1CAD12D91AD70:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+554233FE589683EB6DE4AF5360954967:14D887DDAC1D124186DF25110C618B63:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+445FD65B8A616351C18D5D9E94F86F96:B2A26A5E4540434277654B4FCC76CDB8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+47AA8DCFCF3FBA0684C89CAB9A2A92D4:2BD5D90CB296016CE9FECB90E454FDE1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EDA94AEADC314960B491FA7245CEA146:0395D2ACE5006BE2DF6EDC521CFE6372:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+113106465C379FCE76477527E045D692:7972F08BD18D0B16D67BB3BF99DDD096:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3282ED3A1D687E195315A034F83C248C:BC778D51D757DD9DA5F5051824FD7159:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E30A22BC4986B7851ED0F915AAE95325:D913538943E1553B7A9F9D6C87B7FB26:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+07EED76219973E3CA5C48B1FAFDAF3FB:757F50123AE84DB0D11DFE21A61C606B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2D9D06E07874A97BDE16CF54856BA690:CFD9B00579D84963621B5169E70863A9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+843381809D9CB637FEC0A99486A13157:31E0FAB5DE7BE867A4272D12FC4F05EB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F5F9C1F4B2C6E62BC6FE72AD03B0C93:F4349842DD05F5F81EA9302869793D73:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+294946180CF7EAB708840814BB2117D6:ABB6C4F719C839B0A35B24E2171BA15A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BD61CF3CA72F7B0547D7C86606DAA046:2613987BA99FEF9315563EC460A2BDA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+858989634E54409DD72739F6A270AC5E:A0190A0D109F01A0BE0D9C2AA2BA79EE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+41D4C7B9FA3BF27861B67D28CE795543:0A08FAD749BE5EAB5C3AB317951790DD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A753BFF7F4E43CAD48D7CCCEEFA69929:100AEF381EAF8A677EB25B59FE299357:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+23606A3D54D13B00F9C5C73B8986116C:CFD0988E16F3E2C00B95AA284EC61790:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EC92B059C312D8552048541FA0C08D41:3D463933505FCA55D7D1DFCC70514247:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+911F32CDC4AB95BE21DBB26D02C85A39:6C6822C89035170C6550399D7611FA01:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8314AA08DF9729B0CADF46FF74804827:268F3DB80AA9D7216EB66738C4EF6F7A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E21A90DABBE27C02FB1B60A948401A2B:BF82462448C407E7180DD8150ECFD379:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+087CDE5529FAFB124E8595EEC504873B:7C80B7A4CFA1FFADCC6099AD6EABE246:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+625687201937916FCDA1BCD9F2A848C5:891E63EFA3554394459FCEFA252D182A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7EBA3AA477A029664D9E2E9B99F6140A:2483E89D964CF99B3FB0D1A3A45782FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DCCEE8E27ED8D75763F7524A63D215F0:028BC9E5F853A160F39A83803AF2A7B7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+19CFB7ABF48179C4851C2F25C92BA826:26221D701683AE54ED151ACA84DEB442:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5CBCC9B2BD2F1D3EC82642035A092467:8A5355C93A66CDFE21EF6842CF80E31E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+082504676AB8766CA4F738C7BBE124BB:2B9E10C57473AE627D43266970AE61E6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6C0344E7FA166C41B4199447B8320317:8271EFE5D0E0D6274B8A1C920086FE65:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+083C6A6AD16559D929D128016819210A:7DAE9CBFA76042FC9096F4A6A143AF9D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E234B590C30CE6F2A068598498FE14A8:3BFE3D4FE7B417DC0DF94EBD0AF57154:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8EBC8A9B40C2710981158294FC1524C0:3C6B2E08A25BB1C9D8E891CC19681A2E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A4A883B169B2C1EC1ADFBAB989779DF9:8D1D2E8B3E4B8869F1FEAA1AB2975170:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BE11424787E04DDE5B6D87C327AE5D9F:CEFD8D50D4E917DC70849A1CB8CE3C2C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+32B6435915AF7E05F759494479E6B294:C4563E114E1EE39F46FB68ED092D7C27:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+07A09B044F080EE504D92A3DAC01D303:258AE473968C1DA8EFD1FA5E340A83D7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1E4325EBF0CD71DDEA3C8B3B5FF23E29:073A7BD1ECEF25E0206C9042C00F6731:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E45CD56C95DE72CA3697FA647A0EEC54:57C8671286D9996FEAC834D3692CDABC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+58CC453047697A9D4855613C742F9688:4A56D387BD10C8F7A46C96C0E2F678C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8F4B0DCF7323F12D2C6C3301E1A86CFF:59A2EE2B3F5D52A1354460582394F0DA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+60D7A7390C51292D63F8E13D94DB66D8:D347A65241A7BCF70F04A68A6BE2ECEE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FFAD53B9D3B77B103BF9ED6F7A53DE31:3B16D9CF3680A56D4A23722949AA2FFB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E3913FC5766362632C0AEF411A2329BF:6C5D76419C71E3A34DC9457B990708CC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A6473B8402F5F57FC4BCADD69DA23F78:190CA4D0F4BC089B3F26F03E60290FC1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B714071EB4260C9A0BD650C7E19832B7:B730D4DFE3ED225B06B2A3BEF52DC790:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+388C8FC9F048D4CF103C43CB275179F7:E2FAADBDD818C6F4532758EC96C56A73:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+90934F3C5F5136B11EFE5FF9DF9DA0F1:9D593FF89F7EC95ABDC3B4F8D2B5B3E6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DF2B2ACE7CBFC27887E5483DABDF837C:ED1D6AC5EE3935E6DB4CB7E34990AAA1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BACCF7E913B35F887489C30258B7C2E2:0A9D724CFC816E5CB13A2147BC64D694:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D23A16EE588C5188610DEC181C6C7DCF:9084606C1FFA7A3B8C27977953C686C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+75D6E08BE0C85693706F42390387F792:EEEA1012319432080499711FBBDAF413:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EB7A15C21595522B52FFF012D5B98D5D:70EF833B23D8985C01B7F68BB732035B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+50BD484FE42B4A1C49F9F24D2A0BD279:50F7C8A8D280FED79EA137B19B6CBF63:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+65210A79205B1E90040B30205D60EC0F:CDCCED47818563F849FB6E2E03A536BE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6A6016462364EEF36CD86AFC407DF814:C003B86F7C550805EA2C4CBB0D18C3C7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1354509926BD2A9D24C3E1C343E57685:084EFA18B92E39D6D5929B8A85EDEFA3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+69D5AB6AB54A51F89510DCF5CB929443:E267FCCBF14660B3283B79DAE067CDD5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+936F01C43C2AE4F6237A1198DC1B9A12:E181F5288869A4BBB5BD7B982DCE044D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+09EA3582964BF1C95FC528262D40419A:ACAD023D370F43350F141B95A7EB2B82:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4B4E58B375BDC9FCE5029C3015EAF890:95B8EABE9BC6783C4FF9A39A8188B6F1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8AF33FCAAD22AC2F30C1864E8CDC44C9:F7BE2FA21170A24902994FCE2753DF75:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8F2947144FDB524D6A7E4B8653079109:D7F8A1A155707CFFF493091126ACAF81:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4692BD551D478DB55B88577C51401C74:19CFCD975F915B1B91B52B0A3F0AA9DD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C9006CD66124A21A730EFCFE380EADDA:1C30408126876EB5352A751E29C7CE24:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6B77C29FB0D9236EE31FE1F8DE56B87E:0AFDAA45047280613BAD45D03DE88740:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+54AE286A42141274F79B54DFAC4CA6BC:C68A8E4FA3C13CF7479BF429FEDFE303:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F6FB23BCC18F091F9B8A0284BB112316:C3D26D89600BDA652A0666306BA5591C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08F5A81FF672643FEB06241372C1A7EF:85FAF4EF8BBF9AC0680FB8C23475A52B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+50B8A6F3BA479442E47FF3DE5EEABD0E:6267A16EB828E472607915291BDB007C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8379BE367A37C3710331628CAED61D6F:28509647E60895C9E249CC82576465AB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+48D56A98749F23C5221B2BBED38D6B41:F98CE8293DD9DC8AB4661A44ED500908:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+81952B3F6E16345C8EB291532F8AA55D:2C8CF6EAE96494549847454E451F574F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5F98C90888EACDE82696B9F02CC845DB:BE3A8C77C84E12E8F8427DF0CC591681:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F079009892C0E82DF27E805CDD767EF8:810E8C7A31A49DE7A02F2744F490C0CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3E1BE2C90DFFB9C7D858E23BDE70C3B3:A336A43F20501DE36D9C42DCC69B5C3B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1D8C428C8F0D7262D2109B9D1E16EB51:B11FD9AE0D67CBDB7F990DE4FAAE2A61:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+801EF23541E6FB654C3884771578AE2E:8F1042F616351D5FDF929C50F3109169:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40B14F285E32BDD61B29160C0C6BB610:4D5E33A7533E71FD3C4BFD7157FDDEC3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4226A372CEAAC4F1AA0BFA2588817D8F:D1E9CF5BCCC71CB62C0D57255CDBC2B0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F0353993A789A852FCEE7795E3DB8235:D0CB3CFEA6162C4DD7F8BC29E4702344:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CEA8A3CE895CB4252905D6E8FC7FB8AF:BE8CC9E62A360AAF0F0C3B59F09D6509:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FE7CC498A82A8DBEC2798FEE7F4B6BA5:31489535231BFFA6B300949589969866:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+80703279F021C9624D952AFAA3E1FCCD:EEF27A88328000A4CA3BAE8FE26D03F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2926397A6E38A4EE7D1EF20F31BE8702:626B25E780F216EFCB33ACEAFF53D346:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F24B278B89128056E95D04412819031C:52A77408ACF9483F3360CAC1EEE7CB66:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+757846E9F24ACA7BBC53057D86F40DF7:D9909AAB2D47E73F5B2AC8B4D21C5152:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+69F036E5559B53AC0BE4D71933C9FA6D:B123F297E11321E138ED8B797E3935E3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AE25363E7527BA574B336B3658043EC5:531265FFA27309E010682226D40FF301:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+261DFB2B0FC8058DE4F2BA0E9D07267F:73191403C7F106220730944CF664DBDD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F4F44EF26EEE2F214E55FFCFB67F747C:B27B0272C70703C163EFD2AE9B696D68:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6E7D61A090B1DDFA455A9334F71B1049:3F301BB140FE500EE6211F5EA8C475D9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9BA82C854F0602CF32A7A1FD454A244D:0D07EC51FD0EEA788F4F4118CED4F76C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4943602AA81A1B09F25924A115038BA6:5DB3CF4BA15D10B20FA1C16CD38AA48A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BD655DC9F095901130F61D7461169429:3F1DA00A0B1113E731F09A18012FCAFF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+881C7EAB3D5485EF3001CF123AD232CD:7739D6C688AECA837B665E163D7807A5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DB78BB44ED268A41D7BCC768F1C1DDD5:EC9954AD43C78B7F3E54437EADD41E45:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EDA01E4405F7A5879C1D9DDC99E494E2:5714395272B96FBB8A4DDF3371D99285:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F43DDDEEEF8000C262E2CC8025E7F7D1:3A78EA14F436C82606F3EC036DEADB82:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F67BCA996B8F68C6178CF12B69942EF4:51982744D0D4441EDC22E9DB28148AE4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1B2F9DC1D0081629E2D783BEDCFE556F:0142F890C1EC3B1324242A6266DD6E35:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7F697D4DCBE48A0E0C1B76905EC5387F:B5ABE383FE29DEBEAEEE1B1BA216617C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0087BA91A953F0AA37D906B4F83F539A:2DF146BCF57886EA715DEAB67FC919DA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8BA37531E5AC90DF7C274BA0F09F710F:683F0B9893990052F5002D12060F8737:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+31D0A790D8B5F52BE0B6AECC098FFEB6:709631DDFB876005986AACF3CDCE4309:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C582C293E55D228095BD51C634ABCC1F:EE5CB6D8B964B9D6D45DF97FE26C46E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+82509552588B0707D8E972E34D34FB6B:A8BB6BC6E9044A7D4C0ABD1A63EEEAD5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+92DD30BE9D6FBD8CC3CD6AD5A02B9644:E743F0292626C7198388BB07B172E203:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F533132CEE021C1BE4E27610C7FE658B:EBB22F93A2709B4FCAB29DACC2B7CEBD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+821E2D8D0E1D8DF54F92B0872C26F647:B8AF4BE5223225DF4AA9629C6F3E5DB1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CAC520ADB6D2116EFCAE1BA9CFC07A8C:CBEF84E5B8BDDEAA94FD63FB9C196B95:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+61370431D23B19C9919F90FA630650C5:C9B61AA02DB1164F68A5439133AD0CDA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+399E8C6EFA778B3B0D7414905FAB7FCB:144085908ABF7F86FF737DFF301F3408:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+14189BC9EE6D85C59A56EAF1897C8456:2BE6F430D40E3E43C9C0DBFBE68B2550:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F1E5C20447D785B4AEE92AAB76AADA7F:67E726A625DFDC0AA862F8BBA7097B7B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8FAAF9826481DE26DCA70C204A9060BC:488470EE1514C99C1CBBBF21D2205EF2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B6BD97EB4246524E123EAC300B208AF7:5BE2B23A54FB35FA83814A2BB9C402AB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0A78A42122FE13F849142522BEFAB9F9:04501EA5A82BCC7157832EEDE91381FF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+46E4EC66D3EA604F4F166259F8B31F04:6D2DE018B6024B5860C5F8A85D8BB034:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20AB8FE133F07559C320D5B2C41FAD15:C13CADEF2B413DD1CBF3AB479BD2B9B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7938DC46E7E3DF01F3A24D825BD86672:EB2B02D0A6908C51580D552330189C94:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7F7938F0A5BD91783AAB003AE1BB79AE:B54CA133FE06CDF7C37B421559F72849:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+91A8F9C577E2852E312DC4A5C1255EE1:0EAF829E6680344B639E5F45B0246598:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+ACE62912A71A4F34B672D9C80B73E12A:C91C23C725254124B118BD2DF16FA907:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5B3F25EAA264348B446EAC39C42AC7A4:6FBD63968E0B5E19C62D320FC59DFD42:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+63E2A7973C2A818F6D1F9F9640F703CD:94C9FC1FB22610AE0BA34B8E8AA4A980:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8E72560E63A9C9F1115C3287ADDCE7E:CA01FB995BB46F6B0870F40D672FD0B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+126FC05EB726CB731D90916A80BCF638:CBB52C3ED1DB3A4D60B4C205E167C6E1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BF96CA36FD923F966113671E8C9D84F2:EB8710E2F753B46647915E9B6D1F4FDC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F0EF517FA3B3F8FA6DA04C401955BC47:90432E85F8FFFC8AC6198F14ED96E6B5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E5A4F0D39FDC96DBA5BD04FDB69A9439:52FC091A6D85216ED45716A06BF28F7E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5D484FF8D3B7071714D0CFAF400DADC1:8DE390FE597FF61A3CCF4443B0454940:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3146A7EB1564016886631C7AF1500C42:551CA9841792EF7991ACF162C8F257AF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2241AA352F3AD9FA379F7AE0C756239C:F121B24FDD91E6BB830D131880BFDA6D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D70CDF5BBA9D65227656CDC98C1FE3E9:7FE52C4C3315DEA7B5D9984D5EA4CEAC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FA84B748F0B60B0BBAFCF5B49EFAEA49:F852BDDB729CBD20A2C439D1A659E1DC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FF377F97E2A6125D6E1ED3C0F761A215:7AC46B10E7488936BA1EDA1745AB310B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DEBF9FB92055ED91A1BD841D68F87EBE:85F83747E314AB1A65E42D6BD9F130D9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CF6E048F8EAFD765DF1E1CF230138993:C4B603A7BCB0A5FB8FCE31B42A8CCE89:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4E377F3D81C2DF4850D3EEF175B39155:6C6D4021723B65644CE895CDF0EF2E76:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08D1D0F7E188F57362457B0EE4596CB6:CF1EDB093B63D04AC6A043D69F1E6BD0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+67E55401208F491D5BB672E2F25B8F9C:47B1E80E65C74BD56312EFC18E16F01B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6CAE6670BB9E867784EFEC6E405BC90D:344F3BE8D68569097F9A4A5991D43551:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E4B8492F2D5F9B241855068746F09AFC:81277643B99DC768B898D381EBF55CE1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3888ABBDB9245E535F52C2A1C4E9AE82:B962C5F25FDF7684E52EC354208939CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D0B06EA2EBA073B21628DBAC4FAC7656:75A33ED3B6B30B41421C3B251B76F82B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7387F80E53D5F5B68D262DA9B948C143:51717F47145BE37498A1F1A180B88D4D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+07078EF7871B2DF91526B731CD7EE98C:E8D32221991BB2861AB4F271C17AFEDB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+48CBB0CD929BAD37E3E09C07941A6A79:292268D201E5CEB4C27B9D860B3F0227:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F9FBCCBFE5B4B51DDB3F67B253A54618:4DABC3E8F80E9C72656AB2FFF26BE438:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+49CA02290571BB70BEEE06F07AA31502:B59EAD47674A0A4B59C318DF6378320A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3F407FF4785D3E2E47B66A3675302268:50AADE7CD8EF67BD643B86D4B3023D85:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3E4CE1EAED91968D4D67F804B4576A87:654D279050B241B87B9A511FAACF01D3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+847E63FB5437129DCF4FEE704809EE09:DD41EF5762AE57F0653D786BCBA70DF8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+720576733C67099529A17B6F4010FEDF:FEF594E990F7423A37F71963136A671D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AEFEB7A92EAD088FCC30CD88129E22DA:C54F79A13C6F2835D694AFB48791836C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F3A4234B3A72361AE98322191BDDC35B:689FDFB1AF5CA1B55300A965702F3AB5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C899AEDF52BF6FB16B5F3DB7C47F0088:CAC32974F089ECE899D9AC85C612AFFD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8DD1993D1F9FA3850B2CCFFA7A42BB88:FC6F6AD5E8D1AC86EFB14240D1BC1EDA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6B7442B6328BF059D87828FDBFE35225:775ACCE20C7BFB08F20F8CB7CCA80C32:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+28C94A8AF7348B622A4C8F20434B54D8:CB8066BD149F368A04533E6893669674:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+42E049CBF52DD8A65906BC0ECDAF7D21:63C0F604FB661A4876AA5A806CDC618E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D1FB1FB7F21CBC0C88D05F13DFC35185:6FC61FC03C4D7E7DADCCD93A4DAB5219:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D382977D7754A6BFDAB545E9747B19B7:E97A4729AA40ACBBB409D5CC02A0A075:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+85090B82AFC0B9AC5273855778BBC3A6:F6A41B9AF291ED32F3ED14A2A7395253:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08B463BABBB37A233F5F106C4D5F4129:F3952274AA0E8FBF2803A244A2ED3176:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C2197F028D57D6EA121C8914FE626BB2:BE43FD4AF749F24BEAE40F2DE31B8CB6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4642E392D2326401EF9FAE2B872B809E:950F995FF73976974E602D7C37B7D67A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+765D5C526AFDB0399E1B1DB8A89FAC98:98A8A7CB6C63BC034374D37AD21FAD96:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+39589154E13C7E7DD44AA5A416B19381:9D78017FCDE71C8FA53D6BE31F20F354:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9305802BD1628C12B81CA03A05C18644:80FEA18D5BA12EDB6D4B801C0A8B356D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3FF59332CF19765A310B432D8EC2E24C:90C697E4D23DFFDA31762C96A0314520:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F900F6092357CFC0D24F268F8BCE1849:06DB3FC23372A53D5ABD29D3AABA9784:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2AF78325BC7FF73893B672281C7A8A2C:FF9511236216D6AAB165512C862D1033:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EF0813F05B70CEE98ECDCA10378E25C4:A55D68BC71C81D9803184D5890968A78:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+65D15161C93536E3B3D17D72DBF2C36D:64771CC3E89296E5B51D86DBE5C61697:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D4BF40C1DB6F6E30108AF6C99B379C74:39D03BB7059D1D4D56FFC0F51B46D1EE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+ABC44A5DF6BE71F0BFFFB7EDD43FF39F:114EBE72C55A45A353854EA02C3F5953:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DFF5CF0EF3A729E2BDF5AAC15C47B482:F5CD1830D1E1C80676095F975AE9C4E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+762A7EFCA64FC897E2AB73D7B1E4C55D:5FA9ABFF7A5A4F38C51ACDD1ABF7B1CC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A19C0EF84F3F1EE7671BD3BEAD9F5C4F:97CE27FB349A3E47501026CFB8A482F2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6D9BA177DC7ED78B677A2B777896D122:8CC60CBE26354E70920EE8A8DEFD8C45:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+84D38A4D2BD1603299B4D1268D5C04ED:1A5308CFEDE62DA3D4D250B5CCFC251D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CCCABD652DF9E408311E359EB18F416D:71377B721483470253AFE3181F523921:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0222F3AAF0D213143635B63CFAC02032:72B50A920DABD365AB2C48E888B76377:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9BE224E2313DF5E93FEA7A9051ED8456:D8C83B81A2B73FD56538015C67C61EB5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0F92300EEC97547E6BC58E066A28FBBA:FB0D8CA9BB551B808B335879B98AFA90:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C9382AEC049FAF4CB75128D8A0FBBF10:56E669C32A3481FC05F5AF22473614B1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9F5BFB399A615408DF0BCBA6E43E2130:C5AB52A86EFD123BC5522A64035FECD3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9FBE5F1202FFD449F7833CDE44DCA62A:7320AEACFD518D39FF69068F64A6CBB4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+830408D6A8F161C0C2D058A2CBA5AAB0:FE7C48092F269CC1B9F10DD8DFD866B3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+46D86E657103B18078645E6AB0C24722:D7D1B7E2A137B75C89290162F16C6BA1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E7DC58F11BCE3C7D6B8AD2A5415EF3E5:2114D2BD30AF001BFC2655F832D81C81:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+07BB44ADA25B638C091D92B67015B703:087AA29983682867A4690287BCE3F0A0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4586E5A6EE3B908F08B7392B74B478A6:B92726E53E1596B88C53A82943895CD1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+ECBA6E02BF9C11D70A2C760EFCEE2A76:45C50D0211E804E1A75EA5F4CDD9D672:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1F57C57183C32E7AA748E4E8D2E36966:E4DE4377C9ECB95A7ED81C63C34304AA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1C655E258605EE91AE413C246894B354:3283FC8FFE25005AE6936FF3BD738CBC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+84743F37B54B7B8CF1D94053B0970599:3BE8FC8C5AC5F98592AE3F9B1A77E71D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E4350F6E48912239D635A92EDC5D8BE9:BD62C9A7863097A8E34C5E93461C6B5E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7C4ABA6DCC886B3046F32AF18F3ED0E4:1DD38A4D9730F51F83EC35B6CD0AAE93:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+168D7910C13DB8A372EA719D1D2D4499:445FE01A29E7A8D34CA8B4B2B2B79066:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6D35D9D0C309681F3B2E7663F940D67B:8F10F905C780709E2917AACFF5A6F4E0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F734EF63150021DAB7EA0B421F9DB7E7:833D03B9E53C1FA9E5C4E59C778527C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2420531C90FA129E86D116BFBD4FBE1B:9660D979C78743F9E85683E58072C1AC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CB6354286F89B58A88B711CC9C7E1316:2788DC343D4CB5CA7E9E702FD06244E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7550AF569DE4F4659EB3589CF5812751:103F876C50095392E8CD90E153AC7932:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8D59F016346D94F4A051970F433E129B:5D6DBE294744555924D9A21ED0F97497:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3595D0C290ADC80AB52F260E54062D09:1189DDBB3FC2481F092A162DF999AD84:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9E34D36709DA00EDFD1828D3B049EC85:7E0F45E113BEBB4BC2E0768612E99B84:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BD53751ACA579D2FBEF6AF264C1471B3:9F42747C49F414090AE7D3A370DDD89A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C5CFE4490F9EA125EA08E52B130DC452:0262E84E186D27A2AA3F11ED73560911:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7296903DFC97CE8911E6F69BA9D77C57:CD8717F55E29DA5E2AF4DEBEA34E6871:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+67D1D868081846C76CD5E7C805072AC8:5D36D35E48AFC010FC6AD5751A745FE7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C01ECC52B57ECA82268DC043421A9826:48D7F60A1E126F0F9185B8AD37CA77AF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+03160618AEB467F5D855CF636A96D188:7F5C9F5E608F3BCA661B9568EE89337F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+41075EE5796F93B79506F5E707E878B4:300C3B4DBE4FAF383C7F1CEECACE3BC6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A88BE4033A227A2B1C40EF6A1F65C7EF:112B723BA5AF2B8907B8A9AD4C3F5650:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E0D8C49C27057C8B74D6BC20D4C67D89:2116595D34B5D4F1EA1B0A6816930E14:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E6209F87D0DF56D163DE4167A120D541:88FA904B5A4B678567591BBB834A83F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+98DBCA6051954B0F57F8FD14C0448F01:DA33BC0F7510CCF9A2CA4FA1C1538A76:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7B6C866DEB20E9EF998193BA14ABDF4D:717481414648473321CABC8093446C55:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D7351619C93520F9EDE823B1BE6B1525:D5ADEA8259D2E8B625EA2F02BEF19CB5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6BA35A4E937AAA186FEEE58CD252C383:FA2DE39C8A6944C280370D07CEBA6140:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4CA9DF4245FE3D5BC9BBCF0A77E5A6BD:42EC0E38C6BAC576A6C1BC7944F612F7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AAB1E15C2BACD32DB1CAE51B78110D1A:CEDE8C8A7DF59EB235BA38BBA24BB911:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CB457358E20488B258E360D678BED84A:D28FC92A52E631F0D8E8B343A4A3B203:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+41573D084090591302F86009ED66714A:8C42C71176414120A4BFAC5E712595BA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2376FCB2F9354E84204BF1FECFE37467:7BA7AFC5BE5D69600E68CCEDF780E1D4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0A35CDE7A69929A31C7205821EB5AC74:0B3776F3CAC22BCF870DDF10C1869A4A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+30AC1DF30D0933A1BE9A7885BD4D3C5D:94F0B2C509A8531C9A0AD81637C2DCE0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+139A78E630E49492D3A938D837049346:34579E1E82813F9747A5B132FE4E6964:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AB6010C72E0A156057F8E14EFEDF98FB:0C7A02F13911D33BEAD1471C708987F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3F0EA3AB608E5CF9814AFC56D7AE1B9D:3631C40610EEA661633CD7B8BEC865E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C62A08EA0795752B072A06F4AEAB3ADB:CCB2F6767F50B6896B9244C09287C9FD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B73A62B4C9F994FC383EBD65DD4EA0B1:ADB0391D3F717FECEF62C07B22E31062:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+493270140AEEEA6D72F484B61C9C1825:6ADAF168DEA73E278F0CAC41907F5304:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5F25EC322C5AD4120F115248EB11FAF0:2B6539726858D7A043EFBAA0E33CD073:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C05012D7D2B5270433248793AF438843:AD8ADE6BE4C591A243B4CAE06A709DD4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B9B9D77A5E156DBCDA162DB3848AD95A:C14B99C00345CB680C482D31F8A0C4D9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8FC09B76BE675A5161338F4F73A21D6C:6B547FFB2B57F236A734BACD51BB7F80:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2859C8B12F4439DCC496C5F2BAD2C99E:84C397A83A9A76CF06818FF1534C45B9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+29CD3317ECE7A36106AFF008F7044D4C:07939F9C4DB6097191D90A84D9422F98:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9440D9285BC074FD402117EE963D7A8C:295A81D1FFB0D950B0DF0A61DD96BA84:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C405DE00BAE96D8C354839CFE1E4DA42:13BA97F2392A05E6A2B33C7C713DA088:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F5914DCABF0ACC9D1D58D0011A7AA462:6DB4ACAAD7FABC9CD78E87AC9B0091CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+80BE9CC8DE81F11996F2EC48A55CA726:FBAA38B36394A2ED5EB7CD24BE8E0E55:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+58C8B08BBE5647F74F80FF7C1405DBA8:FB4C62485E9E63D73AA3032CA4387579:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7DA7507D0CA379E2D060D4E8486FC8F0:5135EFE72EEDA1CD3FD8BCD504208BE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+760489E9ECBCD1B99D5F93659E723355:FF7B0E84D5AA95BF74975347B005E3C6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8F26A78DC801CF94F42781677C28DA1:7D9C197C3F6A57D489D7D860F5E735D9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+631BBA38307F0F3D46EC6008549DB395:EFF9418718C2B458C7D2F9394080B2AB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EB4455AC6D05F6D41907B363FCF19067:26611DB477E3C04BAD35582E9DD1D550:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B124E0C47CB5AD6BC70E6517C3BCADA3:99BFF5353A3CDBD7CC524D1397CDE280:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D96D6BE65B50965E1534F10C37B071C4:4520EC9BCB88E0DD255F62B8F58F8CB7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E20DA0529B468FD1F6CEA9E1DDA20D98:7D8EADF99C6DC653A896D3D9AC5AD532:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8FED053284ED49478577BB31C8719DDD:FB895CBFC4FE1B7F30E86B05CDAFE62A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5F30CAC7106D2FC0AEC7D0E6CF1C1B0B:555032BB249EC898CA18C5D212254D98:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+95E61BD1C1F5D208B84E2EEA39776A01:3B80F00821708B2473638EB7C234BDA9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2E13F661363EB00DF0F05D3A8B67A931:96B667807256288CBC343BBFFC951A6E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BE50E7837771DC3782A7B2680AB6EEC8:48A091ED2C8796E030C78F73DEB7B9C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+494E7D3074674BDB8959BD8C243AAAC7:CBD446EDF4C4E69A8BF57AD748BBAC18:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+98EFD397394D507346A9E3CCCD94B83D:1941D2C4E959190CB8B5BE59812FBCF5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A0E491A1C8B2C0441E896AA2006981FF:0D93B922EF541227948915A40F0EBFC9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9906A45DF7FA72CE1D93154FBEF8436F:200042EC80FED60378D724D023DF4490:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+934793FC4BDAE33A5BC62253C4BF21DC:E0BCCFAF07ED0FEC18746AE09A8915DB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B2C82F2FC55D78082818996C8B438D64:2CD7B209F7BD58D71753564D647D3716:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B73CB12EC2527CB24079BC91E7CFCA64:C744C2E0A2FB9B4C07143877CBC8C52A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+03BD985787971F4CA118007DEFC23B32:30569622169CC58B0D258E8466B5D579:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0F1B8AB985B4B63BC911AB0B989CC3F6:37326B366FE3CB33DBAC8C8884977144:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9F641156DAE8774283421494FEC92D6F:8043D5FEA980B3AED3330802B1B7A370:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2B14272CB87B86674EC6E848090BAD52:6A014D1249FDB4F83C784F2F957B1B9C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5174558BDE4E1E82A97A908688C1D932:ABBFCE8176303FDFAEAA8DE9988C6C64:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0C4576A319A31D84FCA00F13B173FD07:AF6E672701B09598056135C40ACFF4A4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2F58921AEDF792D28AC5EF3D89E6E5C3:166F24B5F7ACED72CEB47789FB3420A7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+18D4EC77C7545EB9BD18B4D6EE706154:8E4B8A41E09E9FAEB483F4AEED16D62F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+41CCEF6E389ED4819F2A3F0695E05FFD:1FA1311EB223F23085B0548ED3CB8E1F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6FCD11D8582065E40E45FFC8C236844F:7DD9DAF766CF5D5FED9E0CD379283311:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+84E954B3E51B616843CC9FCF87F56BAC:FC0504AE07BCB1E1D476EA24129FCAC0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C15FE4ABC0C4C3651D73A44BE8363E3F:23A1BE9DF35CBD354FA74DDEDB761EBB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3E590CE739E909499AE2BF2F081A8791:A1E3EF13407D27B6DB3FBA999430D93F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+843817CF22CB788A2E1AFD63B0E800A6:766369A95B5756584277117C7D80D6F0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+47890D85FC7E1F2F50BBADAE3CDDEA8E:38DF031DFD78DBD121875DBD27A65DE6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1E49ECD466A95FFE545985D1CBF83570:D41EE3E2DD807C2664CC551BB4C60716:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0C24E139962730F8884348FC344BF257:333AFA1CC42D2B65B69E8F84DACED288:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FBB395C0500A3C19A737A7C055722B22:F22AC1742C3F881CD2E807380C6EE933:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+47DFAAA0F3C33B25D10C2D1681778470:4E4437B28D253FAB30DEF9F81881107F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0A308E89BA785C02C4A9A356429175D4:954BC0204437536E81EB2981656018C4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9BCD04EE4515CEBE9417C4BA53F70628:350CCB77E4F7582397C8798977551BED:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+116CCAA1796894C546AD402AF21992E2:9B2B8AE3DE719F3B9EED784EE085D6AF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D0FA9A490CFF9AA8D310C9EE1214D22E:DE1DFB5E9A4FFFF1E159CA3D2415AB2A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04F76480D664744295713B1B9B9A8E6D:21B1E562F5F0742871E15B3CAB25A770:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DB3C71A92F5C8F9FC303DB11D12264AC:5EBE82662D295D950B489F790A611A76:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0800C09A9FB780F3E7C28A3FC9EEEC76:CCD61A1A7F4E08AF0033FBB874FAA57E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D0AD8BD5019D6C9A8DD4886E0A142C5D:C0348D858C4A12CC7B8BB9854781A463:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2888E9264256D1002A2EC2BBBA5E9617:9EC2135DC0461CE34B48B8BEB64AE3A4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+394CBB0EE6765EEB5F63108143D4891A:0C4B799D0E3B5388C9256B7CD822D2DD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6BCFAF34034E97142888923020205C88:534518BB353367DBEE27A4ACBFEAC109:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C30940B1DD0A3753F13279FDAE1D74BC:469E5717F92180BA73682767218EEFF0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C5E22C002C00FBA49991B806AA12D7A7:517571B9EC2F2BA2F4E65D399A2A9648:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C0FB5C0623B6FF6E6B98025FCAEF93AA:277D012742F53FF9E72090ACE0D858A6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00FD0D8AEB919F7ACAD97FCEB53B5239:AD23F1C09DAA2E22375E9E46D9C63916:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A281BBD26A06D1437EBF2D0D2D0E4908:DABA99F79DB7E0CECC494BBA3607D20B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8D356DF37371554CE5CA0507A6B7B2FC:12C0D42C2578FEEF42528360919BD833:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+719A3D3C27D8B4B58793E380CDF0EBA3:BBE7E042D9B823A0ABA4A373B1EA149B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9050232A0352DA77C36A4EBF8941E0DE:EEAABE37D6C42DB0A54AA4FABC12F872:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D894906DAB6F24402E0A769F9D6F5AC5:7E650D9CC9220F96BDED18A2ABAC99E8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8354BF3240A66515DCB3F5852FDA3352:F867C36D1BAD141D1C6BD6884E9BD5EE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AB2EE66300CF3886FF32F94962C5F5AE:55F050D0F8160FBA6211AC804F7F9904:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+36C298362E647713C08B4D6B6EDE4E17:9D3AA6AAA9CB2834CD7BAA389EE6707C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+75B95E9CA0FEC03FC14717B4239FE737:9BF44624A4EE5AFCDDAE766F8A0CCBE5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+559EA4F0237D9EEF69264CF1DB7379BE:BFDC04B79E56A3A17096B7D667E29DD9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D5A45AA6B981792704726E4D8744CE28:18B9A46D1F9AC610D7FC93DED07B6F43:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+14B025CB6399B38439DFA3E1A0AB2A8C:AE7161320FD6B793C53AE82C486123FE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E61F5E00147A9072DD5C7C9C73BCA55E:D6614BC4918BFC57CA977B751CB63981:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C130A74BCF9E00080C81DAFBD4CB9C27:678779C91FBB09CCE59BFF0A52E664CD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7B33791FB384824FA4EACCC77DCA836D:DDB78361ED1E569E7D82DDB3446C6CBA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F312A6CE802BAECD8D320F48C230478A:BF376E8A67E0D4A6EACC93D7506CF12E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A312F31CDFC678B772F41D85F8960D81:C3278B947706D148D8495DCF7F940459:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B1E2215B44D517F8F3F4EC804AC7CE4C:3C5CF6F19631D11F1AE26CB8EFE06149:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2D18844BD670192026E39530CE16BE27:33E79315CD18B83CBEA1E45D823F9AA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8B4DBD837AAFAF3BE297471737B4845D:2A30C8A395394CBDD2A970C4763F01C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AD20F1CFF0C4695F0808B4256C3E933E:2C062B870AAB8223454D85354AE69C6A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+64B3C2DC52B3FEAC5562AF4F8DA845EE:C3E4C1B7BCE83E68F75758FE33362CF9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+99807008533A8C8E851015F5719979C6:89265DA4FEA5FEAE14B3C71DBB7625D6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+94641E459342D3D007E15692F316D9E0:51481C83745ED2A0405172AF9B180E1B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+89644AE31F62B3B77C6ED9BEE5CDA55E:9D491E8E17E357D992800CD396668E9C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+74C22A64E12BF46EF00DBB12D2388675:852882DBF18419FABD698794A454F23E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2D8AB2CC4F59844D705917C3D1D1B220:30E77D5CCB70CA0ECB2D774890B72119:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3E3660703809BEE497D36875DFDC4D4A:7EDC11E9418DBB124183BFAFAE82F42F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8E7BCE9B8551C59DC15AF0FEBD75C77:DC497415A0F3BC5538A36EC0EA35D878:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+615AFCBA98D0A5AFA089F4C506E95425:D7CE890C864704A2D90DC7B6E32283E4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+082A395DEA30823A8AB8CCA4851DB836:DB153480844804582364CE5381E15C37:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B10B5E124C741A67437730F8B1CA3F82:C7152116908D13A6D22337D7A7D3D795:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+112AD1550207C4583005C72188BF3511:41E79330C57AADFD089D8EC6B3569B4A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C1B9A37E9747E23BEF9B5C628E13A739:E9AA948C7329B74389E039168F7B8DCF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B2250C2A5CCE8D50C3F193358EF09A48:935D2A954C7EA28B265673279F6B4F61:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D125977E709F9324027A1CB656B8C1C2:7807796076E0BF2795094C36CF79900F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+649600BA81A113BC7722E878D5869004:C69C842CB5D42C4026244806E3270A00:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5718F3B4ED59D02DE5C40E9A826FFF30:9263BE9CA3CB9661695C1CCD1041F2E8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AC56479B43617B1C7C804629E36E93F5:C35E27B56BAA1AF03542B3DA703BFEF7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20027AB27AB4CCF48F9973CC052E0A35:22AAA7F89676ADAA2923903B2A3DB526:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C8DD678E5D5E8F67FAA0CB599C7886BD:734448F52EDB9316CAFA7F095C24B0E7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+93DFF0CC56BDBD950A9BAAD3DFF75B2F:EBD6A3487FEE478BB0EF8EC783E49C43:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7FEF68F9A691BDDD070DB91DF52798EF:4560A566844F1B2F92B35D762F7A2A82:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+86A06EBDB131546D77A4B81C3BED598E:37B9296307EA211F5D6E249E9753392D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5C467E141ECCF1B65B6DD86418F35CFD:409732CE286383F332C492E110F136DE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+35E9FAAFD45C1470EF2BE841B7CE9187:1BDB66804D80D832ABD97BDF145B316E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+72E77AA37ED81CB273582D24FAC4F797:19EFE53BFE7FAA6BFEFEBD4F79885F0E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+73A8FAD5559EE727CF006CEB0EC60D3D:81E197EF8F5B2AD7F0312B705AFB5F27:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+81B566F5EA6961C9241486A6E526E8A1:213F181798188378DD97935F019AE7C0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0DA282CB8796A24A161FC55ACFCAEC1F:72BF6ABC3AD01D3B7F5589BAC18499E1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+172482CA04A7549BAA12E55B0A2619FA:B40732603C7E9C2D373E12F9516E0426:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0E89B76BB98DF1ABA754504C08106755:1F38D616E20D3F0C4158517B162ED983:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+44FBD8823D9D06573CC304CCE5AEE6FD:A4576BC2CA8B8764B30D2DEDF461E455:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E6C9D81608C6B4B736913749E0E06FB0:83756C36B9664E2415D54835CFAA2540:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B03DEF269B39D69E0EB67B873CF2B80C:B226452F5E395B90E46E5CA8F72916DB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+144976F7A2170E86A68359F49C9BF7EF:2183068E0B42CF774DFF0280857F23E2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F86F15E91A74FCD149AC3B27229949D0:A88E509487D41897D882F8A1160F3465:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+65B8EBE1995C281D80E471F6B447C050:84EED5FC045BB4817057902699B81109:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+116AE65A8B432F02F95BF339DE5F1427:4FB98E68E52EDE677698126BFA06BA6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7EDA6705CD1ED178F051188479BFEC21:66840CCF17A78DB4748D811B436D0041:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B3B2780D00D441B0641BF54660BC7624:6C24B364096089E615A8A657FEACF53E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AEFCBE20965D096F631D7844F69D7D8B:0BB3B124E75FE222CBEFB2EB1BA84C57:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+94C8C0B27E7FA6B0C66EF69529280A10:7B0C86F6968BE22B3CF6740FA4E7683C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+866CD3970543E3224E756F301705081F:A0400EDBE1D6D08CA45419D39DF4E4BB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AADB86BD88CD0B572DE6225896E694DA:AD4B42F7356A196EB29EAF62AAAC2DE4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AD22711443BCBDF0DFB1AB96F3217F98:6B39765526E0D0F8E55606559193D760:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2C63EF91C5BA79AE9ACB9CCC9D0CBDD5:368BFC2EE7870480A53B887E0E0273D3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7952E98E82ADAE82305291AF31D82B78:481F3714C9112E522CAB717B00795542:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E0B61686A1648FC82AC0767A30E969BF:CA681F90975354B326F88DA6EE6CBC4A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2AF247328D18F510A4FCB1784979209D:C185B82815B15FD96A75FD0309567D09:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5D2064436576514B4C27365268C6B9BF:267AAC3880B12273AF2B5976AC51C157:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3D04280E15EB800B1ABD005ECC9A8B3F:EBE2628954016D7428DB4477A0641B49:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A55B35CF84CBDB510C38F24C6BF93B90:9641A161F9D60D76EF05888FD1E2A280:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F14320EEA11F6FC7336ADEEAB8E85B9B:7F42B86B1C943E7EB89FD91B439EEC9C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+81D4388A3B919D54311B3327A4643265:70DFE1A70E74F1A2974C81F073542863:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D1469D78D3F38BEC7EE57CEAC7F5393D:5DECB5541E8FB7C65CA8DBCB9A25D6CD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0028367D36C6989C053BD51781644393:28967FC1396040FB4A989A6A19A67930:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0DF379E3ED7A514D09CA440CD91A7A4B:B2405BFE9F872B5DBD87D520CAEF49EC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2E47CF7B14D03C6D89D950DE7EAD69A4:A6A1AE40FB2DBD1ACB43E9C027E877AC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BD6F5ABA7C56CD8F7F94D9FD482FAF4B:1ED91FFAF9975638253641D2826A91B1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BA634341B5A5D226000C04A5189AB13E:F5644F442E6D6B52BAFB7FCF020C5E11:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6E2AC15AFCA7504C209BFC8F9CCA2A2F:73B228B2BFE0B01A24AFE361309E84DA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CE347B81F4984EEBC8C3EC7CBC5DCC18:5ECCDE0E778C02545B16916E67CC5E15:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+DCFFF804405504B5EFE75BF9D23480DE:66C04EC78FAFA8462E94A4A4F69D4D7A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+221352648EBA537DB994F93EA3527CC8:74E0DB0F5A47224A1437B7C519441C08:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C8458FEC89AF924CF81396E641D7DDBD:5C3BD04D99635363DAF7D281230FD600:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F47E1F7EF00B42F8F5A1219C42E0CC0A:6DDE19D02A217B2A5DD41A1454DC677D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+24CDF34C5EA6B37CED3B33178FD54C88:95DDDD7E4CD12EF44FA5CCAF6E093130:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AC8023453190010FADA88C6E71174FCB:F123615073CFC4C5DA553F7758CE0937:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+023AE5AF03FD68B6432D84C218DFE0A7:4B8D617C5728EB7AA6B2D23960F235F0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+CAA35C45DF45601E5935C92B4F5F164F:7155D0E792B5279AD6057C48BC2CAA0D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+ED72D82596C24FCE85E066377C6F23C8:2343F7BD3ADC05B7F575DBFF8B490EAD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+818834EA9DD46525CED342FD8CDF03D6:F0AA5253E8871BFF04BCAAA9FD2DA3FC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+AE528D030A08F5697611F769864C7863:C40D67EB5D395B65F578B01F7FDD4D36:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+979BE56166651E23CD3156624B51C118:4D3FADFAEF95C81DB449741D830669FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+23F2C6298D46CB7B66305B3272F14775:B21F5D9F8CFC630C0C9184B34335C19D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4C5E6E7EF12BFF242402CC42962DE420:0764165513CE56DE4BC8FB238CEFCF15:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+93FB53BF2128A23468870BB679B6CD46:6FEA32419061B0C70A1A098B34F6B008:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A5EB2A49B07960CCEA5C632640A4B8D3:148ACECDF96815DE338312D7E505FBA7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7CE5CA2B71BAD18D4722127C9B28CA20:65EAE71CF60B516EF15EB3C22958272C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6B3BD3BE30DEE6B7987FDA806C5C3805:9C9402BE33FE1EB856AB211CB6F92C3D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FA36C8904B20DA558430AC1743B31515:90E562EFC0D04545190DD0142AC39A05:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6D159ABD062B35E8CE7F08F44F289040:3753E162B8361AACD59B20228221D6CA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F5099C6661352E4093618DCBE1CA977A:FDBE9F07CE5C2E99768DCBAD0B02E321:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+688A780BF7A5290BCAAC1B6132878C53:0629155B1D44909B4CD2A8B30E0E0907:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6021C98BB2665524A443D89A40DE9D06:58039733F59046C469323C29B77C3750:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FBF76BDF9E6245840CA6BBA70055F563:94551B253A232BEAFDDEBFA5871CFFAD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A72FDD6F664169F03CC0CC554AF2B68A:0E01B11F9313E0745A5A6C93F65536F9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+65550E0E11ECE8C52F56D79B8779B631:060F7B1952C3A20740FC3AB3523A26B5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F6C89D40E53B72F349433B135193A2D2:549DD728A520D70C5BAE2F13728D1334:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04F2E6F467102D0C7514ECFF1B74E61A:B9DE638D64DEEB61AEF4C787E9DD35F1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F4030612C03BB7E12CF52DE9368C2BF9:5F9276C06B5B4845634E53D97ED262AE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A28AD08C3334E4FB4D4968ACCB7F3F5F:82B8B3E572875119B1D125A2E0B6242C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B2DA025E287DF1D344E2C76AAD0C2C03:A25398F55C33DE587851C88C96DE321D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+496548B236963ED35F68F21ECF7DFAEA:209F82198BE7609F3C0E1B3291C306FC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8017AD727DBB03A67BC9B6CEC08F82D:75940C2A866B99049E89E6D2FF00902E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6F961163C00C533DBF195BEE8714DE60:6A04C14D65DF615BC9D3817EE4FAB278:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1393EEFECAC81F9F0684A141B37ACD79:03755C3939CCB1A295328C0116FBC40E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2D6F0FC6BF2DBB83EA5180D2B5F2D8ED:F965911478AD9B623B760844CC03327A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9033C3DE5FA49AFCC52A79E67F4D0736:5831046301BDA86CB50346CA1B66C4FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8B7C49D31802C02FD1CAE4401FD2D2B:08F7884E9885E1038B0C61F473EF70F8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+BA9678585636444430D8270E4D503540:421D1E481CAA8A08BBA48665CDCEC377:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9B61323D57ED9FFFE1918BD9CE8EA33C:79169AE974BAC0F7D922165BDC2CF445:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4CCBB469A1750A879B8A74FFB3FF8C61:4E839686B96659ABB8C5AB567941F7DC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8F243A37C08D3BFBBEFE8F91E84323F:9A0367F4E414FB939A86047DC4A8EF1B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D3821E4D2C499F3426B9FCEFFA09356F:9B15BCD64E0A5B52A1B9C63A01A4650D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E67235D373FA498DE6F8AFE84B53D286:5FDA78B9580BE5587B564AF685F12A7D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F1FD811B4F6641BC14A703F8CA365DEB:660CF835E5D77B420EEF4EDD7FE3245C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+2B16C60FCAD353CE3CD64AC3FF889DAE:F78B14B08F30907961FF6B80F4C4F871:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EB7FFD1623A99B9583875FE819004E0E:B454B72CB6B929CBDF3925451B6C37FE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+09E42C31C09D7AE29EE67127085A6806:46305BA66724716ADBFBA60604CFDECB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8A142724C41589A979AFFF93F7EFE596:AB8A4242F1E08F1254A106B65FF3AE81:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+87EBEEF10ABAC49D72376311C2A81533:033DD315A1E522BDADE84670B02F1BC5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B3BC2E9BB2511849EF7BDDA3C2CA6B89:0EDB4BC9961DD9D41AA7A25321ED0202:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A5E7D15571A0B04F499476A994B87C70:D8353E8A311FCAB4E34682DB5F2B7B00:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5DD35FEBA1E40E6DADE71DD3ED785464:58C5EBF33628DD343C822D91D21A4885:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+469EA4FAC76E88BCCBC2922E4076019C:A6910C818181CF1F4E69896E7FE0F4AB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5E4B9F5DC0FE8BAD9799C29F50AD5DF0:9555BA538C915517B8B8648B21E1295B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A8521AA3053C780A138D5D4552EEF9B9:58D09302FC7AEB722D0A16BD13406759:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E195D5EE9732CA9E20DE5DCD3DEBC856:60D314160FC2081AC73F48B62AA7C22D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+FACEDE9FF4706209912726B7EEB2D0A9:3D2284BCDDD3A0EB80812AF638843F43:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B444E404978F7F30AA486040F7843250:9ABAC5E96FB6F7D306AF9CF2E37E28CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+9B54CB9AC90D968812FD1355B2779236:B444FBE174380450EE93D9BD6C2151C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C29668C0A3FF22B1388281FE5A841DB8:4A3F6E376DDEA1791F84D4617CDE9B7C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+75AAFCB786C5A0702C133649B9B73F7C:CBD89BE37B0BA65E3867D8CA0F77C30C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+39C63789EF88E20ACF403262C42A89A7:FAAD0835AEA037ACC207FFCD2A10CD5F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+71583BA1CFABFFBFA412BE228322B297:DAF18FE82A072EC5B9239AEB8E6E52CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D00297579A4B01649C237A176B86697F:212E6D57C1A46A790E082594D29A2F31:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+49D694199247A4290B8A1649D5C82F40:955995D2521F4D100E95E76ABE8BF7CB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+3C88595603173ED5762ABB970D019B13:DAA5CACD2E1BF1AA1DE9C1BDD1132C2E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+83AB295E4F15A8D5F65A723E0CE2D01F:69FA28D662336E4446F4E315C59B1262:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D8A9F3A761B1E45E384FCD205D5A8C61:35529731D5CC912C41153E7E626C8A11:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1D54C56927178C14DA355CFB9ACCFB67:49826A29C640F65371619E940DA451F4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7D9574BDF07BC0A251B88A2B24F0DB68:9651120F3D1AD09EF61607002A040D92:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+75A94C5692A877903A4D43AA1071463F:2676F7CE1D8B91AB29A83970D5EF3698:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+A04C41ADFA612D80843B0569833A9AF8:1282CE00BDE016E61ED8000EBD42F414:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4D159F9CC6B4AA58F7FC2F905F5CB875:A5FD714739BB899FF577C6B3E19689EE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+0B1840E8B119B7C94A045459B61B28F6:5E5213FF0E467653C61A21EBD5EBF6B5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+8E4CCFE43811ABED23A41C33FD5F095B:E92DACB852960B91B9EE58153A102948:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+C9956C304D2BF87CA8564C3762CD762A:860D752AC16CEC79F1DF5C6A3A44E9A5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F4760FA1F8A17216BB95396057F8FB95:6D8EF0B071CE8966AAEAF8C3C5AFD26F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+7CB6538603BDA43BF71C12AB1241A862:7E3B14847526572F0D55A284D626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+E945D4AA05A23561AF42466E1668A734:7E3B14847526572FF2AA5D7B29D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5FA0B49C4A1C2452B33C433383354B3E:7E3B14848AD9A8D0F2AA5D7B29D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+5CDC56C16559E0AB736D6A9AC72629C1:81C4EB7B7526572F0D55A284D626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+4EC8D3AE8C51C84F4B65B82340364E4B:81C4EB7B8AD9A8D0F2AA5D7B29D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+F97F70581ECEB3E6F3F3D37BE9EE6A37:81C4EB7B7526572F0D55A28429D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EECD2D9DCB49A297C458C948CAE0A513:81C4EB7B8AD9A8D00D55A284D626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+1887BB24F5B28366010E7E0F132F936F:7E3B14848AD9A8D00D55A28429D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+EAD576FA649DE315401ECA6471B2C34A:7E3B14848AD9A8D0F2AA5D7BD626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+540D1BA22F928A84C67EF5214F8BB88F:81C4EB7B7526572FF2AA5D7BD626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+74D9CF212295D3670A92269E8D40939F:81C4EB7B7526572FF2AA5D7B29D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+6BEBBCF4AD01F7E3105D0888A0AD9E3E:81C4EB7B8AD9A8D00D55A28429D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+B4FF03EDC70BB97FAE21F21C3A459B28:7E3B14847526572F0D55A28429D94A9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+93F87FBE4DD4206528BF83352452D58D:7E3B14848AD9A8D00D55A284D626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D261D6041824D259290EABD3E9132DB8:7E3B14847526572FF2AA5D7BD626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+92074732D84E1841A013A0034C52BF50:81C4EB7B8AD9A8D0F2AA5D7BD626B560:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DDD26B98A5FFD82C05345A9DADBFAF49:\
+00000000000000000000000000000080
+
+00000000000000000000000000000000:FA735E9BE7961050C202BD794E2E1E0C:\
+00000000000000000000000000000040
+
+00000000000000000000000000000000:7B2D8D2348DC4CE112AEF4311BE769D7:\
+00000000000000000000000000000020
+
+00000000000000000000000000000000:5F35BF3061423D0BC02C07BED67602BD:\
+00000000000000000000000000000010
+
+00000000000000000000000000000000:8C9A19CEBB5709C38EA1AE1D12E291C1:\
+00000000000000000000000000000008
+
+00000000000000000000000000000000:D69C8CCF5DEC9EFA90684C7B70FCDFAF:\
+00000000000000000000000000000004
+
+00000000000000000000000000000000:39B65E77A4D26218E5ED7092AB64D07E:\
+00000000000000000000000000000002
+
+00000000000000000000000000000000:F668C7091F81B2827DA77DD419B708E1:\
+00000000000000000000000000000001
+
+00000000000000000000000000000000:7106BED662E6B6AE72FDC726C98AD746:\
+00000000000000000000000000008000
+
+00000000000000000000000000000000:043AA312B19B6737C3CEBAF830DB6DB8:\
+00000000000000000000000000004000
+
+00000000000000000000000000000000:F95E6F00854F17DBB68CC679570D5FD5:\
+00000000000000000000000000002000
+
+00000000000000000000000000000000:D23FAE81FF497000583F2CFCE54FCE9C:\
+00000000000000000000000000001000
+
+00000000000000000000000000000000:EF5C7DC4DBCE5A51F98011969693DBE8:\
+00000000000000000000000000000800
+
+00000000000000000000000000000000:34D2F0546C260EA4002B4BCC2C12CCAB:\
+00000000000000000000000000000400
+
+00000000000000000000000000000000:B3787BE95735A9581817C64D81F07E13:\
+00000000000000000000000000000200
+
+00000000000000000000000000000000:EB31DC31E4016F7FD8901C5872DCED1A:\
+00000000000000000000000000000100
+
+00000000000000000000000000000000:43D607D9D0009C01DBFB117126BC4395:\
+00000000000000000000000000800000
+
+00000000000000000000000000000000:463B27CF0DA63219ED2CEBDBF5C16922:\
+00000000000000000000000000400000
+
+00000000000000000000000000000000:90DF345556AB04CB12D0799B9C5049BB:\
+00000000000000000000000000200000
+
+00000000000000000000000000000000:05C861F7F71591C8AECF8A26EB020F4D:\
+00000000000000000000000000100000
+
+00000000000000000000000000000000:11DD97B8ADAF7F6B34EB3BBB9A438892:\
+00000000000000000000000000080000
+
+00000000000000000000000000000000:7171E845509F8F4F134BE53EFD8A34DC:\
+00000000000000000000000000040000
+
+00000000000000000000000000000000:864E7B400A96420A98765AF993AAD852:\
+00000000000000000000000000020000
+
+00000000000000000000000000000000:B8F75A0553AA33DC30B3F2D0027F97EA:\
+00000000000000000000000000010000
+
+00000000000000000000000000000000:573FB9B1E047670331D54E87F3BDD48D:\
+00000000000000000000000080000000
+
+00000000000000000000000000000000:03CF30E2ED5C9311F6BF9964C8A7DBB8:\
+00000000000000000000000040000000
+
+00000000000000000000000000000000:ED735C651F003ABCAFE1926472E0CC32:\
+00000000000000000000000020000000
+
+00000000000000000000000000000000:970CDDD5BCCAE7F7BD0F7B67B6707580:\
+00000000000000000000000010000000
+
+00000000000000000000000000000000:6D1C5788F69DC2E1EF928D9C831F3826:\
+00000000000000000000000008000000
+
+00000000000000000000000000000000:8367C4564B707B6C0A4A92ECA38C6EDA:\
+00000000000000000000000004000000
+
+00000000000000000000000000000000:F25D50BBA7FD6496CD70ACE570706ECC:\
+00000000000000000000000002000000
+
+00000000000000000000000000000000:0C43854DF7DD96DC3323DCC311CD418C:\
+00000000000000000000000001000000
+
+00000000000000000000000000000000:8F8827ED63EAFC702A4C7F855E6806A0:\
+00000000000000000000008000000000
+
+00000000000000000000000000000000:DD4FF8498D45936888B48EEFD24CE9F6:\
+00000000000000000000004000000000
+
+00000000000000000000000000000000:DE8BF1BCB7C106D93AA60C744240651F:\
+00000000000000000000002000000000
+
+00000000000000000000000000000000:FC45CB6A1B9267A8B330FC1399BC0F34:\
+00000000000000000000001000000000
+
+00000000000000000000000000000000:9EEC294CEBAEFC664DFA9D1C8B48B0B2:\
+00000000000000000000000800000000
+
+00000000000000000000000000000000:CAFB5B1D66E147006DB2E4CFC8405DA3:\
+00000000000000000000000400000000
+
+00000000000000000000000000000000:B9F43C559CCB8C1933FD323ED51AF997:\
+00000000000000000000000200000000
+
+00000000000000000000000000000000:D11D4485EB7AAA6CB1A8F16E24ECDE7A:\
+00000000000000000000000100000000
+
+00000000000000000000000000000000:A4F7B40448470061B7873A62072CE112:\
+00000000000000000000800000000000
+
+00000000000000000000000000000000:80DF5AD31BF557F9C75701B1395C4AD2:\
+00000000000000000000400000000000
+
+00000000000000000000000000000000:46CE4708ABA4835764EA9C4678335954:\
+00000000000000000000200000000000
+
+00000000000000000000000000000000:72BABC19EE59F6F76F17DDFBE2FCC33A:\
+00000000000000000000100000000000
+
+00000000000000000000000000000000:E76340173FDA4B6F1E2703A732C4C482:\
+00000000000000000000080000000000
+
+00000000000000000000000000000000:79C577AC301DE5ED03AD6D0AACB1D958:\
+00000000000000000000040000000000
+
+00000000000000000000000000000000:A2A8D78F3511B65EA03262314F0C8F8A:\
+00000000000000000000020000000000
+
+00000000000000000000000000000000:6C87E4E87CB3773520F7B3EDB51DAEAF:\
+00000000000000000000010000000000
+
+00000000000000000000000000000000:8D646E78DC20F616A859074DE82D1107:\
+00000000000000000080000000000000
+
+00000000000000000000000000000000:E98DE4AAAC62C1E4251054B42D92F4C3:\
+00000000000000000040000000000000
+
+00000000000000000000000000000000:B0FC458F4759641C6FA64FED926C8347:\
+00000000000000000020000000000000
+
+00000000000000000000000000000000:61F381FA99E58E9B3CEBCBADDE6559D2:\
+00000000000000000010000000000000
+
+00000000000000000000000000000000:2C7EAF752E2B02734A3C3506CDA4867D:\
+00000000000000000008000000000000
+
+00000000000000000000000000000000:600F284E1AB1C8194D6FE065DBDF1BBF:\
+00000000000000000004000000000000
+
+00000000000000000000000000000000:DB84C4BA65B89D0CD51BE73605084568:\
+00000000000000000002000000000000
+
+00000000000000000000000000000000:4C75C41A4ABC17E0ADC00228394F0037:\
+00000000000000000001000000000000
+
+00000000000000000000000000000000:230375EE7B65A2C948809B6DE69D1F50:\
+00000000000000008000000000000000
+
+00000000000000000000000000000000:94EF7F345D1FF0DB4494D9DB56ADFFED:\
+00000000000000004000000000000000
+
+00000000000000000000000000000000:CE277A5063C40BA1418A30721A0DE8AF:\
+00000000000000002000000000000000
+
+00000000000000000000000000000000:BF4FE13163EA85E003EF8E9D4BAF48C8:\
+00000000000000001000000000000000
+
+00000000000000000000000000000000:C8F9F9F1DB54EB0635C227CAE447055C:\
+00000000000000000800000000000000
+
+00000000000000000000000000000000:6F31A90BCEEA0BC85843086C7258EA9E:\
+00000000000000000400000000000000
+
+00000000000000000000000000000000:334EFC7C6930BC0B839C845E1B22F8C3:\
+00000000000000000200000000000000
+
+00000000000000000000000000000000:1E92F9F2E576C864A24F36402F84107D:\
+00000000000000000100000000000000
+
+00000000000000000000000000000000:A5B8DF0ABDBA5DA09B8D8383F06957E2:\
+00000000000000800000000000000000
+
+00000000000000000000000000000000:344B6F348ADA08FF4E97C722463DCB08:\
+00000000000000400000000000000000
+
+00000000000000000000000000000000:AAB52A0482E0A1B84EF07213F8BCF63F:\
+00000000000000200000000000000000
+
+00000000000000000000000000000000:E477DDE4A88A17339157E4198DC39801:\
+00000000000000100000000000000000
+
+00000000000000000000000000000000:33401CDFBECCF499B3226B4C6AD8FDDF:\
+00000000000000080000000000000000
+
+00000000000000000000000000000000:2C06278683B5759C12B147DE2B0E0BB1:\
+00000000000000040000000000000000
+
+00000000000000000000000000000000:B2B67CDC8371B5739F5E213FDD8B60EC:\
+00000000000000020000000000000000
+
+00000000000000000000000000000000:83ACED5FB21035A41B858136D4797BEE:\
+00000000000000010000000000000000
+
+00000000000000000000000000000000:1F6213DC933AEF4C582AAD041E140619:\
+00000000000080000000000000000000
+
+00000000000000000000000000000000:32B7E10E04100FCDA94DC223BBC19075:\
+00000000000040000000000000000000
+
+00000000000000000000000000000000:72FA9C8731E45CF575CFFEBD6F3981C5:\
+00000000000020000000000000000000
+
+00000000000000000000000000000000:AEE9355B2FBD96A06F8F74DC8882E893:\
+00000000000010000000000000000000
+
+00000000000000000000000000000000:B56126C52D0DD2B8FDC5C4A05091F2B1:\
+00000000000008000000000000000000
+
+00000000000000000000000000000000:6FF5B6F133BEB75DDDD0385F9B3AEEE5:\
+00000000000004000000000000000000
+
+00000000000000000000000000000000:6541C5BCE4B3F93F4EC1E7DFED0F98DB:\
+00000000000002000000000000000000
+
+00000000000000000000000000000000:BF9ED60D8A243F1E010345537A5C081D:\
+00000000000001000000000000000000
+
+00000000000000000000000000000000:77679D9E63DB7DF79C0484423FA18A57:\
+00000000008000000000000000000000
+
+00000000000000000000000000000000:548091B07326BF829BA56C786053727F:\
+00000000004000000000000000000000
+
+00000000000000000000000000000000:A8FA704EE06EEED6F7F71A598EF921FB:\
+00000000002000000000000000000000
+
+00000000000000000000000000000000:627F14CA091AC156FB56302D6C3373DC:\
+00000000001000000000000000000000
+
+00000000000000000000000000000000:BC2CAB97EB09919CBC0E6AFEC6581CF5:\
+00000000000800000000000000000000
+
+00000000000000000000000000000000:CC7F5DF0CF522B2242163112E4421D08:\
+00000000000400000000000000000000
+
+00000000000000000000000000000000:084AC3BF07F1E64F0093A014C2690CE5:\
+00000000000200000000000000000000
+
+00000000000000000000000000000000:D3C6597474B740BA1053090A247AB5C5:\
+00000000000100000000000000000000
+
+00000000000000000000000000000000:7435911B23F1DBACA5BF86C91B0D11B1:\
+00000000800000000000000000000000
+
+00000000000000000000000000000000:79E59CE5B78A6D8259B2AD1B5F50F523:\
+00000000400000000000000000000000
+
+00000000000000000000000000000000:72F3659183D9749128AE6CAFBEAADDE5:\
+00000000200000000000000000000000
+
+00000000000000000000000000000000:77DD6EA2D669A36E4C409564A8604EC4:\
+00000000100000000000000000000000
+
+00000000000000000000000000000000:27D4EC7E2AE30CBE54B7CE9F764E3D27:\
+00000000080000000000000000000000
+
+00000000000000000000000000000000:0D68C4922498D08BFEFA450B85659D23:\
+00000000040000000000000000000000
+
+00000000000000000000000000000000:6C4FCEEFF2768549EA590FC20310B95D:\
+00000000020000000000000000000000
+
+00000000000000000000000000000000:FC46909BE47E944F4776956A98E9C43B:\
+00000000010000000000000000000000
+
+00000000000000000000000000000000:50AA945A945A8BE43E4C137F0D7CA62A:\
+00000080000000000000000000000000
+
+00000000000000000000000000000000:7511818C4C8408EB0AF22019DDF7F6F6:\
+00000040000000000000000000000000
+
+00000000000000000000000000000000:D46BA09B00007974C24FC8C0CB13330D:\
+00000020000000000000000000000000
+
+00000000000000000000000000000000:17E352C6C963F7DA5A1CB163ACCB8573:\
+00000010000000000000000000000000
+
+00000000000000000000000000000000:6CED1C994D0F7B2862715D514840A780:\
+00000008000000000000000000000000
+
+00000000000000000000000000000000:AD351E157AFC89A9C0D8CF15DDBF3A7D:\
+00000004000000000000000000000000
+
+00000000000000000000000000000000:79AFB080BADC325DA8C5E88200743603:\
+00000002000000000000000000000000
+
+00000000000000000000000000000000:D326FEA25FE2CA220CEC62DB9574AAFD:\
+00000001000000000000000000000000
+
+00000000000000000000000000000000:A3C980B5DA0B8E3B32818AF08F5310DA:\
+00008000000000000000000000000000
+
+00000000000000000000000000000000:12651FD76182C532CD03B36DD121A43A:\
+00004000000000000000000000000000
+
+00000000000000000000000000000000:6D91A4600722340B8ECAE1055B8DF790:\
+00002000000000000000000000000000
+
+00000000000000000000000000000000:2B1F49C97807430719A958271B5DA303:\
+00001000000000000000000000000000
+
+00000000000000000000000000000000:9E29DADC12AA1ED228CDC78D70C829B7:\
+00000800000000000000000000000000
+
+00000000000000000000000000000000:5B8FF678F88EB96FE73BCBF14AD9304B:\
+00000400000000000000000000000000
+
+00000000000000000000000000000000:158B5F6CBB33E547735E45559CEF3E5B:\
+00000200000000000000000000000000
+
+00000000000000000000000000000000:8EFA3AC040AC5235F2F4AC3A82B7018E:\
+00000100000000000000000000000000
+
+00000000000000000000000000000000:97BACE474E820FDEEB1E66D06139D2F9:\
+00800000000000000000000000000000
+
+00000000000000000000000000000000:114CB849EC2735AEECDB2E51A1C45A38:\
+00400000000000000000000000000000
+
+00000000000000000000000000000000:1426ABD1FE61695A62B7A55AB5DA6145:\
+00200000000000000000000000000000
+
+00000000000000000000000000000000:80C615975140248186BE3CD6FD8D7740:\
+00100000000000000000000000000000
+
+00000000000000000000000000000000:CFBD333352A34ED7F73D3E569D78C693:\
+00080000000000000000000000000000
+
+00000000000000000000000000000000:5F04350AB2EFB6075F381EE1DBB8477F:\
+00040000000000000000000000000000
+
+00000000000000000000000000000000:CF5CE38D2033AD6E6891ED24DB39EA66:\
+00020000000000000000000000000000
+
+00000000000000000000000000000000:3E63AF44877F258840B165CC3D47424C:\
+00010000000000000000000000000000
+
+00000000000000000000000000000000:264E5481EFF42A4606ABDA06C0BFDA3D:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:4A231B3BC727993407AC6EC8350E8524:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:E03269F9E9FD853C7D8156DF14B98D56:\
+20000000000000000000000000000000
+
+00000000000000000000000000000000:A798181C3081AC59D5BA89754DACC48F:\
+10000000000000000000000000000000
+
+00000000000000000000000000000000:34B355520DF861F3F5C66A2379FBDA15:\
+08000000000000000000000000000000
+
+00000000000000000000000000000000:5E86BB8F6B1175510C6B244281A0B04A:\
+04000000000000000000000000000000
+
+00000000000000000000000000000000:B9213190C7A9C5F13764D29B6DE843A1:\
+02000000000000000000000000000000
+
+00000000000000000000000000000000:4ECA55033294D1FF6F0204B2456046C8:\
+01000000000000000000000000000000
+
+00000000000000000000000000000000:660CF6A3F77836AC685519C702548EE7:\
+000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:9EA538A95E21B6738B0F4BDD0D5A6423:\
+000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:19D13A0AC90F83E5B3CA943C6462D295:\
+000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:1B9DD629B9E11BCD27C4148887AE662A:\
+000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:14EF2BA201698B1185B4F45D3C4BF7C1:\
+000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:8AF1A83901D7DD153FF8D271B210E3AB:\
+000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:4209B9F47FE46DA7095E093698227280:\
+000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:5D058517AC7CC5AFD5C33253D4703B46:\
+000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:40520018C4AC2BBA285AEEB9BCB58755:\
+000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:FB12E82326B5B32A88C73962E6B15A73:\
+000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:10514AB50FB935D4DF8D36697E9A892C:\
+000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:23BA3FE846E2AE8CD99FC3FE58228A05:\
+000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:68E7992B17261F9F50693B291B40DE29:\
+000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:16F61AE21DEF7E6FF252F7A7C0A1FD33:\
+000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:79386D808CC081C0888E83C047411490:\
+000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:81421CDE68390C877C025D60D7578959:\
+000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:8BE4D123F250436A35AC1506BF462E25:\
+000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:FD007EFCBF67C125F8532A7FD54724CC:\
+000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:D6661DE82FD241500194134F40C30071:\
+000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:B03A391CCAAE863B0ED315B0CC4FF99D:\
+000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:B5142CABF118C8BA5DA8A201E7E04448:\
+000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:2B078B616E4802ECC0104510E3E7E44C:\
+000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:CE8A95407154E3B8DA3979FDA451F288:\
+000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:EF5D9D75A6A31712BAD7D332FCEF52D7:\
+000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:CE6430157E4EAEA967B972C35C78036C:\
+000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:7117137E956133BF65BCDA326A8156F3:\
+000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:7D0D165BDB56D794FAC1B1C5020270B1:\
+000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:2AE14DC8A1CD98E1BD20D4E01E32DDD2:\
+000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:AE266BE3BF863707C6AECE963D16530E:\
+000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:3A2612AF977665D4E8D05E3EA9947E60:\
+000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:95491F2AD7B48986522E3B1EA14DE24F:\
+000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:8A1E5D419E900C9FD046BA1F74C49DC8:\
+000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:E407985AF526A75AB42DB52D64987992:\
+000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:6C6EAD1E4101F16AD0FC4DE34DA19D8A:\
+000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:84E74236D365A90B6417221C0E5ED058:\
+000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:7DC0D45689A260233E52B56EE49F326B:\
+000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:E69EE6C58AE686AC193F4A118E5C7680:\
+000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:7FCF4D217B2A37C8D3A822C43B1A119E:\
+000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:6D37043BF5B8D45F1E44A7C0E792A343:\
+000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:ED46DEA31CAC83EE9F812C9006891C32:\
+000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:DABC07C4DFDDA34A8B61D1E1F0461196:\
+000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:E733109E82EEDEFBB02512F1C030FF35:\
+000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:9F3BF5E17F297B3B3F3D6311B2874FC1:\
+000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:CF2793EDA6299C358F79D0F15853E075:\
+000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:4CFCD92E08E82B0B3FC7C0CB8A2193CE:\
+000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:409F6D08C56C0129A485A2CD503AA754:\
+000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:4D80946E2267E0E485CDF4CBEA0BDE73:\
+000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:EAE07676A063EB5F7F99FAED7B065188:\
+000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:A783EB0A14B5212A9BC439F225F33834:\
+000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:524282FABF8B62D291AAAADA12423AE9:\
+000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:306D0E55364394631EC18BE972EF0B66:\
+000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:87D8BA08354745FE85BBB710FCF5EB39:\
+000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:894D2F50F43BA36B539DE43637927AC9:\
+000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:479C1979DDB0052BA7DF875314CB2A35:\
+000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:E0E5399FEF15563392741BC333246873:\
+000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:86F93C8B9552D8971367EAE2A366312F:\
+000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:9F18DF64A519FEC0581C0C27F805F484:\
+000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:53BD3E8475DB67F72910B945BF8C768E:\
+000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:456C1BE9ACEFA86AFB9742AB867692B1:\
+000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:89EE6EBDDCB44B7F17157C154BB99221:\
+000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:51ECA17E2C529F17592F9A117F6F592B:\
+000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:A51036D7D90699DDA88ED9A16EE6C556:\
+000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:07C856A3CE6F131D785BDE2E3DB3D36A:\
+000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:A06931BD2C6D9C3701E0286016AB8555:\
+000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:3A07686652A8F7E35FC9B3333EA97D16:\
+000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:FD008310340BA35239165FCA8F52B3DF:\
+000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:FC7E859D16DBF0F92FB8B3286C110315:\
+000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:86C0CBEB5633EF88ABD436BA54AC4D7B:\
+000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:CA66CEA4EAE07B83E1EEB737FE72EADC:\
+000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:019754956B6DC021D25731EF988BDAC9:\
+000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:786EC65CC6C717A171822F1DD1AB3CE8:\
+000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:DEAB7388A6F1C61D41E25A0D88F062C4:\
+000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:F08DF5D467F41CB7D157C6E6C78900FE:\
+000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:0225B99C3E40C8A5FD0156BD6A2B9349:\
+000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:6B8D89725A7AEB5AA433011ACF5B72EC:\
+000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:6A8B55F69923153ED6A95BF4B78CCE6E:\
+000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:199B86F903787EE3EDD60F8393F4A89A:\
+000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:BFE08316360801D0B929BBE1786A8570:\
+000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:887B6ECDBF12DEB314C50F07B870EC3B:\
+000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:C82FDE13839BD8BD8FC408131F559648:\
+000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:0482615608212073881C83A90A0B2721:\
+000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:CDFD5AF33A61EA9BA8C6E4DD3E84949D:\
+000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:A9EFF0A790FEB09727558C1FFB4247A4:\
+000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:EAF6266AC9F0A0E96ECF6E602DE61B73:\
+000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:59F44B4178A92AF2CA778BDA351247F1:\
+000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:87C3730E07C280D110EE11BBDB2C7BF6:\
+000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:5F6BF404C25C812FF2E814E4FEBAF636:\
+000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:92B8C78C75EE5BB1C27DAC75EF76D2E0:\
+000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:1E9F7474C984CC73B7F90F8EC01F547D:\
+000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:9CAAD32B4195E293A792CF2403839879:\
+000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:B384BE1E8CEAD9DE1E209FC92BA6A3D3:\
+000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:4E512E32F6B60CFE5660D7CFA21E13FC:\
+000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:832615D6654549BB930EC8DBACC5AE92:\
+000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:27549DC43C2DEEAFFB1C52AC37AD9728:\
+000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:804E4F4C6FD215D4300704142407020A:\
+000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:C52FECB8EDDA2D9BF3E5856231B87F6F:\
+000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:26474A9B6A125DA80A989286F1AADB77:\
+000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:15955CDA082E2278B2EAB498BAE90A5D:\
+000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:04191E4D8945BA1E9D02098EEFCD65DF:\
+000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:C1841B80C1E0E4608F0C261F8FF91199:\
+000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:7FF3E31C19BB193B4A2CCD488CB44F97:\
+000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:2FB402BFAAACCC4F55C9EBA37D2AA543:\
+000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:97289170C25CE1EC2011B27487DC8903:\
+000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:3BC60DC98B29BA75D7DBA12D78BED74D:\
+000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:21C3E9BDB411A2CF58ACFCDDA07CA06E:\
+000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:174FC71F855D61484B8C05DEB12988BA:\
+000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:337671C8D092C431778655358AE1A622:\
+000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:D671E381AE4CBFBC4D360ACE36538EB6:\
+000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:9915EB2B534C901AB3E208F0B8274438:\
+000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:CBB867073A139F7A39A5ABFB1F9B7084:\
+000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:487B9F02DF40531F6B1BD096A8E32377:\
+000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:871D4D57145444F7858A3A1727FEE068:\
+000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:56463A7AEB3D1B104868B5F0CB88479B:\
+000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:1A00009A7CAE8EF56B167F94F9932585:\
+000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:BA0BDE829631F63E14FE1995C57CBE29:\
+000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:A0625DDE21DF874E27751F460DB24939:\
+000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:3A850B3917B926B7C1861AA8557548DB:\
+000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:33FB35F2ED3A0F9A9C0D62868890B706:\
+000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:8EB519BF9B7F9841FC429C21930730AA:\
+000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:973672A4178DA471DB7C2CC9F3349DA4:\
+000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:EBC56A2AB4DC394C8409EBC529103C09:\
+000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:00300AD85514851A32376A583B99416A:\
+000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:47CB1114753A29FA68E83BF3754F5713:\
+000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:556424407058A1BF639387032BB4972B:\
+000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:C573C69439543B71A1EAF6A38D1DB977:\
+000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:570D68BC03C1AD3173316BB3484166DB:\
+000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:2ABE779A9A42BF593A2D20495C6F5A37:\
+000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:7D648B890DCE86ADAE607B24B17F7ADC:\
+000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:8AF02339AC04EEDDC5D29B1D8AB85E34:\
+000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:D11C7DCD0E9B857DDC1A8D73169BBA2D:\
+000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:7A960A521E193922ED2275B1FCEB484F:\
+000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:357E6FBCA32874FDCE99AD14BD10C4B8:\
+000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:1AC04248825E32B8E71C34875371F307:\
+000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:038A5BB1246BB8F0460ADC7826211268:\
+000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:EF923294B89B78F017C874FC4472762E:\
+000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:19A8882B0FDB10E143FF9DF9D32DA301:\
+000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:399800963634CD1B96D9FCEFE1D0815E:\
+000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:9B5B6DFFFCB2201390728372E1259012:\
+000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:0DB33144E4EB0FCAC271AB4D26F7B3B3:\
+000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:D7987CAA9C1CAB111984C2BA993F95B9:\
+000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:7F57B51D6B2E5E8C3DBEDF6B68A3ACDB:\
+000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:5DE80D7BF3FC0B05ACEB1311BE12E31B:\
+000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:BE2C16F62E116A472C43D526D582A2F2:\
+000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:0D9AED1721E71B09C7CF34650315ADD4:\
+000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:2B06E5A2CB8E141B6F194E7987D32E14:\
+000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:FE2893A03D01523DF7BCF0EC76A71E76:\
+000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:018056BEED112C1B11C6D58F383E51F3:\
+000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:20D29D2A08CAED608CEE792B82E9F900:\
+000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB4786827E61312B24889E8A75BFE0E8:\
+000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:81FC9F0C865FC970721180942F0DADDE:\
+000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:179BA8EFBE611F1358B2D7C8A14F6056:\
+000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:5509A6F21705DA67E685C1D2515FC40F:\
+000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:9EF148F4819E1AD53458FF7B97512719:\
+000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B992E1FD9026C14545D3B45BA12DD26:\
+000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2A1A31C9F9EC3F0041E4981C14075C9B:\
+000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:668D25EAB49A68A353170FB9804C49E9:\
+000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B0851073E77BEBADB5E4620A5ECAB48F:\
+000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:0D7DD474F2ADD4E616C2BDCB31AE295E:\
+000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:19E972ACB8159AF2BE06C2CEB13F17CB:\
+000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:D3181CAF92EB933472AB5D7D9A79359F:\
+000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:AA8B04CFD3F03D913981888D65F595F4:\
+000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C972EAE644F542F2D61581105DAA2DE9:\
+000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:40288DA36DC4A581CFC6BF52768AEAC0:\
+000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1460BD4CE7589DFC8CA2A341CEDE21A2:\
+000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:415E3D395E8AF9F0B367B18279EC9D36:\
+000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:52841B754B398E76A046A808D0254DB1:\
+000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E28C2E20BF18DAD62ADA7B46D46C51AC:\
+000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EACF9AD4EAC19266F886CB3AE50B2CA8:\
+000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:39057A7055ADC3DF052632BA75845405:\
+000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0637B291488FCBC39EA131C5D0393617:\
+000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:53A6EAA591C754B9AFB8E14B39BFFE79:\
+000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AF9DD24F6FD3C9BAD97466F4E19D008E:\
+000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6F6C9FDBB84546B3BD98703730A71292:\
+000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:00DCD917419399ED52E2A528ECAB86C5:\
+000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DC077DA2CBF96509A74980CE12786C41:\
+000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AADD759F77507F990D3856F6EFC91978:\
+000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3948D1EF7CE021CEF9C6C1405BB5A6F9:\
+008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5B8AC83847FDCD6006F7D59A04BE703C:\
+004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7F6347B6A370FDBCD26C91E5F1BE4E77:\
+002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3D8DC8CEF60F4F0F021BEA3B8A268740:\
+001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C9BA9FC07BD7FAD3CBD56DBF9A7C5B00:\
+000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B660D768B8E32F0C4E15386C5F3450D:\
+000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9A15675F3631BD2AF387A7B69DCEB89E:\
+000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:893978E492FED5662D13AA2F759DC89A:\
+000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9E274EAD9B737BB21EFCFCA548602689:\
+800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:92FC8E510399E46A041BF365E7B3AE82:\
+400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5E0DA386C46AD493DEA203FDC6F57D70:\
+200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BEC1E37824CF721E5D87F6CB4EBFB9BE:\
+100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:257A79F891BB8D0C13FEEF1ACC264214:\
+080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B3EDD5BA04CB6FF80A3874411C1B8B7:\
+040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:73C83EA96AE151230B2DEE7110B15E2C:\
+020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0ABD62FC8802C9BC86E2544909AC610F:\
+010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1908EF821AD2EBC0CB28BF66E796EDAB:\
+0000000000000000000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:8D88B1E7BB45E0DD5603D8FCCD589695:\
+0000000000000000000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:284CDF6476175B6BB414E7FAC09CD404:\
+0000000000000000000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:66487D053A660BD840D7DE39A3B1F139:\
+0000000000000000000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:869A570998988F68819CCF301EB015DF:\
+0000000000000000000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:F6899D57F734AFD6473278DBDE8FB99D:\
+0000000000000000000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:A6726CE53BD62BC873F6C0463A5841FC:\
+0000000000000000000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:9858FD31C9C6B54AC0C99CC52324ED34:\
+0000000000000000000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:82EDDDC59E207131F1AE2A2A06A83284:\
+0000000000000000000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:1C17A9F76290FB6C0F0267BB1CE832C6:\
+0000000000000000000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:6DD6415CC9EFB2323FA78ED28EEE06C7:\
+0000000000000000000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:48FD01A424E995B0E0840353439B1A4B:\
+0000000000000000000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:2B139C4C4200A8DA4DAF8169F84A4089:\
+0000000000000000000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:0D7E0A00E181F592C1D75250AC940517:\
+0000000000000000000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:9250D327F678E8EDBC25CB40EA70391E:\
+0000000000000000000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:4D715D9421FCB51C7B4C94DEF2B5C210:\
+0000000000000000000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:19DD5DEC75CEE00003995BF2EA643E2F:\
+0000000000000000000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:BB75015A768AB1E9BC4AF49D2D156C4F:\
+0000000000000000000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:46EFE1B09EFB606CB11717415511862E:\
+0000000000000000000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:360D02F49944ECAE2EE2050E634904CE:\
+0000000000000000000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:93E207973539B6E2EF7D49C772E32D86:\
+0000000000000000000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:2E71481D28ED6BD01157F4D054F01961:\
+0000000000000000000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:AC06EB8186A501262CE9B06FC88F9774:\
+0000000000000000000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:A94CC5DCC946C9B4F38D1D46BF1C0335:\
+0000000000000000000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:17A457DA5304D77BD0BC4B5B8BB02FDD:\
+0000000000000000000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:B6DF6B6C45A38ECE7E940C45FE1E847E:\
+0000000000000000000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:83DB5E464D300A76EDA858E108902EBF:\
+0000000000000000000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:C7FB67AAA9F7417DC5977B57B723D278:\
+0000000000000000000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:1DD21FD2291C7419B5593EE8D6712198:\
+0000000000000000000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:A2E337EFDF4B888C2B94B86AE20FF8E8:\
+0000000000000000000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:61F70FEAB04DB61D959A69E9C1BAAA9D:\
+0000000000000000000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:6FC6C5718FD0B81194A198F873EDE7EA:\
+0000000000000000000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:DFDB243581A8D3DA8A3F268AA8E6207E:\
+0000000000000000000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:965A8653210830C831353A28CBBFD16C:\
+0000000000000000000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:E3442D2FC126CC50AB364E09A0872B18:\
+0000000000000000000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:B261BC4E7FAE6629FC5F5D588E417CAF:\
+0000000000000000000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:940218AC849FD119D89B0E15376213DD:\
+0000000000000000000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:C07DE68CB0ED8C8D398B87D6547BD15B:\
+0000000000000000000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:F14145E5DCB1EFA30A5A6CA08EC8F8FE:\
+0000000000000000000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:4D08CD60B971B10854A0912DAF5CC3A8:\
+0000000000000000000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:73C96C4F08BC5F9725CD2F719402DF4B:\
+0000000000000000000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:488AF3D7E9223041C2C26AB496BBF0E5:\
+0000000000000000000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:CD5038A80ECEC3424E1E9614CD3267DD:\
+0000000000000000000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:C38D3776A560BBC5453E96C1587B0E59:\
+0000000000000000000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:845416D12195B8FC18F299AD41D8F569:\
+0000000000000000000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:07B3D3BB79520764234D247A7A0036C2:\
+0000000000000000000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:BD6816944B3A1353229B02907CD0E87C:\
+0000000000000000000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:CC547CD2016122227D7CE3B4BFBE3EAF:\
+0000000000000000000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:3CF2E1206969ED3A85E28EFA16162E53:\
+0000000000000000000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:801DB46F97025BB099F7755595C532E3:\
+0000000000000000000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:4322F95A6D70B9D4F53B733505A11D79:\
+0000000000000000000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:D1A200ED8E473284B70EB16E93B55ECD:\
+0000000000000000000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:AAB1879D98592963B8F90C8F06804207:\
+0000000000000000000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:E221625345B6E73DD09235C7A3957CA3:\
+0000000000000000000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:02B055320E02DA991986BB53A1CC69B9:\
+0000000000000000000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:FCA1B117007B2C06165E3D773CCEB0C9:\
+0000000000000000000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:853E0E5DD1CA7C9C55388DDBA2F138FD:\
+0000000000000000000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:6991C5D5E1BD766597115C5A213F6CFB:\
+0000000000000000000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:4E0D7A3C6816CC844ABA4BB6AA0F3592:\
+0000000000000000000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:1A93F22F2E11AFC3CECA1FC17065ECEC:\
+0000000000000000000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:1519F9986E85E5B942A66DFE1D6ECBE7:\
+0000000000000000000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:2B583F2363F6C1D981BD2D0C3F965F3A:\
+0000000000000000000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:E92FEBFA44950BE01CE755EB4607563B:\
+0000000000000000000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:A583EF976A292B406BBD5DC8256B0442:\
+0000000000000000000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:08D8A40BCA6BC1C31BADCC9DDA387D9C:\
+0000000000000000000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:F502C9674BEBFAE010527C808CA03F5C:\
+0000000000000000000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:E85D57184DA2B982C18C8B13B1348838:\
+0000000000000000000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:6E71FFAC10EDBF08A6DC42BDA14AE1CE:\
+0000000000000000000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:0F2D7BEE48845D8A17ECF93F52F9036A:\
+0000000000000000000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:CBC811575660AF9F7E869631ED779F66:\
+0000000000000000000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:F7E405B065FB1A03EBD539CFCAD08E17:\
+0000000000000000000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:0872458B2E2C4725CE7DEC3FFFC47F4A:\
+0000000000000000000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:18DF0F25A865A0B6EC844D810D25FD87:\
+0000000000000000000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:35D6DB5996115E7E8C1BE200823E7C63:\
+0000000000000000000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:CDEA1849DE224D92034BEC826682AD47:\
+0000000000000000000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:7343B1923DB7C28C195660252857ABA3:\
+0000000000000000000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:F02FA74352855E5FC194F18476DC2916:\
+0000000000000000000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:ADCAFB490DD340784F084779CE182FFE:\
+0000000000000000000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:0CE37E34B01BAF724841EC58A6B90990:\
+0000000000000000000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:A577782DBA6EDE990B2A28FBF52899B0:\
+0000000000000000000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:E5BD5E55A80FE196A2AEBCDB6798614E:\
+0000000000000000000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:DAD3F4D3B96EF51C2D4D2869FAEA4C1D:\
+0000000000000000000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:28E64B7DC148055040950974E718B27A:\
+0000000000000000000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:08C9B5E67B8954FDFE74F391B7AFB754:\
+0000000000000000000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:9CA79528107403A7430CD50578029990:\
+0000000000000000000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:45A104CAE36E600B6EF91B91FC1C657C:\
+0000000000000000000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:D9CF9457265E7ACC57EFE25736A11FBE:\
+0000000000000000000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:D1DD8AE84D38D129A5FA0E9D9520ECF8:\
+0000000000000000000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:43FB732672D6243DDC9C547E46711FBE:\
+0000000000000000000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:A2622ED785815C12C949EBED89094FC3:\
+0000000000000000000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:FBB93B64CA5D94692B4E6EED934112D8:\
+0000000000000000000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:CD3681FF583D4BC4886D864CFA94EF97:\
+0000000000000000000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:37ED3CE092A1AE925264751DFFF6B50E:\
+0000000000000000000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:3CA305833473AC6990A41E37A7BE551A:\
+0000000000000000000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:CEF8EC0353A04B3DB1309F88265FDABF:\
+0000000000000000000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:51C23A4293BB9B963AD17E349B8A71C5:\
+0000000000000000000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:B324D96D901DB388CC1DF28092714335:\
+0000000000000000000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:E572F8132305A28A1E09BF5ED8ABAA8D:\
+0000000000000000000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:E4CBB63909992197E9654069BF4EE3EE:\
+0000000000000000000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:14B1DF955B3A20EADFF35C3869B0B624:\
+0000000000000000000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:4D9019A6223F39E2075C95C7724959FC:\
+0000000000000000000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:5352A5E6F316C51F0256B3A0BC283D47:\
+0000000000000000000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:9F570DD55188193525D0C0244CBA2CFD:\
+0000000000000000000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:1B206FEA626AD786255A3186AC5F5132:\
+0000000000000000000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:D7078E2A1CB16142851F7C5F86FF4E64:\
+0000000000000000000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:FED174EAC6701DAD5DF03DD8A438D99C:\
+0000000000000000000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:9112A5FEB40E3134C26303F379F29AF6:\
+0000000000000000000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:B190C3C5AC183F95F71495A93C679BDB:\
+0000000000000000000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:5777C456EEDBB7756AE316517C1072A8:\
+0000000000000000000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:5550900FAF11F9D2DDC6CF2F1D7AAEDB:\
+0000000000000000000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:BDE3013E16AFDF64A0F24991D7EE5752:\
+0000000000000000000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:71500F21B4145961271727E896C62F24:\
+0000000000000000000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:801CA8E44FB6BAB5DF7FB96AA5F39F8D:\
+0000000000000000000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:9EB5169E8F72673301D0ABF9E85422BF:\
+0000000000000000000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:CB377E74144F9E9405355F089CA3918B:\
+0000000000000000000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:1EE82E9E6E525DAEB21DF068DFF7AB09:\
+0000000000000000000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:6316DDDD174659C16CF3324A770225EB:\
+0000000000000000000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:E17C717EC7A1CF3492710D9FE53A26AD:\
+0000000000000000000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:675F1E9F7C895DD0B4E1F8D4EED1D2C9:\
+0000000000000000000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:446B5ADE1FE91D73511403B34F20FF16:\
+0000000000000000000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:C19171490B5595E8555C61B352935DEB:\
+0000000000000000000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:57159E7BE66463408FAE89C376318FA8:\
+0000000000000000000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:C2441BB36C7B7977B0E6EED5AED1BE09:\
+0000000000000000000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:63A33251E59FF5A6CE0482EB4B80E70B:\
+0000000000000000000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:4459D2EA77E8E8041DA46EB36705B054:\
+0000000000000000000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:E76A69F531CCC2C1A4C56AEE55B63C29:\
+0000000000000000000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:97E97C261C31046F115FEC15820E3822:\
+0000000000000000000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:3620B17AE6A993D09618B8768266BAE9:\
+0000000000000000000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:4172B0BEBBEF90672EB0623A709FC734:\
+0000000000000000000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:265829FC78FD18069B3631AE596DC9BF:\
+0000000000000000000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:E89B25E3E40E28D37BA6E78C55A611F8:\
+0000000000000000000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:8EBF95D561DD65F9BC66B82A6905828C:\
+0000000000000000000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:8C8F6AF8078C29D23B2958CAE6858A09:\
+0000000000000000000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:39FA2682ABFABA6A705780E72BDA0128:\
+0000000000000000000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:A812C9D68212B21A14E9CEBCA8960750:\
+0000000000000000000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:47BFD757C13ADA4001DF9B0989E7CB80:\
+0000000000000000000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:A95ADAA6A53D1BF0FA4E46EA5D1EE88C:\
+0000000000000000000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:D1031805010BBACD8BB316EFA437EC4A:\
+0000000000000000000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:7B6A4380AF9337C902AA691243F6A2E6:\
+0000000000000000000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:BDEF751D35F3B8BC6A9AB61F6B04A94A:\
+0000000000000000000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:51CFB9ED07D3628D0854C2E85FC4B866:\
+0000000000000000000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:0CDA37833BE087D8B997A54D5CFBDCFD:\
+0000000000000000000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:938D2E6F2149D1E0B6F8878D472F0469:\
+0000000000000000000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:3857B0C25F235A22F347E0ACCD008FAD:\
+0000000000000000000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:3BAADE8819E09549CDA6AA160F4C626A:\
+0000000000000000000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:0F5E7BF2A2590F7A65D17DAA4E828F7D:\
+0000000000000000000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:510B105E4809B4115C999AB346D21570:\
+0000000000000000000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:0FF47C9330A69D2B5C52434394A2D1CA:\
+0000000000000000000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:AB8301BFFFF3B24A3CE63F553443F2C7:\
+0000000000000000000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:49A3F4514E983616F55580EA4EA12DBF:\
+0000000000000000000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:C007AEA2279ED965AD5F037359DE24C4:\
+0000000000000000000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:BE5FCBE21961382305B6EDBC74B6D73E:\
+0000000000000000000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:5F3DB2DEE7074DAE2340174109D6BEF0:\
+0000000000000000000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E530BC0CE5A24E03AD0D215A7E9D9A15:\
+0000000000000000000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FFF5A17155933F6084EA4C1BE1245769:\
+0000000000000000000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:64CA3D5422833F7A4AD1FA5331C08A78:\
+0000000000000000000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E42C18F2B56A0E536E4908F84DE06419:\
+0000000000000000000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:97823D74887FBE3E6B412407A256A018:\
+0000000000000000000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:8A1D4467260F12AB493334133D5928DD:\
+0000000000000000000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:735E7FB4B1B2D54C6D33E3D0C714BFA0:\
+0000000000000000000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:AD4B018D50E3A28124A0A1259DC667D4:\
+0000000000000000000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C899A00A2585C1F654694700F1EC1531:\
+0000000000000000000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAE53DCFCF6D6E360A27755F9CE81B6D:\
+0000000000000000000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6E181C731459C3360778BEA1BA86164D:\
+0000000000000000000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:97FD2DDD6045805A7B34879A6AB55D3C:\
+0000000000000000000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:547D61C02DEF0D9869DF43907D3B8124:\
+0000000000000000000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9E457544FC14C723884DD15DEBC25157:\
+0000000000000000000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E0767EC3934ECF169116B485ED0C755B:\
+0000000000000000000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B4B30728F0DDBB28402E252DC6DDBA4E:\
+0000000000000000000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DDB074D9E22B61FCDCB2323A52046221:\
+0000000000000000000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:91ABBBFECEC752159297B832055E99FE:\
+0000000000000000000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:25415EF8615CC222B1EC77046B094C35:\
+0000000000000000000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C11856EE23FA27F2F426844EE9C7B081:\
+0000000000000000000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5E6F28690F31CDC0DAD21D8E3E1BC985:\
+0000000000000000000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:712D271BAB597FF6728C0A55CE6C3CDB:\
+0000000000000000000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4A567C948597B47A1ABF5F8CCD77AE4F:\
+0000000000000000000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6ED568AD50C256B77945E19C04086D98:\
+0000000000000000008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F2398F417C685FE664735E29DB29BBA9:\
+0000000000000000004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:37D20B991D910044C6BEF068028125D4:\
+0000000000000000002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35721318ED63062B43D37C4F14101962:\
+0000000000000000001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:74A004A5D483CCA7219EA12AD4AF5CA4:\
+0000000000000000000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BBCEA8A80619D2AC53037313E71AB56C:\
+0000000000000000000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:646E434C0FEF5CD6CD9C7A26BA972BB1:\
+0000000000000000000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8F2AD3F65E9716E611501D5B7AD81127:\
+0000000000000000000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BCC02339FCFFCAE0536FB5410AF91129:\
+0000000000000000800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DD6A02B2DC091212A746C8FC9967B8BE:\
+0000000000000000400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4BB9FD26E225C913F9BE1B697D31B5B9:\
+0000000000000000200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2A3BAC4370DAA0D68CA90939F43E33CC:\
+0000000000000000100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8576F1070E25B5FD944C366E08CC9102:\
+0000000000000000080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E620C37AD1650DCEAEBEAE1F57BD8AD9:\
+0000000000000000040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7761ECD209CB564EEACAB4E62DB26BDD:\
+0000000000000000020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:67D23F0CF1A57BA0E43FE82A3F4FBBB6:\
+0000000000000000010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D9732CE2055E7F935468A63A170B598C:\
+0000000000000080000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E9F396623AF12ADF24C0378F42F7B4BD:\
+0000000000000040000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:98D5AE45E15A836C141CF7F64DC7D551:\
+0000000000000020000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EEFBED56D7BD47D088B3AD657A6CB8B8:\
+0000000000000010000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A99342C96F331950D97AFBFC8C0D4E08:\
+0000000000000008000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:25C35298C0A1224F2BEE7EE8AAA86E51:\
+0000000000000004000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:66602FD71F84B2637B2283CD81DE3080:\
+0000000000000002000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D48E45670FD978FA4DB161C0E5D59FC0:\
+0000000000000001000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:ECE089620BF6866A66FB6070C491C74C:\
+0000000000008000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:36CD300072D4EC94A0FF3595F7A2C1FE:\
+0000000000004000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F939CB3D8316B59600F164234E78D228:\
+0000000000002000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:17C6258E6009E282661869D525F7D204:\
+0000000000001000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:45A32C5EA3E2E548A9E6313BEF957308:\
+0000000000000800000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C2105CC6264024EBEC6BA0F825FD5163:\
+0000000000000400000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:85F3D2169883A7CD54A67DA7C4AC613C:\
+0000000000000200000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B5FFC7D92EA2815C0F4DC9182DA160C6:\
+0000000000000100000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C9642C4E3F420CA73E8F1C15C6EB011F:\
+0000000000800000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1BD0EEF566BEFB4D57CE7120B731125E:\
+0000000000400000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CB0705AE3DB537AD1C202DD6635202DA:\
+0000000000200000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D88F55DAC599BEA8440B4BA9E3C50016:\
+0000000000100000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FF227EC8AF4640198173A79B124CEFDF:\
+0000000000080000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CC55A4F4086043F1E1ABA9CC91E4395A:\
+0000000000040000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8D2BAD986865A229601855B024D9A557:\
+0000000000020000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:343E1B000FEDAC000376EE138FD8F0F7:\
+0000000000010000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:765DF290B8D90C9169E6884A0D4D4B92:\
+0000000080000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F9EEBAB9F5CEBF94196FEF3872C46881:\
+0000000040000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:318B1983222E49F5B57E26E70890A5B6:\
+0000000020000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D8DF0A98604C987283ACF7F211D906C7:\
+0000000010000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:92697CF743A72D2D4D7864132A9ADE0B:\
+0000000008000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2C450C8BCDAA9CB59F930DDAE88CBDB3:\
+0000000004000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4284A05C4A0AF59DFF15604ACBB82743:\
+0000000002000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:986A05E8447024C8468A1EBF7743F689:\
+0000000001000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4A7E5D441526F7D4D2987AEDF48F0231:\
+0000008000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F5D9875A70158C9C64136703D231E3F5:\
+0000004000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3BC82EC5FBE24B5AAF230895BBA9DCD1:\
+0000002000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EFF062AF33726C788D261FBFDDA15109:\
+0000001000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E2A342E2683D3F970983D941656823AA:\
+0000000800000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E16066A35F943A426FE47AD1A1FC69AD:\
+0000000400000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D89F891B578FF6B441E97849DD2F2798:\
+0000000200000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4A800443B44112493226E08BD9521912:\
+0000000100000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2B504288F018B2A867597EB53EEA6DB1:\
+0000800000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B3FA8074A573A00B4897DF6CD0D99B5D:\
+0000400000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:38B56FD4C1FEDF5282208EF5F796A2C9:\
+0000200000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BFE421423C53A9942C78D04CB4B231D8:\
+0000100000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EF102196C479E513AE8B776D524631B9:\
+0000080000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AC38F8F6DF320D4409BA6A1CD93A482E:\
+0000040000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FB5D6CD1B6EE155D6744E5BE62A650F6:\
+0000020000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:23A626E559D0B8E4E4AB3F7C38750D4A:\
+0000010000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2CCA19AE45B976236D88E4E1AD3BACEA:\
+0080000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:052D166AA678A987C07256C582283986:\
+0040000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D30979DDC6C09B1158FA41EEB6F2A21B:\
+0020000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C36705BB2A9BAFCFCB64C4468964D568:\
+0010000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:97905460E140685960B561204ABC09A9:\
+0008000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B893B8766A12AAAD7691565C46651623:\
+0004000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7978DBD4794AF35DFB0403423B4E81A9:\
+0002000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4F990737145AAA9100BFEDCA53B69F6D:\
+0001000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A223AA1288463C0E2BE38EBD825616C0:\
+8000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EAE1D405570174DF7DF2F9966D509159:\
+4000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:65F37684471E921DC8A30F45B43C4499:\
+2000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0EE036D0BC32B89C1CEF987F5229E4A9:\
+1000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EC9D6557EED58E6CF89A746BBDB6C9B7:\
+0800000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AD2314BF713CD796E8C7EC6E9C59CB8D:\
+0400000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:33D8944A2D2FACBBA555EC18543AFCF0:\
+0200000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E0885D4460373469D1FA6C36A6E1C52F:\
+0100000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:4AE9A20B2B14A10290CBB820B7FFB510:\
+00000000000000000000000000000000
+
+00000000000000000000000000000040:2C6EE9F8F64B5B1B5587CDF17E84A791:\
+00000000000000000000000000000000
+
+00000000000000000000000000000020:29141D06A6B42CE22EFB8383CEAE325D:\
+00000000000000000000000000000000
+
+00000000000000000000000000000010:2AE6E19905D89A8E53A1DF26AD5C89B4:\
+00000000000000000000000000000000
+
+00000000000000000000000000000008:1587FF28ABDF9DF5A3F4DAF7405D273B:\
+00000000000000000000000000000000
+
+00000000000000000000000000000004:B598247AA82F5C79F9FF0E7EC61B83C4:\
+00000000000000000000000000000000
+
+00000000000000000000000000000002:0C5DABB01245E3A3544E291F3B0F250F:\
+00000000000000000000000000000000
+
+00000000000000000000000000000001:9BEDCEA16BDE863526A937208CBF0ABC:\
+00000000000000000000000000000000
+
+00000000000000000000000000008000:A174B66C47C53B2C34AA9F06FECBB7B2:\
+00000000000000000000000000000000
+
+00000000000000000000000000004000:333827335F88EBB93A0A7436E51398F0:\
+00000000000000000000000000000000
+
+00000000000000000000000000002000:03A7D7D70F4F50AE96835F12B73F79D3:\
+00000000000000000000000000000000
+
+00000000000000000000000000001000:B8B9F2029769952D9664A6FDE9706BBF:\
+00000000000000000000000000000000
+
+00000000000000000000000000000800:A7DCE248EC5A060388CA14598B986454:\
+00000000000000000000000000000000
+
+00000000000000000000000000000400:1A21EED739C6C39A56E0B4C6A17D3375:\
+00000000000000000000000000000000
+
+00000000000000000000000000000200:9073DBCF760A0B9E0E84A2FD6DF164F9:\
+00000000000000000000000000000000
+
+00000000000000000000000000000100:CEE83B85568AD8133D8842DC883052CE:\
+00000000000000000000000000000000
+
+00000000000000000000000000800000:151940BA15A175FCD39CE2D3A0259EFF:\
+00000000000000000000000000000000
+
+00000000000000000000000000400000:9F997F2AC950E52666207183DB935899:\
+00000000000000000000000000000000
+
+00000000000000000000000000200000:015B7DF6BFB9367BF8F690FC0B77DEB0:\
+00000000000000000000000000000000
+
+00000000000000000000000000100000:4A7D36598525699F49667AF4B46BB99B:\
+00000000000000000000000000000000
+
+00000000000000000000000000080000:306248FD603DFC18E41CF0864D2C352C:\
+00000000000000000000000000000000
+
+00000000000000000000000000040000:1367EC90627601E9C1BD1371454B772F:\
+00000000000000000000000000000000
+
+00000000000000000000000000020000:85FE597694444D1A8D7F1CE219913F4F:\
+00000000000000000000000000000000
+
+00000000000000000000000000010000:75BAF3E8194EA04577133509B50FF4C3:\
+00000000000000000000000000000000
+
+00000000000000000000000080000000:3EB8325BCA6C583DC04019F01D4BC90D:\
+00000000000000000000000000000000
+
+00000000000000000000000040000000:240A1E99A51C7EED2E9127DB7D86903E:\
+00000000000000000000000000000000
+
+00000000000000000000000020000000:81B2AF04CC40E2E3DDFFBE3F6AEF8A33:\
+00000000000000000000000000000000
+
+00000000000000000000000010000000:6970437809D0A34E5A76B22F88F5282B:\
+00000000000000000000000000000000
+
+00000000000000000000000008000000:C12E44B3F253295CF742441FFA2712DB:\
+00000000000000000000000000000000
+
+00000000000000000000000004000000:98E2FBF128A1E2F80CABF2DB3F9E62AF:\
+00000000000000000000000000000000
+
+00000000000000000000000002000000:3F2B1D74B9D0D84C0B0DDAD31352E67A:\
+00000000000000000000000000000000
+
+00000000000000000000000001000000:E51D907B84D877250D0BCEC17D292DFD:\
+00000000000000000000000000000000
+
+00000000000000000000008000000000:19E6063C7529E5268E4A45703AFC8AC4:\
+00000000000000000000000000000000
+
+00000000000000000000004000000000:6DDCBD01AC098B04AAA084D4C579DAC9:\
+00000000000000000000000000000000
+
+00000000000000000000002000000000:AFC268DB7CD2A453EA87BA6A0E923DEC:\
+00000000000000000000000000000000
+
+00000000000000000000001000000000:24B199E30672EF17362468CC8C0F4E46:\
+00000000000000000000000000000000
+
+00000000000000000000000800000000:B30C571F161EF0DAC78816A4DC1339FF:\
+00000000000000000000000000000000
+
+00000000000000000000000400000000:214CB9151303EDA5CD14E35E701DE887:\
+00000000000000000000000000000000
+
+00000000000000000000000200000000:57A991425DC55325EB159A0274140EFA:\
+00000000000000000000000000000000
+
+00000000000000000000000100000000:856CD3630F436DACD3FE27AB73F4A956:\
+00000000000000000000000000000000
+
+00000000000000000000800000000000:E5D5DC0D6834E44697BDD5D8427A054F:\
+00000000000000000000000000000000
+
+00000000000000000000400000000000:CAB879F5684241583F4900B2653D76C9:\
+00000000000000000000000000000000
+
+00000000000000000000200000000000:43FE63C8C08E0CE5D1DAB79348F1B64E:\
+00000000000000000000000000000000
+
+00000000000000000000100000000000:1D7850062F3F8B2415F22BC4D95A1367:\
+00000000000000000000000000000000
+
+00000000000000000000080000000000:45D486C0AC551C76AA17E356404726F2:\
+00000000000000000000000000000000
+
+00000000000000000000040000000000:900FEDE23DBB68E48BA9D9806E606F19:\
+00000000000000000000000000000000
+
+00000000000000000000020000000000:F573C581080C5654A6C426DD8971E68B:\
+00000000000000000000000000000000
+
+00000000000000000000010000000000:07AF806C0B6ECF9DD508C0D108572C37:\
+00000000000000000000000000000000
+
+00000000000000000080000000000000:8C30672FF7F1DB4681BA36E48B3374A3:\
+00000000000000000000000000000000
+
+00000000000000000040000000000000:0D56FA9193C8A6FBF653D75D3F61407E:\
+00000000000000000000000000000000
+
+00000000000000000020000000000000:08C0C170A7B0F0C07E1CDEF95AEE8113:\
+00000000000000000000000000000000
+
+00000000000000000010000000000000:F05F7E94EC7FECF973EF5732B565E016:\
+00000000000000000000000000000000
+
+00000000000000000008000000000000:EB667F97B9D94B0C41C873C4B56B334C:\
+00000000000000000000000000000000
+
+00000000000000000004000000000000:A065550C6371DEC580E16276E03F13D4:\
+00000000000000000000000000000000
+
+00000000000000000002000000000000:CDAC7C0A0E363FE8BA16BC11D1F6DC57:\
+00000000000000000000000000000000
+
+00000000000000000001000000000000:FF792A72BF23CABD13EA587C57D05D3F:\
+00000000000000000000000000000000
+
+00000000000000008000000000000000:986EFA59113F5C8A66BBAA7EF978A125:\
+00000000000000000000000000000000
+
+00000000000000004000000000000000:B8CB15A238CA60157C3CB3317021B92C:\
+00000000000000000000000000000000
+
+00000000000000002000000000000000:F262212AC5485BA7D92CBF5A9C58D8AD:\
+00000000000000000000000000000000
+
+00000000000000001000000000000000:DF54C6D917675E73A3659560D5813E56:\
+00000000000000000000000000000000
+
+00000000000000000800000000000000:925D0E759AF1EB36CEEB0FB6D51FAB7A:\
+00000000000000000000000000000000
+
+00000000000000000400000000000000:99BC9E5870190269C4FE5B6FC23C8D8C:\
+00000000000000000000000000000000
+
+00000000000000000200000000000000:C0380B9660722514C1EA4322FE45955C:\
+00000000000000000000000000000000
+
+00000000000000000100000000000000:66521E5F953F2D2E237A259BDEE9C400:\
+00000000000000000000000000000000
+
+00000000000000800000000000000000:1EB43E99040A614F77361601A1806651:\
+00000000000000000000000000000000
+
+00000000000000400000000000000000:A11495F4358A5FA63024A2DC02E20480:\
+00000000000000000000000000000000
+
+00000000000000200000000000000000:CF4D5EAD4E69313709EA9399F5ABF8D9:\
+00000000000000000000000000000000
+
+00000000000000100000000000000000:6CAC3A5E20E13162FB3A31804CB6C7AE:\
+00000000000000000000000000000000
+
+00000000000000080000000000000000:BFEE053ED49F33F5A388359721FE20FA:\
+00000000000000000000000000000000
+
+00000000000000040000000000000000:B2FFBF55E5E2E0CB0935504430E173F8:\
+00000000000000000000000000000000
+
+00000000000000020000000000000000:E521E33E82289A176467E24CBAD5D92C:\
+00000000000000000000000000000000
+
+00000000000000010000000000000000:9609C701F895754A623D3BF3EAC48334:\
+00000000000000000000000000000000
+
+00000000000080000000000000000000:C80F1E35ED81AC45835129665CA5C0B5:\
+00000000000000000000000000000000
+
+00000000000040000000000000000000:27FE1A77E6BF18887DBF7D48FC1EAB65:\
+00000000000000000000000000000000
+
+00000000000020000000000000000000:8E2444DDF34F5320A150471E01AC2F85:\
+00000000000000000000000000000000
+
+00000000000010000000000000000000:9CB3B00CA62767D7A1D45AF44D74957F:\
+00000000000000000000000000000000
+
+00000000000008000000000000000000:A07252FB0F05EA2264F558BDDF162BBB:\
+00000000000000000000000000000000
+
+00000000000004000000000000000000:4CCD47A10722175D4018709698E52881:\
+00000000000000000000000000000000
+
+00000000000002000000000000000000:F9DED80456581D2E6F09BDB09B77C04A:\
+00000000000000000000000000000000
+
+00000000000001000000000000000000:DCA8A545689A58F663B0B7A540F41E24:\
+00000000000000000000000000000000
+
+00000000008000000000000000000000:6801BAF0FBAF3352F3950F0940173352:\
+00000000000000000000000000000000
+
+00000000004000000000000000000000:B969F1B6F56E885025F12E58F87B4099:\
+00000000000000000000000000000000
+
+00000000002000000000000000000000:AA9F1568B6D0F5AFAC34847E0D7152B2:\
+00000000000000000000000000000000
+
+00000000001000000000000000000000:A96B20E51FCB48A0C58306086094154B:\
+00000000000000000000000000000000
+
+00000000000800000000000000000000:C9F389C56576B8C74A687BC5AAB8D503:\
+00000000000000000000000000000000
+
+00000000000400000000000000000000:3FB63882764779902321A2E594275C6B:\
+00000000000000000000000000000000
+
+00000000000200000000000000000000:160C3C22EF0B0D3E4F2FDC914138C229:\
+00000000000000000000000000000000
+
+00000000000100000000000000000000:265AC0BE8E47750E7CA22BAF01153B4D:\
+00000000000000000000000000000000
+
+00000000800000000000000000000000:C1842F4CA2DDC78E55CD91E07AD23A12:\
+00000000000000000000000000000000
+
+00000000400000000000000000000000:E47D5889218FF4CE45EA249EDC9B71C7:\
+00000000000000000000000000000000
+
+00000000200000000000000000000000:FB7566732AB52FE99454CFB07A0F1F0A:\
+00000000000000000000000000000000
+
+00000000100000000000000000000000:5FBF0927A8B293A04024B187AB1BF6C1:\
+00000000000000000000000000000000
+
+00000000080000000000000000000000:CFFBC514515878E10E07556988D8E721:\
+00000000000000000000000000000000
+
+00000000040000000000000000000000:CD3EEEBA162879FF20ABD158C236E3F3:\
+00000000000000000000000000000000
+
+00000000020000000000000000000000:F96D1082131DAE899EBD32CC562F0BB9:\
+00000000000000000000000000000000
+
+00000000010000000000000000000000:BDB475694748128D9959141682174CAF:\
+00000000000000000000000000000000
+
+00000080000000000000000000000000:A5E0C2E39B9821F2CD42875B0EC0A65E:\
+00000000000000000000000000000000
+
+00000040000000000000000000000000:A1397FFDA7C2A4E9A60E0AB48947B933:\
+00000000000000000000000000000000
+
+00000020000000000000000000000000:F20B001C13A0F857FB89C64FFF4CDA83:\
+00000000000000000000000000000000
+
+00000010000000000000000000000000:F38EE20A32B15A5B9129B67BA1FF3125:\
+00000000000000000000000000000000
+
+00000008000000000000000000000000:41ED367E96E013C651AF3FAEA764FE40:\
+00000000000000000000000000000000
+
+00000004000000000000000000000000:55C30FBD291D89E50A9DADCB48E52296:\
+00000000000000000000000000000000
+
+00000002000000000000000000000000:3FE7F1A404C0E4395FCC985F369735D4:\
+00000000000000000000000000000000
+
+00000001000000000000000000000000:6E131502B6A4F30B56AA52EB67989809:\
+00000000000000000000000000000000
+
+00008000000000000000000000000000:3EA36D91871DFF568FBE623DC31EBCE5:\
+00000000000000000000000000000000
+
+00004000000000000000000000000000:7C6DF10118A3AB6545A504790543C89E:\
+00000000000000000000000000000000
+
+00002000000000000000000000000000:1DFF6937399E060342348C34E88B5985:\
+00000000000000000000000000000000
+
+00001000000000000000000000000000:87DCE0F133442B7D4FAF7082F5489407:\
+00000000000000000000000000000000
+
+00000800000000000000000000000000:CBEF868AE34C80C542766358534A148B:\
+00000000000000000000000000000000
+
+00000400000000000000000000000000:DF23BC0E0C0B7F502E0210AF8B353165:\
+00000000000000000000000000000000
+
+00000200000000000000000000000000:E9732D7A112DE03068EC10D10AF8D972:\
+00000000000000000000000000000000
+
+00000100000000000000000000000000:1D17312BE6675B0797C5175DDCC1DE7E:\
+00000000000000000000000000000000
+
+00800000000000000000000000000000:0DB0D17349C89E090C845CBEF963F225:\
+00000000000000000000000000000000
+
+00400000000000000000000000000000:C7128FD1A5EF5202550873EA885551C5:\
+00000000000000000000000000000000
+
+00200000000000000000000000000000:761D7F9855C95AB6148833503958F96E:\
+00000000000000000000000000000000
+
+00100000000000000000000000000000:1D406059F0E1030FA66C52A46751D092:\
+00000000000000000000000000000000
+
+00080000000000000000000000000000:DE2FCC081DF9B136EC62922351E18D94:\
+00000000000000000000000000000000
+
+00040000000000000000000000000000:5F93FBFB11A527DFDFB5E4713E431E34:\
+00000000000000000000000000000000
+
+00020000000000000000000000000000:6C2C4F22E738C56B5246971540E5E3A1:\
+00000000000000000000000000000000
+
+00010000000000000000000000000000:BFF82E042A92224FBD3D41C22D07B610:\
+00000000000000000000000000000000
+
+80000000000000000000000000000000:A3B35DE7C358DDD82644678C64B8BCBB:\
+00000000000000000000000000000000
+
+40000000000000000000000000000000:04ABCFE4E0AF27FF92A2BB10949D7DD2:\
+00000000000000000000000000000000
+
+20000000000000000000000000000000:8F773194B78EF2B2740237EF12D08608:\
+00000000000000000000000000000000
+
+10000000000000000000000000000000:8B1EA69EE8D7C8D95B1DE4A670EC6997:\
+00000000000000000000000000000000
+
+08000000000000000000000000000000:CEE3C6CE66A7AC0C1767923B263B2EBD:\
+00000000000000000000000000000000
+
+04000000000000000000000000000000:88DE61FFC3AD277687626D5F7705DEF3:\
+00000000000000000000000000000000
+
+02000000000000000000000000000000:69DD947EFADCD15A06A0D79E078B35AE:\
+00000000000000000000000000000000
+
+01000000000000000000000000000000:32F1FA100E43561146DCA08D15B90636:\
+00000000000000000000000000000000
+
+00000000000000000000000000000080:D9D076F0512B4F29E15752A21B270BB1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:9668F388DD4F122A4D9DD8D6B8A322D5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:D3F12A67FABEC165545D25F5E5FEAE6F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:97580203AACE7E6F0DEB71BC631D9E40:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:E11B01524EA1F465A2A20043EB9F7E8A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:9BAC7EE501F03D6DEBE0F9EE68FBB3C1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:444E6201556F1C9D73299183B7ABCA9D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:497EA15A5AAB3CB115C3E0091C2E4047:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:A306CFDAFE5C8C2A955956BB61FFE5CD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:4815634545F268ED3BF50021AC0265B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:3B075AFF8F75956DC4BE7D5121BF07B6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:8EAA16AEA0535498D21245BAE97ED0D4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:AFFA71EA9A2F6C4A018CF2F5F22B9B13:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:93B8DD3F9A59DD9231B0885601A2354C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:EE23DB4E914D12A53BE8428161F3DE24:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:E76E230F4BA91426325C16FA168CA44B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:14148C222620E009AC51EE2321641D25:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:319D430B55E2A2C942B089755D4C6035:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:774D83990DCBAF6B9186DF250DC721A9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:81CA67898765727FFDEDBC7DC25EC8FF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:BEFC19FD8A41103B6892AD4A3CB08122:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:CC2DE08FA80BE8A13C8860174AF9F55D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:4935E35A180FEC382D3DCFD5ED572AFB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:D78FE49AB8E11EBA118687045D04A70F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:5DA9109BC3193E5D2ABA0CA577CBBCD4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:BC46C6FE8F7E549CCC402FC4633C670C:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:60A11AFFABBEE4D5D5564A74C7F94C91:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:84DD300A8FDE4AC126F41EA0692F3E07:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:3734062F8FCF37FBD1C48B5AAEF00C5F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:EA4491C7F5A9D671DA358C535965E1C3:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:D46899CC964A2A082C80AB7E0A4B153A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:45A5744C068AC6C7BC028C4D40885F20:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:4FF5F65E2089279F1FFF7BF06EC6D527:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:B0C818F70672EF5E6F20515214DDDF7A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:2A4D0F00CA19EDCEEF86D7F283221A97:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:F9E6A04D60D5C06994E196EEF788ED59:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:602BE82E95A1BEF5C2742099A6CB70D9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:B53F1354FE1291679B6D418AC4A3E26D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:0F68F7C1FFB5FA997D8CC007CF4F5BA8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:3B90014CDF2D614A339B48A6F374D1C4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:3D8075B415AC9DEB6008B51597CE28F4:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:675A3322BCCCF4D78F3376ECC2C8A415:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:B8CD6C76DAD863B3A2342265A42C7878:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:E0F6B38346E3E0AE2C5763C25C01ACB9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:96E295724B3F296016A3F6853B679079:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:305E7A77DC3B62F110688AB334002132:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:324E96A82CE897DAB3850047C38E9B18:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:23EB8F12867D39E24E5A71606E3B5C1E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:EC74DC99FDB377E35EBA6E5C920C9E20:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:12F92E9FF675FFE132FEC127A61ED1D6:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:F8BFC6819A8F1683DD314AFEDAA80F33:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:28552459A3EB05AE69463C26F6413B73:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:E018CED8C1FC6FE1849E945550602D46:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:8A46B1349AE83730266EBFB1D62BA1EB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:AEA0972033ACDA2FE228A3619511B0CF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:6BCD123081CB4DA2197A9204947C4765:\
+000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:1CA839C433F49B9CAC257C7CBE38C571:\
+000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:E6D1727A0BC893BBE5A048B73296FF43:\
+000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:6B38158548081550B6931773C3348995:\
+000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:4159191656BAE5F059625051F329E674:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:5684B43817E24580EE373B54B57126C1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:D31DC022A55A6CB7116D5AA79713EBEF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:B9B7F96A83494D61C0D476E15CF9FC40:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:9F61E523005A37B71A589C35E2320580:\
+000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:2F19CFB18D4B538C688FF0FF73EEF402:\
+000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:2B2D1598BD1A57A6277D0F1182423E70:\
+000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:FB589E7803F8DEC257644DD8968B3BF9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:4E8F6CD48030ABFB6BFAA8C79DF29132:\
+000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:594C7334C5C77F1F311743DBF880A848:\
+000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:8B9060A226A976B4D8701B61A0E16E05:\
+000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:9D5D7F82A45E543A28769767F0B4220B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:7F60DD3212B5FD34A33E95B7CD3C98B4:\
+000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:67A133B6981D6CFFFB0894B5CD60C384:\
+000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:B9724EFA90EE77242862C6D107053799:\
+000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:6CC4B4806D82C681027375553BEEF871:\
+000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:D05EA01E7AE0768FFE5B499D4A0EA833:\
+000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:EB5259D268854E583B02C445F0DBB33D:\
+000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:273792A497CBE6058FB8CE518C05A9A7:\
+000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:629EE820F46138558FE7AA6D547F971E:\
+000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:F04FF6EC27F7412350CA62E6A3BE479F:\
+000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:CAF26B388D8A81C408FC3506CA523C72:\
+000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:79A075A5778E5BED4F0663FC86D92A56:\
+000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:90E59EE9F97DE1590D4C454169890932:\
+000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:30DF4AFE05F0D0EC4495C4A7A3D3A1AF:\
+000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:BF6D54D156EDE791A177F8A5BA5DC1D0:\
+000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:2C2286B2537AFDF52A7EF59D620E7E46:\
+000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:545F83ECF5366475A1867BF81DE59780:\
+000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:5E7648E3575B7A02BEA8C69A19ED06BC:\
+000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:99B0CC109580893A14B960F78C867DF7:\
+000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:4FBCBA60C491EFA9C5B8B8CC9471C26A:\
+000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:7A3B3E4FA8DF6DD964161EF9ADB7EC90:\
+000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:DBA5DD3EE2B0F03D402D5BADAE4E34C9:\
+000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:2334F78508F6259862FAA5842E6B1E7B:\
+000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:F15ED8B81B74BD35586E1594AB3B0F73:\
+000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:A654EE4634624A3593DCC272C0AB8566:\
+000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:E71506E96ADACE02580EA035601850C3:\
+000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:00D43BE69B9387B28A4234D2E5BEF038:\
+000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:BB828D0A587EA543A78A60B6F63CC159:\
+000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:427338CBFA6B652CDCE9C30F29F6E660:\
+000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:D26286844B1BE4D73B44B77A2C4449DD:\
+000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:28D9BEB7444B7801C510D74C90F3183A:\
+000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:9D8949E7F531F30FFD1C6891154FFB8A:\
+000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:B329A557C9BFED767B44CA25F43C0924:\
+000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:1909B5B407CB28E7050F8889104B73F5:\
+000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:DA51B1E831305D9E6AC7F0CDF49F3AE5:\
+000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:4A091855C4AA2436F3C61A11FA4B9DA5:\
+000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:DB8350915843684F18B4B358579A9446:\
+000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:13A1376760534FF5F7D5ED1B62D93D4B:\
+000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:C2613B1D8937C2B1C9D7B0249D938E95:\
+000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:3FB48878619B70DB717F410550B03069:\
+000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:0589BD5D8ECDAAE7ECABC8816EF3C7EB:\
+000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:5AC9C030789D810698AAB706BA6BCCA8:\
+000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:4BD66B7E897E76BF51F1F00671092169:\
+000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:4A72C588A0FA490D521640D1F245E4BC:\
+000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:32205DCCC1D7A129B934C6FABAADEB1C:\
+000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:74F79A4CF6F99359D7EC47DA87104658:\
+000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:2810428BA5177BB0D91C11683008E68D:\
+000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:3863C205AED373BB3EF9E6D85D0AD08F:\
+000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:DD207AA0894DFBEDD7D9802823C04D7B:\
+000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:A6EAC9ECAAE9CC8621198BA547E9B74F:\
+000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:23F5F432AD687E0D4574C16459618ABB:\
+000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:56CD894936F6E9A4A4304CAE06F97CE3:\
+000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:B604D94F461AF9F4771BC53F8E3C227B:\
+000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:BB852AC4756880630D6D63951D3D2602:\
+000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:319C206CD98D2C98993FC2CDAAB3259C:\
+000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:D271595956451E3B7D957A3485ADE9F7:\
+000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:D4257D927C7F2A6390DF198B573DD1BA:\
+000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:7610F6DBE8F3F19682DCC01AF57DCD79:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:2055DEA7C84B008C6FAEB4B192795ADA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:CB98F1C490F33B4F7A3D3E821B3551F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:BB654CB6528C21D78E5CB79D5DA677A4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:E0B2836175A6808D61FEA4CB529401F8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:824C5F6FECE3E0FC4293821B987B3BD4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:9D9286D5E97CCDEC47E03CB12C34B339:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:BC2C09F0B3FC63CE17F1BE7F267E3E0A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:AD86DE83231C3203A86AE33B721EAA9F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:AE042A69C879D524DC4BCC70B84B1B37:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:6D03E3381991EDC800513D30BE07DE5A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:576807DCB0F1A8D73904DBAA84BE818E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:96DD8A88157832B7E45C639C25170333:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:9C1A7B580B29888F397743E76C4E7A39:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:B77FE10336DA7531E1BF2DC41C7E6E95:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:8658E3A6DBAC89EBA6E045881B172E9C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:D2FE26FC85AA40C3C6827B0DFF96AB0C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:56C2530D97A43944BE7874E6FA9121FD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:AAECA9394EF359D851CC9F244D4D1E54:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:71BC0D1DEA15FE3BC4AA6DD829C8E957:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:267FCBA295A670CB9EC18AFBB819CE91:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:D18CC92248E209FF8C9AF4AC93588727:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:63E94B466C955B7204285E418A156B29:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:368A8D2610A773A477B924028DAD455F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:B210E51F2C154205DA4A1D1B892DCC63:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:FFE1B843D7DC5F52852705221ED5EECA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:0E8B9ACE62AA90B258D8090EF2188BC4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:96961DBEC1C476AE00972E54DE621F19:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:A31A56562516BDAE02215CD5F0DF0569:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:A2316B6B9E6AD55D7013A24BDB1EAEB9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:709F715313E17EFB3ECAE3A5D9ED94AF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:BCA04C7CAB888EE6950B7696F5899502:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:6655B0542BE057664DE9B2733CA0E555:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:7407623C54E38D13B48B84306DD8F244:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:B3D6DC13CF612951F9ACB05EAEEDE7E3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:301378F0D3D30AE6613A9E7CF113821F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:9F227635FDAB7D31A7E1F08BBCC34371:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:F08620D46001C366FD6DCBEBC806C182:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:CF51A2A45F9CBFDE788D108B1B4D33A5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:3E70F946FB77C6841D9F001104347659:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:A3EB98B3BE360FAE3B8EC43D5B77FF7C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:4F6E01D8A2437547B50E070498BCD4F9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:4F80F4048084E1150AA6A36A6BB3D7EA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:311471549CCBB1EC27BAA384EC32F30F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:3C4DA8FF90590FB9FC529580DD40E7EF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:60AE8E3F60A099EEF38EFF4ED27DE3EC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:B33C4D6DF1259C4E5799D19B375420EA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:4D1BA08EB1E30F2A3B3E5D1DAE9792A9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:3CF54D30E493CDD7439E1F34FBB098F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:F8958250D6D6772B20051E36666906BD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:B4ED85D72C04A357958D7045BE13C4FF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:294A16831BF660536203030B59DA20F3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:D189C5A12722ABFEBA16F155975068E6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:9A9248C1FEDF207CE64F68E73B22A77C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:CC668772F50D2ED7DF83FF85A0D76576:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:685CA45E48D087563E1886DBDD63342F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:FCE8BFBA1BB12F4990C6DF32C6D71EBD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:645D7562E523058E7708FF03F1712BE8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:FA9CAF3BBC2D52806EF9B3D01F5B8398:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:0D2638505AAE1A5532D74C4F45C136D3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:9721099476B1F963EF87DD29E82227F8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:237AE2CDD5D2819EDAE0947AFB9D040F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:8FA78734E057E8A9486862E00A9886D8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:983F654090C661264BE8F921063B7DE5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:645F0F938A2898A3869190A1D99A3078:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:4DDBA0F24964591307AB909009BB41EF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:5D9333754035534CEF4EEFA73EA3F8C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:F51234B609D397B1D6DA8BB625C0993C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:0AF5205E41F184D0989A78BF149DB675:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:0EBC3926D924F37BFD716F404CA8450D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:53CADA57C7855AEB96B48F8C85915DE9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:FD8E2C7604621D13E64B58315DCC65CD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:A7126988773129D5F6CC330C1A0EF30B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:72C791409F94CE23F4CD61D714670B39:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:6AD3CCBC31E2ECF88C6B54F84E638AA2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:9FE143250D00E25696B01E0A2ED05DB3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:3ABBF724E6C7B2D05D93A2C6D058E5AC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:59300BA5323CF6D84A9FF12B042A5AFF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:4AE9F03EF61BAA670CE46F3A6C205BD5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:E33261C4E54AB7B117C3ABA1C9E11C1E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:B84E741AC92A42F37A77F05D6F464E10:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:0F6D2E73CF929A92BADF0A372FFB31A5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:2002487C2CFE5A223E3A3C19A6B23670:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:A9E22B14D403C7F0FA9D95C064CBA9D3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:CFD3A8EE62F68692A8917C814290E979:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:AECA2C8C0CA8B6F0EF594A13C85E83CF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:E74D77BB281F542A0A78C3D8436783F4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:B81755986C8B60A935F5D9169A2A7655:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:DE964C9FF34F5A79FF43C6AB148DC395:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:0F7CE54A338AB05E2C38F1725DA8B127:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:CAD8158D26EED67D4355BB66D0812ADE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:5332616A057A657FD2FD6562AF33EFC9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:308CD48EC851D7C1251174228B943B11:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:29A5D9977C881DB067136B755BB68E54:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:C0F6B4881776765507CF91DB0A32C70F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:47E518209CB5533F9A7EE02C4F07391B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:58D7E0D60E315EEBA97F0DFA2D7307B0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:C02ED6499331AF8C6CF30A63BB5E89CA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:B5F166B94EC31A17662E24757FBB3FC5:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:17D20FBDA96D4AD0D99DAE64DE5F317B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:320FA060BBB901F66A9E4CFF221E6A4A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:3A259B7AEE3155C0C4DF7A32EF40FB19:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:028EFD3B6E686C87B402151F414B13AD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:D4F61CC61FA1DBD68B8C48541AE77289:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:DFCCE96C8C244586A3BCF098306C6374:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:BD5426FFD3CC9FC735EBAB7C72FD2D9B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:EA3C7C9B02AE7297B4BE551C8C551440:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:11BB660CF8431F2625AB9EF603975BB7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:B666AA7C5BA5209CBCEDE07EB66064D3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:CAD843E927DDE8F92DBBB33C1B4E87F9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:ED29F7805804E2E95F664B2E36C20A67:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:980F61BF6EBDE1A30607A1D51FFFB8D6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:E47A19E8579807B5C44AC62619372673:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:2B451B22A3EBAB1C7A7619551DDF149F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:3ABE3CAEDA54E5583269803BE04CBB2C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:DF581405DFBDEFACB35AD3BC510FE895:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:45B3C3DAC439F884447567B282DE329C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:4192DE2B562CDD43EC4358EA730250C3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:27E310D8032E16CF970F635C517E7D2E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:573CAE2A23968DE1D40036C24F9FEFA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:B4AD06B55E31DE8F1F77C2B7AE8B73FD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:8314675E8AD5C3ECD83D852BCF7F566E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:893BF67B1A845579C8FADC05BFDC0894:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:302F8325DEB1E1A0955D6273368A0DC4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:917B2F6A11DDDCEB53FEA01E194A6CC9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:8229E6539268BB39F3218E2903110C4F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:935A7835E2FAF9F7F20CE85662EE281F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:DF5E38BE0362C35E8AF472C6327987DA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:07E5E5AD7097B849BADC2D5D803B7F6A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+
+
+# Corrected test vectors, based on NIST's clarification of May 9, 2002
+[Skipjack]
+AABBCCDD00112233:00D3127AE2CA8725:11223344556677889900
+CE365D5D21C1A4CB:C00891C551C5E168:9C5F3F996E59C9543249
+CB758E2851482982:6C09A2825D32B67E:21A07C1CED3C2C0C1576
+7B402EA5E4B7A7C3:C6E32EA485F38324:F62D87056348C5D64071
+3AE159B52AE3FD1B:8AD85F68B89DFAD6:0E2B3B9AEEF001392C3C
+3828786C48F705D2:9352B87091483003:51BAA0E8AADF4B8B6A60
+E060FCC7F7F16FD9:8C70B2C901339B1F:CE70B79AE70F7AA44778
+8F5FA719DE4B1D24:958816FE7FC5862B:91A8919EC9360CABB973
+0B55FD902BFECC99:CA7F517B383DA760:FB9F7F8B62E4996E49E7
+CA7F517B383DA760:278B665DB00CC924:FB9F7F8B62E4996E49E7
+6527AF09D0B01CB7:628A8AE67A87F464:90DDF1550EC7DCF4CAE5
+628A8AE67A87F464:CD01A638A878E7FE:90DDF1550EC7DCF4CAE5
+E7951155B748D347:EAEB4A1470307BF1:3516DABCD760F2BEE4CD
+AD14EBC6D0261D94:8DAE0E5E2CD055A0:C9C5DAF7DFD17D902270
+9B0C81EDA6853253:DC354CB74F2FC2B4:EEEE6892DCD1ED868F56
+C76443A5B0652306:160DF886878D6908:03604B2D0D06A9AA9D68
+37F1C930714AA1CF:39DDEC7C8B84DBD6:6E8494476C89110F166C
+1E71CDF5AB39DF1D:AE316B4C32222DC9:DF3A10F722776402DAF8
+9EE6838FCE6C6CDD:FF7F52D9C17728E3:E4EE21889437C10A7682
+111AA47F17CFAABE:1A86B8753F784547:C3C55FCACDD387163C84
+0AC61B6C219FC0C4:727AA5B83616105C:E5F795A933FFD70C87AE
+56582400B014F8D3:918F72548E0FFCB4:9163BD738BEA13D9CB5C
+9C323238D9C76E35:F801578F6050B793:C70CA4689C59CD745EF6
+6CD57A531CCF9E20:619E091055D423D8:DC934E7C08D7466E10AA
+667DE1649DEA2E89:5FD975B231E25909:EA4FC33C0CA289973FA9
+1BC90F76FD901399:AE676788090270E7:9988881616D6CB63B188
+9E9CCADD47C9EBDA:22A3D66BA549CCE7:10DF61754870FFD16CFB
+2E8FCDE2EFDD1964:FD42E226CF058AE4:2C005FEFE7C4C01ADC5E
+128106BDEC982932:C1F24DB137E5C062:6A49942FA39AC190308E
+CC93DA20EE2AAE3A:714D626B8AE5D154:92903F26A46FD43F6EB9
+
+[Square]
+00000000000000000000000000000000:3C00428F8ABBC0B84F057CC19C26F8CF:\
+00000000000000000000000000000000
+000102030405060708090A0B0C0D0E0F:7C3491D94994E70F0EC2E7A5CCB5A14F:\
+000102030405060708090A0B0C0D0E0F
+C76C696289898137077A4A59FAEEEA4D:88C6FF4B92604C6E66656B02DDAF9F40:\
+000102030405060708090A0B0C0D0E0F
+21A5DBEE154B8F6D6FF33B98F448E95A:3388801F66E7FCC0BCE522A23A4F0C7F:\
+915F4619BE41B2516355A50110A9CE91
+F7C013AC5B2B8952E5E554ABE9CED2D2:A1C0E9215141343DEC2B556942C92BDE:\
+783348E75AEB0F2FD7B169BB8DC16787
+2F42B3B70369FC929AE068313F343A7A:3FBE6811B998CDF3E50ABDE2F3C075E3:\
+DC49DB1375A5584F6485B413B5F12BAF
+65C178B284D197CCD3F111A282F17F29:D7B7209E0879744C782809B6D2E0B1B0:\
+5269F149D41BA0152497574D7F153125
+00000000000000000000000000000000:05F8AAFDEFB4F5F9C751E5B36C8A37D8:\
+80000000000000000000000000000000
+0F1E2D3C4B5A69788796A5B4C3D2E1F0:1660060085C0E241F88462BFFBE67602:\
+00000000000000000000040000000000
+0F1E2D3C4B5A69788796A5B4C3D2E1F0:92BFBBFCD2BBF54FFF06AF097893E9A3:\
+00000000000000000000000000000080
+00000000000000000000000000000000:98CFB10F3ED70BB82CC90597B463A1F6:\
+00000000000000000000000000020000
+00000000000000000000000000000000:A643A0CA5154A7D10B251D562D58EA53:\
+00000000000000000000000000800000
+
+[TEA]
+0000000000000000:41EA3A0A94BAA940:00000000000000000000000000000000
+7C944D08DEF34C0C:195C0E8F49761539:271AD15192C4D1204A4A2561E3DB6FF7
+B9682750BB15CAAD:2B5F318FB66806B9:F04EBF798C193F199C1F532AF383555B
+9706769A18A2D03D:8E17EEB5008DC0CB:200C0CE59717D5D9AF6813CD207FEE73
+EDB76C54847DA59E:DFA6C29BEB40F9AF:2828D51F98AE0B33F4DE2B7FBD18A529
+178A49BAFBA53F23:C3BBCE6715D90CE6:61AABA6BE48B0D0D14FE5D27FAB852A4
+DF4CDB61A5F38536:B4E6359C9D9458AA:2080E2409BA01C8532FC84403EE8C06A
+7C944D08DEF34C0C:195C0E8F49761539:271AD15192C4D1204A4A2561E3DB6FF7
+F4C76C1D47FE568F:551CA67C7756FF56:C1E297C0C761777D8A76FFF02D22B859
+CAB16583E15D0074:DE472175D55372C9:23C807A2EF0A551F858FD52D125A47D8
+97B05C60774164AD:BC4BD30CB50DA39B:9FA5D4D8CBDFCECD559E3CE88BF78EE1
+7017A263985B735C:E47FDF06A51D8C24:24F4E91083139099D663647A7FFAC321
+15475A90DF04CD29:4DF54282EAAFA235:7CF8626DE76D8462218ED5C9DC8ACC26
+87CA0AACCF146CC8:F7360F57CFCC09AC:3C6AD7DF17332A3E1E3DE06007387357
+9268AF048ECBAE67:E98E428A9D1FEE9C:24237A762D8A89383A2949F5A0F5EC08
+AF0062CD77A84EBD:44CD624B87CBEE77:209A2833A39472D9720380FFB2F74761
+F922CA875B991A31:1E92C0C51185F7C7:22EBE7A30E8855B3B453A6E926D4F187
+B4ECC305C3DBD8E5:063D8F75A7A77501:1B5E23EBD915C1FEE59F57DD91AF7347
+A4C2F6DC597D13EA:BF8FFEC7550A496B:6C21D105515290DA29339F142685C135
+3AF7F1AE0F58AB1D:BBA581D07E51D8D6:01F728A7433A47B13DE34FCC08958449
+791D8DA8CBB0BC94:7D9A4F0363B6085F:9A2D4C50337D3EC337673782FD385601
+ABCDEF0198765432:58C7BA625ED42820:112233445566778899AABBCCDDEEFF01
+AAAAAAAAAAAAAAAA:423251D460AEBE8E:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+6385ECC14C50C91F:D3A465910B0ECF46:88AD993684E3FE4C4D5DD8F1C0964D32
+99532D57CC7FC724:A846FE0F9A698E32:69F9181A726912C2DFD815081209F9F6
+A874F573DD7A8761:5055A546D119BFA7:79846B4ED899433C452EDED9D6925C7A
+CD58533F9F18C3F3:F5E649326A32F7BD:B0BB57B0E243DC91143DA8F235DCF9DB
+65B4628A8A4ACC33:E2FAC5AB9B301983:6CDF16B8E08604C93A4BC86E269BA2EF
+21244B2AA3071823:14F62A42C4BDA3E6:2203D8EFC29D3421981E0C2FAF90EA8C
+C6BBAD2319111D81:F4068832803914F7:86B435D9BF689FD450352308EDDA200A
+38CD92C3E6882185:A3C3CE70D4A097E8:279243E8F5759FD3D29EF824D65B163B
+56D1B5CB68ADBD3F:4E57696CAC39676C:95ADBC7D2F67A15C395605250AC1275F
+1936713432D87C16:3D3E59CA7EDED044:4E760AF9B46E2C9EF75B7F5721EAFD60
+A9AF22BFEA5639F1:D478E142344FCFAC:2C98241CD08DF0B269C8669E55F61227
+8DEC08977A7F6D02:23F4A36A9D475299:B28F6B02B950BC924B03C39C672A8216
+8535D9E669C2A7B8:30284672AF8877F1:F7A7B83FC8DF8868AB753F435B6E46DE
+03682AB977DDDCD9:9F678A05F82E9326:1BC9B0A578D89DAE5A47F5704640CA4A
+3A1A041F2F1B0FC7:A40CBAE926F0F13B:15C140E81E98AE10443AA43C89E5D52C
+
+[Twofish]
+00000000000000000000000000000000:9F589F5CF6122C32B6BFEC2F2AE8C35A:\
+00000000000000000000000000000000
+
+9F589F5CF6122C32B6BFEC2F2AE8C35A:D491DB16E7B1C39E86CB086B789F5419:\
+00000000000000000000000000000000
+
+D491DB16E7B1C39E86CB086B789F5419:019F9809DE1711858FAAC3A3BA20FBC3:\
+9F589F5CF6122C32B6BFEC2F2AE8C35A
+
+019F9809DE1711858FAAC3A3BA20FBC3:6363977DE839486297E661C6C9D668EB:\
+D491DB16E7B1C39E86CB086B789F5419
+
+6363977DE839486297E661C6C9D668EB:816D5BD0FAE35342BF2A7412C246F752:\
+019F9809DE1711858FAAC3A3BA20FBC3
+
+816D5BD0FAE35342BF2A7412C246F752:5449ECA008FF5921155F598AF4CED4D0:\
+6363977DE839486297E661C6C9D668EB
+
+5449ECA008FF5921155F598AF4CED4D0:6600522E97AEB3094ED5F92AFCBCDD10:\
+816D5BD0FAE35342BF2A7412C246F752
+
+6600522E97AEB3094ED5F92AFCBCDD10:34C8A5FB2D3D08A170D120AC6D26DBFA:\
+5449ECA008FF5921155F598AF4CED4D0
+
+34C8A5FB2D3D08A170D120AC6D26DBFA:28530B358C1B42EF277DE6D4407FC591:\
+6600522E97AEB3094ED5F92AFCBCDD10
+
+28530B358C1B42EF277DE6D4407FC591:8A8AB983310ED78C8C0ECDE030B8DCA4:\
+34C8A5FB2D3D08A170D120AC6D26DBFA
+
+8A8AB983310ED78C8C0ECDE030B8DCA4:48C758A6DFC1DD8B259FA165E1CE2B3C:\
+28530B358C1B42EF277DE6D4407FC591
+
+48C758A6DFC1DD8B259FA165E1CE2B3C:CE73C65C101680BBC251C5C16ABCF214:\
+8A8AB983310ED78C8C0ECDE030B8DCA4
+
+CE73C65C101680BBC251C5C16ABCF214:C7ABD74AA060F78B244E24C71342BA89:\
+48C758A6DFC1DD8B259FA165E1CE2B3C
+
+C7ABD74AA060F78B244E24C71342BA89:D0F8B3B6409EBCB666D29C916565ABFC:\
+CE73C65C101680BBC251C5C16ABCF214
+
+D0F8B3B6409EBCB666D29C916565ABFC:DD42662908070054544FE09DA4263130:\
+C7ABD74AA060F78B244E24C71342BA89
+
+DD42662908070054544FE09DA4263130:7007BACB42F7BF989CF30F78BC50EDCA:\
+D0F8B3B6409EBCB666D29C916565ABFC
+
+7007BACB42F7BF989CF30F78BC50EDCA:57B9A18EE97D90F435A16F69F0AC6F16:\
+DD42662908070054544FE09DA4263130
+
+57B9A18EE97D90F435A16F69F0AC6F16:06181F0D53267ABD8F3BB28455B198AD:\
+7007BACB42F7BF989CF30F78BC50EDCA
+
+06181F0D53267ABD8F3BB28455B198AD:81A12D8449E9040BAAE7196338D8C8F2:\
+57B9A18EE97D90F435A16F69F0AC6F16
+
+81A12D8449E9040BAAE7196338D8C8F2:BE422651C56F2622DA0201815A95A820:\
+06181F0D53267ABD8F3BB28455B198AD
+
+BE422651C56F2622DA0201815A95A820:113B19F2D778473990480CEE4DA238D1:\
+81A12D8449E9040BAAE7196338D8C8F2
+
+113B19F2D778473990480CEE4DA238D1:E6942E9A86E544CF3E3364F20BE011DF:\
+BE422651C56F2622DA0201815A95A820
+
+E6942E9A86E544CF3E3364F20BE011DF:87CDC6AA487BFD0EA70188257D9B3859:\
+113B19F2D778473990480CEE4DA238D1
+
+87CDC6AA487BFD0EA70188257D9B3859:D5E2701253DD75A11A4CFB243714BD14:\
+E6942E9A86E544CF3E3364F20BE011DF
+
+D5E2701253DD75A11A4CFB243714BD14:FD24812EEA107A9E6FAB8EABE0F0F48C:\
+87CDC6AA487BFD0EA70188257D9B3859
+
+FD24812EEA107A9E6FAB8EABE0F0F48C:DAFA84E31A297F372C3A807100CD783D:\
+D5E2701253DD75A11A4CFB243714BD14
+
+DAFA84E31A297F372C3A807100CD783D:A55ED2D955EC8950FC0CC93B76ACBF91:\
+FD24812EEA107A9E6FAB8EABE0F0F48C
+
+A55ED2D955EC8950FC0CC93B76ACBF91:2ABEA2A4BF27ABDC6B6F278993264744:\
+DAFA84E31A297F372C3A807100CD783D
+
+2ABEA2A4BF27ABDC6B6F278993264744:045383E219321D5A4435C0E491E7DE10:\
+A55ED2D955EC8950FC0CC93B76ACBF91
+
+045383E219321D5A4435C0E491E7DE10:7460A4CD4F312F32B1C7A94FA004E934:\
+2ABEA2A4BF27ABDC6B6F278993264744
+
+7460A4CD4F312F32B1C7A94FA004E934:6BBF9186D32C2C5895649D746566050A:\
+045383E219321D5A4435C0E491E7DE10
+
+6BBF9186D32C2C5895649D746566050A:CDBDD19ACF40B8AC0328C80054266068:\
+7460A4CD4F312F32B1C7A94FA004E934
+
+CDBDD19ACF40B8AC0328C80054266068:1D2836CAE4223EAB5066867A71B1A1C3:\
+6BBF9186D32C2C5895649D746566050A
+
+1D2836CAE4223EAB5066867A71B1A1C3:2D7F37121D0D2416D5E2767FF202061B:\
+CDBDD19ACF40B8AC0328C80054266068
+
+2D7F37121D0D2416D5E2767FF202061B:D70736D1ABC7427A121CC816CD66D7FF:\
+1D2836CAE4223EAB5066867A71B1A1C3
+
+D70736D1ABC7427A121CC816CD66D7FF:AC6CA71CBCBEDCC0EA849FB2E9377865:\
+2D7F37121D0D2416D5E2767FF202061B
+
+AC6CA71CBCBEDCC0EA849FB2E9377865:307265FF145CBBC7104B3E51C6C1D6B4:\
+D70736D1ABC7427A121CC816CD66D7FF
+
+307265FF145CBBC7104B3E51C6C1D6B4:934B7DB4B3544854DBCA81C4C5DE4EB1:\
+AC6CA71CBCBEDCC0EA849FB2E9377865
+
+934B7DB4B3544854DBCA81C4C5DE4EB1:18759824AD9823D5961F84377D7EAEBF:\
+307265FF145CBBC7104B3E51C6C1D6B4
+
+18759824AD9823D5961F84377D7EAEBF:DEDDAC6029B01574D9BABB099DC6CA6C:\
+934B7DB4B3544854DBCA81C4C5DE4EB1
+
+DEDDAC6029B01574D9BABB099DC6CA6C:5EA82EEA2244DED42CCA2F835D5615DF:\
+18759824AD9823D5961F84377D7EAEBF
+
+5EA82EEA2244DED42CCA2F835D5615DF:1E3853F7FFA57091771DD8CDEE9414DE:\
+DEDDAC6029B01574D9BABB099DC6CA6C
+
+1E3853F7FFA57091771DD8CDEE9414DE:5C2EBBF75D31F30B5EA26EAC8782D8D1:\
+5EA82EEA2244DED42CCA2F835D5615DF
+
+5C2EBBF75D31F30B5EA26EAC8782D8D1:3A3CFA1F13A136C94D76E5FA4A1109FF:\
+1E3853F7FFA57091771DD8CDEE9414DE
+
+3A3CFA1F13A136C94D76E5FA4A1109FF:91630CF96003B8032E695797E313A553:\
+5C2EBBF75D31F30B5EA26EAC8782D8D1
+
+91630CF96003B8032E695797E313A553:137A24CA47CD12BE818DF4D2F4355960:\
+3A3CFA1F13A136C94D76E5FA4A1109FF
+
+137A24CA47CD12BE818DF4D2F4355960:BCA724A54533C6987E14AA827952F921:\
+91630CF96003B8032E695797E313A553
+
+BCA724A54533C6987E14AA827952F921:6B459286F3FFD28D49F15B1581B08E42:\
+137A24CA47CD12BE818DF4D2F4355960
+
+6B459286F3FFD28D49F15B1581B08E42:5D9D4EEFFA9151575524F115815A12E0:\
+BCA724A54533C6987E14AA827952F921
+
+00000000000000000000000000000000:EFA71F788965BD4453F860178FC19101:\
+000000000000000000000000000000000000000000000000
+
+EFA71F788965BD4453F860178FC19101:88B2B2706B105E36B446BB6D731A1E88:\
+000000000000000000000000000000000000000000000000
+
+88B2B2706B105E36B446BB6D731A1E88:39DA69D6BA4997D585B6DC073CA341B2:\
+EFA71F788965BD4453F860178FC191010000000000000000
+
+39DA69D6BA4997D585B6DC073CA341B2:182B02D81497EA45F9DAACDC29193A65:\
+88B2B2706B105E36B446BB6D731A1E88EFA71F788965BD44
+
+182B02D81497EA45F9DAACDC29193A65:7AFF7A70CA2FF28AC31DD8AE5DAAAB63:\
+39DA69D6BA4997D585B6DC073CA341B288B2B2706B105E36
+
+7AFF7A70CA2FF28AC31DD8AE5DAAAB63:D1079B789F666649B6BD7D1629F1F77E:\
+182B02D81497EA45F9DAACDC29193A6539DA69D6BA4997D5
+
+D1079B789F666649B6BD7D1629F1F77E:3AF6F7CE5BD35EF18BEC6FA787AB506B:\
+7AFF7A70CA2FF28AC31DD8AE5DAAAB63182B02D81497EA45
+
+3AF6F7CE5BD35EF18BEC6FA787AB506B:AE8109BFDA85C1F2C5038B34ED691BFF:\
+D1079B789F666649B6BD7D1629F1F77E7AFF7A70CA2FF28A
+
+AE8109BFDA85C1F2C5038B34ED691BFF:893FD67B98C550073571BD631263FC78:\
+3AF6F7CE5BD35EF18BEC6FA787AB506BD1079B789F666649
+
+893FD67B98C550073571BD631263FC78:16434FC9C8841A63D58700B5578E8F67:\
+AE8109BFDA85C1F2C5038B34ED691BFF3AF6F7CE5BD35EF1
+
+16434FC9C8841A63D58700B5578E8F67:9594CF62D48ACD347A68A3161F0F3EE7:\
+893FD67B98C550073571BD631263FC78AE8109BFDA85C1F2
+
+9594CF62D48ACD347A68A3161F0F3EE7:B23E8C2C731C514017D1F2B88D77D208:\
+16434FC9C8841A63D58700B5578E8F67893FD67B98C55007
+
+B23E8C2C731C514017D1F2B88D77D208:93CC592BC96D95FA8AC32DA894F6AB89:\
+9594CF62D48ACD347A68A3161F0F3EE716434FC9C8841A63
+
+93CC592BC96D95FA8AC32DA894F6AB89:26516E6BD4AEF86AF4F4AD58FA41A14C:\
+B23E8C2C731C514017D1F2B88D77D2089594CF62D48ACD34
+
+26516E6BD4AEF86AF4F4AD58FA41A14C:00A8FFFAB8616BE710A6592438FC40BE:\
+93CC592BC96D95FA8AC32DA894F6AB89B23E8C2C731C5140
+
+00A8FFFAB8616BE710A6592438FC40BE:A19B811C77482D97C842EC62DB2EDCCE:\
+26516E6BD4AEF86AF4F4AD58FA41A14C93CC592BC96D95FA
+
+A19B811C77482D97C842EC62DB2EDCCE:D7FF438678D818CAA26A676342F98E8B:\
+00A8FFFAB8616BE710A6592438FC40BE26516E6BD4AEF86A
+
+D7FF438678D818CAA26A676342F98E8B:84EAFFC0C091582ABB717086E0807A5F:\
+A19B811C77482D97C842EC62DB2EDCCE00A8FFFAB8616BE7
+
+84EAFFC0C091582ABB717086E0807A5F:5500AF1C79503FEF1BACF35A81DC2865:\
+D7FF438678D818CAA26A676342F98E8BA19B811C77482D97
+
+5500AF1C79503FEF1BACF35A81DC2865:7282B2F3E766C83664930A19D201D7E7:\
+84EAFFC0C091582ABB717086E0807A5FD7FF438678D818CA
+
+7282B2F3E766C83664930A19D201D7E7:6796085C32FBDD2AB43E81EAC1262743:\
+5500AF1C79503FEF1BACF35A81DC286584EAFFC0C091582A
+
+6796085C32FBDD2AB43E81EAC1262743:5839F9E148B9FD2B5A52751D4F178FDC:\
+7282B2F3E766C83664930A19D201D7E75500AF1C79503FEF
+
+5839F9E148B9FD2B5A52751D4F178FDC:A88F34056742E55408A7A9E7B6D4C8C0:\
+6796085C32FBDD2AB43E81EAC12627437282B2F3E766C836
+
+A88F34056742E55408A7A9E7B6D4C8C0:9C8C304CB1F937C6E42528459FA8872F:\
+5839F9E148B9FD2B5A52751D4F178FDC6796085C32FBDD2A
+
+9C8C304CB1F937C6E42528459FA8872F:EA3668C0D96529A7F3BF0F7C2B5C5BE2:\
+A88F34056742E55408A7A9E7B6D4C8C05839F9E148B9FD2B
+
+EA3668C0D96529A7F3BF0F7C2B5C5BE2:A8FB6EEFCAAF9C4041072D570984CED2:\
+9C8C304CB1F937C6E42528459FA8872FA88F34056742E554
+
+A8FB6EEFCAAF9C4041072D570984CED2:ABF4662E5D50F71B15FE3B428AFE3500:\
+EA3668C0D96529A7F3BF0F7C2B5C5BE29C8C304CB1F937C6
+
+ABF4662E5D50F71B15FE3B428AFE3500:3B3AED23958DA6E2FA4493BCBE59A806:\
+A8FB6EEFCAAF9C4041072D570984CED2EA3668C0D96529A7
+
+3B3AED23958DA6E2FA4493BCBE59A806:CFBF446E33C3DCD4DD5161CA00D4BA8F:\
+ABF4662E5D50F71B15FE3B428AFE3500A8FB6EEFCAAF9C40
+
+CFBF446E33C3DCD4DD5161CA00D4BA8F:072ADBFA7EB962BA199AFC720339FF29:\
+3B3AED23958DA6E2FA4493BCBE59A806ABF4662E5D50F71B
+
+072ADBFA7EB962BA199AFC720339FF29:AAB346D9123A8140AC563EF17E7054C8:\
+CFBF446E33C3DCD4DD5161CA00D4BA8F3B3AED23958DA6E2
+
+AAB346D9123A8140AC563EF17E7054C8:3C7DDC5FE6E5888FE61DEDA0C69CD320:\
+072ADBFA7EB962BA199AFC720339FF29CFBF446E33C3DCD4
+
+3C7DDC5FE6E5888FE61DEDA0C69CD320:34AA645C7E3532098ADA91BB128ED821:\
+AAB346D9123A8140AC563EF17E7054C8072ADBFA7EB962BA
+
+34AA645C7E3532098ADA91BB128ED821:7A5D12E315038522DA01EC0834B1322C:\
+3C7DDC5FE6E5888FE61DEDA0C69CD320AAB346D9123A8140
+
+7A5D12E315038522DA01EC0834B1322C:86E235A1CB091FF7FE6FBBCA0D73BE58:\
+34AA645C7E3532098ADA91BB128ED8213C7DDC5FE6E5888F
+
+86E235A1CB091FF7FE6FBBCA0D73BE58:F3CE81CACE5D6BA9C558111DCDB22F5D:\
+7A5D12E315038522DA01EC0834B1322C34AA645C7E353209
+
+F3CE81CACE5D6BA9C558111DCDB22F5D:FB30A5D67D5F5BE4048C77E2AD3BC9D1:\
+86E235A1CB091FF7FE6FBBCA0D73BE587A5D12E315038522
+
+FB30A5D67D5F5BE4048C77E2AD3BC9D1:31E69DD3D2D90E81C9EBFAC257E9823D:\
+F3CE81CACE5D6BA9C558111DCDB22F5D86E235A1CB091FF7
+
+31E69DD3D2D90E81C9EBFAC257E9823D:87579B3F19A9CDE12BB882FFEAF665AE:\
+FB30A5D67D5F5BE4048C77E2AD3BC9D1F3CE81CACE5D6BA9
+
+87579B3F19A9CDE12BB882FFEAF665AE:24A8572AA844FEF25F7670FAE30F1CD2:\
+31E69DD3D2D90E81C9EBFAC257E9823DFB30A5D67D5F5BE4
+
+24A8572AA844FEF25F7670FAE30F1CD2:0CFA32E5E33F3B2DAC9F34D25979319A:\
+87579B3F19A9CDE12BB882FFEAF665AE31E69DD3D2D90E81
+
+0CFA32E5E33F3B2DAC9F34D25979319A:3C64D7FC881B9B82ABA21FF122B98F54:\
+24A8572AA844FEF25F7670FAE30F1CD287579B3F19A9CDE1
+
+3C64D7FC881B9B82ABA21FF122B98F54:A794CAEE6756281B7A64894E4E4F70A8:\
+0CFA32E5E33F3B2DAC9F34D25979319A24A8572AA844FEF2
+
+A794CAEE6756281B7A64894E4E4F70A8:89A9BF6B893BC5E6FEF4C77F3D0F29A6:\
+3C64D7FC881B9B82ABA21FF122B98F540CFA32E5E33F3B2D
+
+89A9BF6B893BC5E6FEF4C77F3D0F29A6:5DBE44032769DF543EAD7AD13A5F3310:\
+A794CAEE6756281B7A64894E4E4F70A83C64D7FC881B9B82
+
+5DBE44032769DF543EAD7AD13A5F3310:DEA4F3DA75EC7A8EAC3861A9912402CD:\
+89A9BF6B893BC5E6FEF4C77F3D0F29A6A794CAEE6756281B
+
+DEA4F3DA75EC7A8EAC3861A9912402CD:FB66522C332FCC4C042ABE32FA9E902F:\
+5DBE44032769DF543EAD7AD13A5F331089A9BF6B893BC5E6
+
+FB66522C332FCC4C042ABE32FA9E902F:F0AB73301125FA21EF70BE5385FB76B6:\
+DEA4F3DA75EC7A8EAC3861A9912402CD5DBE44032769DF54
+
+F0AB73301125FA21EF70BE5385FB76B6:E75449212BEEF9F4A390BD860A640941:\
+FB66522C332FCC4C042ABE32FA9E902FDEA4F3DA75EC7A8E
+
+00000000000000000000000000000000:57FF739D4DC92C1BD7FC01700CC8216F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+57FF739D4DC92C1BD7FC01700CC8216F:D43BB7556EA32E46F2A282B7D45B4E0D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+D43BB7556EA32E46F2A282B7D45B4E0D:90AFE91BB288544F2C32DC239B2635E6:\
+57FF739D4DC92C1BD7FC01700CC8216F00000000000000000000000000000000
+
+90AFE91BB288544F2C32DC239B2635E6:6CB4561C40BF0A9705931CB6D408E7FA:\
+D43BB7556EA32E46F2A282B7D45B4E0D57FF739D4DC92C1BD7FC01700CC8216F
+
+6CB4561C40BF0A9705931CB6D408E7FA:3059D6D61753B958D92F4781C8640E58:\
+90AFE91BB288544F2C32DC239B2635E6D43BB7556EA32E46F2A282B7D45B4E0D
+
+3059D6D61753B958D92F4781C8640E58:E69465770505D7F80EF68CA38AB3A3D6:\
+6CB4561C40BF0A9705931CB6D408E7FA90AFE91BB288544F2C32DC239B2635E6
+
+E69465770505D7F80EF68CA38AB3A3D6:5AB67A5F8539A4A5FD9F0373BA463466:\
+3059D6D61753B958D92F4781C8640E586CB4561C40BF0A9705931CB6D408E7FA
+
+5AB67A5F8539A4A5FD9F0373BA463466:DC096BCD99FC72F79936D4C748E75AF7:\
+E69465770505D7F80EF68CA38AB3A3D63059D6D61753B958D92F4781C8640E58
+
+DC096BCD99FC72F79936D4C748E75AF7:C5A3E7CEE0F1B7260528A68FB4EA05F2:\
+5AB67A5F8539A4A5FD9F0373BA463466E69465770505D7F80EF68CA38AB3A3D6
+
+C5A3E7CEE0F1B7260528A68FB4EA05F2:43D5CEC327B24AB90AD34A79D0469151:\
+DC096BCD99FC72F79936D4C748E75AF75AB67A5F8539A4A5FD9F0373BA463466
+
+43D5CEC327B24AB90AD34A79D0469151:05BA7BE9BE5274FBEB4AC5FD5FAAFA10:\
+C5A3E7CEE0F1B7260528A68FB4EA05F2DC096BCD99FC72F79936D4C748E75AF7
+
+05BA7BE9BE5274FBEB4AC5FD5FAAFA10:89D513B989E3CECE4D2E3E4C15D4E01C:\
+43D5CEC327B24AB90AD34A79D0469151C5A3E7CEE0F1B7260528A68FB4EA05F2
+
+89D513B989E3CECE4D2E3E4C15D4E01C:E56E462AE2E66F800CE2224C4CAFACBE:\
+05BA7BE9BE5274FBEB4AC5FD5FAAFA1043D5CEC327B24AB90AD34A79D0469151
+
+E56E462AE2E66F800CE2224C4CAFACBE:F5DBEE5414D79CA46BE17346FDC72BF5:\
+89D513B989E3CECE4D2E3E4C15D4E01C05BA7BE9BE5274FBEB4AC5FD5FAAFA10
+
+F5DBEE5414D79CA46BE17346FDC72BF5:C780FC28815E667B3D224ECF1F4A7D65:\
+E56E462AE2E66F800CE2224C4CAFACBE89D513B989E3CECE4D2E3E4C15D4E01C
+
+C780FC28815E667B3D224ECF1F4A7D65:2EF17A0D75440ECEC9AF18D29ABA3CDA:\
+F5DBEE5414D79CA46BE17346FDC72BF5E56E462AE2E66F800CE2224C4CAFACBE
+
+2EF17A0D75440ECEC9AF18D29ABA3CDA:D653FDFF96BCF89A929F6377AB41967A:\
+C780FC28815E667B3D224ECF1F4A7D65F5DBEE5414D79CA46BE17346FDC72BF5
+
+D653FDFF96BCF89A929F6377AB41967A:36BBAD8838380C8793A7AEA0A11D04D2:\
+2EF17A0D75440ECEC9AF18D29ABA3CDAC780FC28815E667B3D224ECF1F4A7D65
+
+36BBAD8838380C8793A7AEA0A11D04D2:034EFECFC0EFC00D82C3345A8708AE78:\
+D653FDFF96BCF89A929F6377AB41967A2EF17A0D75440ECEC9AF18D29ABA3CDA
+
+034EFECFC0EFC00D82C3345A8708AE78:EA38887307337A2934A9EB802F6CFDDD:\
+36BBAD8838380C8793A7AEA0A11D04D2D653FDFF96BCF89A929F6377AB41967A
+
+EA38887307337A2934A9EB802F6CFDDD:7C279D47775AB4C26442E8A117943DD8:\
+034EFECFC0EFC00D82C3345A8708AE7836BBAD8838380C8793A7AEA0A11D04D2
+
+7C279D47775AB4C26442E8A117943DD8:E3CF581056EBC1169CF451E930308726:\
+EA38887307337A2934A9EB802F6CFDDD034EFECFC0EFC00D82C3345A8708AE78
+
+E3CF581056EBC1169CF451E930308726:65527B29D489C8CDDC62E5E7FFC4E924:\
+7C279D47775AB4C26442E8A117943DD8EA38887307337A2934A9EB802F6CFDDD
+
+65527B29D489C8CDDC62E5E7FFC4E924:3B491F930230A0170819CACB48F9030C:\
+E3CF581056EBC1169CF451E9303087267C279D47775AB4C26442E8A117943DD8
+
+3B491F930230A0170819CACB48F9030C:A7C8193F35AF63B51D7F9DEDCEC85866:\
+65527B29D489C8CDDC62E5E7FFC4E924E3CF581056EBC1169CF451E930308726
+
+A7C8193F35AF63B51D7F9DEDCEC85866:009A48F9A1C27F9AA5F9BD909C848B60:\
+3B491F930230A0170819CACB48F9030C65527B29D489C8CDDC62E5E7FFC4E924
+
+009A48F9A1C27F9AA5F9BD909C848B60:3B507E987B3F827A093B26C85CDFF6C6:\
+A7C8193F35AF63B51D7F9DEDCEC858663B491F930230A0170819CACB48F9030C
+
+3B507E987B3F827A093B26C85CDFF6C6:EAFB3BA6C78E37214FE908669BC24F6F:\
+009A48F9A1C27F9AA5F9BD909C848B60A7C8193F35AF63B51D7F9DEDCEC85866
+
+EAFB3BA6C78E37214FE908669BC24F6F:2B09F10D7F2B62A4D0DAFFB9F882B980:\
+3B507E987B3F827A093B26C85CDFF6C6009A48F9A1C27F9AA5F9BD909C848B60
+
+2B09F10D7F2B62A4D0DAFFB9F882B980:E6B9FE907009B2DC649412DD630AE576:\
+EAFB3BA6C78E37214FE908669BC24F6F3B507E987B3F827A093B26C85CDFF6C6
+
+E6B9FE907009B2DC649412DD630AE576:F2E4DC89724CD58F85847BD09ED4500F:\
+2B09F10D7F2B62A4D0DAFFB9F882B980EAFB3BA6C78E37214FE908669BC24F6F
+
+F2E4DC89724CD58F85847BD09ED4500F:DC650444FCEBC2BD6E450EF4605FCABE:\
+E6B9FE907009B2DC649412DD630AE5762B09F10D7F2B62A4D0DAFFB9F882B980
+
+DC650444FCEBC2BD6E450EF4605FCABE:B7CFB31755FDA2AB0A67FBA09901A73E:\
+F2E4DC89724CD58F85847BD09ED4500FE6B9FE907009B2DC649412DD630AE576
+
+B7CFB31755FDA2AB0A67FBA09901A73E:9C7E7578F3D2923DCDABFED0A5EF86EE:\
+DC650444FCEBC2BD6E450EF4605FCABEF2E4DC89724CD58F85847BD09ED4500F
+
+9C7E7578F3D2923DCDABFED0A5EF86EE:9465E9AE176483BD398C8033AA136F68:\
+B7CFB31755FDA2AB0A67FBA09901A73EDC650444FCEBC2BD6E450EF4605FCABE
+
+9465E9AE176483BD398C8033AA136F68:8551279DE9991805FCFC1937C52AE9D4:\
+9C7E7578F3D2923DCDABFED0A5EF86EEB7CFB31755FDA2AB0A67FBA09901A73E
+
+8551279DE9991805FCFC1937C52AE9D4:A830EB8DA52ECFF7F93B7627322CF9D7:\
+9465E9AE176483BD398C8033AA136F689C7E7578F3D2923DCDABFED0A5EF86EE
+
+A830EB8DA52ECFF7F93B7627322CF9D7:EC89F0E5155425D4B92BD4B200C1A6E0:\
+8551279DE9991805FCFC1937C52AE9D49465E9AE176483BD398C8033AA136F68
+
+EC89F0E5155425D4B92BD4B200C1A6E0:8AF76A782061D38360C6C3CDDCBE1516:\
+A830EB8DA52ECFF7F93B7627322CF9D78551279DE9991805FCFC1937C52AE9D4
+
+8AF76A782061D38360C6C3CDDCBE1516:D4EEAA6A069659D5D88590DE75515631:\
+EC89F0E5155425D4B92BD4B200C1A6E0A830EB8DA52ECFF7F93B7627322CF9D7
+
+D4EEAA6A069659D5D88590DE75515631:259C021D37B077197B80FCDB07EA1AF2:\
+8AF76A782061D38360C6C3CDDCBE1516EC89F0E5155425D4B92BD4B200C1A6E0
+
+259C021D37B077197B80FCDB07EA1AF2:300CC8B4171F0E9BD75710FAD033C570:\
+D4EEAA6A069659D5D88590DE755156318AF76A782061D38360C6C3CDDCBE1516
+
+300CC8B4171F0E9BD75710FAD033C570:5CFA5BD213A74F02E65390A4C14A1DF6:\
+259C021D37B077197B80FCDB07EA1AF2D4EEAA6A069659D5D88590DE75515631
+
+5CFA5BD213A74F02E65390A4C14A1DF6:A443EA1B2C5747CE7EC5F21D4FE0C147:\
+300CC8B4171F0E9BD75710FAD033C570259C021D37B077197B80FCDB07EA1AF2
+
+A443EA1B2C5747CE7EC5F21D4FE0C147:D2DED73E59319A8138E0331F0EA149EA:\
+5CFA5BD213A74F02E65390A4C14A1DF6300CC8B4171F0E9BD75710FAD033C570
+
+D2DED73E59319A8138E0331F0EA149EA:2E2158BC3E5FC714C1EEECA0EA696D48:\
+A443EA1B2C5747CE7EC5F21D4FE0C1475CFA5BD213A74F02E65390A4C14A1DF6
+
+2E2158BC3E5FC714C1EEECA0EA696D48:248A7F3528B168ACFDD1386E3F51E30C:\
+D2DED73E59319A8138E0331F0EA149EAA443EA1B2C5747CE7EC5F21D4FE0C147
+
+248A7F3528B168ACFDD1386E3F51E30C:431058F4DBC7F734DA4F02F04CC4F459:\
+2E2158BC3E5FC714C1EEECA0EA696D48D2DED73E59319A8138E0331F0EA149EA
+
+431058F4DBC7F734DA4F02F04CC4F459:37FE26FF1CF66175F5DDF4C33B97A205:\
+248A7F3528B168ACFDD1386E3F51E30C2E2158BC3E5FC714C1EEECA0EA696D48
+
+00000000000000000000000000000000:6BFD32804A1C3206C4BF85EB11241F89:\
+80000000000000000000000000000000
+
+00000000000000000000000000000000:F097147AE851845984DC97D5FAE40CF9:\
+40000000000000000000000000000000
+
+00000000000000000000000000000000:6117F1977C5ABD9647C56544D9458444:\
+20000000000000000000000000000000
+
+00000000000000000000000000000000:75A6240AAE357DEDDF99936705618284:\
+10000000000000000000000000000000
+
+00000000000000000000000000000000:F026BFDF6BFBC7E50C46C533BD271C24:\
+08000000000000000000000000000000
+
+00000000000000000000000000000000:F3023228D77045D37D1B9CD77437395A:\
+04000000000000000000000000000000
+
+00000000000000000000000000000000:F67467BF6B490209809714D50679B2D7:\
+02000000000000000000000000000000
+
+00000000000000000000000000000000:2C8431B922C5F560095E9867B1A41256:\
+01000000000000000000000000000000
+
+00000000000000000000000000000000:1FB76E90D207BA4C770F67284D6B1359:\
+00800000000000000000000000000000
+
+00000000000000000000000000000000:A70AECE1D41DCA9F24BCE8393F6D54BF:\
+00400000000000000000000000000000
+
+00000000000000000000000000000000:D4580FC395979689221C57A23598358B:\
+00200000000000000000000000000000
+
+00000000000000000000000000000000:35CA62BA8126F015FABFEF8F9119AE6B:\
+00100000000000000000000000000000
+
+00000000000000000000000000000000:C81FACB16E087EEFA823CF34E02FE482:\
+00080000000000000000000000000000
+
+00000000000000000000000000000000:07400F04E4CC6625AE3FB41ECC863F2A:\
+00040000000000000000000000000000
+
+00000000000000000000000000000000:A0941008068D401DEAB6400C86CA53AD:\
+00020000000000000000000000000000
+
+00000000000000000000000000000000:2B63BEF50BA87A58BFFCA4CF44C22927:\
+00010000000000000000000000000000
+
+00000000000000000000000000000000:FD49069AE9F1874A264A7BFD894ED886:\
+00008000000000000000000000000000
+
+00000000000000000000000000000000:232755C754075BB5CC5B85ABFEA38779:\
+00004000000000000000000000000000
+
+00000000000000000000000000000000:41358B9C76E959037E13F7E5050E0B42:\
+00002000000000000000000000000000
+
+00000000000000000000000000000000:8978CD09C054BB1ABDFFBED09D1CF7EC:\
+00001000000000000000000000000000
+
+00000000000000000000000000000000:9F2A7CE5FD51FD5D7E2D42407EEF8F6A:\
+00000800000000000000000000000000
+
+00000000000000000000000000000000:6AA2F0627F312A77C68D1F15DF0E1379:\
+00000400000000000000000000000000
+
+00000000000000000000000000000000:BCD56984E45DBF087BAC8757FC4EFF5A:\
+00000200000000000000000000000000
+
+00000000000000000000000000000000:9D3C6C8ED48C9DE7A64CD05D8BF41D54:\
+00000100000000000000000000000000
+
+00000000000000000000000000000000:FCD577A23F455ACDE3732C262EBD2D86:\
+00000080000000000000000000000000
+
+00000000000000000000000000000000:022E2430D81858888C9E575411D4064F:\
+00000040000000000000000000000000
+
+00000000000000000000000000000000:5742CA8CF1193491C1FBC148627D856E:\
+00000020000000000000000000000000
+
+00000000000000000000000000000000:88BD93610040DFE248C2FE05EF9F4FE0:\
+00000010000000000000000000000000
+
+00000000000000000000000000000000:29A9D577BB3824209FEA64128247CE6C:\
+00000008000000000000000000000000
+
+00000000000000000000000000000000:AC4CDB534844EA86000B845FCDAD605F:\
+00000004000000000000000000000000
+
+00000000000000000000000000000000:AAC6098597D46B8145A60F40D4EC5308:\
+00000002000000000000000000000000
+
+00000000000000000000000000000000:3A7DFD0855A5BE0B16CACBD685FACEF5:\
+00000001000000000000000000000000
+
+00000000000000000000000000000000:ACEBA627EBA87AD051C3E0CA0DEF6CD7:\
+00000000800000000000000000000000
+
+00000000000000000000000000000000:F0A55DCDBC513EFDD603EA455EB9228C:\
+00000000400000000000000000000000
+
+00000000000000000000000000000000:2176DEBC78D6B4A6D0FB37AFA6B51081:\
+00000000200000000000000000000000
+
+00000000000000000000000000000000:FDB1B57379B85A85392613E8B4597B63:\
+00000000100000000000000000000000
+
+00000000000000000000000000000000:58AB1112E0598586E07FC8359DDFC7EC:\
+00000000080000000000000000000000
+
+00000000000000000000000000000000:DD6D1D2629F333528CB66869453BC273:\
+00000000040000000000000000000000
+
+00000000000000000000000000000000:932218D99553BB2D4BFC69F1EA67CAAE:\
+00000000020000000000000000000000
+
+00000000000000000000000000000000:399D066426F7FEF66F8983086DC044D8:\
+00000000010000000000000000000000
+
+00000000000000000000000000000000:3E1BC58269B6B8C8C8D00806975F8337:\
+00000000008000000000000000000000
+
+00000000000000000000000000000000:D50A1F966058C6D702D1AFCD700DA0E8:\
+00000000004000000000000000000000
+
+00000000000000000000000000000000:6E7A6BB3554F12AD1F88C289D621CD0F:\
+00000000002000000000000000000000
+
+00000000000000000000000000000000:9ED4EA506A0CBA89B246C14D1B5B96A9:\
+00000000001000000000000000000000
+
+00000000000000000000000000000000:C395A92C1A6884857B263F01F43542DB:\
+00000000000800000000000000000000
+
+00000000000000000000000000000000:06562AC497C60F802B68B47DB5B86B6A:\
+00000000000400000000000000000000
+
+00000000000000000000000000000000:255A726F2106177FEFA7006BDE05D059:\
+00000000000200000000000000000000
+
+00000000000000000000000000000000:B8FD6A8227D0565A4C174AD270EC1205:\
+00000000000100000000000000000000
+
+00000000000000000000000000000000:C2652FDB48B9DDBFC43B3F7CDD831D6F:\
+00000000000080000000000000000000
+
+00000000000000000000000000000000:913EB9205DB2E17A96A23A724EDF4C84:\
+00000000000040000000000000000000
+
+00000000000000000000000000000000:9A6694FEB5EA44FF0572124FDB265658:\
+00000000000020000000000000000000
+
+00000000000000000000000000000000:E347498DECA6B211C30E21FD0B47A333:\
+00000000000010000000000000000000
+
+00000000000000000000000000000000:E70F0D4ED829A81E05D42E511EDE9376:\
+00000000000008000000000000000000
+
+00000000000000000000000000000000:140BB7CAD8D6A3553BEF7A3D52347BD8:\
+00000000000004000000000000000000
+
+00000000000000000000000000000000:5FA55360F440DCCA20925A3E15B42764:\
+00000000000002000000000000000000
+
+00000000000000000000000000000000:6D5B969DFC3EA0A6682CC66488D221DA:\
+00000000000001000000000000000000
+
+00000000000000000000000000000000:E2799D5C380B49D2F6997009079D03D3:\
+00000000000000800000000000000000
+
+00000000000000000000000000000000:06AFBD8077909E847AF467BB2D47E893:\
+00000000000000400000000000000000
+
+00000000000000000000000000000000:46B1EB96EC9EB10897F1562E59287253:\
+00000000000000200000000000000000
+
+00000000000000000000000000000000:1793F1D4E1A1606F99C7019C19E85129:\
+00000000000000100000000000000000
+
+00000000000000000000000000000000:ED785D0BA19553CE73B69F4D570C3A9D:\
+00000000000000080000000000000000
+
+00000000000000000000000000000000:298DF7334670B7391BE203DF7E8890C7:\
+00000000000000040000000000000000
+
+00000000000000000000000000000000:150C12DEF6EDC844B0B45361C2B3AECE:\
+00000000000000020000000000000000
+
+00000000000000000000000000000000:06FFB5E13438BA8DBD8A3EDADFAC73A1:\
+00000000000000010000000000000000
+
+00000000000000000000000000000000:6C5E5719D5F31E929FF9C44F086EFADB:\
+00000000000000008000000000000000
+
+00000000000000000000000000000000:4C8D0E13996F4D32CB7984B7BB1B34FB:\
+00000000000000004000000000000000
+
+00000000000000000000000000000000:C9BDCFFD4B9F3BBBB33A2D2C51BA83F6:\
+00000000000000002000000000000000
+
+00000000000000000000000000000000:929B29DD0D952161FFDA8CB417B166EC:\
+00000000000000001000000000000000
+
+00000000000000000000000000000000:87F9DFCB07275916E7A446D3DCE74232:\
+00000000000000000800000000000000
+
+00000000000000000000000000000000:6FDFD0BC8F49BE420CD68A894C7CA4E9:\
+00000000000000000400000000000000
+
+00000000000000000000000000000000:CDDC09DE42DC2CBCD9287A2072A30D23:\
+00000000000000000200000000000000
+
+00000000000000000000000000000000:9B2FF668BA9D77AD1E9F30BA0173EBD4:\
+00000000000000000100000000000000
+
+00000000000000000000000000000000:DEF29890D59A511B32A30322D7471E38:\
+00000000000000000080000000000000
+
+00000000000000000000000000000000:5094EAEC9F23D0DBFAB8240A42ED5BF1:\
+00000000000000000040000000000000
+
+00000000000000000000000000000000:79CB87BC375F58DE8DA780B9BAD3DEA3:\
+00000000000000000020000000000000
+
+00000000000000000000000000000000:7139B3D980B85D3B77A3BBDB6CB79756:\
+00000000000000000010000000000000
+
+00000000000000000000000000000000:148ED6E8FEC02168377C96956AE18D93:\
+00000000000000000008000000000000
+
+00000000000000000000000000000000:0AFED5A710F2BF11C77F152951AE32CB:\
+00000000000000000004000000000000
+
+00000000000000000000000000000000:C265AC354817550FAE12A51C2DCD749C:\
+00000000000000000002000000000000
+
+00000000000000000000000000000000:A3B089F79D0A07EA0893BB48D508B35B:\
+00000000000000000001000000000000
+
+00000000000000000000000000000000:C0A7B6BCE0675A48E95D39A7659CB20A:\
+00000000000000000000800000000000
+
+00000000000000000000000000000000:6CE0A0BA02041CB5E6C0A46DE1B71A43:\
+00000000000000000000400000000000
+
+00000000000000000000000000000000:E54045C33A386555C5754ADB0A181244:\
+00000000000000000000200000000000
+
+00000000000000000000000000000000:BB652196955BB7BE7E8CB8E2E992A750:\
+00000000000000000000100000000000
+
+00000000000000000000000000000000:594B2917DE6119B62BE3DDF10A1A47E0:\
+00000000000000000000080000000000
+
+00000000000000000000000000000000:E8B4F95053617F6A10120DB196AAC4D1:\
+00000000000000000000040000000000
+
+00000000000000000000000000000000:79646B1CC19708973215B9891A2C1019:\
+00000000000000000000020000000000
+
+00000000000000000000000000000000:5E7E6175F6B548E5389C1B1C391CBEE2:\
+00000000000000000000010000000000
+
+00000000000000000000000000000000:C0860A7B47544872B9DB5C220088DE5C:\
+00000000000000000000008000000000
+
+00000000000000000000000000000000:325163F073E5A27EBAF339B1FA53682D:\
+00000000000000000000004000000000
+
+00000000000000000000000000000000:1A0C4583CEFF5810F3AB42A471415A1D:\
+00000000000000000000002000000000
+
+00000000000000000000000000000000:F8DDF239D19363957C7C8C9B537893FA:\
+00000000000000000000001000000000
+
+00000000000000000000000000000000:D3B9999669509564741F236EEF2401F3:\
+00000000000000000000000800000000
+
+00000000000000000000000000000000:3376DA406D82B76591B610C6C9FC3F9E:\
+00000000000000000000000400000000
+
+00000000000000000000000000000000:B6AD728D2970637642723FF06204EEAD:\
+00000000000000000000000200000000
+
+00000000000000000000000000000000:0ADF4A82FFE602BC13002AA8AB24EA71:\
+00000000000000000000000100000000
+
+00000000000000000000000000000000:D80D1378E30036D92B4A359F68D0CBFE:\
+00000000000000000000000080000000
+
+00000000000000000000000000000000:EDA13B315897290E4ACEB4B513E9749B:\
+00000000000000000000000040000000
+
+00000000000000000000000000000000:34589936B79E4F43260DC6CCD1820D6D:\
+00000000000000000000000020000000
+
+00000000000000000000000000000000:C7A8FF65CD38D008EC6745897E010122:\
+00000000000000000000000010000000
+
+00000000000000000000000000000000:3AFE23D89E79E9F8A54F103ED51EB14D:\
+00000000000000000000000008000000
+
+00000000000000000000000000000000:27994D1AA909806C7CC8E4AC4CD5479B:\
+00000000000000000000000004000000
+
+00000000000000000000000000000000:610D5528725B34FD70ADC66E83BAE266:\
+00000000000000000000000002000000
+
+00000000000000000000000000000000:3A3064DFF6E0B54D864E81FA76270065:\
+00000000000000000000000001000000
+
+00000000000000000000000000000000:5E9B5966ED3A2358005C9773F8690AD9:\
+00000000000000000000000000800000
+
+00000000000000000000000000000000:713738F580CED6E358D2CDCEDA64F99F:\
+00000000000000000000000000400000
+
+00000000000000000000000000000000:EC7FE3578906291B2DCF0AD7FF8B5358:\
+00000000000000000000000000200000
+
+00000000000000000000000000000000:0F714C096C244BED865A9E064576FE5D:\
+00000000000000000000000000100000
+
+00000000000000000000000000000000:B7C226C60B6F3031A1E2160823A62679:\
+00000000000000000000000000080000
+
+00000000000000000000000000000000:5C78C4BC8F15DC964FE9EC75203AD7D8:\
+00000000000000000000000000040000
+
+00000000000000000000000000000000:178FB7443FBD17DCF1AF122D4D117239:\
+00000000000000000000000000020000
+
+00000000000000000000000000000000:C55C99851BD135155A080A9C4E54B919:\
+00000000000000000000000000010000
+
+00000000000000000000000000000000:AD75C80D72EA278B3EDE380DAAB1F708:\
+00000000000000000000000000008000
+
+00000000000000000000000000000000:95054D1ECA74F75515AE8C17941D3A54:\
+00000000000000000000000000004000
+
+00000000000000000000000000000000:8E0B0D4F95C9C9D65420B4B1869A1D3E:\
+00000000000000000000000000002000
+
+00000000000000000000000000000000:7712EA2F0598CC8CFB9A934DEC848B5F:\
+00000000000000000000000000001000
+
+00000000000000000000000000000000:9D730E0F7450183C0804D6817CBE058E:\
+00000000000000000000000000000800
+
+00000000000000000000000000000000:3FA52E9B242F9AF61322FBB6BA583A01:\
+00000000000000000000000000000400
+
+00000000000000000000000000000000:3D47D74F667D60458188922EE8D8A7A0:\
+00000000000000000000000000000200
+
+00000000000000000000000000000000:036B4E4E02D84C56AC61007DAC33EC33:\
+00000000000000000000000000000100
+
+00000000000000000000000000000000:4E171141E51234DE6E4B236643A6DC85:\
+00000000000000000000000000000080
+
+00000000000000000000000000000000:DB720E7B04462829DFA258ED9E7C7F2F:\
+00000000000000000000000000000040
+
+00000000000000000000000000000000:8B10E11115FF4336DE57F2EA13AABBFA:\
+00000000000000000000000000000020
+
+00000000000000000000000000000000:F0E35BFF226C064E08368AF440298DB9:\
+00000000000000000000000000000010
+
+00000000000000000000000000000000:6C4C8811B4DF74F2A7D7F79A6253CEA7:\
+00000000000000000000000000000008
+
+00000000000000000000000000000000:7DD12AD3BC7A419F92753D8CC39637F0:\
+00000000000000000000000000000004
+
+00000000000000000000000000000000:A465B01EA32B2F4F87C85FD06F9B0A02:\
+00000000000000000000000000000002
+
+00000000000000000000000000000000:8DC902DDAE09F52B1A3A77EE89C1441E:\
+00000000000000000000000000000001
+
+00000000000000000000000000000000:B5AED133641004F4121B66E7DB8F2FF0:\
+800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:998110F200555A32C6C123E66CF87DE9:\
+400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2DBAEEEC682DCC957C2D51B0990E123A:\
+200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAEC0A31F6557D6D13B888A94F63058C:\
+100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E51ADC9773E785730586E6812A0F0FA5:\
+080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:97067E60FE010AEEA48C0D3224AD0941:\
+040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BB73A7C859E6377A5E42EFCD55CD2C5B:\
+020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:914BFE25D7FDEE49B46FB5C2B60DACA5:\
+010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EFEF0047892A043A1D594118477CA513:\
+008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BE59CF7C4E4B482843E67B4EB65B3038:\
+004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35FFC8038CB124B8078EC5C7C7928F14:\
+002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:086025FC1CC6056367304C51DE871DEA:\
+001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:950F0B7BDFFC78AE3AFF022F78E1670E:\
+000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CADF4568B43C950FB688C6608AAF5FAE:\
+000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E2313E3CFCB5E745EBAB983BF2867579:\
+000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B4394412F7B4A1A4A22B73C93BAFD85D:\
+000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C014C9A992E6366B3BD2EABDF1508187:\
+000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4344D702AC78A5808F4AB566D5509B75:\
+000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:937893DA40E9D7F2ECE9028FAA4DE6A4:\
+000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E77874759C6AACB611B715A52A37234A:\
+000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:841FC7FC0EF6CE08CFC6056B3C557F23:\
+000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6AC04A6988F1CE601E4C48241D42C1CF:\
+000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5254F42B5DD207461693C278B6ABC855:\
+000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F58B1AE230B417541649CB035FB5231C:\
+000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5F015060D28C6CCB2E5FDCB5AFDCF309:\
+000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B0DBAA257FEFFE48A688FE247D0460B7:\
+000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1235DF200338F96E39E881484B6B11EE:\
+000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:671D87102E35609B32F40A91A7E29E04:\
+000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F01FB3FA3E84DEA6057F3D88CD651876:\
+000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B96C1E40D0D407ED90D11892503A296F:\
+000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:2E27350191DE6C2E9DCC51022A3C96CB:\
+000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BDD6CFE5D00E7F8D698143E653A0163B:\
+000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FEDABEF20F51910E57CF5ECEF878A8E1:\
+000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EEBF9FE247A78C6FF2A91428C54D70DA:\
+000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:41714E55E90E0E154802FBBFC0BF58C5:\
+000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:69480F26BC5DFF8F6D8A0F10E0959BF1:\
+000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A39E4BE5A7E13BA3C48CFD98A52CFA70:\
+000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:95809A16888FB49F5053375A6533CD58:\
+000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:5F0DEF37FB14F956BB31703F1FC968EB:\
+000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:CF0A28C9598D7BBCA6992238B03EF4EB:\
+000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:7FF241BA32E6878542978957F137856F:\
+000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:8D489E0496B54F91A0254E4103804145:\
+000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:9925949BE93F4A0BF4114CCA2E05B566:\
+000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:6ED9A5F014FAFAE3D05C4AE027066873:\
+000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:958453307A371EE2D3DA8DD327D9B51B:\
+000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:1EE0680BF9A798A1C63636EA917B17B5:\
+000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:C0CEFB2475B21AA8937E3048604D9928:\
+000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:9034DDEFF43C9CC82FADE8DE0A2476BB:\
+000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:09D32779D0C8D02E0670F377187756FC:\
+000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:6557BDB19F03E62D823C0613BEA0FAFB:\
+000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:83505664DED694967F2D9E7853BC4B43:\
+000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:0BBABE3B7F381C3B3D8A9D846D8CCEAC:\
+000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:E3AA0A67CDF79DBAB013103E39E8C822:\
+000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:AF3D0C9B673C322355480E8681237D13:\
+000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:60D325226EC8DFB9E08DFADB479649A0:\
+000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:845B92A3C56880E8007B452B57B73B75:\
+000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:76C59CD9185C518D65EC641EB73C6387:\
+000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:735567D0B8A52203492220804F3D62E6:\
+000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:E74FB07622191A053368131DA36FC299:\
+000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:3CFF40E0E9A86F67D938D2483BDD08F0:\
+000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:7C502AE730F5A9ABEACB15240EA1E8F6:\
+000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:0B3CA10C02E24BA82261E65BE4413512:\
+000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:F7D50E95931755A98B143AE254090F9D:\
+000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:A4E84B8A7B8CC3766307D66A9C6AECB9:\
+000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:5298367E93E9B9CB5CF402A8BA9EFC62:\
+000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:03D44830C40510CE7866FB86FAC6E1DC:\
+000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:978E4BA4EEA6739B1769FF4389F0367E:\
+000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:707EF1166D2F11FD1519B37FB00D23EB:\
+000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:435088DBDD8646A7FCA8851CA2FA1FB5:\
+000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:F3DC32DD6931A302391F9B992A5B6122:\
+000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:D93286DD8A05432614FD03169F36ED15:\
+000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:59F83FEA4BC9B24BF69A98CA3959CEFC:\
+000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:A689BC3A8DB36A22763E911370C9DE2B:\
+000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:04EB5BA604BA64DD112BCAE830C27966:\
+000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:7EF653E2D804E80BD678C3A6CB222625:\
+000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:A94EC287E7F70C6503DC0B891920C622:\
+000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:8A78497E9D18A365599444C972359F0D:\
+000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:2F1832E285C8D24F226B50CCD71FE46A:\
+000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:0B6675F4BD4BD6951BB96AF62D3C9B96:\
+000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:D6DEDAAAECE52984A261155ED7AF5290:\
+000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:7600A0FCF96F24A21419103466B937B5:\
+000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:C3E359420C4C4AF445C470AB347B3667:\
+000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:D915133DAA11BECB43E020266B709BEC:\
+000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:A0001FC4E31664ED8C375644D02717AE:\
+000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:D8E96A3F240666FC02F31E84CD1CEEF1:\
+000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:DE0B6B80C40ED4447E36A84A62EB235D:\
+000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:8B15F04C34FC0F35F96C86837665CB38:\
+000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:02DAE104DA462934D87FDC73EB4011A9:\
+000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:B1ECC134EB7221CE00EBB977E08020E2:\
+000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:9F13CC1BF91C1B49AB6DDD7AF7A05ABA:\
+000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:414D1178475679525B5EE7ED373E2A0A:\
+000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:E69F2CC70EF18DBD360DFDD5C6573EBD:\
+000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:FA45D9E00E4C221A14C359742AC25C35:\
+000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:BC2AC98007820862150CC1B1E3E11ED1:\
+000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:C7CABAB4D7DFFD44C5943EB8E9441C3D:\
+000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:6DA6716020FDE292E8ADFB2A31BC6B24:\
+000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:9516AE03F102950795E1869E07BE0AFB:\
+000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:4748E60F70C6172E5D5B0C21E67F366C:\
+000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:40C7CC6385BB634FB68F73CCB5C446C2:\
+000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:7F0CE574F643711ECFC5011C0BCCD49A:\
+000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:2628849CC2C62FEB305A1287F24B9693:\
+000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:6E8C11B5EA12D40CE9F83693314BD836:\
+000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:503FCDFCCB2AEBEEE6FB59326D06745E:\
+000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:69698FE789F29872F0A4116CD8714255:\
+000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:3072C09636828285E7135E92B04C3601:\
+000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:00C19303036D6D3227B9C7AF806BEBDD:\
+000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:E6B06BC172CA8892C8A04D6717AB08CE:\
+000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:F7F08E268646EF8B9D728D422195A88B:\
+000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:E6C0BEE988E017E708FF1A1DCFE38FC8:\
+000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:33D0841FC04A6394056AC82D68DBFA02:\
+000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:066AF29F6138FE67D676925DBC375ED1:\
+000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:60E1109A80F56DBCBCAC75AF9EE3A982:\
+000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:84E692562A2DBE9452CDC7F5F7DCD4E6:\
+000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:DA5C0CB7DE7C2A9DEFC76348955FB51B:\
+000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:26AC1CB6870A598585E211852F9C980A:\
+000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:49776D30C4A10352FF0FBA170F09F275:\
+000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:D02E72C408A05C89F80C9EC450419FBF:\
+000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:993D122B38640477385BBFC79177C212:\
+000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:1482C5D53BE2F16634C22B9294D6E10B:\
+000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:4B9518E3188D68E20266DCAA5B26337F:\
+000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:7D6C9C9F375EDDE4A23D83B8B62E198F:\
+000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:FCCE30A6961099AD269080FF07A24E1E:\
+000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:C822629D39268498E02E6E4D642E7921:\
+000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:B96890D4CC0BD3C41A14D0547F98E077:\
+000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:78665BAC269A5DB3FFE165526A42F688:\
+000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:5EB1E7293616CD444011950212E53E78:\
+000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:FD682F200B2D5D17D177E785EBCE6C08:\
+000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:EAAEEA26A8AE037C288DDA6791580418:\
+000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:AA525000B28A88169212096B6D5FF58D:\
+000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:09C8F1F28B94167498D9377CB9909458:\
+000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:847E4FFAD40194940A0F7FA0E34739B4:\
+000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:50DCE06E775C1A6DDA24B2A926C9EF8E:\
+000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:3896FB03AF06F69CFDDDFBFCDF8E10A7:\
+000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:FED04C2F49DB4BE1D7BC5E187FB1612B:\
+000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:69E749DFCA9AC8A990444E9FFB6CBA09:\
+000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:9B2262EBF59AB552E04D57A72FE6F013:\
+000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:8FF0BF7F0088916764CF9FF21E1BDA67:\
+000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:5DE1FF41440B4CA0EEF22C8C3F96F23F:\
+000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:FEBE3209C8D61E85024DEF2122AF0268:\
+000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:DB63B702C6E39A283B64B90F36FBD426:\
+000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:BB364F05F769FFBFE18288BD782D20EB:\
+000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:8A929CBDE0CD9A9545A08DA2D16BA838:\
+000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:C5AE232EB4F293497E79E20E436B5A4C:\
+000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:3979A57AB9EB520E1475D745F897A9A9:\
+000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:469B440BBD0711C31B9AAA2564ECB68A:\
+000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:260AC31933A32B75C13364E868FD84DB:\
+000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:D5A76D2E0D00BE53B401ACB0EE70F8FB:\
+000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:C3475809C89275DE82F9F22D59A3DA37:\
+000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:C9B8FBFBF1A120BF47D0F2F48DD23661:\
+000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:C662358CCCD46730D243DEE03B871DC3:\
+000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:F5BA874DAE43AD835B3F1344653411B6:\
+000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:F0185396A6A69D48BBEADFE5B644EED4:\
+000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:DA0DEC6F13B5AEFC056F5D040C5DA310:\
+000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:7E1DBDE7B45F9C3E01A285EA575AD5ED:\
+000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:7A814893FBF78A6F5345F4E250DA454C:\
+000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:8C8B9E24399A6DF8293B0117307D6084:\
+000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:11BB87A542E9135ECEB6143A07E0B65E:\
+000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:495A92DB6E242E0A878EB4AC4C886802:\
+000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:97A5A7E3DAB800B3D4E7D468B4CCB951:\
+000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:C74D778D3F0440EB91981C23CC4F5669:\
+000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:1B485B0E4A063B844BC2AE8B722D0757:\
+000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:BF9D54F977A978797A4268CFC84132C4:\
+000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:90C50CB6D84B6A74F3D64A419B0419EA:\
+000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:776EED1A9849173A7AC46E94C9B2681B:\
+000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:A42F612CBF53529173E148ABA2B55D63:\
+000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:6F8B5F268B3DBEA72BF0D1F92B13684E:\
+000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:9379DA858CEC7AC58856E7DBF79C4757:\
+000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:17FE109D4638A9E1FAF130D621C160CB:\
+000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:2BCFAD82613FFD8D9BCBC539C1158BC9:\
+000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:8EA212BFBBF476CE35939066A7F1757D:\
+000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:1BFAC7B1B8EB14C26ADA2055E0C9CD36:\
+000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:9FCA8C1340C47C586D6A2FAD9FAA6833:\
+000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:D22D10708CBA6566DC096B8ABE3F9679:\
+000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:1FFC5754FC94465A073B714267DEC18C:\
+000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:FDED0173236B23DF4DFC1953355AA78E:\
+000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:FBE9178C4B27E51E24BF17053724AA2F:\
+000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:F02818D3D58D1F3345594670D3009DF4:\
+000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:6E148020BAB1DD04492299F6A9D9BA22:\
+000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:8E045AE3022AF7562106681B2B8CB70E:\
+000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:2C73832593114BF299424E30C5848625:\
+000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:127FC7BCF85F44F5041158A5EB3D040C:\
+000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:B25FABDA9D6E6704F23F33B0D907B762:\
+000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:21B968BF3EFFC638F54BC1524D8D378F:\
+000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:18F3BEB5D5A6B6AC512752AAA65EA3BD:\
+000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:5588729059256CE49AF2DA14EE4C9D00:\
+000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:A6EBD68D0A6F46DA22CD17D4B55BC4FE:\
+000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:50434829C09BFB7C174E1BE33642FEFB:\
+000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:682C20B72DDFE4F678B2379FA25715CA:\
+000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:925721E954372C9EA115BFF97BBE9A12:\
+000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:32929E53C8E8D85657B9B55A4911028C:\
+000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:8EE624F18BF5AA25ACE8667643D0D80D:\
+000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:30A61DCEB9A951B829DE01414A801807:\
+000000000000000000000000000000000000000000000001
+
+00000000000000000000000000000000:785229B51B515F30A1FCC88B969A4E47:\
+8000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B095E0619E70CDF5F4BC6E88079CF22F:\
+4000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:44F32AEAE82516AC8857C1985B7109EC:\
+2000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B2BBE93B433C8F0415B90282E788C071:\
+1000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9E953EBAA3B13F43F90908B53DAA0C09:\
+0800000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4579140290095FB25B3144444505D203:\
+0400000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5FD5F687596A9AA9EA105A2F7CF59A94:\
+0200000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:005EA3AF8AFF3DDA323148690537853C:\
+0100000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CD8E33C4F06FC0586E821522B2FEB08D:\
+0080000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CABEC07E46D11086778C3E1937CD0797:\
+0040000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:56BA650835E125201400380C4D2D5D99:\
+0020000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:EB48A1B279E95EBF8FAAC13D70F8F452:\
+0010000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E52435C29F7C9687B268C539BF6598B1:\
+0008000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:27785BDF6F6258EAC396BFD0F56BEE82:\
+0004000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CA16B1969FA373F43EF09D19B3379F3F:\
+0002000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6D1B6F14090368034E10CF0C1E4F5744:\
+0001000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:5AE3ABA331C5D765E3D112B1DA09E7BC:\
+0000800000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:767F9CBDA1BA9914EBA40D7A172A4077:\
+0000400000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8FAE713F677A82075D773DB73D58763E:\
+0000200000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:616CA9A15D710CA38FCA9A8E0B16A21C:\
+0000100000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D36754729DB34ECA1ECAC2CE2B381713:\
+0000080000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E68E3A421462A49AF8D7E544F7789301:\
+0000040000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:69B24511DF9BE48CFDB416F08908315F:\
+0000020000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:1329EA7551CE6C335DB924D563694058:\
+0000010000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:74DA788FB7A6172B65FBB62C7ED4FECC:\
+0000008000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:862703854F75F433135601000CD9363B:\
+0000004000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:824D4C002C401677D5785D6C6DA96C68:\
+0000002000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7F9F21E8C45D1E8A843060B963CC628B:\
+0000001000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3F6F7B1157906913B09BD2AE2627C6B0:\
+0000000800000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A1B7E0CC8B69B3C0C6F635F962D0A22F:\
+0000000400000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6FC34DDFF0C74674CE124D85E8A3447F:\
+0000000200000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:436A5D315AF443DEA9BEF8D1E817E7E0:\
+0000000100000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B0434C9C98CDA4B313DAD6F1E64A943:\
+0000000080000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AF9BD15EF1535259C63D688BF67119C4:\
+0000000040000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F61EF2509D173E348E01839A26D033FF:\
+0000000020000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9D37D036C8568D2173654423CC7AAB39:\
+0000000010000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A93D98C055DDAA592390CADB0F0C468D:\
+0000000008000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F19CB2A5067E9FBADBD4F0D103007A54:\
+0000000004000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:83C5D584511836263D8B0DE7CEF0AD16:\
+0000000002000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E09206EB6A5E8AC933BAAB46547E4CD9:\
+0000000001000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0A0EBA6ACED7899AA633CE67E8923936:\
+0000000000800000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C93968EC0EE02DACD3F3EE9AC2320B88:\
+0000000000400000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:64D62934D409F36505EEC3B925BE914D:\
+0000000000200000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BBADB03D5F0FCF375E671F8B009F3AF1:\
+0000000000100000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DAC60B05A1C3A203C6B4FE882E780079:\
+0000000000080000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8B650EC280BE261CCED5B5FC7F8A9BA7:\
+0000000000040000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:35EB82F0BB6735E2DE661AE4E9E9EE57:\
+0000000000020000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:40B1042CBE87D64DDBEA4BAC8CF1F08C:\
+0000000000010000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:13D46AE35D868401D23C891ED92621EE:\
+0000000000008000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D2C6E9C239B4FA5A1E76D038EA4660F3:\
+0000000000004000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:DE3BC7CDFAF9AB7143E255DC87645F3E:\
+0000000000002000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:8FB6CA966B5ACFB180A296EA5D93711F:\
+0000000000001000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:59F622ACBBA15E522717A9EAF7047949:\
+0000000000000800000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BB2939FFBD77B308DA93220AD68A21AC:\
+0000000000000400000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CEBE5EDD9BACF0A0FB75B259DE7097CD:\
+0000000000000200000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3448844E63AC2BD809E254AC3BAA6B3B:\
+0000000000000100000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:49C27499EEC1989626B1E50435BA0273:\
+0000000000000080000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:39E97018F547A8A802578B80952F2457:\
+0000000000000040000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9934453FBAAE1CB362A0012204967AE8:\
+0000000000000020000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E9C98A03713835EB4497346866791190:\
+0000000000000010000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:E026C858938B47D28A8758CCFAEF0FA8:\
+0000000000000008000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3A84B0A26CEA6A8D8A94D5B791A0D3E8:\
+0000000000000004000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B054259980B45B9D2D7CD6C13200BAFC:\
+0000000000000002000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:13645DBEDE21FF7C79C06141AD9E4CD1:\
+0000000000000001000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F29B1370BA8D8CC19AC8DF5DF77F7319:\
+0000000000000000800000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:6A2C94C488D5BD32742F143B2E8D0659:\
+0000000000000000400000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:27A0BF748F513F18D4F7831527A3608F:\
+0000000000000000200000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0B0D61E162A88E04C38C19CA668C2DDC:\
+0000000000000000100000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:4055BA24216EF49FE36E6145A5CD31D4:\
+0000000000000000080000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:99699B31EBBE6ABE1F7B2AFEC86DC7E2:\
+0000000000000000040000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:C8D70448CBA770CD94088F60CBF8C5AC:\
+0000000000000000020000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:56C89F1BA6D3AB20465F01F81D00A894:\
+0000000000000000010000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:919FC5BBFAB8C31F8B2A346FBC2AB282:\
+0000000000000000008000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:FF57E3AB8751DAA252DD0DD917BEAD8B:\
+0000000000000000004000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:90B94853B317FFA8D41F2A32A3A061AB:\
+0000000000000000002000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F4A0257D0CF6C8C87D154746C2C94B52:\
+0000000000000000001000000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:03666F848F252B501754773CB68CF3B2:\
+0000000000000000000800000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:F3D0941DDC7412A981C5F6CCAB082DC2:\
+0000000000000000000400000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:21EDD2A11C57EE97AEADFACEC20A8691:\
+0000000000000000000200000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:577CF09B5606F1443E8B57952004C68D:\
+0000000000000000000100000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0CF408A2FBDA07068BDB13A371867FCC:\
+0000000000000000000080000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:88542C9E680C27FE8FBE090AD73410B9:\
+0000000000000000000040000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:7A8BA6DC89A1AD4385D0696AFDD89496:\
+0000000000000000000020000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B84FA0FA046D5D77EA94CF3E8FDED147:\
+0000000000000000000010000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:D73CB079FB7101C933176352A93BB028:\
+0000000000000000000008000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:A7C8C1A59E141D608BC91BB69E7B2859:\
+0000000000000000000004000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B2DA67AFE49B33E5EDFAF148A17BF06B:\
+0000000000000000000002000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:AC2DB35ED86D358616648D22B52DF012:\
+0000000000000000000001000000000000000000000000000000000000000000
+
+00000000000000000000000000000000:662EA9D88A9A2C89581502EAAAD074D5:\
+0000000000000000000000800000000000000000000000000000000000000000
+
+00000000000000000000000000000000:773A30DFDA8EBCE50EDFB925343C9ECC:\
+0000000000000000000000400000000000000000000000000000000000000000
+
+00000000000000000000000000000000:10B7242D9C7CA610C20F1183BB949514:\
+0000000000000000000000200000000000000000000000000000000000000000
+
+00000000000000000000000000000000:B7DF971F9C3444EFCC13210292126942:\
+0000000000000000000000100000000000000000000000000000000000000000
+
+00000000000000000000000000000000:13F7406746C6E0CD5666EC04C0E540E2:\
+0000000000000000000000080000000000000000000000000000000000000000
+
+00000000000000000000000000000000:9382384DCAF80CF537E24FC5F2F71A8A:\
+0000000000000000000000040000000000000000000000000000000000000000
+
+00000000000000000000000000000000:3D5819934619E09F10E90C4EA7F30F40:\
+0000000000000000000000020000000000000000000000000000000000000000
+
+00000000000000000000000000000000:710446D0A254F68975CD6AAAE92212FD:\
+0000000000000000000000010000000000000000000000000000000000000000
+
+00000000000000000000000000000000:0A44FDEAA17E5F3E536A08D7A5B3267B:\
+0000000000000000000000008000000000000000000000000000000000000000
+
+00000000000000000000000000000000:BAC72F53EE39296D3A23B126F8D8B20B:\
+0000000000000000000000004000000000000000000000000000000000000000
+
+00000000000000000000000000000000:88C342961D0EE83902CB78C29539923D:\
+0000000000000000000000002000000000000000000000000000000000000000
+
+00000000000000000000000000000000:CF3B48A6351C4561752D6A209F93A30F:\
+0000000000000000000000001000000000000000000000000000000000000000
+
+00000000000000000000000000000000:957B107D23F3694F3FFD9957BBE13168:\
+0000000000000000000000000800000000000000000000000000000000000000
+
+00000000000000000000000000000000:23675E18C1C66B483D55E14AC7F9CC80:\
+0000000000000000000000000400000000000000000000000000000000000000
+
+00000000000000000000000000000000:955B8619F99F7609201CEEB338F32795:\
+0000000000000000000000000200000000000000000000000000000000000000
+
+00000000000000000000000000000000:9F2BCB0C28768DA3B76206979B14EBC2:\
+0000000000000000000000000100000000000000000000000000000000000000
+
+00000000000000000000000000000000:258F95A0E86EE0EE8FC020B4A01900F2:\
+0000000000000000000000000080000000000000000000000000000000000000
+
+00000000000000000000000000000000:FD7B1DD7C7FE279E6A5E2926DD890B5E:\
+0000000000000000000000000040000000000000000000000000000000000000
+
+00000000000000000000000000000000:59CF38A7C863C623991B5392944CB43C:\
+0000000000000000000000000020000000000000000000000000000000000000
+
+00000000000000000000000000000000:27BCC9206AEC78DA48C1E9AB8D1A7A07:\
+0000000000000000000000000010000000000000000000000000000000000000
+
+00000000000000000000000000000000:62D8460820B18811DEBB617DE7B8EC8C:\
+0000000000000000000000000008000000000000000000000000000000000000
+
+00000000000000000000000000000000:782D8A4D30EE841EDB2E7E88C63B851A:\
+0000000000000000000000000004000000000000000000000000000000000000
+
+00000000000000000000000000000000:4D10D177334397F49211BCB10F207905:\
+0000000000000000000000000002000000000000000000000000000000000000
+
+00000000000000000000000000000000:C8E608BAFE61254A0DDF866BB4D063DD:\
+0000000000000000000000000001000000000000000000000000000000000000
+
+00000000000000000000000000000000:05DDAB3DAEA0C64C1077BE22DA7ACDD4:\
+0000000000000000000000000000800000000000000000000000000000000000
+
+00000000000000000000000000000000:951388F2BE1DD7013A00327FC6DB7905:\
+0000000000000000000000000000400000000000000000000000000000000000
+
+00000000000000000000000000000000:62F8283651EFDF475DE8511EA7256AD6:\
+0000000000000000000000000000200000000000000000000000000000000000
+
+00000000000000000000000000000000:5B259EEE6B19EE12D4CE20D2F38D4BCF:\
+0000000000000000000000000000100000000000000000000000000000000000
+
+00000000000000000000000000000000:704414E13DCAD9DF7F593F630E68E13C:\
+0000000000000000000000000000080000000000000000000000000000000000
+
+00000000000000000000000000000000:41AD9DAAC24ECCBB454DBAF75D5B9989:\
+0000000000000000000000000000040000000000000000000000000000000000
+
+00000000000000000000000000000000:919C54C126B54D7A570D8ABA9FCE5D08:\
+0000000000000000000000000000020000000000000000000000000000000000
+
+00000000000000000000000000000000:BC665541FF0F2E86DBDF4444C01AC0EA:\
+0000000000000000000000000000010000000000000000000000000000000000
+
+00000000000000000000000000000000:FD30E2D851211506C112D5701B859BC6:\
+0000000000000000000000000000008000000000000000000000000000000000
+
+00000000000000000000000000000000:7DB7B15E4ACBDBB0BFF4C4EAEDC2231E:\
+0000000000000000000000000000004000000000000000000000000000000000
+
+00000000000000000000000000000000:F0AFDED56AD72D4C1E57A66EEDF4816E:\
+0000000000000000000000000000002000000000000000000000000000000000
+
+00000000000000000000000000000000:E53B053D9B2E06656138D4A1EFA58888:\
+0000000000000000000000000000001000000000000000000000000000000000
+
+00000000000000000000000000000000:4DABE13A3E656E95150440F81DD92666:\
+0000000000000000000000000000000800000000000000000000000000000000
+
+00000000000000000000000000000000:175D44DFDE1EAD6E0E6862B511AA7007:\
+0000000000000000000000000000000400000000000000000000000000000000
+
+00000000000000000000000000000000:09B690F493F5C779E8B6ACD09667A997:\
+0000000000000000000000000000000200000000000000000000000000000000
+
+00000000000000000000000000000000:68D0E4CCA0119EED57ABF3C7574BDA8B:\
+0000000000000000000000000000000100000000000000000000000000000000
+
+00000000000000000000000000000000:12C00618DA7EBA5EFA5E58D2696D891F:\
+0000000000000000000000000000000080000000000000000000000000000000
+
+00000000000000000000000000000000:5DCE21AF0D23BC5AEFD4EA331B16219A:\
+0000000000000000000000000000000040000000000000000000000000000000
+
+00000000000000000000000000000000:A5D7135A053B904D44B40E4E21693751:\
+0000000000000000000000000000000020000000000000000000000000000000
+
+00000000000000000000000000000000:3257CEC675BF755FEE67A44D7EDF2731:\
+0000000000000000000000000000000010000000000000000000000000000000
+
+00000000000000000000000000000000:324D30DDC6979F17A3BEAEA3A76AD44C:\
+0000000000000000000000000000000008000000000000000000000000000000
+
+00000000000000000000000000000000:A1AA0E04E2B61861796FD2AA30FBEB05:\
+0000000000000000000000000000000004000000000000000000000000000000
+
+00000000000000000000000000000000:90CA81DF4000404B567F5CFA9D193CB3:\
+0000000000000000000000000000000002000000000000000000000000000000
+
+00000000000000000000000000000000:A2E6864259483D059B57BB921B7FBD99:\
+0000000000000000000000000000000001000000000000000000000000000000
+
+00000000000000000000000000000000:545690C09C8C396F1273510DA9065C12:\
+0000000000000000000000000000000000800000000000000000000000000000
+
+00000000000000000000000000000000:16D86FCC5910E2DD0CEA4DD5219B2D03:\
+0000000000000000000000000000000000400000000000000000000000000000
+
+00000000000000000000000000000000:EC4114C19DD5711CD927B0DBE34AAB4B:\
+0000000000000000000000000000000000200000000000000000000000000000
+
+00000000000000000000000000000000:A78C62D8FD439E5B10A7EF436714AC22:\
+0000000000000000000000000000000000100000000000000000000000000000
+
+00000000000000000000000000000000:BA5D708CBA34F782DA00C7643C971DB9:\
+0000000000000000000000000000000000080000000000000000000000000000
+
+00000000000000000000000000000000:7DB9ADCFA26C1E784E7F485BD0A0A52C:\
+0000000000000000000000000000000000040000000000000000000000000000
+
+00000000000000000000000000000000:8A025CED99AF1047C5345358A291CDBB:\
+0000000000000000000000000000000000020000000000000000000000000000
+
+00000000000000000000000000000000:187A1824D390AD2798E4F2264E5F1F21:\
+0000000000000000000000000000000000010000000000000000000000000000
+
+00000000000000000000000000000000:BA28DE5C32353C65B97A59889E7A7A40:\
+0000000000000000000000000000000000008000000000000000000000000000
+
+00000000000000000000000000000000:5D486AB86A883029EC74916851FFFA11:\
+0000000000000000000000000000000000004000000000000000000000000000
+
+00000000000000000000000000000000:F9C79D54CEEE6170B195F4D30FA63FE0:\
+0000000000000000000000000000000000002000000000000000000000000000
+
+00000000000000000000000000000000:96B8429F476485F8CC2E204534A8B64E:\
+0000000000000000000000000000000000001000000000000000000000000000
+
+00000000000000000000000000000000:13061D65FEF26F5ACAAF3B55FDB98C36:\
+0000000000000000000000000000000000000800000000000000000000000000
+
+00000000000000000000000000000000:C72DC86F70B40169B3456783A611DAE9:\
+0000000000000000000000000000000000000400000000000000000000000000
+
+00000000000000000000000000000000:82AA2DB6FEE9212968D8282A1BF3242B:\
+0000000000000000000000000000000000000200000000000000000000000000
+
+00000000000000000000000000000000:220C8B197F54F8E86DAE575B07A570EF:\
+0000000000000000000000000000000000000100000000000000000000000000
+
+00000000000000000000000000000000:873C47F6F75BE9F710F91F2C54A69A7A:\
+0000000000000000000000000000000000000080000000000000000000000000
+
+00000000000000000000000000000000:0392FA7BB908FEF23774772F74AC968D:\
+0000000000000000000000000000000000000040000000000000000000000000
+
+00000000000000000000000000000000:A94203746A266C5744C16BF4E8DFA6D7:\
+0000000000000000000000000000000000000020000000000000000000000000
+
+00000000000000000000000000000000:D3BA78AD6B01CC7221FA7778699C8316:\
+0000000000000000000000000000000000000010000000000000000000000000
+
+00000000000000000000000000000000:994FDCC09C25400D14C05117B936EECD:\
+0000000000000000000000000000000000000008000000000000000000000000
+
+00000000000000000000000000000000:4012F67B2A0BEF2623CA6AC5B054BE62:\
+0000000000000000000000000000000000000004000000000000000000000000
+
+00000000000000000000000000000000:1134AF65E6D3D5E3D3C23A499EE2F677:\
+0000000000000000000000000000000000000002000000000000000000000000
+
+00000000000000000000000000000000:6B35A344BD8DFD4002F5F22EA288F8E6:\
+0000000000000000000000000000000000000001000000000000000000000000
+
+00000000000000000000000000000000:D293D438C563B8EB3FF26E23A7323B74:\
+0000000000000000000000000000000000000000800000000000000000000000
+
+00000000000000000000000000000000:8085B7A7B939FA37BC4E1D746E9F9B37:\
+0000000000000000000000000000000000000000400000000000000000000000
+
+00000000000000000000000000000000:D628AD150E15F413010BE15E391D3F48:\
+0000000000000000000000000000000000000000200000000000000000000000
+
+00000000000000000000000000000000:A5C2AC88B6FD4C57CB4F2C2920A584EF:\
+0000000000000000000000000000000000000000100000000000000000000000
+
+00000000000000000000000000000000:D7F5183F6BAB04B87A1ABAA3914DA848:\
+0000000000000000000000000000000000000000080000000000000000000000
+
+00000000000000000000000000000000:3B2116BD2E362FC8985A0F0C618DF58A:\
+0000000000000000000000000000000000000000040000000000000000000000
+
+00000000000000000000000000000000:BF31E8DE8342A32BBD80A8F91507BADA:\
+0000000000000000000000000000000000000000020000000000000000000000
+
+00000000000000000000000000000000:AA04A56C13507AE5137657546766AE2D:\
+0000000000000000000000000000000000000000010000000000000000000000
+
+00000000000000000000000000000000:72B9D7628AB21DF89666E50517C50574:\
+0000000000000000000000000000000000000000008000000000000000000000
+
+00000000000000000000000000000000:2B8DE8D2D3332E6A30215ACC10A69847:\
+0000000000000000000000000000000000000000004000000000000000000000
+
+00000000000000000000000000000000:AC421C73A789D79B452623DAFD3D6D0B:\
+0000000000000000000000000000000000000000002000000000000000000000
+
+00000000000000000000000000000000:995207D8CF8C10904C0F47652C9C4287:\
+0000000000000000000000000000000000000000001000000000000000000000
+
+00000000000000000000000000000000:F83BD19A357BD7901C0E8FBEFCF857ED:\
+0000000000000000000000000000000000000000000800000000000000000000
+
+00000000000000000000000000000000:F42BB427C894A072C861C1425CBD71BC:\
+0000000000000000000000000000000000000000000400000000000000000000
+
+00000000000000000000000000000000:3D1EC73B166DC0120DDF24267907C0F9:\
+0000000000000000000000000000000000000000000200000000000000000000
+
+00000000000000000000000000000000:8EF136AF5D7D1B513FB59FA21F7837A1:\
+0000000000000000000000000000000000000000000100000000000000000000
+
+00000000000000000000000000000000:EB4BBA7F94CE9429255A583D2F9810CD:\
+0000000000000000000000000000000000000000000080000000000000000000
+
+00000000000000000000000000000000:5FE1C3BCD24818948514CB5A32FFD0A1:\
+0000000000000000000000000000000000000000000040000000000000000000
+
+00000000000000000000000000000000:A990117E78D1C5BD7833B96A4A180744:\
+0000000000000000000000000000000000000000000020000000000000000000
+
+00000000000000000000000000000000:E63684CDC37E6768C45012EA00D008E4:\
+0000000000000000000000000000000000000000000010000000000000000000
+
+00000000000000000000000000000000:78B711F290DA924CAF1E4F1E11A08F4F:\
+0000000000000000000000000000000000000000000008000000000000000000
+
+00000000000000000000000000000000:85B7F0D391AF9268643D9C0B72433A99:\
+0000000000000000000000000000000000000000000004000000000000000000
+
+00000000000000000000000000000000:F51410475B33FBD3DB2117B5C17C82D4:\
+0000000000000000000000000000000000000000000002000000000000000000
+
+00000000000000000000000000000000:A3C5BF72F39940DC7DAFB474A77A6114:\
+0000000000000000000000000000000000000000000001000000000000000000
+
+00000000000000000000000000000000:4EFB0E18FB2F96FB6F81514BCE0A7BBD:\
+0000000000000000000000000000000000000000000000800000000000000000
+
+00000000000000000000000000000000:10112F5ABBF246996860B843FC7159F5:\
+0000000000000000000000000000000000000000000000400000000000000000
+
+00000000000000000000000000000000:94A91373701569B8C21487A7BDB164B6:\
+0000000000000000000000000000000000000000000000200000000000000000
+
+00000000000000000000000000000000:A466821BD64F552C0610ADB737C562CD:\
+0000000000000000000000000000000000000000000000100000000000000000
+
+00000000000000000000000000000000:511BE2BA9F2A272CA2F5C1D0F3E249C1:\
+0000000000000000000000000000000000000000000000080000000000000000
+
+00000000000000000000000000000000:5578CCF8B92D48363EED4601661EB56E:\
+0000000000000000000000000000000000000000000000040000000000000000
+
+00000000000000000000000000000000:BF90E87173A45115C811B6319C24FC4A:\
+0000000000000000000000000000000000000000000000020000000000000000
+
+00000000000000000000000000000000:8029EE840D130319330B432D95DB9AA7:\
+0000000000000000000000000000000000000000000000010000000000000000
+
+00000000000000000000000000000000:19D6D9F45582481A573D77917E778F3C:\
+0000000000000000000000000000000000000000000000008000000000000000
+
+00000000000000000000000000000000:556D552FDE7C64227E2B72776488D6C1:\
+0000000000000000000000000000000000000000000000004000000000000000
+
+00000000000000000000000000000000:3E81B51A214CC1F1CF6F35F9106A84BC:\
+0000000000000000000000000000000000000000000000002000000000000000
+
+00000000000000000000000000000000:4E48243857ECB700F8F16872E0BB4FA9:\
+0000000000000000000000000000000000000000000000001000000000000000
+
+00000000000000000000000000000000:681654DF6668CDDF1D3D604483AB483B:\
+0000000000000000000000000000000000000000000000000800000000000000
+
+00000000000000000000000000000000:BD6CEEFD85A336E4F12D42076573ECA2:\
+0000000000000000000000000000000000000000000000000400000000000000
+
+00000000000000000000000000000000:7488F9790FEC8AAE2AADDF6A600629B3:\
+0000000000000000000000000000000000000000000000000200000000000000
+
+00000000000000000000000000000000:669C36695C33B63F16077CAE9AA940AA:\
+0000000000000000000000000000000000000000000000000100000000000000
+
+00000000000000000000000000000000:7CE998A357384159C9B34A9A8AC7DF78:\
+0000000000000000000000000000000000000000000000000080000000000000
+
+00000000000000000000000000000000:51BE07BA8106A19CCC2005B8B3932FBF:\
+0000000000000000000000000000000000000000000000000040000000000000
+
+00000000000000000000000000000000:2634245A6EC3F17A35B7FE1D3E17F769:\
+0000000000000000000000000000000000000000000000000020000000000000
+
+00000000000000000000000000000000:24D4114760BCE04C0109C06CCE199F6C:\
+0000000000000000000000000000000000000000000000000010000000000000
+
+00000000000000000000000000000000:3F055452FCD596C6D588BD48BB5D5080:\
+0000000000000000000000000000000000000000000000000008000000000000
+
+00000000000000000000000000000000:A1D97F66DEF90DE14CC2BFAFF09286BB:\
+0000000000000000000000000000000000000000000000000004000000000000
+
+00000000000000000000000000000000:80442DC4EBFB53B86E232D886CA166B9:\
+0000000000000000000000000000000000000000000000000002000000000000
+
+00000000000000000000000000000000:76A593802C6A691152E8A04E5DE2D05A:\
+0000000000000000000000000000000000000000000000000001000000000000
+
+00000000000000000000000000000000:F923A147E00807D58FB9C686E01F7E07:\
+0000000000000000000000000000000000000000000000000000800000000000
+
+00000000000000000000000000000000:8EA3B396D561A3CFCE729A0B59647760:\
+0000000000000000000000000000000000000000000000000000400000000000
+
+00000000000000000000000000000000:4AA735D710704790C060BAD696DACABE:\
+0000000000000000000000000000000000000000000000000000200000000000
+
+00000000000000000000000000000000:7F7C322D82557737F5407A797069B711:\
+0000000000000000000000000000000000000000000000000000100000000000
+
+00000000000000000000000000000000:5094418C55B7D591EFDB7097CB95B16D:\
+0000000000000000000000000000000000000000000000000000080000000000
+
+00000000000000000000000000000000:CC014984ABDFB760A835846668340929:\
+0000000000000000000000000000000000000000000000000000040000000000
+
+00000000000000000000000000000000:18F86EA6C633228579C5728FF070AC21:\
+0000000000000000000000000000000000000000000000000000020000000000
+
+00000000000000000000000000000000:AFCF921E4FA24FDEF85EDAC12CD479F1:\
+0000000000000000000000000000000000000000000000000000010000000000
+
+00000000000000000000000000000000:684085D0BE8AE0D617B2EFEF62CAAC93:\
+0000000000000000000000000000000000000000000000000000008000000000
+
+00000000000000000000000000000000:04C7B0268EAEFED098C815935D868CF9:\
+0000000000000000000000000000000000000000000000000000004000000000
+
+00000000000000000000000000000000:39AE859D255487A68093A376D358BBC2:\
+0000000000000000000000000000000000000000000000000000002000000000
+
+00000000000000000000000000000000:F1218B59E947816041B21AC28685EF36:\
+0000000000000000000000000000000000000000000000000000001000000000
+
+00000000000000000000000000000000:B9BE024D06447F8965E480B33975E36F:\
+0000000000000000000000000000000000000000000000000000000800000000
+
+00000000000000000000000000000000:24ECD5B3178150233BD38A4B9F8EBC86:\
+0000000000000000000000000000000000000000000000000000000400000000
+
+00000000000000000000000000000000:7AD12485E896037A8D1A4ABE8A80B9BB:\
+0000000000000000000000000000000000000000000000000000000200000000
+
+00000000000000000000000000000000:CEC561C6F4C45CC944371E5D1C18EDF1:\
+0000000000000000000000000000000000000000000000000000000100000000
+
+00000000000000000000000000000000:F4B1088B0858A3737DF2C90FD919D1D4:\
+0000000000000000000000000000000000000000000000000000000080000000
+
+00000000000000000000000000000000:5EA6D1B9881CE230B8EABAC59B7F5393:\
+0000000000000000000000000000000000000000000000000000000040000000
+
+00000000000000000000000000000000:8023134FAC8BF5FDA86368BDA618AEF7:\
+0000000000000000000000000000000000000000000000000000000020000000
+
+00000000000000000000000000000000:D37285234A927061BEC9F8AAE0E796C8:\
+0000000000000000000000000000000000000000000000000000000010000000
+
+00000000000000000000000000000000:68AC18DB2FBF0A4A095A4B3344BF035D:\
+0000000000000000000000000000000000000000000000000000000008000000
+
+00000000000000000000000000000000:563868079C5DF91E3B47B370B0BBB820:\
+0000000000000000000000000000000000000000000000000000000004000000
+
+00000000000000000000000000000000:86C3BB221834F7507505434E4F98DC92:\
+0000000000000000000000000000000000000000000000000000000002000000
+
+00000000000000000000000000000000:FD8220818731607D8B69AC5963D0FAC9:\
+0000000000000000000000000000000000000000000000000000000001000000
+
+00000000000000000000000000000000:550726375ABB0F9A7C010DC4E47833F9:\
+0000000000000000000000000000000000000000000000000000000000800000
+
+00000000000000000000000000000000:8AB5E8973A5D6648517D151295091C0E:\
+0000000000000000000000000000000000000000000000000000000000400000
+
+00000000000000000000000000000000:338BB4B5569AA06411B9911381F350B2:\
+0000000000000000000000000000000000000000000000000000000000200000
+
+00000000000000000000000000000000:332D696EC49DF4B58C5FA9CC84773F47:\
+0000000000000000000000000000000000000000000000000000000000100000
+
+00000000000000000000000000000000:DEB5AC8F895AFF45BA5815D4912D8371:\
+0000000000000000000000000000000000000000000000000000000000080000
+
+00000000000000000000000000000000:89A49D3AB772D0FDAE05FC692EAF6C7B:\
+0000000000000000000000000000000000000000000000000000000000040000
+
+00000000000000000000000000000000:02116E6AEFC21A4D4D64CA27AB7AF31E:\
+0000000000000000000000000000000000000000000000000000000000020000
+
+00000000000000000000000000000000:58F79FF1810CA4B0E0178F7D9C24A581:\
+0000000000000000000000000000000000000000000000000000000000010000
+
+00000000000000000000000000000000:686FB1ED659D9BF17DA2BB79AC636C93:\
+0000000000000000000000000000000000000000000000000000000000008000
+
+00000000000000000000000000000000:1C5C176C4F5796B2C34D2A12858EB511:\
+0000000000000000000000000000000000000000000000000000000000004000
+
+00000000000000000000000000000000:2A94B92CC9C4776817C0A77D49E24F22:\
+0000000000000000000000000000000000000000000000000000000000002000
+
+00000000000000000000000000000000:890583A6C9549A3DCAFBD54BF391BC8F:\
+0000000000000000000000000000000000000000000000000000000000001000
+
+00000000000000000000000000000000:EA88A883197E483B4AA16316EA97CCBB:\
+0000000000000000000000000000000000000000000000000000000000000800
+
+00000000000000000000000000000000:CC5732CEB99A0A0353BABA6432BCBE9F:\
+0000000000000000000000000000000000000000000000000000000000000400
+
+00000000000000000000000000000000:88811B506D565779F09DE9BDF8702BD8:\
+0000000000000000000000000000000000000000000000000000000000000200
+
+00000000000000000000000000000000:E11FEE3AD4A9A03956704B58720C92DD:\
+0000000000000000000000000000000000000000000000000000000000000100
+
+00000000000000000000000000000000:644555DFB9CE8EDAF888EE142B5577F1:\
+0000000000000000000000000000000000000000000000000000000000000080
+
+00000000000000000000000000000000:716E2BBCBD8FF7E7335784B767F27CA9:\
+0000000000000000000000000000000000000000000000000000000000000040
+
+00000000000000000000000000000000:83588863F183ECE04E95629A322F9A09:\
+0000000000000000000000000000000000000000000000000000000000000020
+
+00000000000000000000000000000000:5E2833EC95ACE6B93AF28C6FCDBCE5D5:\
+0000000000000000000000000000000000000000000000000000000000000010
+
+00000000000000000000000000000000:B3EFCF17F0E1B275D413DD4D3A5CAE68:\
+0000000000000000000000000000000000000000000000000000000000000008
+
+00000000000000000000000000000000:3C943E1A2E7E56E4B185302D2D5C5DBD:\
+0000000000000000000000000000000000000000000000000000000000000004
+
+00000000000000000000000000000000:8CB4E2498382B523DCE6F7C17C91400B:\
+0000000000000000000000000000000000000000000000000000000000000002
+
+00000000000000000000000000000000:85F345366155D13F8F257734D2CBD6D9:\
+0000000000000000000000000000000000000000000000000000000000000001
+
+80000000000000000000000000000000:73B9FF14CF2589901FF52A0D6F4B7EDE:\
+00000000000000000000000000000000
+
+40000000000000000000000000000000:F5A9150BAB6D6AEBD6B4F97D9E93B28B:\
+00000000000000000000000000000000
+
+20000000000000000000000000000000:C30F8B221FD6D3996F973CDCDC6E305C:\
+00000000000000000000000000000000
+
+10000000000000000000000000000000:D6A531FE826CB0454F2D567A20018CB7:\
+00000000000000000000000000000000
+
+08000000000000000000000000000000:B62324BE427332A6089C7BE40D40292E:\
+00000000000000000000000000000000
+
+04000000000000000000000000000000:929B4789E9D6940C9A158880CA21C0E2:\
+00000000000000000000000000000000
+
+02000000000000000000000000000000:C14830DB50BA7221B27DC033B0D8D331:\
+00000000000000000000000000000000
+
+01000000000000000000000000000000:743342B02EBE647AE47092D435FA60F6:\
+00000000000000000000000000000000
+
+00800000000000000000000000000000:4F02AF45C09373D879CD01506A4E7D14:\
+00000000000000000000000000000000
+
+00400000000000000000000000000000:92BC9085AB0BA8FFEC2EA6D360864817:\
+00000000000000000000000000000000
+
+00200000000000000000000000000000:670A4ED16EA1BDE23E16CB52DBD31CB0:\
+00000000000000000000000000000000
+
+00100000000000000000000000000000:A52335AA9F42886084E21400DE48B62F:\
+00000000000000000000000000000000
+
+00080000000000000000000000000000:A5A240EBFED79F38F31497EA4C9CFCDA:\
+00000000000000000000000000000000
+
+00040000000000000000000000000000:46A64A07123E1212FE9E2F30EDFD80FF:\
+00000000000000000000000000000000
+
+00020000000000000000000000000000:20C9F20A8045AEDEE9D6E1CDA948339A:\
+00000000000000000000000000000000
+
+00010000000000000000000000000000:DF1606EEF4FEE3F4FC9EC26E2AB388AB:\
+00000000000000000000000000000000
+
+00008000000000000000000000000000:6758972B3171F0EA46304542776337FC:\
+00000000000000000000000000000000
+
+00004000000000000000000000000000:EC9B591DB8476C26C3CFDA618C1DBBD8:\
+00000000000000000000000000000000
+
+00002000000000000000000000000000:651551E741359E0A10BB4EE6A1C07C02:\
+00000000000000000000000000000000
+
+00001000000000000000000000000000:88BC2BF1F8A55562B95F8547C9A19E56:\
+00000000000000000000000000000000
+
+00000800000000000000000000000000:1A6CCCBD8D40AA14810ED615A6A6E24D:\
+00000000000000000000000000000000
+
+00000400000000000000000000000000:7B68DA568ABA5AE69D93C915E37DEE91:\
+00000000000000000000000000000000
+
+00000200000000000000000000000000:EC3922A728DA9E4C212D910E5C4AE632:\
+00000000000000000000000000000000
+
+00000100000000000000000000000000:5BAC94C97A4069400875A5ABC07BCB17:\
+00000000000000000000000000000000
+
+00000080000000000000000000000000:F3B4662918864BA94C1CF79C73B1F259:\
+00000000000000000000000000000000
+
+00000040000000000000000000000000:6FBF5A9A93EFA6640AFB80D9A2D22CF7:\
+00000000000000000000000000000000
+
+00000020000000000000000000000000:74139BD645DED7690F606490CCA44DD2:\
+00000000000000000000000000000000
+
+00000010000000000000000000000000:B20F456519D353AF91C012793576F9B8:\
+00000000000000000000000000000000
+
+00000008000000000000000000000000:C0AD52D4B4F67A9333A5E4B1B1176EEC:\
+00000000000000000000000000000000
+
+00000004000000000000000000000000:797224710FD09F9830B0F160AE9051E8:\
+00000000000000000000000000000000
+
+00000002000000000000000000000000:73669B64C292F4461FAA3A3D091D08DA:\
+00000000000000000000000000000000
+
+00000001000000000000000000000000:EFE0E893CE04008935CB7D43A7DC9ADD:\
+00000000000000000000000000000000
+
+00000000800000000000000000000000:3B0A2D3B236324221F81BFCAE45217D8:\
+00000000000000000000000000000000
+
+00000000400000000000000000000000:CE6F569FC89127B1AE19466FA36DD6E4:\
+00000000000000000000000000000000
+
+00000000200000000000000000000000:6037FE38896C05745C58C28CDF7FF386:\
+00000000000000000000000000000000
+
+00000000100000000000000000000000:92F5817D0BE37241F9292F6FF918A8E5:\
+00000000000000000000000000000000
+
+00000000080000000000000000000000:20C9A2A684563495C255A5751C1AC01E:\
+00000000000000000000000000000000
+
+00000000040000000000000000000000:AC6B6DB6D069B6895F2283435D33BD43:\
+00000000000000000000000000000000
+
+00000000020000000000000000000000:F9354B12C2366F1CE10F9A0550281267:\
+00000000000000000000000000000000
+
+00000000010000000000000000000000:684FDA9FCF3B3B5648A452CDA07CF002:\
+00000000000000000000000000000000
+
+00000000008000000000000000000000:9BE294C97C2A963006A2BD4541DC7DB5:\
+00000000000000000000000000000000
+
+00000000004000000000000000000000:A984F6F70E93FE65C8798C01D4E5D30C:\
+00000000000000000000000000000000
+
+00000000002000000000000000000000:E06A6CE2D74DB3D78E8F5D991C322B87:\
+00000000000000000000000000000000
+
+00000000001000000000000000000000:646771D16BAEDAC3F8E9D00C212518A2:\
+00000000000000000000000000000000
+
+00000000000800000000000000000000:9D2D410DC6F3BEC913D64BDBDEF3285E:\
+00000000000000000000000000000000
+
+00000000000400000000000000000000:6850AFECD8064E77F4F6944BDF5B324D:\
+00000000000000000000000000000000
+
+00000000000200000000000000000000:2E341142550F73F4C8E9DCCC5931A158:\
+00000000000000000000000000000000
+
+00000000000100000000000000000000:0CA58E149C2120A8EBF9A7885A89ACBC:\
+00000000000000000000000000000000
+
+00000000000080000000000000000000:41EACB7F6B5F9E3E3D299CA416EA2C59:\
+00000000000000000000000000000000
+
+00000000000040000000000000000000:C4D45503484DBC83CB52D3DB4AD0A7CC:\
+00000000000000000000000000000000
+
+00000000000020000000000000000000:CC52B159C2BCF87EE5F4926C6E7B7744:\
+00000000000000000000000000000000
+
+00000000000010000000000000000000:7E8A4023B8890A2DBF0D54E330FDF2A2:\
+00000000000000000000000000000000
+
+00000000000008000000000000000000:B05E771660493DCE3A275B0252D343A7:\
+00000000000000000000000000000000
+
+00000000000004000000000000000000:83D0034D231E179207F6A97FB1457FEB:\
+00000000000000000000000000000000
+
+00000000000002000000000000000000:7132BF130E8732C41F68107F49153FF2:\
+00000000000000000000000000000000
+
+00000000000001000000000000000000:B93021593B9EA2588F16E87D3C5DE0EC:\
+00000000000000000000000000000000
+
+00000000000000800000000000000000:26031449FBD6C84201B0BFB53B2C23CA:\
+00000000000000000000000000000000
+
+00000000000000400000000000000000:AFC8E9D2B9BFED9CE0B898F28607DF4C:\
+00000000000000000000000000000000
+
+00000000000000200000000000000000:C5094DE7E36CAEBE1B76EC3AC2C875F5:\
+00000000000000000000000000000000
+
+00000000000000100000000000000000:7DF8910A2D256FFB5D56FD1358F131FE:\
+00000000000000000000000000000000
+
+00000000000000080000000000000000:D93F84C1519D6627465E984675AA800B:\
+00000000000000000000000000000000
+
+00000000000000040000000000000000:5F1861F1523CDA0C95644B0C4F2EE6D1:\
+00000000000000000000000000000000
+
+00000000000000020000000000000000:FC5C4893AD148E4134EAEB3B1B190E29:\
+00000000000000000000000000000000
+
+00000000000000010000000000000000:80D1463F9E9416A143B2FF69DE629510:\
+00000000000000000000000000000000
+
+00000000000000008000000000000000:F16305404AE6266C619DC8ACA2D492E1:\
+00000000000000000000000000000000
+
+00000000000000004000000000000000:3B2554E422F9CEBB8271D7A48C94E03F:\
+00000000000000000000000000000000
+
+00000000000000002000000000000000:18B039EECB68A05CBF8C65EE85BDC4BC:\
+00000000000000000000000000000000
+
+00000000000000001000000000000000:BB26ABB17AD5482B1DCC4018E7DB0950:\
+00000000000000000000000000000000
+
+00000000000000000800000000000000:7E7AC0FD5B98157CEAD4BBAB643BE4CA:\
+00000000000000000000000000000000
+
+00000000000000000400000000000000:BD8A3B64849E54CC2D8379DCA9E42FDD:\
+00000000000000000000000000000000
+
+00000000000000000200000000000000:58C388DFB41FF3E14394C73FD8AAC56A:\
+00000000000000000000000000000000
+
+00000000000000000100000000000000:944B295E23C5B2542DED57A155D33EF8:\
+00000000000000000000000000000000
+
+00000000000000000080000000000000:067B4DD07DCA1292CFF0D80D75BDACA5:\
+00000000000000000000000000000000
+
+00000000000000000040000000000000:7D7344373196C5B30676F270BFC90B07:\
+00000000000000000000000000000000
+
+00000000000000000020000000000000:988C5164A82254B29326C98812A716CE:\
+00000000000000000000000000000000
+
+00000000000000000010000000000000:8FFD48787C28542E0450FAD4CBAD34D0:\
+00000000000000000000000000000000
+
+00000000000000000008000000000000:C50E7CD771628964E708425160FFB02C:\
+00000000000000000000000000000000
+
+00000000000000000004000000000000:B293B07F92D68C18FEC1466996B78020:\
+00000000000000000000000000000000
+
+00000000000000000002000000000000:DE21B2A6C8D7B90A7714DB3EF5209A6B:\
+00000000000000000000000000000000
+
+00000000000000000001000000000000:4700E22C08FE953CABAC7E78A3F747A7:\
+00000000000000000000000000000000
+
+00000000000000000000800000000000:504C1D7FAE3AB9A62323F21BF9A80A67:\
+00000000000000000000000000000000
+
+00000000000000000000400000000000:064BA0E8ADDD8E9DF4496E6931AD25F4:\
+00000000000000000000000000000000
+
+00000000000000000000200000000000:51D0B15C08FF32F1DCE7B28320875566:\
+00000000000000000000000000000000
+
+00000000000000000000100000000000:1A20EA3DB071121460244EDE27DA7A39:\
+00000000000000000000000000000000
+
+00000000000000000000080000000000:0035A5F7557B1B009327109D0C62F25C:\
+00000000000000000000000000000000
+
+00000000000000000000040000000000:803939C10EE11BB254A7768FAD053DA4:\
+00000000000000000000000000000000
+
+00000000000000000000020000000000:35D493255A870959C12F26170E6A1B64:\
+00000000000000000000000000000000
+
+00000000000000000000010000000000:DE8381198215D45B1BE787E4E8438500:\
+00000000000000000000000000000000
+
+00000000000000000000008000000000:B22E9707E738F723CD9B99386CE0162E:\
+00000000000000000000000000000000
+
+00000000000000000000004000000000:24C65ADDE5C3CD24B75C343782E87F6E:\
+00000000000000000000000000000000
+
+00000000000000000000002000000000:0050FF2C1A3C2AA68207D333F9956A72:\
+00000000000000000000000000000000
+
+00000000000000000000001000000000:162F7B8D35C1A98305BA0FE2A91FF27A:\
+00000000000000000000000000000000
+
+00000000000000000000000800000000:223D6117FE4864C2B3C513EAC2A5266A:\
+00000000000000000000000000000000
+
+00000000000000000000000400000000:3DBF645715ED7AD1964E2DCDE2F8806A:\
+00000000000000000000000000000000
+
+00000000000000000000000200000000:3DBB85509557BB00FE0F2013A90A5753:\
+00000000000000000000000000000000
+
+00000000000000000000000100000000:F2D75E45A62D1758C7A542BC805AC482:\
+00000000000000000000000000000000
+
+00000000000000000000000080000000:77628153A62DFD455B1C0E5B6CE9688C:\
+00000000000000000000000000000000
+
+00000000000000000000000040000000:8AE9DF2D94F6E85C86459132130E1BF5:\
+00000000000000000000000000000000
+
+00000000000000000000000020000000:BB610990F42303F4ECCD795E16780A13:\
+00000000000000000000000000000000
+
+00000000000000000000000010000000:A38330C5C0B464FFD6983972CF9541CC:\
+00000000000000000000000000000000
+
+00000000000000000000000008000000:EFD11CA98FEBB6F1ECBEBBCB8BD5E35B:\
+00000000000000000000000000000000
+
+00000000000000000000000004000000:3BC6740BF141DD33D65FDEAA10BF1655:\
+00000000000000000000000000000000
+
+00000000000000000000000002000000:FCF7BE4B89B54547C0BEF84EB85734F6:\
+00000000000000000000000000000000
+
+00000000000000000000000001000000:CBF5EF38DDEBCA39F2F6BEB2F3042D96:\
+00000000000000000000000000000000
+
+00000000000000000000000000800000:1119C20F08D4EA77A13C331678D4D71F:\
+00000000000000000000000000000000
+
+00000000000000000000000000400000:5C8241DA3FB0DC7328271B9FF72C91BA:\
+00000000000000000000000000000000
+
+00000000000000000000000000200000:337FCEE0AD0BDCA24AF5411B69D39B37:\
+00000000000000000000000000000000
+
+00000000000000000000000000100000:F6C56A841A31D58A90F5693F87380A3F:\
+00000000000000000000000000000000
+
+00000000000000000000000000080000:DD8C11B46F768B7CB2EAEE7E3448DD37:\
+00000000000000000000000000000000
+
+00000000000000000000000000040000:B8EE7182E563888E4F99335CF0372598:\
+00000000000000000000000000000000
+
+00000000000000000000000000020000:FCA9BAD58DD9C77B0BC0E616E7DE7F2D:\
+00000000000000000000000000000000
+
+00000000000000000000000000010000:798DA99BEFFBF99B23A3C15A31F60CB1:\
+00000000000000000000000000000000
+
+00000000000000000000000000008000:015CD86F000C87948BF3591C3DE4391F:\
+00000000000000000000000000000000
+
+00000000000000000000000000004000:B40B9945EEF7BC52E0B244ED71FAD3D3:\
+00000000000000000000000000000000
+
+00000000000000000000000000002000:D9BBB27B7D8AB20241E60F04108F1E12:\
+00000000000000000000000000000000
+
+00000000000000000000000000001000:6EC3F259B3FA960505CDE9D20F9EB905:\
+00000000000000000000000000000000
+
+00000000000000000000000000000800:01C1772AD104A988B2978447B91199F0:\
+00000000000000000000000000000000
+
+00000000000000000000000000000400:F8D5E997A8DD1B5BBE79C9F36B94C73C:\
+00000000000000000000000000000000
+
+00000000000000000000000000000200:4040058B08B27B6A585F18BFDBAE3E29:\
+00000000000000000000000000000000
+
+00000000000000000000000000000100:55547D09ACAF0C915B24E15ABAB0C827:\
+00000000000000000000000000000000
+
+00000000000000000000000000000080:FD7A0B33D397DA035D146DD56C869960:\
+00000000000000000000000000000000
+
+00000000000000000000000000000040:80C38900313E9350219EAE9AA7DA5E1B:\
+00000000000000000000000000000000
+
+00000000000000000000000000000020:F50D8495C3DCBFF4DFED0736F92475BB:\
+00000000000000000000000000000000
+
+00000000000000000000000000000010:58A06DC5AD2D7C0550771D6E9D59D58B:\
+00000000000000000000000000000000
+
+00000000000000000000000000000008:EEE324733E6409500FC9F9D6DCA185E0:\
+00000000000000000000000000000000
+
+00000000000000000000000000000004:F97C415886D05C12598F2C95F6B3EB16:\
+00000000000000000000000000000000
+
+00000000000000000000000000000002:F0FC7D86D814589A09D8EC136F95A124:\
+00000000000000000000000000000000
+
+00000000000000000000000000000001:CA737FF1FD0FE5B8E41E90358A5F2CB1:\
+00000000000000000000000000000000
+
+80000000000000000000000000000000:62EF193EDB7D399ACA50EC1CBE5398D8:\
+000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:E7A58D547688BA8B69DA949E38AA6FAD:\
+000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:71579F70A8EDB2BA5C00C513E2D7DEEB:\
+000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:C6171EF892F8224DC5FAE230AF629F52:\
+000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:C6A61053C48D7ECD7DDD12DB0F316AD7:\
+000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:EA5833714F1324DAB7F53CACC63F784F:\
+000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:450BCB0C7351CB1CDAC5D02E80D13C64:\
+000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:C267D3634F84215FB7B4635AFA385E52:\
+000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:6DB5B1B156DA1C36B9AB5AB59B063C29:\
+000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:EDF2D9B19FF75561E8FA6F411C4A0431:\
+000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:A11AE84E6D2C56DED2B9497FEC7504A7:\
+000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:B3A1A1E271BF94DA3A5ECFF1D4293A56:\
+000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:5577374ADCF2F58EEEFFC432C42AEB76:\
+000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:CD9D355C3574343BC7FBE645CE7EA721:\
+000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:76EB4C046F052AE4ED41060BF60067FB:\
+000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:1273A4BC420BCC9E29619567B1E61762:\
+000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:1F80E1CE3F12C96F2E647BACB6DA78D8:\
+000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:12D34A7875E716B37A7E250D37AFFDEA:\
+000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:5A54D764EEFFC4B64143A58B071514B4:\
+000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:F4F1567BDC5B1F938D5A214419090FE0:\
+000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:6CB91B935A0FBF49636CDF64A12955B7:\
+000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:C082154A07AF64FF6ECA811B0E3302E6:\
+000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:49A746CC225C1B6009A93649CDD9EDCD:\
+000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:1CAD0512E3CC51210B411EE452DF62E4:\
+000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:4FE9A0CF34BBCFFF906D8450197CC9D1:\
+000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:38DB8EF6C8993F17BB4D1614B9DE15D4:\
+000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:08DB3F476F551D19D9643A9E139E0553:\
+000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:F0F518F73795AB51BFB6E0AA99A0DAC7:\
+000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:91544D597F679E7DFE6D16D475809851:\
+000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:B1F92601B6D8C6B81176A46EE7341D28:\
+000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:796C3A8CBC6450E51FA6F8765ACD0F10:\
+000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:5F7BFE71BD2E81599DDA3411BC1CA579:\
+000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:2DF7D576EC6296101CAB16012092C12C:\
+000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:20769DE071FBE22AE49E7B3F5D646418:\
+000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:B6F5C012E4BA15DC86536F328B137FC0:\
+000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:1C3031DD05EAA4C278B55EF0E7E4C1F9:\
+000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:3D72A53BD537D04AC59E0AF36D105ED9:\
+000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:A6FFE499A2050C38F4E89DBF12B27430:\
+000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:BFBB2A537B2C1339D6230F35A256F289:\
+000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:70E79718C97DDB187411436AC072B148:\
+000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:13BB56699085842B81DBE8FAA8B26269:\
+000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:3E4DB71B9C737C7F8AEF632A5ADEF61D:\
+000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:D7A254B7341C7677C72F9DE729A3BB78:\
+000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:527D14E58B74224622DF7F3FD65932F5:\
+000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:708703993AD1DDE5C7F8714686F3AF32:\
+000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:C57D3ECB71A7DA4708DE6F338BC13E09:\
+000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:B31FF60BE0FDC17001CAF87FC7FC0B2D:\
+000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:01877AC646A283472DA74182FDC1E2B5:\
+000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:3C678BADA3FB1B872C018DC035AE16E8:\
+000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:A2CB209DA6AA40E043E6FB9DD2476100:\
+000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:4F9402FF56D04C8FB37DBE1A3109D2DE:\
+000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:342DAAD90F0F1699048D5CD16FDA2EC7:\
+000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:E68CC86CA4D952BC3890AEC0A7AAA4B5:\
+000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:02A88364BF94A677124F670A566E3F0D:\
+000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:C961EF325E2A32A4359CC63BE1EE2C77:\
+000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:03BF43C9083E4D9919D12FE5C0315E67:\
+000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:B27063442470BE07DCC2256EC71A4F1A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:222CC5A29084A4BDB05D4C2FD95648DF:\
+000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:E08686BFAA936E1890AEEC834E3B474A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:10DC4FFCAC5F5A1FB668277E8E75BEAB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:03A9199978F9D652A4C528FF86C39CE9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:DDF718A1BEB37CC1B0905520DB7C1611:\
+000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:2072191C277EE40FD557FF5F67A2A546:\
+000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:96B3608C06112F619B156105EB082BBE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:B5D919DFD9828C4FF4427E72ABFC77B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:9570E7A96D4674C800AF8DCD01DEFF64:\
+000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:59723DB66EDB29A9C81175668903777F:\
+000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:1779BDFAC6DB722BCAF4D3A8D9D2E725:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:5107B50A150998C6EA01C14697FC0E53:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:36A6CAA08BD5D2B332E9323F7C2E76CA:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:D1CF37451667EDB8D2E9934D39A27A92:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:4E96227B0A018755FBE8AD5BF0E421B0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:3221B3D3A24745B483BBF99509B330A0:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:98A4AB39B84D21D36A5DDC2660BD68C5:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:E5C351E1783465EDBA5CE0592BC77E8E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:35489488EE33D0344C1BDB6263D28286:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:97EA899F53C60536DAFEB18123FD6C5B:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:8511B11C7D2D8FBF63702A7E3AACA08A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:FE0C90596E4F47FD8A9927D83F4DCA52:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:186FE000683CC19F621BC6C2DA300B71:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:8291F94EDF578E8A70CD0CF8F3FB3558:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:2891C81846949C917E757EBAE20D34EE:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:762D85A32DAF0C9F3CFB3388E808FEC2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:CC6807D209B728C559C32336FD8FB71D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:FCD07057EF4820154075A0DDCBFC0BBD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:FDBFE2C3FFC82792D338388A1FC6D22E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:04D5F7CD68FC2352BDDBC82CFE35DA80:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:B1784A7BF395FB525471EE3DC8972FED:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:CB5D8A62D16220123EF0005876E35B19:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:311292EDE1F30E9F22F1EEF8FD19BD80:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:382BC583EC9B6E16E3DF2188CF0BF1E8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:632C9AD674BD1B8A15827A789BD133A7:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:0EE175DF45B889CED6974E9C2B8F8A78:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:6131A1A18F00CFDA5B4AF4FBE5487445:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:0C8746747460A540E2304B55C12EA672:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:DD6D4D2AA3EB702C597E4E2DE59BF4C9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:774EDF219459A4744AA1CCDE7D969A60:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:1D7B340C4CE68AC97369FFF0FF9980C8:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:D18104617258AB02AAE02ECCF552A891:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:8DC66F1D7648EB62F1DCBEB3CD237985:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:ABF090054ABE052ECE0B07BE6B6CC6DB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:89239AAFE9BA86E5EC794397E0180111:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:6E1CDC049333211B4D7533E21504D200:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:EFE662AF24D9997FAE45CAD4F92F3091:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:16F53F3A6CC3B4F86DDA1B8792244901:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:047CBACDC5EA84771A61FE1204813D46:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:B442FF3318822EA7F60E2A8A082A043A:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:971D07AEEDBCA5B7BDCD033F708C97DB:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:D307263273E250C0B9E08FF23003B0D1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:75F7005CA9C6EE5A1F9A4897FA67C661:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:9B421C68873D49F07E3B9025AD609787:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:5B182593B47DC674D8B1942CB97224B2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:A896871A3157CCD1F5A788E253A6B0FD:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:789A3D2B2A70181EFCCE5529F200DC44:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:7F9462D23DB6E99AD0A54EA84DBD94E2:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:23EAFE1F7CCE96B6BFE2484E1DFC4AB9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:A76C323805F9C252C8B86C83294B9987:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:D8CA1075B7A3F2CF2DAC0980B1B66CC1:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:8206D89F2A07BA6403647FB85A2F4D7D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:3DE7573CD46D85488364472B038869F9:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:31C62401D6E9E4995C0913747BFE7C7E:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:C464728025916B4E8D56E4A9F98C1A25:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:0D4643EE09ABD6D6062187789AE9A77D:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:0C06EAC3043ABE6554C2DA42F21E7B05:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:E26C6B2CBE2130729A5BF96E7CD29912:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:4DE2B8FFF3588A5D4E62CADB720E5BCC:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:B96DD46C6A286BFF721693A98491F529:\
+000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:64F1DBD3C79EE69AC9E0ED5F554F4AB6:\
+000000000000000000000000000000000000000000000000
+
+80000000000000000000000000000000:23A385F617F313DAC05BCB7EABD61807:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+40000000000000000000000000000000:35BE2B4738602A1DA3DE5C9E7E871923:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+20000000000000000000000000000000:03E8BB7A568E95BA792DCE77D5523C2B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+10000000000000000000000000000000:D3ACBE92C482D2E806FD837E41DBB288:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+08000000000000000000000000000000:DC3B1C37C69B4059EAADF03FCD016EB4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+04000000000000000000000000000000:3C9D9BD904E0E6916089A4BAC35E5368:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+02000000000000000000000000000000:C47DA045701B93A388E76FCBCD349F22:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+01000000000000000000000000000000:52F264B196925A345CA5ADC57C234B96:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00800000000000000000000000000000:C923754C5AD2E3F842D01705A716BE8A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00400000000000000000000000000000:630075C7563CDBACDFEADB781CC9467C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00200000000000000000000000000000:CB4F69BCC76A2499C6FCFBBE4CEB8CFB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00100000000000000000000000000000:0442F15EA2BD6D9EB773F9B99804DF56:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00080000000000000000000000000000:9CE6896C15C3CC00E2AA1944D7117B98:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00040000000000000000000000000000:E934066740023616B349F45582442647:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00020000000000000000000000000000:D08EF37A59D94ED645B1D1B160E3E816:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00010000000000000000000000000000:E91891CAC17FE493C7167C6CB59DCB69:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00008000000000000000000000000000:B27A42D2C870DC96BC6C551218C44CC4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00004000000000000000000000000000:CE8D23E64E6BC18208CEEB282E387326:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00002000000000000000000000000000:36F76678A27F2F5A436073D5ADA4AB3B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00001000000000000000000000000000:D0EAA36F9A648905B277F0BD24B1A339:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000800000000000000000000000000:82BE0E3673E7872BF79BBE2A45F4BD93:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000400000000000000000000000000:013CAE3986083F8D321273D68CA9784D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000200000000000000000000000000:0A7FCF71DAC023718153FFB761BAEBEF:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000100000000000000000000000000:C784C5EA8CE3897F153336047D2FE3E0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000080000000000000000000000000:FE776B4476A4F029E5EA9293E3C1BCA1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000040000000000000000000000000:302A5F9A73B07D83699EB9DE1D86DB7B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000020000000000000000000000000:E6C43F6F62F1EEE0BDB3484F325053B6:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000010000000000000000000000000:C5579556F710EACFAD9319AA85B89F6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000008000000000000000000000000:96C88E46C1C2BA0B583F30FE0248A794:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000004000000000000000000000000:287D27FB1CA40821294B1AFC868F3A6F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000002000000000000000000000000:F4602DF76A24010DE5A1353043CF178E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000001000000000000000000000000:47F98AA9DF5E7314D3D5571EF6B95284:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000800000000000000000000000:77CBF7DCA60F913FD9C82AC65212EBB2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000400000000000000000000000:BEB1C2BC4B5C363FCF5A0466883079A9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000200000000000000000000000:2AB8B9254ADBDCE17F0A719815DEFF7E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000100000000000000000000000:75A30CEAA03AF66E44A85DC66DEB20C9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000080000000000000000000000:C37E64CE86B615573C4C42BBE71DACD8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000040000000000000000000000:284CB50259A96CCED1C1C64D8B603024:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000020000000000000000000000:BE346B07869425CBCA54F93D7A1F4035:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000010000000000000000000000:60EE2023B03033A972E28E4A21C7005F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000008000000000000000000000:4E1FD4BC99AEA3BCC6B9066EC6329D43:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000004000000000000000000000:079BDF2DAD2CE6FB7D21BBD76A7ABF48:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000002000000000000000000000:6B933D9914169C2A704E52EC6D7E4E1D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000001000000000000000000000:FD854A50372E5D301367D8E98CC88028:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000800000000000000000000:8CE94A2C43B01825CE5F271135481BB2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000400000000000000000000:73A43C713898BA7D7D2B6BC8673A7AAA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000200000000000000000000:13873CFBDED482C0B7B435025A9F1CF4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000100000000000000000000:3F168CD782896F22C56A92A09EA7E162:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000080000000000000000000:BCDF1C8686E68810FE90B16ECAB46147:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000040000000000000000000:95C18EBA59E3CB6359DE7CCE9E8751F9:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000020000000000000000000:03CFEA7D36D56552CDEF806215EA7596:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000010000000000000000000:CC189A2E8F529EB139DCA2033109F40B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000008000000000000000000:453912532144CED54B7D4049BC8B8CF2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000004000000000000000000:C6DBBF405A056A80CA788267538FE8F0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000002000000000000000000:2EB5E272874CE244A328BA6410480B4C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000001000000000000000000:263BFB611CBD9D9C7FF6B1A9E3276696:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000800000000000000000:9CC3EB61A9907F5F22251239A9EB38ED:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000400000000000000000:726A3EE922EDFE52206C2191E1F045F4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000200000000000000000:1344C1E04A9D97668A240D82396AC021:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000100000000000000000:9067BAA44C264E9A2AEC292390A6F492:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000080000000000000000:1176621BD24D35670B08D6A065806B02:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000040000000000000000:DF0D31D14D81FD086E8E32479919FDBC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000020000000000000000:44BAD80B0BA01E971ADC4139D6DE0C36:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000010000000000000000:76C59131EFFAE14058D99E22698B602D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000008000000000000000:7604D9F3110F8440917ABCEA49710ADA:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000004000000000000000:4584FCBB487171176C4318082EFEFDF7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000002000000000000000:019D3B42FA31A9F9175759E6C3193A07:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000001000000000000000:C324FF5F71A974F13F5D83226441E3BD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000800000000000000:D9DF41408DFF80DE7C9571706B39038F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000400000000000000:FBB99A524AC23D74047D814EC0AEDBE2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000200000000000000:877C855E25345F6C7DB4237ECF64C874:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000100000000000000:206500F822C1305F9D61F49FC57AFBF2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000080000000000000:C7538D97A78844C3C00740865E26755B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000040000000000000:FADBC4A6E4564041ADA094C603CABAA4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000020000000000000:04C482E0707DE6DC1917727D00C4FA6B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000010000000000000:EE36B8996AFF98BEA6E2115B9D173321:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000008000000000000:DBA4A5F38B104985D796ECDDD812B605:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000004000000000000:1DC0F910CD5AF1E5734169459E170192:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000002000000000000:C3B7D6914052503D377B01DB4E3A630D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000001000000000000:54D807506602ECF7D6B8C4D923317738:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000800000000000:ACE4949143D4D1441AA854331E7F511B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000400000000000:F7BA140AED4756B26789498A17EBF62D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000200000000000:F23E08B81ACB75FE2326A94ECC5968AC:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000100000000000:4CF26F088604368B17DDC09FF9D0146D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000080000000000:E93AEB7AD76A6AD0AF4092F363421F1B:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000040000000000:3D234C0F78ECBEFCCDCE1EA6EC98C145:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000020000000000:BA300B0234F0C96125D33123CDD7D6A4:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000010000000000:1CF1A160FAD7E744F08BA1454A999211:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000008000000000:59A9E8C14ACBCEC235529425CF86998E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000004000000000:22D29CFEF3A6DC0EC67A9EA8523D6158:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000002000000000:513971F979FC906FADD982D7F08E4F05:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000001000000000:6A95C07D7FACF2CD36DF362116A2DD5F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000800000000:CD62AD57393A38607436FAF0985C2D50:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000400000000:5209ADE137B93BA0963528E3E1A40F2A:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000200000000:545BDE9D1C11239ED70D93060F24E397:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000100000000:720622F5194578B3C24B5DDDC7E30327:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000080000000:9E12338BF484106249754EAA6C441192:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000040000000:F13303DC759CA65097EC87F8D854163C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000020000000:4A2A6EB6845723C1C790D693B596CDE3:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000010000000:EF3D7C67417CA1FEEF03EF71441BDDFE:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000008000000:214FB38A7511A87CF160F59CCA2B8E33:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000004000000:DCFFDB5E44574D0D593A70ADA4C79474:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000002000000:AC9D55D4A4FBB80C9B79C9077BA381B1:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000001000000:05C6D61B75312924E0BCEDCB4B8D55DD:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000800000:E650CB445AF48A77E8DB6E2EFBCE6FA7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000400000:4C9902E89253D7A172BABFA87DB94816:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000200000:5AF4F5E8491EE7F87EB809D82AEC12DB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000100000:1C11730D62BCA6F847B1457B5287BD12:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000080000:BEF65A32FF7383CFDB5A90C2F3B93837:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000040000:2F3AA68FFE3B99DC92621782F3F9ED67:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000020000:18BD598BFA2C77E21DBD594EE0E5CDCB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000010000:248CF533016A6AB1F84F85B2C5CD41A7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000008000:A3B12F578353514CCC500ADD6C495A6C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000004000:EE2DC099B37D200B4D3930A6DE07208E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000002000:412C9F198D58A0F01F66DF07CF211636:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000001000:5B3532BA46716B02E761339DBAFBAAB0:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000800:0148187CA72EC46B522E4FE7E1261522:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000400:84C529CC4E23683AB90A24A6690662ED:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000200:0D1EF0481593A3D95F0361C776D9A4D2:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000100:D622171C73726DB6620FFDA6540D510E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000080:F218D92AED363C6829F7FA3BA346E0FB:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000040:40CD83A5F0BFD0E1D7FE14299CECFB7C:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000020:512F022157AEF0015E93F3737911A35E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000010:C7A5A88356152E95F36739AB5EF9F63F:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000008:8FD0F15E2504A8F4FD751CA7799FFB1D:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000004:0137C87257A8CBD18C218A867B3AB5F8:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000002:3DB0F1674F187DF1CB036DB33A05A0D7:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+00000000000000000000000000000001:23D1247EFF4CA8CBB378DF118369821E:\
+0000000000000000000000000000000000000000000000000000000000000000
+
+[XTEA]
+0123456789ABCDEF:B8BF2821622B5B30:00112233445566778899AABBCCDDEEFF
+D51399607F7AA9D7:782E4E131C5BA746:D94576CD1A5F99E4155DC7BEC5D33DF2
+10B233473624CCD3:57733A1DEECE283E:07EF12BC9D06D7DA20131116B665E335
+3B905E951E4FAFE7:776F4965DEB65775:C6462B48AFD604B75FCC455506FFD411
+15B623D1FA2DF9DF:3BD5AD5C9ED6101E:BE195F703D6FEC2232CD0890C981B27D
+7C1035940696D91D:5F93FA1D06991415:5B8410F7A9EB92DA120810C56FCAF8C9
+90B245144895F3AD:6105BFB0947828B7:B85C9E26661889D0FF1054C6BE27FDEB
+4EF2CFD120B8D4DC:51FAE58A10F7C3DD:A8A1E956D54D238F6CEAB186E7EC99ED
+F6CB5353F4A1C432:550AD71BA8A34568:8BC4879201A96368927ECCEEE67024EE
+215C080CF158A09B:13D1E24BA9FF7B63:F1372D85D8C3D1A60DF57EEDF317AB81
+568583061DA98D0D:6439B1DFE2ECB541:017F01683F5E009D196FEEAAD385C5A9
+0558B306316B0823:C8F82FE4491A8917:281C932DDD3C364B09F1896007FFAB03
+FDCB2764303222C7:244DBFA1D2C914E4:C1E95465C7EF8EB04254D1A5463C6A43
+EADDBA89070EC46C:5A4909646763454F:0F86DD6C96DD31164B656B0F25E4B411
+C6507BCF99B9C2A1:6F08EC714E8A7C18:FBACFB479AE21194C35B8184E58DD66E
+C380B0F1C21D4D37:72D4D4BDF5C00585:2EB36C4A9598D471700A1330070FFFC9
+E5B7C1517F24F298:64374B40BB732354:0A7F48127091780617A1F534B3271BC9
+D14DDF77FDDA17BF:014F1E707D02C8D8:303FB24822A1B8A84D0ECE77B86380FF
+B9682750BB15CAAD:9001D21B57AB5360:F04EBF798C193F199C1F532AF383555B
+9706769A18A2D03D:835FD788C089FD45:200C0CE59717D5D9AF6813CD207FEE73
+EDB76C54847DA59E:B0C0125494D39CE9:2828D51F98AE0B33F4DE2B7FBD18A529
+178A49BAFBA53F23:ADE26742F25EFBE1:61AABA6BE48B0D0D14FE5D27FAB852A4
+DF4CDB61A5F38536:9C895E72168B409E:2080E2409BA01C8532FC84403EE8C06A
+7C944D08DEF34C0C:B784E23E00B3B498:271AD15192C4D1204A4A2561E3DB6FF7
+F4C76C1D47FE568F:62F9E58B0364B0B6:C1E297C0C761777D8A76FFF02D22B859
+CAB16583E15D0074:4563BE765E74653A:23C807A2EF0A551F858FD52D125A47D8
+97B05C60774164AD:714807767366854B:9FA5D4D8CBDFCECD559E3CE88BF78EE1
+7017A263985B735C:CC68E1ED7F7C7832:24F4E91083139099D663647A7FFAC321
+15475A90DF04CD29:416EAB1EBC155782:7CF8626DE76D8462218ED5C9DC8ACC26
+87CA0AACCF146CC8:DED575554058EF42:3C6AD7DF17332A3E1E3DE06007387357
+9268AF048ECBAE67:899B9B877106C764:24237A762D8A89383A2949F5A0F5EC08
+AF0062CD77A84EBD:26DB40C151B74530:209A2833A39472D9720380FFB2F74761
+F922CA875B991A31:2763F255636A34C1:22EBE7A30E8855B3B453A6E926D4F187
+B4ECC305C3DBD8E5:FBBEC8F5DBF4CEFD:1B5E23EBD915C1FEE59F57DD91AF7347
+3DAADD7A9633E19B:4DE5C07EA1564A64:A6BFB85FA91B8CA4197C8B502A62F972
+
+# MARKER: Cipher Modes (Encryption)
+
+# Cipher mode format is plaintext:ciphertext:key:iv
+
+# The block cipher tests above are distinct from these ECB mode tests
+# for testing reasons. They could otherwise easily be CIPHER/ECB/NoPadding
+[DES/ECB/NoPadding]
+059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE
+4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF
+
+[DES/ECB/PKCS7]
+:705FDF4DC7ABFBFC:02D863A4885D417A
+FA:2281AC7CFA703BA9:05ADD235B01BBDA7
+B895:8C3BF9AB9D16C8CF:93F04843AFC3A191
+8E97DE:BE38BD2AFE108D2A:1F4E2C013314B55A
+C1DAE88E:998341E8B0CCE82E:0F59C05186431E13
+A6E0360E88:F5E88FCC387B8883:E68BF7B98D61FED0
+55E67A79F043:A868B107BD96F35C:AE3AB00A0BA38BE0
+D77C93B63D6D5B:19DA07A34FA683C4:9B661C7A536AFC6D
+328D09508E747AE1:9C75845C6BFF94438EB7E7E4C77342F0:8E1C689280575F05
+421D4BDC3869E59F07:8DF60DC27A2E2EE23360BE31343FCBDB:EB4A6B437572E1E7
+160E525583C3E4FBC4FE:9B649660DFE5B875CD81180AD627943F:FFE58726B90C9F97
+E873B3C2B31130719E6469:6E33AE2AF48CC39697800A3AA357CC5E:560EE1ED2CC2BFFB
+405915ADC0111EB8AF225612:569BE1F2AE91785B0634F8DD4EC1DFF2:012A7DE9CBFBD230
+E923C535186730F309CDEA6DEA:846D7314F76E00902054BD2B2AE1F580:3D5D56CA2E8E359C
+116053A5820F9D36650EEF49A05B:\
+9BD56C43036485B648EFE6D31E69F0C6:2AD63A5312BF4259
+B6DCD40077FE89138B5A2ED35E1B3D:\
+2FBE419BADA6D4BF3F6C7BB2A1AAC329:7FF12D4D8A9EF138
+08F0AA208F8A06C6292838A8CEE9104E:\
+44BFCA2722D274504AF482E9261CDB7B16918BE77A461B3B:F71A3B1AABD660BD
+878412F6255FF4360A22772711289FD351:\
+9C92FDDE178D3B6C895AAD1B8DC886176910B021D5B3AA77:1ED8B08898872631
+1399A0CD9F2778BCFBA9C0F7E7C89CA069E3:\
+5972F89D8C161DD30A409BCDBF43B20BB104E8A293C48FDD:0DCB3527035253A5
+EA1CC272D3725E4C5DC56079FA3C9F26A1373A:\
+D1B2FCC83CBF11E022C058FCB988CBBBC3843517F5E9D900:BF4B260909243B2F
+098DD47EA5784D307C115824CFC3443983FDF58B:\
+77DFAE7F46AF6DB0D0E5775859943E2875854A680B54B59B:5D869F3486DFE1A1
+
+[DES/ECB/OneAndZeros]
+:09B0A56E79B07C38:E7BADA575103632A
+96:C602F30C18C2B878:06779EACFBA84CFC
+6EE7:5E9FCE6A89418AEA:09EEAA55C12DBFED
+665672:85589647B376B1D1:79C5B2870123FA92
+7F862990:ABCEF68C99607B22:37EC3B88DF82E1F3
+39E551A9F1:04F6D20B0A25B97C:0BD2E04EC57814A1
+52BD5DAD29B0:0828E5AF2A1E1157:8900F77C54E909C3
+49EF95ABD932F8:A3325FBF67FE8F22:D5E02CC281CD647B
+B0F0218A6C30542F:E8045C90741ECCE8F90B5469B2E3B359:C4E91F2F3EEC7639
+80EE077361737B995C:F2E9AD2163C0665263CD11C7D976260F:AF593C04EDE5F7E2
+3BE81FFC61B21BFC81D6:59EBA86DB5734577B9E665C3D8BF65AF:77B77F440177BF65
+3EC3AF047C2817138C818A:B8C17B79CB5160EE4612CB5639D72AC8:B1E69181A32E7CB1
+0133FFE3ECDE48F98D3BDBD4:8CBFF36A7B691F168AA2D93A9360DFA5:D6492B1E5A936965
+638A220840B1ACBC24CE4F8B5A:F7A3E8DF04252727E4056A5AF9392DEB:404B2DC43EBF706D
+70197E5EE1D774B11005E8700740:\
+8A8A81862C313C7F904D86B953A6E5FB:8188847D3F21BB71
+9EB11AB4E97D026703BFD0645108E9:\
+D7D02FEC752ACD59B235441A4D6682E7:EE97A705E4E375C8
+87F1A7ED6D8C4AD56AB716BC8E02D8DB:\
+A6BEBCDEB9285A54EBCEF6F94142A60C0E5D90CCA6D256E3:A1B692CE93547EC4
+5448723839EA0910C29931F5AE6BA9423B:\
+AA328F5083DBED23B18CD35C4B4B185714DDDB02E81214AE:824BE4D31F8FF51A
+F454E24EFF899FA825534965855D2B1D03E5:\
+27D077F2B382CD8C6520346DB77D83D91BD5B08882203858:91B2A69AE61A53A7
+8C4BCB186170411186D2A0496051E0988FC83B:\
+E1C1D7EF18964E2EAFF84169252F94EE315209D5BC151241:E43579BA4E10BD39
+90CBEFA6E4F3D57BE288197E3E1C2055CE07979B:\
+37860F65AED6EE5312E3FEC4F2CF948A3CFCB27092A7B3C8:346ADDF6AE9E62D5
+9A5476706A45500C9AD6AFBA73E68E0355C11DFABD:\
+ADC2FACDD08D2AF9CB00E22209C109D0D39BDF9EBC1200E3:3C6A1A7DEE4FF813
+9EFBCC5E45E15F83D4A62995F4F8CAB036A63F1B18CD:\
+2D9C371F7CD55E7A95B2042A91C9B10025078FF0070EBC62:D584B755C7F2E8F3
+3758CF70B2A1A36BEB273545809B35C92202124A30A113:\
+C728B4B0F49233489B0453CD81FE8C07C68BD17661F75523:35732A4D581F153B
+00E0D8C19605363653DFA5F778DAF9E959CBF9BB7E4D3245:\
+BB44D4E603A6CD1EBB27E47FF7AD9F163420E58B97F1C7FF975B521917E7879B:\
+58780533BD9EEDBD
+
+[DES/CBC/NoPadding]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6:\
+0123456789ABCDEF:1234567890ABCDEF
+
+[DES/CBC/PKCS7]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF277:\
+0123456789ABCDEF:1234567890ABCDEF
+
+:FF4903E653AF83C4:46B534FBFFDAE457:297873B948A44B5F
+69:60FA7B46523AA51F:D581A1D0C70F94A1:C1DDD7447249EF80
+02B7:63C1C1EF79555ED8:A415B62E7E94CAF2:57FA9B2F95F57401
+568960:D0321483090F524D:5DCBE42DB374090E:B6215A095582763F
+B6EAF23C:88E289E1DE3E6451:8FE92291C654EC9B:0C054BBD31A9F623
+60A658CBBD:89BFFA9E36FF1780:DBCEE35E86088501:11A8928BC6D0D117
+7E10CBD9E95C:AFC5CDF559ABC6D3:72338F946012CED5:EAAA48B0C2EE2F3F
+D907CE88F077FA:3476402272856EA8:837FBB3167F0CCAA:CD399DD3E402F8F2
+9476E85B198C9AEE:1AF298A150514CA70D252F88271B3CA7:\
+308D1C02E7A4E09D:6BAA74F7F1A72E1F
+5C11285270E9606CDF:78665ABFE3DEF34F8BD55796825EE915:\
+126AFF39882542EA:51BADB479DE66A73
+D1D3D8675E42A4242FBA:E77BB4A24B4EE8C9EBDA4971C2E60D10:\
+0AE8510BB0FB3994:6C7293A8427BCB3B
+65026A8A41EDC1D880F6C9:45A6EF4ACD49F9F1D892A808FA7B6F28:\
+0BE9277B3504D524:E47EC7A77DB94755
+D72E81F4130107E396D5FB27:A88EFF91876A1B6958D52F99FE9B18FB:\
+2F03C36DE4F78E13:99FD2E8848F33FE7
+C8A3971EFDA18AF1B18BFAD98F:54FF90BD90F6213D761F4B3FF89A8DED:\
+69329672E546C969:294922CBE7E12341
+BB9A90F11551531DE512DD48270E:9BA7908E56EDB1BEF992FAEE40F5B1CA:\
+3007D71E86D8EAF2:D7E300E168F60063
+77D6C182E4DDD444D614BCFF98FB13:CB50DEC4728FC2F1A1A5DFB84FA1BD25:\
+F73C8C3355092EB6:2E0DB2552BB83AD3
+40AED22F93DCFCB1D734B7E4657DD31A:\
+66D17A6E9D5BE3281E857B4C7E497988CA684524FD994882:\
+DD006F15E727CB62:B256DC4FDB58451B
+
+BB25564C7EA1E5BD22016915805C27B51B:\
+B7CEB5F5ED2945F131064BBB9213694B19A04FBD1F138866:\
+DF70FF987582CCFE:88BB3B9BB2EA56D7
+49DAB8D85EA753CF4AE2ECE7A80F0784E42B:\
+D7FCE9E5BED161AD7D950E453677E5BEE422B7542AFC0BD3:\
+747E09FA9BA257DC:F1BBD406191DE0D1
+DC13A6ABAA35CEB3E6650F825A67942114AF2E:\
+BAFDB50E16C9FF4449BF336D410441D56E1E5335B54C9F11:\
+CDAD411D0FA80E9D:C83D55B1196958C4
+A8896D88907AD77AE790828C0A3384C1614E07D9:\
+70A9EB1C11BFD1B1D68C20A6B72C869DAC5372A8ED46AA07:\
+642D12C591F6A4F4:C17D0C69067AF296
+B3FEC4CC29DC1ABBCF7D86F01D2C02C2A723E7C2F8:\
+48ED5583A04D333FFAC9D6462FD96BF79222EEEC70A6AE70:\
+62C62F54C426C59F:CB6252CA271FF303
+AC0B4D5752D2009BDCD42314D9723716294146424542:\
+8A284713F8C9873AD5F558B995C5A67A66557A52601975D1:\
+386DCAD5EAE86830:48153B966C8D686D
+EA331F6E518A8AEAB2EF0A4E92E0D198DF5DD0CC74369E:\
+6D3D7DE9938935F9FB9AF839E416EF6F842F2ED827334BFB:\
+782545EA65D89B01:C2CE203020AABB0A
+B292D3A3FDC5D709709C87EF91122761847871F9B4E33426:\
+21DAE17D157192146B52C49D90F898B25D0D1DFE677E8CD5B568814E9C6BB6A8:\
+ECC650E1ED1CE8A0:AEBC43AB811AB5F1
+65026A8A41EDC1D880F6C90BE9277B3504D524E47EC7A77DB9:\
+A3B6404C4D87F72D5E0995D7CC20ECE742D9705D48524CFA2820317087FAF578:\
+4755B8639FD7C8A1:4152E22F14BAAF0A
+D1D3D8675E42A4242FBA0AE8510BB0FB39946C7293A8427BCB3B:\
+DB621F2FAC9A924C83ED0B9E8ACEC9F1E23BF3FF2AD6EFA814903F2CE293107B:\
+92A18B78A25C4B7A:C3AABC68CEEB22D9
+C8A3971EFDA18AF1B18BFAD98F69329672E546C969294922CBE7E1:\
+940C610A41F04E7D9BE0A74D5D00FE97A2647D3D16E9B76FF0DB5BBDC197C82A:\
+2341239C09C73427:C4D5B2B6863DB060
+D72E81F4130107E396D5FB272F03C36DE4F78E1399FD2E8848F33FE7:\
+7D495CBA50C4127347E3AD29E3B8C098A3312782E3D45ABFA1621F64BF8B8A06:\
+166EA8ED9D29E1B0:2BE993C1BE8FE9ED
+77D6C182E4DDD444D614BCFF98FB13F73C8C3355092EB62E0DB2552BB8:\
+9D926142271E814BA4603509187C9020DAA0D50F15AF6E698E384644E9468C11:\
+3AD3301094B2F471:8638489AF44732F0
+BB9A90F11551531DE512DD48270E3007D71E86D8EAF2D7E300E168F60063:\
+44858416F946C7FBDFFD720282881630803803AB91CEAB1AF4F68F50E9C16DCE:\
+04BBFD95AC12E6FF:30CB120D13391C44
+8EB8FAF49126AD5B8A0AA6DF8B52DBE50DD5AED271641EF983BD650DA69816:\
+5B4622F1C4FAA817EE3AC181B969A7AFED7117E23F68BC6017519A7D1399CFE9:\
+35501029E137D63D:C1E0E3A06B357B51
+
+[RC5(8)/CBC/PKCS7]
+FFFFFFFFFFFFFFFF:7875DBF6738C64788F34C3C681C99695:0102030405:0000000000000000
+FFFFFFFFFFFFFFFF7875DBF6738C647811223344556677:\
+7875DBF6738C64787CB3F1DF34F948117FD1A023A5BBA217:0102030405:0000000000000000
+
+[DES/CBC/OneAndZeros]
+:79FCDEE6F5A94E74:0741219814F4369E:DEFD8C15FEB10458
+61:AFE5BE1DF47E6958:3FAD1BFA365F515F:587FBFB91B510842
+6162:FB193EF114B131AD:C6DDD3B4CFB3BE35:3397BADCFFA5CD9E
+616263:DED4DF8449FA9AF1:39CD739C5FD324F9:7BA9456759F9D9F4
+61626364:90D644584B46BD60:0CE7C79E562BB380:FBFE8D32A056DF18
+6162636465:2A70B1E3D641EDA8:1FC96BC8537C2BF5:7D14C2BBF4FEBFFA
+616263646566:D46AEE73FFF0871A:3EA0FEB6F73FA584:F7EB4F725333CFE0
+61626364656667:98FF67221E6870D6:938DE716B9569292:78C186E4F57CFCBD
+
+:4543FC96F4B8B122:819B1D2932657450:BDB02A5EE4B87D94
+47:CC6E8C070695E305:0D41339A489D8364:BFB7F817CDEE3C12
+4749:6FB34EA238CD511A:855595B620EA4AB0:39E6CDE9483737E0
+94A320:C2D8EFE2B7E89888:8DF23DFB014D257B:4C3D7238A857AD45
+621F374B:709D24FE90B62702:E6700FB699FDA882:3BBB4962D510E0B4
+A8A6EBFA30:9BA4AAEBF47F2934:33154E7A3744B1F8:9A7CFF1E07BE5EE0
+3F15A3A21DE5:32857A77CD5F0837:D5B9736A8BF39C52:9F9C1DDF2E81D3B9
+13B01FB8554A61:42F700714759E23A:AB8AD1DC2B5E59B5:AAC43EEA7CB833C6
+875F37E530711B59:8A46DA643B1D2782D0DFB5210AD2745E:\
+AB36FE234780AECB:E573C3E555078997
+3C6D4C4C7D419EBC5C:A51F4FCD2EC5EA235610B21F77035E0C:\
+9BA56B459BB4EC9A:0F779E7C90490B73
+D6EAC1E0BB495865632A:E7295D7EBF14D4401639A62B1A59B963:\
+5E5CEF1045C62E7B:1B4CCFB80E497471
+AC0B3DBE737AB8DB9ECC26:26C9D2560D7E1B8247EF2B13217E1A8F:\
+4AA17F4FE7CA759D:7BE44B5716CC3883
+97032F592A72724D4B6BDA35:66F27FB8B1A5E3AC7EAFCE2266D6C694:\
+C6913279B07861CB:ED65E32206546915
+F8B7D69BAB9A491010D7B41C7C:9F86FD8E20FA43F370B4BFE50735B62F:\
+267267DD1B7F94F5:F6B7788B39D47060
+D87C1E74D45EC6906392F3DA14E6:75F8450FE5EB0294533ABE2464248209:\
+6F5F0F3DB8D7218B:2BFF759EBBB0F0BD
+BB6A3D9A99965DF79B4CE7697A281E:16B73C7FBA6F359B582921165E988021:\
+6C6FAEC81E8976BB:9519212C97D4283D
+324A67F9D21E72BFA9B47B6D44F0A5A2:\
+08E30F789193EBCBE48D85AA29C9CBBA77DE5065FFD7E1CA:\
+EDC12C2E333DA4D6:4D2B65F5A40434D6
+BF0640B94C6208A3DA03C7EFF219086590:\
+2DB26514369B9A739631BE6B63E928D437EB39C3641E7C8D:\
+AFC1F8670347B23E:CF7643DE09109D0F
+6796890753E748AF37ECE642392E6F4DF6D7:\
+1157FCDC653E1644319CF7933D05D60E81FB2F85A6503BC5:\
+FB90A71C36341FC0:E2854536F1ACCC7A
+3E13EE1BCDB631B81D58505B471278FF1127D3:\
+E8A9BCFF29B6C0C5CB60A73C91E480AB98EECD3BB8E9A503:\
+352C22EE6D1ACB80:2FA6DDA5E4F094FF
+CB286DE6105AD73D734A7E03F256556C9BEAA513:\
+423EAFEEC86ACD6807D575386F65B9B6488B51306D762E7A:\
+D2C4D489B222155D:FAB0A2C5D80FABE9
+5D047DF0F33352B1CBE1C0C6F48EE8DE30A4AC4E5A:\
+4A73158C12322376A5CB9F6A88BA8A4BB36C5D516D3112A9:\
+041B7EE6A1C92B4C:FF04A9048299F7B5
+CF0791C7717083D47546AF26317647F3E9FCA95E7228:\
+53CCEF2E488E717B0BCFF30C99E257C36B57DE139778CD3E:\
+D7D6ABBC6B3F0D51:6CDD58FDA4C96D27
+F51232D422749E5835E694EFE010190AAB2B8DDAF5E7A0:\
+5D35E1E183A8D3C3305DCB01C1751CCCF6FF6D7BE9A53C8F:\
+EABE42DC124A4526:3F57581479CDB2D1
+E0184489D98899102B9053D27B87C6F6C5D836BBFF93029F:\
+C10EB94F783DED8DF7AD46C605042CB610948CBED32E5E28924A998A1490AEE2:\
+4E6B9FC17A58A95A:70EDE349767C59A1
+
+435255534820414C4C2048554D414E5A:\
+69E0288D17900DA45557053EE79CA771E90CCB8D28198E0D:\
+E3BB33E82BDB2B84:593A08135216F478
+
+7777772E6D656761746F6B796F2E636F6D:\
+14D752E45A8D28EAB2A5C8E0A12E8A88E804451282F62CA5:\
+458FD140271920A6:605C41F0790BE4EA
+
+[DES/CBC/CTS]
+9F8789F30E3ED72800:48C597491E0C3C1706:9076D5A743FC9721:A9A6C2AD38E682C1
+CD8254CBE545A5E9C714:2D6FEEC8BA6070172D37:0CDE4B75FE1C60B2:23034593F143AC0C
+
+AFF70EB1F349CCC1584D88:F22A14BB906DEA068689E3:\
+911DBDA323F5B30E:51D47FBBEC9C4204
+
+A0CDAF182FFB93314FE439F7:762C34D15E861502E7D5C77B:\
+27399EAD16C76FEE:DEFE481F6C7333C4
+
+3AA32EFC2AD3E7A81879C38905:95D71FD889E597A3F52EC664AE:\
+B221AC0CEB5AA606:1C01DA1D9AECA0AD
+
+58FB7BF8F6A8C26398053B5AD1EF:4B3BDD1C187FDE4EAF0EE05B2A60:\
+710931E0736D16F3:378013D6D8779222
+
+1E73E7D1B82FC519E7D6778CBD9E6B:A532BC6B9C5686C563B59E6EF47F8B:\
+BAFDA9C3208592C5:1FBA498F337A06CF
+
+63B0ECA8495901988D536A8764EF4DE0:C9E597C818E5D2E8D525744D1E58BAE0:\
+7C92F7577E9E5821:85AD46CB62C42A4B
+
+3B0692000B6FFF4622977B62358615D8B5:8110C505835BFE6AEEA9D8877469F677C5:\
+EAD7E457662B61A6:9BE7F359CFD116D0
+
+04AC84288F0BE9BBF06A04E2DD6DE213734C:17679CD3AD54BAF73FCD7F72C518F0B4313B:\
+31924C5C146EC54F:DBAF3718A8B17FB2
+
+5D8B2B8476827B801B08098CE6F5E690FCE32C:9461193572872EDF01E2266E56CB72A78A19C7:\
+09CA9A9F64DD9CDB:6B31656961B96C3C
+
+F21DBD30623DDD0C3137578B1ACA3D048C075FB8:\
+24657394EC233B6C7076CF6A33FA53B86C98CE74:3B1E7CEB3483A31E:B3247C1AAE6F97DA
+
+A60CB3ABB1A52085A334641E9C26FEF09156E7CFC5:\
+FA9F81191286962E5B710C20C99983916AF173C8E2:\
+0C133B1D431666B2:9D01A2A546DCDD89
+
+800301AAD00F8F895B84218BBA09246DB23230AF3CC3:\
+11ECD036643726BE0924C4C401058D15B63E539F773D:\
+9C6C9BC335380837:EEC9907B66BF8F8F
+
+5467CC7DFFCC6E60807E09AC80CC0F323AFBCF3F49B65C:\
+24788ECBB92BC763FE238037EFFEB0AACAFBF106DB081A:\
+AFBD3EC2FFFB2855:021A20C31816F20D
+
+B1F5B889B9D1E78BA612BD7941D5812444D3510AA83D0B72:\
+3266DA8CAB200E3C171CADE8AC651D44CDE2902EEBCF0F5B:\
+22612A76D074686F:6435B2BB76583F97
+
+9C8D3469E24F2855E477222E3342136CF67673484603EDC5FD:\
+8B4405DC91225416A4A3F6838C72CD0F9743E5F1158AFF7DCD:\
+8DB74F62C79A83B7:C4422D5E3E95C4BA
+
+41B52662B96E82080D704718332453E8A3FFE3160C48A954244A:\
+1AC7CF83548D910658FF048174904A465D5F401FC585F69E96A0:\
+DF38AD749B054C2A:62DF2A547372237B
+
+BBEF9A510A56A5595612AAE5102CA399C2954E5C0A6507B7E30137:\
+525AB2A4FDC61E88D17263F7726807D66719D0E33C8D97968FB00C:\
+D7332D48E4A08E73:BF57A1ADA757E6D1
+
+52407DC79E76D93EAA0AF19D9910EA4B101475972530E5DE6AADE1B8:\
+22FD7F774A84EC5B194B9B3159342F6DFC0EE7F3A82BD2DBC4551BD6:\
+BB99706196E706BE:2CB49529735604FB
+
+E69039A548D7C922BE551BE70A404D8BC347B5840EE4472E319C7F9430:\
+1D69B5C8EB2BA0CC8E418A24E7F397C54CE69419048E0EE7ADD6142B2F:\
+4F9BF676A7F95396:64DE012EA4EF1853
+
+20081F83FD34060842DF4073EA8F5B3CAF0B289EB25FBD807050EAE314CE:\
+FFDD0C2735740CB998DF8ACFDFB2C80AF3FEDB07E01A8795FAFF51098730:\
+817F84ADC89EC13F:E166F32F3549057F
+
+6045C8B00A0D1349C6576AFCBD95435F90068C3949CF32FBD2190C3F906919:\
+C99CEF2CC47F6A3CF8588501D20B91F99CAC725EB2D35DC8EC9B1BFF3FC193:\
+F67E4196CC6DF276:EAA8CAD5C86EC7C6
+
+A1FA682C81629A841AC8D1B371053997F4BABEF1D83D236AE4C77086DA24DBF9:\
+2074FB01FD3D750EFE0548BD2C51B127188257F76431B71AE3A3A6AFE7103822:\
+42CE0D2CE01F9ECA:71CF9AEB127BF362
+
+541DA0919992A383F739B2B601B92DABD3F4AE1583D607EF692C010E7E00C21967:\
+92B790B103A7664D2508D08E21994EF3705E6F8109D83E087878085A2B5DF354A7:\
+4466C9BF5B474B21:0DF3DB1AD76656D6
+
+C909604CE459AEE764AADA4203EC6AD3B34D2720890CEB8DBE38CDD955D1BED744F4:\
+602D9A17F224434CA5257433E395A8EBF714DA7A41654063F7791051786C21C6B2C5:\
+EEB3132A403F49D5:18BB520F687B1841
+
+2D15B7F8554FCFA780172E27C7658A2035CDDC09DB71D10B9480C5345B250DAD722C65:\
+2ABA254E087A44939B17C0B013FD0D2515A81F552CB833F83E497B0894DDC9B66DDAE7:\
+6208B08A597F770A:4A71971DFED24F2B
+
+559C03E98875616C541C1FC689D006ADE4FA75C79DE33DBFA5CE7829106A6EF2199D9496:\
+8D1C902E4DDAB97D67508E13538675BD45E59E21D40432A2D2A5E9243AD30158AFD5AA69:\
+A25EEE00A0B616AF:DF78562B7DAF5D2B
+
+575CB34C5B252FC26D750583111B2F0440B93317119BE9ED482A0FBFBF0B6965C8BD672B6D:\
+BAD166C1EB916C9C12DD3134E4F2A85F59109032E85A6989E581AB8834C6CCDBDC5A47E7FD:\
+9BE282204F105A61:F7F2247110CE2237
+
+82EFEFFC150758BF33700D7E54FDD0660D80B023B66DD10597A08BE9A5F26C9F71A00FE72CD7:\
+95EF6D44507187386142436237DFCD9F5BAA7376B71CE10D6D47DA1D7645F790D1C30FA84131:\
+86543EB8BE5D6E63:988C92F9C6E7F0A9
+
+E3411B122E35669226D9A9676C5A735A645C258\
+8911B5DF3F00AE88C48FCF91CBED0EAD776511D:\
+D9DA0C4ED498214DE38DFC8B6663DC231AB17E8\
+39819761952446E7BD4F3A4D5996D843B1A080C:\
+61091390D89E195E:55F954DA491D0487
+
+82905227D786AA54224A9A98EA663F11765606E3\
+7449774301E9229AACA08D8AAF88CFA055EACF46:\
+F46290E04EF671B0F1B40B6A3C957E416EC02401\
+49D8E2DA20A936E9B65DF371BE6E3507C1075823:\
+46656F1BAC4034F3:B0AE27B323665888
+
+0132501B732D145D7B44D0CF92493B3FD7A56DD5E\
+8762DB54BCECFBDD68E9843A1D0BD0F20849A3756:\
+F6253C8998EB2E8A898661336F398E555241736B9\
+C0B5B83500121F96A3C85EE5BB6FC3489BBBAF3B1:\
+1C70A4D7A305675B:05131A93D393B7BC
+
+374A3C384D246E0703BC69704DCC2EC8E8B4B6249B\
+B9690A13F50D1723CE2638330B61D8F7328A8FA0E6:\
+6BC4D82EF7CD9780FDAA3FEF10E2C786AAA81FD28B\
+62F9EB47A2F25752A0E262554976A3BA619A02462E:\
+27B33E69D3BCC393:7166FB734C6E9095
+
+BF720B89414128080AE8A26CA4429BE5BC0C2C3FF51\
+E29A13A8DF38B836817EDF289189948D9D8699DB418:\
+4717A106215F960253C5CE8B091703C4235078F444E\
+52B85E64CBDB4B1F76C7AB07346112FE05AF4356BBC:\
+593C3910E6A31016:B4F04B72B87551FF
+
+3B7AE22299A6A9C4CE1E553821272605ADC48B7D8BEB\
+B81E1C81F3C45CCFDCB6452989C314E1563F79D29824:\
+A48524FBFF6C0102E72A7756C488C8B317B33F7C3A5B\
+7DBAC9B5B2F3D0245837CB6E4622407ABE3E6F9E6947:\
+201DE422F64787D2:1ABB95D29DC719B7
+
+D52C0A8CB50DA55BCD2DF81FD7FDE278862A60417FA2E\
+3805B99844CBE4B0DBCD062B233397CD3FDB7B05075D4:\
+92377CBF81BB2682ADCD32DF7054517FA3E3589A51042\
+0F6BE4A20E64FAB3D3F5053F8A2FDA8DCFE81BCDDB9D0:\
+656F047010D196EC:57008D1C6490B4DE
+
+282651F1695450455B6524AF1E2FD0C37BFEC3C37394E0\
+996CE31E46C198B24949E7DA0D33D2388B865A946EA2BF:\
+B76BE4E8CFE9B2056E2295CC3883CDA8F17DF535A51EDB\
+480931AA5BE0DC2AB2101BDE55BC8E904EF6DA53AE525C:\
+113094CFD2CC5B7E:659806A7F5D7EA7D
+
+9ADC8F91CEABEA3DF51FE620533E848233BAEC6DEE4DC0F\
+C6F83843491AC8F614DD036616EC8A07CE5C87A13422E88:\
+2AC49B69F5F2798FAA2726A26C4444EA6ECFE9C632FDCE9\
+D15C7A9149FC1FCE7E9D52AD5844A04F504414B5D650771:\
+58077FC3CC4757F3:6E459E39F0AB37E1
+
+B6D6A97A8F856E1F1652A0C0C5B4F0CF65A98BE4B8CE2775\
+4514A2104A97775326312680F5F0D209ADB2239BF8C6CD08:\
+30DD92C5768A88EB8A8FF3FF3A4E0A2DB9BE7C9C3E358591\
+DF5807A1D4C2EEB46408CF1329A20A2A0D9D810F89CA87C3:\
+84270A179A8FCBFB:230750471B258152
+
+F630D0A6CD851E68D6779C8D493BA6A3C86618A97317E3CB6\
+9CFDFD8E792E1C7E8CD786F0FBDAF0169C430001A6C8504CE:\
+F9C32B13EA6A1C1D2BE47A89CA46827840A8D5676B658D74C\
+00F36F19E7285CC5BED7A81450C70DDC9D30642EDC266AE4D:\
+2360554BF329A8D7:B58908438B0169B6
+
+023A29F413E2008EFA90CFEEA4C5E95D05FC24AA151B897662\
+476C23C88928A50D28BC3A5A77A2DA6EC8AE91B579993AB509:\
+84D24A62307BAE86B50E5C3584F3648D64CCF3B60C0C74F947\
+116A2B54DE75646CADC8289F78161A1EAE8880AFB83248A57F:\
+7DA9A637BF1880B7:E1B8D1DD907D13D5
+
+# Aka DES/CFB(64)
+[DES/CFB]
+5EEF8199471C2A7EF97509623CAE32C35A90245B70A21CE36E:\
+658B25E25DF23948847AFA4C9FFDD5B3DDF35D801CBE945168:\
+ADD9CE7BCF48C44B:0F90E78835BA3183
+
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+F3096249C7F46E51A69E839B1A92F78403467133898EA622:\
+0123456789ABCDEF:1234567890ABCDEF
+
+D14FD67A9B4D7B0F65B7CA3DA91741603DA446:\
+0CB8929A854E61AB3BEB72CE0F13BA328BA73A:\
+7132D895529A7AFF:FA1FE8F921706C75
+
+# Random tests, 1...17 byte inputs
+16:E1:F51CF13FD55F33B8:10E61C7F8276132E
+B8F7:9F09:6A2306397E6399AF:6791874E16642DD8
+914AA4:1CDDAD:08D3B08CB02E2547:B35072A53FA36190
+252F0616:E22A706A:454A9ACA108AD24C:64DADB33CCF1DEBD
+F06F376C6E:C2F054E435:087FC9F0B8BE08F3:5E511251C063B3C7
+9A181AFEC04C:C49218C8A25B:FE1EA0F0AC5F2C02:A247E69CED4A2BF1
+AC465CBD745341:768B6F5BFA9C24:1E7C7274307EDB90:AFB634941C366C1D
+52BDFD51E3434E94:C5D84483756AC360:53E241E43AAD03E7:BE0A4AE59056D8FE
+A62C02059AFE67CD7F:032A99BE4DF6B63F97:487C9FBD140EF278:43F88DE155E98523
+32D3C8A283257F6276C3:BCFA26EFE2D93A4B1364:8B068595D5B79177:7129287761D94D9F
+17CB11A60F880C16D6CC3A:3DC099D927B8AA66B2A5C8:750C87995AFD65EE:A61398FFF559FAAD
+EAA91CEDE4EFC60F02B1E0EE:75614EA2FD5474FDFE3A5612:\
+08A5F56200AC9300:9F9ED0928B8CD2DD
+68DB8992E91D759256AB373748:9D0E14F0B2BE2D3B47103DA75F:\
+B11DFA915AD86FF9:3885ECF48A611DC5
+D75ACDD3E4040DFDA924CE09E627:A878CE766412A9C387AD61642FB7:\
+FBF9E6D9344B0F2C:6917F8FE1AC12101
+38B667A6E4458C8732AAE6F4D0AC36:5BCFD93D6B4B45D9D0D03162FA8FB9:\
+8616D2EA6E6106B3:CFE4DFA7044F56AB
+0B439A72A4430B3D15E234034BA2C066:1ADAE0A4A0D582B70B60ED1C859A07B3:\
+E255E4A4C3606081:3F160DFF918C3F78
+82E27182FC22CD8918DDDBDB850034A4F2:9767881B1909DB5E146CAAF5FC6A118814:\
+B9CDD5442E1C7FD7:5D1B1ECEB7335274
+
+[DES/CFB(32)]
+BF28A5B2F3FC788F:13799E52F0BF6B0E:44FD92D1AF17DA22:5EF2AB4DE2C32258
+
+083F1997FF19246C41ACC1EE3A18B489:31C4C90B034B75B21280B60751E60821:\
+75E1E4E29E6C9205:40D4F3DEF6222186
+5B38FD10CAFF5611114CAC8033DE01DE:6434BCA36287C8FB3FD0BAF32874C740:\
+875D1C19A20E6740:E2912582ACE9830A
+44D4480CE326D9583E6BC13A78D7DE03:7D52C87B2A0D33B3A48631EF3184397A:\
+79FE005333D6437E:BDBED60C0E069960
+81BE542AD00FCAEB34945D89B4F29EAD:DB0DBCD722960D54B531D8AEFE1B26FB:\
+FFF6D6B146354428:2EDB634B4C7CF4EB
+E0A787DA56534F407586ABA1736C9DDF:34FFCFE532186F84EF57E0CB5AFE654D:\
+330AAD15FFEB8E78:826F429D0F342F43
+302C49BF921E0516261F00B2FA2E96A6:19D49D5A54C8FD15EF317AFD5A87EBDE:\
+F15BD42AEA7F38FD:5E10F9CAF0730C4E
+
+[DES/CFB(16)]
+6BFE8F2BF363D3DA0A2CDAAF2D7E1D44:8D407E5A8B5217C56B8A88E3CE478B85:\
+302A7B0BDB8669FF:47C89DD706739D23
+
+A1A3ABFEB7BD450F:D67A4F0C8DD67769:4243AF4851BF8400:BE0C9A3B77C26C9F
+D316B78F0C25C56E:E8BEBBADFFE18E2A:4F05484FAB8D47E7:CA6129BC11056056
+09BD5550EDD99666:69C4AA4C8B88370D:04ADC5D1401848D3:5DE8A3519C477771
+7C1BCEF78CA58DAD:D14FF21AFF121E8B:B045BACEC002FAAA:1716B53D7A87854E
+2671E5DC0341CCF4:D618365EA3287474:8053149DC51A7F4E:E18A7936211291CC
+
+[DES/CFB(8)]
+CDD4BAAD59214E97:DFD8C7EE7485E30C:3400AA949E053449:2ABF031C3DD08BA5
+0BE8FF9BE975CE5A:FF834A9315DE58C0:CA2CC8DCAE150ADD:2AE7960241E5ECD0
+772AEBCE3E9DB532:E31732388E069526:9D2A486812B8BBD3:AAF8C0A145A00319
+B6DD299F4D45C378:1A5DE72F6BCEDD33:CA9CEA52658150EF:4DF0F3A7B49AF71E
+A5107583CA3CAC3B:D5541A94B73C2DDB:139D5249F1CEE0F9:1B3212F80A91A42E
+24E224330C88791C:177AA6BD3D885167:D8D3F1611C2AD43C:7B4CDFC2344DDABF
+92C51FE490D57CE8:A6ADC1AA622BAB1D:DC24F740905DDA96:5C307E5CF2C73D46
+E85D092290F3A53F:A1A2A831C55F1454:3739A5D446E8CEA5:BECAFE19A645F489
+CDE5CDDDFABED42E:4AD6E96CFBF9443E:98ABE3C8857BE8A8:B4A9E4A90C4D08D0
+6614A9AB1E3EC578:32B6733A61D38CD0:51668D4A64FB31DE:31E42E3EFE3ECD65
+
+[DES/OFB]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3:\
+0123456789ABCDEF:1234567890ABCDEF
+
+B25330D1CAB11FDDFF278192AA2C935A9C7745733E6DA8:\
+39B9BF284D6DA6E639B8040B8DA01E469DBA4C6E50B1AB:\
+F871822C7FD1D6A3:B311792C8BC02EE8
+
+73AD356623A1D6E0717E838B9344B4FFF21BDA:\
+0C06E63E9E81D9976E16D2009255F917797D51:\
+5860F4A413DE6C68:527A1E050A9D71F0
+
+08A6091FA2987FDC682A8199A6D6BD1F:640B5033DCF26873FA8A34DB644F2BF2:\
+3307042DC775035E:99DE32FF0351509B
+
+[DES/CTR-BE]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75:\
+0123456789ABCDEF:1234567890ABCDEF
+
+11919B328564DA68D9F4216AE1B4FA7C46AFC7AD5BB867DF1834D77A3023ECAB940725AB:\
+F40235A0B8B2EC0B53F3C0D8799497463638AD0CC3E07F0E8B8B0DC7605AE6AEAFBA2A88:\
+A67ABE525A0E5AB2:727BECDE9FCEA20A
+168A502D21D71F3BEB702BBF02D3F6D04B72EFF2F19EF01D217CC7AA739A67466AF3B14E:\
+3A73770D157C23EF8913D874CD92DD36C465679B2BC691DAA0DC6CD4591C4CA44D5D69D8:\
+CDB366CCD621D62B:1ACAAC3F760C674B
+24889A268E11AEF80852C4FC4893DBEBDF4CB06115FD533650CA39A639C659F47C3D5556:\
+782B24067A2C5D61BF6ED2E980F6BB16A0A6E0B5639B4208AE273C0BDC0311D65464F217:\
+EF510AA740BE98CB:74E74E01E5C72084
+3078866926F75D18239A3DA92EC9EB88D18393440B47D46A49D003F2C3B5D51C1CFE3FF4:\
+DE4D9632BE88235D717B36DE4C67B81CF3331E8925726CAD1BCC05126B87A6CD5D5DE3B6:\
+E8CBB756DE4FDEB0:AEE751205CABA9BE
+4602C97A25AFB1746DE8BC1A65AE0B635ADDAB9547A99421AD86AFB087997ABC1458F0CC:\
+754BD27902EE4248BEEE65D2BB035C9139F98735C85603BA9565EDAADE37A7FE29833DD9:\
+B050B286E47C6E6A:701F72AE37D31F2B
+E344E0C2E45990C451C75BF74406821B99D4EA5F56F67BB2F9B0EA52FF5D1BB25D82A181:\
+1A23AD101A776F902B8DB40E273A1F5EAE8AA1E43CBA52546F2EC50EF32960BDD05101D3:\
+445A14B76AFEFBC0:EE2DD8860B75788A
+2C3A117378B8DB1287CE8FE084EAA08EFCEB253DD4A92509EAD154E6AE483E25D2B790B5:\
+75235CB3E2BF7DD3ED893DA93AE25D7A34D43521DB620E2BC9072159357010E6D81E5884:\
+4B1B62B9D6B8F54F:036CC5145BCE2A01
+FBC7E48930ADF4A36DE18CABDE25ACDAC8F9AB727E3AA69FE8EC6F965C6E14EBE9AE437D:\
+B271913A8A58ADDF3C89132A15DF1263B63018CC8EE6763E6FCFB4DD5D4AA8EC4B3E2D78:\
+2E0F06AE7B1C30D7:05E144D6DB9E7939
+940C3FE78C56A0F922FBEDE7ADE31914C993BB84F5BC1557E5F8004CB75D7D339801FBBF:\
+9615A71536135E50946A8517E72A980CBB2378A3286F08E76E85E5FB62140C9B3720C7C4:\
+E6E85EABE538195C:B86615CDA5C9E9A2
+256ABA748AE0005A5F99F1C96F8A197E3867B8455A4D6BFD6795BBDB89062B222E6B0DD7:\
+2A6B043F07ACD99141C7AC616B7F89AB7E52174A41AFC1FD0C56BC77B9C2EC9CEC87A0A6:\
+9985CE7E0D79CFEF:25D1D57C3A6936F9
+44AC3E1333DE5CD00475317CBAD26AB4A812180DAA7405556C41335572F5A236C37CD36F:\
+155E5B86FC06AD433DAEFA05C329BC1407966220BA91EAC2FD32B35C5AD973D94A0B8792:\
+47550AB0F346ECB0:1C42F4559385E11B
+9DEDC376CFD97AE823AB2E0CB0072DF26DAADC4FD9316C7E8F4F796026DA9ECB8ED69DCD:\
+EDE3E69EE5B55AC758EB39E70E6533CC4D89C148F6AD68293E743CD82B9638F020EE589D:\
+098EFEE0D594C332:88D9C46E992B27AE
+
+# From NIST Special Publication 800-XX (prerelease): "Recommendation for Block
+# Cipher Modes of Operation"
+[AES/CBC/NoPadding]
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+7649ABAC8119B246CEE98E9B12E9197D5086CB9B507219EE95DB113A917678B2\
+73BED6B8E3C1743B7116E69E222295163FF1CAA1681FAC09120ECA307586E1A7:\
+2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+4F021DB243BC633D7178183A9FA071E8B4D9ADA9AD7DEDF4E5E738763F69145A\
+571B242012FB7AE07FA9BAAC3DF102E008B0E27988598881D920A9E64F5615CD:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:\
+000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+F58C4C04D6E5F1BA779EABFB5F7BFBD69CFC4E967EDB808D679F777BC6702C7D\
+39F23369A9D9BACFA530E26304231461B2EB05E2C39BE9FCDA6C19078C6A9D1B:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:\
+000102030405060708090A0B0C0D0E0F
+
+[AES/CFB(8)]
+6BC1BEE22E409F96E93D7E117393172AAE2D:3B79424C9C0DD436BACE9E0ED4586A4F32B9:\
+2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D:CDA2521EF0A905CA44CD057CBF0D47A0678A:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:\
+000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D:DC1F1A8520A64DB55FCC8AC554844E889700:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:\
+000102030405060708090A0B0C0D0E0F
+
+[AES/CFB]
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+3B3FD92EB72DAD20333449F8E83CFB4AC8A64537A0B3A93FCDE3CDAD9F1CE58B\
+26751F67A3CBB140B1808CF187A4F4DFC04B05357C5D1C0EEAC4C66F9FF7F2E6:\
+2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+CDC80D6FDDF18CAB34C25909C99A417467CE7F7F81173621961A2B70171D3D7A\
+2E1E8A1DD59B88B1C8E60FED1EFAC4C9C05F9F9CA9834FA042AE8FBA584B09FF:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:\
+000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+DC7E84BFDA79164B7ECD8486985D386039FFED143B28B1C832113C6331E5407B\
+DF10132415E54B92A13ED0A8267AE2F975A385741AB9CEF82031623D55B1E471:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:\
+000102030405060708090A0B0C0D0E0F
+
+[AES/OFB]
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+3B3FD92EB72DAD20333449F8E83CFB4A7789508D16918F03F53C52DAC54ED825\
+9740051E9C5FECF64344F7A82260EDCC304C6528F659C77866A510D9C1D6AE5E:\
+2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+CDC80D6FDDF18CAB34C25909C99A4174FCC28B8D4C63837C09E81700C1100401\
+8D9A9AEAC0F6596F559C6D4DAF59A5F26D9F200857CA6C3E9CAC524BD9ACC92A:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:\
+000102030405060708090A0B0C0D0E0F
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+DC7E84BFDA79164B7ECD8486985D38604FEBDC6740D20B3AC88F6AD82A4FB08D\
+71AB47A086E86EEDF39D1C5BBA97C4080126141D67F37BE8538F5A8BE740E484:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:\
+000102030405060708090A0B0C0D0E0F
+
+# From NIST Special Publication 800-XX (prerelease): "Recommendation for Block
+# Cipher Modes of Operation"
+[AES/CTR-BE]
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF\
+5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE:\
+2B7E151628AED2A6ABF7158809CF4F3C:F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+1ABC932417521CA24F2B0459FE7E6E0B090339EC0AA6FAEFD5CCC2C6F4CE8E94\
+1E36B26BD1EBC670D1BD1D665620ABF74F78A7F6D29809585A97DAEC58C6B050:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:\
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+601EC313775789A5B7A7F504BBF3D228F443E3CA4D62B59ACA84E990CACAF5C5\
+2B0930DAA23DE94CE87017BA2D84988DDFC9C58DB67AADA613C2DD08457941A6:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:\
+F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+
+[AES/EAX]
+:32E55CE0C3FAEA48164B122C1BE22D85:\
+C61A0851AB4E515D11525B92E2B9D850:C825FC7C4D539DC74887CECC70884F37
+
+60:710DABD24D400F3B6B284EA47F81EBBD26:\
+F956B879EC7F807F1FCB482B53623671:E64F90B4619D93137E6237929EABF297
+
+A62B:C91C09BDD89CFC81AA4427FE8CD841B5BCAC:\
+8A554F339FC29E76EAC079676463722F:86B95FEDD6827A6EF8B17E6C4B2498D5
+
+E67238:B0DC7388ADF2785A4B898443655C356695BACE:\
+A3EADDED8E4A7476DC783312CC70F878:8559F44BACCAE49D39DB6A77C1DCB065
+
+29D564D8:A11BF86AB2881AFBAAD85D2B8313203262BB0ADB:\
+C1F38AD3298EA3DE3204BEC244866534:43D1D9EF0769CE901A7F0943556D1B16
+
+37863FC2F1:89296DEB6C1C3CEFD643926F474568D71C4D52305C:\
+E9C35F70B9D294E9D78D904AEC528E99:EE28B45B0F136E06B7CD3D3D0D002EF6
+
+9678A48724FF:2013CC564BF1077B300341089DCC23F4B20CA9B1B24F:\
+84298DDF4FAB1B8C2608453F0FEB0BAD:3035DB091BE6C0C3E3563B87DD5F8761
+
+C6D04D01D2F78F:67BF2D417058C7A26F446E13BA65171CA34AFEC3F842B1:\
+C3D1651AB7A5DDB1E815FA3B91A2EF14:C49440F324F5F31DBBC46ABC96624B5A
+
+26C63A9C769DB4E7:7A1BC9EEC765B7525AF601B682DF05B681818F6637A64EAA:\
+A342F5559FB3E861BBB3DAD8CBC14964:489EB99930FF1057C54AF33CE7A7238A
+
+A6C0CD7D8555AC3C49:1A75242A16FE656C43CE8F737F60FA78F95AD18BDCDD2B0E9C:\
+D88CD2104394ECBE9AAA9F101B578DC6:0CB244FA0D43A0CD101D5266C98EAFA1
+
+4215211D6CEC517F8925:FB8E6E2DFB3C7FD71DA2CE7041FA36E4357D81471DFB8754FBED:\
+773704610639CFEFA6E1B30F589D7F14:92BCF960D83B76F958E2E5AA616ECFD9
+
+EC23DAB61590F6E1FB49F4:80F5426BE96A6F7076BFB5A24F080D1FCD687FB4CE1E911A532DAE:\
+33C0B5F4D5355A351E0C3D835E468705:D481CAAE6DED8823021919E31463D848
+
+168A348A554CC29EC53D4AB0:\
+65397D2E8EA7E82E954EB36E0E3495781189FF5D2567EC7D3CA57225:\
+D7DF4487FAA7AA9FD485E16F25AA27EE:266C313CF766C74CB289EA78C735289E
+
+CF635CE20D305584C11537C1E7:\
+023D683A14128FD01704F6A97ABE231B77C30D1209EA139EC60F0FAC6E:\
+5DE8E05E68E4C3E8DDAFB5A2E0A6A92F:400DFEA369E0B09935355A4B6C1B32CA
+
+82287737559AC1EF31FDD382D4F2:\
+D0B1B5C3C2339BAB6C4FE1E899613C70460E825515A4C12259D9ACAFAD0C:\
+19B889E617FADA6EBB6E264FFD6AF0D1:1B72FA92A94F2C6B3F5D6812DF3D04F9
+
+09C05A1D6AB2961AFB06BD429012AB:\
+14FC9EA106FC2B59595D02C746B59819D3A914D532402389CC4FD9D0573926:\
+2B488ECF950B2A8716FED085EA768A22:7F4A7C9CB42F32CE2A388B6DC99D18F4
+
+2168CAC31CCF37DD4BFEDD800FE4C532:\
+4F5777260F776D716DDF5BD445BF330E55B840842EEE4838D7057EC3E95F59E4:\
+B5A870393560724B10918A377F7C28A0:E5F26301C19BDE0C99BC8DA8A052DA56
+
+A1A540CED8942569B2F5FA365942442CCF:\
+DB409FE74B6CB54A7FCB00ECC6926D3CF8599767451E634D425C9C7C253CBD8DEA:\
+485BAFDED6CFE581B4BDEC8ECE072F74:48FE4CDC23B58E19B0C472F2099EC251
+
+81E320373A0E35360990AB4070678E6CE72F:\
+97659AC60D8B8EE21B98F954E9C56B72C088AE5F4CA39721797D1C053E8D69E21C4F:\
+38704FDF0CF20334F749860D1F07F13F:3E2B4E746157040C97757425E15B5419
+
+97D8CF240D88F651EEAFBF162BF082CF9B96AD:\
+0EAC8A7289E6B9E5C345BCBFC5A3084D0AE6CF14C9D6B0760A1DFFF31F71AB6C3CC88C:\
+93C41CA3886983F5C6F8FDF18FD5C0B3:E248A9343658F34C84E3CF537F650012
+
+AC817C3EC75DBDBCDF03D6FB4ACF9A40340D8F9E:\
+E26112BE7A99FECC557C3D53674E6E670F824FE7784EFCCFA40BC88D4F88B5A29902171D:\
+3779FE6CCC7B03D2F7FDE0A37E5DE146:BA9F029AA2D995ECA82F2DDC3CBC7A73
+
+8F7DB0EE7F6D12F29637694950206B5CE9424EED07:\
+70EA3A6F5DFA46723E4ED47BA1EE5E784DA0971146F0B532D28630453AC7CA713F1BE92923:\
+05E2FE7CE92A97444451D3C101C1406E:D333040B9C4D5BBCB8B7A6FA0593020A
+
+4EDEF8A9C660D2BECBA2B49CE509EBB6E567A47FA367:\
+FB18B846F801571026BD501FFFE67E8D51D6AE9B8379A8676F65E2C7EE0D02E9FF9BBB23482C:\
+30B6CF4FA2DDAE8CD2FC6ACAA5302B77:EEF619A392FEAC7DB491E4591088C041
+
+814C87C4E33C797A93A77DB1F045996667A1C10D78123A:\
+F5526447A82E275E9CAC44EDB940171F9123C3FDA7F55D\
+8586CB574A00AFC12381F40964D096CD:\
+6EF35F1EDB02E4C384314A481487C28E:1A690BCB595164BFB80580C57D93FFEC
+
+7FD5E1A1547E1628F736DC7CFEFA9A00E586E02AA98FA394:\
+2EF4299CF27B80976CE57AE89DD2FE554EB7F00D38345C60\
+DB67CB9C88E078D581FB5A9F66D30688:\
+D89BD6AD540771D3DD537431D18A59C8:C13544BF30DEC01564A03F0E2FE2A208
+
+B234C341F0D5552F75A1C0C917B642B0F8E08C297B92BD31EA:\
+26B7CA59E71E9B7F866C2F04A0A3829E879E59E9232073E320\
+1C3BFAE519F23654B17F07EDC8A20344:\
+960065D92C1A8B61DDCC51B2218127C2:41F0DAF7338AEF1317188EA9D6BF946C
+
+F67477FC490F530BC502AF52FD9D1BA4C49176EBE194B37249CB:\
+36B043B8C7B08E5B16A73F60C09EF517C14373919C028FE3B430\
+FB61CCCDE8CC4B3266FA1AAA00B25D19:\
+F982385DE22ED1592B1B697E262E81D5:807E739C22372D98220E2CD58175A07A
+
+488E90C2F8642F621A615B362F67EB21BCD4963151D4B255F2325B:\
+39157652A4D31EF499708E065889FD3FAF9BB5C1D8CE98CAA4F629\
+05D7070962979F403E1514CCE6BA8FB2:\
+FFE4B7162C45A6EE3E0B1DA0257FFB5C:AE6247CF1E1B65506D3A02C22C341E2B
+
+638B8AF02A05F6E3A8535AD5B7AF2C5FB83EDFAC7F8DF0820C895131:\
+ACBA840ABC4086D65C676AD70F19532035DD4A724454518391BAF2CD\
+1330BF920BCD19D470C5578D5004F9D1:\
+739B15D6279FC651A4BC344C108E21C7:3D4E26F58C06A10C93928E9F1BE0D08E
+
+9ED609612B72B5E2F04E6D377F436DCFE45B5163486EEB94A31487E1CC:\
+A0C71029D7DC4FDA90B823AB12085ECE8592CD27B61743D5C6AF02663D\
+CB3CB27958E4819DE2BEF9893EC06B7F:\
+D3396BA942CCD4B481B6A5CF23DC4E67:491D4BA46EAEECDC998080AE07617ADA
+
+20EC7BE8711CB24261B375FD713002517B6ADF41D8EF3BA8EA3ED7B84C0B:\
+8F969FA4F9FBF293A6FDD11906DC4296EFB87EAD619CE701CBF60487F2\
+C66BA6C281D2A8598E3AB405D1C5D0D725:\
+586DF8D45569F007AB52BB204F2C5051:7DCBBB5D0C934C483C378613EFD31F47
+
+BDE3424FB4BF46067A5B09F76BE6F91203ABA18B3BB8C595C9071FE36AF048:\
+D9F1D76E17891B94CACADD217C9D37F58EDC782CC5FB539F59F965A5C4\
+43F3965DB7E399467CEB05FB59AB1AD01804:\
+28D38A778749BE8DC41996BB847DB497:805F380C9AF0D12FB9D94F9C433FE56B
+
+836569924C3AC998F64F43C5292C899A8A498CDDA350A1AA9F329E0EA5CB4A28:\
+869B404A038ECF556D4251C871EDA3F157983BA4D40974921D44D58AF9\
+51F007A5119534C399DA8593FBEABE60BD074F:\
+30B4BA7DEE8315E5D258AAFC8533960F:7C23EC1F738DC912BF682164336B8D63
+
+6C89219F127DC76D45896C6A3B527890B5BD95473ED55D8026ADC6546A26B2D6B0:\
+392E84D3857017287A0A62701D45C2FB9A9949A1292A9C159443297A562CB89A36\
+4F85F422EAA7BF0C046D60B5F02B675A:\
+D375C2513D2F96C69B0101ED7991A336:26EA74FC47F422F5BA765FE1283591FC
+
+3997AA01FBF84919CD76B0DF279077ACC79D495042B89F4E3FAD42AAC9F6C9028D73:\
+6621F16BA0DAA99B85C34080B73A09B81A64DBC6EB9E237FDC3C773D41BBD2514CAD\
+E62633D626881F8685331B5A0A656711:\
+04886B4DA138C35117EAE18F96A82CDF:F96E9898BCD745FE810EF44A1181BD15
+
+50B5DA3F355434BE51D36199C8834F4193CAAAED89103664ED20A9A4F481F244\
+36CC836B20B829728B8A0B530E5A94A1243E8EAD4FC4123CE4BBE0D83CD21C72\
+9EA0DDBE580630E3913B379F95CB40BA0ACE67599279957735754F71476CE4E5\
+0CC1A364C8D447590F7EF8A54A385F:\
+B08CEE141F8B1822F2C1EE4E0651F8CDBCFC095768EAF76A5EF2F7F012DAA30E\
+F7176B74264A92FBDD0E4E9CB475DBA651E1B51992716F059005C3F75022DC92\
+093ADE8A275A796D387C13C11328F1F0031A36757CF5986002F27E537367A290\
+365C026D58CA21413390E58B312F264D25E87B6CD94D13E048B694A19F8416:\
+5406C6AD9840420F75B75FE6FECBCAE3:D78C863B545A82AD6A01A50F4BDD6E9F
+
+AF47A39628206AA2A9A4CC539AEF077B31DC9AE5437D4021F279441333ECE8E2\
+338B785BABE2FE5587CAA821B9AF9DEA8C37CFCFB40FF0A6:\
+5E967714597273C7A8AA4F69314D2A1F75054F1110847DD421674F07FEA712BB\
+B67BB45DFF9EE7264354D750D73E3C6A773DC7AFC2B88737CE4C215EC87FD4AB\
+064707DD9B624436:\
+8935B9BC21A19E542C16B0D8F8AE2D7F:78D5A132853E1C1175ECE02AFBD1D084
+
+2ED861F5F11D7D517C138AA01F61D0A007D000DB97CF5B2FD6AFE5E18558F4B3\
+3155A922722673EE3AFE8E595F5FFA672FFA42C6CA9DF6A04C:\
+147FDA2A8847B0265EF27976DF944F11BD0272021BB0269B787B6C8BE6782B21\
+4DF59BD16F569142460EE80B9B6F38C980F81098D5A4C018EF6A5CD84E4DBF93\
+1E623D74D3DDD8737B:\
+DB82D133768464CB2D873E54FA2C8EF8:BBE7581AE1BF49DC010FA69E0546EAE0
+
+AFE2204DAC92FEF378DDB89A917B5A2AC94C22AD19E1EFD71EB97E4A87791037\
+5C308408C283FC3B60B4D5F12F2F1BF87B3DA6941F956B3D4FE9:\
+7AB5CAEC2D40209B3E4302BEA036D8536DC8D7E9D8FD23607421D122914B4E13\
+E1658B9924916C3D0C6B39F4B0822A98A7A7789A4E59CDDD350BFE3E3193EBAC\
+56303350B1D061910A9B:\
+87D663970DBFC792C78915C3C4757899:66A7C881A043BE46D7DDDB421A2A2CA1
+
+638BC9B9EB565BFD0BFFC256464CD23F0035CC25E5FF8DA305A60C8E3C4D9F9F\
+D86959C3BFB4C0CAB48320FACFF239CF:\
+22EC2594915889C9910FF444008035D42E90F31624F6D6790B1399FCED092BCB\
+A4C68CB9F648D816A9391D8A292E4AFE20096D856F36A23D9F18D732E1645BDC:\
+2805F50D0582B00A28BD99650A3804E2:A15DA66012662AC6E94BC0B93DFA8865
+
+E6CB34ACA3A0D94429AFEA82BAB4FD9541A2ADCF5D053029FD70C7BE4D088233\
+D4B6DF7757B9BB8068A502225AFFB89BA2:\
+824E5010A54C9DD6E08E0DB38A1B1DE2DD2197A00D094A0AD1F49A8D9ED6A01F\
+D1DEDC021D595FC87B54CC74665FE75A2D873241D81F1163E6EBB948DE7A18438E:\
+656AFF6B9A28680BEF2658F7A88BCB5F:6A43B623FE368BA438AEFE376699D9CB
+
+273DD7B96BB7A1CC9552E0EFAC43E5E58707BDF5D3CA309F7B313132F838E91F\
+75C0D8E17779AD0CCC8DFB78D1E15D58E81A4EBBE47E5B60AF8C92A8C47BC739\
+3BA01AB219C7BEE555BA5E269BBB7E83D6CC3FBA4B9A1AFA26ACA2EA276A2362\
+0A3E142305D3095A8D67802822FFABF8CBEAB31684CD11AA7AB394A11DB80427\
+F6184BFBEB545678BBD6A0DDD54CD6A13689B7BB56C865D07CFA7299B276C1A8\
+8E0CA37A60F9F21BD093F8A5DFCE461557FED0AEC6367E4230F0DCE2669D8AF5\
+A92D6F09276124F7F41C9CD3EBE3E942E1B9F0A7EF6FEA1F5FC601C6638BBB0C\
+B92A15E08B39D78055735340563C8337F673DFE5:\
+4A0F85EDD82B4E39F9185ED4E585187B51D3326DBA5FCB83CB3ACD36327109F8\
+CCE17CF5CD152DB941E3480AA22AFDC51562246CD99DE0423F6E9505349D547B\
+C39343B06025EF76F4C6C301FE1917F391433BC8A7F67A007BB7E8A238D59F5A\
+29C6B5519165B2E05E3D04493F5342E9E917C65088EF56E7C0A0A0703E3AB949\
+F86D3ACDFF9EE70815CBBFB1ADBED7F2A2C565DECA76D99FA3941719236D7B57\
+2248D8A4B2FE8DEA33C7E909C132E3D107A625FCB2E088201F3AD33A37FB4411\
+4316FD7FF1B161777FEA4391E51D102D1884671B0AB994B8BDFA91AEE09105FB\
+6BFE881FC4A67B8CEFE2E7E4DBAF844E896DFD1C4164243CB888765C58C19611\
+17A6F062:\
+E2C905428F0608F292C3FE4BED132B78:4C02F8A1754CE2CC8865037ED8E264BB
+
+956B7E15A1BF4DC6A9CE6DE460513D43F45191E0D1997ECA88327B01487291DD\
+DE10F27FCF3F45780EB35C6E0499B1F9EA43D9BBDC5785648A0066D273F7B051\
+07A2D0D6E2154EF0C8AA5ECD430FC62E529FE92EF76F93816FF953E2F00333F8\
+A603CE88191D78E1C7D6AE0BE57439381422660B91F98C01F2DFE3E3E317DB89\
+1AA91133C689158E5FC3994438D27C4CF4E35786DCE387CFC26AB2A5818D2E9C\
+363FCFFDC8E48B27A8246CE0F6E82CEACB8370A866F777286229CEE3B6FC7FEC\
+3C4FE90433742CDB9898BB8E80E7794C6AE9F4D0E16BF94394C7264AC3A636FF\
+F52004289430042DC8BFBB48A73494111E88E2FFF3DB42:\
+308B1A08871C3FF57397A79639FD87A99EC36711A83FD2B3250247FD3125C7FC\
+1681F6AD15B0230ADB4ACB9B3C735C287A2C530532BA1BF62DCC369D110B31C2\
+DB627A75B5419B5177956E64FFCAD6C83A391B0C2023F11FB13066E6D49BFFE2\
+FF12EE0FC05706C001401204FE70C739F0836F0175DD77AA37BC308737F7FD33\
+96FF25C6D5E6BBC9487D79D4C3F69817940A9EFC4FDB3FF3BA85BD36B4F57888\
+18B29530D3F0BE533FBFB9F175DAFBC920D5B5EEB62BA02F339A7501404E52BC\
+9DE4BBF27702189731CBBB49BE2FBAFA43F3A79BF2DE147AF3C12CCBF2FC15CF\
+A135F5EB4603A9C8158B78E600658C102EE637F77471E0F621F2EF8BDE7BB113\
+1164DBFACB1C23:\
+87A268D1650E08650328692CBC9930E9:61EFA5A996D93EA8F7C68AF6BA653841
+
+169C8E816CAB0C159AEBF19C954B87089D29C5386B761D27A028DBBC2518F33B\
+B481BC202DC836C7B327634872EB500F1415477F8B64A72B8D82E8B29BDBED4F\
+5CAA708972A65026CDB46E3F9FBF4FB3D4963360FBDA8B885C733AF74E2747AB\
+D1B734445D856A2A39D869D897B88B6C4FBECC4A9857D2F5CB0CEC193333C405\
+EAF949477EB371B78BDB8F23931A8FE2D95B2C71B2FE667D0A53973E865B4371\
+548CB8D23F2A89CA0518ED98337C7B0CD7A77D8AA6E407B0379EEEBDFA312E4E\
+BDE721FC11AAC716C3B4AEF631290208D17F9277639A279A3816583247868105\
+6DA2017E4CC8940F7D4305AE6C07B63D8749B4EAE3:\
+93550CACF92B81F03129D4DA45D0B6A217202517FF34CACFF291D9FA51793F06\
+D020E63F9E54042D0E1180E131C805D3C392603316D8B990006379C54F51506F\
+8238D4EBF4F78AE95753D852AB7F0D974A16F374E20424B4E79EF83D3BF78A83\
+DE23F50078CCEEB7C8CFD887AA6EF3ED004C4F1048A608C0EDFB8FE56862E533\
+FB0BC90BB19175BA99CD747050F6DCBB229C3B11F89054B9A78A80FAECFF6821\
+1F1BDE2EEFFB2D690602478184E5C51B902C246DE285E15FEBD6AC0B7ECADFA9\
+153F982434397AD0FB4DBE4DD5A1803234F00B0894C8019741F89665D3D51587\
+792F5BD7142C739221A1C2D4A2C86BB8782F1CF7912C32C8D3A10BECB4C7AAF0\
+1DF64C2F90:\
+DC851BF2DD4E3963CF3ED171404FBD08:E4CD8527D23393DAEAD16133854B1661
+
+E4BF7D594228D3CB4D7E9EC6397DB3325B61D7C1437D0634C62FC33D9B932B7F\
+52A8D894D0AB601E29FEE4637B9795D7F96D983CEA9E70B0CD33EE68C619E718\
+C1C0AD916B0DAF950B93F8872B8D5E24FAF660E494D095610483CACA9CB1E35D\
+7190EEDD9D9E72A8316A2F5CF78D80F283E0D617B16B79B5EE437F8AF462E766\
+F2D6438F74B538A51F670216F582087863DF90144A09C9394C48C340ABABA69D\
+81E92DF59E659ABDCC9CD4C11FDC3A82BBCA9606D35F3F1FA7025F52AD06F02E\
+EF1D238E82BE4B4E5A1F1079FC4AFBB71491BDE7F0FC0698FF65EAAC6BDADB5B\
+F7FEE979BC34C81754D89050228C07361DC51D0EC123A6C088906DF46B484F62\
+4638DC036CA41AC07CAA109E3618D454DDF1629E14085F9C98CC900314DF665A\
+17425D84E6774462225500586DD4AC4AC50EE8D9164775AF1306B227E51882FD\
+5ADF814057C5A2791AA2D187767ED13B8CBA14A3018A521590043C751DBE7277\
+9EF3B8F5B95A6ED3FD3F5B73BD2CAF4AE6C3EDE84D3FFDDD43395360F8C5D896\
+B9908B72EAF945E738A05BF6CD0A40B3CD2D9B1B6C98F8AFD24B10CA11E860CA\
+78EB3C62E4814A1C22A512EFAF52A27C7F3E97EBD6909BA8DBAB72EC93D2B60B\
+BDF26DA174B7BE965CD0850B232788A2651F8E3CAF29E48BD4577767292E72E7\
+20DF889497462AF317AFFF3AD787DC3CA66A7856935DE167B458CEDD8640C4A7\
+204D3BB79366AAAA15A9E4EC30C129D72BA12DBFFE0E26B266F590ED35549455\
+A1CF0C3535B7DF4B60C43791856068B002956F00A396B3098B43F6C0978A1639\
+5A226E8FD94DDA3A1112CB9672334774C8B6756B4C2874D76B6B9802F5AE3B4F\
+D0A9DFAAF7B9E408CBAF9F3EE2E6B2AA9C2715E94F89C0BAF458BDEA06F839D7\
+A2188199D265A19D1440DBF6268EA0C3B5B5AC053E6CBF33C57C1DCB7556A217\
+6F23B0418851DE9C92BA92B848327BFDE727022694C259593E7624B3CCC7CA3B\
+EA7A7C73CC5B0F5E15A2165DD4925ABCB95DE24D1F3BA65DB1CB117D92DBB97C\
+5635EF2290FF80A5A1960275285D31E2BA132FD94ED636FFA1477D332336AF79\
+6B9F9BFC9E1BA13FB1A4B4DA01E6BCBBF9EB9448C1CA476212C49535FA45AE66\
+E44962826403C115A775EFA85BAB635597F79D58C2E4BBD4A95009A395B70979\
+006BFB646FBC79163269BF8D1422E2AB1A7F04DC64BFB00D0FB9B0A570BA1E70:\
+C437723C80E3B32AEEBD6DDE08D614312CD3176E8BFA8650EAF3A34DAE3B7276\
+9F823BC48F88F42AFCBBBDDA0534E8D2C9BAB65A83939668C982A1CBC1B826B2\
+59D83FD6505381BA99B1C850D5EFB5D0DBB077F4AB021246366292971BE121C2\
+65BCAB722A6AB5B7CB7D55C91F9FD5B3BD59A8436250F17D110B5B2588F2DACC\
+98EE60884436810570A61AF2D7A424D4D597004D175B650F9EDE8D2544974909\
+05E5AFFD31DBC4FAE7EEF180B07B7D9D2579C1A140F63F31B0A2847043FE6F98\
+556A3F90DE4C28F858581F699ED3B6E3E554DD0FE91954FC067BABC6AC62E314\
+57B299B9CF5E061A9B6ED628DFBDC164AFB6560847389EE0257A7CDE811292BC\
+761E4D66D2CDEDD2C6DE0333CF8ED6682185AD5B6B1B05526338C6EF72D02A03\
+46C4527CCB3B1E3484B83FC7AFC7BFA69B111980FDC53C70BE72F3BA7F8B51A3\
+63CD590A988AEECA67265C9BB813142F34D0B2FD20B06F39C4DE7A00D763E2B2\
+01D90A8FFCD199EDE60EFFFC0CABB648C1D7F15323F0E9BC13EABD1EBE99BCBF\
+970D0AF2501826E37D222EF4D9AFAB22EE99972F2A97C84175AAA49ED2CEAF34\
+0213E29C7A88AF38F2CAD42C2AF49937262F3281B806E343AF3ED0C7535725A5\
+AD0CACBEDF519F69CF820980169FD6DB67A165F3883216E227B07E3FACB1E279\
+54FD1D08A2EC6472B0B1F7B0D6AFA2C616F6207E7A2C4444C6F952268BF73EDB\
+EB4657AF472D08BAEAFB237F118EED6CACD80E24ABEAED97D1634367000778C0\
+E095994798006D874999E542F5F479E08AD481D211A7A4D51D58CFDC374414F6\
+810A5AE08573A34D914BE3176CE7C3699D83A06FB9D8585A03854CC38B8CFDF5\
+CDD7C888790A04D2E7F2D22099A9120CE0C37390B9AD918AD0B41C4239D2BBBA\
+B82B98E59920B173BCCDE0D48FF860F91216C4A7E68E05DAF7F53EB7641171D1\
+83C976C6B9CF1F57B2E48F88BD5E8F5558934245CBFBEE365A2D457B2EA5E6CD\
+0F39AAA154692EB604B2A366B53C5893C04568BA98B4A0AFA8B6DB80C6D66E9C\
+93DFFB1BE584ED1CC111D315823F25D6BFF9367EA584A3A0FC62788D7D385D08\
+14E984E6EE556F83D01584C8DE0656DC2A89A08BBD268F0644C63B80A5BE57DE\
+F71566B677596557D4C218DEC8A7D2611FE6FA07633C558FF372308F5D680C0F\
+9858362C2B2B8C2989F19FD8411C10B6E37A647A07D0B1D5E681E25902C36231\
+E9E5E812B623D9E72C23518F082EA48C:\
+251AD494D64DAB08B66A96CB8C7876A6:F87A825C39326949EB19EE5BD30CCBF9
+
+[AES/EAX(64)]
+:32E55CE0C3FAEA48:\
+C61A0851AB4E515D11525B92E2B9D850:C825FC7C4D539DC74887CECC70884F37
+
+60:710DABD24D400F3B6B:\
+F956B879EC7F807F1FCB482B53623671:E64F90B4619D93137E6237929EABF297
+
+[AES/XTS]
+# Vectors are from IEEE P1619 D11
+
+0000000000000000000000000000000000000000000000000000000000000000:\
+917CF69EBD68B2EC9B9FE9A3EADDA692CD43D2F59598ED858C02C2652FBF922E:\
+0000000000000000000000000000000000000000000000000000000000000000:\
+00000000000000000000000000000000
+
+4444444444444444444444444444444444444444444444444444444444444444:\
+C454185E6A16936E39334038ACEF838BFB186FFF7480ADC4289382ECD6D394F0:\
+1111111111111111111111111111111122222222222222222222222222222222:\
+33333333330000000000000000000000
+
+4444444444444444444444444444444444444444444444444444444444444444:\
+B01F86F8EDC1863706FA8A4253E34F28AF319DE38334870F4DD1F94CBE9832F1:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF:\
+27A7479BEFA1D476489F308CD4CFA6E2A96E4BBE3208FF25287DD3819616E89C\
+C78CF7F5E543445F8333D8FA7F56000005279FA5D8B5E4AD40E736DDB4D35412\
+328063FD2AAB53E5EA1E0A9F332500A5DF9487D07A5C92CC512C8866C7E860CE\
+93FDF166A24912B422976146AE20CE846BB7DC9BA94A767AAEF20C0D61AD0265\
+5EA92DC4C4E41A8952C651D33174BE51A10C421110E6D81588EDE82103A252D8\
+A750E8768DEFFFED9122810AAEB99F9172AF82B604DC4B8E51BCB08235A6F434\
+1332E4CA60482A4BA1A03B3E65008FC5DA76B70BF1690DB4EAE29C5F1BADD03C\
+5CCF2A55D705DDCD86D449511CEB7EC30BF12B1FA35B913F9F747A8AFD1B130E\
+94BFF94EFFD01A91735CA1726ACD0B197C4E5B03393697E126826FB6BBDE8ECC\
+1E08298516E2C9ED03FF3C1B7860F6DE76D4CECD94C8119855EF5297CA67E9F3\
+E7FF72B1E99785CA0A7E7720C5B36DC6D72CAC9574C8CBBC2F801E23E56FD344\
+B07F22154BEBA0F08CE8891E643ED995C94D9A69C9F1B5F499027A78572AEEBD\
+74D20CC39881C213EE770B1010E4BEA718846977AE119F7A023AB58CCA0AD752\
+AFE656BB3C17256A9F6E9BF19FDD5A38FC82BBE872C5539EDB609EF4F79C203E\
+BB140F2E583CB2AD15B4AA5B655016A8449277DBD477EF2C8D6C017DB738B18D\
+EB4A427D1923CE3FF262735779A418F20A282DF920147BEABE421EE5319D0568:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+00000000000000000000000000000000
+
+27A7479BEFA1D476489F308CD4CFA6E2A96E4BBE3208FF25287DD3819616E89C\
+C78CF7F5E543445F8333D8FA7F56000005279FA5D8B5E4AD40E736DDB4D35412\
+328063FD2AAB53E5EA1E0A9F332500A5DF9487D07A5C92CC512C8866C7E860CE\
+93FDF166A24912B422976146AE20CE846BB7DC9BA94A767AAEF20C0D61AD0265\
+5EA92DC4C4E41A8952C651D33174BE51A10C421110E6D81588EDE82103A252D8\
+A750E8768DEFFFED9122810AAEB99F9172AF82B604DC4B8E51BCB08235A6F434\
+1332E4CA60482A4BA1A03B3E65008FC5DA76B70BF1690DB4EAE29C5F1BADD03C\
+5CCF2A55D705DDCD86D449511CEB7EC30BF12B1FA35B913F9F747A8AFD1B130E\
+94BFF94EFFD01A91735CA1726ACD0B197C4E5B03393697E126826FB6BBDE8ECC\
+1E08298516E2C9ED03FF3C1B7860F6DE76D4CECD94C8119855EF5297CA67E9F3\
+E7FF72B1E99785CA0A7E7720C5B36DC6D72CAC9574C8CBBC2F801E23E56FD344\
+B07F22154BEBA0F08CE8891E643ED995C94D9A69C9F1B5F499027A78572AEEBD\
+74D20CC39881C213EE770B1010E4BEA718846977AE119F7A023AB58CCA0AD752\
+AFE656BB3C17256A9F6E9BF19FDD5A38FC82BBE872C5539EDB609EF4F79C203E\
+BB140F2E583CB2AD15B4AA5B655016A8449277DBD477EF2C8D6C017DB738B18D\
+EB4A427D1923CE3FF262735779A418F20A282DF920147BEABE421EE5319D0568:\
+264D3CA8512194FEC312C8C9891F279FEFDD608D0C027B60483A3FA811D65EE5\
+9D52D9E40EC5672D81532B38B6B089CE951F0F9C35590B8B978D175213F329BB\
+1C2FD30F2F7F30492A61A532A79F51D36F5E31A7C9A12C286082FF7D2394D18F\
+783E1A8E72C722CAAAA52D8F065657D2631FD25BFD8E5BAAD6E527D763517501\
+C68C5EDC3CDD55435C532D7125C8614DEED9ADAA3ACADE5888B87BEF641C4C99\
+4C8091B5BCD387F3963FB5BC37AA922FBFE3DF4E5B915E6EB514717BDD2A7407\
+9A5073F5C4BFD46ADF7D282E7A393A52579D11A028DA4D9CD9C77124F9648EE3\
+83B1AC763930E7162A8D37F350B2F74B8472CF09902063C6B32E8C2D9290CEFB\
+D7346D1C779A0DF50EDCDE4531DA07B099C638E83A755944DF2AEF1AA31752FD\
+323DCB710FB4BFBB9D22B925BC3577E1B8949E729A90BBAFEACF7F7879E7B114\
+7E28BA0BAE940DB795A61B15ECF4DF8DB07B824BB062802CC98A9545BB2AAEED\
+77CB3FC6DB15DCD7D80D7D5BC406C4970A3478ADA8899B329198EB61C193FB62\
+75AA8CA340344A75A862AEBE92EEE1CE032FD950B47D7704A3876923B4AD6284\
+4BF4A09C4DBE8B4397184B7471360C9564880AEDDDB9BAA4AF2E75394B08CD32\
+FF479C57A07D3EAB5D54DE5F9738B8D27F27A9F0AB11799D7B7FFEFB2704C95C\
+6AD12C39F1E867A4B7B1D7818A4B753DFD2A89CCB45E001A03A867B187F225DD:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+01000000000000000000000000000000
+
+264D3CA8512194FEC312C8C9891F279FEFDD608D0C027B60483A3FA811D65EE5\
+9D52D9E40EC5672D81532B38B6B089CE951F0F9C35590B8B978D175213F329BB\
+1C2FD30F2F7F30492A61A532A79F51D36F5E31A7C9A12C286082FF7D2394D18F\
+783E1A8E72C722CAAAA52D8F065657D2631FD25BFD8E5BAAD6E527D763517501\
+C68C5EDC3CDD55435C532D7125C8614DEED9ADAA3ACADE5888B87BEF641C4C99\
+4C8091B5BCD387F3963FB5BC37AA922FBFE3DF4E5B915E6EB514717BDD2A7407\
+9A5073F5C4BFD46ADF7D282E7A393A52579D11A028DA4D9CD9C77124F9648EE3\
+83B1AC763930E7162A8D37F350B2F74B8472CF09902063C6B32E8C2D9290CEFB\
+D7346D1C779A0DF50EDCDE4531DA07B099C638E83A755944DF2AEF1AA31752FD\
+323DCB710FB4BFBB9D22B925BC3577E1B8949E729A90BBAFEACF7F7879E7B114\
+7E28BA0BAE940DB795A61B15ECF4DF8DB07B824BB062802CC98A9545BB2AAEED\
+77CB3FC6DB15DCD7D80D7D5BC406C4970A3478ADA8899B329198EB61C193FB62\
+75AA8CA340344A75A862AEBE92EEE1CE032FD950B47D7704A3876923B4AD6284\
+4BF4A09C4DBE8B4397184B7471360C9564880AEDDDB9BAA4AF2E75394B08CD32\
+FF479C57A07D3EAB5D54DE5F9738B8D27F27A9F0AB11799D7B7FFEFB2704C95C\
+6AD12C39F1E867A4B7B1D7818A4B753DFD2A89CCB45E001A03A867B187F225DD:\
+FA762A3680B76007928ED4A4F49A9456031B704782E65E16CECB54ED7D017B5E\
+18ABD67B338E81078F21EDB7868D901EBE9C731A7C18B5E6DEC1D6A72E078AC9\
+A4262F860BEEFA14F4E821018272E411A951502B6E79066E84252C3346F3AA62\
+344351A291D4BEDC7A07618BDEA2AF63145CC7A4B8D4070691AE890CD65733E7\
+946E9021A1DFFC4C59F159425EE6D50CA9B135FA6162CEA18A939838DC000FB3\
+86FAD086ACCE5AC07CB2ECE7FD580B00CFA5E98589631DC25E8E2A3DAF2FFDEC\
+26531659912C9D8F7A15E5865EA8FB5816D6207052BD7128CD743C12C8118791\
+A4736811935EB982A532349E31DD401E0B660A568CB1A4711F552F55DED59F1F\
+15BF7196B3CA12A91E488EF59D64F3A02BF45239499AC6176AE321C4A211EC54\
+5365971C5D3F4F09D4EB139BFDF2073D33180B21002B65CC9865E76CB24CD92C\
+874C24C18350399A936AB3637079295D76C417776B94EFCE3A0EF7206B151105\
+19655C956CBD8B2489405EE2B09A6B6EEBE0C53790A12A8998378B33A5B71159\
+625F4BA49D2A2FDBA59FBF0897BC7AABD8D707DC140A80F0F309F835D3DA54AB\
+584E501DFA0EE977FEC543F74186A802B9A37ADB3E8291ECA04D66520D229E60\
+401E7282BEF486AE059AA70696E0E305D777140A7A883ECDCB69B9FF938E8A42\
+31864C69CA2C2043BED007FF3E605E014BCF518138DC3A25C5E236171A2D01D6:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+02000000000000000000000000000000
+
+8E41B78C390B5AF9D758BB214A67E9F6BF7727B09AC6124084C37611398FA45D\
+AAD94868600ED391FB1ACD4857A95B466E62EF9F4B377244D1C152E7B30D731A\
+AD30C716D214B707AED99EB5B5E580B3E887CF7497465651D4B60E6042051DA3\
+693C3B78C14489543BE8B6AD0BA629565BBA202313BA7B0D0C94A3252B676F46\
+CC02CE0F8A7D34C0ED229129673C1F61AED579D08A9203A25AAC3A77E9DB6026\
+7996DB38DF637356D9DCD1632E369939F2A29D89345C66E05066F1A3677AEF18\
+DEA4113FAEB629E46721A66D0A7E785D3E29AF2594EB67DFA982AFFE0AAC058F\
+6E15864269B135418261FC3AFB089472CF68C45DD7F231C6249BA0255E1E0338\
+33FC4D00A3FE02132D7BC3873614B8AEE34273581EA0325C81F0270AFFA13641\
+D052D36F0757D484014354D02D6883CA15C24D8C3956B1BD027BCF41F151FD80\
+23C5340E5606F37E90FDB87C86FB4FA634B3718A30BACE06A66EAF8F63C4AA3B\
+637826A87FE8CFA44282E92CB1615AF3A28E53BC74C7CBA1A0977BE9065D0C1A\
+5DEC6C54AE38D37F37AA35283E048E5530A85C4E7A29D7B92EC0C3169CDF2A80\
+5C7604BCE60049B9FB7B8EAAC10F51AE23794CEBA68BB58112E293B9B692CA72\
+1B37C662F8574ED4DBA6F88E170881C82CDDC1034A0CA7E284BF0962B6B26292\
+D836FA9F73C1AC770EEF0F2D3A1EAF61D3E03555FD424EEDD67E18A18094F888:\
+D55F684F81F4426E9FDE92A5FF02DF2AC896AF63962888A97910C1379E20B0A3\
+B1DB613FB7FE2E07004329EA5C22BFD33E3DBE4CF58CC608C2C26C19A2E2FE22\
+F98732C2B5CB844CC6C0702D91E1D50FC4382A7EBA5635CD602432A2306AC4CE\
+82F8D70C8D9BC15F918FE71E74C622D5CF71178BF6E0B9CC9F2B41DD8DBE441C\
+41CD0C73A6DC47A348F6702F9D0E9B1B1431E948E299B9EC2272AB2C5F0C7BE8\
+6AFFA5DEC87A0BEE81D3D50007EDAA2BCFCCB35605155FF36ED8EDD4A40DCD4B\
+243ACD11B2B987BDBFAF91A7CAC27E9C5AEA525EE53DE7B2D3332C8644402B82\
+3E94A7DB26276D2D23AA07180F76B4FD29B9C0823099C9D62C519880AEE7E969\
+7617C1497D47BF3E571950311421B6B734D38B0DB91EB85331B91EA9F61530F5\
+4512A5A52A4BAD589EB69781D537F23297BB459BDAD2948A29E1550BF4787E0B\
+E95BB173CF5FAB17DAB7A13A052A63453D97CCEC1A321954886B7A1299FAAEEC\
+AE35C6EAACA753B041B5E5F093BF83397FD21DD6B3012066FCC058CC32C3B09D\
+7562DEE29509B5839392C9FF05F51F3166AAAC4AC5F238038A3045E6F72E48EF\
+0FE8BC675E82C318A268E43970271BF119B81BF6A982746554F84E72B9F00280\
+A320A08142923C23C883423FF949827F29BBACDC1CCDB04938CE6098C95BA6B3\
+2528F4EF78EED778B2E122DDFD1CBDD11D1C0A6783E011FC536D63D053260637:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+FD000000000000000000000000000000
+
+D55F684F81F4426E9FDE92A5FF02DF2AC896AF63962888A97910C1379E20B0A3\
+B1DB613FB7FE2E07004329EA5C22BFD33E3DBE4CF58CC608C2C26C19A2E2FE22\
+F98732C2B5CB844CC6C0702D91E1D50FC4382A7EBA5635CD602432A2306AC4CE\
+82F8D70C8D9BC15F918FE71E74C622D5CF71178BF6E0B9CC9F2B41DD8DBE441C\
+41CD0C73A6DC47A348F6702F9D0E9B1B1431E948E299B9EC2272AB2C5F0C7BE8\
+6AFFA5DEC87A0BEE81D3D50007EDAA2BCFCCB35605155FF36ED8EDD4A40DCD4B\
+243ACD11B2B987BDBFAF91A7CAC27E9C5AEA525EE53DE7B2D3332C8644402B82\
+3E94A7DB26276D2D23AA07180F76B4FD29B9C0823099C9D62C519880AEE7E969\
+7617C1497D47BF3E571950311421B6B734D38B0DB91EB85331B91EA9F61530F5\
+4512A5A52A4BAD589EB69781D537F23297BB459BDAD2948A29E1550BF4787E0B\
+E95BB173CF5FAB17DAB7A13A052A63453D97CCEC1A321954886B7A1299FAAEEC\
+AE35C6EAACA753B041B5E5F093BF83397FD21DD6B3012066FCC058CC32C3B09D\
+7562DEE29509B5839392C9FF05F51F3166AAAC4AC5F238038A3045E6F72E48EF\
+0FE8BC675E82C318A268E43970271BF119B81BF6A982746554F84E72B9F00280\
+A320A08142923C23C883423FF949827F29BBACDC1CCDB04938CE6098C95BA6B3\
+2528F4EF78EED778B2E122DDFD1CBDD11D1C0A6783E011FC536D63D053260637:\
+72EFC1EBFE1EE25975A6EB3AA8589DDA2B261F1C85BDAB442A9E5B2DD1D7C395\
+7A16FC08E526D4B1223F1B1232A11AF274C3D70DAC57F83E0983C498F1A6F1AE\
+CB021C3E70085A1E527F1CE41EE5911A82020161529CD82773762DAF5459DE94\
+A0A82ADAE7E1703C808543C29ED6FB32D9E004327C1355180C995A07741493A0\
+9C21BA01A387882DA4F62534B87BB15D60D197201C0FD3BF30C1500A3ECFECDD\
+66D8721F90BCC4C17EE925C61B0A03727A9C0D5F5CA462FBFA0AF1C2513A9D9D\
+4B5345BD27A5F6E653F751693E6B6A2B8EAD57D511E00E58C45B7B8D005AF792\
+88F5C7C22FD4F1BF7A898B03A5634C6A1AE3F9FAE5DE4F296A2896B23E7ED43E\
+D14FA5A2803F4D28F0D3FFCF24757677AEBDB47BB388378708948A8D4126ED18\
+39E0DA29A537A8C198B3C66AB00712DD261674BF45A73D67F76914F830CA014B\
+65596F27E4CF62DE66125A5566DF9975155628B400FBFB3A29040ED50FAFFDBB\
+18AECE7C5C44693260AAB386C0A37B11B114F1C415AEBB653BE468179428D43A\
+4D8BC3EC38813ECA30A13CF1BB18D524F1992D44D8B1A42EA30B22E6C95B199D\
+8D182F8840B09D059585C31AD691FA0619FF038ACA2C39A943421157361717C4\
+9D322028A74648113BD8C9D7EC77CF3C89C1EC8718CEFF8516D96B34C3C614F1\
+0699C9ABC4ED0411506223BEA16AF35C883ACCDBE1104EEF0CFDB54E12FB230A:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+FE000000000000000000000000000000
+
+72EFC1EBFE1EE25975A6EB3AA8589DDA2B261F1C85BDAB442A9E5B2DD1D7C395\
+7A16FC08E526D4B1223F1B1232A11AF274C3D70DAC57F83E0983C498F1A6F1AE\
+CB021C3E70085A1E527F1CE41EE5911A82020161529CD82773762DAF5459DE94\
+A0A82ADAE7E1703C808543C29ED6FB32D9E004327C1355180C995A07741493A0\
+9C21BA01A387882DA4F62534B87BB15D60D197201C0FD3BF30C1500A3ECFECDD\
+66D8721F90BCC4C17EE925C61B0A03727A9C0D5F5CA462FBFA0AF1C2513A9D9D\
+4B5345BD27A5F6E653F751693E6B6A2B8EAD57D511E00E58C45B7B8D005AF792\
+88F5C7C22FD4F1BF7A898B03A5634C6A1AE3F9FAE5DE4F296A2896B23E7ED43E\
+D14FA5A2803F4D28F0D3FFCF24757677AEBDB47BB388378708948A8D4126ED18\
+39E0DA29A537A8C198B3C66AB00712DD261674BF45A73D67F76914F830CA014B\
+65596F27E4CF62DE66125A5566DF9975155628B400FBFB3A29040ED50FAFFDBB\
+18AECE7C5C44693260AAB386C0A37B11B114F1C415AEBB653BE468179428D43A\
+4D8BC3EC38813ECA30A13CF1BB18D524F1992D44D8B1A42EA30B22E6C95B199D\
+8D182F8840B09D059585C31AD691FA0619FF038ACA2C39A943421157361717C4\
+9D322028A74648113BD8C9D7EC77CF3C89C1EC8718CEFF8516D96B34C3C614F1\
+0699C9ABC4ED0411506223BEA16AF35C883ACCDBE1104EEF0CFDB54E12FB230A:\
+3260AE8DAD1F4A32C5CAFE3AB0EB95549D461A67CEB9E5AA2D3AFB62DECE0553\
+193BA50C75BE251E08D1D08F1088576C7EFDFAAF3F459559571E12511753B07A\
+F073F35DA06AF0CE0BBF6B8F5CCC5CEA500EC1B211BD51F63B606BF6528796CA\
+12173BA39B8935EE44CCCE646F90A45BF9CCC567F0ACE13DC2D53EBEEDC81F58\
+B2E41179DDDF0D5A5C42F5D8506C1A5D2F8F59F3EA873CBCD0EEC19ACBF32542\
+3BD3DCB8C2B1BF1D1EAED0EBA7F0698E4314FBEB2F1566D1B9253008CBCCF45A\
+2B0D9C5C9C21474F4076E02BE26050B99DEE4FD68A4CF890E496E4FCAE7B70F9\
+4EA5A9062DA0DAEBA1993D2CCD1DD3C244B8428801495A58B216547E7E847C46\
+D1D756377B6242D2E5FB83BF752B54E0DF71E889F3A2BB0F4C10805BF3C59037\
+6E3C24E22FF57F7FA965577375325CEA5D920DB94B9C336B455F6E894C01866F\
+E9FBB8C8D3F70A2957285F6DFB5DCD8CBF54782F8FE7766D4723819913AC7734\
+21E3A31095866BAD22C86A6036B2518B2059B4229D18C8C2CCBDF906C6CC6E82\
+464EE57BDDB0BEBCB1DC645325BFB3E665EF7251082C88EBB1CF203BD779FDD3\
+8675713C8DAADD17E1CABEE432B09787B6DDF3304E38B731B45DF5DF51B78FCF\
+B3D32466028D0BA36555E7E11AB0EE0666061D1645D962444BC47A38188930A8\
+4B4D561395C73C087021927CA638B7AFC8A8679CCB84C26555440EC7F10445CD:\
+2718281828459045235360287471352631415926535897932384626433832795:\
+FF000000000000000000000000000000
+
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF:\
+1C3B3A102F770386E4836C99E370CF9BEA00803F5E482357A4AE12D414A3E63B\
+5D31E276F8FE4A8D66B317F9AC683F44680A86AC35ADFC3345BEFECB4BB188FD\
+5776926C49A3095EB108FD1098BAEC70AAA66999A72A82F27D848B21D4A741B0\
+C5CD4D5FFF9DAC89AEBA122961D03A757123E9870F8ACF1000020887891429CA\
+2A3E7A7D7DF7B10355165C8B9A6D0A7DE8B062C4500DC4CD120C0F7418DAE3D0\
+B5781C34803FA75421C790DFE1DE1834F280D7667B327F6C8CD7557E12AC3A0F\
+93EC05C52E0493EF31A12D3D9260F79A289D6A379BC70C50841473D1A8CC81EC\
+583E9645E07B8D9670655BA5BBCFECC6DC3966380AD8FECB17B6BA02469A020A\
+84E18E8F84252070C13E9F1F289BE54FBC481457778F616015E1327A02B140F1\
+505EB309326D68378F8374595C849D84F4C333EC4423885143CB47BD71C5EDAE\
+9BE69A2FFECEB1BEC9DE244FBE15992B11B77C040F12BD8F6A975A44A0F90C29\
+A9ABC3D4D893927284C58754CCE294529F8614DCD2ABA991925FEDC4AE74FFAC\
+6E333B93EB4AFF0479DA9A410E4450E0DD7AE4C6E2910900575DA401FC07059F\
+645E8B7E9BFDEF33943054FF84011493C27B3429EAEDB4ED5376441A77ED4385\
+1AD77F16F541DFD269D50D6A5F14FB0AAB1CBB4C1550BE97F7AB4066193C4CAA\
+773DAD38014BD2092FA755C824BB5E54C4F36FFDA9FCEA70B9C6E693E148C151:\
+2718281828459045235360287471352662497757247093699959574966967627\
+3141592653589793238462643383279502884197169399375105820974944592:\
+FF000000000000000000000000000000
+
+000102030405060708090A0B0C0D0E0F10:\
+6C1625DB4671522D3D7599601DE7CA09ED:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+000102030405060708090A0B0C0D0E0F1011:\
+D069444B7A7E0CAB09E24447D24DEB1FEDBF:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+000102030405060708090A0B0C0D0E0F101112:\
+E5DF1351C0544BA1350B3363CD8EF4BEEDBF9D:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+000102030405060708090A0B0C0D0E0F10111213:\
+9D84C813F719AA2C7BE3F66171C7C5C2EDBF9DAC:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF:\
+38B45812EF43A05BD957E545907E223B954AB4AAF088303AD910EADF14B42BE6\
+8B2461149D8C8BA85F992BE970BC621F1B06573F63E867BF5875ACAFA04E42CC\
+BD7BD3C2A0FB1FFF791EC5EC36C66AE4AC1E806D81FBF709DBE29E471FAD3854\
+9C8E66F5345D7C1EB94F405D1EC785CC6F6A68F6254DD8339F9D84057E01A177\
+41990482999516B5611A38F41BB6478E6F173F320805DD71B1932FC333CB9EE3\
+9936BEEA9AD96FA10FB4112B901734DDAD40BC1878995F8E11AEE7D141A2F5D4\
+8B7A4E1E7F0B2C04830E69A4FD1378411C2F287EDF48C6C4E5C247A19680F7FE\
+41CEFBD49B582106E3616CBBE4DFB2344B2AE9519391F3E0FB4922254B1D6D2D\
+19C6D4D537B3A26F3BCC51588B32F3ECA0829B6A5AC72578FB814FB43CF80D64\
+A233E3F997A3F02683342F2B33D25B492536B93BECB2F5E1A8B82F5B88334272\
+9E8AE09D16938841A21A97FB543EEA3BBFF59F13C1A18449E398701C1AD51648\
+346CBC04C27BB2DA3B93A1372CCAE548FB53BEE476F9E9C91773B1BB19828394\
+D55D3E1A20ED69113A860B6829FFA847224604435070221B257E8DFF783615D2\
+CAE4803A93AA4334AB482A0AFAC9C0AEDA70B45A481DF5DEC5DF8CC0F423C77A\
+5FD46CD312021D4B438862419A791BE03BB4D97C0E59578542531BA466A83BAF\
+92CEFC151B5CC1611A167893819B63FB8A6B18E86DE60290FA72B797B0CE59F3:\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF:\
+21436587A90000000000000000000000
+
+# Generated by Botan
+
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E:\
+D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+[Serpent/CTR-BE]
+F3:3A:\
+740614949B42870F0851A0D639A37AC8288898B0F9CC3B326B983ADA69BDBB76:\
+3377FFD0C8093067A0E33B8700E2C2E1
+
+3018:053E:\
+872BCAEFB1985B9C10B1F2DE2790E22CF31C362AC7276D437D0DD697F1682BC4:\
+53C8B7C9BA119E81AC5474FB70BF82FB
+
+C503C6:DC4178:\
+DE3317D05233577D476509E638486ED2ABE26ABFD847C13A8AAB189F322F46B8:\
+47D690C680A567B9942BBD0A2700B884
+
+FC9B1F9C:89FC80B9:\
+A2B4D60F8F9B35C56168D80E8828F3931A5BDA190E65B9B06A814277DB2B4F63:\
+B3B98D928D3EBE1B9E07B291ACF9CD2A
+
+F1CDFB642B:2BEBCA6F33:\
+E39D7D09F410CDC21333D8EBE5E33E7A2E24872A99254AEDAFFC633061C32EE6:\
+107FA9631083DE98F5C72A383F541F3E
+
+9C3BACCD6154:DE9920471C92:\
+9F7268895714AFE229162D50CA59F1273744BDC28B198E1685F4323AFAE1243D:\
+68C5EEB64FC3DE106B99C0896CC0689E
+
+B5602241E6ACAF:2FD52D0292019C:\
+27757554DD1B5BE2E660576FBAEB238A0F7642F9A65771B69AF276A57FC04354:\
+9BB3DB1661C90DE853294D20A369B999
+
+8E27C11E30E23C5F:0294FE7CC3F020FB:\
+84688112BE481C65B282D4DF9A953526AEBF05FDD2F3D84E7C32830E3BC185C8:\
+3ABFC6E1B2358A3B968E416B9087BBD9
+
+A4CC3F182076E93409:00EE68EB6CC635BCFB:\
+967BA8A79CCD302B294E519813B72EB5C4D24BD86322FBDE08C292C2DC4723E8:\
+D7DB3A2BC532D1F1685CB612FBCF33A1
+
+25B63E2B38DFF81FA490:E75F1A6DF39CC7A76D12:\
+6757B7CA6D7EEBFD0E679E18CB30D16ACC71D0B1A149DA27E439DA1BA0BA37C9:\
+3199830075CB5E87016EEAE5B0B26F13
+
+310605508E614C101E829B:366A5DCEB8E76183C95CFC:\
+F92107A1778C99C45B4E229567BF5CCAB2C5B1204052B8720161AEDCCF57E36F:\
+378D5BF003FB48A4D183D5227151FE11
+
+6A706D5F6526ED4AAEE00D7D:8145258ED5FE88C34E671101:\
+F892DD670B66CCF6B8E458A6F068FBA79F4A69AE3A028E43D8E219BE940BB826:\
+08BA9435AF764BE0E44515FF72D6DCBD
+
+FE62E34899D4115DF7FFF51A8A:66F68C5AEC9A4BB123056667D9:\
+BCE52007E10A2CF3077D00225C95F2D68FCDF380AC17304553FBC1DA10117B15:\
+3FFED78824BEB8D6D655CC80190124BE
+
+191D3CFE172BEFAC1A8A428DF951:7CE0D419C43342FD2CD8D56685BF:\
+534A1F49FCD2D99E2ED2F094E170809091195EDEA2ED94EA4DEE64F9A6F89E05:\
+D98E8D86E9BE95318429FD7286D528E5
+
+2C92024B2587851C0F58C91B822DF6:36FAB117335A5F0C619826ED801670:\
+41422F58E73BE8C494D750910CA612B2FDA0A41D041ADDDAB4144DF30CE7B26B:\
+DF0771CEB11F1BAF934289FA42F54319
+
+0CC08B6ED36673C0591901E14AEF4792:250C9E812F38A9192CC65C6EE5B9DB60:\
+EDA2AFF3C4923D3CE745EB78655B0D27DBDB5C584AFE56564C7B625903CED927:\
+95C67856E6EB7B0E98F0934A47DF6485
+
+C6B6E1F1BC46E8377F6C397C136461973F:AA0C36B960BFC811185F74D22356686414:\
+D4FBFD37C5B9D12E5E43D1867E1692A2B331CAC9E6C46C228A45E95AFA303185:\
+30B9693B12B7F48C1C07F1441706821D
+
+CF1DAFB2581C47D06D8F178787729F8FF457:\
+10510051990A826CFFDF9014CA0B49481E39:\
+47E9CA81E014F6AA4F94A7C0B8A533B7A636FF14E76935D9C7A3CB01E3AD64E9:\
+DEE733BD4644E258CF98F7FE87AD8E5A
+
+EB95043E36EFDF2B5FB8F17B6806B2B021D1DD:\
+A739171DAE7EC95CEB492183803D37165D1A79:\
+6BBA2F42B85C58A4916F618A294553E084E223739F575159DE9EC4F5A63F3AAB:\
+0DCA755F625F78C363AC7EAB801DD471
+
+3277ADC7055990FDA21C89F183F0A380E71B696D:\
+610369449E344D609EEB89210AFFD1C90B05C197:\
+F3702792DEFB775F10B142CAA78D05DB26A4A8061CEB39FA2B4A27106DE8D9DF:\
+5C8EF39AE0EDAEB76CF3C10B94D1A002
+
+43733C60414C054EACF68F85C67D547AFD0003AABA:\
+E8F7CCA960B713991BEF20DEB3DF284ECFE912B479:\
+AAE83136AB1EC19B3BC892B0B5E8EC7A6E20FF5AC6C126DAF6189A7E2E344AF0:\
+C99EBDE92D57326A37B4B6F2C19363FD
+
+E2ACCDA4075886B085C7A7B71E39BD23F71DD16BC4E1:\
+7A0552BA9DBCE00A60AB31F8D0E590D79E2EBFC49713:\
+222373452D105C2F58E87F5DDDF07FE464E47BC8309718FB30674770CA24FD34:\
+A03B629DB1C399F8EE32A7C08C0FDDB3
+
+33CF3C69194FBBD03B0496F1982C570B363DDE621303AE:\
+8D2763FAD25E2A3BA7F4EE3ADA3CC05310B453734EEC56:\
+CCD9F95EB29B2609CB35C959009B56FD43A60B4353A2F3D60FE78F2219074330:\
+884C24E8368B3DB123F47D03F3812F12
+
+32DE0A03F6D52AA26BEECF4AB22ABF3A49768683F86EA983:\
+D4EE5E9BD04A09D73DFA9752A8DFAD00F151E822052B500B:\
+F7C88B964D55E40A04D8016900A3449015D6324DE16A024C0F9FBB1DE505C1AC:\
+308E6F85EE34ECE3C70C1EE2CB7E6777
+
+52F14AAE8ADB041BAC458EF07FA247FE50B868888089587933:\
+BE61DB06D28CA4D3B418F10F463FC42EA254929C5C87D35418:\
+972C448AA251ACA8F589BE0F5793100D14EE3282DFB321CE5943FDE99D1F31AE:\
+11C202F46DC54AEDFBB543C3A55E7DB8
+
+E56DFAD59ECA41C38A68C64388CA4D2CF94B319C65E033C26A8C:\
+DC4A5B96090CC569B623D54BB1DAA4A7B6D879F21BA420D80637:\
+DFFBD3EA5DB1F4D7D9613F069BAF8737F0E37A33BAC9A9AE2EC67FF20E37442D:\
+17E670BC9C590D7B320A233232D43311
+
+A89CF708448D7D4B1BD8C252F9EF7A0A7D978A1E862713F807E0FD:\
+A244860FB2E83D608B25D77ED4EBBCAA7C2AF886708002C77EB5F5:\
+A14BB231478EBDBD7B6A7D7039559099AAA281D25D095F286B8104DF77DE0C8A:\
+5410153016A90F03A3863EC58BD66004
+
+BA6C11D80E304AFD1D922E2B35A47C3ACB34F7DCB7826F76A3C469EA:\
+CE19CF171B181B3CC5261B5A38E9142DA7479F88A9B0F7F63E98BD7A:\
+B5C0F5A46D855F6CE47CAC0198FCAFB7432AF8810A3746A90CB440DC2AA1CC9C:\
+A1A57176001EF2B0417FB7DE1630AB54
+
+90D97D574AFA947AD194F3B94D17D83073D6ECF2FDBDD5CEE09D3D553C:\
+5139448ECB4D8B454563FF5BC6CA47D9BD23329E772F03E4C661E4CFA7:\
+D684575372F4EC2F0131D786EF6B9666C38D2E99C2DAB7ADBD1C9FC805DA4229:\
+81301A434C73C64DDB94440FC887542E
+
+F4C312864C4FF38BA8D285608FC924DE8E60F4FF0E603AC7D3548CBCE1AA:\
+04823EE2C43AE04312C6F538F03DB4635D13026D546254A1E0BF5AF97B58:\
+7C3F63710A6B10B0131C5BF96BCEEF6AD226FC25880A975E355CC2547435D861:\
+B3F1E356BDCB368C8F1D306DAFF59684
+
+9F188A9CC6957F8408FF2A93AECEABEC0D6484AAD13C88060CFA7C52F55130:\
+FA96B9A0FAA199FF22357287FA8DB515ED3D522039C3FA649E5BBFDE5D0D79:\
+8C263F3C683F2C78E8607AC7E79C703F0F1D872BFFADB07CBB9E07C62624291E:\
+1BED13CCADDA5A02EE6F3F529A7A97A0
+
+6F129CDB56D48914EFAE7A534C33D03280CF30D12389EB5119106790B84BD73D:\
+29ED54DFD26F097312C42848BD496B78436F907238EC8DBDB5A22FFD76CE76D2:\
+69F48BB5EAA67974713FA974EE645B5DA6B8E5665CE0E40347575D050755EA6A:\
+CD6E4DDE0DEDEB87B7BCE9998F41218F
+
+49407E33C46EAFB24B01BDF5300DEA35AA5BB5AEDAAA2B5E47B2B63753A44F71127F:\
+DC0A9F56FB2F440305B288C1C0CCB896B21D89FC3F741034DD76B6887740C5CD4A20:\
+3AE57D49BAE4C54AFCA650206B3FCBA71306286F1B9A51624CE3CF08B5791CB3:\
+75D84A34073AA6331A8990572C5FF55B
+
+C34EF208CBE5F148CCF3E005BD2168C8D8346B18464EC8A6C8DD156A3ED34CE35C2A16F2:\
+878A83F17390490E68D50937BEC73D4A5BD4183ACCEB0D582464DD9D3ADE683E830E8C24:\
+F39D1CF76592D48DE487808FBCA14585C15F29FFB7C9EF9A4AF74B1DC29459BF:\
+50FE7E7F598B4FC4D0FF6D256135861A
+
+6732BDCFAF3C9681E5684208D5C49354C8C221FBB584080639E3A66C0CEFEE4662BCB787\
+FFD2:\
+2B40579DD8E87440DCBC664920573309D3342DB52463F76FC7BDDA45861F8775553129F9\
+48D6:\
+8B387194C2E79916F5D2B5E3145B4F7CBDF8190EEBD05B598A3F44D1480FE045:\
+6C7EAE05E72898C271A3D7F1668532FA
+
+3CC7B907609C374805F3E0625C2A8B77BBFE8C22860F749E4871541D27BE589B21773489\
+E08EBFC5:\
+FCE9006F2073F1C64AE42908C2E7F21EF88422526423ED8E341F869B2EC8E9BA679E9028\
+102C9BFC:\
+60FC4F62E03E3C0ED6DD21259BBF3D4C24031DFF6A20ADA2E2D637CD0FDA2351:\
+6BC92664DBE433FC2580850BCF0E08DA
+
+741C912167AB5A5AEE918FB21480A2EAE39C0038A458A34D4AF86F6968A97A945B4EBCD8\
+D74E5C1D7388:\
+116F94F7C970083C2F918454F7C5740F3F92FF83BD5A0C5F8DE592FF115171711879C6FA\
+739E14D0AFD7:\
+DCD3F3A96FEF4C6DAD109A65D574842D04029B155BEA7AD54D25D3FF8FBE5A2C:\
+DB7728ACBA219FE1AA8259448BE3D6DB
+
+CAD05D525C37CA43C187403F3357EBFB580ABB2F782CFA7B9661B1F71B1809920EF0D897\
+13598CA4749763DD:\
+C17D53A4B37EF4AF33DF4E0F317BCF8541ED66DFACDA662289B261ADACCA3D4C0066159A\
+BDCB108BBF5C707E:\
+0CBD7326ADF581A058CACF74A3404D3CF9EEDFAEC8E47BB30BC1AF1D3660E0E4:\
+C4DB5DDFAEE532C12B7313A9258CE63D
+
+6032DDB7CAAC7CE2CCFFF53592FE2F40280F8C79E312F4DDE307E90863A9CA18E320E0EF\
+27B21216216FFA8EA570:\
+5497807495FF72FFC8C994E00CB5E7F5C521C86965FB17AD3578EE6240233A7E2C9FCEDB\
+FF7F1B05FC6DACF4A0C5:\
+567AF81216E5B25179143BC1C3AC52D940F93EB4EAAD54AE0A6F33661CBE0EB6:\
+EBF6B3BFE42C2AC5AD0B02B7D294DFBF
+
+F3DB2D14DDC5CC45CEF2986CE9775A64C435B36D305DB04A75FFD3BC83ADB8595397EE9E\
+1B8137A8227535B3984A7267:\
+7BCED3DCD661CE1BFF9A6D1B52D957D12E657DD6241F64528C496B6D5A729783FA011AD5\
+788BE7DFF57D892A0ECE7A92:\
+818DD281DE7C051FE22A5CD1FF0154293556D693427EF49CB72D31E05B91FDDB:\
+4A3F1F5AC035B0D18543BC763D42D61A
+
+83EF6209E5EC332E9CB0A2F73EEFA34EDCA0DE7148188A5A5E8AF5812EC9F272147901F3\
+8B811FB759DA8060A1F93E972204:\
+C4D6D68DF04F55151A46D291F188C71E3C59C06319D4A6B40B86312E93ADA7EE4CCF495C\
+D56E0610ADA4EE49EB4982601DA0:\
+06ADD322678535E83B950851EC12D6DCA818D19F1041F69919A1E0A16D868ECE:\
+8842C25CB6F1E93F2485204B8DF65A61
+
+14D9C539288AF393FD3552DCFCFAA4EF497514E7101ECDC92E875BE2D958D296FF1BE307\
+DC5AFD29F71460DD7F093A392C8210AB:\
+792DBAD92AF1F5F5E5AB14060E6245D4175A6D73910FBDBFF76A08493464827A108141E3\
+83E3104E3F4B7EC645FEB7740A426AF5:\
+2638477FF92C0A140CA99B62CDF46452AD58B01A2DA667BD5EB3D425E9EFB5C6:\
+FC9E9308891984AD0B305CF160A64B45
+
+C4E76E643B92D878A7BC2693EA1D0E1E86A06FCCFEFBD91506D2B8C6024490FC965F037C\
+EBA97C607F808E48C9D86E40AAEA079FA7B6:\
+66BBC945447CD9FC87CB47AE7F72FCA83696BE3BE6396ADD9EFAB87A3BE17718CA2E49AE\
+00758AB922A2F2049BE84577DDFA228918C7:\
+ABB8BC67A8299C34C4B97105230E203F1BF8032C876E908E6024F31F0778C2DE:\
+03C8C55A12AFBE4B5930A8D8FF80F1C9
+
+C8A5C5A939F5872E56BE199D24422A7B99F797617B5E39E02729AC05ECB1990CF8D287B0\
+8A718495D9F261E9110E4EAD62AC789918CF1CEF:\
+23D2A8B6508552F2075D340707541547F37E622DF4DF55EE3E0F4E0E610216B7E4218358\
+ABFD86EF3A6A5739A0EEA49267AAAFD89B28D5A4:\
+5DBF7CE56C2C431FC9B69EB80635D0B7BF58C7860A1EBC876914BD040978391C:\
+9E2DC1FD8EC1C9E1FD0D5273F1379D46
+
+37B26B33453BC31C69BD09D5778E04AA8F5FFD7F367727B30246C81BB92F9ABC3DC9EF72\
+171C3F38B76CE887F647AE42D87319D4209857EBAC0F:\
+8F85405DF5DEA595B58FCE86713593BEAECD39B4F4BD11B43024A5FFBBAFA0F4817AD6F9\
+2C111C08506056654E003CFF9A60162147ABD56BB4D4:\
+6A3CD1AC06DC7198EB08F439CFED766EF40551B1361048BD17B1A88E9447EA27:\
+23783203B030B2AC2AF81621781FB946
+
+44DE8E16D60C2CCB0E804ABE95CCF7CC597B1A9D0B3FD15BA2CE321273006322B4EBC4B5\
+BB90E1456947B3B289A9F6DF266FEA780FA13A2CF50A0882:\
+03BEF28AED188F7AA6128016647546160DDDBE80BA403CC4F29D9D90A5761075B170D1E2\
+7EC6ED96E7A329ABF59F7016F4BCF39F61FD82C010B4F7A0:\
+1CA7FD4782991006FF0246581729BE4341A6556C61FEED749EE9F48DE8037874:\
+7DD54BCD7665BD84E8DBC84F367AA008
+
+8136A889B8105FBAB44325DC6114F395CEEA87EB6E69D35C6020AAE00B47942B262157FA\
+273B2317CE08255AF899CFAC6A83AAB7D4C5FE5729A64AD9F8B7:\
+2D6B1B438E8F7A70555902ED6FBFE2ACFC371DE250F32C9D5B75321913837E36646DAABC\
+E5B69AA971A0C6FFB5928E0A75A13E004BF241E73754B74F3947:\
+9E8BFDA871A63F32DC05F53D1859291E6B099E2B4474A43E570D6D167A2E99A9:\
+51027A0552EBF97D8372668BDF106F46
+
+80E71459F0F7DD4E490FFD23063D1F741E44939770B6128F07BBFBD48323A2CC7558A4F4\
+CA4FD9C32A137C5AFBDB278A9ADCF66B0CA5086D0C09126A7FD5D20D:\
+AD68A517A73C9485AE996D79B90344B5ECAE6C11EABC4F268B165232F7A062F73FF46E7C\
+674C706F14BA70EF9C77D5E6DF90CBE09114AD4E60417A597FD896D8:\
+9ACDD36A9AAF77D9E2C6286DC456D461508356818F4FC2CBD001A94037E42E1F:\
+0EB87233AFD4C552D9D5ED5C415F03E7
+
+0EFC9979CFC65020583D4141A6422CECFC1E816B8682A1BF73D05175E8A2E83DAB239DB1\
+5DC57C4ED427EED3C73491285767EBBFA20CCF1CCBA594FC45980A34C659:\
+ADECCA8B5879B64CF35C8AED809570D12BA0C0EB19C319C0B9FB1A0A33C04F48E2B755D2\
+CDEA8C0582019F7847DBCEC023A4AD27CF4879C07CC33CAC9DCE9C47A491:\
+B0B664A621FDA57B3DF93323B61DA43CD55EFE1B1954A8B86CDEF4963E082B5A:\
+63DE5E4E1401030D736BC327D9DB2BB8
+
+FD8A05EA9F872847A37F33D66906C085D10DD980435028CC0F7FA168CE8363A8A5420E33\
+67DC06AB69C2DDB49C1BC0E32E1F1316EEF18C01A95C23B3342ADA89C131E42D:\
+B0A2C09A27F4128353DA11A0797B63AB54E2CE00BA58BB765C8F6F65930E69258F2C3F30\
+914FA964AADEC9B8DAFE39C58757D65CFF6702B955550C8A494B64056B906FE0:\
+6C62EF4976E50622F623337E32D70DBCE1E423B4CFF652C2ECB1D3DD194B8722:\
+B7F60B3D94FEE7768CD92148FAFEADC2
+
+A592978733D8647858659889303CAC080E95C2B2B26642520CC6B8598C146DDEFBE1E4C0\
+68F3FC0BE9CB0EF3D61000F2E688AB2D9DE7B7A28C3B32AA3F8B872F91D2CCF9C927:\
+2B3D0D935877281412DF2AD20602D0AEB7E375826BECF964E5EE29A8EA1B20529943BE59\
+5C099BD2EA0F70ED95BFF11FDD52069274E8D21B00AC5EA11369BCA9E6052F1ECE13:\
+85357F480C3AC5C8E412523D2C6D45862CBC91394DAAE40BC20C58DC7FDC113E:\
+CB11FF4AC49C513BD56A79104FE48F89
+
+60C42D6EF79C6FD920FEB2A9EE00EDDF34B3339F99BF13ED42FC65247166B19C42099DA9\
+089F8131856FAC9CF0703AB9C73DADDDF700290479146F67B49770CA9B53511D94F6D7A7:\
+35409AEBFB98BC6CC70BE661EADF99C7E1133F912D8FBB957A5A61AFC01E622864C1AD2D\
+B0898B0D3682042A510D65584C7EFE9517D0CEA31D3385C857AA334478BE651DC48E81DC:\
+53286FB5B6E08E9177CA17919D845A958B7D55361DDE5E9B09B40138BE3F68FA:\
+D7FDD75B3F672908845354CDA2EC33C2
+
+55204AF292A15EF0907E3A05FEF0BAB2FC199A874FA3B72B1959CCF5CE59B1A63BC7D0C5\
+709A1EE8152A11423FF3D021726C9B914283610530B80114A6AB16F1821434CA0B5B66C5\
+1181:\
+790F49950B195EFFE12FEE3DEE248147793869ADE0B46B412F702C4AFDFDC92A95889D45\
+F1828CAD935CF281BFDEFEE68057906564E63509A464206A3939C9787AF559C2F18E857F\
+9794:\
+CA1AA91974D69777335BD4CDE41584FE09A0F90B4EFC1DAB01F5F6EE475C5B26:\
+A753ADB21556F5166B8D0EEA24AF4D20
+
+F1B63FFD3C223E65972E716872206B656F036AB58CDC6BECF814B4372828651A28FEB0BC\
+6F7D5E008A0C9D069C5765D9613F75AE3CA564089840C2E5326AFCBB73E9677D60261C1D\
+11DDA8D6:\
+05C44E476B45156EFD1A73CAAE0CCB4A02E7A3BF461377AC5573624F3CDBB03E5F040EE0\
+0A628EAA819B84461B8F39D63308C5FCE21B823AF0508384E0A5784B99FA47AE0A15F8A6\
+31CADD11:\
+67EEEFDABDB4E221A3F5D331E021861D80B3E52EFD3662FBE4B7F96CEC220668:\
+ED8A0E2821ED9E46D9E47973CCF4FD25
+
+415E13F78C19D639C7E2A262D03D17C33648D7852706B0787C5DBCA2F7BC09FCEB3C570F\
+CF3E121AD6B9E467515998EA53B59532A5D0C86125928ADA505D07E9C0683F0F2862A0A7\
+09B76B9F3E5A:\
+96D6DA75EDA6029E162A70667227790B28DD1D08731D08024FA175861A30D321CF95FA07\
+A96077F5F9F3BD0EF809CBA394726CDFCED17507C89295954F7AF19E7CD513D18869E7B3\
+418E193DE7E8:\
+BA8A42A5079A1211FF373CADEDDFEBE4230384AE50C0CADB777689E9FCE03021:\
+F2CAE7EFFDDCCC54DB0DE734347ABA8D
+
+5ECB18F27BDBC1469A4EE7273423D51CF53DA0BBCB3773C04F90934DF1A4E686B76A2CA1\
+9B325F91CBC13CDE9FBE0E7FB1D205D78EB92DF19A5AD39D9E5CC07A4329EF14115D5A89\
+4F4669D6B6C3E920:\
+47D37261C8ECBB954E6980BE6EE8A89CC31E83CD8703AF97B40308FC71FD5C204C9FFF43\
+B35BC9709CF9089BE6EDA572EC4B580F74A3C25741B147D3F2D06A7C5BE8AA35DF232546\
+F93B603A91A4D4AD:\
+00B1CFC598BCD9B708AC9CC600AD951E95228C4941FEA43D3E9F9C4C4DDA9F57:\
+AAA2D1218D7E5586150602486330D79D
+
+ADCBCF6C2797D693DAECD8B395FF2D8951D9D58748398E1886146CF39B6BBE94AE5725B0\
+8DAE80061365508ADEA2F7E27006BC2EB8296E441D9ECF3A1F105AEB72A7B7ED65C0ADAB\
+96DDB4C56D3E6CE7EF9B:\
+204B284617F9E475636543C231788FFF1566DAA35B7188BA5502116479D8CFA3571726F2\
+3F83EE62960DE1C5512364AD31BEBD71778926B4DBA86C69C87BF62D590FF01D43A7FCCD\
+9DF526738DA3ECC07313:\
+D9E06DC86E89570392B95234B2B4DD1D424FB5D96D8E5EE6522EC023247240CE:\
+555BBC29444DF1C9B19DCC36E8F526E7
+
+D1E3667AE3F908CA70E42ADB571765C2977A7597AF1E93568BF144FE6B8774AEC889EBE1\
+C55EB673F2E05C9049FD38FA112413C1F5DAD6400104493225B2A1FA2EF314267671682A\
+96A15FED5A0920BEB7915759:\
+0D8B1A4D0B4BBA07DC3D66FEA6C79EB79845A303A99D0CA6A1363494FED39D9B2028323E\
+A66F48420620AE16522CA5C036984E431645D55BB71C9729786A2942D246763AE14D4D7B\
+E8182F4412706F88D745D29A:\
+8FA2C547E80F8370524EC80BE768591403BC8B84A31E823E1EA7B58D13C2C1A2:\
+FC552663E080DE3AF70F1843B20C2321
+
+9E66CD55C5F5ABE2D9F479572D1867AE07654DDFC4B09603A7268BDB98CF22A15EB207C0\
+5946957927BF3442FB92CDF2BC64CB1AAB4267884C65AB29F7C7F1AAA0C797DA1BDC2FD4\
+7E02566998933F0371F054AF75F7:\
+4998F91D12BD0CD7C9C3E4D7E4AFF383D87555C75523452F7764B8CB017DE1C9775DEA51\
+AC4A84CBC77FEA7CF4D4ADB3F79279E73EB443513AC9FBFEF3F210F80C553C758149CEAB\
+515578E988A8F49D4B87CFC7C3CB:\
+EA2BA62A693024D30A6F86F92534B011D6D8ADC81E6DF43A15F1A38B077B47C7:\
+B09F47C60D4A913E80DBEB9572CDDA2F
+
+0B515541E94644E05C6D33B0DEC22322A23EC8666C40697D58B0D7E28FE278DC8C6747E6\
+0924A09442A04C167D48CAB29D095BDCC0EACEED2C841FBFF1010769D8829EC1CABB235D\
+CEE28CC09C4D905CA1CC8BE624298D76:\
+0FAD0D901C43395C015B252EBF61F66FF41713C2DF9AD2245E1EC1ACBADD2007412DE768\
+E5C986AF3F26FC489676AE5F7507AF559A8A23B56C417FA1452D92CC6671F6E4BA5C1F60\
+819811F9704953BF349CA5C4D3A0631A:\
+E659BCA785C4BB8BB49DD36F132EC4984397B2665B97689FFFE7509F1A1D7551:\
+069C61C342C4DBEC240C709C3CDB361A
+
+D2C5A20331AFA2FC82F0A0D64160B4EC447FA5572A26EC3C64C9F736E43B0915AA7C3E1A\
+B6A9D36BE4A15CB26820E29AACFE83024959676FF05376C1AE788D276079F199936AED0F\
+0F688E42E337329BEF9336FFA36FA4005399:\
+7DB91F84F3477868CDC873EE908DDCAB90CBCAF18C0A70791A120AEC86CDB215E6221A70\
+14482F9E3802EA3467001D3601A63C92C6AEDFB4946845F13A52351CDCC6D5F922D19DD5\
+B1EC236E822F62655427E62A4D0E84914622:\
+FA7AEFC8F4B784C193C785B93E90D08F8523FF065E19B2F8CE817FB401A21FCA:\
+A66594B33C8A53C811C2D97CA6D14303
+
+7255CF6B4E647EBC0AC95A5695F0AF0E9AAF91E3D95749D6A49719093B1200B9C6BE09B2\
+6554E36EB6652041744605EB051062C0B6D1CC01257709F751EB7B9667AE7E329E43EFD7\
+44D96300958FADCA3C106AF1733CBCA1AAAF823E:\
+E3D3CF5237D3A038F5F6C89EA9FCA960FFF212211D3C2CB3490607C9957B553335B18C55\
+1BA25506EB2CC3BFE9F3EA6CF0AA9EC434AA592FF77B61BC06F0B2B95AFA8FF5FA494E94\
+DB731F57DE8529ED53A50C42F986C16EF7C7A940:\
+A26E2B0A05D0283D38D7169BC2BA47226EDD259B8D57B381FFEE069F1B98046E:\
+C4E7CE77538E9914BEEFD56DCFB571B9
+
+AAD33FEFE3F84DF826588A512B14CFCC1D853F2AB84203C1D4D8F8B86D6AF3F7173F6A6A\
+A73843D5658489507104DA3D7BFCF5168D986464C3448F234CA69BE3DCBB6672575564B0\
+2ED92FA0F3877DDCC06D502A33D6957A0E33F2DAFFC9:\
+CD0C9764841179AC19328315A39CD34BAC626AB5DB485D0F9B46059F54E08C5492B908DE\
+07B85E7A44EF9462BA8E0A81FD1220C558295A948DA4DAE908535719C1F88B1560673BD8\
+07F5262483B40AB9BB0C64926FDCD1061E504B4EBD76:\
+6EDD7092DA78BAC7E1AC92E3770134A03D2739FF5D34430F7F4D4D6E9764B319:\
+8AEEDB0DE46407E08707969C750E38DC
+
+8168FC2661FBA3600E59774138459C2961176EFC931CBD6B5C33560078EF7518635D6939\
+A98B0767639E0E93074057CCA6883F7964A1668FF9F8210E95D0368F6FAEE9FA8D7D7779\
+2AC00EA2BE1146BF56204FE906FB865AD039577C01234AE2:\
+51A47CF78D2484F3451F0C2A43EB428379D1F6893C1B8A39FE3E60F685DC87C0B840E9B9\
+6FF58B5D5FF56AF2D9E6DD1B2701C68A0E845D4D5976BD315A353D67347BC8730CA8EFF3\
+AA0DF4BD6DC8E05F7EA07EAF2C39D7D47D9D84B474E7ACE7:\
+BBF6DF7DBF4037FB25B611E6A2930DABF072F65AF0A6457CB9DC93972E9ABE7F:\
+501092F826689BCDFE80F092C26B5EF4
+
+81EFF330211A83455CB238BAB684E0067FE4067B8C991BC1AC8E7633D080339190E5D94D\
+B793154FC74FB0AFDAED0804E3C1CB51D2C1E13041FB81B2157BC60C1FF633D16CB4B9BD\
+331420AA12B95CC7AF57C713C24B727846B0C7227961F2C2D36C:\
+6886E3F70FD5F90852F3CE559925D769036D93CE8D9476835D517E0FB32E9C96D0388391\
+30C1C25E1B169ABE4BABA9B82C4ED74DD45F597867C5D53A0506AD37542F25CF58F4A362\
+BA222FA1DE9038A8FE543BBB44D85B2E0E4738067BDAE5DF7060:\
+432FFA626DF2A52CB0571B6E90C61ACED99991FCE9C16BE3B63F32BE944E2E56:\
+5C8A73A4AFFAD697BA8B1BCD810D8F11
+
+EE2EEF94470FA795A889D2669CB2B80D3155C8B61BA73019CCEEF203FA4EB1D9AF6C1AD3\
+B2954F7315935535333C758A4EB3247E19B07308569400B897322A4752612F0FF13FF3A5\
+361DFE0DAA88394F3642B1C6270718F28BE8C76C89ED29B6A6B0BF94:\
+BA17AF1457C42E6E6FDF4F98C8E45C0FF78D4849039ADCE1A168A6ACEEB9F419F49125BD\
+F26E443EB783108219A2841F82499FCF6870724044D9CBD95AE1F4E2A3D4A4C44C54B2D9\
+90E0DEFA120414ADC438E66B298B72EBBFDD7BF38EBDC44143E16B69:\
+A249D7A363F984C302E92C5F94F8896DF3F776225C022878944FE2C2CC5B4C19:\
+5EE7A0639A58783D7E82D1FE5AE0DE2D
+
+577B77E72EFE7CADFD281160BEB544AF2F28B41CFE4B92C5D770B322D40DE7590090833A\
+12EF4FDFB0EE57CE0A4A36AA71C0C39B33E78EC4CE15CA6400936E1561FC6206916DE9B0\
+3BEB08F90930048F493C05BED453ACC98FE7AB2256B5271A1E8958D07AD3:\
+A34F475248B72AD9BA2F461A690921544CAD263EC739AB3ADB4E42652A547553B3A303BE\
+29F23BD9BE7977D6750E50A2106ECF52C0A6724AED2EE8D482D09D0D2B9AFADB78B357EF\
+0F52E027243D445B5066572B0CF8812F3E19475650FE85DE610EEC640091:\
+AFCEECF27458C2A9B8F34603C639A5FF1250F1D6DEC2849F0D74BFDFAAE36660:\
+5C453B6546216E318A6036E803322401
+
+4A0F51F3716D41FC3E5264557D19CA35FE3B70E215AE6DA3990D1EFE383B9DE7E50DD085\
+5F751F95BC093EA76843089F284CA6176D2F25999230F6A5B9670059736CE084CC167274\
+9504BEC04B22F26045366030599337D1DCE783ACD0BDECB76DD4E9E8D4BE9421:\
+D747558707BE24371EB6DDA6B5FF138987CDC42BFD71D75BF1D6DA35591E4B35C32F9F07\
+A1C0B82A55AD28E4DFFE43764A814CA13D60EEFBDE3345BA454D49179662ED53A9F3FFE0\
+92D8DABE481E3DB0D7E34D6296102BC45D61E1719C864FD26FCACFDBA986A6F1:\
+EAA4738DE7B609D36A756B5DCEA1CF8F4359248FD8A423BAA925F0B6BCA7DBF7:\
+7DDE259B3EC5CD93A2734626A9B99FF9
+
+D8D191D620CA6DC8AE66658AC39D87B8465D32BB2637128191F0F92E47C7E99E01FD4B8A\
+8BAF767C8D66EC280C77E877EA06435A7EB72EB477CC2BB6DE52160E7B66F305DF97AC35\
+C821F418E1FC56FF8617B9B595CE824207099A8D9CFE24B616F14EBCFAC508C37127:\
+6A320C22C68E984F0308A5D626C16343D268693F283FD71885860FBEF767B02E16834BFE\
+FAA78B6A806D2E0D1B54451532B4F77365989259B8B48AC65C0B730951DE373B4D51276B\
+0D364BED18782613DB2057C4EE9AACB56CEB2D0857BAD4CEB9A190AF7B9E04B8267B:\
+EA42B4BBDAB135C2B0BC54A539D5C9A3D9B6EDF21C92763CC8F468BCA9CE5D2C:\
+013847F7E5082E4F5FD6DC16D754A80D
+
+A7033720AE2A602FDA4BA5127C4EE042858D0376774704D582986A848B2A0DBA6DF135CF\
+3F1E5D65F68E8940858A35E9C61E7AE2469CD7B08BE72069354A2A13955FA21FF3B4DBC2\
+712647AA20D73428D426F9B279B5A0C82E2A2620F836B28B03BDDEF45FF3366DD9AAE66E:\
+7FA21E16C5213010DB8F3DDBBDFE1E5AA16696875F632EDE3CB31B4325C4E2135B9D2C30\
+42CEB5415306D0FD7AE237F26E3F135732BDE6C753D0D844AB8270A094D5B24F6C753EE8\
+6455B2E936F2F5EC5AA4058099F6929C95AA2AA6CF70CB2C519D6854579CA23192AD83BC:\
+AB8512537C3519628BDABF83E005E8685A180AAC1988E48E39A95030BD4FA6AF:\
+693E3B87BEBD7D144FDFC1796922F843
+
+E84897FACE6ABD7B897B935DB435C22299FB4346BEE1C4381948622ECF3328172D0C3A48\
+A30EA2411201A5907778C994EBE29637A290EE6DD503B6EF1D53D368811D5DD731E7E44E\
+27EBB7382E6AD4C74F49FFB62CCF996FDC7710B943334284A38957EC822B4F448B7482CC\
+B972:\
+C5B740D2E9AE85FC5CFB4ECD1E375C05AD9E5040A8FBB149320C263150A83F2DDC3FBCDB\
+DAEE0BEB6C1CE6EBD3713DCA848F87200922C1879238E49DDCA5F931F1EA2CBC586402AE\
+B83F1BF2175341D4937CAA2B97F4BB51BDDA63C1F50686F2C40AACA7F1F049F08D43C6F8\
+7E06:\
+69BE0E539EE3C48F260249A10B2DCD3A63BBFBB5AFC85D9AF388B79240674A6B:\
+9A1C7753E6140825999B5695A2CAA7BF
+
+54D9C7F322D68ABB78ADA56EC4B23C1478DA181F30C32732C9ED38BBDCED81F063255395\
+C52E8EF6BCA23CD23A70BDE242DB86265C11777A13CBC9752F2ED55CF9D816C2F83AF85B\
+25001D486F5812E39F4F661044091E10C3429894E92EA4F87CC998E22ACBBF867D3B5B20\
+C97857C9:\
+1C4D79F2EABBF97E147FB8369933B4C7E7BA77C6A539F571AC2AA8E37C5D8BBAA1308DFB\
+BEB2F892BAE9064692A20B8A2CE2A1DD8879160C7E46E2E5039D5C32E50BDC961F3A7DBD\
+A36AD5043A87C9F0583EEAF9995994E764E19B62CA4410A87F33DEE40747EC23CE6E41F2\
+80858149:\
+B66821FAD6EA6320F3B5025EF909411DC68120198DB4B2A7BC148EA922F64DCC:\
+3A875E75096B58800EE21B31E39BF38B
+
+0EDFD9C739C9F72766EF8962032C1003669F5A648B0D21943E99DC5BF7A2507985223324\
+2187574B279FCFB57182F8F9832AA9E44D15ED2D8386AE4572986FBBE0E6E0D5D3AA4DEE\
+E2188614F7A8A381B335FCF9B899B86685320D457D85C9F761EAF43F49B9C9061AA606EC\
+A4750FE198D2:\
+87CB631FA8E039C050740F72698E74A93D758BF0D090B1993D6F7042E4E3A6360D0BDFE4\
+5EA8423B1C0FB9ECB9514769890BF994BE04E7A17874866FE1A15CB9C785B0A103F39384\
+A54AC746673A7A98D9F9E20D409F7E172592CE58EAAD74ECB2BB56C95C6CFAA6309887D8\
+956087009252:\
+33B871FD2A012F18E3914F1702AF7485BB793B7DA154804EAA715136B568BD6E:\
+596028337CAFA821457B88131F5E644A
+
+00FB363E56B460D690672DDFC0B71DF6E19F5A5E74E6E85E936937A054E8F7D87511FBEE\
+4A982792196FE8456A849AA1C2E8310E66D6C4BFFE084E791A5EDBFFCE270A4A50E5E238\
+2A18C3B9DDB1B71EF1E51B3568B75F423263E025D4E36012BD4350C226DC9805681D6F74\
+52591921AF631F6B:\
+33B7C9F0C16B82C6D6B08A42E1467592FC9F4D51DF70BFE52139614AAB3FDA3FDC97FA0A\
+235A2AF801134B58CD643E325A020AE796E333C9B3C3DF1208AA7CA5185B3FB1A7FC3B79\
+E717FE1A8B4AF71C96C2A58576CF14906E0CD7A8C4FADCDCF28145D26131DBD656ABF6BA\
+7D522FF9FF23AF29:\
+51D9223DE781C2931F7E2C08CBFE7FCE5CC2AEAE58D22819A60BD9D4A688C5DF:\
+0A55917388EC7A7648973240F8C2EEA4
+
+85F25B5F5D3E68479A0F84CB9F1D92DFFE17975C864C8A974AE1E2DE60292D281712952C\
+AF99C570CED2854B6C98BDF025DED8D8A873AEC8276AA9A1A6711C49FA842C4B446EA596\
+3994F33C74F7C9074B4576750770BD5E5BD9CFA01EC26440A122A6BA0E9A5E4B490581FA\
+BEDC940EAC9D6BE86524:\
+E4BDC3821AB65D06994979873EAEB03796A2A8F5B4507411F6E96EE5A246118EBCE8BD66\
+9514E234A991D708FF1704CB811ADDE53BAE3A147EDF0CAD867ED1547F4C4CF7199B35B8\
+C548D037E494E9DB52ADCDA17129563FB928D13F8EB153A4BA85F330F263FED7B14E66B0\
+C37CDA03133158D1A0FA:\
+FA54E69192980C674DC51DF702B94A43311661E98AAC776DD7F09FEEFF530B6F:\
+DEE6D2C5DB36158D964F28370B147CB5
+
+54E53C0739F2BA49B5A2080E324089051EBC24783771981AA4EBD0E63ACC86BDADCC32AE\
+88099729B4A72D8969D2EB1540F8A7FB3B79C5A0A7F769054EF2EFDDCE4BCA0294AD2B02\
+ECA48840A2A0AB20437D9085E905AA2074FC8C3561C564F1E992FBFB15877B7CB54DCDD2\
+7BECDDF9AB3A58699D4B901F:\
+6D4B53FC1B7FC8B97BA8E1D1526944490B415D3D59887437A24F8384CE850F8005512A8A\
+4BF1E79D03AC1245600DCC83EA21195835582B041B5AB2588DA8BD956D2FB69465485452\
+85C2DF36D26CD09B082F1CDB278F86FFB6FEF9DCC3C71E9CE6B629D7B2897B69CFFC2E14\
+510B4DEE8B9D957FC5AFA769:\
+D22A6E996F80C4AD83209F4E47A17D78EC0F1343CDA8890404FCA4103D038056:\
+3E4EDE2C0488BB09BC4ADFB3D1122E99
+
+2A365C1E10368C49339B3F64A7F25D6682E34A3BB273DEE16D6679B7DEA80FEFCE351964\
+587CB68A939B36D705A32F1760995CB3B9276BCB06AFF5F68CCAD25ABB7CC702D6DFEF85\
+722303C4D27BD81B2D42D2C6A47A9BC4706CEE256B5CF3110705753929B95248761234DB\
+E773C05E79EC9FF958DFB728F8B5:\
+75BD73BB09EE09FF5B8E138D84D776BB8D9B26274D42B012B1D252C22A0E29C66B2C6988\
+0EEDEB0F02376EFDE6F02C85ACDC24BF7AAB725D1CE86688ACB31C5C91DFFB290968B415\
+F7342AC9D60A49F7CFFD35D350D4B63DE597127C5614D609CA27EDD1CCD869D3C4554C30\
+81450A67A2495BAE987239937DED:\
+7B7E24D8792EAECBD7CDD6A43A1D0DB9681C8964D1A55332103C3ED167B2CAD7:\
+8EB77D48DE2CB3E862CBCD9D53234A46
+
+BB6817631F1F0A703F4D5896FF5C3CD94187A82F8287347B80924856B84CAAA3A05B892C\
+C8D8CAFA85F65DD1922F017728CE2E0ED7D4FC9CE844AC9FEFC79FE1EE7181939F4B7A91\
+213880D6B725FCB8348A4879641A628B7BEAB77673E4CAE70CDF36CC92D3784EF7D529E9\
+404C1E54A9086D0C33A50661295ABB24:\
+A2875C6E81960A33F8EC626B9E649747E956690DC4DE11801AE67EFD2B563695CC8C999C\
+1784FBEF30B753AF38C413E361D523C42521A4DA656BA0A1076E8773A335C854037DA8F6\
+E84EB48AAFBEDEF12D4451E9FF1636DBE938960753D3E0FE96165474298512792B8C457F\
+83A8664A4D679D06C22FAE43465F9549:\
+93C474796CFDA89D8FAC562ABFD5426E1611582D0FE40511A503119A48A07202:\
+81DB28BB02B082FE9F40675F752B9F7C
+
+AE29C830ED344F0072FCBDFEC9B9C634703819B24397D59C3D5418B47DD3861B5CCD2119\
+66B4DCB3FFC5E97F6B171F5C51D75B18AC13A78E2CDDEC9D4B23ED26CBCEAAE29FF78F01\
+C5B4201FCEBF7BC029C7730F7603EB456D2AFBD27581BD15941F85E816AA6EFB0D7408D8\
+5F83AF88AF157D3C90BC849031CB9B410819:\
+835993AD13882518F2A1662CA9B4160BEDC60E53083E1F8D72CA3AE2F890856E4B52832D\
+A83B341D9D992C0D9E489BB04C75149624C6D645BB9909E12711FC087C56E1210BEBA66B\
+DBCFC865520E4DEFAD4000CE0EC528916A415C4661E1ED7095E5777BF375DC31CED5F966\
+4C79CB3FB80C5EECC2067B4313CA27AF4F8E:\
+11C63D070095FCD408DC7E7596C177C0A09961B2BDCB6E7C0F300C918E7E830B:\
+41EF5DF5CF14D6D2C14CC4CBC4EADAB7
+
+# MARKER: Cipher Modes (Decryption)
+
+# Cipher mode format is plaintext:ciphertext:key:iv
+
+[DES/ECB/NoPadding]
+86A560F10EC6D85B:059B5E0851CF143A:0113B970FD34F2CE
+3FA40E8A984D4815:4E6F772069732074:0123456789ABCDEF
+
+[DES/ECB/PKCS7]
+17AE296967C5D076::AD37078F3EA426EF
+A9E2BD3B74E7F3CE:E7:9CBEDD92FF2A5B73
+059CF1BEEADC62C2:896D:2FDB746F903CAD45
+784F42BF01754613:C1B1C1:64EA8FC0D24CA010
+9F4559AC8F287060:0888EC54:4C836F4563DF32BC
+9553EAE17C9554C7:5B0E9EFF57:C6B1BAA1CE9585AC
+3ECDE9A96CC20C64:3D0B96172D78:D75487A2708B6667
+05CE6E5D61EF4C58:90628E099303AE:3B7C17F8189C21EF
+DC9D7EEDF77F3B4685EF88B5E3736DF0:3216ACECC41D0D6B:D53C39F84A7E53A4
+EAFA4A1BEB450770265C5AF8A87B807D:8C04066386282D98D5:4637A64E19D8C59A
+91A2C846731747F490596CC2C1354E2C:D2802A5A871F246AB192:0971FEDA66F7DD2E
+8763EEF91B589B6706EE96108DDB9A70:D3E87AF21F0313835ADAC3:8E8F17C42B91EADB
+C75CC89A8B528B1CFA9725A4F6F22C9F:D6FBF31C50BEF03DB36D9CFA:A87F5FF0B3545400
+3888F955A7079C88ADDFEE8C5DDDDE85:40C86D519650F7506BAE823B89:6DA82D72B5948390
+FACCCE40C05A410B329340EEE8E63E89:\
+0780C2ABA3516BDE2A2F8970EB75:040128669CE30F4C
+7AFE6045F807102D354B17B45F3D9D70:\
+BEAFD7CBD536B9800B10F9CEE81E72:A25AA7C651B67CB2
+2985CE350364A85067F32C4E5D340F1658E77714063EA91C:\
+3D8DDC8C215EC27AE07C428D093DBEBB:E4E5E82C29060303
+C78110FF4EBD0FCC3EA2A8F1B3CFECDAC527FF08EE874167:\
+BD6FC0629E56D7E151AD3BC303B02852E4:587033C361C2413E
+02F8DC588D26A55A5B8E441FC66804CAA198A38CF5837A96:\
+8AA4B5C93DB2727D4997927B4570DFDF630E:9A65A821B5FB59D9
+FDBFEBDE42AD8228D33B0032ED35B4AB687BB44CDDFBFC78:\
+13B6ED27218594D16AB5A8475BADA80C03E36E:ADFA49E8BD20F49A
+43391357D31B758921A07ACABEDA50025421B9A15CFFD863:\
+4FAFFCA861CDD5B7393C2F1171E3EAFCFF1BBF09:7C4C08429BBC99D4
+1BEF25251A46159EDC6E7410E9A3804E4DE32A202E2D3FFA:\
+4F246C4C3F679CAE3D659820ADF948B04DA101AAC7:C4D15330927DB0D5
+BAB47B7AFAFD30234BC4E69F1A602788B294438296F6E046:\
+C00AFB680484638EE4BC8999CAAA7EDBF32ADD6A32CF:DBDEDFA4B3BCB30B
+006EE0B1E90468292B72A70426DCD3975A6A4F21D6F6DC8A:\
+94CFEC7A15A35441AC72222DC4BE7508CE12B1D9690E86:95C9471D839AC3A0
+7DA18BB325DABC8F5DDFBAF9B41F4389C0FF9E37A86A1E318C9065FC7F3D654B:\
+95F6A941BBA9BA711BF1962D668996A315157A49EE32993B:F22460847CD66211
+
+[DES/ECB/OneAndZeros]
+D573EBC3919CB0FB::9EAEF4F67688739C
+96205FA42306698E:56:FCC8C062DAAF3A6E
+C2A09626D3200B09:7106:F4FA38ACB1D2A9C9
+64850779AD424E5B:9B5D19:FFAE7E198369326C
+5A4D009F2ACFD643:30A671C3:585B8E1A64E346FA
+BD29AF6B945A8413:371415B9FD:4B6C26F53E7317AE
+6904EF148ECF10B4:1F5E2F5D845C:361DF31C6F8E772A
+4A749E5874DC2FDE:FFCB40A7CDB5B6:050025D50D9773E9
+72EEC4B5CCB537C1AA223E5DF3368139:610F58A0A16D1303:D4F1D443093CF941
+25259E1C4C1E65966D933ED350668BC3:171A5D4E209F133F3B:CA2BD0CF16C9D7BD
+70C87505241FAA9BE93633B16880856D:927D2B314B4CCD1F3D04:C64374B9C7E2A06E
+393C836014C3A65EC36E6165CE192CE4:2CCC4DA982CF67BE929C4A:E30F4BDF1B96967E
+858A4172FAFD4614B5263F418EB9EC56:4E92F895CAEA28B7208236F9:308DE63A2E3A5BCE
+2716D7195AC4D979C3F81D3D08897E8E:E306358941C2BAFE286043A113:33482C296BD8D44F
+5217205AC00B31FE8D7CDB916AD49773:\
+5ABDB2059249D0672AC52085985E:C893C0B250AAD5F9
+1651D5785652365C03541F62BDB343B8:\
+D9E343F4A600D4C5467FBBB923BFDF:9490B296D0EA218D
+90C4F548C806B6B86EC2BAF6A96CEC5D9748FCA16CA51F44:\
+D3DCA72E82C0572ECC7C0DF2BE150C00:F5A1291B1A39F5E9
+39EBA35BF86A2926B0A489599B4BF94C31A9F7FEC351ECE2:\
+5E3786F3E7B3D91AFEE1295C314AFBAFC5:83B78C6CEB56CE78
+B32E06E80854E4B815E12F61A2431B7E9F378ED825168C33:\
+6DAFF95A4C3E781594AC22BE9E9E3067CBC5:1B5E0FD12573752C
+BB8FE34DE658F8E9D7CBFCA9EF0D5AC7CC48949FD419663A:\
+8340DED8A3C5DFB4C59857E5C7B066D5FFEA84:D78448EA1E73DFF9
+A6CC24FE20B8D417592A12E4912A131BCCF69B71EE25B420:\
+5EFAB4221460C884D8E84FEF593E7AD2FC065AB5:A960C2DF2037A814
+4373F2160343E9E626A13A3D28B5D9A1A6E19455374A7070:\
+BB2EEC90C104A60DA2CF1C31A1D06B84C58C55B396:001247D9B6B26506
+F92FA72F2295337D949F8F2C34A0CCA63D0A2057CB2E6F5B:\
+A3F7B5142BE18B4F54F828F42D1BC5A3643016974399:E6FF6AD89409898A
+06C29E86F4CE77256D64E320F6A6A9CA8A72336469DD1EBC:\
+249986A41700E34D49F01D21CC84059D824E9DA320FB6C:761B7C6F0F783305
+75190AC0CF194DD8620D6E6A664E5F7FFFCB615AAFBB098EF54F8430616767B6:\
+3234B4AF6F4B7CC0527C4D23DC7F22BDBE84E7BE010C2F39:F4399D05D289A404
+
+[DES/CBC/NoPadding]
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+[DES/CBC/PKCS7]
+07E8E4E137A70F64::FE4BA85E69877F56:C5C7186B1F9CD61C
+D452289D1ECBFB88:DD:23FB4CBFC76F9906:550DF2EE0D0ECC39
+5270ADDA7C33A133:0AC3:4DC779C79E31D084:B6B763B034D4921A
+215580AAAA09884F:5CA7BE:07AD83CA822CBB58:2FCDEC1E5CCC7DCA
+1E89C0730B3ED0BC:7AD95A87:4C66AC5320597311:378EF56C445206CF
+4D0B351457FB1D19:F1ED735A21:ACDA801121815F40:4254636AAF235A60
+4FBCCA8DBCE392AF:C284BFF3333A:66105A77286C96F9:4F4BAC49BFEE1523
+101115733330ECE5:3E918010C3A311:FA43D72CDD6A4F04:D8773D690E7EF671
+8996ADE0774169D11A1EF78E157AB3C9:3A913A52D35F6D41:\
+82BD7722A5704C2C:7D59C67162592989
+A0B1C44602858AFC9DF4FF3703561CF6:C4E77206DE7FBEC001:\
+C4FB35FB4CECCA1B:91C5204B300E9C8E
+5EEC6084E8EA4CBD226B1CE9D03760D7:C2FFAB037354BBF6681A:\
+6462FEF31CD53A14:15F7C886C55B8C80
+635F4DA9940E6BFF3475718EC80A6032:B38993F0421A9482256C3E:\
+B1F09583E9F4332E:6B3A296CE234FFE4
+6C427B05365CE2C1CD7272F4580FF4E7:FC39AFC5C58A746797C64540:\
+C2509FECD82996B6:FCB3F5AC6122AAE6
+C48B1AED56789C2ABF1DC0A3F0F09D95:006F3067DA4F4EF4294925551F:\
+83FC0D025C2B27D4:8A9424DB9F60DB23
+ED198040B7F952B3B2C7B550B8D3E207:8953C0470CC17BEFDCFD7A178941:\
+B29FD310B15FF558:0D832323132E79B4
+F562D640B39DA7BBC5F7FBD0B84EC880:673D81110782DEB537CE33A0DD8F96:\
+E5F2856E63C54113:EEF1601F3C40CD8D
+492862C0FA48CDBDE714A0B8881BC1CE6F9F17E9A2754D65:\
+8F4169CC8771200D0BF3D8F7140AA811:\
+5DE9685DEAE62242:3835A7308345E312
+F5B8D08D269EC0F196BA8BA6BB98273F8D90325CEC83424F:\
+8DC4099DC33743F0E6B903CBE8FFCB7C68:\
+1A99B0DAF28CC879:2AFF0DB963454727
+C2DC32BDDA790DADF329874B09727A14BE6F01E097AE5B1A:\
+6EE8C6C2C73E58C82D58105B005149DEAEC7:\
+5ED0CB977CA524B1:4F45E91DE65705AD
+920184D9311F88F5D0725F4F40B066DB6FFD1CE2AA86F933:\
+968F75526E091CAC8BD85DD75AD15D49E38ED9:\
+6C9E8BCC4C9F7B91:21728BE0081A555B
+A6744F04F97363A5EB120F09DFF42275092E587B14D12492:\
+CD4CBDDA85C9B9E7DE97209472BD2BCF9182150C:\
+9908A488E9ABB414:958C9C62D9593C5E
+60B161ACFDEAB66C476EA55D13116F865687F06CFFD13CB3:\
+F58720F8B80AA229BD7642AD9807C647839D853033:\
+61F2CCFC031ECEFF:9F94F426B4ECDEBE
+8751AA8954A97684A06B2BFBB85133B33D3DFCE1B8562156:\
+A95527CFC36EFDE34B771A0370ADB1E49879AC424D66:\
+F8A2DB331D17C3BE:AF6D13D63CD74439
+FC16DDB93CAB78299B5A18D9417DFC5A84565BE49057C394:\
+604570CF9BCCCC86FF411D0774AC6559F8D293BEBAB80D:\
+B8D057BA9652F60E:B23B7F81D64B4E5D
+C3BF0218E9F75F284871BBD4D4CC6664D964EA0571FC40B1CA54BDB04105DD65:\
+4149D929BC228216A0D58E880112BE987BC1BFEA70D7D9FE:\
+283320F2BDBCECFF:06C528C2E7AAD887
+
+E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF277:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+[RC5(8)/CBC/PKCS7]
+7875DBF6738C64788F34C3C681C99695:FFFFFFFFFFFFFFFF:0102030405:0000000000000000
+7875DBF6738C64787CB3F1DF34F948117FD1A023A5BBA217:\
+FFFFFFFFFFFFFFFF7875DBF6738C647811223344556677:0102030405:0000000000000000
+
+[DES/CBC/OneAndZeros]
+79FCDEE6F5A94E74::0741219814F4369E:DEFD8C15FEB10458
+54EC08B8ADBBCA8F:61:113F04B28F2A9B7E:46A8D61A1D40091E
+7F5C2A6A9F539AD3:6162:7A1771070C736156:5DB9B23CCE795B60
+F0103B237AC98CE5:616263:C4FCD43F56E0AE9B:23A3C25145BE0D20
+65997360ABB15119:61626364:C4FCD43F56E0AE9B:23A3C25145BE0D20
+34D30333EFB7979B:6162636465:F0C27E2EA299D6B9:933CB62A4B934A86
+875E07E80AD49DA0:616263646566:32B6417E7DC574F4:7B42506B38E4A6E1
+994B8B68EE1B0599:61626364656667:3F269D9FF30313AD:DC044A49A694D3B1
+
+C224E73B1564AD1FC49353481E6F5E1D:FE21E07064BE5336:\
+80A21AB24ED705D6:ED03EB0F3FB37D02
+55E901FB4BADDBDF1EAE173AFC8D7099:BBAC475C9BF8287A77:\
+CDCC24E1F5D9947C:EAF397A30C64F5FF
+6105DF0EE9CF1EBDE42935D364D6C9FB:8C5350033553101EC583:\
+94DB8915D14857F3:91499DE2964505D3
+690EDC0411344EC2B0C7B41A31D2F1BA:F3DD004162E851F63D2340:\
+E32708EEC7FF69DA:5782AB9B02BBE4B6
+CC613B80C91901B3216AD10F6596D8F8:4C609BE7D7F14EA806AAFB56:\
+4F6A0EEDF83718D3:FCE76482531A27B5
+63AF78D1B2A15AECDA6897AD6007E5AE:CA17CCA6AF2B27A30B5F92A2B0:\
+C26991460E22605C:126CBBC4A9FC3EA5
+A096512FB2DA7D0A75A1DA41F234A83E:C2DFEE0749C5A21378D4506AB8A3:\
+07D0D1AF072F0737:B66510CA43FF801E
+E641C41182D543E18932FC306FD30726:5A9450CF73A49F570860727C070012:\
+533571A680807F5E:D0FB32F8A2CB7D8E
+9C1AD6A9705F9A72069BB0E4D51A968C2399686815F8DCDE:\
+04184EF5DD2105CC02AFA58B68C2C7F4:ED8250E6E97FA6E4:5CE0CB36A781C6AB
+
+EC41D8E3AA50FC221295274F65A76330:\
+6162636465666768:9F853348B078828A:1DA8B83A9ECB0F6D
+
+69E0288D17900DA45557053EE79CA771E90CCB8D28198E0D:\
+435255534820414C4C2048554D414E5A:\
+E3BB33E82BDB2B84:593A08135216F478
+
+14D752E45A8D28EAB2A5C8E0A12E8A88E804451282F62CA5:\
+7777772E6D656761746F6B796F2E636F6D:\
+458FD140271920A6:605C41F0790BE4EA
+
+[DES/CBC/CTS]
+1F807F8FB9678124B9:9E1CA14BE6538A35DB:88B23AFD0683D337:BAC170D943D262CE
+C6FBE4158F2939D81685:673E242016F6BBA293C0:FFFFCD5B8461A7DB:6D688D63D006AFCB
+F09F7DEA21F678D8FDF997:\
+15FC19F91682B6DD84E60E:4520E59F0868DA60:D572977CA711487C
+80D4E9906F5E093CAB19C835:\
+07F07F2E6E08B791641A95F9:E6A1584C2D9B0F7B:CFDCEFA5DC5CEC3F
+1D7DFB8D1670FFA2FDD99872E2:\
+CC5B006B635A022707AE5674A2:3F2B64EC09DB383A:CC26B1221547BBF3
+DEF7C893EFA8282FC430D92DEC8A:\
+25D30B3604955F5D9AB140C0CA08:41899DF2C47BB49D:E92788E786D65178
+4B0DA5D1E34EBC1AFD0EE115F6D6EB:\
+3736F5354719478759C0AE03FBA044:E15683D9B9731171:6055901E02CC51AA
+13EBA3C09DA9A92CE12FB67D8D0EDED1:\
+121BE08F10A108CF04F6BD59F8A80EA2:EB1A14148700BE54:93AE09E97D6068AC
+A3F29A3DE6B3D52054CDC85FEAEAD5440E:\
+B394FBF91C772ECF3964975819DDE9380C:166B1D73EC15EE53:477A1026883D68F8
+DF6B5B1591C712562A19631E8DAD95153F49:\
+E2416356E94211935EC4448BE0AB43EE1A80:2F01F85201D1B010:5066B27BF6719D41
+FB7FDF98254DA02C2FF2A7801EEC8CD4B5DE03:\
+50FD46F08A0EBC980F24C9484799EBC2028F75:2CA90BF9C26CCEB4:50446BBB5961F03C
+DAF13C5B1DBB958869C0633E8F7EB75646A17647:\
+CF81978920DB7182CF7CA7B5D1177DA83C372C4A:29B6B35BBD8575B3:76EC8D7FA07B8BE5
+87F9684E940E9C410327370A9F10270081B0A5B431:\
+FFE5FC92FBBA432A381F0CA62691AFAD668A0AC192:54ACB83F531EE8EA:9CC628CC5BDEE576
+E2BBA60098114B85838CCA4F1FC8D22A3D8234E0D796:\
+F84EE66897F4D44F882304C3C7D5F630BFD47250B6BD:C562A007017EFC2E:9E4C18CAC2C60138
+
+2DC5DBB9A4F55CEB1A65871417FB293A9726642DD02171:\
+3B4EB0E3405E17EDD17856D29AC97E7B6E3BC196802A24:\
+4A403657C2102B99:90474AFC765346AC
+
+B902D393A62F51E99CBC97B1310830767557835CC56BF88F:\
+506C86A1D0E325684DD23BE8445CDB08D734D6FAA48BC1F8:\
+CAC16F52CA80B183:CFF070594D1A8020
+
+BE082E12FA28CEE1F24328D50FEF71C055D61A6B71466EE56C:\
+B03B09966AC8261CBD17E6CE218B4A826B3D0D36C735BE1CB6:\
+2FDF8948B7AD54C3:8CBDBEF17F1B1328
+
+C9C4702752294E5C3410071A0BF19549AF90213619754EADA1F7:\
+4D790FAB1374E5387CFC5AE9E7FBE0ABD57F634024BB32FA6D95:\
+6A277A4D5B27FECA:6007E397C5E1B6B2
+
+C91A1979FA1A4F93FB8FDA30BD82C26EDD397D91146C044D3C9AB5:\
+01FADB9D549F559E4BD4AABEA073166D76ACB68B3BC7C38E758CE2:\
+E554075663480335:287B947D8D85E403
+
+ECAE28210D616F758CA9111276A10D2151E3F7D0BC567D88944FD697:\
+4DF4CF96C82CAFCCF4791A26DB3A55E8FFF1F374020B1495AFAC8B10:\
+81CCB226258A2BD9:48CEEAED7E7D2B60
+
+DA5A434A5416AEDE9AD557F48183C32406EA78FF5B3B37D5069A8077F8:\
+EB80E96A60CBE0E7E430BCC748F4CBCD61382FEA8787AD11DD598A202F:\
+BAF7BA1C4F38A3FC:13D4AED7365948F1
+
+243B2A015703ECD61FE8DCCC3B216389AE437C0582F5B96493BBEC9B4C68:\
+8FB383275E6F93391E97B13EFC3F7C99F731CB1B346EB15BB5F8DA6248A2:\
+24EC41340744EE04:811219783983A9A0
+
+7CF27928B68E2A4CF007F5C740EF3D42E3C86AD0A768C50F65A92F7EF76CC3:\
+A3165F6001A3C69BDACEF31D924F4CE8AC9CC6CD10BE9948742A2E98DBFDF0:\
+A9A60A3BE162FA91:771A271B54C3DBDF
+
+0190C2294922A17D6E40B2595C9552F0D460F1552315D964818F01CFC7836E74:\
+E6DD056E42D117095F389321E259A004D467096DA28EEA534DC6568C3485B9D5:\
+47B469F51A41EC35:623A5F40A498554B
+
+BAEFF9B09693512CAE7CDEE14628C39898360AE20BAE66C845D920FE16F6D626DF:\
+4D0E59994E070D66F913698947E4AAE1F3044928F29D4ED59CAD18D24E134C52F8:\
+E8C7568DD459A5D9:F82C3042C634B503
+
+B60D0279220B5AC636A861AEE3867B21533A579ABADD3EC5CCB7DD84B23AF3794CC6:\
+4786F439927802927B1AFB3B0DB3C059CA36E4E9D8851C304ABF12438A5F1D7C15E8:\
+5F4379FC61646FCB:8FFD75FA48D32230
+
+245DD4A56151DCDBD0000DF64239D4E64CBC9E82878E3465BBEB86F8DB4782565DC96F:\
+12B6CCB90894783FEC5A375C1744BC7E276DF3D21433EC842373FDDEAAF4D2FCB4229C:\
+1B9F7251AF742AF2:61E984D8B88552DC
+
+3B7598C46993B7046BADB4240143B112CAD1955913073B61E1F77871300A3A4933CE98CC:\
+B84AA9F532EB1DAEEA5332BCAF2402E4CAC762CEB614A686A7A5483AC968FFE6FA84282E:\
+CDE1C86F35672CE4:4B1A4FD4B170196C
+
+5EF4F1E99D2B142769C82590356C5C69C0B3524FC5F849A583464F6448420A7E1FC3563BE0:\
+16064D069A02CF2F8E05953D3B94764568A1C9A1B12AB56CF1032BEE90DA83A807ED5B9670:\
+D427CDE3D72512B0:DC0C33ED870E2BFD
+
+BB8ACFD2BDCD37D952FCFB3C4E668AA5A4EAD2273BD6C84DFC0E8E55AF2DC54D7E3C908FADF7:\
+2E682E802242ACD731E439A7392A5F8701256FD23BA03A65A723671920228B34EC6484E53AB4:\
+57EEEBF7FD0D4E18:B88F867E5276A8CF
+
+[DES/CFB(64)]
+F3096249C7F46E51A69E839B1A92F78403467133898EA622:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+F3096249C7F46E51A69E839B1A92F78403467133898EA622:\
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+0123456789ABCDEF:1234567890ABCDEF
+
+0CB8929A854E61AB3BEB72CE0F13BA328BA73A:\
+D14FD67A9B4D7B0F65B7CA3DA91741603DA446:\
+7132D895529A7AFF:FA1FE8F921706C75
+
+# Random tests, 1...17 byte inputs
+8C:14:FC32B875389C53C0:6CAD29F658A72118
+4045:20A8:89D26DA778B3BA96:C6727E943ECFD50D
+3C17ED:E13C5B:A9F4D6E479BDE314:271C258E90098CC9
+4B465AAD:DDFB818A:C0DF30CA0DC7B5A7:0F141E7F0EDD71DB
+EA6E62D9AA:F70A23F77F:EB26600BD965DE91:6F700666CF4EDEAE
+C486B45156B6:73B635137A36:C56CDC1349657886:5883CBD2A332FD55
+3030B2F0CF44EC:2160B2C75B616F:0DDBF5FF8489B870:F9E9C856200036D3
+C6D70FF570F90870:260C393389E6489A:4E96BA675101F1EE:4DFCB5C3570E2235
+966F556D1AB16D9A84:86083459660733A6EC:16ABBC1F03F13DCC:571EF2769E6DBDFE
+42CD5A8DA77110EB8E56:300AB25A182F798D2195:DB2807197F31E79C:465C5C1BE8DC2699
+1A6829A79F40DBEA451043:2DFD811615ED4490B9AA6C:97D3995360F10777:B4D324EC37BC140B
+D4736432091A2DBA9E7624D5:6BC6540B34674448AF311283:\
+6C7E65D7EECBDC07:2E41B63F4381C5AD
+ACDDA761DDE4D7D23065726194:E7FE3DDC6257543EB319DD565E:\
+B55CB5A2BFED0E0C:C290747BAE6C2651
+E9CD9B31E903C3219D3D83D3B01F:1A17ADEB075B2A94777C8EF0ED11:\
+36982D604982EB26:B4AD47CB63991A37
+5501CAF4CB8843D460CE4D64AC9F3B:168583B6B5A1B5E8246EA11E1D5B25:\
+BD51A1B281929DC7:C5AAD3504E6C4BBD
+D4FE93AD0BA52E4919308E1273714C52:CF0C5D133700651565A8C1885C1576B2:\
+A8C2FAA4B9EE7986:9B733E3380066255
+E4D2F1241759BDC21164DD17CEF53043E7:DB72BF34A34159D488F9C6537D062C8E56:\
+B90CAF95123094D8:48E6D697471B2639
+
+[DES/CFB(32)]
+13799E52F0BF6B0E:BF28A5B2F3FC788F:44FD92D1AF17DA22:5EF2AB4DE2C32258
+
+BA696D0FEFF0882ABEF2E0BCC543CBE2:A6D36D854511809856A9911919FCF070:\
+5046A6A7584E015A:D006FDD64A63FFF5
+6A837A170812A9E6E1A5DC69AA6FBCE2:19359DAB792F0D020115A7722C171532:\
+B992C4C6A2320278:5AEF500DDD6608E5
+77672D81E388902A764B427DAC586F20:B4EABA09CC71CB3CFD191F20065A1B70:\
+E6862A4F40A85BE4:E743B2DD825BF2C0
+EF7DA9BCA94489CE200530EAFE1CD7E7:244273B4BD388B9099669BBEFDC4454A:\
+C4438F020753FE17:36AF1E8E06E278FB
+9B51C216FBAD699636400C962F2E3405:3B9834AB792F727E788C7D32625455D3:\
+465537A2E2167EEB:CCFDB7E38ABF99D9
+19D49D5A54C8FD15EF317AFD5A87EBDE:302C49BF921E0516261F00B2FA2E96A6:\
+F15BD42AEA7F38FD:5E10F9CAF0730C4E
+
+[DES/CFB(16)]
+D6522C5DEF57233BD3A6A30F457A079A:769DE609244B94A8B4E4727736DEA7BA:\
+E1D28FFDD5036622:7A3E915CE8A03836
+
+E8E4A04E0F07E2D9:BD4E5489C5CC01C5:BFCA0E11D1ECFBA7:E115ACDCE0EADA59
+7DDE9ACFB699E9B4:CD42413995D601FE:EDFE86AC2EF8ADFE:4ABE7D04F174CA97
+5F803D644DE8B9E5:5D4B3F430AB38F6E:B94861B7AAB541D8:9EE77D9E68A0968A
+3421750B8D2F984B:2230CF77A827A379:DCA93094B06CB02B:B7D1CF1634AC7D72
+4FBEFCBE20691E11:AA9DCA8BD9C31D51:6F4C469A7710EA31:D091690C4D0203A1
+
+[DES/CFB(8)]
+205EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF89946
+7B0CEB1D343B181B:BABB3F2ECEE17044:01E4B49A4C327C83:7837CB9035139E36
+FC48CB21644AA6A6:35BD7CBB4F42FE66:DF6B71F274CEAE61:8365BDF506BD2382
+7423BC2D230FF167:75648C39AF4DE0DC:2E1BAA1165A460A4:35E0A0149D95735E
+8E511E034A21F8D4:6FFC4455799C1A52:FB029C10575CC9EF:DCC44B7A2C4912E0
+6AF4AA1647F5D301:BCFB89E0F3FEF946:468B7763A174FB3F:99057856B861F898
+8BCF14590ECECAB3:8A8907B5BAA3C332:60E50468766A6688:ADC6C30CDD00F54E
+FB5984B0442353C5:59A6F97571EFBAAD:23A9AEAF310E7134:809E47BF2565701F
+52ED7FC58FCD4DCF:B9B761F8C8AFD67C:E9480E1E6AFBA1D5:23D1BA6B06632D52
+7DFEED75F6A1306E:DB7A16136E5B71B7:C82593A34F75DF42:B6D33655396C925A
+
+[DES/OFB]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3:\
+0123456789ABCDEF:1234567890ABCDEF
+
+B25330D1CAB11FDDFF278192AA2C935A9C7745733E6DA8:\
+39B9BF284D6DA6E639B8040B8DA01E469DBA4C6E50B1AB:\
+F871822C7FD1D6A3:B311792C8BC02EE8
+
+73AD356623A1D6E0717E838B9344B4FFF21BDA:\
+0C06E63E9E81D9976E16D2009255F917797D51:\
+5860F4A413DE6C68:527A1E050A9D71F0
+
+08A6091FA2987FDC682A8199A6D6BD1F:640B5033DCF26873FA8A34DB644F2BF2:\
+3307042DC775035E:99DE32FF0351509B
+
+[DES/CTR-BE]
+4E6F77206973207468652074696D6520666F7220616C6C20:\
+F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75:\
+0123456789ABCDEF:1234567890ABCDEF
+
+11919B328564DA68D9F4216AE1B4FA7C46AFC7AD5BB867DF1834D77A3023ECAB940725AB:\
+F40235A0B8B2EC0B53F3C0D8799497463638AD0CC3E07F0E8B8B0DC7605AE6AEAFBA2A88:\
+A67ABE525A0E5AB2:727BECDE9FCEA20A
+168A502D21D71F3BEB702BBF02D3F6D04B72EFF2F19EF01D217CC7AA739A67466AF3B14E:\
+3A73770D157C23EF8913D874CD92DD36C465679B2BC691DAA0DC6CD4591C4CA44D5D69D8:\
+CDB366CCD621D62B:1ACAAC3F760C674B
+24889A268E11AEF80852C4FC4893DBEBDF4CB06115FD533650CA39A639C659F47C3D5556:\
+782B24067A2C5D61BF6ED2E980F6BB16A0A6E0B5639B4208AE273C0BDC0311D65464F217:\
+EF510AA740BE98CB:74E74E01E5C72084
+3078866926F75D18239A3DA92EC9EB88D18393440B47D46A49D003F2C3B5D51C1CFE3FF4:\
+DE4D9632BE88235D717B36DE4C67B81CF3331E8925726CAD1BCC05126B87A6CD5D5DE3B6:\
+E8CBB756DE4FDEB0:AEE751205CABA9BE
+4602C97A25AFB1746DE8BC1A65AE0B635ADDAB9547A99421AD86AFB087997ABC1458F0CC:\
+754BD27902EE4248BEEE65D2BB035C9139F98735C85603BA9565EDAADE37A7FE29833DD9:\
+B050B286E47C6E6A:701F72AE37D31F2B
+E344E0C2E45990C451C75BF74406821B99D4EA5F56F67BB2F9B0EA52FF5D1BB25D82A181:\
+1A23AD101A776F902B8DB40E273A1F5EAE8AA1E43CBA52546F2EC50EF32960BDD05101D3:\
+445A14B76AFEFBC0:EE2DD8860B75788A
+2C3A117378B8DB1287CE8FE084EAA08EFCEB253DD4A92509EAD154E6AE483E25D2B790B5:\
+75235CB3E2BF7DD3ED893DA93AE25D7A34D43521DB620E2BC9072159357010E6D81E5884:\
+4B1B62B9D6B8F54F:036CC5145BCE2A01
+FBC7E48930ADF4A36DE18CABDE25ACDAC8F9AB727E3AA69FE8EC6F965C6E14EBE9AE437D:\
+B271913A8A58ADDF3C89132A15DF1263B63018CC8EE6763E6FCFB4DD5D4AA8EC4B3E2D78:\
+2E0F06AE7B1C30D7:05E144D6DB9E7939
+940C3FE78C56A0F922FBEDE7ADE31914C993BB84F5BC1557E5F8004CB75D7D339801FBBF:\
+9615A71536135E50946A8517E72A980CBB2378A3286F08E76E85E5FB62140C9B3720C7C4:\
+E6E85EABE538195C:B86615CDA5C9E9A2
+256ABA748AE0005A5F99F1C96F8A197E3867B8455A4D6BFD6795BBDB89062B222E6B0DD7:\
+2A6B043F07ACD99141C7AC616B7F89AB7E52174A41AFC1FD0C56BC77B9C2EC9CEC87A0A6:\
+9985CE7E0D79CFEF:25D1D57C3A6936F9
+44AC3E1333DE5CD00475317CBAD26AB4A812180DAA7405556C41335572F5A236C37CD36F:\
+155E5B86FC06AD433DAEFA05C329BC1407966220BA91EAC2FD32B35C5AD973D94A0B8792:\
+47550AB0F346ECB0:1C42F4559385E11B
+9DEDC376CFD97AE823AB2E0CB0072DF26DAADC4FD9316C7E8F4F796026DA9ECB8ED69DCD:\
+EDE3E69EE5B55AC758EB39E70E6533CC4D89C148F6AD68293E743CD82B9638F020EE589D:\
+098EFEE0D594C332:88D9C46E992B27AE
+
+[AES/EAX]
+B39AB9280E8E75FFB9A6C0423D94237757:A1:\
+32942F082B82885F3965397EC13315D8:79E2ABF57EAB5DCBB887FC38069FDA38
+
+F28FF0575837BBF9B18E1AF21F086271224BDC:DFA72B:\
+16EBB23CE362FE4F9D75D7FD330C57AE:13A112FDD1A803DADD153FCFF5E6FA0B
+
+79B15D05BD1198BCAFDC4E5479C94479EED48273:8EDCC43E:\
+5D83726C0764B9DE12E97C81D925BD12:E2614B57C71FC5DDE11AB56FF67AAD53
+
+6CF9258B79066C6D1D3CEF7DFDC07F1CD3A2C456:2CCE2B48:\
+898EEA34047E0896A49BD8EC9E5FEF10:86B46B759E771F7DD2F5D6FEC401474D
+
+2B098DF40219F5378FE910750AA62597BCE7F2BF91ADF6AB8933C113F81E9488:\
+C202A2C43538DFBED961D4C6B9628E3D:D41C09CE65EB3924456360D76B78C42D:\
+7A67F1AF9FD16E7832423FEBA5CD2879
+
+3592BF54500CAEA6CBB6AAAB7CB3BFBE::\
+CA0F81BA5479F3B8AC847B7EF116C2A1:29D2ECC2C99C3676E7B9F85AB3B1E57D
+
+4DA9BE08E753EA123DEAB8DFFBA315DB50:B9:\
+D71D44511C92B390AC9C7961506D9E5B:032E8F2C3E7E0B152DC087E20FB59CE6
+
+178CFF2FAA32FF902EC92AEB5B30834B5758:0ADA:\
+39F797C50D5BC13FE895367BF2ABB56C:58399D9AA144C8236655F51D81FFF7BA
+
+37ECF2F5E41D4DFDDA3DA85F1D82A3767E8360:3CD5B1:\
+DEC57BD1A4D6B9C0160E53492DEC88C5:3D60B53B4A64D1F9B6802AF9BD00AB9B
+
+3165D9ADB4E3CEC0831B85AF88C5787C0D145A92:09FEC8F9:\
+7A09C4F9265809EDF4BB32E3270D6F46:EEF79DD485F69FA5D0457DD94345D2BD
+
+05B76D5CBE49DE233B6F62E4D87763FDD0A210A84B:F3C0EAE690:\
+9FBD4E3CC8B0B54454788C5B68AAC81C:2F0269EAF6708D3B1B332EDB1E146BBD
+
+FF9CAF05A8107C410BFCDD14E3852C5A76F8EB5C116B:1F31923D5518:\
+85ABF08534075B6EE35AD7C550794BEB:AC962D0FE55AA2972BC2C8BDFF1ED584
+
+81655A74F4F64E21B004F3D04D56512A7D1EDCB9B20200:C7C8F67C72E962:\
+170247F224B15FE3D501DFDB21EEA1AA:46FB86732B98C18460897ADCFB643E12
+
+D81940ACDFB353AF804BB411C6950BD8FF9E15067B406830:06C456B3B74175FB:\
+CDC09E48511B3E38B75D14EA069BC885:CBF80EE76101BA67C5111A7C528F781F
+
+DE25F7B65F16113841D5AE12F80A1744A5F81B09EE5D29240C:0B2FC9C8FA81E7198E:\
+165372615FB7963B7A6E59364ADAE29D:401A0B4312344F41FD173B7FFF540D15
+
+BB873E2B7A879E53F513F1834C54853FC2037D9893F65824CCB9:DA2057C6401125A5808F:\
+2F32841E15A6A883EC5CE8032E563BB0:B33743A1061DC15DE3026E09A7EF98D7
+
+304864E3B8DA2359BAF5ED60C76DB298E2C12E94D18FC615F934BC:20DA4B54F8EDC93EE5DF91:\
+AD94D86D3D05ACCE0FED495B6FF5F23D:4DE497550471A059698E22A773013821
+
+8CBAFB5678D47121DC5F0CABA76F0A1A306B22C19B86C883CCA36F39:\
+26C2C7533B8481560FA3F226:\
+9D59713C92F96FA1CB0469662541540E:B4AEC9DB70912EAB15AF012552F44BF0
+
+7AEE2EA671EA8B5F25E99F000D181CBEDD36BEE605D35BB4AFE833CACA:\
+C0C7FF94C3588CEB45619BBA5C:\
+B98A22543794F9DA5C3419BD9A1FBFA3:CE98649597F858EF844335E5DFEF4198
+
+D0FE64F8842CF1A4C0750C6F11F8364E72A23D80D139900C9883CCB64090:\
+924A4112C3B76FF98D45355A60A4:\
+4AFC52C6B9C20C594DDA2CDD347E72C7:CF05111017D4C887CD55CC02B02DA6FA
+
+CB869382EB0644E9D00736793D5E19A56799CBF313F87EEAF28B7D997FD34B:\
+B545B07CAC05C6ABA080EFE09F1B58:\
+4AD8D6A4A2E9A16C690EF49ED125F92E:DA3EDE56EAE31D96839D85633DA0BC87
+
+E267E3C9701672235AA5B69C6491BB54CD490FE8F99A6668A94AE6DCD94035AE:\
+DB210878188D2D0A9E72BD7C674D3F5B:\
+4D3E720750529D0F513E92763E59A31A:7BAB929338BF9DD7315B5398A892F3F5
+
+861567E2AD28833FE5B6F4D1A37D2D0D5984FB4EE2FA0AA91F7AE9BD7D24231BE5:\
+C1DE878D368F80A87C15BDF8A40026FAA9:\
+42353F4A310C9A8AC8C8514C792E0D58:B69A8E451A37C12FF4B9D3F4E0CD9D22
+
+AB6C088C4E0C0EBEC2BCBBC9A98514B05A445D563FDB50BD62EB2B9C26958803A297:\
+9ABE34A69F182DCEBB766EC9181F2E083382:\
+2D35319C7307ED58372CFB6712952547:3BC55F69931ADF01E3F72111FF54942C
+
+C3B6CD7D76EFA2E354C4E8F7304C7075E18768F4289D7F3836FC8DE15474C7E29C58E5:\
+65CD9E4A150319445A8C66F02CC3BF651E9FE1:\
+3D837364406414252F703E8CD50B2A1F:212D386588C4CB78F08E3756ACD637E9
+
+670B848D3BBB52E923AC9BCE4317E68D7962C73F3D467FCF5924EA7A3C6A49C815D7265D:\
+B3DEB5D5B958DFF8A64ECC1D146E33BA0A261A89:\
+CBA99B5D4C96D127F5C5B4A8A3697E5C:C25D5468AB2185C08FB97A99DF9522AA
+
+7682A2E42D701828D7DE633AC10F944CE42E00EAF52316AB023662E4D8A7FC16C1D06F7ABE:\
+D1B17D59C7BFD0F0E77B8EC21AFA78018B2ACD11A7:\
+CCE8F486487E7A451DAD16CE2B6F96EA:4086D1BB1594D50F0CD79A36A4ABDD70
+
+F083A6CD239631E8CF3055108CE5BC491F57DDB5F57C3BAA188A12DBE43F1670BE36BE92241F:\
+A7AD209830FFCB8A89F2E90A5C4F57E3AB63559A0FEA:\
+C4EC64DD6D082CB6B2D363D26B94D136:1E5B2907658557BC690220BE9C2FA860
+
+57FDB6E005621F3F5A23049803817D8B2982C20C3504B0\
+BAC825269431C3CF68D51A0E349E5DCF:\
+F6C8C495B93A0AE6F61EBA1773F05D7C2ED4B9F17E5E16:\
+76A0D567CE9CECED93B5B1286EEB3354:E1510EF8C5FF55412D29FA1EA758341D
+
+8BC73BB8EEFB46E742DE9EA40226DD48755B1049C0D01E75\
+47FC1A6537B61CE2F3573496F291D016:\
+F7012F6E6E938F7529E7905ED045D0558A5B168B3C6C815E:\
+E8280E1F06468BFD47BA6CB54EFB2A77:E3BAD5B3FFA50889001F143D8B959B73
+
+AA1B16CDA20C35A84D0B7F89C4D6E9C061FC2469080F1AC929\
+8590EFDE1B39474005CB319B19EF3CB9:\
+8B8631197B30C7370B7FE540567D2CAE5C8E6053DBCCF75162:\
+7F52829F60F32AE6244462540B99608A:7EA0E1FCCC8F585BF0AB36BCA3871F22
+
+6B2F99D7840808EECC6CC70DD6EE11038906EF6EC8C8B49BD121\
+B5199B440625D00CB38C327597AD9573:\
+F650F5F428CC5BF6B755CE90DC86F46A7DAB41B1CC9E8243A731:\
+A42FB43E3BAA8E309EB6FCF9ACB34F7A:432B0037957DE2D72FAF75B1F21CE296
+
+FD24E4137BFB0BAA260C5263FBA35BE28E1ABE1928F2AA55C192DE\
+C841A8D08639F4721712E1CF737E9BF6:\
+0146825F3EB53904628D652D59F003EE604971226BA3BA2E8F3DD1:\
+552308A6244E28838DDDBD913F4AF76C:A3E7709248B9036A25A724533661258C
+
+52F6DC00BA21BF0A0718F5F931822EF23C94ACFFEDE0A7BE28E4DA74\
+6246F6B89B5899001060A42D0543DE26:\
+CCF9C55515CA3C5162D3847DF2C6B318314444CDB8AF9C34E985E351:\
+D209AE9F0273F4173E3069A004ED1DF6:B3D10EE41552B1CD024E02EBD3E53CA5
+
+4A87AE20CDD8058A3507B1BDCF4AF6737D38C40F8AEF647DB8158D503B\
+E3A1C394C7438B171AB4E57CAC2FE274:\
+CEBE04BEE25C79D6167B220733336A5E2D7C27E888359C3D6F1F01E981:\
+FE034FBC070D9E6386757A01978134CA:EC92F768B9E0F0EF7C2D5E9B2E471C2D
+
+1D8B38719B5032629F5AB5B6EE59C3DD22F7A48735C5710802DF28704836\
+F8244F62E56E0E12479AE6C6EE0BBA0C:\
+C3D1992FB96CD9A6F3668EB54276600EA7DA9E9D3639C7CDFAE556D851D8:\
+9115AA2A4463971D0A8A84983FC60EA0:D4B67A7253B0AB1A7EA5FFD47D51AD0E
+
+6D030D5AECA8239E4BE536F5B9886AC6F38FF34B77909FDFA81C030348B701\
+3AEBE5C0889189A4B2F3F2B3E06A5DC8:\
+5BB719AAC1999824AD9AE817491AE0924A56628A895DA88EAFCDDBF5F32CB0:\
+4FE3C9F9A56391C9102BB12774CB0707:165E69A0E7C648767516516A097E1A58
+
+C932628CBB4E53FCEE5C585F04BC9C08::\
+6ABE1356E6A4B484E454BC488E108979:B29D87C2BD94CDFD94DBD318309CDE9A
+
+C712CDA7CB6CAE9C067FB1006B33A740B7:61:\
+AC7A66CC944A177467DD30EBFFE24344:4034E0C5EF7B49AF710B8B86BABAE767
+
+4BD4FB492AF9296BD50B0338A4D80BFCBFAE:5EAF:\
+C41CB4E2208A2AE49D59313AA3852A50:B23B3A8E850C41DC30448304C9E2B38D
+
+944500DA2B82C64DB63101760FAD9B04B7B5AE:8D2848:\
+CB5972D3FD65E49F000D5754664E4209:69C9F9FC392CB8055E4C52BDD97A05A4
+
+EFAF16EABE3320C8C650AD585DFCBDB537E4E5A1:B29B9A22:\
+F57E5FA4371F40528911EB3168011F36:ED4B8BB9B6635CA38F871E4122B96318
+
+F48C1026C094968A52983AEF848644390EF0AD887D:1D74EA6C4C:\
+13EBD6907963AFA2A38725D1C584C40F:809E32023528D14D9C626A114CD65D5F
+
+8A60BBDF08C42353DDB7932AECEFB220D692A8E8DA2B:44C3EA4929A1:\
+D5E9FD2260051E900851974AFF447B15:467F03F57C4A071F4D4CE237950CD86A
+
+BD6CFB5269FEFEA13CF4E32FF4CCD483A27B8A7A1D1B79:4928D4FE0CA3B9:\
+8B5E6F2B0EE6F1239D9BBDB7AAC91B00:7F9E64B73FBD80AE06A88205B425BE3F
+
+F9A4A1646EBB784A59D7CFCA193B3E9C2527FD92542D0006:44F885030002B7E4:\
+7065E368FFBDA1905BDEEEA754C0D5F5:35E4CDE820A334649BB9679CBB1E802B
+
+6896B0857D444F64787D6C61B71AFD5DCE6B9B143A1DF9DADC:5EF4B47926F72F4C43:\
+E6619897C6063BA60CC799EB1A05729A:D8F3B9E8F6A746EA5BBF1053EE5D96D5
+
+9F75767C335CC510E6C814189ECD49E8841F84558AA47D491263:\
+90E00F618EB235500F89:\
+B64A720D683731BAAF132D6DF42600CD:98CE0D42969D23A5FEB158330167BDB7
+
+29CCA4206E1C37A5BBF518BADCA66A13C0EF15C354C63CDFBBBC1F:\
+4F332A5B8C25A9113EB2DC:\
+FCC2E4AFFA189E41FCF0459C26DFF44D:CF12F4E161270BBCB33065C56F17A16B
+
+1BE9151414493D890F745B9C9810C915C679A03EC472007E07FFCBCA:\
+8A000D4EE11C4E34F75745A1:\
+29A10586F8D97606B9E41A679C348050:1709BBA10AC8EFEBE43E20DB95657CBE
+
+DF3DAF8B27B621FE4A580417174129C2DEDCD57170522DCF082B122707:\
+F5E09BB8E5DBD03E11BCB8D472:\
+CC41B73738199B467196B9A5D6D39682:2904770A9F30EF7A002D8CBCE5602FB1
+
+F9A7C4844697FB986EC79D855EEBC2EFCBC7720F2A9FB9CF74213A49FDA2:\
+FF6503CEBD39F306CCA42EEE8508:\
+9BCD3AF2077CECB7A2FFD54AC8082C23:0A2B880DF94646EC4C12907B0016839B
+
+8ED7662492F58987CE4FDE4229EDC77BF0D32EC9D8F9B048F7846A34D85A3F:\
+449CCDB5F645CD9637511D12F0A3F0:\
+506B94A8633D7873D6C4AF0C6908AEFD:4D4ACB024110D0D74721F45A11974A61
+
+BDA3847797F2B5D97A2E4B1F307B865E4F56543BF56C50BBA1F6020E91F592F0:\
+A66868B66D2467C7216A6338DE8FC825:\
+ECBBA42D11A978A354AE97A093300139:9869EF068E56CDAFC131E79FC0B0C5AC
+
+532AA827573A33F5B81E62BC9DEE898537A8ED67239B80CA3453B71020D864D90F:\
+037B870E75AC9115506E09A0230BCA03AC:\
+B72999FCFBA184A8B895A9B1FD3DB478:C5C2ED715403C2C20C62E5172DE9C3E4
+
+FC2B9B937B6A7F4C9A0DB15278C5CB8A7BA136430DE5D201C66C50689351FC237BDC:\
+E71ED7DFF82A2797EC693B182D313B08C6B8:\
+3DA9289752DF9B669A9D8AB66A71D441:50CC6B776357E19F700ED0AB17966354
+
+56CBFFC676262403ECAF1BC51C3D65E5E1CD293BB5B12546C264C79891160300842334:\
+3D4300526204967051D76410E3143B9C17CD80:\
+37AA0C11E0EB1F53AAC3EE8500318553:9489E904DAC168EBA47C264093F3C0CB
+
+B24D05663B3C762D59AE8B164047EAACE87695B82AE57520E0C87A2E6D1DCBD4407F4090:\
+0A22454378AAD07A5A541ADF20D54664BB7310BB:\
+8ADF49FC3784012C38A95042CC968544:4056BE9AAAD879CAADBF2E68323F24BC
+
+C79E13FADF1F05C15D7953D016FBAAAC7969DE1AD696F802231D449176C2DBB6BA56467B27:\
+FC30113613A67D7C64C63A8F8B664650ACB6DCD00A:\
+6D5300B815CB728A792086AA32BCBDD8:39393D0074CC8BDA12DB86C8B756D224
+
+FAF932FE8F4422C8BECCB00EC76DA79257C56E1EE4ED314A0A1075D952CFB97621D4CF7CFE14:\
+0F1A561E0B0F7C0FD152926D0F90D57384D7FFC38D4B:\
+D64CA6972E6F91E7B2A00108BF0C183B:1BE98EAE579D3E2C10C2030F85905A5B
+
+1F09C21297176C1788562A8126B83E0F0CE3FC15309E6C5B46EF97E56AD125:\
+966B82E2C328FDBB167D085DC029A6:\
+274BAD60A536DE7D916F95CB2175AF9E:0B1B20EDDE48EB9A5E68A2BB28CC614F
+
+23DDEDDEF95C0B28FE8D5B305FD83D52F442D97D465CE637A648EE04578106C0:\
+5A899A3B0AEC81C95D7AA595E2FD72AB:\
+A7B1C1626B3ACA26D2C216EBD618B630:A1506BAB3DED749A67192F4A16A1F5BD
+
+7985DBCD7922D326F9C06DC90E0FC7F518A5B7B11C155EAFBB9A708D6E10CF9440:\
+A73151592F0952CCB9723ABF53269882A7:\
+F3D05C6CFF898C80E2FEC0CF063A7737:8CD0669522324E946D0EE793A6693A9A
+
+C843A2352EC2F9E40094A80D3C7B00D56F0F266128D4EE4CD2AA0EBA9FE98A21D4CD:\
+543D2E144B36DF48A1083735244C91FCC30D:\
+79DAE3A9A8D44798ADC660173CB4556A:C9A0A0A8E941B02077D56C08D130154A
+
+5EC8F04849BF9E61A2145BED2003B1784694AD418CD2944888848D03B16D717346359A:\
+3F5C581B378124D866EE6046CA54DB45993CB5:\
+5487234213607058995B0E949A6BECB6:A26DDA7AD3C8DA19922EF4D8C7308D1B
+
+7EE5D87A59A6B11072123E7B728EA99A0C89E3F4EC9D9E6D088D09C57F77ACA82B6B36D9:\
+0C1AABA9072AF4CA02D6AC2AD5B2329523AD8C7A:\
+8E9A279E45508D14A43293B14D3F5A54:694E1F6B24CB95F97EC78EA1751B1B03
+
+83765858587AEA004B2D98A3E1841DAB06E251E5AB455B6E7434889B014BA4586ECD354880:\
+829F5237301335F035CC410BCE75C4C2E89E8109A4:\
+D96E6D0D53061BAD69902F08E26638F5:9C292B686A3637DFFAF9C7987AD03D54
+
+15674158151BA6A84F7C8937712D65A5B4F61325685A19EEED471E2CA7E2EB43F15CC2DC1D36:\
+B9D5B9BD05F145CD977E358D799D637F093D797D8378:\
+AE3F3D269BC1B851DC7126952E2C8774:F91EF22FAB6BCC0EEAD54B6353CFDB01
+
+4EC14FA09C85395DC42D807C64B052203FD889907B40E8\
+DBEC0AB58A1C92882CE226770FC4F5D5:\
+339431576AEE57FE6091D148E5F6CF7827F25C131F2CE0:\
+7CDA2113620FC51042594199C32FF1C2:8F8293D76789A6DFB1983BC4B868A434
+
+3A1AFFDBF58441C6CF36D4E40A7D2DF0170D1EA2B99F53B7\
+37814376AA1BFE8B4E09363225EBFF25:\
+0ABA7C2506C0C304711B50BCC699B7C45F3DED61A794ACE5:\
+ECF144123590C83F4A44655005285576:43A532093EE9CE9E26BBFFCE4FABB33B
+
+7F3D6219C09BD6ADA2C02A8E7A6218E070A2D065F68BBDE76E\
+8CFDC872AEFCBFCDF237D789371BDBEA:\
+404C55DA8B61CAEA5ECDD03602058A07F28499944B86692B8C:\
+DFA17F19D8CA59241F34AF81FE99DFCB:6A15CD6F9FD462236DF66FF4609A803F
+
+A4140A86D0BC3A9383C19709D2C4E833F3474C8AF0C3DA63CA\
+6ADBDE7BCBE8EC0F11141C4D0E4415FBE1:\
+54B2BCC0182145BC510319425F6AD3B10A1A9BEB65C04B32DF65:\
+3B0E2A90CD7E438A3F5BAB8417FC8730:3EE79A1198A52B339091F3DBC3D340FF
+
+2718AB1822C8BD9DA39B479402449CE0834BC1616ECC3F1308A24D\
+EFA73CB7D1FBCC310686AECBE95F7532:\
+1A392F066BECDF3F15D95B92098028FEE4310A283094A3A81CFACF:\
+C4D21881ED51B0F3BD9DD2FCB2AB5744:B5D76DB3BB9EBDE3CE5287776E814632
+
+1A6C33093FB3931CEBB1E7CCA95FE93B135F8D3768AEE395FDDF81A1\
+C60D528B0BF40326DD56FE8ED50F158A:\
+15E86BA59F0E3D5AE3A664967C1BC3F6022B8DC12986DB779273BBB0:\
+ABC25FC0AACA664AD9A3A4BC490952C6:2415BC27414AE86AD0C3E163369C13E1
+
+585F73C77639D0DA807CFCEF82DD595E5F57866BBC2F619F49612792A9\
+6C2E4C739BAA2220F986801C95FE12DA:\
+7C9C82DEEC159CEB4E9890F0FCFF5010F9E574362A3D6D06B2147BD18F:\
+14440CB0C6EA9CDB8687291E181A1B17:6A2B104F9F4779DCB47F8FC8FB60580F
+
+F942097AE0852BFC7E5E4034BA987782575056C6340177427F61E313BC2C\
+A2CD299779B29E8D500D5B8F84D6CA5D:\
+7D4A2EE3D0CAEBC205B91F090E6195C472AB3C8F56587625ABA45EC236B6:\
+2FB3005D96D02881922D3BB1364912CB:0D84764913CCA18AF14C2E4F0E64053E
+
+3EAE2A7691FF14A55BF3364AC597A121FDA3816505447F6E656E6F90DE370A\
+B2F5301C67E32A4791273DC653CB9062:\
+8B64BB53067C0A54A3CE6747467225AD9E3C853FEC39257D37A9DDADAB277C:\
+368B378A91B494E657624D9FA8BFC456:5E00DB9DEC14C2694C6C46F9176D764E
+
+EEE5FB0FD6F649C34C45F27D661EF1148620351502B170EC1B0C677569FD210F\
+59C137EA5A5C0A:642F4682F88B96C3CF59B2E6FCD637AE208CF5C909ED77:\
+1F9CEB36B1C443E828722EAA6ABA412E:899AE06F96B7A644D73239A03B27185A
+
+A75638B27A2F4FE3582D82415D92D25C0B1619CCF369A212\
+D3821CD8268A2861E684DBF033DEA847:\
+9B20A4045D8350AED236E92ACCFD43608017D7CE19ED43C8:\
+923874D1FCA7C997C86D9C25F1ECD3C3:22BCEDEEB9304E3A48250861124B2AA5
+
+DBE84456BCB905B3637422CA28EC7A35AC31EEFA1BF37A7487\
+8755F2FE39C2D2B2DCDCB2F31450E800:\
+EE45AD121C59A97B8CEBCFFF2BDF5DE934F0380DABC2BC109C:\
+F65DAEF41041E256EEF472479EEDD489:BCD3B49B309DD021D6DDCC989ADC3490
+
+690F6EE8335B14038CE0C4503C2BB83B7A0198BB4CBEC743D187\
+F18DFD6D02E879B2FE69CD0EADDDB3A2:\
+40765E67929DE7BA3ADCFAD278046E20484408B14FCBF9CEF874:\
+6D3FD9D7C1194E1F80E0BD679AF74494:C9BC9838DCE17CE592CBB08B99A80007
+
+D9A4B214F4E32DFCE30964284BBDCCD6BE6EE0189982ED45BD6CD0\
+64A073D0E97D1B750008C05466EF09AA:\
+45FF5A1365893BBEE1B34E6A127E4A73F8AD5BF102B15B346F23BD:\
+9CC43DB3093D0D1CA2965760780AAFE2:1D2D2C9025D9EC16DC9D72100D95CDA9
+
+1978FD1154D9855E614E6916EE875ED1C938F9CB92D57E582D74018C\
+EFCF84BA0767344E0F4AE7D283DB8D89:\
+B81D674F959354838BED29ABDC7E3F7D8481C96CE99D67E0E4DE000C:\
+EBC521A3E388F3781C47FBA734245210:A2918D26125692FBF3FADBD7D8DCE4C3
+
+43BAF08789367FCE02931A495923920B1220B3D5C80FAE8AE5D971C7\
+C325A84838578241E52E76B684EDD3DE73:\
+69786524F6287A494B81812425603368DE8E50EB1E437EB6EB478B163F:\
+4D5CA9C6C1CDBCE9480534C98659EFE6:8C57C41BA7AF39EA2DEFD6757BECB4C8
+
+47D494E426676CE2F7008D773DECA0F70690502D89853406C6D7D2CCBA89\
+6CC0E0AA8E3F23E7F7DE8470305BAACF:\
+15C0756699C707CE22491F8EE3798CEB43F07A9C654CC5B0F6B1533BD430:\
+47E9F0BC4F89835757A6A0773483F0C0:6E33B1E8D0163595C62B4719661B49AD
+
+8F3E66BC1A646352B7F4CFF7D001CD9B86BB808E3A87DEEDA3E8B68C7B8315\
+D03ABB22AB91A9168498263FBEA483A2:\
+EA377982769604FE3A32422CBAD2D886D39B523DB489319FAFF15937C21E13:\
+AC558C2ECB2332C95D640B8A1FDE62A5:B1FDF8EEB1811F513010AA67D2C87B7E
+
+40310341FF81EA8A88D7E4A56587AF7C::\
+59A8A96ED2E623F4E9D947CAC18DC990:79674D1D63FCA5D519FFDB6C296F7082
+
+8062337F189B40867709312776BF2EAB16:E8:\
+15BF347878D67E708238EDA55C887885:203E5B72637E6FA8A1073FDF3B20C750
+
+01EB7399A21FCDB387D25DF865AA6BC1C267:72A9:\
+B896C67E8B41B87260D02A552F6308EC:5246679BC7FBC5624A8DB7CDE1297699
+
+5F88883DDBE73A2F42C189785ECEF40C2840C2:015060:\
+099DEB942571FF3B10A92A6E906FC2C1:C2CF13025EC6D16B82C6284DC779ADD0
+
+71EFC1445B39BDA3653BC6782E63CCC3972BF760:D82B67F4:\
+29C312A40B053890C346F9D28115EF8B:1962F49E4AF7703CD8470CB07373A49C
+
+8D3954997ED9F3520F6ECD1C9BC47DBF1C6CC57D26:504F42CE2D:\
+2988D5019BD60E616400FAB5477952A0:5B4054DF62AF337A438CCB93CE99C0F7
+
+24EC9189DDB36C88F3FB33DE3ABCE099E43AF40EB1D8:611330C7AEBE:\
+561DDE748B1FCAE57C3DEFCFDE0271A6:83737F42C2AA4BCF18ACE248749007CA
+
+2A9BA364F8E7F57EFAC8109B1E03227934B549A3A0078A:298A24AD7D6DBF:\
+7BD999B1F33A36193E4EE6F028299388:BB9687C2176C6A4595F56A4272D701ED
+
+F6B6A2F6E1510711ECFC957C93C68919A5A45EE3D0B2AFD6:75FD2D40877B8432:\
+6D74EA617E714D793C8DB9395A49C63E:F42A025EC9BF043EBC317E44AC02761A
+
+0341E6D787948E8BC9A17F8B9A59590964FE0AB06987334169:0FB90FB34C5B9BD476:\
+2FCA567702AF585D40A48AF2DB191901:94FBCA24E072339981E6E6DD82BA53B1
+
+2456A0634E033EB2C782A76127638297E61DA31BDA1F54909D3B:B3990AA14BEDA81F703E:\
+4A15134D809FBBC80CF4B079EFC6D4E9:E27795C82349622DEAAD1A92CC8AD116
+
+6ACDCF1AF0A6C75858C37CB6320AB22BE515CA582A1F72DFAC1097:39829DB0BA6AD872DCAE5F:\
+B8457C4211064A0C8B73983C6EDBAFE6:883F1918789BB528561F00C8FCAE27B4
+
+A215B0BD9C58AB3331F78C0EB238167F27B1AFE1EA4BD87CACC5B300:\
+F6C41B2D43AAC7F4F0DB482C:\
+1827B62D763ACFA140874AB706C80FF7:7BFB0171BF1C9E02C666F7B7413FE359
+
+C2AE1B5AF7059EA891A6D1D467AE9817290A893586356F79C7381BF177:\
+9E10318744C56A3008A5EC8515:\
+1649066C2B19B5E549F90C0E0C0BEC53:AF08F2BF3A7904FFE4340889208D9E36
+
+4F26AC6346CB5D7A8F8AA5FE8A3F721ECC63A3DA914B1AD48B1B93D22635:\
+60F4F38483E7AD0025500B8B437C:\
+FFFA2092F276F4B3FB5961F4E8059C6A:91FC5F8480E26C2DE2917EEE1CC16A1C
+
+EE5529B4F23A6D8B6D4A6116F512D755E38F05295A21E9C6B5239558FE06BF:\
+1589266048285014F882E3BAD57831:\
+94A5B81B06729AED640D236929A28F13:B7183917606167755AEA5814BFD04554
+
+F801A572F43609E21B1B2CFC480CC255B6B3927C2B14205DCBF0930E388EA229:\
+EB0E42B7343D3A6EBEDBA8A6A049CE77:\
+95B69A2A04B2F33C552E7960EA802CD6:8E6E8DC2ACC7316AA2D9104322DEBAB7
+
+F880860816D3A071426469345BA44BB27D070DF896D9AA2581A1D89689B56B9668:\
+D8DCB87E15D3BEAA03F05B2C77AAF23535:\
+78D92F1F74591CF5628909EC20E2C4FD:9B43126E01BD71F1189E68C2909EF708
+
+F25661B5CB948FD1B2CCA4A7B124DAE53BBBA8FEE464FF95109DF4D1E02E4604426F:\
+AFB23921379CCB087180CD8A614FB6FDB2B4:\
+B16386FE78B6316264C22DF9DDDCAB17:FDE3B3C8EB2448B8AEA90764A6B91858
+
+A900370A2EC7AC2CEDCEAA2C255294C9CB46D6D97131D8E1505F7B1C4340F843BD1CD3:\
+71F1F9A2A4A33361417CB1A99ECCD83BEE148D:\
+77A9689AB5DDF5645E678C57D87D507A:21F3AD82342933DEC7FFB603EDCB9064
+
+BD005D094AC438EDE11B7D98482155DC8E86C614CB13D2FA0CABF8D2631988444A3E5D97:\
+AA6AD3EB14DA4E60BA09A9638DCE91CC31A66830:\
+CBC59EFCEBEB74619CF0AD465B81326F:5B80D015897978164709E279AF4AA97B
+
+57FCB6852E72126F5DB7B311D1CFFD5D879EE6E2013A1FB568CE1FE61A82F712256CE617C6:\
+A5E672D7BFFCADF0F12C81B2D06DA016C252D54522:\
+FF38036E82ADCD2EDBBCD4C12EAB802A:58701C85F1CE555E6F6B21C14066E33F
+
+A11936A7930617BFD935B7B380E052AB245B5EBAF26C8E7E55F28B9B1FFEA3BBCD3224F037CD:\
+A80EC62DA758DC5378B0F4E98DD8321C1D7E59FE55F4:\
+CA603873A7C460A7C409B58A365CE212:B05AC2A4444F7C766B9AF4C49849B862
+
+9DA94E8A4F0D70643357D8D8C9B31D85::\
+69A8B04FB205D3FFD56C34E2C76E0D35:11262418D091320D2C04C8D0E810F751
+
+7AE167B307C2F4DF79F63CF916B9BF1A58:25:\
+A3E94A0B4499F368B968B7C6FCACC234:025F7513BEC5B9744723A9FD4B7522EE
+
+C02B328AC966D363578406EC6781732A0441:E954:\
+FA133478073A08E890B4E159B4920BBB:901D53BCFFF7DD75AC0F1E3559078953
+
+250BCF631D446250F8837F8FA83A6BF5386C84:E2FB3E:\
+E4F79E765765409D324E1B1EA414D227:FBDA962D22F40DD772DD774DBF728CA3
+
+203D92FC604EA0896CE956A5DAF9EFB62714D238:373F1A06:\
+50070DC0D5244E49CB9C66AC7057CED5:7ADC4F5C39F9A000EF14B52653CF2CA4
+
+757293841970FADFE86782CA41EAD6CEAA2EC957C2:EC3B7CC743:\
+103B1080C15BE0AC6124A0264938A10C:882023A6D7A67CB1FE759D39F2647C02
+
+59C5C5C3EAA2D728B32BCF1B49E4C18870AE4C2F7098:BF1B83377790:\
+CF665E60D491E84EE5874AB04FA9D38B:A8021B4DDF9C63E58A23000D5A779E29
+
+93C5B53F5C534BC3ADEFB928D3470DCFC8852C5E24BEA6:70CE6AB07A9A8C:\
+BDA78F4BE0174F8A04C5DCF1865E307F:6020C7248A4FE110BFAF7A702915FCE6
+
+61D5E9CCB1E8A2F1458ADD75AE1BEB7800D6A37244109E83:C5814686F6429BF5:\
+55A89D0EAE5316F685F890E297E62AA7:FD97541DD6D93C9B5B822151C4BC4619
+
+C818A94252A8257FC51501B6A67D4D008ACCE6A3B09E1B84AE:3D8F73596B10934BD7:\
+C9F99830A1E6B5BA8D8A1A48E7C2060B:5A1811DA7C2C170B9F7177AF04C287CD
+
+D987E31D050BCCD469D18C44A28640371A867DF44373D517DBAE:B8AFCF7A49212AD45FCF:\
+40E64886878D1D3ADFEC046F61D3E81F:FEA453D7F80C87C786D0E9B1A44880E5
+
+5F2827FEDF63228EA08BFCDEA50C9D5D904D71618E6DAA63EB9C22:A3CF005672C1F2E6E1983C:\
+1B3A82403AF3B423CD1FDCC2E6714A28:8670E19913B19969235A5C093BF44657
+
+E032CBD49F0D644C67A352AB9FB1107242BE2579D1C7A45D08B44DA7095E577D\
+9A897967CD41602B8608C8670914C13A009EC1AB9857143FF6E6A0681D24A75A\
+C222FA89CA68E7994A969D5974B4755C66FA404362F336B3D4DA9AF4AFEBB077\
+F9907F9FD674B8F80470819A0C09993B768F9F5A22D8057C416712E22E9B31C8\
+62626881CD3229D5364A5C949985177F0D8A3D1583571931CF2DF2D20D893E61\
+119313BA902831:\
+7F4E62DFB140ED5C948D666A2919BDB42905A549A8B6B97259A273C9E974AA68\
+C30C48744C35D0E1C2364BEC5008A0790D45C3B6FC7C28551F9B1E0810C871D3\
+D5B94721EE1702B04D4D9C9D563C176382DA197E5641D375DDF17EEDBAEFC08F\
+A807B0961EB3466B00E309561F20BAA1FAD31F5015F2C6F2E444DF9E339F2DDB\
+A6DD71C490B72F919A38E7BA58A15B52757BA38A6D697C:\
+51AD5BEFE0FA1CBBA0FA2C648AE3931B:7ECC033824A49377190E1AA37C831FCD
+
+E5CC4E45013E62EE928B519F369BBC2C49FA0F4A7E99419E2D67721DE413710B\
+2BF0D011EC4483BFA796635544016321C284DCE6EABB25D0DC72B52DE5F6C48C\
+384F516F96A2EBFAC4FA005C8DA36DFAC06BDC133A3BBDB64C51C3904E8CB149\
+272AAD85852F60F3673C8B14C1EA06F8C45ECCF898531547A5B928F893874BB6\
+51599DF89B31B158DA2DF6FB811E059F15DD49569BF3CC8103322A21F089FB80\
+41B026695E09E872D82F1533E9FB88B6C6E8A237C7294F6F72751F06CE9FFE85\
+74856C7006F9592FAA80332E74F7AAB78F:\
+D4B2954F1C16268C7C64BCC8066668635AD9CECE9E811018F948DF1560D6D734\
+886C83A582AA31FF0EEDC714532F78AD08467BA7C88BBFC1D39ED73375AE67FD\
+1AEBA29D95D39CA3C163B714932FC29B763D423EC902FF9CA0D6D0158437139F\
+22B53CB789D85A4A3B125ECE41206AB75EACF527AEF5C34FCB936450CB77EFED\
+2D2BA5B603FF003E115E0D537F770ADD230004D2F5C721C05B851026FDFF132A\
+2AB8E02DB8E06CC93E791CBDF0279A13279EE51C6606DCC18CEDE789ECFAB317\
+B3:\
+93446B73B034B129516F1978092D9FA8:12BB0E1997CFA584B62E71B0E1886374
+
+17355698DF0456602166D82D5399F159D9BD771D3D23EDCD6364A855067E2CE4\
+AAC59A671D0C223B9D144B67DEFBCBB2025580F83EB5BF4C0AEC626C7297001C\
+A1A9A0EB46505265C591B1514F75B17EADC5667E991D3871F6EA8BCC1183601D\
+8D80E24CB6A2C22E27AD9A22F5B745033DF0960722D1176E9A162DFF184D8011\
+7DFCE09B8F97ADD449C3ADE8F7F0B45C2AAF447536EBCBC610BA543C3D3D91E7\
+37558D54C9F724B3501A5AA24B2DCBBA9CF2FC17D8700B356F5733A64535ACF9\
+325B48F40E28BF57649B73C63461B4EC9D7163:\
+407B43EE14D1B3CFD48F4FD112CD92E4DF5BC3A9AD29C4A5DB5A0C4E6151E4A2\
+CC2890E1F943B0CDD3FF9FE5CC31CAAC8C8D5539B61ADE9274EBE0D53CC57709\
+ED08EAE64B9AB31E9952046683CE120F5B6749128127A4F51284CB4F49425836\
+4A421C96DCD0B47522B8DBA686EDB5E255FEF4D62698CC381C978766D9DF9C24\
+21B9BAFD896E73AB274E51AD3C078F910583672B1B336438CAEB9EA4CB3AC8EC\
+F382EA7CF05D2817AB79C5E780547886D8E0B1F313152BDE01C982CC044AB8F7\
+CCA274:\
+BCFF9CD4AB15999296ED0B1CC5EBCDB9:FEE3E4DCE4AE5EB0B2A868A9740B1D31
+
+8571D4B7665B32DF2A17849408AEBC9FFFE73BB7AD18FF8BB037227C54583C5D\
+B7A28B87193F94DA28F45C8D2EEFE4F765B3C0EFB5A3C09DEB3EEEABC7C78CBB\
+120C68C13129E4609B05CE484F5DA5BF07C3ADD4996DD14CD7F2D34420CF9E96\
+B529B573A8376317CA02B47A55156AB51FE0C713831C3FFB5E0ED8575FB3FC69\
+24996E6FC9BF0E20F5E58A137347A7532C75F2ED45C33061D0D3455A473FCFF3\
+41C0DBB260E583D4F499ACBE4DA22A19CE8D2BE53541BEEFCDFEB028793A60F7\
+156ACD1ABE5EC842B3B1F8B8A6A8DC028A5B15EF:\
+4DC29DC34D600238E38882EF62C982CDC34DED3A7EEBC36D99E11FDD3D523A8A\
+14D74D61374F991AD71B0939E48C06A8D9F4E257DFA5C47887E355C435904E49\
+679BAB9FEA44B9C160C3FA444F00EC28F4CE80D374444CFB28A1BF5D310DA799\
+A852389296F153F6B44D3B034D272C42F6AC156AF061651803247634311DCDD9\
+6F056B05F7BEFCAB0B37AF585EDB9A5487B0BE77112390144706497823165192\
+1CBC97137A93BE85CA6DDE2948787DCF283C473A5FD74EA7DD971F00AE7192CA\
+2D29DDA8:\
+BD9B2D87090BB051842E21AC6A68E6C9:3F35701CCC901C7A01AE442ED721D694
+
+CDCC757B0721890851AF53EAB7DE0BC2C0BABDFCCAE5ED76E01B1351E7DC7C4D\
+882AC19EDC147C7B04B6203B1F4AE98251E13D7336B80B35BD42D5549951E2F9\
+F0CB913E3999527888D6B40737AE5EB9AB41B0051612D08F956B157D409EED5E\
+BB62BECD72B92A553DFA52B185357BB96F74E04D63EFB0AA7B239154698D4241\
+DE34ADC79D944FD8B0C0DB24826C57CBB4847CEFAE328418925FF3D6FC6EF3E0\
+2CC580A2D18DA0F6FA0E3E5BB44A7B7D058DF60024BA4F9866E804E05DA6FA77\
+453DCD3008430F314BF10E70FAB7BBEBC69B07CB60634F3D251FCE93AAE69702\
+010E5384D395CB82967BD606F9E686D3832C39497F1A9DF2DE621C2F92C785C7\
+CB0BDEBEBA5C4F1C7436B0FD931C9B245B8D0991215DD63F32CA48345EC64A89\
+68927310CCAB1E4B48813342EF6C24F92595763D2E5969F960C23D682A38AA4E\
+BA7C5E730FF289A58DC28762D79C15B249A0D31C7F6A7B07A41FB78A418429F8\
+5F58314D5D65F58C7C21B5657807FD8907CE47B5324C94D391676E86BAC4B9F6\
+CF870B2E1F7703BE8FCDF4E82C848712315C8C61BA10752AC59F90665C7C4830\
+CBA53E602292634422CBCA81D3C7CACA33F00FBF136358A921A0A7267D683A7D\
+2CFF3F35553CBE486BD7A4423E6F167D998930246EFF28CB33B042FC8AC78BAE\
+D594B5487D4FA8BC2F32712FEFDAA5B4A91085A5C75B43AAE3F5E753F0CDC68C\
+113C94C2030BA2C7E1C9C580592C8D4A08D0C46A0A45FE486369D72AC0AFFF21\
+5AA6CEECD32A781BC52566FFB25BE7975D724A825D2A74113A0840A00CEFA835\
+04C8DE918967EE89DCA99BDFEFF8C359FEC0023104BEBD00398E6EC01D38975F\
+4AB4027025ADE93B0BB7EF3FD24A9400DC304068221323CC87DF4A6AB69160F4\
+F683C6005BD32998B323750A58FC532C437BC40F0D453118D813178F332AD789\
+C2875EB6C3249C93EBD2CAAE6733093678F5A975A00D29D5931A1CA8FC07918C\
+5F232359F044558ABCC36520E75668886E9A8D33D088AB6F2B15FD571B220B71\
+4AA8D9B9014EE6EEAA0BC6F36EEB508B5914C1C13FAA9351C616221A7A880271\
+F84CE54FA9F377DAEFB738636C6D8C563F6D14362306D89F8EE8C9C3A13E04D0\
+01156654A41FF5405A6F8BDAC1FEA59EA0B6206E3E9364244E9C9DBB00836993\
+F7E19605E3D09B2918744DA5BDA9F396FA8D008A27DFCF63ACF7AAB37593BF3D\
+183146A59EA92D:\
+FCA1346D6430C5A6DF980E7E456D9296BEAA203C3A63704FADD47299AAC26FA6\
+63A313C7D4D86DB3717B31B6E9C44CA76E6DE3A8D053F77D276917D12B86778F\
+2A8A56FE63C4B1D43FE38A28A7D6CF1543B2BD1406B4912D1DA8FF492F76D859\
+012E5764F2083832EBC25A92982AA7DCDC64F0E2188110362A0F7F598557B286\
+8509EA781122AAFDE4048F7D2E37590B9B49EDB4CAFDEAF40C694D92C0FF1845\
+0803BD1A2567170A6CA6879ADDE0A57929932DF39017E89D80352F403547853D\
+4A435770AA6E7A161501B1F2E1566B0AE998FD7AAFE5172F1B466F508DF58DD8\
+38E548E253C2F968C3AA5BA400C6AEEA5FAB640E917B3EACC1ADFC4EA28926DA\
+6E6EBDC230B62AF3608597604C454AABF1AEB98229F72EEAA52A3947B35F2222\
+CEDFE4FE950EF2F5948955E0CFA08BC04E4442783C7062E19A9B284DFB4A6FC9\
+2953C7BE62B9B3F64309D612A961D2F7A5146FE184D2C21E6DEB6B6835DB315F\
+2EF91D90B2D186F5DA5C0783BDD97A63EDEA4471BC078F29F2FB9227D6C38604\
+BCA4956F751B644F786CD235454C983336DDA4F2E4341CD62FAEFD057184092E\
+289E9D9DBA01EC326DBE67B30A00E641DD8A33C1BE4F97EDFD94F26F18FC9D40\
+9A3ADD543BC986A987EE5C92EE42D3CBCC068C8B56237853B76BC2D0675F1001\
+99EE56D5B7DC7E3FCADAD1B81CA483E8AA0F730032EC54EA5716BABE76CABF0F\
+B815E470F262AFBC3C80755824F841CE08B4CF3AA02324F739DEB5AFA975BF61\
+8AA3D17C0680394200AE9B24A6DCF3AE90C2E931E50D281EECDECE95538DF6DD\
+30C85A364893794941146DE7F0609680227FB1078CDA2678B8F40D0B8104E8B1\
+CC42E814D5615D1675CBFE652B94E54E1397559F717B18296F2534F0291CA2F5\
+5F8A0A34EB674B603249C55EDDAAACF041018FB27DA7DBECCD0FDDF62C7FEC8B\
+09F6BFF45D0A54905319EE30C39A20059BB0B71857930524A2E21BCE6107596A\
+FD195E5A23B2EA77CBD8A78E72C8930E784B26CFDE2BF4800D0F4F6E16A8D813\
+C1366DE5E8585CB3300342A3CBD5B14320D713FE03077F1016CE7F2C76573F38\
+8EAC1D7604792A357C6CD84841898B62609E6063A5DF74BBADF3E7244A265CD8\
+D3794FD7F2790C6EE5E4B6266D4288CEE0E93186C8A5417698299AE34FF6BB22\
+6F0AFA618306CF68EB868F58C81726A800582EC9FD703F:\
+9699D979E8CF340B3E3F059FC20B6E2B:F6F4BA4FBCD17565D2CD939BCB03DA61
+
+[AES/EAX(64)]
+32E55CE0C3FAEA48::\
+C61A0851AB4E515D11525B92E2B9D850:C825FC7C4D539DC74887CECC70884F37
+
+710DABD24D400F3B6B:60:\
+F956B879EC7F807F1FCB482B53623671:E64F90B4619D93137E6237929EABF297
+
+[AES/XTS]
+917CF69EBD68B2EC9B9FE9A3EADDA692CD43D2F59598ED858C02C2652FBF922E:\
+0000000000000000000000000000000000000000000000000000000000000000:\
+0000000000000000000000000000000000000000000000000000000000000000:\
+00000000000000000000000000000000
+
+C454185E6A16936E39334038ACEF838BFB186FFF7480ADC4289382ECD6D394F0:\
+4444444444444444444444444444444444444444444444444444444444444444:\
+1111111111111111111111111111111122222222222222222222222222222222:\
+33333333330000000000000000000000
+
+B01F86F8EDC1863706FA8A4253E34F28AF319DE38334870F4DD1F94CBE9832F1:\
+4444444444444444444444444444444444444444444444444444444444444444:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+6C1625DB4671522D3D7599601DE7CA09ED:\
+000102030405060708090A0B0C0D0E0F10:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+D069444B7A7E0CAB09E24447D24DEB1FEDBF:\
+000102030405060708090A0B0C0D0E0F1011:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+E5DF1351C0544BA1350B3363CD8EF4BEEDBF9D:\
+000102030405060708090A0B0C0D0E0F101112:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+9D84C813F719AA2C7BE3F66171C7C5C2EDBF9DAC:\
+000102030405060708090A0B0C0D0E0F10111213:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E:\
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\
+9A785634120000000000000000000000
+
+# MARKER: Stream Ciphers
+
+# Stream cipher format is plaintext:ciphertext:key
+
+# A few tests from somewhere (maybe the original reverse engineered code, or
+# the BSAFE vectors that were published soon after? I don't have those posts
+# anymore...), followed by a load of randomly generated vectors by OpenSSL.
+[ARC4]
+0000000000000000:7494C2E7104B0879:0123456789ABCDEF
+0000000000000000:DE188941A3375D3A:0000000000000000
+00000000000000000000:D6A141A7EC3C38DFBD61:EF012345
+0123456789ABCDEF:75B7878099E0C596:0123456789ABCDEF
+
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+010101010101010101010101010101010101010101010101010101010101010101010101010101\
+0101010101:\
+7595C3E6114A09780C4AD452338E1FFD9A1BE9498F813D76533449B6778DCAD8C78A8D2BA9AC66\
+085D0E53D59C26C2D1C490C1EBBE0CE66D1B6B1B13B6B919B847C25A91447A95E75E4EF16779CD\
+E8BF0A95850E32AF9689444FD377108F98FDCBD4E726567500990BCC7E0CA3C4AAA304A387D20F\
+3B8FBBCD42A1BD311D7A4303DDA5AB078896AE80C18B0AF66DFF319616EB784E495AD2CE90D7F7\
+72A81747B65F62093B1E0DB9E5BA532FAFEC47508323E671327DF9444432CB7367CEC82F5D44C0\
+D00B67D650A075CD4B70DEDD77EB9B10231B6B5B741347396D62897421D43DF9B42E446E358E9C\
+11A9B2184ECBEF0CD8E7A877EF968F1390EC9B3D35A5585CB009290E2FCDE7B5EC66D9084BE440\
+55A619D9DD7FC3166F9487F7CB272912426445998514C15D53A18C864CE3A2B755579398812652\
+0EACF2E3066E230C91BEE4DD5304F5FD0405B35BD99C73135D3D9BC335EE049EF69B3867BF2D7B\
+D1EAA595D8BFC0066FF8D31509EB0C6CAA006C807A623EF84C3D33C195D23EE320C40DE0558157\
+C822D4B8C569D849AED59D4E0FD7F379586B4B7FF684ED6A189F7486D49B9C4BAD9BA24B96ABF9\
+24372C8A8FFFB10D55354900A77A3DB5F205E1B99FCD8660863A159AD4ABE40FA48934163DDDE5\
+42A6585540FD683CBFD8C00F12129A284DEACC4CDEFE58BE7137541C047126C8D49E2755AB181A\
+B7E940B0C0:0123456789ABCDEF
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+7D0EBD8586251EBA5612E7F0AE1461B85E7D6D01870ED72CAE875737359780097099D507F3F9:\
+2E
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9E10A6E1E7C66081EE6B06A86F27B31528029DB35C156E571A7A39E09CD7FDF706DE80056CFE:\
+395C
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+193FBAE8145757A70ABF7E4B5DA4BAD3C8208916085ED2462C901EF01FE42818B027A6E0EB2B:\
+FEF6A9
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+EB75D7A79E5F7C25156A5A63FECD9A6A67F48B97448EE49C3E3311C940ECE6D317F7CADDAEB6:\
+547BD96F
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+39979C6BC7B8DC7243AD1148C1AC76899922F9759DF1988CE2FEFE0FF91CF7E908F30777BBC6:\
+284CD53FE9
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+309D05E88D1A980CDBB341930F0086CB0672C85F37BDFC2CDC36D80044AF6B02E3475E3D2712:\
+DE8C6ABE0052
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F409D463A1293AD11F4021982B7397D554F504E80C3AC0A6DC5C54CDDD090309BE00F9213E5E:\
+B4D915156C6488
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F76241985FDD3668E0860D9396012F61F338EC7E41CC23BFD0B62869119560DC2A0604CB3C6A:\
+68B5FEF1FBC10AB4
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+61FDF65602F7A63ADF57B05792F6C3642241EF46B97CD86171AED28D26D67BFD6E1E66C7ECF8:\
+EC498E2BCA7AC2BB9D
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+75258D597494A88866F4FE45B09ED2BE41D49B7D653539508B4BA1A3B6F9A08C3C103267D820:\
+169D98FB855CDD15E205
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9FD90A643014F30D5D2BDCCBC37212904F0AD69FB23637B0FBCFA2B6E61A2A7B8DD9B6B3A344:\
+0C5710A5843C9AA2C675BB
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+3E04F9E7804F3F8267B2F5EABF4722183BCB17266F81EBE3A3EE8B00D5C9A727105F43131667:\
+837C0042EEA1A15CA24AD014
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FA9B2426AF83EC289356B58006370907DD5D8A7C1BA887F188B7F695DEB96F3DE94E5AF4DEA0:\
+4B5509356362D35FA63C5B8C44
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+80ABD7170971295FA8D525B1EBB8CE95829CBC9C81AAD2472DEBED0F087558433B84E11CE574:\
+3F6CEBC8C94447FAAF9CEC4E778A
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0C3E9A53C6862E2121F3D089737FF54F96916E469BDE5A645FA134ED4DDF76AB41B569649A98:\
+E0A97B4D129FB0BFDCAB24076DD5C2
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4:\
+97CD440324DA5FD1F7955C1C13B6B466
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+07001BC046443693F173F723638A685CEB7DF1CD61D4E93A52E44B914063903A578138EA0FD8:\
+31DE7ED3BEB6EAF9131922D06201A19366
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+8C68C80B6A01A6571642966D601BABA39B1644177C7C3B35A9D91669F7AE8D22A57308D05F1A:\
+368C7A9662385B308F696A0C58E5E57E768E
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+2A0BDB20E12B4BAA2E8C3D40B333B55ABBD0A156826BFBFDDE066F9D73398841E4A38CB78B5D:\
+F745ADBD90EF249FFC14183A9E20F69BC68214
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+64ED1979AA8B458EE96EEC995E4EF2894DE0D029B1C0DA497A9BD7A81ECE4A408C253E9DA074:\
+872DE53D5116911D916A947041D22A0D50B7A5C1
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+DE31449883D5E651E6F889E2F18C453F06276D13999607FADC393A2619DAF7E2182C214872C5:\
+27FBBBE2EEC453C3D5970A6BAF03FFE299EED3FEFF
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+81570047B8BB9E5968B15F9C286F3F2B6264F8BCEE5C64A698BB2F35B697E32FAE6372BD07A7:\
+1BCEBC37EF602F758CDFBFA1F1BCA61AEBEFDD79B179
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0D8BBBA8FEE3CCEE8CBB3548F52AA85D9FFA58E50655E19FFA31DFCC97F65116DA34BA775559:\
+6FBC9F1E72F7E6EE8D233C4B27EFB98351B5FEAE803732
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FA087B45D61566E102A2B099CCA04A499191C54BE21C67C17D40A2EE81B0AE1F525AD7E61BEE:\
+852F2F3CA64B0C256B080A577E135A54B01D9079A8785EF6
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0E79E4BD49A8CFC6BD1031FDB6DF4BBCDB96D64967AD1710C3BD96A8287064B211A984C82C4D:\
+8EB43FD27CF769A39BBF2FE02B9E4C6ABEE996DE591E5FC521
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+B420CB807A85D5EF897AE3EC7C7CA53EB2580F11B9C815DC6870FD3D0DAEB8EFE5AA28DF2E9C:\
+C3CB4048B42619DBB1A16373749B8264960CF7CBB1EB6D3565BD
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+92762FCEB9FC304D2FF7994AA435E4774FFC1D97C9CB36F89722AED507310EBF028EDB0F6323:\
+A7F0BD928BBA925A49B117ACDAA68702B4D4342F8FD62503319BF8
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+978D46FC073896B8875C7D4EB2F7EA35F58877550071F056584DC59E722E850E4E0DE75ECFF9:\
+3BC2C34F2653E210A1E15282FFA01149DF53AA6BFAF5FE04523DB614
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+AE6AFEAF83A30B85D865FDC86362F95642E7A9CD157DA2F12ACFE9A718F3FB996C1C222B2432:\
+6538CBE80D306CD6AB1F027E4EFCAB804D407B00B281240B33A8C7F40D
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+D4192C0818E7E4CA10AD05FBB3181C41C4D0BEA1805A883708FDE321B70D6C7D8B5601079D7C:\
+B7793A33C33FE1C3EE024A7EE40BBD13ACEB02049159717F35279D67F730
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+65029B1DD806694E4AEF4B63016D0685A8EEB682E86353C049378EC540BC0F4BB682740E3534:\
+0C9856E6B845A33EECC0F30BF1974DB4DB088BF02314EE48FC369B6515994F
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F33562228D9339F23EFE694E45A6A5B4457F2865061384B064DD45321D399FD1DB1C3CCBE64B:\
+CC26F0F11FF7759081CC87B0296E46E1A29611FA042C0F09033F12FD06468624
+
+5EF2DE98C92BAE4C15CC2194D37ED3558A44B6FBC7EEF695E85E33DCE1C2CB8CE0779A73D6DC\
+CD1B906CE940A4FD19C4436A7832D4BDF5EC87AC472BB281DE038D3A20DDB8791B2E12EE0B2B\
+3D273F14D90EDF7F07D32E03D74B261F5E501C0D6DAAAEA6E2474379AA983A54BBCFBCE08E6F\
+E0E48959F7DEEFC0CF9FF10FB67DEB51F78248D650D2432BB1FECBAC3347C541BAFFDF0E7072\
+89EB0CDD8C5FE960C5C8206D3DA9D4A2B43A9A3D2F449A7C2834C152E1A07DABF6BBD7BCF931\
+E238BB759D4005E540612A8F7921D368B906586A06AE9ED078C509E4AE7678F01F8ACB681AAB\
+ACD3D644D9579AE28937405F59161E45123CC61385B1BFC75B738D21CDF690B5D041AE425D1E\
+D7C9CA20583B79AC7BD28135CE4B9C1012A8FB7A7791F3B016AE27872CFA7F7BA29D5E1C267C\
+B30E2E7238CDA5FD6BCC1C904AF236EF9E7A88EC71DB8700A7FF0BDF09FB24110B121DB825FA\
+F79FC7587F0D8853AE90CAA6F479F5D3E221E4C832E27B6DE7340850F2231AE13AFC8E9C94E7\
+3BE0F631EE0549622A3BCB2C79C7D6440F694C77DD66E9F98A5CF1ECC80EC3F7D0D0A14B6D4B\
+FC1BFA5DEC3743743F7893E94AE563217546653E2F75271B1CE5B3DFDC01B0A3A5AE6E4796B2\
+6F8059B1B35BBD760A08B48BC60323BA42C8224E7EBEF5C3364544AB3D4C8D93A7805429F787\
+EE5B57D85A570F05268B8FCADB24F16FD4BB95BEFDEAC40C50C55EE32988E7B15334449F78EC\
+A703A61260FAAE9F695715637732837FA0559B6B6BB602D55915B7E401E2B53151D3633A933B\
+786210794111073B3238D16CA7B14D0993CEB7F04A7EC1515B1E79F4BF518B2195A29A5F59F7\
+595CCBB04314535BA452351D23811E01CED3E086F2A6132294541DFBBB6352D0D58AC70AFE2C\
+187842CC606C59527F3EEF330FE4923DA3D0CB838C7DBEEA26EAFC032F3C15C80FFA09C9342A\
+8910A968412DC31247831F1C2CE9B5ECF365A84880DABEB08213F6EBEF78D42899DF0A21349B\
+B01ADEB9AB51B1C312EF0F5E80E03BDC84CA28AA4F662F7FEF874F8572956F44F49477092F45\
+E0254CD941B70964706677C50E9D0B98A6CF838FF4FF81E60E0CC4706F0701AD520DA6D6123B\
+F6983EFCA5F081AE9E548464BC049BB66C28551D79F8FF465E406A12E5605FD236C57BB7000B\
+DBCB52429F2C2CA5B257BF065CABD0B19D4F1AFB91985FA20248BEAB707527B40ED4B79CFA28\
+329B4A2A83018DD00665EBA2E4F7304D665BBF4E05A179A0C0D78449A4A72493390B7DA66F2A\
+0206B8655714BCFF0E5804CE02EF3B718A14F7A1882EB763701CD6064409B545303F54736599\
+59F9219D5AE51E978525D1D564DDD6A4408D3E47AADF8870DF2B1AE657B1C077BCC231F70422\
+FE0BA5E86A7C82AE64A6D8739A57EF629C7D4BE277E6F5BE859F17AC4D960CBD09B13856:\
+FCDD62469810ECE85ADBE33A4D967BAE4FF6B63C6F0D7CD6116228D7DEFF2F741D7FDE4DFEFE\
+48DC89046222B23EA184B1E15BB70C2293CD25AC3C047BD0B53A246A78DCA3482E752FBDECC1\
+6104C9067ACDFE811D3537AA7AA750C10050A6746DE68F6B543BAC92C42E5F8A946A2CC843D6\
+79508A8FEB5D1904C5E61C151E5899849C3FE54700BCBBD009E10824953C41D367470690959E\
+951AD644D05999FC8ACC64A61F2889794235403EFE4B55AECF2DCE5EC6ACE52AB1ECD8B8E931\
+DD8F05E783CE446DFD41D7B4456CFED0E54838E38F4CADF51E33DED230D42300192F8E1B6D8C\
+7E78E5C94AD4C0227EB8AAC759CE436DBD22025D0B1D014898AD77902BC77DF45F137F51277A\
+C6AA476AAB193EFDFE0ADC781DE75050409A94B9B41C6EBC99CA065D99C5E6DDE5EFA43BF3F7\
+A011DB66713D44DBE5C818C29B89B37F2A17108D53DE0CE4D9FE3BF7480BB65E18B5531A410C\
+5060B0F16715D499C2FCB6B6C3506F1E6193B629572843888C18D796DD5D5F7C4A62C658869B\
+00EF502C620E110E5D9E2DB8729E4CE731925FE2F41D16A3B5A9B7B9A2062E96AC93A0F4A3C1\
+7988E46002EC10556DD0936444BFD2ED9C1F7D64FACB3439842763EA0D6554ECAE5515ACE038\
+7B1A96999D218C8F97151B0C9CEAC62AF1D05E7553909D789F9C6FBF0C8CB0921168675DF8A2\
+8A7A4A6125324BA9B5C5BACE51DBA568C25D77947D8781538A9BC667129C25DA915C70F2E0BE\
+E3823986BE2C3B0D84667BD0DE153EACF7A34AF495AF62452A2C3999886AA2F032C212DB60E6\
+E85A9ECEF1FC7EAC3AF28E4F56B0A432AE32A2F239EDD233375CE3C62F77D976FF44B4132779\
+189C0B2AB6316E057353ECE809188EFD7BFE1D1F845789386A860705BA66A9AFF09D1F05A542\
+C86C96083D1317C9053467621F6CC34469A0F61220E5CCD460F9144710571D5D920D70CE7687\
+CA0CC3838C1B7A27D915BFB071036962F7D3672D2FBD13E360980CB484CF9155ED528489A684\
+E4C69262021C9E77F094D1449E8D8F9D358B4DD8B4F7E4148AED8FC6265C1975675C67E5674E\
+4976A64BE3231191EBA7D379451176A02052D0A7AF4676B044414C0ECC075E9D67B117E225D0\
+669F5676ECCF3F2E3EE1A30AB100FF777CE9C51C78396051BD4D747B7B167D8D897FFA0DE5F3\
+1862FA55741CFA45E1C8AD935EDC6F734989CA9072F1F6148D133C09E6EB797A723DF2B45DB4\
+475AA127273A3977C1913860BACD285741E261750B2B7921DF53AE1F51538C328F94A3FB04C7\
+EAE66E1AAEFF01C02CF4EB6EAAA0D5EF2784414D2E3FDC6285B9F4713ED629F100AFBAAEFF74\
+E9F9C35ADE18142C4DDDBEC330AF3FCB6F3E77F05F2D773B6BA545DBD4BD13AC2E1D2B300BA4\
+C1614E779E761A9765D5C6F15EBB6A769290B3ACC8074761189F3DA0F3A4A804C2C3472E:\
+51
+
+4F3657558B507F48C7E1C7D78C396B6ECCCD236154C94EC67D72A17E02AD38EB5719E50B558E\
+5AAA4A6364670A195AD3B932B1994BAA9ED914E11B939D92EC42DD4EA4F4D117FB286C3434EE\
+551884EA3CB4E6C83320AFD10A4BEED39E96E5D04257934E33E13296A18674393A3A5F23B6AB\
+EE2044322ABA0A4211F604B698FAB9296D86D2FFB41AA0AF73BE170193B486A37797819E2180\
+3851947EB4EED45AA56F0E9B1189A72DFA2690355220C122FF3AAA584849C65090DAD778E387\
+6D0E7461A459BC80CB334B3D9DF4984ADA808137DFD32BCDFFB7C59D7F15F239367B0C883994\
+FA4EBCBE89FE18BFBDAB6924F03FFE95C621C71D956809734B33398460DB4ADCDC0598BDCFFA\
+0311B4E35E570F89FEF167861CD57BB1A48764AE557CA475DA66021BF503E5EF5EB6F40260EF\
+2B8018916314459DDC1FAE820C492545F20F9A5F284A465DC1675150E7707F38C690E8FF0501\
+68EE5EEACD67DD48174A80144A057F5EBBB0B3A1D65D61AEF93532CC008DA66196D5B1200FCE\
+D7ACD48F2E9535A3F08D6CCB2F6E20983676244BF3F0C97CF22E496C99A9DCB8C76140C7924B\
+54F95A859C088CCAA8B3B925AFF6393BDAA9333346D1F3D18E6525C5C5584C6BA634AC465854\
+3CEE45121B5663FD99C106AB4479D844442C6577A28CA84C8D41AC3D05210E3994A793E238EF\
+A2797474D770CA030B092E835524B843970FBBA98B01C5FD64844EC271C2924B20AE17EF7EBB\
+472418FB9D31E6F7F065B40950536B697DD773F2C0C1E0FECCDEEF17AFCEFB8297219BB25887\
+0D32AABC8A91E4710B37723228113D5C9504005014D0358B133217CDCDEB164E02F57F30F7F6\
+316B5BD82255D7EADF98E27007E834E98A4AAE8EA0B42AA51B316C4D5201EB3F2CDC70A35D71\
+9A99DDBF0F4078598E1B5233387E20384932E4A59D9FAE8D3A4AF93D25BD5C18199353FBB488\
+D9996D44F0889C572DD74AC545BE159862352D3948EDF79085D812FA9CB1CB2A42A1AAC3E9D4\
+90DE90BABAB42B66C13618C18BB6606DB69FF9A737129F70C27828E95A8450ABF1F18B5C271C\
+0A48A63490BA622976FB7EA3BEF37A4AE7C6350E39A1ADAE2018F6003A7C5CFEBC7E0D934D01\
+9FC9E1F1187CAE86FD50CF003F08EB7F139078EDAD295FA175FF3F6E79FC015B37000DEA64AE\
+D28598FA4DE06EB62163B18FEC329C702F9EDB7561645143ED8027BD7863396F4164C632827E\
+90724298A24DEE1450A11F737C7B7DE56666DFDDADE45345961FE7DD9F95DCC7A5DBA76309F6\
+594E169B8706C21B19AFA85E312BA656078E7C072C125B3233C66A130249BEA9B8C33D501ADE\
+4F1A03747B1BA0C7BA9240C9D2DCD339158C52CB46238D09DCDB6B9090B797ACAACDA233AC4F\
+D5C796AA722F352BF3766C673060DBC7901EA9827FA7ACDB32C64E7D58966306E8959A27:\
+FD33B57D9ABE946FD81156CF3F6475849F742B7FFA9250B1E1A4546416A479A20C959E45E7D6\
+23279E762C85986D22B42F6E64C0F118994A540304E94FAE195691F858F77C2B12772B888D23\
+80344DB66003BAD5D0E305396255004C468A7290852B02C6E4A920C7EFB3B448E6334191A8A1\
+CF19BC3A70851FFF422C45B133555BA01BBE9D06D685665FC58A7CBCA76EF2B22C14504A5AC9\
+DD8BE5B4DC317B1E70E65194C04DB27600929221DE48D4B90F1A28F05B801580DC23BB79CA62\
+AE7B2FD9CE99D195A05776A7C779AF8ACFFA9B78F3C09B0036A875F7C837776EDC0DB1997C98\
+B8905896BE04A6FD1B408DC26926513D91A5E32BDD1E51D9E99284A2F32959E3282D4B8858EA\
+237DF3B4AA3A493D196734DC11362B67CF20276C48BB1CAA07CEB2FA37927773A0EE3F8C18D7\
+760907A1677A3C75B6FB07E98809C56E9D7AB64997CF6F54B292E56759E54A33132BFAFA5FFA\
+7183638A66D436E70616CC4A5724103A7FD3D5B61924A6B6DEFBE6200124EBEC929F61FCFF58\
+2766C2B5F78AB953835BC1FF7DA76701A0933A91DF9F2ED680E60EF410C96DD9C7E72C773DA3\
+CC610F80E9134A8075375B921A03FFA555C3C26A027543DC6DA55ED6F6FB6DB10B34075E4057\
+F74C01A97B9BC5A5B05B83A112FAAB2B975D3062A63534E38C9969E5374698BB585B0C470FA1\
+F74561C1CDF939C7E77CEC8A49F5667B08A6DE363D36B93FD2F719DDC27112DDF10DBA73CFB8\
+86834510E833A45C8835EBC19904D911FCFB10112D0E6E4F636DF88D9FE028E79F5A0818CA52\
+0AB3E9D4E049BF574B8B2F1C196E8A69137B497E11F3EFEFB750315254FB218411F5A7604FB6\
+BE3F2FC63F1ED170A1C53AF8273CAC3780C23974C98BAC1902754A672ACD09FDFBA2DD1B72B3\
+01A80B7F1EF004A08DA13AFF02F4AA8DF711480925C322D43EC25242D0FDD4420E200DF964F6\
+CCB4CE2FA5CD9071E2DA17B6A06492D99AB4E24810BF4132C1B73AE746D3864AF44D88B08AC3\
+CAE02E1DC44BA8AF450537B7C2642B7BD4731E14D3927729A65411851B76823324457A3A16DD\
+EC2D3B304E5F8CF9823E5A062439B5953F6ED9A7EF0FAF93F629FED8E71D024521C6AA922B03\
+C4267B964C65E83D9C2CF16067ED6EEAE9EFD3A3843085597A683CD80E91858DCF5C04AF5E1A\
+D937C4B4DB4EF30B495E873D0A92636AC2EF4F6A1F9A26A99620E6803C1BA230C50D339039D4\
+DF0E3C718AF32F24D80EFB446C160F8F5D3030172F924B8CC3996D454BDA5E958498823D86AE\
+9E55292D33E6E7ECC0CBEA239ABD10334AB9A3FB1763AE997F5F4764637C7D6137531E4D8EAD\
+4D05C39D825CFC3FB16FA17A760C9BEB4516563AD0C40AC607FB616E9845DF833B989207579F\
+5A32A29FB54E6D5D7FFB90FBEF64128957BEDEBE936293268BCE7FE0E8C455218B1DB7EF:\
+257F
+
+8554C25CEA8F0E19357FABADD66C519E97622F36CBE09828CB271DA5EE14DD3451CC8FD25421\
+45EAF13D7AD49A42B7092ABABF1C8796CE4B3C4A16BDA80FEC5F69049F2B94550283E5626B04\
+43F32FEDAA5C5BED3AD64E8D6C1DCD3C7C2C5CD3B38907653CED0D7E6BBB25686654DC0167C0\
+B0994C274F645F2AB1947C56CC64AE8E920C24690ECC1AC67DC4B95E69F321232E71A6B859FF\
+EE32657FAFE512B4BD33303C0838EF3E275562E09373A7E431E552489DE6284B58299058993A\
+44509F2E10B07B3DFA7B20103FB9497E6BFA6353C930A0F9D565A12F241697637E7ED81D1BD5\
+E609787F79A0C95C1B18422A42D7690DE2288F5E5C8E0AA8BEB5B3A68ED358E3196CA20AF163\
+C20316B8E64216581DDBE553EF330A717DABBE0AD1209B9A541A7BDBE70A22D77995BE26D99E\
+3903C0E251CBC7990AD08489431C8BD80AB62D63179EC93E5EDA73E46B22B4D518B8765C2C0B\
+3736817A9EA60C86A86A1A69BB7C3E2D05AE0AE4313B2C766DEA92481C7A7786EA82EDA96EA5\
+0964765A171D552037415A3D7F20B19104C7565265BCF660B4685B66707EB778E39B5B34D551\
+729CB39C8C4AD50E68FE2B988EA8F770749A336F79189D6B157E9F64D17BFE477F7ED5997918\
+C18E0CAFB2C7652CE554FAE70C52CD7A7319F768AC001C7C2D60C567D9D9A6501640544004A3\
+8243B4EFC37425A46ABA7BA98BDBC2CD7F106F69485819DA79FB483C2B50FFAF67EE27A4D0C1\
+84B20E98D9CD859FF2A336C1544745EF4EFD79A9906BC3B9D5B5E358BA1FDE3101D0B27E9F02\
+51EBE26EAE239EE8393E1DFF8947E6036FE4293253D223E89E7F6B439E1FA8C67A9440DCF5C4\
+0BD7744275E66EEC2175706046F67A55B8580A8D902F342E24A76509077AB3C2272AC4874E52\
+E15644A35A78D57C650692B297EBB6C9DA215357567EFDD6D2A64634C2F0FBDC39BFB6EF1707\
+9805A0D9C2506DCCF9C858441E2478B49030F0A741EE8303D3EDA6FE0D82EDFD38D5F66AEC10\
+AAB25AC72E39A46E0EDDA0AAFBA16F9CCDE84316195655569EAF463D2E046E3E9A2D56E78E8D\
+495BA69BF997BD972BB724901CCDDBA065491D7595211995C6F44644C63E275FE1EE3F2A6C61\
+BDB05E7223CAF113EBD060D9740344BF8FD878E820331427DB67DDF921DCD27C08C5B176B864\
+07578907ECD6A561AA6CC206CA6CE5F8BBCDB7CE3797D0111BC52DD1FF4082D6AF0D65001C9A\
+13F42F4F66CCC9079FCE07AE288EBA8735B7D983D8E3038B4A774DDA3A162AC943D27F8BB41C\
+90E14422E69E2DDD726819F613F08B1D2D7DC25634035B5BAF6CC0AAD642160DFDBF3B3862EC\
+AA88493F9153A5371469212FE7A223FF11A85C08D4D8834F2D3744F6975D06C9522505B0D107\
+44FA476690E9885D995777C6DCD79A0F49FDBB44ED03936A0F2629E4BD4483F94CA76DBC:\
+4BB0E901B9BE38A39A8E116C77C05704C8293F44D394ADB23B0E87AE8C66D9A9BDFD51BD5CFD\
+6ED04FF5366723074327E923BB63E200698184BBC24A47DEAEA92CFE39A9AC48F22A1E0B76A3\
+5B9729F8A14AC41B430FD4373B2C4D2AAA7560E3D60FF4EB63D1AE440C8271E3339C716B592F\
+1857BD63D9951FC38D334F75987FA381DDDD324D62DC9D1564EA417BEAE82B0F8D5D138419BE\
+02E69FCED4DAD1D4991DF70B701896E180ABFACCBD4CFC07E07D23625371EE0199D6C7BF146E\
+2987CFCE31EFEF4D6305682DE92015362FB1926822C672920359932AEA49C9969CD958742BF7\
+B436F03734B3E0B899A513D3B6DAC6A715633BFA7B30DB6988EA2E14EDE3095267BB5407CF7C\
+8B693A06227E990B256A3CF18D64FE3D2EA8D4D168B0DE71876F3A77F3563739C5A0754823B9\
+7BEB1B16B32804DF7623888D57E6877B2040E68BD1328A69A3F6F9F3796EB8300D53C68F8189\
+D93A11EDBE4608175C3D2522CB0CA8BEF0D0FB752EC50CCC7ED709EE5CE90CF44F788DB78613\
+692ACE14A617973914D9916D4FFDAA07D50673A5F0A60AC73031D3A96E89320C7A81A42D3246\
+D95099219F85FE5BA00631D833DCFDA19A029A7670F848CF16BBD271E64C8BD741DEEF9871AA\
+A68B10C08A64A3BFE2F99D7D04CB86A1F0CABE561654553131B3F903D420F2CE748068A81AA8\
+33609693C633F04BC1DF7BC391B2DF083B84CC9D4E14F3803E704720D7C884E5026861033582\
+D0E854D61C766274FCFB8C8ED428C5B9F2C8FAE0111611EE0A0278B72DC305033F51545744AF\
+98C6DC2F721CC42F71531D3FC8C0E003B6C9E65BA3588C42669BA65D3662160A8A6CD0B652F8\
+7FBEBA6F4FBD0499AA4D8B06B9B67F4F0144CFD8AB517C86B68F2D648E161029EED96979C24F\
+0C64D232D4E162C5EC93E2F5C8483920DE7FF0B23CE3FCB6E8675435D579031B36A10B08A4AA\
+F16B563DDC94C8C5C922D7AD8C72FB15070E00D1B9AA09C8F693CD179E8C3CDAAC20FE4CEC4F\
+14DE10478C419359A8543AAE601DF2C1205BE051A1BBF572E257DB5EF8C8659B6BA93683C76A\
+6979BCE9AD27C3DC4BDAC4122EC8FF7FE53FC651EE4B68AD38502157027F7741B30F013F0DF3\
+D2BB14764355FD6CFCFC855B838A18F06896817E9E1252E1F466408FE09184601DCF3B0EA47C\
+62AF09B84F890E5F94A8A6F94614E9BFC5A6EDFD2E7F2869ECEB8F03BDA424E2FCEB9FBD676A\
+3C051690E555DCEA6C124681D1255C2E0661B1023C15BF071B3EE3A8E8E6DA8DE8AEC78EC3CF\
+9C7A1C9EB23B8B706FD5E8703EA10A1F6FB29A0D42139D1D6EBD7EB145EA565ECE19A4485474\
+8908BDA769E9634DE30E3F06F3216D121A92323CA73374371012BE9BE82B158BCF9B634192A6\
+D58538C3208DC6DEC7A9BFA83905A69E9D6F78E2885499885B5FD8E88305BBCD2192216F:\
+D746FC
+
+72DA33B988192326A043A7B70419ABD6B89BF899D19E0AF5C1ABF6B3A2842492BA6D4F254E7B\
+ACCD74646BD6560FC87AD5E59B77750437045BDF17CAEFCEF0B07983BFC470A9F034BEC6218A\
+012EE7E6109E83849B5890833B5D2EC79A5D3570C7AF5DC8ECA37F4475A352FEEF4BD0C33F31\
+958D2E99113467D30CBCB9F6DABFA01D3728FDCB13B6ABC5DA6C7F470DCB2055DBAA0E779893\
+99AC345739674F4F4AB66C4D7B2D9F04DA0808848108DDCF1C6D70190A66FDF84D5B5F19FFFB\
+0CB28D47731EADBF183740E0E06CB33CBA47ADE2781EEE9A7B13335F4A7C629B2A1E808D92AE\
+ECBDB969659E67F93FE25E6A86EA9D471E5361FA961C35768AD89D8DA6AB16B9C1C4690C8AF2\
+3798AC217DCD23F77DA4F531CA9C25FD73C6EEDC174AC61B1D38BAAB4238AAF93A336DDA9C21\
+981EB80957059FFFA939D1A5FD2F6FA6131880E59C5CCB6A6FB73B077172AE85E6EB0700A3BA\
+09C9DBB0699628B24C8A50D57C5C6C8C9CFC6ED3B8FC8213BFB0D2277BE162E390DA561A1787\
+B6029A6908718A180046CC777087E271859C190C1B6F517EAE660FF7CB950BFC3B8E572BAADB\
+121B6E68077632AD28D27866D7A76F854808C68E69F3620E079A99839CAC76E31F259CCB1A9C\
+C04C05E2E74AB9323C619C0EC6E5744EBC1A22F951544D5B4AEC306D8921BF6FAD4E749A3FE2\
+5B7B8F206B558F14BFEDA34D29793AC53A4ACB9E519C05D0EEB9C22F785ADCA395EB0E7C2F6D\
+19D1C10FEC2A3EBA50A47990B64C108294AE6B26A7E3805E5599596DB55D2D820BFC27DDFAAE\
+C08970144DEACCA2544CB758EAAEA728B10ADC70686A07F4AE77B14F2D58BE107160D738FD53\
+A5BA74A1ACCFC1A7E90B888F397C4807BD347BA9739F2EA7421016EE9520E217CC7390A2C686\
+55F7645D1B8B44FA61AADC92FCA2DFAD3954E41DB3A15E1C7E529A32D6ABB68A636BE5538460\
+3CB605F6A42F8B4FFBE795F8F644588A27A7C3C406179C8E4128585D2980D51DDB831D3BE643\
+D180CA129C183337E08E3257201D77D56F84A8DB60582DE8941F70618DADA81C33AAEB0D9D0F\
+2A3C5E60A8042C329668EFAF8E50F72C806E2F17B785B355F2CDAB7E5FC75F86BE10ED77C982\
+34CE7881311A9639CFE5BE4373348922B0B4F368C376B8A20E04E154FB6F2AD6954A7B8FED2D\
+B2FFC94EFDDEB0BDE09EA6D64BAE5D670F4DD245E253F99341C1F80117598F9A5C404AAE1EF5\
+C8B225326A5F1E4B37315A328D635FFA212BAD1495AB583D1286439024C6C0C9BCA7AEBD4607\
+CA2AB18069B216E289812B847B33EF52F0ADE59A5A44AC63174DAA82CE6C1B80BC8440A814C1\
+8E5811FF086188C4EFEFB2692BD3C6B7B4A6438C61B29093E62666F5B760354DA1927D97E0E8\
+07D6885F44FEFC453A6397BAAE5A9F8BA53E8FE56895831D6B1A2DA44DFD3046881BCCEF:\
+E2B67D05FAE6CECFECDE72E33A41696FCDB48CC035033C1F53A8F6B4C1BA0824D7D553197FBC\
+22859B2B32BF2A636DE8F1999D54CB973CFF9D633D39F8F7C32E4D6248CECEA4222ABC898FEB\
+6764D4FD192758D14CB0EF7881C50E1FA07C0705AC4533B6536EB7FF6A430D8CD4A145E15679\
+6B5D280C5933F69E813E642ABD145E43A03CC1ABD26FD5F0C6430C5656998BCC126D522D5656\
+2DA04C6AE0B19293CB11E2A06765C64C18B20E5BBAED65E46807C0513E6BA36E3231A28B426D\
+62720278CC4986E1CF3F71C42D4F1CD45D7477475E7919E353FB498CF32BD81CFA4084BE21D8\
+698F2040BA110A32DAF535E1B1F4D6FD3A7278E55EB5314CD460B39704FFB019F1004176451F\
+029D473458CE705E62F2A461DC2EAE9DBA2BBEE77ABB320C6FAF2FCC5CE8DAEF599E3D379155\
+45332EF305D8386F34C5D9A2DCE8FCDA1A3517821B761856D777E311F918761C873DFF638D80\
+6967DFA28D5213A2C17DBFA0BAB947B7FDEEB4F6648F2F415FF09947E6E3EC01EAA96AE03C6D\
+07BEA5FF5599A47E23389A2D00577175FDA3620B4A3AC3C22092E8829CC12814976E38A5412D\
+8C8795C3EE89B76C8678FA6273C06F12AB9121BDA619948E1F2EB6D6C46844642C532E03E449\
+4CD7D89E7479F2B75CF3D1B072FAEC4E293B50E45DDE6936485EDFD091999899AB44059E192A\
+B81F6661FF98C5DA37C545980721C6741FD0CD84F65AD04DAA49CE4F494BE674CCE1212FB868\
+F22E81097E1B3D16C9EB43035979DE7FF557A5540A36E42A0BE4940280D3837C46115AF90F88\
+73AC0F26FC265DC0250FA0DC894B16CB77E0A5C80F4E86EF503DB8A42DCD9F800AB108EFB8CA\
+C4C3CB2683D73C1B4EEDBC3F80547C167F7B72DD0AED7E5980174124812AA97FF26F1AB6242A\
+387F8C5C921A93BBF6B132D20C3797035A131408561E5E2C51D7629DB47684D76672A5B508E9\
+A59AAB30C2E2E207689DB69F8F3D8F79A2142A8CDFD8D251DA941FE8BAFA507E9E8A7C69D6D1\
+6A272594CF0218052B981C0080676DD245F419276E9E07D8983F9688FC8CD9AB9B16756CABD2\
+1DD320A6A435EF40C4C88CCE50A98D79FC0EA58BDB4F11431AF00D4921B0A49995A9CAD78CB2\
+28A8274B7272E3F82671258418592D03008715A1216DF499197946B661293729DFAFA6239482\
+EBEC503B7836E4B7B20E47C2FE6BF62C845B9227069742B654056A4F31A0B4937F1056083921\
+25E63E82F9045A54799E4DE18D8010AB5E3E3B9FF008D494DFB5A2041A6A5B89CE72F68F777A\
+8DA398ED66ED6637AD105871A1BCD7679F55AF3989CD3603836E9636C8A1ABEF86D4AD3F6AFE\
+CB1D6417C7030CA8AC09E3C15E9C275477097D77FD32509B7643C5B96DD9F9213DE07A083B5A\
+8E5FDCBF4A41890D4D1B854604BBEFAB06B598D3193E57570FD137372DFBF983819CE35A:\
+48B842FA
+
+F3F1796F6C00243B96CF802443D16F213BE4D527551102892AA6BFED3FE95B1A4B3E0E3C52B1\
+D32595B83D7575379B34C36F4ACA0CF3D9CCBA91AC0DF206D9A98B39B48EC8F168FEE924E14C\
+D9DB1700333EE88992667774D31B42FCCA673A3C1A0F72473FACF463578619C8828604F056EC\
+6948DD3B6A12F7C92AF902F3F6C8DD2309D9B1DE9A2B83AAA8F3DC15B5D2B1ADD86077CEF344\
+6538F7CFD4469A031F91717A87C23473B8B6D2961484D675C0AA938207C326C1A98691809228\
+64D9E5B57361CF9004B613EBB2F75CAE2CA11D6EDE4944F54CD8CFDDA923BE42908EE94E8AF6\
+64CB9E4CCC86B31605C0FBEA52DCD22DD1827BB361F13C8558AA6087A420C3E2D6D7A67CD1DA\
+849456EF7CBF827BF856FC397B8F921819F6FACF26240D89D7B9365589240CA03C30B2FE3D29\
+B2E5889C683D6EFFF09F90385AA6B518AD5C0F581788D9D6F0B20FF8D2C05F16BC766C107753\
+07FD80FF2DEDBC64202527149547D784C7A97FF8AAF03820E8D3CE6D94FE8F4F09961BAB6ECE\
+873A099F49511A4F1AA527A0294F9D4C2C7CC13B66BFF754CA60EF76D0678AB6C247027C5658\
+506EA706784543083F83E6F11B3310C0375BA203A857C87F846727DCED355AE64773262F8632\
+58C77B8A3A8466283B5702C45FF6BEC024DF5E0D72BA36D81482A0B4E15EF0FE18609F925B94\
+BD8D42A9CED97E32DE17D90B8ACC07233F0A684FB85EEA4EB25A5F9F29B3B8897C8E735114BB\
+E4162869C1CC53908894A392F15B49CB1684A03822D0E02F1C89AF37BD4A22451145A97D28DB\
+88E3E85E9D17AC0BFAA8575676F4E132B20CC91C946FC973DB2B2E8EA35EF7B8CD1AE83951CD\
+62AE825F5209B1705A6FF0DBEF9D3D350426E5849A26CF767E44E9527D9DB39C7E19B79876CF\
+B38B26FBF3F3017671ED423FE20DF87A39BBA1463E894FC1B713D01E79488B4B751856D8AE26\
+75B136FCADFC0251C30FC472302368419452CE227BE74A3E167A76BF8B9B225A57781CAAF79E\
+FB924E4A050D1FCD723550205D04C17E4C865302F8C09CA68903D271C4A3AB420255B69A7C78\
+79C7411D6F2BFBC1E3EC555DB70D8536ABBC9CA80E620ADFCC00C088A910E686161DC9D6E383\
+C74283A0348D7D3C49EF028A549A5D9849CCED60064C25ABDBDAD3578013B4CFC4939A30FE1F\
+5D043E119CE8BA1B8CC67F23EEBF06C08DDB254693C3F66DA3E45739D284E2D797C3FDBD3517\
+830674EBBCD92E1C87BDDFF9C477C061BE575866AD1D6D81C5CDE36F32204A6ADC96CFB0019E\
+2A74742FA541BE8FB5F6A73928E5AB1A21489F8E385391261392A04241140D7EE97C57391B85\
+7C6D8599DA250270A2C07F3F05D64495F2E4FDFE7336022443343E7BFA9FC10077B2357406B9\
+68208775A2B0E07F657153B4AB3206EA83984EE3A5D03DAF44BF30AFF2F181BD2A1F02B4:\
+12E5CF2EEF42624BC53D8A0FEA029E604CC6D20FA927ABC186E00771A634C5002012D6AADD89\
+C5192C56B8E3E4B54DCF041056188A5671CCE981D4A02137DF7F40533A760D200648F24D5C18\
+BB08E3A694730EF165A1AAD4A117B8D800D0B8ED9F6AAC1D9850A0E12CE815796D5220376226\
+A5F29232810EE969E537459546110B9B747C1F0E441E59682216F27192E69C7034EDA3FD3BF7\
+B9F4D2EE0688A5FA20607FE37C5BE1051F5AC439903794F7C4F34C97E88CA61FFB46D948E5C7\
+8937DD683F5EFF633AD94015B51B9244C0B83313CCE16FECE79FD5BD26DCBAFC05E1A34DF5AF\
+398E09599E9CE94158D2FEA6F0E86C7B054DAEB531A1E836E05B1CCCF2E9F8AF048C94CA1EBA\
+E9FE7503F367FAA363DF74AA9E7E1C3D2A22E0C342DCA5A5266387F86A02A8F5B848D56B0F2A\
+5C119FD930B8408FBC801914295B0FB7797C0F214F8942AF336AEA5F24BEEB021994EF75A15C\
+29CE5B3FAD12886F934746CFD8E12CA0EDADEB86F89396D17FA0D7C992F24AD06A5045463345\
+C5613DB25967D87B9A72CBFF8E2B008DE3004F45CB6028EFD0AFF07602AC624E11A2B4F908FB\
+8B28605AD0B27A2F4F96DA80E5A4AD1247EC6F5F0F9702BA60845E5AD8E15F12F2A74F8E2D18\
+568AAD6753C2C0A91D6823C412A48053C877C6B21240941F14AB921911424F4DBADE8B02F20A\
+C65E68170F9FB64CDCA5288059C08D39BCEB78606693D17498D892E0C058AFD44A7269A8B2F0\
+A3C036A4B53B2218CD54B0DB5E2CE2F59B923124C304273F39365973151AC85244B054980588\
+CE632026B05EE656357D1D7DCCAC80256DC59CAE11FFE5C9C03742D192963802BF27351DA535\
+B087296A85658481054FE5E04CD072A5F77770C391742CCE3DF8FA3ED45CB29375F7F7D25A60\
+35264BC677CC116F27C58A61696C8FF4BB117C9F452A441E543FB95E8BB857E071EA4061118E\
+137C67E90F8F82134E477F1266BCA6C998D9EC25EECB1FDB19F0B11B3D58D2594DBB943D019D\
+4174ECB4A18D42681CE823CE33CD803CC68A00A89E9DA7D8D3441D5D6BCA1CD8B915E0B814B2\
+0C0D5526E67B0ECFAE0B318BC63318846620E9EEED3D981FEB6E2CC2A9AD1E115E1E29C1377B\
+8A173B166C579C7DF0713C88A8E75EE73149C2DD187EC6165E30B92F90C62F963531CA593602\
+DA6A2DCFC2524CCE80BC764AE1B24EA2D903EE25B7DDD545AE3D3FDBDB97987DDBA315788542\
+6EB2BE46612F9362BDD0E65BAC163B0BDDC1FC171BC91D3191243FE0851BC36E95F928342879\
+1C122BAC07B2F6BFE9362139854CD114B249F5F6413121F1D7F2A63318DA26F8E9717E1AB99F\
+D7F894610375B71A04A8E066140CDC42349D5B25128D401C784F2A5DAA7E6B6B331C8D2221A4\
+0EAD0357E72AC5346DA1712FC85D42C2E1BEB0569FC6FC31641D9785E1ACA85A67B69077:\
+B2771B8F57
+
+190D0B444816CFE9A58BD72DF9C8257F5036A75386F85F20344E8094CC6A1445E7475CE75D3A\
+3F645084D9481382CD8F33AE9957BB977A49FAEBAE48F889ABDFF73C8CE67D3BDB99D6C7F764\
+1362A75D7BD1FDB2522E1CDD246F044E482FF989834C7C4CA7CFAB83F75675DF9EC88AE7FA04\
+FF16D1415DAF85B119DFA9A740A745FA632BF3662671ED20198CCC61549F63AD75B04C313091\
+F301CE2F9E9E7323677FC926ABF881E1EB1ED92EA0D4E6C9B2E2B74DE021CA73C651E93758FA\
+036CADB304CDCC3E685F7DB07CB275BFEE14B005A21899D3FBC79EE80BEDEB579F163C60FC52\
+5A231FC33650FCE48F798B6915D0D85B7551E93D99B8E053CCC2F81A808F73D2A5E7B184739E\
+FFE57F33536107457740FC3483E28CECC770D083BFB935DA436D19FC65DECF57C94896ACAC4D\
+C0C53A41B9B270853B10AE3D31EB205086D4AA8AC6E488BD82B39DF844B782591CF7943D78DE\
+06E189AAC9EAA1ADE0811D5CE37805FA53C76B2D8A1D4CA7E8D9C700F77300DFFC17818EE1F3\
+675AF79BF797DB6ECF3E60F34C0629A52D0F5C9389155EED7D4D9EE397BA77753C584900CCAA\
+F3C4EE0823644DAFBCB0DFBCE1E1516EE62128EDAC32D2B1463E4CFC98F0268AE4C2BFB12C45\
+0FFBE84D3601A0F62C30039628F66B779DA3984784122784CA667277FA504A1FE731DFB70479\
+0B7265C6EFFB40A3515D1E370BC879C74E77F7765E7F473E3E44397026AEA2F6B0E0C23089D4\
+9D7E6E218EBA7A1FD841A90301EB4C3782A6AC5C52DF861C6F495F6CEFDC1A597956F32170DB\
+C01CDD5F431ABE5229440EC56265490869F9E0B82D7847A40EB6E18CFDEC0483DA195A61EE45\
+BBD9B3098DC2EDFB19590EAC0225D10E2F4654C7EADD240E535785BDBC0A4FBE5BCE491AB773\
+B717516E369A95B7135E77EE18BE2387BCF450E18FB205A46CB2041B846269328A7C161D6A70\
+BF0C84BE33542045F837C31FDF12495444009DA082C5B1ACAAE10445B5CFC29294A19F81A749\
+2E05C04BBC6A7D47CE681E7978025ECA19B01B1D7A7D8F03CEDC9E651D9A0F0D2D3CEA75C0A8\
+00D88E79D550AA1A306839F080C7D9EBE010B6523141D9FD06B5AB40099B37B31DC592CF967F\
+C055027FC93BF4631454F5E0B4940EB2AC81BBFB3BF088CC00C84E5733F5B7620FAECFCCDF23\
+6DC9E25D2A07EBE9619438CA8EA09B03BDE999AF5F163B2048993418A47EB3D3B87CD96D5C5E\
+94F169E05BF998022D41C1C494D0538A49B47DB7BA9D4339079872421895941AD12946D74BCB\
+FD741DA2E18A268803FFFBABBCE8FF4DF0563ABBC4AB0F4C426561AC10CEFD47D1369439DB50\
+33EBBB048397BE3595E79A11420153FA157371388FFEF1D1525C4F5DB8247E048C8292ADBF45\
+511CFE147B2B374EA9D0D776F66C1312E13FEED497723B1EE445778EAF1B7FC0F419DA1F:\
+8F6EA7B4AF404A493EC11A2E3869D46B71CFC47E26537804E0CE258B6EE6A85164C35C547DA7\
+80653AE8D290CB34F3FA4E17528E5938E237EDCCAB9385EF5501BB0DB7AEDE91A32AEB7BE0D3\
+6477AEA80FE7D0714CC8056B8651394C1AC88A230721AC8A3415908A321B79003F42DC783453\
+898A47D5E3FD0A24F839D5CEEF4A9BB51C1DA54EF0481297B5293278985275723D2395C7BF28\
+A7F78618CF2E841AED31FD98C7DEDC3C821B92CC731714054B1A51FEA829470B32D83B63F087\
+686BBFE3E3B56FD6332695FFB8C7F24B243FED3E314EDDA8B3CC5E2D0F6B968092A4CB44E52F\
+AAF9A5D37866EBAC3358AAA4A1F725391D226D30D7561A8F88894416F0B055FCADCC55F19FC5\
+29D748828F2E3BF78CDAE9AD826067D266E4ADD86AB680F3DC5E8AFCDCFFFA1971B9A1B9A21E\
+0DEA1F3339F54D19973D75C812DCE634B792932B99724B1750FF95759EBF9B33DC92DBB3CC16\
+81E56F9B1AC1CC91E863735A96C9709166A5835B81862E0514D557F1748F3EC77B6A35204D68\
+7028F9597E35BC28AE8DC60029945AA216C2979BB9D87EA6CDC49CB43F48B5181C2CB9102005\
+5D7A33513D8C8F34A27CA058AE98D03BEC7AB1806010743C55F7351C9B6C552B8936F5F092DA\
+FFD9DA4B836EFC280097895A9C655E5CDD3BB1126F92528A94C1E8BE5B65F188FBF7D198F480\
+C26713C9D881FB760383039FB926AB578EF5EF7746CD531B9D8EEC55325C4CEC543C832A781E\
+AE64E06604A6342BF886B038DC672305925D72C8B8CFFF9DD99311A80F3BFBF6F5AA94059B30\
+F7ED70F65C022E9C148C338FECE35AD3147A0AFBC3034C9C4D876D0FF1CEC97C35AC3E5A9D7F\
+CB02ECC02D8F01550E961B283765EA7BEED4C3194CD054E14E2127280D117DDE0710D706FD65\
+1761FDB2AD33979CA5E44344BD615B1AD45E9ACB55F8562D18D7D15CEE6AD07EF245F7B07A23\
+E7F20C0E25D4C274A54CC030A6D21A12BA65F7D530D897435AF9162A609F91E7EF9F923BB5B9\
+A075DCCFFA99F075EC96155549027950F3DDF6B35D4E053B9E255EF4EB8B9A1DE30EE7BD516D\
+24D607ADF658BBD7DBD1F58FBA34C0A6FD81AACE142ECADF63FD763A03CA13FA4032CD10CEFD\
+D759AA1E34484625CAAC69939E796C1E8E4817E0EC17E8D3C456283C162183E6796EAB5D4613\
+D3ED080808DAAA70DA3A945CC0ABECA5B44649F234F0207C3811A9E4A0CA173096CAEEBF3DE7\
+A2136B5F48516DFB4051D9DC98D90C3A011310339947F1A40493FDAD6098B17AF61AAA9C610E\
+21131B97A33F94D8A11F7A33FFBAB4F85973A2CEFFAD0E7FC555FE5816D67FEB78E696FF34F9\
+EB76EADD09224EDAF9FF2B0C44E8346419D1100C223AF42976B031C10AD1A57D44A0A042459E\
+88D4265DA5A3017C31209411E67F468A5912457E8670D96BE6D460741866F5DE24BD45DB:\
+AADAD8921C1E
+
+239CF518A7A49CB68A264F57C1B9776D26D0E21264BBB25C552FA15915FCE66C2006D8AE6B5F\
+CF9F0D4F780C94925EDF2CF9193C2F0857C050E522F72D873EB3698CE789FFCBC7268EDE838C\
+C0277C6CF4135522E1B32BAF00DA4A63492D733222D451A3335892F83C560BB0C074157659BF\
+280198698261631794BBA5440FC2E624BD6CF0F9A3C014D3046E891D06AAD67C123D52373003\
+C9E9FF370B8D0F6F18E5D425B71F4F90110E3B9683B6A1162A0571B695C6D2C4269B1114DEDC\
+B345AD5C7687F889835D374683EE01CD3B290F70A66C3731981573A4B7FF0729E42801E94E29\
+BA0D3CFF7D5CCD6AEBA27A44C84B6F0A28F27ADD6277AE5A2ABF9738A9AE473DE4937093AB72\
+646B67839752E048C00C2EF7607C7863CE5DD7C761258013B176494C7AC826A19ADA853A87C7\
+F10F8D148627CF69D3755C77181847C469C8721A5F92FCBBDBA729DB34AF27C7FE37FF3F28CA\
+56587E22596378664EAE0E8BC1F76DD7F4D28717A4550E7D668C143215646BCF3BD759BBF03E\
+2671A1D01C071AA8F9E45638072FDDE82DA96617953DBAF76C22DF09F0C827B3A0439F1F86E2\
+E1873F3DC854C8F1C49768153B2091941ED2361528D7BFFC3158B548F9EEC81677EA1D1A4AB4\
+B24DCB221DFB055608BDCF25FE92DA59F87965F5B5C60363518BC0392C5F1FDCC5D2AEFE282F\
+B20587D0F609594F5A1FB5A0B9DBDC3227C59EB4174D0EBF1A5BB17E52E489825CD50C604D34\
+671C0224427E0DA9E6DA00C41465FCD836895215C14CE15BC4B304E3A06FA984094A887EDED8\
+AFF731FD07DB8F5CF871B2C27586C427A8E75BA1FB9D7A422E99F48F81E013257D2F580798D0\
+400BA3EFA12720F497946478C4AF612B280F18677F39EEFD539B66574F35B7ED8A918A8B0EBA\
+8870121DB7B55F3016AD93E865319A95C83BAD41266699F2F4D8DEDE59F181F6FD4AA179FD3F\
+16A9270CE16810F99E6F2AC5F54C7598E86534BECBA5D083E6B3B9C67D9F2B83EA704803EFE9\
+148E72096DCA3C97B296B1D86950607F5D17153C9050AC6AE97FD4C9CA448BA98E671BA92264\
+E2F87B9CAF1D63506739DC62FE4FD97CF6D1105E156FC4DC1B4F034D5C3AF8C9F675EAA460A4\
+DED2C847135A64A3B1980BD4625A29912415A3A947C0B4FCC9A2B8D3DCC6F3261B89E9898A43\
+AA60B8B274F01FAC72438D5B5581A05D6CA300B06BB5805CF0E86189DCBB8A60587DB1F19043\
+6786374F6A2ECD23FF8E460782A2E4D8EA98E167FA330F336CA7E4C7F94C03DCFA55AA57B6BE\
+D032C484EAAE0501F04B018901DA071E519009E0B26542822DC3E7B9799B34AA9EB69277FEE1\
+BAC2E98E80296F6554CB3D60B6DB62811EA97BE3BEFC12F156881540509988B92F42249FB4AB\
+8F39A21232E2ECBC30907F8EC123B0D773B1C8B67A8DB0B0770DB559F6EBC63B23CF806E:\
+3D1D43BCA6010739D96D16DF036C6B04047BF3EBE1CED4DAC2490559EFF84120E194923FE454\
+DCBDFC7F2FF02B8F3E70AF354D333D826DE8C4DECC83ECA6BCA35A42E7F16C088B970205C119\
+4A21F6A5B41CA13097E93098878EC5FB52D67CBCB36E3BD6643D407C2CE10F071A7EEB44D9C8\
+3DC579DF0ED3434B65A6C5606022A134674E714D02444D5BE22ABB4DE8DA93D928B2E6A02F22\
+07197A730BAD7C43A75BE382C495890631CFD4C943BDA20DBCABDB5BD5BBA0DB6B7A2A8CC985\
+A04D4732DE32536087259B73023A0994915884AE9A14222C5A7A57F838B15091FBE3A39B39AD\
+B962B36F03F3A81D52DEB13EF79487D58AD6F9591EACD2EC7BC256126D2EE696C611AC050637\
+F88594718D6FF391A794099963C9EE7E094048F36D605165BC7DFB8DCC57B59115AFDDD2C66F\
+EB4C289A00E85BDD6B08EA290D6788022A9D52BE4E87D2F433A52AC998109584E1AB7F8D414D\
+10728C58D50F8C4407FB9701868F3957BBDF48861905F3CEFED2AA6488A03B84E37F6848642E\
+CC0193FCA1841A44DC6E6BF30BD17E1FEF02ABA77492CA5525FDE471D070C5B2A3AB0E1383D3\
+E9C7AD274C2534E17741A4628EE9731CF69449796134F523F76C0934D88F0DEC7CDC67C45F4E\
+28D056B9E46F97DA29528AC6EA55662F3ADB6B5112B04EA807B40AADB0CE0B8D1B2149381EC2\
+7DD75513FBF8B271136E1CA59D87B0EAB956C37AE0BF57E099738074740E7B10D66CB01678D2\
+488C4F1F8D9011A717F68750902BCE93D9C389F29A53568E60E5B735431050469207E8720127\
+F18E4553329404289E15B1292B8DF3FD88562B981A9202E0D92E3A83710ED49AB83BBFBF4322\
+3584DFC9C47D7B5DA45D199F81F40E94DC4FF4C5AB7A92D9D246E690E053C2BFF4307AA5C212\
+48A2D1FA5BAAD7BE81A6F07C61509FC625121184D73A0AC1630C345662EB6030C660C911FE5F\
+658181B7555EC35DA7F8FA00EBD2BFD9BC809AF4C125F1B5CA88B65FF8B93EA758489B481BB0\
+D4DE2CCC0E68381D8F91C66815FC08A0546C0BCEBF52E0D918A61A597DF46A8817D8D5265DD5\
+59FCC426A9D7486D325F6650C5A078FF1E2BC11F27E298960A9A97007F173483C83EEE55159E\
+01370868C8C5C0FC139A9BD54F46F8A9DE0B7B82B80FE08DA0D34EB531D9CC2C46BC15F9CC23\
+814B98D38A39BB2E2E6DD9C7BC98C44BF822175610F78E034C5311432161B29A7A6653DE0040\
+A99EE878E8BB9B30F004B31ED464BADCCA96596F6568B508E04D82BF5D2D836CE4FF3613C529\
+B8A25DC5B8AB96C541C74E2C9B40880979ED2D60783089275CA75610FC2868F6BD1B5880D0CE\
+FF0A8E4DDFC233111267DF38535841E42231C3AED60BC89B965DBA6E805B429F5A15FE0F54BF\
+5ECC3207156A5DD019F18699090E8BC3A6E80FE9213C2F0B59DE9AFE60F1646382F7D04D:\
+633768D40512B8
+
+24CF445438C0D1EE449DE2AD694CBD75526DCDC1D19EB4F67D679C87F5BA69FB70BB6903CCFC\
+332D4C6744F617DA3C61FDC45EA5731BE4C141030659CCD7C6A2120AF422CF31FE39806BC536\
+1172948D12D937A67E7FADA2A49F91A5EF107B1BC2C314732A64AA49198208466A873EB04F8F\
+F832BB4813384E0F9E395D51D1908C34488EE81EEF5754103907D8850FD3B013BC8B6BB1AA65\
+2683C46F7AACB7754C0AF944DDD2A94E7A4D5F8BFB4B134F2F834068096EF5DD82C198E101CC\
+7AEC73AE88F0E0E35FED59E7A53A959D8544875BCEF200135D309C27A2D74EA95F2645C3E2EE\
+82E2162057E4E47AE26AB1F3637DDE57023C4E97B83726CD47F2ABB1C6C7B880BB14F0C7FE42\
+A52550B282961BEDFCABD97B5BEAB51333E90637B29F6041A9CF0A3EC65318FC013E583A2E56\
+C89525BDB118FFAFD46BDE45CB3EF582647CCB40EBD6EF1C4EC7AAA9F79391F1A38B418D8810\
+5C24E49EA226766496EBF19983AB76C6C4EF3C9D1BC6DE59C2B975CD0E3F41BACD5E091977E7\
+C40F974FEE8919F6C0F58E126375B697BBCE04A584A64BDBC1343774D9F0146FFF543A0CF0B2\
+28C30B231693C98E7A67A8EE4294D136F64F7C150BFD06C989711AC42A35A78D96E04F98A4EA\
+2111A4FE5831E30A6EF96300F14875B217D1E94D12B41BE2D112BF81B30961BBC028BCA2B105\
+C97E841D1C7B02FB360ABB442217366F90F469A1AF64FDB5D95B9E50F85591F3CF499B440E02\
+9EC31A49CEF6EED2D7B6F15A49B6515539F9C3F5C5C4651A9B0442ED9534A863D15B035D581A\
+FC705DC598174DAD2B8E4B012AD4C4E5AB965B778B5382EF8BE6AE93108290B9905ED5A37EB8\
+5E819447A48113F61B9E004F42F3893808E2240E6355C69B007C42A33549F2AB08BD2C6A012A\
+BF27CBC4774002FFD1AEF10F971331B4413E632E020848C9E9972EB4FCFF9D7C0EF898F29931\
+3745247CA3F22A699F7D31DF7D7A908A64AECF10B9A9A7EE0ABA37910AB7C7187C4F5F028264\
+83CE39134A54D1DDFA183CB97C3A940A88159DE9F3390031219D3218B7166891171A7CE3D7F8\
+7CB701B9527280FBCDC429E285D645D01E668887F8462E2D21040928A06FA8F1F302C6CECDCC\
+7E97572AD1B46C2AF8DD02BC9701DFBC7B8D5A973A100CF332F780324BCCE3E8080EBE251573\
+FCCA30EDA25360F1618F25076289A92CA4AE2ABE59FBBDA609568EE283F747F255DB20074944\
+5022B78C0AF186AD7D8B599CF18EE9E78E84E81B8CDBEB8CFACA1886937D6262486DA8DFE9F7\
+E2C28921A09AB1C3BA7AD57BC7200AB49C12D562FFAC9F7C529A0067ADFD2FFB865B9EAC9C02\
+33C24D467C2B2267B36CD342EC88CAA672F77FF4359E1DC597FE50E82F29A2D973AB1DFBCDC8\
+68C373D4D6660FEFD160819F71A4AD464A9EC67A214562DB24472D5B278C5B2AEB3C1A79:\
+4917B75D7DD10C7DAAC6922C3807DC446A8AFFBE5B2007DFAAC632EE14AB8809D426B6C31A47\
+51F5AC0AD459AD4BEDB81E4E9A26A47A2E420D529F2D598F0D1597D21E36806386F142C00A2A\
+B18DBE21820206EFF2283082FBDF19B8CE53C324D5FAE648C1E67CF44AAA2F850E21E9A978CD\
+D5FC0F98A7F153BFB1C69A0982E357841BE6BBBDB0B994638BF7651CF0986F508BD69A21A4FA\
+1607B5054745D2EE18F2D11E115A1F7B6686C5E2E84CEC92BFE4A9525CE7573F31849B3AFD55\
+1A0A12387E3658B03730242318AAF5C8253265C116809936C0E0FC52C665F518DA04A78080EA\
+B0693240C3AD5BE4E9F08771F5D6A31B8EBC68708CD8188A44D9E22D67F9D839B27F4F91BDDF\
+7AAE3F5141A3FF4EACA4E2D6FF788E2B5B2E5F3BA296D55C62671E4F1CFDE3123C4ECDB2640E\
+CD477E0AAC5461D5A79AB67184BE38547C08ECEE1C51B45F2CF1E9B407EFF3B6A3BC14AAC5E8\
+3387CCE406B115C0EF7BB0FB7BFD563481A707434ADD742918DF8C711A7CEDCE355D34B5D08B\
+F07DF9630FBA1B712BAFBC784F3C914ADA7B28F9CE1359C951992627677A70C5171A63408A49\
+4C097A1C3AF7113AD5E2DBA66DA11876487BBF998B024AE60D270E57B89ED1C86BF0396F836A\
+B8940BAD499B20DB8F9631A7D104DC912BA1C0ED22FA0B1762011EE84183AE19F87615352C87\
+240FAABCC5F6B8D970B5A7544655B352DA64910C81E1C57B4FA410147EC16744DB0F7BDC5E91\
+8FC90CE7420EE31ACAEC353EDF5067B24BEFDA4A3C773C73876BFA2470405F44F683C6C54254\
+BF9613E2226A40DAA7A703A15C582FD8CEFA9CEC0AB2B8F28EB7C3D97E2FD44B6E6934E44997\
+4C5DF97F69E377E80BF02E81115F43A5C057D4AA68A111F9E7B5A4F87A7193C4AD026F06A85F\
+4D6C8C86B378F40F8860A246419F0B4036C6CCA20891F5AF3C804F05D32292121DE0FE7431AB\
+B29587F9E38BB3754CE18D1DA91589F4BDD28C472FF4FF6010391EFE83834A2E61AD7059CA60\
+241DDDE5412C67BBED50AEA0789911BCD56EF0612DD00F82C3EDF4E39151B9CE5EB12D4983F4\
+1EF9D756311083AD080A64CBA8518855A2E7BB50B2662FDA413469F7B906F6E7E72FE778A95D\
+3689553F7C7AF367E47BB47A7C052C3506D976FEF9F3F3389C456F84ACFE21A28CD3EF275CFF\
+A495E1577DA1B95E867D0050B27CEE11F3332E66E04586974E815B13C34E0704EC151EE0A9C5\
+85D7F6259C6241E7D50A78DFB83E6D45C0F988DF270E65175FA688741F0800E106C14068FE70\
+F03E3989B6AABBAAF4929B5DBB080BB559D1153735E28FAD7F32699382CC8AE5BB8F72AC5392\
+EEC4F92FEC0CFCCE3CF36F0AADB781D0E7CCBB43977BE203BD4A92336C4ADB4DD28770D39447\
+06E93360B54965DD846F4E17A96D301DC7DFF7073644F4C630B3924377E43BFBBFFFBD8B:\
+60B01F1603339963
+
+C9C8A2527DED20D6CBEC16939C7012335A7E0BFC8D23D7CB7A819E63FB3FC39175D2F1964557\
+4D9DEFA9DD9096A00CBF062AB5A30F99CC110C5F67BBA32526C96B0A62DAA9A38BCE99F67DF7\
+3CF4C424C4EF673EA3B1EB32CFC0C44254566A74A9EA8610FF9FBF1BC8957E54E91A169AA98F\
+CBD119B24E3EC19E0E6E23FE9288D02A230BADA7A77391A691021F0565AFB0ED5BAAD85697B6\
+8A42BB71C1EC0ECC99B227BFF334F2F218922B56BC6BA15CE9EEFA0B3536465CB7D81AF4CDFC\
+59811C99B499A38A8CF945D9A83E1A15C4085AB27B2C413031CB54D818382C626FCB4996D738\
+CCC697A33A8ECDAD86B1082CB97B38DD8FE47188FD9D9D773A8F72D5EA74ABD533AF7C2300A8\
+F5C881277F274734D14279A08D90FAEBB4D6AED98C94299DD411EC1412CF34004DD2E7BF812A\
+8073E586800E0DFD62159F754FD01C3D89756DFC50D468D1647A4C77D0151727ECAF60257851\
+C06008D3A0BA6B74BA815456A789C3965102F5D5F1277B873792CCB0E40B44B373DBD2FFCAC9\
+BD674256BE1DFEDC78D7909FB375B607934921F3851C90BF8B82DCDDD91C42810143807C62DF\
+EE6183E59701AE53EC4D0347B127C0D609EF4D951FACA3667D29FE914AA449C941682D7A17D2\
+42B4A333DC970CDFD931D35288EA7076A7D4054AC233A6AC17E612FE32570A9ECAB968DB5B39\
+964E6E301E63B815F13DCB99793312C6D1AB998A1E87D6ADE96B497931FCC0FCD3D0ECF79C23\
+D44BE879ACAF1206856A4F12B948548BCDABB07664199E1291ED4B2C6CB0895FA7DA30486F26\
+C5C7BACF8C5A2ECD9EA43DA809067E1EF29F92A0DDCBB495AE07CF77A0D3E3973848CEEDE377\
+4BDFA19F802313665A64E7B9291B2153080F7BBD28E727624D5DB27561FB8CC4D45BB66F9A16\
+20BE69A759265CC089DCEA331508E495F770433966582058337C0D8CEBDDA660DC74E9FF1791\
+06E0831F9BAEA68839D98CFD2C2507F85942E7E0178581BC5185440C6E8470AE31794F422823\
+F80B4A424866918F7146235AEB6D69DAA7718A18EACCFCB05A6BD6CC8B656CB03FE0D8FF5AAF\
+936417827FD51D811E1182E4B726E0AAC3252FECE247CF120A0985D8FAC1A9574FC8882A5830\
+32BD4778997825D84A96CF7C939544BB358928D2BB64D695B6F5B002889505B3D8B98FFFCE5A\
+48F9A05E05461C462E8B30E566B95CABECA00ABE7385B65B5B9749DF238EFF814F5F0F0C378A\
+366179CAD80153A9F5172BEA4EE42CA2963778D70D4953907935BCC09C899EE3D8FD5EAD0922\
+F71576442A760522C4D0118C9AFB867C338131EA0ECE114AC44DCE202D4D998D585A9E37987F\
+0057556B526D39A472D66425580AE3AE64FD24B663B1B56C7EB14F543E3611BE367D31167B99\
+037AFB25A049E80DE1B4CDF8EC69CA049BA9B51101369938995D2A8F82244FC4E8D92A71:\
+DCC0C301B6C08825CEFA3555DEC86A5BBB7B86B015699C2CB7586E7D5B27B85237D0993B9E67\
+E77BD06C357F274781C52AE5F0AC9AFE42E8343E0CE46B77C639C18A1859A007F7B6C5F8F90B\
+13D88B7C041383FF4E6D5457AC473370331073684F248B998C0ACF1F5EC1B32B749C012E68F3\
+CB8F35368171AA4735A3B7DD988205E9662520D0916A425628F48A4A1AF94369835C2E042512\
+89F1550C7AA99AEE184152A86E00D121FA5026763DD8B106BF9ECAC68366362464A58335386D\
+E0AC155E344B5C687B3CBE126E18F4A237A20F8041831289D79F12D2F53CD1EF0163614BC2E8\
+2DFCC2714C02280113EF1908FD40D3763ACC6AEC03128CBD3469E152E81C2252DB94A972B189\
+1FD62D774AF979EE53BBFF7A4B6EFD30B28DA1FD5B8618CB6CE82B3D408CB165FA55FB8C2A55\
+3C3EBC448426F3691ECD20EE48F9F06607A4F10A16C2E9A186C1AADDD35908A34620C3AB189B\
+F8C666B9BBA5A9787D751550196569E7B5231DEBD02283B5B6EFF002FF33941E755731A1E2ED\
+27EDB322284716960E0E421F6C00D96E872474C6C18F6ADF6DB307549FE6FA29CEE34EBEAA1A\
+3B5EC7927CCCD5ED29FF0AFE7478F78D461FE000623775A010F9319E22D0417E9014CFD944B5\
+165E0A3A71758E7C15E4C64F26F455862B6A806ABCD8D542FC07358BDEDB48E06E07942BC335\
+92D44269009A079C6B5067B32C083277B43CD245BDCC9F32AF924A69B8FD6203E147E4F24D98\
+6462B4FCC19895DEDD69CF631D9362C21744004722B419ECEDC53266A419623188E9234BD0ED\
+D0B6B434A747050EEBCA6485CA81893BE4D488D181211161A7D1BA0D91BC2EE94EDCB99A45ED\
+F8160A9120E477913A225C336A24E08A7640A8329C9D4277FAB518B67EC41ADEE3E6845EBE8C\
+53C6F7273B0891E237A3939AB9CEA6839EAB641734AFA5206CED08100DEA1031CAD6DF653926\
+30A33B791A2B10036948CD441D20D013A1BFB2730A0D265FC7AF87FA58EB42CCAA6F954936DE\
+EADCE4A160045258A6B65771C8916396751C0B39D804FB642A7FC071887548268B6DDD38DFE4\
+22720BEB1BA13278C284321953F2CEEFCFFCDD051A0B847238ADDAD359720054869202346BC0\
+C0D2CF83408A68CA1657754C19BBAB2F1A302FA988B73CE061DC7C98E8EDF3918360FFA4214A\
+7F7AA75567A2A0E077661CB379B40743E719178D55B2132697E3D73C924C15F99925559E2D48\
+879C1A798FE2E18CF15A5B3819F36CA5A1DEA0F257EFFA7C9F1EED365801CFCEB2EC1798A543\
+4B0702E7339E4785AF3F558A7EC6CF8D9EF7BC5A57DBE2E3CD148A210F86DD59C9D75D949870\
+FC7656972118585DEB702E02B8EEB2A2C291F46078812A09FBA07BD5473F2415444540C615BF\
+D49F9635BA7E4BC935C27416509FA81B6787767CD67F296253F55F0B55B293B399E316AA:\
+9FB8C092B2A0DFDE70
+
+A946842004EB370887F8E43D082718924A419A24F3FFBDA01CFEE2A57E061B5E939B2A38C798\
+F62EE5C62F46711D980A9CF38057E73F6ADB9DBAD2A1B4CBA828E79E5A587760D6DDB3B04AD9\
+F61CD53E501668DCAA42CFB5DE0769AA8688060CC7D2C9D845E181C18A842D9E3C45FA1FAC06\
+0CBE4E9D3F2C168B3584AC87269DD455112BE67218D5D4C027A1BE4ACF7C68FB33100E8DFB1E\
+A8DA8F63B7D89A5C972B2D4DD0B2627149759674CFD8C7C91FBAE6C6DC156D8F2D58F45252BE\
+A15B0EE577230386F6ABDA8B40579F216166C8492E1F9ADA792C42A987B270A2DD4ED6E21B8F\
+B5AB98A8D56A782F8039474D0233DB9CE6A0A2B8B28D16C2B7E69B8834D3E2579A8038CDA9D7\
+BC37D2E4E8E674DF39B6B62AC55BC76A83738EE0BEA1F236B938E0F2CA63D1C97362E00364D7\
+8BBA094AFA3546954461138F2012B04144E8C95046E4C1C5E8AD6D17C5C9F74721CE68F84000\
+D101FD25182AAF2888E3E75052EDE707D2E16FF382A04FA30488FAFCBB2D70E5B4C0294B8C8E\
+E04CA6C6A8624E476C25451BA7E1FF956FC0CDF4E8207E6961B1A017751E40A3888966644022\
+7613AD3C3A3BD853816C4B0E17A7D1267B2615A1482CB304EFCE54901A35F3A56E8A392F6EA5\
+F8B79309F69EE8A936FCAA6B1DE2D5C6108043DA1C11CD0E199EAB241385646F4ABB81315268\
+AA77404EFD3E2070E8342251C9D433E474C5FDE3546A2735C406194220CE42B830E6A483390A\
+2BA772BB36C9671068CF6E7BA70EA29AF7BAD1F9362D368E69E01E29566C27C6D3B926F7378D\
+0BD7195202D052B3148F7C5D5BE19C0772960B9D08EB31CF2AC357C2A98E4594AAABCA37221B\
+09529DB5EEFC26CFFA57F973AF90813FEE0D8E25CD49C7634B033E4A3AC8E370348EF6B76AFA\
+DE6DD823CFAC381AE795852F95763EADE551F65A729E3366538E8723BA2A7931F217C0E7554E\
+5C7F9E02CC2923717D6F285AC12E4E126006E99EA0393356A3DF5EDF1CE578B9A5242A8D3526\
+BEEE473B2EAEBAA89B593D93398250AC62A5B111E8FC473E77C4F64C61128AAD86887EA35362\
+E1F1AA1B72126846E7C00585EFD36D3C350BC9F2E6C99DBDC4CDFB18EBED3F9AB9324A58C944\
+ACF030FF70A196A6C125DD2C79E698C9995C9160095534B104D5859FE5546FFE5EA14FA398A1\
+2E15DCB0106E8D1962A41D229694F24F858744BC09C0BD303572CADBF0E389822BFAE830C71E\
+C5EED78C5F5903A30308331F8DE92E20F1F94561D74344049419C6158E533F3B29F6C8F0242E\
+832475DAC711D5F1A3AFBD853E4F48905F0E1B90E6C3EB4560A7F5265A10601C8B9EB7706B5A\
+A9C654366D4894BC88DEDFCD7E75AEE80476D5C7FBE5DB7F82152D98B0B27AE01161A4037E69\
+A96CBD11EB512259E178284FB41FF4A5F16A37053F7587C2F237F10059FC38699B86ADDB:\
+3B6BD8169D4643AF7E792FDBC9A2ED78BCECBBDF7EFD7B7C86FC7B96C4A1E089888BCBE572D7\
+15C2ADE3367E948E02C723DD7B4CB2789BDE1664375529E183C061E263A319ED240DA7193A9C\
+C7CCDCC188F651E1C2A875B06D6A27EDC6F7D7B4AAD7D725AAC9983E150F7B54A1DD8D36068F\
+65A505CE401474AD2C79CEDD0895E64AF67907D2867845D13286712FD294C4F1604582C2BA78\
+B540614A7FE2D72B4C943305D8AE39EC416E6D1FD9FC6BA6A6093BAEF7D29BF04F879166968B\
+3067228069FA0D1CC1EF70B870EF4FDC2484542CA88FEB946C8169F8E786DEA68D654986AFE6\
+493866943BF065ABA7DA02E9B225E1F9428B3466212C733E9CC293189E54B703C0C6F3DFA17C\
+A183F4F752CBB1E4803715B2B49B00D70EB36816CBDD856065BE5F86A5DE04A3FDF0FC5AF5C0\
+3E95895A28A806123559E642298CDF940912C7B58A1B0A536FE6AA9DE8A5F98C02FFA7C8A99F\
+1ABF7129BD0EB678F21B3273BA5CA047188F303E6F8A32A7EF864E49470478EBD7187C71EFF5\
+7EEA68147AD3D5C87CAC6133E3B8F71221E8B742BD60A4E73137978FBA51F459C22EFBE66D8B\
+496D9385A8BB9962071F997A2AB3E730A529269213F121583E1A02F7B1F15F754BF6BAFEA740\
+BEAE9DE0CC3103F9A9A61373956AA02A5D072CF658A2BB250557723F64BFCB7DBEAD7441F25D\
+2EB1A54AF9883B9BB25653539D5CA8289B8CA9C3DAA69486958D6B190183D677598CD9A4CF27\
+9DBCA1E323FF83B82DBDA3F416AAF6FF2C14DB6CE5052E5657DEAD8DE3C7F14C74A4EACA1C97\
+4DB989625E0B9548245A3D7857DF36A7066242261336E72347A3D9B765861DB6D9BF843F2274\
+6C063AFA1F724D83204E5CB3A9E8F1AC86C8AB62A83B323B48D52CEAC0C3CDF4630B35F26749\
+800DC95AAD88EF7F83844413E04A17136618E9CB799DFF24432798BA5777966A07C0A3F24159\
+963B9EA803DA5562D544A6CDE1FF21D6D5AA7CAF38D436B706F2706AEF6EC02F003A023D7476\
+D0FAAA3B5DC397524960DF83616EC5D5B11D2CB148BD1D2D6AF388AA4B978F1A2C2A2E6AD548\
+F5F7D12B9BB28C96C062FD13EADEAC01CBB32ED06B75A5DB7AF0DDC56DED1EE5CD509003C211\
+E3B5E673B7CBAEE0A2281B156BA5264CFA602080CEB2626A038BAAF69FF2C3778F06277F71E6\
+2375C78683B4809D2017725D9A4AC03FFF0D3474AE23AD183C012B201DE91ABF005944CF60F0\
+96667E506C6879771172EFDDCA4BAC2AC65EBA86BDE7E78E6F6970D59861708A01EAB138F33C\
+197997B98507E5D016D7B3AAF9F774A93F3A7152C22279D2DB55966F387118A0A23C36A539CC\
+D75DEF4367017EB0502F7E5E08CC7541074280A90A6CBE0E4D881154DD3836E6E50BAA61BFC3\
+BC4E4427BE0519D74ECADFC57A3D3CC3B3288A6195A4E1E91ACB74F7CFE2F4ED917BD7FA:\
+E8547EC6BB8CE2F8D4C8
+
+18D660AF6D52144C394F285EC02FEE9AA28F11EA732D393CA23B6C68A1751EF3BE0F28159E00\
+55FE925E3EAA77308D9FED109C764405266781B890836069A817C8CC2F33476F02480ECA4F6D\
+389B2F44A7207F17AE94EDE443064A1C6DFEE28086033DD69C4AB8622A9BB65D1032E14C4F36\
+F753E70F9E399EDB92092FAC60F9540A2F8E6D2DFC418BCE35F56B1FB7ACB6128829B27326D4\
+A4CE6DE1ADD9755BB6429F5BFCF9779CE46A041466C3CE353534DC114F07A62AF0BF7472BB0E\
+760098E920F77D3F3F48145C9501C699ACB53B9821DC56875662E524C90EC65C3BAD9A2D2D15\
+2D504EEEE8C64CF87278F964EDB34A2B89889979C71E02581A4B87C3B6377287AE1FBDF2D777\
+900E318201B257A1818349EE5A247B755D4173A9A6E9393B136D92AED9D8420D40C91CC095DA\
+913FBC8C8976D61A2D1AB5191DFD0ACF9B9A694CDEE2BBE42DD8B600616F40B97E6399068FF5\
+A5FFF39456202427938AEF8D4DB27D8460FCBD4D91E8F2C16C1E9704479CF48AB364A26C85C5\
+C2531A7D624EB8A3FBFD5591E91FAB465EEA54296C0314E944588FC8B74D6BDC68363037C8CE\
+EF9EA7D97792F25266AFD6B2328E53E8AF6FA5D8D8DF625621FA21E29D809CFBB86C8CF7B018\
+6A8B90159724A57C5E6892161E6802BBDB36141DC5909D4BA3CFB59DBFE8A5833F3228A9AD92\
+54815D69D09C1BA3FD21CE5DA19B277D46B2EAFAB171DFFD7504A71FFB96AD17422E7DC9541C\
+FF16BD5AFBC498BFACAF7E5D5D79EB9072CEC455BEC783F0935ACFE8E2594DDF5252B598AC3B\
+B6F7F8DA99AB326B8C914DE01E4FFC0D174803CD4B69787726D9324FAE54CFC17C0E8A08692F\
+3E9854630A6EEE746864E0FD2D9785B426BAE60901C9E7478394159B4E7539869398282F7998\
+FDBDD29FA5D3218F05C623AF3B0EFE1D98AEF1B05DE593906A6BEC93CEAD1EBFC743E7D96832\
+45CFB6DD3D05A456868DC0730FD426066A261F27776B910244AE61111E4CABE88A0B75E97B66\
+4CA5B3E896FBAF5550948DE7E6A695C413021C702FA31988D734E4E2FB3B71CB33DE3E942035\
+A9D6D0D0C9FCD554C3BE6797173CA5BD7E2B0C7AAAEDA585BAFFB630BBEBA0AF1AAA95C67915\
+2248BCCB76470C2896FEE0821435F466B788AD81291B9BEAA98AE92731ABACFC67FF5CEDC3D2\
+F528243346CFE6A1113C71DC8E0E8F9F88637937B70863ACD5F413ACA4FD0916E9173A8ED8C3\
+0D14A2A3D017766353EB0A89762678A11D3AD47FB961E5DE31D9B24F98128A273E3C1F282A1E\
+214DEFB324D162F9025CE8CED03CCC1B140131CF0E17EDFF2EF1F53CFB3BEA8D7ADF14D84FC9\
+8D43CF9F5F771423703FCC3D034D108AE32904975D758C8234A2261ED6DB23B0C04212166DED\
+54B0BC15F62E6E1ED9B020D79192271A6A2714A9998B3DFD08A19E8E2BE334DAF2BA6626:\
+024CF54DA77692C014693C6FACABA08C52F75332A7D5084E2D12F3547CA2B166FDD6B71EC89C\
+F9FF02CC4A289B133DBE6AFC9E87A7A28D62E7C4B636E4ACC9370E77D900F089163961BB6277\
+64F444F013501BAFEC9F80F753C9FD0055D4BAB050FF1C1DB22C95517AD76E5686DCC7DE0D1F\
+08DC2EFB287C41E279DB75CF4F67E43C452D10537E8AA653D284039909D33C4EFBBB47FF0939\
+830CEA000B447FEF774BFBBC378008D0B212087A73D572C54BD9E665A7A4D2D533C7BDE9B976\
+B65FC7BD540F4E9C81B2D26DBCCE5EC12739863C8C76071AB93C2D18F84C9198E6C70976414F\
+CC1DE005251B308009912D6D2757AA9359BC20FF60130E12F4BE75725B69D5F29A4177DF104B\
+78CBD08F735E1DBDD51C0443268143CDCACD180726EA081A9B252B26A4A6C16CA6225CDA357B\
+E3CF4F72D7171C853DE6391944CA2065A32298EA17EE0CFDEEF2BF46A6A83BE4E06F076DBAA3\
+74ABF450B78CDCC3E5F3976EA2D9248CFAA75B292542C55497339A149268E895465B44AA16AA\
+A91021CBC32B761D1ADE1E5CEDD5403385C23A2DC36B468A2EB54DDD3A78A7B0491F2ED546F5\
+034A9D4A7BA067C10B920045A04A6D27629701F92EF442DDD3B81FD992C61D17D81625727516\
+F3163E9E2FC538486D5AF1C0F09226143E79661E6C52449DB9518E1DB541E0C0F862A7E783A4\
+EB78E916E9C9CCFFE358D139369D416E15B361740530E525FAC7FE1A5897C658A66C6E8C541C\
+B1C5B0DF7FDF1818341AE975E1CC0517CBD55F8166E499F48C78DC017FFD4A2FEE2318FAF150\
+34EC62D451F559DD47B09F4ACB5536F593194B43ABBB5B88C8AF87699F38C2987B4D212190E0\
+EDE8BE80E97B0E8FC7C5A71C694D2FC7CAC8470440D6E6225B415E6A6DA4BA879468DB40D765\
+9971A38DE502253EFD724AF9DC2C702B9F45D6613181877A2E3E7957D0CB6849101AAF3787BF\
+FB188264EEE9337DDFFC7405E80ADB30DC5CB367EA438D502E3B1DE303D5755A46A46D8B46AA\
+DA4E363CE08AC181A9E4EA6B1DB9B3AB551085DACF99849624DBD7933F1723B7AB4190CB429F\
+696D8DA5DDC92618BEA7E235E3D8CB423DA90E90A8540561FE3B27ACA309FB9F1D4373AEAB4A\
+C6C45D90E1D95C0B2F2B7A9A9DC468C8654779361CB4DA6D6713C7218328707DB6F8382A3B8F\
+274712FE3E70B439001E80CECF6A7385F91B720F815211CD9533764CF8245FCAB3ABF7FF7271\
+E93D25DAB94D6C75CFFDCBEA6199E5A6069FC13892085E713EAC8396988CD6554E0ADF4FDE2D\
+8C4CE6FAD62FB2A0C54D3DD6E55610E14F6DEBF5126FC552DF942F06651AA8E4AD9D4A35C10F\
+611822FDE83ADFCA8ABB678F9465FFDA3D5AE38CF0EA04DABF0763C68E95519ABBED916AFA17\
+1A487E72F54B6C88794DFD6F80660A23E2F26BB6E844FE27DE41B062910228FD1030583A:\
+2F2758E4C63F9C698C6503
+
+F6F77F1E437560515CED6B16CE05A52D89B68DD10EE26E826F0E6C54264619B71A4AC1F4D56E\
+204947DC46804E29689E8EFC3950CE25482C4ABF907798691A3282374A822289F24E0253346C\
+0DA48BCD2D28EF6CA9485221612ED197A3E602810C97B644ABC1A43C40B29BB99C5DBAD8D641\
+146CD621EE1149A3E74C51B460A4AD695E77A574E23F4E74FEA26EFE64FCEF59844EAD15B28D\
+AF3FA97FD49DBCA5AFF113289E616B4E898CBE2C7073215C02C3E33D1D67261075D077414DFB\
+32BE4DE414A21DF902AD16AA76A176ED1B7A9AB8F6AD35635A38034757CB52C48B3F7BDAF5C6\
+87DF0836AE7D11E91A41733C721F68CA8D882F2B0A6B00C133B230422A9E9A476BF016082036\
+876D7607A34BC9021E867A24C33E1130589E3F6FB2C75273BC0271E849D6DDB84F430F6548CA\
+BC9227EAE780379BF9657FE9569460036A7C1CD8B4C63B3587F0ECFE522128A286CD8CF0F2B2\
+52D433B6A4BB4445AD845F9E56C35934B90AFEA01DD6D5671754C0B2132D4FA6562B9DB9488A\
+607BC6607197FD93F7EC345A0F0239514F1DCCAB1DD67A2A12B2DC2511FC789EE8257402BB64\
+A02C703D70EDEA45D64DEFD9209F9172C3DEB8948C0CDFA05E3B33AF4CEF56F5ADE10D8BE406\
+61742249F6FFE71E49031AA605054719B59B1667695E1A07C0D126CB477BC005C44E6FCB47F3\
+D08A7A39DB4A7B446A810EE60E71BBB3951890CCC182D0613119A65BB08309BF87214DB179A1\
+CE2D3F21C3F2132047F8EB5F4BEE3198F316C669E007A435921DBA101CE40A07DEADEB308D2D\
+C2B27EEEA201B75633476DD8EF2091FA1F0950FE713BA1BF06F1B55168CB416C181EEB0374AA\
+728531BFE226CB67D7B2F5F283EBA5D1F87F3FF90AAE06130F34EF44A8D2CFFD7E8A5CF9AF42\
+D3A7AC0FD4FF2DB47A38DAAEB3A7C22280205879415418B429800762F597CF5C4A4B07BE8273\
+827038F83D805A4E6ED95D415E9FA13EB8F5E401241ECDFA71DDE6BAC2F397155948770925A1\
+BA9AC1BF5A65B51C26381A09E8259D4AA8B62AA97454D3F257C0E5FBC9145A4F4A47BC743B3D\
+E964C2FC8E273DFB21B78B6FB42F8B6A66DC766F5729F1BA68426D4EF7D5BDF9E28BF39B964E\
+EEF5A880E2F67B8393A57A5DA788B51C181EFD35D919C20518D32425A4050022EC73C080D404\
+F1400D1EFA7FD2DFD8AE759ED20D3657795A4DA020D1890830FCD80093AE746DF9250F2749BE\
+C1143B8C7E20DBEC9E94F69B768DF054C202E17A0756C02D32A008AADC2F009D057AD556081C\
+68832EE240EFBA8F46D6D99F96F66B508360A42B38F0EEB367DF2AE78FAFF7C30B0A22CEB9EC\
+B05D683E3963E7B06EDCA94BEE20C8D991B1931D0C4A1321569679CBA497406F6E2F74B36F93\
+2DF3134B77747D321CF4A19C05ACDC25C548AE81F1676AA2C18B7C14E6465569AC436D46:\
+6F2A05211F8D2800394D5FEB91B7740DCBD71033C4395845528B814C495B9CC7E242905B5C6F\
+30F024532A50D8A1A4AA3E67ADB9B33159767DA566E5E50E7844C503F48BB9647B24ADB996E2\
+EDE2208521DA9B5BF15B344F748E215EA3063A3E5ABCB592F2C04FBE841BCF53A731DC1322BD\
+EE3F3E91310FAB216ADDAEBD5E226AEE12FE00ACA9022137478C2CF93DEA82B302AF5238EAFE\
+873FEBD1F222377DFAA177D8E1E313085AA5B1A28E473C7303BF0D131C5F8188896F2304FA95\
+83ADD474E92924FE1782740CFAC20AB4C2728CA3D0C41F6C369EC1662D166723E0262A7E4100\
+4F41A795EFF54585AD8F8D1137EFAE0F158F9B373ED73DC73DFFDFA00730AE381A71794D48D4\
+2C90BA49AF77EAC887AF0E01AF68665F081AE40757C6CFE430C3996EA4BB2F1EAE8E97413DD5\
+C04F1B1B64122C448F40701C60DAC75E34909B9B8B61895D819EA5F55B2FC6CA5492AF520E81\
+6AC2EC14498891D073FB65E3D33272CB5771A479188CDE2FF818881481A4747BDB20F0A60155\
+7E016C564B8F5FEA42694F12681A7D2906B2EB0DC0DCD8B98E763C5E3334D65B84AD23AB7C5E\
+7CF8CE1EBB34494E23FBDA3D34994BB20207AE5E12BFC95A217F3907565E742FED414060B86A\
+14C710F5F5DC79F0611F2B2532ACF37E210B123C15B51E03936D8C5362B2BCA153B19F7F255B\
+0BCDDD9FE6FFC5DAE45C42FB0277A56FC5F6B56CE49FBFA7B1C8C249E6A5EF497CC7C8D7CE32\
+0BEDC0D6EE2ABD5FD67F6E953F5D9BB025F7853B04E304C382E3BC80D6E5C87FE637E38A8293\
+05348CAB5BE542A7DA8A6B47A1186B6590934AA86356E58D6FD059D333D8AC6ACFD1315EF3CE\
+A933EACD22933C9F29A7455D83BA1A8DD9B69189A181038542026ACD15085129F824475E1EBF\
+76B591422951D96498F1FD5CF93701D2CEB12F466E701B1FEA1D38C6F57DA33A69D0CA041BE7\
+86A045BFC27451A76B0105F00F9640180A97A39D6BDA768D330E7DD5CEC42A78E12D518D7742\
+485717A383B983C8749315037D39A100248087F4FC40143873B11ED80FE496532DA3CD09C5FC\
+1E22311922A3445E07FB84F9924063503ED11369F70CAC8B6CF7D8367658C333A2C421447FEF\
+A05FDB39055F4A46BEC4AC90A2868664E47AED74AE0B0B5604C06CE8C33BD2DA41E8714AA852\
+8C68A84BE11CCFA67BE6F74AB4ED104342D76BDB9DDB8F38CCBF28E118888ADB1D7626122FB1\
+D265ADD42DFBE823E93AAD3EEDE4D472AB139A7DEFD026B758F3669EAFA7A1D99386A5E87056\
+0DB879884906C0CA9805290FB19187AD24E7C2BEC4DD3D4025E7B29667ED94599751378DC4D2\
+E0A5A916DD35D46518451328BC7187D60FAD9CF47CB13B8B4BBC9AD71C064BDCFA9A1F674AAE\
+15015B5EE1BC46B1FE3C4FA2A83DAD03239953B55316F49B5CE605AC9CBE41B02DB59965:\
+195CAE9B4ECBCB8DEBDC6C48
+
+EAB25B3642470318B8DF509B4B1939289B9EC9CCF3A12181C8AABC6A72747AEB41A68F69AD8A\
+BFC1164765EEF06961714B7F49D8098088B245E05DCA8E52CC7AC8A5E97C6DDCCFEED8B6FFA6\
+1EE8DD8644BD31888D27F81D1A21C1681771B732747FAD3A238381C80B004244B0A1EAF51425\
+957D2380E7BD777F74833DE0A3E3CEE8953A921F9DB5B6B8B8BA19982C7CC2F8C2005D1BD8B2\
+022FB01A687D9E0DB6298BD42630A9660B25EC35B2CE6385C8C15A79670A23ABDD74ECC9CC79\
+14055063BD762659F41DDD1AE6F7912428A55EF0EE4EDFB257F05BC04C90EB67196608108599\
+887B5FDCFC265FE811ED1A21E71DA52EED2F1B37884BB888A23CA74752E1D612E3575B54F556\
+85FB6BA51743FF5BFE44384FED0832819BA014F613D7B19A046AAAC4C8902212C6F54BFA57B8\
+E9E5C50BED0E0A1F56AF878A323791DA52F173BC284F3BC38DE23D27E06CCCCBB4C1B7E0D6B3\
+F594FFB71E39120076D78EB85722A7EC25EFD39FAF7EE4D020B3D05D6ABDEC9318075EA81995\
+97E9056DCEC1678CCFB0907977BEC59338AF03D28A80669A629A70D6C7882484E2E4A43B9C01\
+EB5FB0E034D8A6E5B54238F3EDC82DF6741055D093F4E43C6AC4978A4F7D00DBCF4110E6266B\
+70F7AE7DD2A93A74B16A3FD7AA249F6182E84094611EAB686DDA57D091CC2E156026D72B7D8D\
+29965F9CF1583CD921DCFBD57BB0532B0B502F4F4FF6FB19DFD858AFC912BA411310122987E2\
+84D9463112C879E9B0DD686F9DB45923A69B3BD200ACDB83FF41366A2C417CA841D9B85B7CAD\
+21681B8992D0243A6C30476B85AC2B3024A6331C160CDEE694D09416300FE4C7FA1B76F05BF7\
+9E5FB6880ADB3A1DB894ECC980A10895163BA57D36060C5596ED1AD1621161EE6068184EBF42\
+719E9A9918A819B77394D25D26481BBE51858A4BB0EB3C693CA99DF8A504E3B1FDC84A497312\
+CC4396F7C4EF1043B70484499CC24002737DEBA24D9AE4C538410887830AAD0E5C15498C5AF3\
+A24597306DD953E6B342DDB22496A66E156BD753F4876C26421CE720E2C3C864982433374351\
+3617A426374D0DC812C9C1568950B68F8A8EA1AFEB581C4F2D53C48654E19E4AB76BEC7C8D38\
+4366F207EAD9D044F8E5C5652A6A73626F5AD08A0C3AFB50DC9E6541E24B9246370F834D6E45\
+B4C8EC8D7F4C64F01EB97D11E8DB1C1EE7A489926732E8C8CBF6873B7B947D98F96698D2F2B5\
+513F2AAD60F481B39D6CB49485633CC81D1B98F6A7ACD09CDC001D13F059C1921B7AA5F7E760\
+05C51291F902E6F566439B9D2AE60A4AF32E939714B55BAC5E5A8E2053AD063E05738D03A704\
+441BCA926D069CA0910BF5D4EE3F81B4D8940E1B5980038339362F08C293A2F28CD0385C28E9\
+0D542C36BDF80172504110A03B3F57EC6F700D38CE039E7227FE6BBC8463057D92ECA65D:\
+7D681C0CA45B1919BB9DB6102FABF4FBB21CEF49BBFF6744D4779533839A414C06FEAC76C278\
+20EC237A08EB003D46AF81CB4354B701A8D0C8CDD6BBDAEBA2C5D7D1D089B6D530B787BB25C2\
+9291239FC3DD2F7FA1BEF55D84E569C40308D792EF44BDBD9FC557CD618B6626157567C45481\
+4009A611698576378B094988D2AA04BDE298B96AF7942A1DDA481546F080BB0D3B093B288152\
+C1DE21C7A6429A6C794AF36D387391A5C71A388EE30D9A887268FA4FF2E8D249FFD62BB6905E\
+7FA605EA81AA0E21BC895B333CB7EC253693A6A035632DF8FB6AFC8DB3A59D05BBAE5A5C49C2\
+0E24235082C55F7EB8573F18B3D379DA4188DDA7DC6751C5F20DE416DEE4C09E8A43D60EFE26\
+6F0048A127617255653B3AF4DA277A11D3391C4C4DDF9088A7B7880F8CFBFAD185FD436363C6\
+B36E9FC45FFDD896E502061A7B154B67D5A0B715AC4B970D27645CEFF88770290A3B9ED84E18\
+F306FF39A9C70E9EEA4DE6E661BF81D6178336E556A36A87024D7C2EBF04C10E19B8E5F6BDB5\
+6C7351B51345F2D6C29D5D1BB28B10357818D482A2015221DEE8798F326C223D8E382EE38B3F\
+2B68EEEDEB726F94BB1A33C5893AC6EDF050A90B7DABEDD734E269B70C5E3ED5300C370E8EF0\
+DE215A69799145B11918D2DFBFF65F80C00BDAEC88153886BAA2219EBA027B6B93B6DD6D27E8\
+A70F7318326E3A0F2937C6C25301A33A521C5AA47E609980C4DC03EE018A128F7A0EE614CFFB\
+F6081A89C0CE27E097EA6C639FECC0B2241B18651177B3FE4EBEEFA15DC588562D08D4F63938\
+2C86C15B99BB96AAE55F841F14ED67C435BDCF48595C0EC4D2929D75B1C4A1833C9AED228DB2\
+0FA1AAC9EAF5ED8664E56C586B7E5A01C2308BA61DF95FA3FCE90FB91B049C51DF7E58141EE3\
+1744FA1536A9516E16BDAC93E223C616ACD2EF48CE973B6D6A123944DD0B3EE161007F3272C0\
+92E953A008B0F1DA7FB8E2B8A2506D762A82D89AB1A60E33D1D96AA189A23F6D475D03F7C19E\
+F77A6290C8456EAC591C40E92CCB5B60A5C5248EA04E6037AC206232F3EA830661A344B82517\
+3426B31A8EFE80CB6C4B9BE4144B48162C63A1B95CA6E3D173D9EDDDFD712D56D9D6215102F3\
+43B35F9B36ACB7566A3BFBDB376F48CDF0F0365330EC35BF414CA33C2919410E429699B97B57\
+AEA59FCF3F21C261286276E9E2CCBB1E50A970493BB1211324473EAD9360C98703259BAFC93D\
+424FD2CFA0DE257BCC90C328F7EA2890AB3398D173E19CFBF3F43902B43C080612A81DB02FF4\
+8D65C214727A81F9F19C8C4E4C6D40EFD03B0F5084A9595A5C5B330652036E611452EF24516C\
+A8AC71CA5B7874C209861A12DD5CAB8E310784E82058E5B574116D6CD88D7CB4C228E5C44599\
+6703C93E73460023CAB06462C9858B19DF2329214ACFFD82EBF2F9ABED4D1E62B38FC2C9:\
+18B309BB8EC6931F8C1F224D9A
+
+2549472387BADE846341B6E3BE1938D72EEC5E11805ABD34DAFF0E8C1226D5BB797FB149795B\
+1A1FA79D5F24D91A60D7C664D82ECD90803EE9E941AA5DECF159698727A984522CCB02B024E1\
+EEA19AA163A6886175AEAEF0259D1103AA35D44B3D64537992BC1452DA51C9C133F118A88659\
+42FFD9BD48DEE841294BB59308BC6173A4CB9840D4B118E31C479ADE52D9D281A9B97ACD9CFF\
+85504C2FD4859AC73653B2F08C1C9FE2712E0BBB26EBFAAE8D5FF3261DF6C1AA330FECDA2459\
+82D406E607602AE5058242D7040B8A0A0F8FE07131912FFC80895B0A3AA9E3E8E932A5083A4C\
+987D4DB0FD651DE6E00FA13B6454237C7C03D069C57ABE94F2CC23E23E648CA81DD010D06406\
+5CC225D70657A5145F947D4C8EA3DA0695D7DA7569FAC76033E01AA3C2770385E8633327AFF7\
+BFE3B36FED73CCF8323AA2949A3EF3AC72F2D2046DB3B98FEA69FE98B3B9FB9CEE71ECF90DB9\
+0B65B27417A8E1656E8444D5EB6DBDA3AFB8BB527A26C51BDDCC47938254E38D58853BAA1717\
+4CE36ABE1F4708871D41E77F240795CDDBF5115654CF724E0A68C776F705CF1623989B8D2E04\
+7EC25662CBD1075FA6CAAFE7D911C61E30604E3361925B922D1481A071918F0F2F28A4EEE8CC\
+BA7FBC6FFE2C0EDC102B0BE7361761E6C75B1441B9D8D22898238CEA6204B060BA4CAC3F174F\
+B103947C08DE40753F3CC319E0EF163193173560BC94C0A24646F298A3F24FF1C4E6D322399C\
+6F92201B288218D443EA102CF2BDCB016FB7F4E1EED7D48D4316081484109C4F9588F8D909D9\
+EAEB0725F6EB487E3F12A1E653A70F3EA5542F68983018F5E9907BA9B3AA86335FC55202937D\
+0F45D43389846C51A121346AF692A00F8C4627A3BF58451EA0E8EC047A5D2275F944F67305F9\
+F46E58B218360810C94CA8295BCA1A3F4997133360683E8F83EFEFB8D27EA6448AEA02F5507B\
+5C1ADDB848B5FC185A934FBAA03E6FB058C164FF4E0304E388487E1C37BB83D3FA64E713565C\
+E976F9D1C6C69BE7EB6519E67CAD95E90D4FCAA8AC90D43A2074B41E0A6F7773B618DAAA1607\
+5104D9BBBBD97DD219530EE47AB277AB0F5A8378F6345E045CEF9D9C625D82F568912C131140\
+B98FC8FD5DE20D5F2F33A542129EE85D8139D1D49FFE7C49C412439F9B62528A1D1FDFF6B7E2\
+FD645E63814F597BD52AAE1D90E0054B6B1A7D11D3A361A46D0F12FBE93D236911D2A2D06DCA\
+1C9E71B6A439B75A5513077D568EF9CCCED07181629277AEBCBDD6547E0163BAD4CCECCF5CB4\
+2A87FC1764AD39F289135557B5F3448C8903C75078D05A8AE2F77E60D5FC2BEEB2749EF604F0\
+5442E1DD139C97545456351E0CF51248E9DDB5C18E5FA8D66F8BAD3F87EBE09D0BFC51402096\
+0A4EF76D357EA5B7338898AC6F27C1259A52B1687900BA66C665D8351777298881A7917A:\
+CCCF1A77029D9C52B4C36FB1C15EDC2539FE0A4D6F51CD45E613AFF6D4D71427F104DF270B74\
+CB9370FB847CE64DF227D9CEEAE19EBDCE1C1A281B5D67EF617528B86BC5142E4AB877236AC2\
+9B8E290B941134B8C6F7FFE8C4AEFF033543E30B0811624C77E0B5AA06988B46EDF62AF7EFA7\
+1749BB1E18C302B5254AE3469BC14C640E01F38B608E5311C62A47D2FF307A7C5BEDECE1B8B0\
+1A56165FF8F6D68E979B5C35DF532933635E4D2A9E4127D2B7CBC84DA74FA6E7FB88A923D794\
+ECA14E45C33F728D5FE66A43965E13F535060CBB2941979F934DF418A5105F2AF9C587B0260C\
+E7917A06C03FE5F345D3059FC783DFB513378B215D17849A671089A3A5A136B79438320FC79F\
+05D03F96910BEB415B744B28B80438319BCBF2681DA358387201E74D68FC65DDE18F7A7CE9C3\
+8342E8156D685CEA43087B5811ADD784413F4A4898372522B341D40EFB7A4F37BE9A9AC48217\
+7075E0CBBC95A4616724A2697566A827F18789F4A788B6FC5B98EA8C52D4E5F57E89CB4F56A2\
+975017B39C23C7CE80DDEDEB0D4B008CFECE71043EDC59AFCFD7B880C246F4F4370D733D7671\
+B417A39CB1AAAFE237EEB78A84F3DCC396E12694FBB841C8625D68FC3289F56E99D0BB17579F\
+8419E0676C8D4067DA5B4E0588D0B0F9F2A0568740475CCCD9E1598E905F5D6E8D2B3FDA6126\
+CF3C954CCEE4997BA4BD27EE1486156362B19287AEBF1F6965796FDFE2EFE976007510C0B452\
+A97035A913999F690E43D23EFF7F97209E6FE6FEB3031C5D59D2E03CA437A5318F9AE8359045\
+8F64D39ACEDDA1457BC9B7E87AC666773580EB2C2B6763D98DF65B6CEA506CDE22513090F35E\
+E5EEC1511D707E271BD8B279B0FA06487F9ED4E462282BDF4E532231F9465D5084772A152E50\
+203F185335C02CB65E29F6FF02AD2C0069DA80ECF10C8A8794E98754929CB2305E2830B457D9\
+DDFC7C8589A91959373279A170C7D39B25EAAF3C0A9CD4B5FBC09915C9ABD9B3BE52B1A645CF\
+E72ECC29D86BEFE3FD4EA60858C674F4B80514FC223C9551BC5080DCB55BD3FF5C7D6E506824\
+236E9168B43D038EA0899925318CE4AC85BDF007B5586DCBC226D18B33D17D6A2B66F478827B\
+CED487D62AC73AC4A1DC503045DF98B3C5C60ED32B769E2464EE09D212A8D02A30CD0841AAA8\
+EC3F21EDA30B2D6A2B87F3BAAB38AF5B5478E004A9F3B1EFDA02C5024E8C83FBBDD780E7203D\
+81F08FB024EEA7508BB554E98A0270B732445E2F57D50B82A943BADD2729CB728E356F8F6456\
+4CA55B545332BFC24FE5C4FD6613E5F82AD6163A9D45E22E3F871F7C7FEC2C784E2A886E781C\
+3B45CA32863C729149714EFE9D345E3758F9BA83E25677DB261BED30EA50689FFE39862C225A\
+605897779FDA656B12DADAAC515B4D05453B4DB307D5D441BA48590D0215547A024A6654:\
+00C03EF75295806B9C351F89FCD6
+
+40B8DA2DBCBB6C202250FABB2FEA9315D78BE5208437616A16646CADD9D0B0AA2239BEB7E698\
+A7C764CF33BE1F3A783F0FEF0746253DAA0DB5C912440C58A8B4D17A4289FBC819E1EDDF2639\
+5C7547231CFDD2ACF6D2CDB9DB04AC73BBA3841E5BB476AC18E39E010DCA432C171D18CFA150\
+A2F8C913B0F00BCF61A976480183A777A1EE9280075319DC3FE8BF35113AD2AF6A8869CC6372\
+89D8845E2DEAECE42244DF5F8C3610E0BB3A16089D32A41887DAEB15534259A0852555AEA52D\
+7BC7F4DA9E8E93D236151742522873153BA0E3F083F473C0F51BBEFDB322B34BDE7E9E3B2CC9\
+729C48AA3C6A27C54550FAB48F805FE4C073E1EE4B593CA15D6E702154B3825DF5936E97238F\
+6184A7FAEB6B33C25F9C5E92009A0A5684F299AE7DA60B84653B4233EF0254726FC4D2319EE7\
+3644E510625F80D02FB4D18D210F019013C9B76421BB833DF3A852548F7DFEB8FFFF3168B326\
+96852B85B7CC62EAE28D3B4BEFE4591BBFAAABB5A42B7B600F48FBC8A56555499292DBAB37BC\
+69D93BEAEE417580EBB8120BC6016E1031C9FFEE3BB793927B632D35E2573C067D3200377284\
+395F995FC6FF47FE26539A55D6697C5B8C52FB1836B7A8C0A691DEBCFF4F9DFC32DB43B3DB58\
+26D4DAC23A1332D2F8EB52DDC4D0CD1D48A59D89A168EC5DD80D3389F88694DD53464BD5BEE3\
+D60BB0C20805CB1D62BF86F232B0CF9CAF75D2162AF79980CC4989B6F0FBB505650EEDB31102\
+0FB8F3844C4EEE994274E190A42B783D01C7DB90DBB237713E38343E48D53D923426EC428491\
+C446421BA13DA837FDF7BB1A3810FB05670760F9009C117CB02E2FBB51E1184402FF351EAFD2\
+ADB05BD0B319E481B234B0F1512308E13C91411F9C2D983B615C48055CEFB1003562C1D0B29E\
+88903A6DB2815C8B5BF146075CFA14CD8CDF59DEA035A7624697B1ADFE64A8BE8980D26AE531\
+AD9139B1F9E724A2E431D4B170F46C42E84186747B163C39A1D3BB3C2AD0D73E2FC19C7E1185\
+E40F8BC81D8931B2A86CC56A4A4B0C422031F8B93D5BEB68E3A26BE266F737DF729FE815B08A\
+2877A6518DE1B753F4DF16CB655C0A27B420BBFE0DC997FDD7EDE4F95F04F5D53701C9FAC435\
+3D4D9370C9438F418231C593FBA37777BEE9F42A912A70FAA1B82B711300E84B2DB12E872648\
+EFB2D91B4DD25F5A0B9EC113F76C9410C0A43B48E70D7D37DE6F505654BC209A42074E3BBDB0\
+4B57C1DC2C15033D60666C49D97EDB5649D6265238B21EAB2C84E0B5205BC671D457BBD1BCED\
+41D57E07304A72830E26DBEAE598447AB16A767DEFC3487487880A81DE64DE84CCDB06754444\
+5DABCAFC048CCEE7E5AEB6782EA6F1E67609635676A0F13830C3D5291345090C822513FEDE4C\
+DA4D00137BDE30683DA84F58324413151D33099C1869FCE3660BB6A30E11EEFBAC191AF5:\
+43BE6EBB5571E9AE73D0A4F11405E5A09A248DBCEE76D9FFF09318E5FDA50B86CCE4334E6F0C\
+F79AA44083AA896488ADEBA02C038543F7ECA4DA5B5110EB3AD4D70DE2A21A32B568F05067B0\
+93697A1C715FBB4685E622ACB8F3E6FE2C9AEB11897969395C387B25791A648C7A697110D578\
+7F32DB5EAAC8B04B24A1DBEE72983054ECD00A57E37A5C2169D19B2EBE8E76F1A99312C6D119\
+11239578C1F2009DBC09EA9F38F706AC5E59BF1DD489AE38F7EEBA9692471B2F342E87A4E794\
+BE9BB0497546B9D4D45E381FF3D45500EA202DC2A680C16BDCA210335BAC87D274897CCF48E6\
+E813766AF5461084289CA27FD283561E82F144CBB08A704647E980C3795200C465D16A7668B2\
+238E70DA6A81D93DF64609037D22CA744E7562C0F58506B899FF1339B93371BFA5F0230DA588\
+3634DE5C5623C67232358D3D38379B82EF5A3B08BDAFC618E92F3E8E65B179822B2421A6FEA8\
+E385184F17FE136CC4D9288E2AED7F4BC8D9C26106E40F8AD7C8F158906A0579DED7181B04E6\
+EAB501DAD016A098A8C75D159CC2898AAE7E67E2F0D3422433C4688C566FC0FC214628F6BF01\
+26C354ECB7A626BAD22878764A370F20901B39A3D16E9E6AAF9FF74A532712DD9A4CE8E24B53\
+CBC58DDCD96B41ABD04A2BCB4A6B968A053D31EA7D8F8D656AB9466FD46374E452ADCBC69103\
+98441669A1A51E1F80514FBA635B807BAD7A18D00F0BF39E44C7FFFD97B2083C7361239A6773\
+1A1A68B53829CA92B0836F94B76DF5CED8A30DCED3F6D231C2C386D6FFC86B9F556EF871E0AD\
+C52D66AFEB91CA512494BA5ADC302B5D30F7F84205F593BABB81F07C3C5AEBA649E40CF6EC90\
+3350A01E30D1C24096D4AD06462E914492C0E342CE333D1D05D0089125C04B82676ADEFA258B\
+A8C925E57C221C5FD169BDB26210F147E56A1DFB1697E7C21F8131B9C2C4DC5D5579B8E7DAD0\
+4AD45B1E1B8E2EA6A1594DB7034995653C9740D05C13EE79FA642448F1005B3DC1FB2AFBD2FD\
+4B7C5D2CA9D96A3F22286C26852CEBA0765AE8C11E189D8E979B385A2DD77AE9DFBEE9EAE48B\
+A0A068F9689099D360EB4C8F99C1978D6DF0F2F3DD2B721A9079D475E0CD066E287D6708B924\
+B78B8619E7154571B055E6D9BEC0EBCEB74EF927E730A962764B09D8CFFE90EDBA0A782376B2\
+C0E9B840F7AAD85F8374C741A8D65D3D8FD2A4CE9848BC6F259CA5D01151C11E137D539991F0\
+BEF86854077180285813C8FDB5E65850EDC53A4238005191D798A0876BE174980E1C8FEEA43E\
+53EAEB2CBF02BC69862D6B9771F79BD3FE544835D9AAB1380069246C930BF019FC0138B6ACB2\
+BB330238DF7848B423964C8476A8E5A53E0CC259D4D58971E0889FF10A04357BCE979C640FDE\
+60ACFA9FDC8160E78490CC6884A637BBEC35D47F3C5E1E93A3198EB398C47850FDBB3600:\
+1FF724B44BFA454A160460164B97E4
+
+92F94DFA72C653A73AC33A740CD9C917466C163873B9D90F4F4D6C8FF427BFD0F24350EA3491\
+783D175F73437D8EC634AB63AB445F5B30BCCBE09FA9825AB28E326FC52CC33EDB529E92E75B\
+9D5E447BBDBF9BA7D6F04967E90A56C144B5894D3A3C4EA2FD61CC59160E656B7AF60D6510A3\
+19F043F0FACE3E9E8CB195DF5D2FAE6D45C3300092E26EE90E1E714F41F165DD22D27026A3D6\
+8E150AB7C6A81484E2A39458849BDE93F2654A35333DF2DE42291235E2462647AEB37000118A\
+358B9A3E1CA8130F7B48DB7BC2AAF7B5279B6995DA28D8942EB41470E30F9885ED5278DDA22A\
+69088BBA20772AEDB1925261B7480F73CE7837AE3FB198E39364AC30BFA6C20E7A8F95D0A456\
+A20AE83C028434545EDC952E091B12537625B9EB8487FF705478A34F587F17DA64EEC9B0E9CB\
+B609B9AD290A6553709EAC85D50CA733B35914FFA3A39FA4E0A0F53D8E2AE80D13401C328F0C\
+51C45EBD0EEA1E73F1CE5DFAC5F04BA4D6FC92CDCE759B73A30515F7EFBC206FF5D2D5F1E638\
+FC827349FECB9221DCBEF64DB66387CF2BAACB9E97ED6966DCAC0919F1FB2E0A0044E48623C3\
+1E47B40DE61AA82D703E5ED5CC7984FB73F3EFCEF355ABBC5A75C4CEEAF34D41139A1DEACFC8\
+416150A231729C3A609D2976C2482D7B77C73B27D8B20369426F525E8D0A32D500A155BB4E2B\
+839BD10556CEF79EDD1549EDC8C78FA6718836AEBCF2DA9D5D182A543C76A37168C7B1CC201A\
+FE0559D2995449EDC7E11EEAC81577351684871FE7CFF80642C238C4E376A7C61E8ECE2E9B80\
+97AF9ADE84114B8FCD4337FB0832FF59E9B6EE2974F5659F8401908300FC99B93B5703B773CA\
+EA586413009982BBFA293F523F3981E80712F471123A7235458CCC242F4CFBFA2DDDF55084CA\
+62819D4CF4F01020BB2586701AB99EF0E40CFF2AB948A9AAFA44C1FC1EFA3D9F2F47F91BB8D6\
+45EA0699051B83A61187B48F1DA5FF1E9347F8AFDD042BA30A193E06636BD8D6AFED22A8E67A\
+2E9B4BDD7FBCC80492F9D37FECB107F44D93F4C352A5CDF6A603F3AB39E78062B046F679D6CC\
+80D87CEE0F9F718CE8EDAAA6C8B2D6C70AED59F58C02E1279F18D68928C4AAF2688E8D283002\
+15531C08C8E8FD91DF26C06355364684B27826322A0D247E5866EAEC66AA54A30C97E71AF538\
+B83DB2F89168B0FB6737F9E56617DDCC84CF7CDB9910CAAA582B2D18CE103D1466F554287CBA\
+C753FABDB92D4B3500D14CFB5DAB5BDA49FCDDA541569DB38B046C063B2D1DF35CAEFC183C71\
+42B4A8FEBFBEEB25671E4B7844E82D7B11ED990AB4CEAB28C876764C1B3510FC50D4E4DAD614\
+F8928592ECEB38FCA604C3ED3888A45A8AB951FADAA962BEB81F5A517821DE7B319DA9C6B297\
+D52112F5BA0FBE0242237082BA2B0081F21A3AC1EDF48DDD41FEE7A227D0A3B26FF0DD73:\
+598BFC4E02D49D5D82FF1031F230B1E9D289648EFB03F8D9E7818EB5023066F4E5FD2A1E401E\
+B20581A69C2A084E0DE4436AEAEDBEF9504C7C0560FD2AC6E94BFCEFD9703C8B959BB9EED253\
+F4AD7B6BF476E7F122B5196A45410C0D8D53FFCF7CA72DCAD7E3359ADD694EAFFC5BCC4D062E\
+129595490147C070FC21BB903F8964F234D69B890527985CF28E003B0E82143F87F91B7042F1\
+15AEA2CE15B49F1E8A2A9A6DB2B0F0478847880418B2FACCED2F54E7BD30BF766360871EAEF8\
+1758C750E8D1B032F299152ECFFACF43E726AA158E26EDF352B185DFEA6A452E0EE95DB05CE5\
+6E5FE2F75C1EAC692BFEB433B17203118BDEC883591EE735B889DFFEE6880721D11959910A3C\
+0008D0B148FD73F8C211AA4CCD86E1BFF6C4C02B87AB5DFD911C00841289B5969D481B798BC9\
+E0E91BF409C6C1F84299CC31EC2B7ED0A84FD1D4A26244EAD85F81121949CCE7973D1A333F30\
+1269A1C437CA998A225AFA8394027381D37E598FC00B62E58CD062E415CC2D6CCF325CF44FD9\
+B56EEBB1F9BEFF521710496C63CAC94FA1095B41745DD697138DBCD71C096915874615DA84CB\
+97FAF5269566B4530744726C911AD5D6F078F9812091C5E6B0523FC9070AAE823B9226CEC9B7\
+0A36465779D6766A9C4711B403B207C9170E1739E56443FDDB401E1937F86E8319C8E093D01B\
+AF7A9EFC41D84DE3D20B60A69A9D92591E1D91D4209E987E5DC413A65994EFC6DACA40E6BAF1\
+5E61495043FFD03E94A7DEC7E98004B93822FE56E4FE51392E24DA1F401EE1FDA7AED2EAB149\
+7459209FDA614B3A69DE3F3B6E8222962A5B29F0A28859254AA3200A1F59DB7F36AFE39E0F7F\
+2B89011725672FB8B3F282186881476F69C782689D6D7ED426B1D58F36B3F2E6372BFBCC89B4\
+017DB81D350A23F59FAEDDD3C3A125A6AB46FDF3E8C12CF60F850BF651FDF60943AF01FA55E4\
+0B4D9DFD31442892B1FECFD0C7402DFE97F15F33AF0A1FE70EDB72F555594E67C22304169913\
+6F9D011231AE19CF6F25F5B400683D07B2C5E91BAB306EA3D7BEEF47F10A951BA2FD7022AF66\
+8117BA672D9A3183F908EEA212F5FBE3D7BA26BB0DF0E1DDA4FE80989659FF10CF5EC682E431\
+D7D9F0F232C39059AAAFA376584BBFC7AFED07FAE0CBC9B241BE0CE4A61649D97536A47CBD2C\
+875B9AB51D255684CF74A99687E7DB759056C46ED1F826ACA2BD9B0763340FDE52236388FC68\
+DBA8F620F07D2452E7A8C67177B1A51C74CF8C142E33D89B78792A9AD20A7402C963ADCE6AFB\
+C5D36592AB284BA52C11365E256FF4E9309F00AFF74629DE4BADD779E1776A7D797256FC667D\
+E3C2D11E27127FD24020C84FBEC99BD8AFCA2BA1A3641B97DCF4594CA0DA9BA814D4F73349D7\
+E04D3379C548245241CD5EFFFEAA0CEA8AF3A88162B9B83B743DA7E5998D8F00E3955F2F:\
+9503468A21F5695D3D070FFC76E14A5A
+
+19B7000075DF02A525965B3F59A35D09F38FC2FEF8564F7DD39C34D875C692833BB9547E1606\
+5EF7238AE95F3A39175BE680C63B91AA592C9DA6D6AA31372F25A3B95FE40DFC0E9B4F45C703\
+CE60E7A2F3700D81D7FB70CB958F58A841E0E13D431FED62A4298D73BC4D0935E921B3EC670A\
+1260C20FF7557609166D40D32A59AA67682173EA2FF7B21589A37E05054C413E78CB3B4CA675\
+A32B32CF92A63C3CB115340DC75C3C8E45F33AF4B31D8B4AF466E7E054AE8D447BF359E5BE94\
+A34B52D1FF16DEA89AD84811159D7A48967A29BD8840AF80677A15DBE3912D2BF2DB8F998B20\
+516B2197B7350967A5C2185CD6A0AFAB165CDE4C3D9CE0DE066B25EA297FC710B3CC21CFF4D3\
+2A7F7A0529DA626AA0A3B17E890D6BD1CD6E9FECABD07B8DC7D0860E45E5F3A071A1AF0D461B\
+0D9C94A54EBD84EE1B6D8F0FBB432C0A73212ED19B16461A5B30F3257C93060390C1D5A81165\
+F8B341BAD0057034BEFD47025024E04342099F78973E46F6E3946E7AF975856D28EAF281D230\
+77BDA73F1B908B6B88FB40FAA0164B3D6C8A32BDB61BF081C2C043045D2B2126E34685C87721\
+126DBCF2D226E2584A2C1CB67676C06EB19C9BDD7F4DAEB02289E748C0812723FE99BB09CF48\
+37831B59420363A5FA7E7877715273F7C48AF2CF03050C0AB2AFB8888CAE62F5DC8B705DDD85\
+1B8354A30D9323B77D9BC4167D2715AA21AA6D566F1392F574B5A23229F9FEA21EACE9736F32\
+3553C2A6F294A4060C7724C5D2F8DEBB5FC7BE61AB25752881ADE4A6C1C1B9230EC89D181C2E\
+DCD9C0393BB0E5C22CE3279B918D990368B95F9D84F98A7ADF09C4C8DA5CCA026D10A4635131\
+0F63913EF23831BC66F7B405EA97BBFA8D74C049C328FFBAE1BEF8AFB5CE8FB7EFDFCA514D45\
+036BDFF84045A911814E5B28CC44CEACC7484BE3C399028E31A585ECA083EF18182DDF5E95A6\
+8C86BB8249FE534EB66625CD7367B032234CBB52CC5CA4C49E233148156D45BA7A80BEBE4DC4\
+BD412777FF38A6A9CA268ED707C86F1C9178F1C51B69F3BBA9A751758AA2A66240ADFFC178B4\
+428830B0D6FF04A2183224B627DE686526D460A4ACF890DAED0E4D2F181F692AE66336AD4B40\
+CA11302F0D4FF97AA219B60477E2FAE0A8682F4B87D4507AA2EE2DBF61F76E8A289030959812\
+D5BF2248271E10BA6D83BDB71FA6BFF16694EC5F8EEFAA2642B3C1C661BD3C60035AB7E4AFE8\
+A1361D2EB0845F6DD37CD5F8EF5AE403D9436DAB73F0D3DD408F9AC933442405B3A4C2156EEE\
+E9E4FEBCB41774A96259B7C45F513AC24A8B8AF555355FACA9732A8B95062BCDF1A18E09F75F\
+4B3D7538117E8E8B449A212A4ADCA3C6724799E3B2AEE646F31A3EA29A211A4209F93161E876\
+E9138C4B6A4B654A08184A4C2330F2D7FDA7F9C61784E4FF04F87ED6F30D95B857B022A9:\
+4D8DB26DD443C4495849B1A9F05D59A64B88C3BC7C6A8208E02571799891D1BB268DF842E162\
+43738DC811CFF37E10E0279C828AC5922191D2282E94B551896B6C86EAD7C05A7E25CB5854B2\
+7D1A3680EE75FF75E5F5C2E421BD7F3996B19F5074A2DDC87326F7CDCD0CA4E56112C6242496\
+1FE8A8FC85CA6E56006E5D9BDD1A29CB831B9421E89C2038BA958BD00D596CC7F6440C61E922\
+1F3642920ED9E1634924986D9AC1F889A8B02819182E1EDCCD96F71244A9BFAA2097EBE53B18\
+222FC15B219AB3E410D7272C8BC8CFEE1696A8B90E2B0F9D4044728DF3BD8CCFF988D5C1FA67\
+9BD78D51453F796022E7CF1AF96619E999C3A574EC2C2822D93B4E0E9FA31C26429019F59D36\
+2CB996764D2246A8DE9398043BCD292A1E492C794F7E1DBD02E3E0E73E7CD381257C4402A8FC\
+6AE3E686AE844241F191DD557EE254E1E8AAC99A3E946682D317563C473D653DF8CD5818F615\
+651EBEEBFDB2E8E27F744D4B830C72B69B235EEC4AA2431F8F35B8C73C359B718161444425EE\
+5A70F8D965FEACD187ED4557B56260AFF9632E75E0609090B9F130A9A9B81E53C83AE23B36AA\
+78ABB50AD0CEF64262D7B106AFA9CC1EE9D5F61A6EDB232F2152902BF0AD86101CB7DECAE8E3\
+CB63A515468AFB873D8AB5C3D3F132C2BCF29C8EE9C98E7FE3037DCE5E1E365D0F5BC3319089\
+2FBDCDCDB1B9C49315319DD3F508764EE6CF68394D46A9AEA9DFCBB03E3C60E70989C5CB645C\
+E060445D2FB569F8A7176B067423EF657396CBF0475F2A79BDF714499F642A064210A538EB16\
+2C16F505AB6B2C101DB317DC9907BD8FC42CAACA246E8A95A2DA8270E2F32299039E36CF1AD0\
+AA880707318D3D998C5DAEA87A5746C754E3B64D121E3D22F2359FFACF08D9C5EA0AD2D6AB97\
+60B4189CF532686C8E137255C220BED27969D24AE1DB6785355E7C789FD8021075E243FA9641\
+2D087010B9FB20B10479D055F7B7D631F4B8DACC3EB5DB5338A94775F9191D8361D095E8B29C\
+56A8206E04CDFBCFDEB8AC953D3425F41E1A6E313FDE132EA0425BE42BE8F4903D3091B894F0\
+8243F59760CD9F3FAF8D7ABF567A927A99C8660AC55C37D2E0BE845A91A47AB971C684A28889\
+BA53A2CB81072FEFCDEC751E7D5A0AFBA49E31A110B533335ABE1A7DD479E20BB84B73E87BE0\
+C6255F9A961C68BB3648309D2F8BEE5F24D4A30B8690890F0BDF36980981FCC7BD98889B8DB4\
+087C1D0C20022018BCFB0A1B22F330F0AEE6AB795C099C214215003087F337F574DE917E8595\
+745DAE00494E4339F634F3A2E98F80380A05F9FB871C1D14719D7E95241ADBD9E60D96EA5097\
+8234BF71BDF5330B2793B8E546E075527A0965E60064C8AA0B2CF5D2EFFC063241D4363B1893\
+271C6B3DBDC266FFC7B9D6644003C1BE5CE1C0F78A7FEC3346E31CE674EB59046327070E:\
+165013851816370C99C2B47DEAE6F41DFB
+
+6ADECF136BF4135FB584DC375E92B88C14F8EC184BBE9371A97045A7C3FD0825AABD14A4FDC7\
+F587BB5C0A7695F738DCA4A3CF362058700F4DCDD4420B6C236B5B527FC66CC6A13543A51CEB\
+9B42B21C9EF4B368B541EB880A2AE8A7C3D9A94AAB6C34739180F07645B7B523B3C05A97AD09\
+3B0EB7010433BA92CA744DC5190C05F96100E79A3C264A4B81D114CE98AA84F6B1935EC21C5E\
+A5035756C10399BAFDC1AC3A42BE5611713F5FD764F7A6CF3DAA97B36733C1AC71F4B4C3E078\
+D95A05D87424689E70CA8536233D733FB9C9AF9813AF8670CEBFD81DA31D3F0233E0B8AC6CF6\
+5F720E5A8EC0447CCF961A25A68A1E50D2D1D0F87E0089EAC17D5E778243408A9CA33AA73426\
+BED6EF146FE083197DAFEE1E7E08080A82A61ADFA9E2B69725618C3507215A9F599B29E43E89\
+800ECC4AB9D6050B094D4E22B4528F9874384CCB2B87D91875897544806A1BE8E141EC84B9B3\
+410DD33A1DAB0FEF1F65ED0B8CF2C43307D86F210B652E6684E6AD5A5CDF581AC46E5E7CFF68\
+E80252F1CD6A8A73D13855D5C338B8F24C8A52AB4C635A7C895B365D296AE3B80AA73A514299\
+F996A574D7FCED7C249CF14E3DA02F36810AA148FB2FE42BA08104FA3C04B2D363D17FF53363\
+D2D33FBE9DBA4777BECB70692BE9DF4A110327E89B1E322B9384655E941A12E16BEB88EA1600\
+A5657F5C699407E132E7D9AE03D3F39D3F0E3A0FB459761361DF949020CE3B75AC49B58047D1\
+D818F3443015DA8316B10DBEE7F8629E901F63AA8D2EDE58E77CEB5C0A94B05C4D87ACDD3B97\
+6EABFA39C4A5862A4528166364CF43C608AE1862158FDFDBD599F8DC1B67A3B6B6FBC296D538\
+78F5A01F5DD6C5CE02AB9D4BC7563929BBF3BFB8C7A8F603925E99F98E02C3CEC3130959F6CB\
+9FB0CDE693A3FACDDF06A33E4D766FC7E01B3C67BA4826B0656BD7BA9E7CEE5504524F47EDC0\
+642B707BE5E11ECB84908B95488848871FFD96DA278AE7176BD8704836E248CF9F00CBFCA2EB\
+EA155D240F1708112AB0F31904FA684C3AEBE5B9F5486D8EC0ADD1C9A877F3B49E5DC7305F99\
+B0DA97D453EB9D1ED41DB5CF025100D048404951DBC804F9152B976C0B08F02D0117DE4FF023\
+1158697E4DF098D3BE1395CA873BAEE64C36FE3138937EF55D5F098276D20EB4F5D19F99DBC5\
+FB88D57890DB2728EC97D1FEDCD38F1CB2D05FA103B66F591D37F4DFDA80D7F11378956012CA\
+2F5E32FAA082565420EB91476A337CD813665DCAC92FFEA96B4300583C6461C231C7654C8CEE\
+DEB775FD968E5B6F2BE3A3A29EBD82AFC4E475FC4F71ED41C6FD825596A3E1D653F09DF2E117\
+1ABFDBBC70F69A7AB8712A03A807EE56CF0A2E2C1077F8C7C5C25FB1E981A1F837720742D5F1\
+91D5F0B8C6FAD60D4046794F932A03956CC5436C74E9400C6F40E0F35CF54939C7851B5D:\
+3142889174F9F5FD84846155E4A752B91E7A9E549EC7EB806A046E3ADB941AB1A188C1BD0EC9\
+E93D60A1164F440D0AF639CFD40C6E17A20B24D2012479FA01819EF6DA4306C0E642A0EBC866\
+E0BD1006643D120D90C50B224BDB742BC398351FF3D64BB7CAC968615CEDAD679F64C304B49B\
+FC7E275DC66C0B56817F810DBA4BF8CC0F9A71A26AD4E784918F70597474C3C2D7C526F4856F\
+5BC7A939B5F129118DD1980C2044C8C843312C0DD803E9618EC77731F0E601DBD62FB0A4B2F0\
+9DF129E054448F59C965DEEC1B04E1865662FA4BFCDB9DDED13A8FA7A6D594F2ADBAF45BCEEB\
+EE017D04FD1CFE071012EC258647FA98BAAA9628F37460289AC598962C1080A33E31F2ED07E5\
+10A15092E0374BE6520D892F0621E95D4C7385D874DC8D6A5B79B18E942DAD742073B67AAD20\
+7FF9C7F61CA858157C9164592DD268C6627E7873C13831BE7FD0666FE8BCB7D2BEAF2FAEF2C1\
+FAB74A8F2B8E8964BEEE7B7CA9F4C3F58DC3242AA6E40991AE32B082BDAB5E784AA9BE0C69CC\
+386D4074D4125CBDA87C40FF4B6B563FFD8431EC4AF544DA3232D78CB944592BF3B48F912F2C\
+E5B8872631CB34FDE7B204C0E661FC9D5EF02070BCFDDD4EDEFCAEE5DE676740255BEE02087B\
+8DA08A6242679838DF4263EA73C61FB73B5423427DECDC131E1AB0A485C87ADE2A3E6A413059\
+48010B49D03F1AB428243CC98C43407BE41B715752E9A7B4342C21B16EB9BD740511C75646C3\
+C5BEB0A8A66D2A640BAD624387D8B0889EFB7193642EB0E8A7287EDEADA7DB365202C1645B62\
+2B0EAD1A8BF2290CBA6EBE9937428A61F3C5C843997A72C4E1AA71622394533630EA54436061\
+EA3F34FD4259CBB3694BE5E5303718FEE8D548F6C9BF03EB82F5693F4152638A66116249E32D\
+68F02973258D516B9DA2ABE8D13C5F189D79A61284B6C0F4204E6FA9B8B7F0401E95B569C460\
+6F3E5D8619311129BE3D63489DBE29F47F4116E786A1312EC53540FDA97F8B2C118541D8660D\
+33BA282B7BB43AE1993DADF500394C519F32D2EC5BBA04A1BD02E9AAA084E127736C7486C878\
+C1DA4D82CF94CA06732723197A0718B99FEB0504F01C8B7BAA2F09BE0DF739658A703ECA0098\
+9A0B608F9FB4627D56FF08009DAC83876AE0856E42B24B3A5DD6DFF8D83CE07EBA0F21B570C0\
+F206238D44E966D63DC94A2D715C9A56A7F99309F8A512801D57000BC59E57D2A856CCEF243A\
+C153822FCBACEE87C41A75153B71ADA7B884B75AD7E5010FD3C9230230A2545E784FD029C0B8\
+6F81DC4E6DA708F03F6A5167C5C793EB8FC29F51A3263D67457A631B37D65769BC9A252B761C\
+2F3E982C4E9F1CEDE6A7E3736DB8A7433FC58136560AABFB36A2C3495AA8C1E0EFE79BE95CA1\
+C93F3857A9D8E8AF64978D4B0814C480906A3CAD1F34FE90003B2C7CA883977ACC62D148:\
+BE6281335EA5230E73E784D383537496C36B
+
+4B5B723AA28E9E0E919A276F20AA4375FC4FE86BA5E9A3C62BE3A5CCEAFA5D9245D4840F5CB5\
+0B75312CCA8A65BC43B4138379EFFDFEDBCC90E6DAEA4BE65ADD65C765AFBD0D4D76CEE405C1\
+2C56DFACD8B17A1F4C1F91E108C30E529B8EE8544A8B7130AECBD2C208BB841F5D50BFE6ECA6\
+D262BC2912A1FB4EFE644C9E64FAE643A9C8D554B6DEA630D4BC2112E898CD8C2F9BE95FAF38\
+F7263113336A2FD99D2FB5F3C1D0F977CFE561019C51C92A171D7E271FEC0EB225B55A776414\
+2754DE8A2F9145BD5B9FA8CB9847D3813FB5358043799C7E3A78FB7DD8938FCF4E064D79782E\
+01DEB5CFF083954A687EAA095169E02F1C8CC3B5084617BA9B89D542EF9B93F213DBA1B4ADF4\
+5B87B14394E6AF7C17C6D79F136DCBF909DF8FAF62AA70726998CCDAEC519AEF238D71FC031D\
+CDAB3E79DCEBE2A7A6241207FDF5B66916CE31DBADE4093222B0D1ABF69A9FA90F9BADA3373A\
+75F18625FBCCC20318B7B7C1339CFAE3122A7AEAECBDBF807D0C4C2BA882467E1FB72458B70B\
+31BFB10451202CD10AA31E12587493E66B5282B2D8FBFAD823472BEE1A66F63F0471E985F10D\
+A9FD43B7ACD6EAF23C56AFFC83192A383D9B69ACF3033A1216EB9732F88944334EFC31F81892\
+588F1D197ED9BCF0DD40F7EB3CC5A9C22CFDAB86CA0C89C638D1035C978A54E3BA544EEC2AD4\
+6A8D57AEC61E534139EAB0ED4095EA8CD5EB132DCA6CB7F988C7A6E0B9DC9D28F61781415666\
+036C39304A62C6482B851819F2E0A513DAFD2CDFF8C8EDC8B6A3966A2F2A9E7BE68655CCCFC7\
+68FD92DFB3565A28AB967CB569F940E09FED962BB21515D5C753ACAA3AB2F76C1FAD84F30CA9\
+5809772032E23E2FDE043D563FC07D1289989E9859CDB8074B361D06384C295B2943182D7C46\
+2E88E8E0C599D1377389602CE931142C5CB30AD4DB3AA6D01BAF616EEE1922379B30127C643D\
+59C134298BFAA172376BDEBDF0DD47B52879172F96B766E30F669252D126E5C0837FECE300B0\
+7EA6926BDECBDA66C8EA66B636EEDA74814486E1B3D20FBCB1B4F5DB0A915E3E4D2B1AE7C7A9\
+F13557110CDCC0E71AD28CDF566D97232458F01A803AF9BE6DA0313979D66791130A8E3CB111\
+101F8A2710D0404F32B0CA2F4677B5DCC34542B651491DD5D173C93247657C181074F68223E5\
+440D5386217899F939835BF19889AA6FFE59027A75A38B32CD6975C3A543B37FE3FC52F4DB66\
+BC012A14EA0E2EFA6CABCB6DE0BCA100E60BC25BFB54FD5B23DD0C1A8229CD0BE80B7CEE710C\
+A8598F6B6B5CBFE3F5566B8B15CDFAFD928851E07D6A6FBE26439F1719CA648ED6F4396310B3\
+E128A34C4D5A17CBED908A2394D17186ACF6F46848A6D32FBD5FD8BD14D320E5346CBB73D2A2\
+FDC323F5A6216559D7D0C177803FC1D9EBC9859F71E85E34D3C00A4C364068088609A5F7:\
+251E008BB0445ABD75C166586B0AFC536ABF124C9C7A5FB568EA647330B5D7EC79DFB57048AE\
+CDCAC37400DD26BE375884DDD8F7B6EFDC93DB9F62F393C1987C45B7857ED49747F7FA57244F\
+63F273F3B51D86FD2AF9CA6755568BBA9FA528E0FB43798EB0315653F495727914FCDABC0FE4\
+3EA93AEA5893A1E1A9488D5889D7D3ED05584174CB3CD206D7CD4C117933487768A3670E283B\
+295807C6B1E15AC03F46782D70DF796F3A9ABD41D8F1928502F7197A99AA6112919D7B6CE336\
+2787A6A770CABFD4650EF223D1B566B1A86EDC96DC294669161AF5FB414D6EB0912ABFC11436\
+9815BF5B9805EFDFA17BD57C8C28CD22A34EB7FA23A1ACDD32A66BEA2B382FBB29FD1DB18B8C\
+3E539B42A2BEC7A14EB06907BAADC0E003FDD9689E26712B3D99261B4714FFE846E5425B1BDD\
+90039FD225EE93C0310583B7D7FACD3CB9644C9219DD9EF05BB58394C6C3C2FAF455AD50558A\
+80B7C6D7C9F4DC2B7086C6E31EBBF9446665F8727FE0AAFF7C483DCD3AAB34EDD181CE00393C\
+93A28C280EC9F6513F0787689C3EF4B98408C110067BF3990553E902D5D3CE1F7C4473E7C9AF\
+84CAF731B5A31D5994E5DC9D7820820EFB514C8BECD773CBDF6E818DE24AA4E461613F7859DC\
+0BFAFF61375BDF20956F66EB534694D14DF29A78A0488CE3766BC85C1FBD3999765572889BDC\
+A13897C09FA11C10E2FC2B24C591B3E3DEFE7E0382166CB2551606876D98B2C77B01B84634BF\
+34C26EFE2C8B4C360DD248D63734ED6B7C9FE0487321E0AB25D428A0486404DABD837884572A\
+0B0E9F343562D7B767F2A5C94856E6B9E3832CBF063B525352DD472275103CBBFA032CE5D952\
+911F00BA5A6F33461D2D536E341D09C3C1F1B5C1BB9BC1014AD9BB25F2F19D4AC04347DC5440\
+581D4BACF25DAFE6B82F526736875EFCC056FD89A01DCDF72FEB0DC70E12C2243AB8A28F9637\
+8B1633C9BB08625584F10E80CFF77D050A81A2925231D08F215E381ACDBCF11AF61964185611\
+435EB7C70CC18A2810EDA5B55EF5A622F6484D8E579C7315E78F0EFEEF6E4C85A7712259682D\
+E4003FECE559542554B36AB37CBA4B8BCF07F88241665D806A0A213FBE1F98BCE2895D3BF642\
+0AC591A8FB947E6EF53780E2729F45677E06E425DDF65D545A9177FD99B53BA47B46AFD200CB\
+9301001B309FCDEA4CBF2E8EB9427C84EC9E560CA4748061BAEC60D6FEEF6E3A70679C77066A\
+428386050D6AF7A358A92E3357804DA0C61DAF3335EFB18750519B9B7AD2F3677462C5562461\
+1B8F0B4278388422AB646A90705AB52D65B2C6FC4BF295E59EE88CBF8624F1B03BE99513F1A3\
+C922F129ACF665797D56877283F60B89BE4DC0F803762F6072EDA1212C9A6E3046942BF97933\
+2386F83F4E6938A2FA6B951C4D419594A37C6016253B88DECBC7C9DD39E1164A9CE64BAE:\
+99972572DC537442E8C105AC248DFD511470CE
+
+A29E49FE59317DB85DF4CAFF962DA6D4DC94594BB7B195DAE82B7E32ECD55854762C857CFEBA\
+610B39D2F9D8091B38D6A225AD2A2CC2195DCD5A80ABD06CFD12BE30E914C1FDDAE3BDF398E2\
+3E994F6877095BD1EC8E48105804650D6F872229C7F0B17C8C9BB9199A1E137BA50A34D8A626\
+C0DFD6AF1875DB00A498CA6F36DCDA712B2A0EB8FEE3AE69F2B6BABB9D779798234165886033\
+D91F5B74E86A91E03513817FE24CBB71D4DCDB3D0AA421E7256E3F1D7F332FFD974403EAC2D3\
+DF374881F9D95258B29E46315D326F08EF18909B2CA4DB8526BCA9B06672940423D9B039362E\
+1CD8EEE68296584D94EEB2162C3735E099519F694D94EC732D59F4E1413601E8177D379CD4CC\
+788DF64CF234A8B1FCE575A803DF5FB44014484D7C9A527B95EDDE983A072DF17D042026DAFA\
+0E3B2328626AA8F84C8FCCD98E321C8012B896C32762FD7BED3F0636C6B9DBEE15EDE2AD9634\
+477F9D9F0C7F8287A1D1C77893E08A2F5C2590A6B8260862DC4AEF39E7A0A4993605064BE04F\
+F8E47E5659EDCD0AE97F800A520E587674F423728EE3A70DE8681B929CF6046551A6B90D13D4\
+9A8855A17EAB3F4C3BC4ABFC09A5D3A1876FF119CC8A75623DF7A8731AE551687FBC8E93468C\
+9E3FACC033A254E46A20AB8D0B9FD4EDE15AC81DE9056145339FFBB450F01CC801E5443229DA\
+BD75E391EE7C2A62678F851F5F1D6C4AE6FDC878B12608A218BAA1CB258D42C16A84DA809A66\
+772B5EDC39D0AFAD4EC22653FC98C15A033698F1B4671B8EC331A277B489D1B166759A0CDFB9\
+97C19CBE2A500F474E0C856B1583AC5C86A655208D2715E3D47A553BE7000C8286B749C850F7\
+15F99A971C51CD21AA58FC37ED1E7F2857B21E1FBD183AB8C5C29457C9F5072D5B94A45A5391\
+796ACDF93431E494D18958C79AD5FD9BE02D42C1FA05BFD360A62D43A4F07406A8AD0C677936\
+35C3EAFF28F24FC01360E4598AA651C35E9944CDF1A5A4ABDB0F925C03CA2ED9F3B0C4C76114\
+80023BD8812C47BD61622CC01FB7DD8255279C6B17A57CA938329B80604C36AE7E847D7624D8\
+D296656573A24970EEBA52BBE8420AD06E9D312F05B6FB5D1D45689A072701B0F39AA226A4D1\
+78876821B54430F96D480693E5269B551AC45D5E48007D026C451FB9FB9106AF072E7591C6D2\
+9803C75D5345A6BA0AA27A9DF7C7E15FFA47EA7AC241304B6D3D511ABD0E4ED9D56502204009\
+0ADA249C10EBBB9FE0F7E02922005234428561C7D4A96414443FFBC3144D4B354B50EE52DD31\
+DADDF3DDC8B7B2C221F631279D5055CE38FC5ED54D5D811D84EFD1413EF352B17C94CA7DA223\
+9398896B1559B1EF78C657AD8D6E968CAEC86CA22BF4706FC8CC1D419C6FD40F502C010C65BA\
+AC9394460AA133332E342904C7B4106D1B84A7F6C73599F7F3FA2BB0255E06C133556CA5:\
+C107C43BCCD34DB295D0C6C64ECAA5E37D50DC0A88275976E4C82D93527BBA3F038FAB94F84E\
+F875F0E8357E5459AB23BFAFB1DFF7926C7F17B11B47E93EA1D5E8DA1295C0378DD812A9C87B\
+7F52C21E546462063EB11767774C83D95730EB5FCD1A8DEEE223B95D6F4F5BF16C6A00B5BF84\
+F2DEF735FDA064DE08F192E2D240FE7A77CF4912DF51BEE784A36680F5CBDEF5B85BB912104D\
+6B0B888FDB40B4B90456662E1FBEDA2BEEF8B19E171C0B70B454E10A847ADA2C0760331ACBC2\
+3EDE26010ABB1D8166165A88D3F3A6D629695CC614048529CA98DFF0D801687587A4857DA083\
+2D14BC954ACA4E1FE5000B9D37D2DDFE89115F43811F2DF4E73A31B7A0752CC80ED33C53ED53\
+B1E333C2C9EB63843A46B2C40D81315321B657A2426711DF4652CA64EB671E1365C3F32AA90A\
+29441709B77E7D18D9F2206B70BD91ECD39A2B17240508BFCBB2C2EA04EADBEAE814DFA98EE6\
+CDDF7F8023CDAAA12B5E0B6219EFBAC1E4E4D108AF25ED9CCCFF52859CEC02FAF3E809413859\
+EEDD622BBB2B45570364E8205ECFFA530BC98F464093F5A4473FB6C3868CC1691A36CA4F4AE7\
+65312DA992E74135EFEAC2F5FF8F8EBA3B17B88247293D6C183418A50E5C06722E0721FE105C\
+EBDBD404714E23355EE78116FE3D0A561EA5C6DD06F509EF38B31EE88B941E13682A3A54648E\
+D7ACAF6DDAFF80746363E7F0550B7A306760480894F6D4B9C449C714F9DCCAC680A494E07336\
+8C04450FCDE296960C0021F05774C2E53308668A2828BAA39CB4D98809BD852A3A3864ED1370\
+48AD86E121953199C35D955F606CCCF2AA11FC873EE4532F884D9C5E72DBB48FC220D2FB3E53\
+F78BC1DFC39F8631254800A47C83D85953DF95A58FFB94DBD5EF36B456E42C513D083CAF5A5B\
+DA7014759CE8646EBBB99E5AA6F8B996B5389DEE8D4FE2F945EE68A6FEEEA1DCE81CB55478BB\
+87C60EAA1F2D5D7E4F0380FCE0ED00FFFC05F60BB1B685F1E9AD0AD42A7330A9A70F63D54BAF\
+837136FB53203458919882F2F67EDCFBD631D0EFAF6AE2DCF75193C6891A164BAE455E1BE35E\
+93FF1F907B049D56501EA27DA959792E9716F7357182C87E5E68A78A92E603EB82EF4D175445\
+7504D07EAD8F6C13A855A2A458FCFB3D6264BF0C8C79BF7613A1E703E44EDBA5FC4424F86556\
+BC98D89CBF9CA2280F4614AE53AFD3B31BC0A45AAE6FF0744ACCC3579EC6BDA9EFF4332F2EAE\
+C9EC99024D8255C72AD5CA75B2E97004717D04ED6484B9B13B1F3BD1E9B39B0762A5560E8F02\
+DBDAB9BEC8972B1283F4267E55885DDEBF764E26D050D9A148AE386850DD857BD5A3568A0FF8\
+F172F5B9754CCF16D1BF4BBC6FDFE79A51466E9DEAA38C5EB9144AAEDADF7867D7B866A7D76B\
+5BCBD25165BBC7392A3E51ACD40F71919957FC23E19ACF21C5B62DF36337249CAE5FB22A:\
+388E2850F2A8DE89492204876A7DD8A3DF568F58
+
+40F2EF525F91C2B7A8DB54A86E4CF21B08EF3C7C34450374A358FDE05B75C166B02ABBA087ED\
+9DEFCAC5C38F970EE7B83E932FF490B7DB64C8FE3DCDFA7105C5CF67A159F3DB52A6093147E8\
+C8B7E066723912A8E1D8B9618BBEF57B1696B7DADD547C246F74912282711303E22FCB202171\
+F5357BA41C6D5B5FC32D1FBCCEF5B0A090670AD75C15A7469717FFAEAC7BC588A8D9DFD5ECED\
+D786BDE5EA70762CAF3F2A159CB1FF8DCA307D2DB822C2DF5B1C3D81FC9D992781B6D5215B3F\
+4442537E1DB75F3CB1DD53E2F26765F9172DF5ECF9A0E572774E8448ABCBAB3A63176B7A8090\
+984C5EBA6AE2CFC0872AA364A5A90F0FE6C72AC3EC5873FB84B908487438242C8324CCAD23C7\
+9D03928832C3153DA6D5D5EBE50D00F844B85928F04DA60B3D4C2A81C9DEA01EFBCB94FC7FF0\
+B66AE81E2A85D1C28C5387CC2B6549AA7B6A5FD940E57057EE2B9A98D490DE3A40FBD493CFFB\
+B71D0FE44F58110C2830DD18AA017C0F45480C7B404C73A3FA756C807C8C569C29339933321A\
+74EB2D1001754C5CDCDCF80C8CD3DDDC5E64BA3736FECA5FD9801B54EF8F6F780FA4AD09BBBD\
+B87DF9A07D88B005E803AC7670B236F0C508CC874D120BE45BC9997CE2D56B55F94A547172E0\
+46A01C18A63BFF3BFA7D60FA49D1856E002B36EF6D38DF71CD1E45CD6FAB59264F6550DF8459\
+1FB7145BE757993AE5B9327CCB5FA23C2AF8B35D50F17662C6A8CFDC0F0B47270D84F4CA8FD3\
+5597D18C757D4D474E788098B759705567A1740818D508E9CE6593191820F1735A48B7C43806\
+28F725D86BF1324843A4D85C2DDDDABAFD0EEC45265D95FEBE3F9FF87363F073F1C96E569861\
+5E9C841BAB30EEE72D2C559CFEDBCBD21AFEEB6391EF578B8E6F393577D9B3A36D269E65E673\
+FAFB0FC582DC899C8145DF1DCBBA1689E3819DCD784106EE6642945ACC8C9DC44E45015C02C4\
+084416CE7E19322DBBD5FDD55B35385AEC50308A4CF06EB4261A638D681344F48DA7CB2E0EAE\
+5326F54DE4589E8951B7BC42BE7994FB64AEFEBDB7FBF8949E6D7FC360EE722883A3D06ED3C3\
+C2D0EBC6AEAA0606543888C600EF69C444F08C1DFDAB3671F44C85B0BAB0FC91712D50C1AD97\
+9F32C25F3C9CAFCBA9E8C82817D4A1180EB4766CF7844A27D47067ED7376E071BC7DEFCFAD0B\
+8C138324D77F54E3E41D4BB8C33892B84860F97468223D3F155B04698019256A11B2A20E1720\
+E6F40BA100B2D887240F78EF499A5C253385EE2D4A491CAE743FCEDA6C1A0C585992167B6039\
+954774262A9F604A972438AA52C4228A4A30C7830272AB66E23458BBF3CF055EBD6566832951\
+51B7C60979A87D806432FCC107C5F533C32BEB0D4C412A0EB7932840B1B1414A3B091BB69201\
+589E2BE699029E09720285581958F71A350A24438541F3D05CD921FDA0FAD525BFFC30F2:\
+59CFBDC7D164AA6051360ACD53540489ED573B013B52305E530F3D51BCF8FDDBD35DA519C9A0\
+66AFA8E8D38E9AA32894EBE216D09C6B28454B2D1CB1E62947E3C7A19A33B95EAE69B6158D7A\
+179EDDEA39CB308B36B8F446EF02AD0EE039225376000A6717A27D8C7692E3D9F210B521C561\
+A8D46E022D56BB93F232FEA37257EB30EF41C92C727126FF7058A7DCA2C5649C3A5AE6CBDB5F\
+B9C5CEE676885A27773433E1E3756218041AB4F95E71771DE5D52E40A425FEE63C3D93A0886D\
+4C56E69E0C01954249210F792B19BFC25C3FB872EC1D9BB94CCDCD695F43F5D7D1210A803539\
+AD9B68BBBF893FE055D715A8EEC0A289D77A3FC8FF9F2B7B6994E476F16988E6DE7E002F0083\
+EBC007F0CC0FACFF5E0238ED1C0598CACAC390FC03F75B876E8B8AE1F35E1A64D3F2635ACC52\
+618004A21B0F8FC204AAE2F8A84FA419A930D266C619D4F736AFF6D2C1028CBB129C355678B5\
+518645316A3F9C38E37707548CD38A24428A989E14EABD3AA8D3BD1252496E458193C5CCFC39\
+19602987E4CD4C8264E1B8279B598A910C235D7FC9C861B517B59ECAF0B797F18519420A993B\
+016C9A6728D707EE7EFBAE8FDCAE866DFA3686FB5C65CCB11A9DB7C7B3D15E8A747679BC9DFE\
+B2177698BE98A216514009BD1BE3C62A0234252DF983DF15969E97F99DA7913BA518C52017B7\
+EEF0B789BDDDC3A083BC1FF8018622CD3455EE108FE7DD5BABCAE1E0E88264016C0A1FED524F\
+EDFAC1BAA8D9D4CA330A27128E2F774F3134CAD49A41548D0BA303717D8EFDF9EBAD46FDC719\
+24FDD61989E1516E4C2CC6AB099CF68A3721AAF8B4FEDBE794D2A5D60F3A618F1D4E697A60C8\
+8014E0A9B465538E82FC37F94FD368AB1B0EFA99FDBAD037F2162554C714E1A539F5DC35E620\
+CF81454912E92943AA12CE4447B83DAB8B75EE124A34038BE4297D8C88C6DF3EC8361912B883\
+D4BEBF5858F5116A3B8F9A818E0C19B42D11499A70A75A577E46B9793BEA5E6195F23394EC4A\
+F1F1F4BBBD10CB1B672568795AC479865C4EA8540BCFCE77F78C7F0B0600693007A5B69B6827\
+5617DC6ADD55B5192D6A4C8BCFB8B822CB6C9DC831C4357AD605ECE9F15C5C3C0953807E65FB\
+3E06FA59A8FA4314111564691962AC895715053CB22358A69A2DD658F14239C4BEA0D1940F7E\
+786A53E1390B74DF3B176D54272B62B1D61245B958884349A7ECF2ED98198244DD0001FCD5A0\
+FC8B3302B0B659CD94953AA0C3A0003E74A074673E9C3C39DA5DADCBEFD0A638CB7B3711FC17\
+967E44C01B65A64EDF9E9A0DC1DB5E810E8D3096A959C918E9813E2934C8CAF1800B55C623AD\
+350FF26006E97919D250C2EA700A54231E28FC85E2193162F4783027BD86F859B01868678F2E\
+1C911F23364E350F4628570FBD639D15F30AB2BDD7512BDA269C631C3D4DACB0B3FA6F84:\
+C2F4F2996C7BC1F19B88BA92B41BC6F42BB4DDDE56
+
+1F9093D9F61F1FBED0E57C530B3A38755A4F8E09AEE810FB7033F47E7461A4B6BB2EB898EBD7\
+9B3BEAE94B0BA1F3D43DD186D33F7B0469BD9357B4A8CFF6CA3974D795C11B55F7218FA5F7A6\
+5AB3799F7CB571E670F12C5318F734B9A63C0ACF016214EBEEAC2FC77961BACEBE48681EC078\
+C933C24B2A1431AD0D4910859F98BC3D3CFEA2CD07D5062639D5189A0C439D3E8078669B8123\
+EAD0038B9B702A82260014E6A07A965C2E7BC16D5AA7BF8CE23970677144FFDBD4902E4C195A\
+66811CD6C0B3E6F38525B3854620F1FA4B2B699108CC090EC110DFBAB90C289C37171414AB86\
+AB0A1F09EC28A844B21A2A3803D832E3C1704339CECA91B93E98014124E15F7EF2ADA34C2267\
+C5FF600385B6176C2E8DDB02266628EE51A58716F1C6ED39FC82553AC1D646B16208601DCBFB\
+9C75B1821BDE1BBCFCE0EF4134759D1CCE23DCD4BBAFA24D5BAD86D09AA3B9EEDAFAC4B405FB\
+DD6B107D6C65B0BE3194F41EDCECBD1116C19ED72BAA7E1FE91684CD430E683D72AF2E7ED471\
+D210189E9651EEF40943111F5B19D9A05B453006E32323A9489D1FEA7EDCBD486EF8CBD8369C\
+B342048F63E0A8503E61C17A4BA2AEDE680C48834B28B43A7436AE84C1737F68E0E6ED6983CF\
+C17E33515D6C2303AD08971F990793EF2F6596BF67AD773104BD01EC4848122567C6A4BFB0AF\
+C89122296839B9B01A603AEAACCC0EA7A8C0801562F50C107B9FF06990DA929B3A6FC51955A0\
+010FE2C412044DFBB519B0BE5F151AC8FA5A3E537276D8C6D18B9666E607C03E886F74D9F4BD\
+3BC20122C5A111E6CA07C14D3D12D43BB80B5D3D69C11538A56A9CEA77FDCB9BA0A73D992B60\
+64F96FB32A513E310261E87BEB457382A6897334F486323F90D85620C4AD93A7F88A3F310513\
+ED54A38743D9918C4B12714373734862E6EC1E5681E85BCFA8FF283BDA08D7333B95596195E9\
+4DBFB5E65EBB0DA07A1A913AC2E936EDF3075A8C6CFD07C80E60B3254C188ECD0661A4E276A3\
+DC4A729E6E5FD18AEDEB28B81694421885924C5D6CF5EFD257AEDCC39B1A8B88406200D19BBE\
+E9AD2346117F576F5AAC7A82BCDE6CB19A1BDCC70F335EF6543E9E25F157E189EC8624DC3B8A\
+6724DA2691E2FCF06CA9AC2D92E9335B70248EC33E8F83532DBEECBBF4B1158F3B2766BBD2D0\
+11C931005FCD3EBE3AFB23F252E19D12AB9304410DE599FA6A4D37EC7736155D92B668D7FBDC\
+BE5C2CA70536A5D401822261801D9D0177C81287A33984A56E9FA0DFE02D150A0A3A223BC86D\
+2D7C0CC50E8FFE77151CB709D6514889750165A2306E7F204BC0571BA1581F4059DFFF9D748E\
+B45303362164B24C975926549EB6EC3B4372530DA1A4E3293F1B0403A0B7C0C4EC72F18AB1AD\
+83533791E8846191F0D27A1B8BD6F91A3A8012A18E3B34ECCD8374AC203BC644ADAB06BD:\
+22D743189DA67A78A29148D4545DA4B72DE285A43B42D9CAC731B34D12DDD16541A0EC412A77\
+5E24EFACA5C206081E5C3328F88E2BB0C06BA703044E05CFFACE073068830D9C856B2920CC6B\
+006257796A7FE2ECB3CE6644913FB5AE98F6476DBEE36936D386CAC9C39B0D9766CACF5DE9C6\
+0084F09B36282DE5F109417FE711E0425BE00FB55620F386C81F0EE91F4E2306D8D134A1A458\
+13E36DCC9F045E4C7A18BF1427BF5C3780E3EFBAFED3E4714A6EC62C0309803C7C187F97C780\
+2DCA176EEE313A574B49C81DF25E427C8C373A9A5EFD6B290AD9EB6ADFB52BD7E3A4B86B056C\
+E75D50AD4564F5755A00F148ECB36673985F8F17F084D75BBB251FF261C06BB1972EF6F5AD98\
+A8221AF8E962A869BA395AF096ED24B58B810C7449E20DA628A69B69673278C6A1DD2DFEB5AA\
+FD226575923095CB6FD06A1379404945925B782A09E25FDAA51ADFDDCF2F8384FC1A8D53D36C\
+C3423099B54B03F0FBF5ED17CF363B140EDD3B4C20B982024A9E4F26C1B330D2A9360B737A13\
+90163E7347EF8FDC960F03C5F9194F8EC838CDFE1FE4452300548857F424ED392CDA3D88F831\
+58347D931E87E11F938BEFC178C2E191FCD5D1FB6087D09C2A25FCF65AC3286401A908420472\
+02825D6BBAE5D937E3117F61C1E212BCD6520BA984C04D1A9A03AFC01793063AD19288FB9AE0\
+324106D305D9CBC1AE8D4CE73808911DC45A3D543B8FB87347E5BD3103E95BFC51245DEA0C6F\
+4AC7E9D40B28CFB48866930D91464C1B602238C7E2C4752640F1B4344DDAB38C34BA694B93E0\
+9DC086FC49DFAD08F37C1F543B2768806C39E9386CA47DB9373EECB375BAD545DA04742C6725\
+5668B63E2408C564DA1FA44EC9833689DD4EC5EC8AA1525137CF7E935F079979B7E09E211E60\
+2A991AEABEB423A939FCCCFFB9EABDD6B03F24D2D0DE2D01FB40638F069234A66A7A60E3D667\
+6A82D7927306865FF74D4456E9B73E498B88CFED4C0678613A74440886DC0A17F948A1FDA388\
+7C99DB2133EC4D8A09CCB6DACE059373250F8BDE5EFB11C3897D592E1B9E080C185A4ADD3C9E\
+047C5DCF9781C228F194DDD075423D89E8DB2053FCC1DEA35FFA3909C791447E1CC85A77B5DA\
+82D2E012AF8D2C23017219ACD2E4245DE9197A0F4EB43EB3B203C930D48287321845567AC0F0\
+1B639442715A07BDA9457B38DFE779905990C0CAD83696514BF524F889DF87031B0CAC938265\
+18321921523BFD2676636DE5526C3D10C176AB27012A609992B3BD01D822F11AEC3C88AD3E1C\
+AC3F9F42FF60D4CA0ABC2BC93CD8096D66C135C4FD6E7835F506D26FD5C0A4405FB353FA10BA\
+DFDB343419FF6102052362D5CB6841ED111E55B7B609195A36A6E79932C363D7924E6725D28D\
+F66FC871357EF8F78CAD93AF7C20B9CA1C9590EEBF12E15B1A2EBF02D9EC43A78B7C6AFF:\
+B49715EC3C39DFB191BDD75B46A2151C033FEF2652C0
+
+8EDCB7A73161A699F571C3E4837B05B8510F8B47C6177E293F376EC69B607781280EC24A8EA3\
+F1B57C6D4A842746A35EE44B86D6463997B8F506168C3395ECC8613E1DCC181A26CE0B541551\
+511CD570D3B912F0E7F10EE18E51B9C83EEDD4E81FA6F14529E886A5E6F3D1A815847881DBB5\
+D432745CC24D2BCA39ED8641F35297A46ABFB5E06FBBDC9B23404B42B4F6122E0A29DD945AA3\
+A9374531E60CF973D4E42B5F21385F2BAFA38372DE67205335EA1BA7B9C6E75F85C9437E8F69\
+D48524971B6FA192D6476B16EBD6434A9C802AAABE857389A9538870B7A17D1A62B2033AEEA4\
+C84666EACAAED730D8B7557C7B3D4421F0074372606B95D74518B017D8725E691995E215407F\
+51C745B09390AE6E7ACEA17ECAE1C9786AD70CBBED26A522D215B4EDDD5C5239612BFC9B400A\
+6F33AB66F5D4E96D497E0BBA951084496D8BE3621DE03754321A6B2A9C4394B04FDCDF606933\
+0D5651177FCDD78132ADB1C52910BA87BB544713911CAA9B8491907AA9F1FBE1650A8B03D216\
+5A97E68AB092E26A03910472347D1E12F9868B39B872F3339FA8817FD5427F073527FF6642D2\
+0F3DAED64C670598BF3E6163D88333F66F0D6F50952CAB037F29F2C6F5E7985C5C23CFC1AD2A\
+051BC94F9A0116E28B6075138B207DC639FF8D6C96D4ECC9DA9B5365FB61338EE7F398862A03\
+D70819403DFB08301AACB19D5E20BD17A428AEA172A63353D6EEDB8B39003912ACF52C6D6EB1\
+832629F151835D3F518A2E018BA9F9A4D192EA9683AF1A726403BE65C1E97EBF80E55CC8BF9F\
+DC4C7692003E8E5E10B62179A669B7A87E88B8395255344609DE906F474E90A74EE6F88D25F6\
+022DF4BB9C2491F20D0A6AE16FBAD102CDA4A99214BA494D7105CF54D34904C67B76A73B75AF\
+F13D9F9597F07B2C2A72103759A6EA6571AD68AE11BEA14BC8A02EF623137F349036DEB2B105\
+8A26C58502CC55629F3E5EFB9A3F30BFACD1BEB34D26B73666033BC3E8957D5CAB95DB5BE1EF\
+3AC844E6179F5C3DCAE207CEA301937C7B6F6392B7A3C885E291A2772B0F9998D98853623177\
+79E9EABF3E5281CAD5A9827EADCAE9371604ABD85BB9811E9DF0A7DBC9AFDF8C0D2AECEFE899\
+6A6B8C355C49E5638230CB00B552BECA580928987C7A958F95AB3E4C0EB30D2C89C2946F0F7E\
+2DF961C02F8DE4676636A0EA87D5941DF710C55EB37EAF9E2D0CDDF0406065EE6877F259BE55\
+11853F777BCFF730E642C671C12807B4A590D59D40D69C3E4278A32EDC63658F47B0F01A3361\
+136AF4F777DAC44AE1173BC71812A335B8119B06F71324642560A609289B9A7AB6271AE98B3D\
+3EF010200C4222077110CE34558F860C7252E96AB61127F39C9767BDB716EE2E812F9AA39577\
+AD4820C5F3580BAC84D6186C72D11DC2B994F72E7885A08CBAF3D6CDCA020D86B4D885E4:\
+7CEA4FA938DAA9A9E01D791409298E10C3921441647AE602446766820A0059E6289EEC102A51\
+EC6C884E2B007052B9FC863EE06E21429392E2AED8831125E8AABCF6E184BFDE646279340448\
+F61F1C6351FC6739E088F4213A63BB95B38FC6B83BF38B8FB45D27FABCEC411B6F18A8B9E3B0\
+F4A4CE3DA6FDE2464FA8F37AD06C99362CCB716DE824CCB62EF8F5D8873D8237837F020C6797\
+CFFDB23E004D532E3640A0869577ADA434FC7DD3C1D287083CB2547CB6FEEA2AEB3774629775\
+53960FB634700115D677D2C12DB25AADD1DD7D52602CEF1F8861E291CECDDCA69DB08D98F2EA\
+CBDBFF1FDB7EF5D08B704FC6C8F7B4AAF2A62A68267BF50FDD92FDD106C56393CF431DF3D7FD\
+82A3517609D32787DB418E2E41C55EED489E3186244DA744D5D50FF4CD71EA8F58C4CCE5D84E\
+BC4D5A37BBF7A7D93994B3B8D41F4D2D2367A4A8CCAFEC61F4D1D8FE637C9FD275CCB15B0496\
+4433F8F0A8220EDA6D3B0E96853447BBE97BB9EDCF60899896A0829FD2D0E17389F5A55FBA37\
+1C55E7D3E93F27ABE89474A243B2867A1F16F474E6972FD54B8A683884360159F0F8109D05EE\
+799731A1C36CA22AA6D0320BC9B25FB1FBF9F1CB98886CF53DAF959E1FCB277173339C1CDF59\
+702E4E3894843C336B1E527F5CE2D2DA9A22824D68FEA16222810C42A78E70B574BB1D5CB42A\
+A6E318EB0A71E415E9CD0FF6E98001B16134B6AA8CC258652E156B16407FF5F7ACFB27FC869E\
+A07835E38F4476B4D9D014CFD6FE90DA6D9D64C24934DB12D6237F9B782BFE0537F30E1B3115\
+D875DB468721FA0201541D4EC6760C6E3E7D0EEC428B34ADB6F44928739BEA013996A9AF4E1C\
+E74585C8BEED9A8C778633753930AD8A05589138B647828E01A841524B1A87071B77532D7DF3\
+3173AA606A196DAC31A26C3B7225CD18A0DDFDEE85CF90D8C2796B1782BAB320116101A63BC4\
+B7C4FCF336968BD2DF51D329E6BAD996923FBAB99E9F198E067DAD4C8267B0B80587C88E9773\
+755D1BF62FB694AE313DC6AA85A4C0740E4983E2527E5CA9C860327BBD67A53B9DB1FBE524F1\
+8B422F8DA23323926ACBE1BF751188C01264AB49F0A3DC5107E85C2F5C3897B9DA326D04BEAA\
+8C9DD5490938934855E67C3A0F34C5F74F25D710BBB4FCFF65AFEF6877E51B05739CF64573C4\
+F18EE1D2C19CD4F966C8A037B93ADD684A956091F82D91EAC6D929401A660FEC7A969B2D4D44\
+523362F50CA7EA5D37E0047384F24411CCC9506CF1484F8583344EC6DEA320784C5C496CA9BB\
+D30066A57D5452AA33CD03D041638DEF81D2761DA24E2AEFAA6A128E86926DBEF4F6CD832A1C\
+0E120B0F7E10B8C970754E5E0919A4CDD9C288EC9316E2BCE4357B8E3B708C8BDCDBA04080DD\
+1E986317E1316E95A7B0DB6C87DACDE723BA6E59277BCFFE4607ECB5B8FBAD0340631D7E:\
+A0B8CA1B1F83F3303578B0CCC449871843D7C8360F93C6
+
+DBECB1C042AA98E8593629327CAE8C1984169010D5EAE745ED9122E71827818ADFEBE013E774\
+ADDEC8A2628EBEB1473A8864E2FAB7C9973553993689D72166197B31DA18F5B0A95363F4E765\
+A419756BDA665E66C10DB27D712ABF7146ABD48F9DB2638FF3CB3099FB0BC26B6CD4C64A6652\
+63112AA378F6A093C11891B641C74D2C0F816FD5E52F37F01BF84BE64F9AB3727D8031213A79\
+1F9C6BC1EE49A259CCAD511D5CA26DB3272DB3751D73C2E56BE46684D6F9E952DB9DB1C9E879\
+797C487F56993420102418AA512F50B1C1339ABC6FC13E905DBADFFC651CBB420D6D9BCD7B86\
+FA66083DEB317FB538A5381636F73CEEA73F28EACA590F6AEB4153B5DE87B25A7D58A7E89659\
+DE2673C751343C72CA13B2B5ACF96129DBD9587DC1F427485DF9D75366C099F186B6E0821805\
+977C728C11269C4650DC21D8ED1ED60CD00C41F0A362B9E8F938A20E7B68B51A264750D4F825\
+3CF216D17DE03191360D6C9B33CBE7D2ED1E6214D0665C34D03EF11662C7CD7B25E9CF939B05\
+C77943ADC1F8F4D3B861842D5F4B147529113C414A66269CFB33B0334D7C18A80821EF56C151\
+1A2079AEC4A2C9E5A1FA2212A358CB5D994BCFB43042D5696F895A7E2F24D1F9F1C9EA37F56C\
+2F41824B1A628FD1ACB5D0BA64B858F68816C76B11D3154337E49BB54CBB894E7F4781087FEB\
+75123B50F59D34E12E99D3BE1CDD6C1167A45D4DA1B5E4A0657BBFABAF3CF360C1BDECD6C5B2\
+9F268CBE1CE12A08B7C3EBCCCDE1521CA93C16259ACDA418D48319BCB93AD13F6E379D6CA25C\
+7277CD5CCAEF1EB90B2036D6CF7BDE5E64CD038C469F936F56D86D2DDCCDDA23810C2391958E\
+FE7C76512F66F11F44B9E9F1CBD24AF6E5A728D01C7FDEB95A17214C48F52938404BDE078254\
+872B6003351A464D824424DB0D573BE4A2A8D836F342022B87097F8D20EBCB3AC56D26FD4720\
+77845CA68200D60261B79C4B60C6477A1A597C81E72D09BA38BD4B0E5E692B436CD1B541D4E2\
+E72C24DBC766022ECD4F6556499AAFE062B260E104903C4FE3AF208B6D25A5738760B2FDAB52\
+D1A5E66B7348F7172924E15E0A4F00D0FF01F6504092555973DAB665AAA68D9E6E54141805CB\
+409FB511507C66F76578C40A034F7398D88576B47AB98EE94CD18CFE6D99471FF56EE064B70B\
+224A43E691AF4166D97CFAEE55A6B73CE15FEE6AF7214D12C092A5FEA66EC489D868902D5293\
+48B212D5A478A33F918974620818C12CDB01B150610C1A2B5DA3B693617C64FB9D084B293C3A\
+1E460776A5ECA6CF50419B4E6DB18FAD314F0C7877213FCFAE640E11B4D64B0EA1801D0CD7EC\
+123A9EA0E290872A8238FCC8FD358586EA73F2A065E0C9B8BE847B836077B6F3867F23539AE1\
+9E6CC3A245A059D1C3A17E70C68F92C69AE400351B9AEE6BD3E896547622262D02370247:\
+8E536C2B3E9964DACDEBFF25C78DF2B29CFD2F423E3B85EAC810F536E18CE420763AE2F07E9B\
+EE944437DA35D5843BDA0FDAD0F5C0C70474B84402D56B7CC1EDCAD0F6FD87ACA8ED695BB2FA\
+F60F916C401BBBB744B0C6BA13D12C8557EFBC024441AB86B0E63B40D86082B51677AA296CAD\
+65B16335740DD87F75614A2BE2A025278FABBC19FACC257F01B395D803B3868177AB0E8B258A\
+931A9F41F2F3D08EEE08B4A8384BCADC8348B199443853D97C2DE47E896142244B123B98D22D\
+281F6C5999E7ECD0AF5DEEDA96B65041807A7520BAD6525F9D2F5DFC19630297C5C738510C94\
+78C0F105765B0E15995042A8E1F255D572C14BB7F8556E45BBB38FC00ADEC00DA5F7BCA78B26\
+B8E38B37DCB845F968010DF7E908078504D4C6B09246140E27044D9796112005C878C983C27C\
+0ECF9C12F2ACD41078EFEA7B1BB1CC5A6A288B3D2FA67E2FFD0C42046F06862CCFBFF191F435\
+07450409670E3076DB2C6DA71550DAC99861E7D011A3998D3A27A268D93B09DAE44D7263DCE2\
+37CC7D136D977DE988B24FBD7A0AB103669733E4C1AF667EB71961F242C0E5551DEDF1037FFA\
+037BE420458B8921D59C6076F9DFD257EE563B922E703846F709E8498C584B9D2963C16C2160\
+7E4E3F4A8E72C41C54A51EDF14BF9DD69A78EF3BF0F0420FEA75D62BA644389F5DCB01D95B5B\
+BE6A268ACBD7A0C8FCFB7BA6076EDF1DB4BDF8DCDCFF73E5D99E864C78A6E909DBDAAABF7326\
+C572CBC82DAC8E276CEEF2E75A29916990B1C0B9AE8E28106233DE6EBF15407BE06D20B4C201\
+28F15FAC31841DBE8CFDB93EEAF7204BCC824933F80615C1123419AA8E28737D11AE352C36D2\
+F69CA9A348EDBAB3952AFD8136B4FDD2261A57BE6C42206742A8C54F94432D480A52DAFF7ED6\
+25E6F5D1FD5CC409392400B80D62F1052190314B64694003022D154F7B12FCE34E3B9CEBB498\
+1A722E2C344475134F9685DD95BB419ECBA2AACB502B28747665F4A1650A881B37F6D45280B3\
+35E68AB613D826757E1BAFF076E0E45CF5899A73384EAE2468CD16B12B5041E736723A771CA1\
+F93E80FA664BCE73A5D88BBEBA76DA2FB3521D70FB06D61532EA28D7AF279BB6C0EE77FC3EC9\
+C8C4B1652CBD71D64FF5E55817921E5C6088F0BE653A754335D9A030C89B4AAAA3586E77D8B2\
+3D969B5D1BFBE7B5E8D0C4A612B38270E51A63591F7DAEB0815DDE403F7ED968FD1077F94270\
+94C5B212D03B4DA47C7E968FB8F982C81398BCCA00A304A1F098B451D9A2EEA2DBF9C2561097\
+F0C16666C8471FEA676CE01A6DEA5EBCA591C509C3C0C943F5AAAF8456E1E98508E5527040A2\
+8DF9F3010AB8DD3C7EBF25BD7416BF65590E5B3B3BEA45477C063B90FA0207D56D716D2577D3\
+F5808C4C40941DFEEE64D2AA91710A5B2169FF77E21369A595F3A1EC1A956D916DBBAC22:\
+E09C01FC9C5EB8AE01A145C966D18B54D86962C307539BE8
+
+510F5C74619D838446DFE399B6D460EC17CCFE8EB1FB0A32E65D6C8FA1C36E2D02CE83C39603\
+AD466C16DAD9528CEE7E3644AF881CE6E764FC8F6C96B51B7E3467D9E52A779F091C174748D4\
+9BE6FF831AEAE0D9317DFD0F9054E6F6E9AE61F491D23860FCA94E6E99260A7FE8311A91A337\
+57B140B9E08EF8CA4CB62EBA23FC2001D5F817F861A901076DCEFC95324E426F839AE0ACF452\
+7F70EB3C218FE15C2FFE7CB522F7F8780AC620E6E86CFE47C0F37ADFE0057A9E66D4DAB6B83D\
+1478D57819291CEBB798C1D97363337B15188705FCC6108F1F4CD55B956304DD270CA10BE504\
+FD93B68A7224C02A065F2877D93CC48FEC8A5BD5969629BA11169F0812A6C268FF5D09346F0E\
+848118993F240F25FFCAEE40FAA3CA451F08FC167C5A2BC3F2F43907A03B116BCC93C7320C62\
+B3DB61039CCDBFECC1D9686144EE8EBB884020C5D7B7FA8AD199CEB512EC5224149A911A96F8\
+8E6F4D000C72B20CFAB17B0028876C777F5ECE01720BDB7DFB73C2BA43DD77032B1A23712439\
+459FBC5D539C63A16DC168BAA923784AEFE68C403733AFA0C9B70101358EEBF05C81518181F7\
+ABB606FB180937799D256437281984017D56AADF3CAC1064FB198D54BCC5FF354961B1C11845\
+973F93BF878080C3206DD1976106EFEC6768DDD4A00039168E00A7515191A1C06145A5460BC9\
+323AC9204AC1A4AFEEE7CCE1662C034C63566DE3FEF9671FB4277702F4A3429B2D7B8FE1B7E0\
+34E00B2CA548DEFBE7DF7BF3B77FCBDBDFBBC105E375E9B9870E7FAA4ECA36FC6E25A6D4E04D\
+1001C5E0EA40ED893B59C6E7B16536028CDDCE2DB3ADF756504A546CD7CA1E97FD83D7FED79E\
+C25DC4780544FEDF3675FAE8474323A8BBE081C401D097572E02DDFD088117C7DEEBED761490\
+F812A2F2FC1C38EF62B597710655AE6C28D290D003A41C322654395FA3EA0B5389B3FBDD5EF7\
+C9D3E159924FE179B2B8C25F36EA1A26D883DE42B2B800C9629CF99FF280B9ACCD51495C60BD\
+A9E6963EE0007D86963BCDD00589333B7C84B8474BCB2BD28B6B5ADAAD16B452152ACBB951B3\
+A603283623D2A445E70F991A9C5C5B883237BB6200A47A7D601915847AEA550F3663CD366A33\
+981B123BA770ECE42ED5B933FF829682594422D1F3341D04120C1FF547A1F80C08F097E64D50\
+F7A9E1E2B28638543BD36A603C40ADEB9CD5453D572FC0309516AC24763303E652C170DCE7E2\
+F30CF22EB5C8E1ECB222E1EC2650334DE8C7504985CE290A48A0702EAFC9C5752E87510484A8\
+A4706AEE25350DE1D691547CE9F474E440FD3A8C22706F9362D8F4A6D7F2DA1D3B6E458FAB7E\
+601C0811A10FF6BC5CE7AE7B5E7CCB9FEF3216A883EC88853340B306336D58F744659D67BF7B\
+C738D0E89FF18C7B386D786B111B2C90BAA220267A7454E5229A4E800B94D2C9D78C8753:\
+C813B0E5702C0C6DE3328EF88A7E1F823ACD43EA6AE2A3339FB3F40E71DF4085142161B6414D\
+BDCA3450B5303E2489E7D0A943E836FFCA6D99C473F46664818F5FD0CCE69A5B0DB47749C1C5\
+B85BF8B93DBF8685ECA343B7274800D757C3D482E9E27DFAA293C37CFC4E6A87A51B8E283796\
+8D9D71E0CBCA79D7F7CA29C849CDBFE3C0E1A67212AA88D55C2667E7E18FC77ACE1325C6C497\
+01D0E51BDF69216EF105FE3EE23234EEE479FF85DE0451F0245515DA9C7696EA7B589922D44C\
+65DF23DF4FD437D2A68130EFE72A5BEF60754D7087692B09CAE3D964CAC2CDF2E4E47152DCAB\
+D0C1E9EAB1ECAE68001A934EB8BF08B35BAA4857A085A477AAC48D3C33104712947053A3A6AA\
+E9420761A148F42AE11F29507595DD468F9A0B24BD667C58D52E303673C5BE286D9ACC26FA8A\
+401E8B4A2FC327BBAD64E7E27FFE5C9ED91FBBC7EFFB9DA538121567D934F43B89A10A9086E6\
+94818B3F9F076BCC04DF8BE4C39E0C8FF4891E45B0147D435A946BD2A099C64D4DD6E3BAB8CA\
+C7A44FB825FC10A0CFCF2E07144BF92513B4B468F89BD04B451A59A0F36B0B1768C8520ABA30\
+6EEBB7BFA6470BAC3C99F570034C3B8C73824A14719AB2A7C9177176C626447F2392DD1CE5EA\
+E77F66F3EFACA292420E947C96074557912526ED5340A282581825055327454110F16A601058\
+77F16346CE130514CF938DC48AB7C5B6BB5814860EF7342087AA12283BE3F4E5D052740F74FE\
+A37011E2FAF3A991F6F64ED4D0B27359646AF04177033E9A85A70E1292EE24F17E3158605F3C\
+4F5E50115E3FAA01584D3615617EF0A78B6301B4ABF79E0F13F227C03AA55EBECBA7253A74C6\
+DD3539F9A9651AEEBC0444A7F2D69F175D757B25B53006CC424947AD0FE57A722B3B5C994992\
+74AA31A994EC8981A18A29695414CA397F3EF2571E165002693CBA1F54A72B9A2E0E0EF83C40\
+18C864472474A52A53CDEF878471648D2748FCE41CCBB9B55A1DF82AFC07B378B814D57EA8A6\
+F60F8872ADF7D0CE4FB942424602508D1550711365BE45433656E1A4734BCE2E1729038BA26B\
+9D3BB3D47C960A7E1A3286A41632B47147F533F8514A799B96B740BE43DF9E5D9596DE6FACE8\
+F75517B97E6764D700AE9B0F4EAF9259DDCA66972EE5CE74D376D59D9A7F921D92E172368191\
+CC21FA0B367A8522F9A05DCC89776596BFDF7DC34B71B2171E8D74F8E87E26592E84AE240DCE\
+A4F8236F7E13FA1D254EE7CA048F36DD359733A5097090293E676638C54348DA584F38BFF03F\
+67E61A38331D31769D41BC04C8EC73CFD9A66C95656F87563E17BFD7A5CE3C1B2BEAB42BCE01\
+7DA00249A77AB05EB39A99999E8C374FE9EFA7323A542C7ECE218B1005B100A171C94A5A7169\
+F679E0C89F6AFAC45202B3344F1C1F11FC749FF120A7B1B2E30DF2AB3A1A20247D8EBEB4:\
+BC7974BF2DEFA077AD76ECF9B5FFA109B688D685A736A03F42
+
+A3878B8AD4FA1EB390BCEBD93724540756966688C1ED1F877932E75D50C1253CD20E79BC6FA7\
+1285DDA89BA56FA95BFF11E2EE1B171DD95F698971B3B850EE1BCB8EC181C3921A8D9857203A\
+2A96260818B0B7807F1F93C32BE2DE700E75C81D3EF9A515B708C516327DFBE7C642C14238E1\
+F2E2348F92547B2A1F8058E467611E3D139D1616FC616715754E8593678E32A49B2BF820BE3E\
+55AD895B388F43B587596103A3A01271DAD456205BD53C03BD8ECCD9C7182B1BDD24BEB7C845\
+CC775D56150DED9E059BCEA42AF4072803778040E1CD33EF81A21767006D0824C90185C54948\
+8D9092CB0EF9175AB351B394786611C6CBE7B47F1762BAD1F39AF185B9FBDD3DEA790D1BF5FC\
+A6A80E4EE953DC61C54F7905F45F373AC9299C67C9A543AA3597E84653C43D80D11BCFCDB635\
+E12A846CB4B0D4F82CBC40DE236E6D8DA39BD9C90A03C8C9C47C8302CB53518A2D7328BD0463\
+B2931EEC975F3699C28C8B2A08C3C40ED78931C6FB807441B0B154F8EB0F8A0D811482864A3A\
+755E96C62CA19609A63AFFDE31F11A65CA9A98268F7797E883558A9221C57F32E126F156945F\
+E4AAFA2C5D9E4A2B383794F23D0E7296613DD73558F5B16576E7D8F0D87D4F2AC6D3196C2827\
+4822C648175C919559D85C13B97870FAC56C5151CBAA305CE02A23621F3C50A53E4C39FC6ABA\
+9A957F32DEBF5DF62FC34BFB94B186D376EE4FBEF617EF511AD2ABB1B3FB8CA56735BDF60D9D\
+38BF4AAD71D91F194DB1B8AD003D803402B047CD714EEAAB30C9B7A672958265E032CD9F1BA2\
+55856CE3CC55FA29589610624F25A68AD3A0B668F69426C5D91D17C5FD721628B0038ED397D0\
+A0D88D4436F317E78AA05446B8DCA1F3E7A1B16F754046001146487B06A6C1DDB8C98D3D0727\
+D9CA9F5A99A428C63018EDCB49D810BE4C3D77E2F006F9787DC1C0745062A4AB11734EE71175\
+DE27FB2FC04502E1A8E127E374FBC983227FD935035DF6D99A99C9700213EEF4BE0AB6DAABAC\
+727D6FC09CF528795E7FC36481EFD8E982AA5721895AC421D73B902B01CA30103AFB77594F8D\
+62B021C7770CFA088549B8B6292481901AE54D542AE2B547A41C8A2E54AD264A511965065E1D\
+5352CD37E0F0E9A17A0A237E894618079F5FDFF5019A2DE7037CB7073426F1933FE7777933D6\
+F212DB8C5686613D73A82C070CD06ADD134CADD2C746B8B175CC73DC606F0F2206B269E3E2BD\
+7070AEE53EE4BDEB702C8F5474305D3A99527779967DF66785AEE17CEA574FED7250CCDC111B\
+BA529548FC52B9FF81F1CECB530BD3A5D8799DEC62074C0C5F2927E0AD6677CE90B57FFB1796\
+D9F62157C4D4A0FC09F4A376D8D6E96EB58AB67073BE683E1A0B3DFB6BD5331A73CEDD91C104\
+DD8FBDEEEBF4F80CF2C79653947AB84F10663621160D20C32D60F15622EDBBFA4B1B4435:\
+30C59A448D99C6CBAE0C75F3012A728713BC357DCF1E814FB0E164F2502D8E1838C20A053FF5\
+41E0D51EB389D0932357DEA124126D40AA8EED077239B429DB16D18FA4537D2694A7E78AA8F7\
+B5CA9E2E4C62379A860D4BFEF73A23509359517C8F191C83ADE0351EC54855449441952B8D83\
+40F9A8E9692B79C9E52A48F55F7D281D5A093DFC313E704DAB8897B35142D3055E2B26816D11\
+8A1B2102580D87E888B5BE5C26E00FC6BE2A8A2DF05E35D0F34B43191F1A5BB5865D2F9F0695\
+B5F163F5AAEB43A21190C81344927DE4DE397DE23905509F4A94144276EC3085E353E9409BBB\
+FB4CB4871F67C11F93E772BF800DAD9B56CE49ED9E807A7AA2E82E9341FC5531EDE9D39C5DA8\
+1158501B0C0A23894E04418DDF6B3106FD980C676E65B7599197FCE7BED861FAC3E3DE4B6113\
+400933C276733FF335B725889885D1F05B104D60621E823E9E1EF47FA982445FC5F5FAEDF701\
+BFAE44EA5DAB480861FF4940C13D9E4351BCA2B84C21FB3EA23433FF7F2E9C56DDA92D645180\
+E6EB610B39309ED073A700C891BA183AB048FD285476EAB85042605B2BA614B390F5B0062647\
+31E736D9D266A56B62344A25AC7B95F88A53916BC0A764B373CB04ED7B1F84290A368D2B2F37\
+E794CBCDDE38AAF38915C1E0035B190C7AE546C9C3641829FA089F3E454373A90BDCF7BF5FFA\
+1E91D89BC026C28B00275EF96EED2A3E311CE73A3F8BE58C5E30380D67E55BB16CFDEF9EB6D5\
+2FCC797C0C017A4DABB554FBB4B3AD7D4EC0520EE5CB63BE6FEA34F8EF1B9B94CFB1202F4A1E\
+D694ACCE6B5D0A07147F0C15A554A6B05BF0224092A4CD3EEC46DB5CF93706D6EC1184AC2280\
+9617A6A9FDE605794947A10B11F5EBE05E674DD48908F71DE8045C71F345D22851607353201B\
+0B0B0FE0744063FF262B91894584784D216E63A7E0A550680053C85687C98DC8E8D31AE8EBEF\
+ACBBDC2AB15176136042A72F6E80A12168462723C42FB6F759392F40E4C38C74685B164A7AEF\
+478CCB598B39F3A84646A945CBDCE3339E369720A5BAD10C32058C07F7AAD768A693B3CCB9FC\
+677B5AE21CD4EC66992B8D1EE676DC0108A9C2E4344FA37B1AAC704D6A9AEDAC68741DE35FBB\
+8D103DE27CABEADBCF06E214EAAEB615051528456AB7477CE95BE4DD899975806D8F21055CF4\
+5DE6C98456F5A8F0B30AC2647B5A61B7A10BB77C91D7353541CCDD5CC98B24B5B6CBC28AE123\
+713AF68D9352407A232E65316400C25647840F0B60B8172325D3338561B797A9DE775C847A28\
+8D535E9A42530057487A8D4DB74A9E8D989B1A6CE6A9F66AC9121B8FD1FB4259275CE1BB28B8\
+25D1825DDA3330AD4AFD6B94B166C4C2B069C77B134AA105857772657A42976FC1B671F21B68\
+67F6F2F79DDA6AD5E207602B57055B0654FAF0ED455F164A7033F6B91E28054232030D56:\
+9F442E3FB2EA592A0CB7B0CB8D8CC4EF5257C2DAE393C21BA0BB
+
+C3E72DA2352F1272F2A862C1802DE449E63051F6D9DFA19260EA094B450FB888C40A82AB5283\
+AE400000BD786852E0A9502FC25AFEBEB3BD6787887DEEAB68A7DA7614A9446772DF7FC0BE33\
+BA1494FC76DBF30F7894E644FA1DF0191612BE7516420A850C46CF65389CD5AF7C5A534E7A40\
+CF76C90BF322166E26057A3CEDF2497B57742ABF06774C0E4A8675199F3CFC5DE26402B40BB3\
+CC303EAEEAED2F7AE6A0ACBD24D54549EDF40CF1EC6180B59CA17D4568201D211E400EF9D47A\
+320514F62404B010F730D40A1ABC45D4FFE475997A8692202E88D8A4BE2E3891D41096AE609A\
+19105E5CF74CE58EC9C574F0815DC470DE7E36F3780684EA0CC402610327879AFF283DCE3FEC\
+687D4F4A58CD4DE931DD5F3DE319C93E775BC417C29E6DB8B875F2F441B0BF7119980322C071\
+AD77B723E0823C5062D479820EB6D53F9F39AFF69D69C741C8C1C39EEDEC6A15336E0F25FE17\
+92B17D236C0567D14703F6C64685707C7221DF34EF5E3849CD44C3199C9D7953F132C0DCDA32\
+DB03D1A1C97511AE7A6D440277CAD76332251201B1E2FAC46EBA667C2905C00206145A08B25A\
+8FBD1478084E52300BC8187B3AD4EFD51CD7E2AF440BF7B61C52BDB5E25B2EE89E186F8FCAED\
+91E557DEBC038E3E0EAE0F894D89F1843E12C9A450721977D74ADDE7DA2F13C4D1F20884F03E\
+BACD1DBBCCC6815FAF755554DEA59BBE56B54F3EDD76220F35F82D9EF760A72E5EB70A20F45F\
+9458B2F42CEA0068133321772EF76C79760ADE842ADD7A9449B30C9E88D9B707BADCCAF72986\
+8EDD11B9460B39BEC7605A54CC156AD27B6D96A474D183EB1C0D2C5EFD388DB9ADDA2EF38B06\
+D723A0E11D94D0610701E20A8DF084F8AE67FF6DFD52A8D7EFC25D73802540FCA4C7E99008BE\
+15BCF36461FD9D5D3F66AA25510DB2DC7C715A5A1D40ED8DE77F3145BE7918BE39A579BB1AD3\
+9B64750436A2619A96094EBC67B6C7095A9CE54D32D866DA097AE970C5254113940BE9E89497\
+97F8F0FBD38281206D2F36AD1D4E0DF47FF3917173FFB99652F74EBDF85E0C26BE6E88661811\
+F285A02A8995CDCE78820711266D6A9ED3B29220DFE13D7FCADD3B3460903460EDC6C877BFEE\
+1705C0688C6B19B8AA29A712864BAD9D221A973D133317EBFD85095706D553452A31E9FA1C2B\
+18E11269524A8C585D0D852B5CEF5C20C898776C36F269F09BF33A645C860460263399864151\
+F13B10DE554AC09EFC791652451FE761D93F6B159CA6CE312AEFE8989A0C173F0C9C3D185DA1\
+ECA468B1C246F9EFE6D8CD7BCED96DE3D6E6F34ECE1EE378AE4A3D386EEE3775DA3192617163\
+DB46D1E7BCE606B6A43E07A9C17C6FBA952E2A6EAC4DFC3D4D31B447C85750361B9F08B0ACCC\
+87887CD270CF7A898B8C0DE907E28337F9E011F20E219D313E3BFB708A3273149DF69193:\
+EFAA6D16D871391B565E2CD61AC153AD5A52CFB19535E0F0F0C0AD361D70053885367ABDDCE4\
+8793DE9FDCDDAA35ACCF7E99D76A98DDC4FAB05C31A1F39B971F20D2AF515B4EC62C686AFE08\
+6E7571EF15629281B76988CAE44892015C3DBF8F44731CE3D2C862F8A1B0600BD7C10B6DD5CA\
+276FF73AE22C411A6FFB7177819132DF0C012675B59364231EC6222A270F80004E403C20A63E\
+0EEAFE8F8B1D7F389F53A27BEF11BD9486FB83678A971A49D584405C9010F1A28EAED00FC2AA\
+F4A763659C28D73D0F79429A65BBF18F4736DED48043CC8D9E4BBCE9C8742FA66F566CDC64B6\
+C77F0D4C5EB39C45B65B748F86E00B0A94850B4A3EA2BAE4508DCE0C2C040032E714FAD46A91\
+08CB9053E5DE1108036E816027BB28E8A4F9BC8FC4E0532C0F734247EAB51C3EFF525FA160F8\
+2AFF051E3E0879A5C0B37BE3EA7FB811CD473D711C45DA6C35A499BF6F4CD9A61FF77FE4D62F\
+F750EB353427496F34C46741A612597BEFA6E78EA7F73C3A9AB06D66C46E0254F5BD2634FB8C\
+87B188A7ECBCDA62E7C60A60629EB89630760DC9946C898FC6A8FA1CA72AABB45A44EC09EA7C\
+B7A83E32088957703617C53FC8612EDC540F2B9F12263EA3DBE1C137B7401C4BBC79601C8986\
+02E0FF0F9FA82CC31CDFCFC876C8692727982F95081B21BEB36664A103D743BB4DC43FA4D886\
+853C555787BE2EF4BCECD3F960271494B3272FFBCFD15DB4F13C808B43A93B18FA2D412ED8EE\
+94798D45177F25B64BE91681901FC0067D78CDE05797968A4A5A17EE2DA3B13D05CCAB6C9BA1\
+DDA97AA52B7D54348C902EEC725B2F27C0E30F080FEEC33ED2406172833EBCF7324AA784E34E\
+EE33987AA71B631CC63577FF8DEA298986EEA883FF69E95EBA40D94AD348AA8D92997F4718A9\
+1A963FC2954D6912EE70297B365133822978C251E4F8A3CA7233A6A928E36D0CCC15BAE70BAB\
+7D6FD849F2EE215206CB09E91A879B475832EB839A19032985A3AD58C99E89042080B4BEBC24\
+A4643BE342057385E33C6C08C8C66E9E842051B5D53AFC272EFF54B6287CA60A54A45DE35B9D\
+83B0ACF58A5EF76A9562630DCE413E2650AC40E6AC286D170A0FFCC03EFBC6E19F0BE6A7A694\
+10F019FAE61CBEEDD64AF69D9346ECE739B4F0DF179406293B16137510060206B34D47069ABB\
+5CF345E8273C6E614B9140DCDC7721920FAB33FEB009E51A1A65E2A004C5E24FDE771A4FA06F\
+692D8D8FF6E41CDC2B6CCD81E001EA39E529367B7CC7DB6602927E5A7916410AEAEE2267545B\
+79E3CFBBC6CE1EF761555E387524990EF18539BC4B69F65C5E7F6BDBD4C304105C7436F445D6\
+1B69578ECFA9DDC357BACBC0919C2A796B17778EF65FFAC0D55CA5055AA2042B00B1B92F9227\
+B061EBAB643853CEA690A77138B4276840E895EF691370E6A36434EC092A815FDFB12AA8:\
+98D9C8D2899042442EE0AD2507DF56B749696D07D2B3BEDAB9D13B
+
+70FA4F489BA7A72EBFE10B8A591FC75809D116425A300FD9DBCC0B8863EE25A11D531CF58FF5\
+FF93D05346FBCE189515B84C8AB100CE6B802A340E11D522EC771C1EB4071A1A3874674E285A\
+C4A8AF302E95BCFAF741B3FBE85ED098EBC177E509FF2B120DD48FD41C914354A8818A4AA8D3\
+6EF2926CCE7C71FA19B0FF67ED6B9D2A3AC3FDB6108E3A68477C92897891176D4B03D4E26292\
+B79FD0AEA177B0F058D3F0917D642D39F4DDC8D02773C1C75F705529629E25B10E465148C498\
+62B0A89F1BF62AC70711AD6313387BB0185E8AD71F8CB4244655011E7170A304DBD9D1FF3EA5\
+CECE7C3207F3F94F838CB61754672BFBBC8F9F7BF255012D759E6A2E07E90C7DCBD8E0F87FAF\
+CE0B095957A07F5CA27D6754F3B1FB5090D4F971486F533BE5012BF3C1CC4ED7F7963854EC84\
+932B8B0DC8690F1402E201C0821A345CBBD7B65BBA2849287B4EC1C62D822919AA1F1F46CCE1\
+ECB1E01FFA7445A38B1BB8A7AB84400159C8B1738EB3642F6BF12DD4418F2C2A4B5262891F16\
+E5496561C6348286DD2C1DE2C8FC1657E49A0C039AF09DF56C5EB561DF4CB947FA0A932A07BB\
+0970B3FBC018D9B17A4CB87AD93E51CB2F3CB13164AA6C3FD719419F4B67D1B03E3A9308FAE9\
+D6DC94B4B1C0689C9C97D9BE77D395071825C3ADB32D0702109F702AC8D7B762DEC9A1AF5038\
+59F98F7AE75AEF4691F3A55174623200205D7DE038071CF8B02736C99A3A18E92C10E866F6D6\
+9F416EAC0EF9420DAFF040BFE3CD7AB9A240268C03B9D66F603C6A1AD1254D736BA669F9350A\
+EEAA647D3B7FF0CB3456A9C39EA5F936C5F6B124281ED41F760BCB1E49056F74142A0F6A6BB6\
+4B85958F8B25CF7A9B90345ACB5C3ED17B285977125A090F7C7FA391DCA1FC2F442746EDB895\
+C466D665C949BDF2AD3E56049A3F62C916987AA911CB3D72969F920FBC4883AB0B365109502F\
+D5AADB0DA1B79324D3299DE64C6944776C0E9F575DB1812C408FB263F7CC7612007216741B5B\
+397F7F3E7CCADE3E9F9A891FA1FCE70CB46DA29E520F7E7BC049A954D6F6997E82A7B49C1E98\
+0BEBFDEE9AC11D43C152988C1BD90B9E643A1761898993BF642B4465DC05D87FD83F1BB98CB2\
+6F1CFC986DFAAF1BFE98096C65ED8FE76AF4D085837D46F63AB58FCF5FADC6E098D319AD7172\
+E0B2CD6AF62E10C41A46C5F08B2A401C212D49E4ED6F7A372B5565D7164897CF6CFF57E0F25C\
+C814A1B46B01C78D76391D76EAD6D9A9F37B6DDE47BD32E153DA5CA8AAACF436D4C91BD5BC85\
+AC9550D4181A3FB20F6B0DE6E136161DF570D6BC72C52AB743BE670F3B83351ED71F3018B333\
+6DD861CC0DBA507BC2A16B6EE7E0F29E7472772E7FDF47DA7AA4BA19253CA2CB69BB5EBAD19F\
+30C6321EDB5D908DFAF162550E06BA90276B9901BAC6E7F1F21D9E7E6895396ADD9E6DD5:\
+B2511B9C8A29E538FAF6C9FBC0C5EFB8B53548000F3B69A8192D1074ADEF8A589A68F0ABD991\
+5F869AF21281EA9910C20FF08006AB2C558FAA5E42D2C3117DE89C276C1977E36EB8DC80AB91\
+9B142D35ED73382D4736F9135E16F58B64D5FF75D235637AEBF4ECF8677F214C039EA29D2B95\
+37F88B9B20C20F590B26A8394A2B9D4A4798EBA65EAA6342F370E732459DF8A13BFBB49F5331\
+B5B0B60526FB42D093271807F7873DFF03F5303725CC3E2AA847EDA1E413E8D11E9B8BC85C9E\
+2B95E14F38991CB01164EF054076D028D9C0AB1EFBAC1D0CAF727194DBD817A6FDCA84965434\
+495FEFBF6A5B28D8E816680002B03754178FCA6C5EC96FC069D30CCE54307EC1EF1D4EEC73F1\
+45240D4BD8C86BD1C42A79456683A8D1720B24B839ACF53FA450A5A5AA6350E8DBEF67B8E072\
+F1DEAC1FF5940D1BF7EFFF618DBD461C66298EE462230CD07AA44D1B145432995F17EB6BC069\
+6F9260614FB1839AAD3AFB70B767232EA053D3A03AF278BFC4396B31176082A97E96B11E88ED\
+DE6E419BD34079C5E2C0E3063EEA2E8D285B11F886B1AD177DAFCF6C5159ECD12393743FB6E8\
+734147DC08F681C79B8ED889ED4BC2908D37168604740F92F13C8407A2F7F1138217154FFB55\
+4D1CBA031337867EB64B03FC343C35CA899E2B279A3879F1A282535E53B7C54E1429FADE2FDC\
+31D371BB3A0C6FA886E592CA9E3A41864CE3B3C1A4C64737A835C40678F2F22A48BC2F02BB63\
+462BD9BC8A0108DDCF3A96FD4426EF9F5F9515ACE83D9B37DEB30D9FB6612E1F8509E7B55730\
+2A86F491A6DB9E7BF4FAF867D8237A491D41EF94F36A691892275248AD721092A5EBE87CE010\
+9D497221E17B6582A0C6AE2E6D9486B8CDE0046A196FE4F6E9490D2D3341DA9AD473BC94C341\
+E1B003E5579CE7C07C8ADECD38AF583A226EB1365C853FB512F27B25CBA25FCC210F3093CF7E\
+C680A2A32CE434E7AA563236D86442E7935DCFF3050681CA2CD516054DA3D94C159A935EE03C\
+96D2906391BF5128D82FC106A2948649E8AFA0C5A3496F42206DDEEB12168A248B4066D9939C\
+036CB94E54570B18E234429EC67AB15B8760EF62053F2834DD41667C3CC57291C7AB37395908\
+7A101AD986AD201A7BE01E79DBF19D392DC119796382C7F1748D86418110309C27451A89F111\
+24F41F8D497DFC0874C9618C8DF99199D2E366E7147E8DE0D84FFB122BB24ECBA72ED6F42AC0\
+E0A4B73924CB2E193E4DE685B9C0C557F2AE0441B93838003F59A014EAAEF999B41ECC3E0A9F\
+F58C38406178BB2271F2DFEDD3B8F4611E1795755EC713F5E7F4967919BD21AA336E767FBB31\
+0E2B305EBEC9E3CFD2F2DCE6F2695D29C3A69AEDC81344D1975522B20E2A39BDAFE01F370C4B\
+21AF921E5D39A47D5F9D0373F69BC94E154A95DDA966B83E9D72AEE63A3C3F01FA45F7EE:\
+3EDB5024B4439FD8463FB27E72DFB2A0EEC2A108770C9EC58D91D5FF
+
+13AFF54F5FDA5CFB464DA7CB2B7EF98B3E19DC7BDB50302DFD044BC96A26F889A3C869F861DA\
+D16F832D9095855385F7CEEB11C9FF029E270A82AA00B71D62951AB702C24BF5AB04E72974CB\
+70E575995F093E28E3AC8B74931B77FA74BFDD704E841D3AAC4C3CCD41829B052ECBCE10CC90\
+9285F644CA5EE801434B95B7BFE1E8D13B8BBF0DA6D608CF438409B9A5BEA68CFD03A0C040DD\
+53698F0CCC5A23AF583848CE756821435B9DD99B431CDB9EF5419B8D595260CE0D129A475CB7\
+8105EDD56C24B55860A56CA0A404B695852637C8220E7B26CABC0EF8477191FE4CA80356D693\
+DA691FBC7881AE3740D17740B5B39C01FEA3463484A016621E1320D2503F1B680F62FA2F45F8\
+5D9CE530CE7456257D86C68198338BAD10CFF149DA46B4AE5F4B4942204DF5D45887E8171581\
+283BF27B420C99314556C74FAEEE06FF34492F7D6B9E1DDFB4C7B0C68AF0DB1309548F3B0C14\
+DB47D59CFA2B990C67AFE1A68E765180F7F28B9A022FE1B9D46BEB9CA70FC84848C640BD2658\
+22BDBB22ACF459A83ED381DD01C1B4FD8F560EBAEFB47798116BA55D7401F876F841DD7CD7B7\
+A868D8E25F177C856F9DE63A800FB38DB1B75A1AB8F5DAE7F17F78158ADBE74B74F55BD6D2A5\
+853DDB39052B7F8320266734019EBCC808EEAA974B9B25DA57CA946FE338E551DD1ECAE44098\
+5FC7EBE545C7DDBD2DD6D9F8B998460788C1B9BF031A3919F56D425B08ED00BF8B413A094D88\
+F5BBFA5C080D1E9988DAFC03CB7DC3DA3963FF91A57C35803263821EAE880A90F4A50BE0E253\
+4498E8360AEF2E6DCDCE3BF0C9B44B865E82B26644010A5560E0C94E6C12BA664399849B71F5\
+27F74411D41D408C938805C3E9674B8854B8505EAFD47EFA6157CAAE3CB05E11F2A689AF1449\
+9895104A59778EF19385D6640466CF19E45DCE6B7367D55F802AFA2BEC0553C730EBFC603CDB\
+6BCA10B5066BDDB55EB6E81AD2012D7B9802ADE7A8AE708CC5816CB77E52B44648032FAEC763\
+942C3AE1B6E226F2B89590D9D738A9BCBB8D8F1C92F3F5C84DA4628ADD590E71AAB74E91B7CF\
+558459B641A5F5496B93A973EA4F40A1A3DBEBBFCFC01559B0F081F01A83074C16F101E46563\
+9B159ED430C194DC78D398EE03B779D978FB4BAA7BA417B12BCFF174F22F71020264B5F49D91\
+0718DE1EBACB8D80DC7D45882EDC842DAE134679F60C5D59A0B8B71082009A5D0C335CD44389\
+9E62A2D693EA93F593F1CB33A0519EFB246421F3BAFDE66A44D6061BEDB0E93F1C5DD6CD6D22\
+864FC0407664349C83AD6C3362978DC255F0C9DD421D9247536401887301E5BFF9286FBF0D71\
+ABA606A4C3DE065FC95D282209ED7A18221969C79147191FE629076234C62995A07F9550CDC5\
+201966645DE98A12FB2F36AFE4779FDFC1AD49A59992AFF96E372AB59CFB056A37F3CB56:\
+7037C2E54E86E1F52D497FB4E60229BDBB7357FD617924EEA72AF90D68BD5075267A9B02B8C0\
+2EBF86782C0B4BA174D9FF66014B2AF61184C722D5398C531218054D7D8F30EB6FCB0A871115\
+2AD577B2D51179E6266173B6F4CC868AEE184AD2C39D06432AA31D672BB75FC710A8BED7CBC3\
+B3CE303C13781E243441E7B6A1B6D223A32D4472EFDC8E50F6947AD601F4B07EE405AA66AA71\
+313612F904626550F6DDBC71A24B3FD9F036ADACAE04A035C13E2DF78AD9458174DCF3677776\
+BAF8ABDB1668D39F4D4B513A2DFC8D36869154DF1D3F45EED4DAE86E77090FA21B0C2514CE24\
+EAC2A0D928EB487843CA5431D3C6FF527BA67D8C337DAD9163EFCB9001E027A4EA629624474B\
+112EA2DCBC213365EF44B1388EEA3C76D02AEBF1C2731FC54AB6D197821984DA98D22FE979DA\
+6920C15A2A4F19FE86A7A49C1045421149548BF31A48254D1908F56B885F39909BE3553D8242\
+2FC41AEC0C63D047DC65A1DD9C7413097A8B986C3964A498C3C99C2E7A4DE23205265734C29D\
+457C32A2FD4E598C136C2B74A51511024F75E9CFFE60278D7DD4E674EB07F1EF7149B9859A3B\
+A40E06CE8DE91FA588CD228765D7FAD214DBDED8B7BFD6726A51CEFB803740CD87D8F23E7385\
+5691B6FBAC114C929992BEFE46465FFAAA6C592B0570C9F9EA87D36856448B9A5881A8F3446E\
+9F884FA0D3F6F396AA1B95CFF30873141CBF22DE721E355675BEB018E2A725B296F029E9A683\
+E43B9FA417A3DBB5E9F5756EA1DF3C3797E70E54960A9ACCB28CCAC4A4635BFE1F4A2A2CA5F8\
+4A9F2FF6B2498C7F4F93ACE34128B73BCE971BE0A5920E9A938F37402F1BC4DFB2B651A7F30A\
+DFBC991263418BEB635E25C1CE3E748A0BF9D9C6D4CF3EE48646033EFDC377FA5A5472375349\
+900D1F1DB1D313DF7E64B9B34C4A7CDE434E16A9D93797C07D50400D13E7F65486DADF196099\
+FE9F71554CEDD782D89B92AEC58E007BC903BE82C26DDDF2C86B8FCBD52ED64A19FC2920C74D\
+7F0B47AAE7FC176851AEBA05E33EE2081DD244B751BE89D8FD1E74A798EEE60A493CC36AFB34\
+DD96C34541EC3A2C32F1285DDBD88BC71138DA04E373DC80D958CD369C64FD5F26485369ADA4\
+1B93F5D43C47E2DFF1CA55320A70A0E07903964571DB66C75FBC691691B0520A2D31A3BD0CA5\
+22D842576D01B57AE4580B8AB4A6160159A96DA5FED007FD02E4D63ECCAFAC155251F316BB54\
+FCE1390AABA68E296756AB4F0189F92816FE9710C3E190F4679687631E99981F17429ABC4CA3\
+482C56C0E42061171BAB63AEEBCAA30B3CC4883A74ED71E47D5D8930A700F6D5DBD39627996D\
+9B93B978A8ED52D6E87752CA617331543CEAC386A6E3A8F43ADBCBDB46053F570119B3F19B2B\
+D92477AD98AF4197C274C2B569E013A7FA7850D8425F65AA425581B720E27BF9D9399A76:\
+4AA2A4958F5A0F91B928D76B91C36506F6B4C7C3EA41EBD6416DE2AECC
+
+2407970735E9026331AE5641300FE86BCDF45897190370274A476C8790502949D887AF8DFFB7\
+D1CBEEE0BA4BBFD0AD393E2D0698FBEE8F3E56C6E08C3ADC37A2B2AD1BC1A5AAE25B21B6E779\
+E41DDEF6C1FAC6EE571284F4DEB791EE1F079DB666E2E64C1378763C3EEBA9B998C27C757E70\
+8C680CE0E9C64B3767B4711C62D2C10F7905364DEE5C4A7DC533299BFF6D55086941F876CF1A\
+803F04EBC45EAE5D48612FCFAA1E6FF325CC8643DD77B48B16CD6C01E767DC11499644B6C301\
+565E16BCFFCE712676FEB37841608CC173456A4BFCEF5F9A40FF521CF94A9A38E20622277426\
+EE49330442455945510EB10259B6FB360F1C38535CDE3CC563DC44F36F978A1766CF91D49592\
+1BE0ADF59EA0C659D97E1C321BED0113B840350085179AFA32426A6F30AD9CF478A727D89DD5\
+693A087B16AE1C40010984D8AE35323FA84598B3F7A13BEF741A6BC59B47BC8D5250BE51E563\
+BF30BA364E54B68B75955FDE0809C56C25B79831EBCAB1DE292095DB60DD5E6F8C68386EEC70\
+4CDF5FD9B21D2011A955DF9425E62E94E7B5400801E549959B1D7512A5F69494226824FD4E14\
+80D28ED9D41094AB13D280D6E324DC2C61AAD4141F82BCE5B2342654F2A78F08A5C272501617\
+ADA60BD42A7E5214072B104A6EB88916E59694D4C72ABACD08D31130C88A6BFB1CAA47E3F142\
+8F4EF3D55DA9593408A60CAAC3058FCB5520C86D6B5A127A2D711180313690B79EDBFDC16EB8\
+3496C458426F00B56F5DA2AE368A297A76E2F6E86974FAD93297E55269E03E59EE09EEAC0DF0\
+2655DFECF618C83575EC012F36D6BB05196CF85D49F82D99C5DD164AC87AD9C5AE7698B721AA\
+293A63EF98535F7547BB044A3EAF9E9F3970DDB3DFB6E1BACB4A457E7D8D63780BEA7CBB1068\
+D66123C401ACDC047E0819A4BCAC745C2F4EFFDE8249B1FDC0428972EA8FBAA981F004C7CB4F\
+652326E43819BFF7530D44D8B42E52CB52EF56E897DCBAEFEE5984E9369E3EE7BFE5EC40FCC7\
+30E2C15C05D6319483329E117B79F94E441F1F4BF0814501418AA5349EFBD62F7CA3E5E67257\
+D9FB373C8D3DAF0080493F181EEFBC69C5B9F8D2EADD3D9D18774CF76C2C063C9B487FDBDB12\
+A9B5A104D1B6B5C4081E6A83EDDDAB5026EC6A5236D2360550372AD28461A60D9E5ECE6E1005\
+405252035365C61DA77ECB6126C7CCE1A5F1F2B5E8B53A50A49B6626159175623A537D0593FA\
+142194E7F137A88950B5BBE35B30DAE7A6375831FA9A3AF07E35A0C92BB60EECAD8F6AFD225C\
+D68B7F77BB8D96CF9225324527F5575A17CC29C380650B1D6C8A4F273FD3492A30EEA845B028\
+3EFD0DC9E7D2F241E77218342F4B263855D3C4DBA5279891BDE280942CA5F39A48A73A605F65\
+42E64B8D234DBBF3765A6A142E20EF90D4D30F5C93B243E39D86411A5EC1C04D0BAF7157:\
+1587639AD9EB4304EA3BDB1B51BD4A3E928941107B3E4D0BD637C39676F1EC92F01B7139A4A2\
+5AA3060945143EC36BF7A6D38478ACC037988AB7D334C8DE4D0C4163F8F8180A0B45CA17BA0E\
+4D850E169DD0DA41EBF7EBD08B6E059AA7E5012286BBA63201F44129C0B214C31E338C0924BA\
+E2552EA450659AA96464B34250DE693E4A1B917B63EBD1528BFF6DEC61BB70E84309245195D6\
+4E9B30A880CCFAD7E39EB3C526E657DDD41183A13E16C23B9E18194F14372EACB8DFB31B6DC4\
+18614C4A2679C1D101A4259DB50781795C55FDFEBA2A5621831A2142461D3BCF80799DBFCD41\
+26C85398EFD911F7039C62A32667C4067E155C1BD9DEB210E6006FAE5DB67ADDA8EDBE2DEC75\
+B5BBA1570C2CF3E3118C0DB8E5890A94708A9C089BA5822CA7F59F897DE20020DE3EC4F6D092\
+DE2159A93367083FB15A302F5113F49A521BA8C863161080EBF49FB603990D1F920FF5C23455\
+E1560C1D54E5E7E4227DD35E86298E12B344FB30F1F9565382E073A2946D7AC8B3CB903D7649\
+01A04E79F5F09E563E6A84FBF60EC88990ABFC71B071997FB6024F1BE56B94159EDEF135EB59\
+FE37EEE584BF4E066D014CEF83151103C21B64D623B115F84E0ACC52435DEA7D39C11A68B608\
+332C56CA5B9CF0EFFE59040FC386F947170D22F2453A8EB948E3FEA25CD482A4822335005DFF\
+5A6ECA44221231E7EE7CA8AF990346B049AF59A95CEB2A7C884A5DEF765BF8D837817F4019C0\
+C323B2087159CAF7B9E6EA2678DAE509B4C607134F6293DD2591DDEB92D9884D96295A811593\
+89D44CE9617921842F6D7249738500F3CF2B73EFA762B9EB399F8E2DB5B29EFD71F1A6AF0B37\
+97DFA41651947F330361A5AC495C0D3A2B9E4F34FA5D186CD946EDE0665F861EF99AC831F0D6\
+7351E848D9C9FBB74EB97F4CE03B5B9D70C103A7530063C4A7A3EE331F9A6314335E1B433D77\
+D158AA36563ED4DA4CDB9B635C5EFBC5B7A840A6F74B0DBD906D949BD419FC7503AD21E285B2\
+EB01BD7123BF7AF375D05DAAD012121310CA7A9A5ACDA2218D5FBA47596F2BA86FFB59090040\
+40CEA480E2EC50AF9953D379CAD0A00E375CF4AF2F225C4C66B2BC26F751B3FF35512CAB8B94\
+4A5120EBFE7606281BB53C7AA3CD5012592638A9C6B8D855264940A980DB68FAD2441691384A\
+C8ECB31C6529787B5B51B534E94F1DD21E75E8D666F74485642BF4FFFBA1DB6D8D4F40442127\
+6BF1CC7B5AFF5E57241B1E14BBC4DE84B137EF7BC9E1434DD36FB9A91B551E82A9E82F87FB53\
+665DE96A33B5B3871EF88A18560AF91C050AB6476700C7FBBA84F861E1A738691BE2BCE485C6\
+FD4E6D958CDE8DA49BC4B2ED3ACA18D12E8802967BAD848CE3C5CCD25B4941BC96B0FBFC745E\
+802D86C8E11642F3A0C2AA1026ED148D15D4EA27D68B26F7A73A15F05C056A68FD8D1D3A:\
+FD7760119A0432CB5928F24CB65E989B523B540161A3703E2E9370EEF544
+
+BEC2A17A991E96730F4189382AA0D0B9FB9F3DC9478D3DA9BE077815332DD60D74A5B06E2EE8\
+91E2DE94FB011BDBAFDD287053B792FE58B6C0DDAA56731A160CFF5140FBB15AC775C99E5265\
+42D2F885902869689561B6CC222F216231537665F3055258B99CAF7E24A756AA64F9F5F93C7B\
+9C790F0F56C83CF32F265C75A1FE60A0D03E2AAEFA99EBF6F3B5C3FF6D12CC8C8D1BD9F13EA6\
+E3EE9C41963824CAB090305A928B7732F96C8538489AC959AA38CCA32669D3477E25102349C0\
+59E47DF8CF161E174B75918249D61F5F8BC5F5010B48A84484AEE8149822750112052557DBD2\
+FB46C741338C1AC533FED2B753906A47AD8FEC3853BA882A35461FA5BFD649DC1349FC9D8A04\
+117029FD146E54B4B434AF5ABCD0194C226FF3AF3FE22070DF5FE6B927D27AC30B3CC304FEB8\
+A8F087ED668700E1268AE6B2A575E44ADA0BED14592410F4252585A2559F6A59E4E226F53F5B\
+4DB4A9F886E6BC044580B20EE79D5EFB6C035DB9D24A2684286071DBCDD5BEBD4B38DBE2F990\
+E7D0C30E4BECD54607D673A6FE226946D54BF84F11E4B10FD44C7EA79AD5A523BF38CF23D856\
+311AFE8BE54A9E417CAB529A77BB210AA8E3DD8C0A9F810FDBDD9F7EF1726F489F907BB6AC2B\
+AA5E6B7CBFFD864B8B47E91D0CEAB50ABA28245A1A93C3C6A3B0A907F678F2424FEE8C25FE94\
+AE69C454158F8ABD844F499F4BD39ECE28DDDB373C8A1C40C0B060927C7A879E1FD03876830A\
+7C2A67E9AAD1AD7B41B960C27D0912039FCA6E49075D1CC86619AD7A8FEC8422BF3AF1DFCB45\
+E2826D96DDCD8616FF4EB4CBCF2634104A09250739D6FE762CD05619A9D552D33B8AAF54CB8B\
+9AE834DC2EC340530DFD16D8E122F46092B03CEBD8AC54B70D0157F0D30DD4F1CA25EDB7F527\
+741AC5DC48E2AC752BFF7CEB19FC1618008A4F622C9DC1B29B4CC13C2170E7F771ABF40D3A63\
+4FAF580D97A3D7F7014EFD71425639EA7E026557123C347B3E2E57C7A7BF14BAB4B86EA05B2C\
+7DDA0787F4DD4EDE1A2F7675DAE9661E3F13D200FDBC64649B977BBA5AAFE6DEF9EE606E3152\
+675144015D012B663C219434A9F413E4331503B0EE68B7D53C71CD30429A33A6FC421C3EF8CF\
+7C63954B071D36A0EA1A9973C0BEF37DF9FF62C3FE6C9CF9D5F040CA663EFE4D9501CBA1F9EC\
+71F55DA295954E119A2172252618EB74DA2A931AC8532F9745BD6FF660E9E851D58976882ABE\
+61ED14DA8B2C0AB5A16EF9CC949B1F8854103F4D8C55E02802E9CAC30D0B0C8D5FE26D987BA7\
+F63C195FC376DA3C0518D2B8D9D7CA945EAF8ABE2BEF78F99FA8EF19133FABB845BA842E1CA8\
+6927207452C129FA12ADCCA3E4752635675C4226B473749817E57986BE452B67F9D6D8845EFA\
+0B1642905D0A9A1FDD6F4741111E578370095FF5623EDBD4DD92D7C4A9E51AC4660FA2E4:\
+27E92D9318FB1F44542B1FE1D040204690E57E289012A86D785E230A6A473A0CC3FF61846382\
+6C5A6BE0EC29A42424539114D11325B75D7F84B8BEAE7AE78122AC69E8537FF94D1E5514F12D\
+5B2A985DE39B68996471E15FE5AB14E533D36D61EEC01B70EA9749BB431AB9533D1DD1DCE6D5\
+69696057DC693C0BCAA9BF18DB7B6DB009230D492D01E7FF2DECD0BEF61E4425E1706FD396FD\
+2203818AF5EC5833BB7C902D325F47E3ADD947DFD7F7773CB791C7878FFF63916FC373642F38\
+B3200780C9831D8C173389AE404C6ACB29E844B96487B8F59B4A5C64CD03F1BB0AE9F5200E3B\
+C642D2FCF3A422FADAC4A23788B44B4D085D25C346A381D43782BA28240AC89C75BE6E346E0C\
+098CC65D785D3B522EA3F03DA743D84471A2FDA73B637A849C0D924CE9DE42E74F77AAEBC64E\
+844E69FAC8D1125AEF4770957ECBCB1E7F3183780E30B188101D598D7F89FA6A8B32051C3D44\
+6F9DF12A850F418282F819CDD06A95B0A08FCAACAB87D1D9CC91FCB3A762EA11427CA8045C6E\
+AED46D823E6813D2C1C9D496B726A3F06DE1C5D70B943CC41E39D7904105875E9D6D1571D07C\
+3FD63007A759210CF93D8581529D0C3CE80CC60EBDBE318DBF63F914F1BF0E991F51932DCE90\
+08DFF7C6C29EDCCA1836BDADA487BA7080A6D154939FB82A0F41800397576636804E97DDAC08\
+F36508DF60A2538F0DA657ED17A54AEED2F46A9D924B97C5A8442611D12E140D5584B7375C2E\
+47389F339469022C055E7303A144D63566069DCBF40432EDF8A6693D2764BA19E590114B44FB\
+CAD4F1699FDCB64F89AB053D34355915E987F260E09D657283CB7758FE7633143FDBAF479598\
+6A9E480E8448FBB16EA49C51E6359491A5215DE7947E3AE0FF018E8DA065FA6C17AE90D07431\
+F8F4B6B956884B3288937F40F72B7A90E36917043C994B354DE67E3DEAAF15B683A62B023BF9\
+DC0E6DACA05D75FA9B8A16CCB8802355B0ABDF961B34E18853220E5D01BE63449F002F23799E\
+7989E9EA37BA15B525AA053B200B4AE796DB432242B9EECACAFD1EBBB9037C90D837AF20407B\
+194ECEE1A4D468BB95EA0135C84BDD8079818C822768728CDBEE416FF0B5311A3AD893437D57\
+60A14A94F4ADE9A0C4D7F2CD33AEFB982B8C05E4CD0D8E7C50C9591AC3678E1DB93796004E71\
+9705288C15F8FA49CAB636757ECB0037B852B755B2B519552EC3F1D9EB79676DFB793806043E\
+880319E9781B9702E3A39C80D8DD30A9ACDF993319287ADC774EF961670FBF74EF41CCFC4EBC\
+CB2A571945DD5652F7FB85B20C5BA4FB4B7AF0993C4ABE8DF1231DB8E635BF7E6B5F73DA5FDB\
+042E699F68EDA254EAA50E9B180341C1AC72E0DDA1275205AC0AD31388F2D002E3DD3FFE26FB\
+8CF8B69D9728E583B1369F3688AA9F3EC3F1C306836635E3F14F37FC6FDF7FA8578BE943:\
+8B73381DC14BAD9CCA68FD348320642E282C53740BD4E479F9FB21A740C4E4
+
+B5E5EC7969BE71F2CB23A1B3F03683D760849D250CED76939779CB56F68A1FB0C5203E70C709\
+AA3BD5F46BEF4810F7A1D5D3DF80C7E887BF8D8AAF851D22A70663CFB11F9FAFF3C7C3CF7989\
+A62D3D51A317F5AB3F34E3E666FCEF0AF7565831C148AE441EC5B944267D2A5724225EA7FF93\
+B39A3B4840FFE9F379598721C1C8E5C72DFB37999932C75D16C5F43D77199BE6FFC9F19EB8C1\
+9296AE5C06CF2B7263941D6CD40EF0D68E3D4E309E46794EB0CEF97FFC79A2209B49657CA501\
+0257AB977BEB3070192E13672E94C99E8250CBA79BA46A23C1613D46EDEB7DF6D2AF8F092811\
+5CC002103BE69BD1E7BA4D81EC5CEF372DD1A6FE6B2BBD643C04E0C7AFE61BAF19140C0A45A7\
+226D059D66EBAEA5346F6C79B32F234813CA2365D3F45E13F77ADE50C16A216ED9497BCC77AD\
+AE50DEDA9636E67504C71D499707951CB28EDCEB16974A7F8015170E7CD9A2962D529EA97877\
+281DDBDAB23988502C46A0F2CDA4700DE1923334CFA6F344F4F8514DEDE2DDC82C0079729840\
+A459A59DC89C57FE7CA34784178FDD70D1AD7F46C1D464DCCA8D0D9CFEC542A0689441360C33\
+F1EACC4B882DE9BFE1B593459A13B73E86BD8C0B0282C69387B0506FAED80D13A2CD8A61FD55\
+6AA52CA111A250A9759B65C9815E8917A81248E47F7AB963A5D26ED23F07F1DC07F74490F97F\
+0EE79AC55532855E44BF85AC6870ECDB6EB454F04332297D1A219E76CDD92BAC023036C580F3\
+311D5255201F6617AD800A7C1BD4E0014AB554840B72BC2E6492CF27E246DFEEBFA679789260\
+0B13CDDC4B71F644492950476B21315B6BB6599355EB2ED3B41DEDAEC9915803204A77B2BA17\
+F5EE77143D62939326C6B0E47D013C8B4CA35EFD56969CD9922DF373DA3361692F2215D1D79A\
+620179B399ED509B75D64229E678D50BA5DE297D4E3F43E63910BDE9F50D81477C4204205F74\
+3F94168FE1B1D49BF0DF9B4CDC54043BB0992D1D8D2DCCA0E2BC3D16BC9750DD2683C8B60313\
+E9A8E613DE853B5BAA0A6F987F6E7DD4753E285ED6FF895D521BD38567588F36DCAAE3CFC13E\
+A204DA65E1D8FDBDB8406FB10F99C977D2523B0556C989D7A13E4B6CFCE1C92CAD06F513D4E9\
+ABF607D88FECECD8C47413ABD8814DE84075C4BD8315EBA45571247DB384BF6C84661B93E4CE\
+7ECAE02CD3B2E5C93F08FD020AC41B583B73E5C1534D5F101058B9EF51BE65959D30E2A74F64\
+3F55A71DAC6441D3C03A117A675F6472AC5BE7C3D05791E85134CB10CD4C8A4F9E62EBFB24DE\
+64FD5713CE856BE832F4D6C409390EDEA43E8B1BBEB195C38478342B33BE0595334B3D0EC5E3\
+92BABACF0052B3686AAE8AF9A9D49093EBDF6507E073EABAD120CAF75A172E08046542B14958\
+8AFBDA53A1713D91980F04E95A048BA7A92B98C4C090A622ED1C9E9BBEE79D1F24E36DA1:\
+A497092296A16CBAB0B6A592C33FEAB468D38BC809F666492B55F6A0FA8C02B38856A0ABFDB5\
+EB16423C8FE8C50DF5522C27CB55251A8560E25633B97CD00434266786B57AA4CBFF2334D072\
+CC32652917F8371F17EEEB05B46B520F97D63EEE0DBEB2FAC94896C49D13EA71EC1D6553B05D\
+C266D1C2B8AB82932B5821A5DE558317B0C42DD1CC86DB784564BBAF915F5467701FD7C28C9A\
+A51DE741D90FCB60A16FB21504F77E7EDD65CEF98E1C88CDC657BAB27039C3A89A022B18783E\
+65FB6F7DB2D8DB623BCAF56FD94634FCA45C9537BDFA76C6DBA3F4A7F39037C2B935C25DD517\
+AA2DA9CD8F5E83AE7D3E95ED63025E925253D1C5FCDBBBF18310954C22CE7851ADFB0527C057\
+B51EAA8504082D138DC6569F9736EAB6C11BB0DB9243BBBEE576A1CB9390F92362F7A3581E91\
+F27B3B47FA0E2E375584D8B7588BF5B5EF1EC2CA21267685AD9E76B985F5887B0A6E313BE827\
+5E3F7C0BBE87228DFED01E37A7213349150191860B1AD3E20C91DD504C2FF642AB869E4B427B\
+11B1C22A6D1029BCBC7610EDF9B2F4A2834A8897303A9C5A313D7C3B18796CB0F0F968B175D7\
+CA252ADF80CFDB258228FB6A1A9AA52F8847E18866C4F1038B28A6A3EB14C51098049C519FFF\
+83136206BE095094C66CF3F683BC5757D2394DE9E0808E42DE433988FF30326AD87C4AE38521\
+A2B8E4BE8BD7634FC62FE02E450510A190A767B3475639A86ED3F31230C21B2C9BE5C1285C8B\
+127BF153B2F3D082F4F6B18BC2AC3380BFC4BCAC748C7C8F781F58CD674DA01CC6351C354FA7\
+5879E002A6C95986A516035F6F2A9C50FC8BE5AC79B7E9EBE8FB4F4DFE1683C52C966DBEAC35\
+5965A04F9AA6C91833BD55F508B04100A88FDA58F14E5C260859EC7CB60F625928EDD7CAF8B3\
+490655E234CC511B523C40B56BD07CB9A6A08A3642DA96C3D889C1D95176C9FAF6E28E74A548\
+FD6F8C3B0FBCEC237A5BD739A2DCF7EA93943DAB8CB5F228E0C752867E116842EA867AB7FB0B\
+4A6D031E9FEB8780C1318DFDBD6CD335122568E7B7294DD851C800156E13B445D64B22E9CB46\
+49B07E4BA64D2D22387173727EB434AC69D7A3F5580EEED15F7D4F15B6A6B190630C3B4BF6CC\
+BE98549152E5E6EF47FD02E5ACAA8D1C7E8621FBA77C4C712C6B91EE273B81C9CB4B0F5C6103\
+03F700C441DEE3C05540B793CD4E72C787F262F711EB788057486250076C2B1F09B93B2DD962\
+098CDEFC48CF50A90DE67B97819FA4248D45BC29B3325C4EC1EF95C9C2B1701190BD7420FEDA\
+9976DDF8CF70AFCAF1A8799738C5311757616764701CECEFF27D2676B1F55E3749751080358D\
+D9E9A9125287342FCB08E6BD33C776B0E0E2A6F28A043F52A6508DA1C7F867512E13A64A20DB\
+83D86884B50141254C71B7388F6A7D65EFB2D069A815FECB0970A3300CD5C5AA73776E2A:\
+8E3BE5C3118FA8382BE650BF4727BF6B84F6D962367AB966A072BD5913335457
+
+# This is quite trivial. These were generated by OpenSSL.
+[MARK-4]
+97212EACFDB13D5BBC037B01A81CBB736B8136124E275E2F25823B8B98EDD3C4BF7F6AD52D:\
+EA57CEA491D69813935D09E0DED97221B4E909BC5C59CC8C1202BD0E7BA82C53DBD27540D6:\
+AAC76CB1CE2BF5144EE9A543328AFB95
+87742937D3EB3D9729D4C668273DFF01D6096DE237BCE72B598727935704DE047378453395:\
+120EE944C947D8EAA10A446BD6E65BBC1D5821764262F2129FE2C37B65A38C5FB41D4A27DB:\
+141619BCD6053F33E5D479E32F937222
+B0B0488DA6A74775D3C3B3459309D21E20D00798B45EAC2C6FAD29A1A8C1743E744D34D1B5:\
+AE1EFEE98A07A2654C42B68FA24065C02714D43EED8C0AB336EFEA1DA1906ACE3586C96DAA:\
+A2F81CF25695060C04A2ED2E6F92339A
+9BC14F96CEDDCF5440130D170608752B75A2D1BD7227F8CA2B991AFEFEC0EB3B9656ACFA53:\
+953A60AFE169AEAA288638AE7DD5DBC2120418F44470194E6B869584BCAA13D7E0FBA35FC6:\
+4404423C571E0843B8EC4F5B0380EB60
+7B083BFA430729619537DF5BF575777CF5A433206CFCB8B175AA4BB5AE46EA82A69A15C2E6:\
+80206B94450FA80D81D44D3E751C8541E15B9DCFBCC05DC6007425E52851DF51B8166A9EF2:\
+BD348966C075CE6B78BA2918258538ED
+
+[Salsa20]
+
+# From linux-2.6.25.9's crypto/tcrypt.h (all zero IVs)
+0000000000000000000000000000000000000000\
+00000000000000000000000000000000000000:\
+2DD5C3F7BA2B20F76802410C688688895AD8C1BD4\
+EA6C9B140FB9B90E21049BF583F527970EBC1:\
+000102030405060708090A0B0C0D0E0F
+
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000:\
+AE39508EAC9AECE7BF97BB20B9DEE41F87D947F828913598DB72CC232948565E\
+837E0BF37D5D387B2D7102B43BB5D823B04ADF3CECB6D93B9BA752BEC5D45059\
+1514B40E40E653D1839C5BA092296B5E965B1E2FD3ACC192B1413F192FC43BC6\
+95464554E975030844AFE58A811209:\
+1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A
+
+# From Crypto++ via Linux kernel
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000306090C0F1215181B1E2124272A2D303336393C3F4245484B4E5154575A5D\
+606366696C6F7275787B7E8184878A8D909396999C9FA2A5A8ABAEB1B4B7BABD\
+C0C3C6C9CCCFD2D5D8DBDEE1E4E7EAEDF0F3F6F9FCFF0205080B0E1114171A1D\
+202326292C2F3235383B3E4144474A4D505356595C5F6265686B6E7174777A7D\
+808386898C8F9295989B9EA1A4A7AAADB0B3B6B9BCBFC2C5C8CBCED1D4D7DADD\
+E0E3E6E9ECEFF2F5F8FBFE0104070A0D101316191C1F2225282B2E3134373A3D\
+404346494C4F5255585B5E6164676A6D707376797C7F8285888B8E9194979A9D\
+A0A3A6A9ACAFB2B5B8BBBEC1C4C7CACDD0D3D6D9DCDFE2E5E8EBEEF1F4F7FAFD\
+00050A0F14191E23282D32373C41464B50555A5F64696E73787D82878C91969B\
+A0A5AAAFB4B9BEC3C8CDD2D7DCE1E6EBF0F5FAFF04090E13181D22272C31363B\
+40454A4F54595E63686D72777C81868B90959A9FA4A9AEB3B8BDC2C7CCD1D6DB\
+E0E5EAEFF4F9FE03080D12171C21262B30353A3F44494E53585D62676C71767B\
+80858A8F94999EA3A8ADB2B7BCC1C6CBD0D5DADFE4E9EEF3F8FD02070C11161B\
+20252A2F34393E43484D52575C61666B70757A7F84898E93989DA2A7ACB1B6BB\
+C0C5CACFD4D9DEE3E8EDF2F7FC01060B10151A1F24292E33383D42474C51565B\
+60656A6F74797E83888D92979CA1A6ABB0B5BABFC4C9CED3D8DDE2E7ECF1F6FB\
+00070E151C232A31383F464D545B626970777E858C939AA1A8AFB6BDC4CBD2D9\
+E0E7EEF5FC030A11181F262D343B424950575E656C737A81888F969DA4ABB2B9\
+C0C7CED5DCE3EAF1F8FF060D141B222930373E454C535A61686F767D848B9299\
+A0A7AEB5BCC3CAD1D8DFE6EDF4FB020910171E252C333A41484F565D646B7279\
+80878E959CA3AAB1B8BFC6CDD4DBE2E9F0F7FE050C131A21282F363D444B5259\
+60676E757C838A91989FA6ADB4BBC2C9D0D7DEE5ECF3FA01080F161D242B3239\
+40474E555C636A71787F868D949BA2A9B0B7BEC5CCD3DAE1E8EFF6FD040B1219\
+20272E353C434A51585F666D747B828990979EA5ACB3BAC1C8CFD6DDE4EBF2F9\
+0009121B242D363F48515A636C757E879099A2ABB4BDC6CFD8E1EAF3FC050E17\
+2029323B444D565F68717A838C959EA7B0B9C2CBD4DDE6EFF8010A131C252E37\
+4049525B646D767F88919AA3ACB5BEC7D0D9E2EBF4FD060F18212A333C454E57\
+6069727B848D969FA8B1BAC3CCD5DEE7F0F9020B141D262F38414A535C656E77\
+8089929BA4ADB6BFC8D1DAE3ECF5FE071019222B343D464F58616A737C858E97\
+A0A9B2BBC4CDD6DFE8F1FA030C151E273039424B545D666F78818A939CA5AEB7\
+C0C9D2DBE4EDF6FF08111A232C353E475059626B747D868F98A1AAB3BCC5CED7\
+E0E9F2FB040D161F28313A434C555E677079828B949DA6AFB8C1CAD3DCE5EEF7\
+000B16212C37424D58636E79848F9AA5B0BBC6D1DCE7F2FD08131E29343F4A55\
+606B76818C97A2ADB8C3CED9E4EFFA05101B26313C47525D68737E89949FAAB5\
+C0CBD6E1ECF7020D18232E39444F5A65707B86919CA7B2BDC8D3DEE9F4FF0A15\
+202B36414C57626D78838E99A4AFBAC5D0DBE6F1FC07121D28333E49545F6A75\
+808B96A1ACB7C2CDD8E3EEF9040F1A25303B46515C67727D88939EA9B4BFCAD5\
+E0EBF6010C17222D38434E59646F7A85909BA6B1BCC7D2DDE8F3FE09141F2A35\
+404B56616C77828D98A3AEB9C4CFDAE5F0FB06111C27323D48535E69747F8A95\
+A0ABB6C1CCD7E2EDF8030E19242F3A45505B66717C87929DA8B3BEC9D4DFEAF5\
+000D1A2734414E5B6875828F9CA9B6C3D0DDEAF704111E2B3845525F6C798693\
+A0ADBAC7D4E1EEFB0815222F3C495663707D8A97A4B1BECBD8E5F2FF0C192633\
+404D5A6774818E9BA8B5C2CFDCE9F603101D2A3744515E6B7885929FACB9C6D3\
+E0EDFA0714212E3B4855626F7C8996A3B0BDCAD7E4F1FE0B1825323F4C596673\
+808D9AA7B4C1CEDBE8F5020F1C293643505D6A7784919EABB8C5D2DFECF90613\
+202D3A4754616E7B8895A2AFBCC9D6E3F0FD0A1724313E4B5865727F8C99A6B3\
+C0CDDAE7F4010E1B2835424F5C697683909DAAB7C4D1DEEBF805121F2C394653\
+606D7A8794A1AEBBC8D5E2EFFC091623303D4A5764717E8B98A5B2BFCCD9E6F3\
+000F1E2D3C4B5A69788796A5B4C3D2E1F0FF0E1D2C3B4A5968778695A4B3C2D1\
+E0EFFE0D1C2B3A495867768594A3B2C1D0DFEEFD0C1B2A39485766758493A2B1\
+C0CFDEEDFC0B1A2938475665748392A1B0BFCEDDECFB0A192837465564738291\
+A0AFBECDDCEBFA091827364554637281909FAEBDCCDBEAF90817263544536271\
+808F9EADBCCBDAE9F807162534435261707F8E9DACBBCAD9E8F7061524334251\
+606F7E8D9CABBAC9D8E7F60514233241505F6E7D8C9BAAB9C8D7E6F504132231\
+404F5E6D7C8B9AA9B8C7D6E5F4031221303F4E5D6C7B8A99A8B7C6D5E4F30211\
+202F3E4D5C6B7A8998A7B6C5D4E3F201101F2E3D4C5B6A798897A6B5C4D3E2F1\
+00112233445566778899AABBCCDDEEFF102132435465768798A9BACBDCEDFE0F\
+2031425364758697A8B9CADBECFD0E1F30415263748596A7B8C9DAEBFC0D1E2F\
+405162738495A6B7C8D9EAFB0C1D2E3F5061728394A5B6C7D8E9FA0B1C2D3E4F\
+60718293A4B5C6D7E8F90A1B2C3D4E5F708192A3B4C5D6E7F8091A2B3C4D5E6F\
+8091A2B3C4D5E6F708192A3B4C5D6E7F90A1B2C3D4E5F60718293A4B5C6D7E8F\
+A0B1C2D3E4F5061728394A5B6C7D8E9FB0C1D2E3F405162738495A6B7C8D9EAF\
+C0D1E2F30415263748596A7B8C9DAEBFD0E1F2031425364758697A8B9CADBECF\
+E0F102132435465768798A9BACBDCEDFF00112233445566778899AABBCCDDEEF\
+001326394C5F728598ABBED1E4F70A1D304356697C8FA2B5C8DBEE0114273A4D\
+60738699ACBFD2E5F80B1E3144576A7D90A3B6C9DCEF0215283B4E6174879AAD\
+C0D3E6F90C1F3245586B7E91A4B7CADDF00316293C4F6275889BAEC1D4E7FA0D\
+203346596C7F92A5B8CBDEF104172A3D506376899CAFC2D5E8FB0E2134475A6D\
+8093A6B9CCDFF205182B3E5164778A9DB0C3D6E9FC0F2235485B6E8194A7BACD\
+E0F306192C3F5265788B9EB1C4D7EAFD102336495C6F8295A8BBCEE1F4071A2D\
+405366798C9FB2C5D8EBFE1124374A5D708396A9BCCFE2F5081B2E4154677A8D\
+A0B3C6D9ECFF1225384B5E718497AABDD0E3F6091C2F4255687B8EA1B4C7DAED\
+00152A3F54697E93A8BDD2E7FC11263B50657A8FA4B9CEE3F80D22374C61768B\
+A0B5CADFF4091E33485D72879CB1C6DBF0051A2F44596E8398ADC2D7EC01162B\
+40556A7F94A9BED3E8FD12273C51667B90A5BACFE4F90E23384D62778CA1B6CB\
+E0F50A1F34495E73889DB2C7DCF1061B30455A6F8499AEC3D8ED02172C41566B\
+8095AABFD4E9FE13283D52677C91A6BBD0E5FA0F24394E63788DA2B7CCE1F60B\
+20354A5F74899EB3C8DDF2071C31465B70859AAFC4D9EE03182D42576C8196AB\
+C0D5EAFF14293E53687D92A7BCD1E6FB10253A4F64798EA3B8CDE2F70C21364B\
+60758A9FB4C9DEF3081D32475C71869BB0C5DAEF04192E43586D8297ACC1D6EB\
+00172E455C738AA1B8CFE6FD142B425970879EB5CCE3FA11283F566D849BB2C9\
+E0F70E253C536A8198AFC6DDF40B223950677E95ACC3DAF1081F364D647B92A9\
+C0D7EE051C334A61788FA6BDD4EB021930475E758CA3BAD1E8FF162D445B7289\
+A0B7CEE5FC132A41586F869DB4CBE2F910273E556C839AB1C8DFF60D243B5269\
+8097AEC5DCF30A21384F667D94ABC2D9F0071E354C637A91A8BFD6ED041B3249\
+60778EA5BCD3EA01182F465D748BA2B9D0E7FE152C435A71889FB6CDE4FB1229\
+40576E859CB3CAE1F80F263D546B8299B0C7DEF50C233A51687F96ADC4DBF209\
+20374E657C93AAC1D8EF061D344B627990A7BED5EC031A31485F768DA4BBD2E9\
+0019324B647D96AFC8E1FA132C455E7790A9C2DBF40D263F58718AA3BCD5EE07\
+2039526B849DB6CFE8011A334C657E97B0C9E2FB142D465F7891AAC3DCF50E27\
+4059728BA4BDD6EF08213A536C859EB7D0E9021B344D667F98B1CAE3FC152E47\
+607992ABC4DDF60F28415A738CA5BED7F009223B546D869FB8D1EA031C354E67\
+8099B2CBE4FD162F48617A93ACC5DEF71029425B748DA6BFD8F10A233C556E87\
+A0B9D2EB041D364F68819AB3CCE5FE173049627B94ADC6DFF8112A435C758EA7\
+C0D9F20B243D566F88A1BAD3EC051E375069829BB4CDE6FF18314A637C95AEC7\
+E0F9122B445D768FA8C1DAF30C253E577089A2BBD4ED061F38516A839CB5CEE7\
+001B36516C87A2BDD8F30E29445F7A95B0CBE6011C37526D88A3BED9F40F2A45\
+607B96B1CCE7021D38536E89A4BFDAF5102B46617C97B2CDE8031E39546F8AA5\
+C0DBF6112C47627D98B3CEE9041F3A55708BA6C1DCF7122D48637E99B4CFEA05\
+203B56718CA7C2DDF8132E49647F9AB5D0EB06213C57728DA8C3DEF9142F4A65\
+809BB6D1EC07223D58738EA9C4DFFA15304B66819CB7D2ED08233E59748FAAC5\
+E0FB16314C67829DB8D3EE09243F5A7590ABC6E1FC17324D68839EB9D4EF0A25\
+405B7691ACC7E2FD18334E69849FBAD5F00B26415C7792ADC8E3FE19344F6A85\
+A0BBD6F10C27425D7893AEC9E4FF1A35506B86A1BCD7F20D28435E7994AFCAE5\
+001D3A577491AECBE805223F5C7996B3D0ED0A2744617E9BB8D5F20F2C496683\
+A0BDDAF714314E6B88A5C2DFFC193653708DAAC7E4011E3B587592AFCCE90623\
+405D7A97B4D1EE0B2845627F9CB9D6F3102D4A6784A1BEDBF815324F6C89A6C3\
+E0FD1A3754718EABC8E5021F3C597693B0CDEA0724415E7B98B5D2EF0C294663\
+809DBAD7F4112E4B6885A2BFDCF91633506D8AA7C4E1FE1B3855728FACC9E603\
+203D5A7794B1CEEB0825425F7C99B6D3F00D2A4764819EBBD8F5122F4C6986A3\
+C0DDFA1734516E8BA8C5E2FF1C39567390ADCAE704213E5B7895B2CFEC092643\
+607D9AB7D4F10E2B4865829FBCD9F613304D6A87A4C1DEFB1835526F8CA9C6E3\
+001F3E5D7C9BBAD9F81736557493B2D1F00F2E4D6C8BAAC9E80726456483A2C1\
+E0FF1E3D5C7B9AB9D8F71635547392B1D0EF0E2D4C6B8AA9C8E70625446382A1\
+C0DFFE1D3C5B7A99B8D7F61534537291B0CFEE0D2C4B6A89A8C7E60524436281\
+A0BFDEFD1C3B5A7998B7D6F51433527190AFCEED0C2B4A6988A7C6E504234261\
+809FBEDDFC1B3A597897B6D5F4133251708FAECDEC0B2A496887A6C5E4032241\
+607F9EBDDCFB1A39587796B5D4F31231506F8EADCCEB0A29486786A5C4E30221\
+405F7E9DBCDBFA1938577695B4D3F211304F6E8DACCBEA0928476685A4C3E201\
+203F5E7D9CBBDAF91837567594B3D2F1102F4E6D8CABCAE90827466584A3C2E1\
+00214263:\
+B581F5641873E3F04C13F2771860655E2901CE985553F90C2A08D509B3575556\
+C5E95690CB6AA3C0FFC479B4D2975DC443D1FE947B88065AB29E2CFC4403B790\
+A0C1BA6A33B8C7B29DE1124FC064D401FE8C7A66F7E65A91BBDE5686AB652130\
+00846524A57D85B4E317ED3AB76FB40B0BAF15AE5A8FF20C2F27F409D8D296B7\
+71F2C5994D7E7F757789308B59DBA2B2A0F319392BC57E3F4FD9D356289744DC\
+C08B7724D952E7C5AFF67D59B244051DB1B011A50FEC33E16D1B4E1FFF5791B4\
+5B9A96C553BCAE203CBB14E2E82233C15E769E4699F62A15C69702A06643D1A6\
+31A69FFBF4D369E5CD7695B87A827F2145FF3FCE55F6951008771043C6F309E5\
+68E73CAD0052450DFE2DC6C2948C121DE625AE98128E199C8168B111F669DAE3\
+6208187A254928ACBA71120BE4A2E5C75D8EEC494021BF5A98F3026855037F8A\
+E5940C325C078263AF6F9140848E5225D0B0295305E2507A34EBC94620A83DDE\
+7F165F36C52EDCD11547C750406D91C5E793951AD357BC5233EE1419225289A7\
+4A2556774BCACF0AE1F53585307E594ABD145BDFE346CBAC1F6C960EF481D199\
+CA88633D02586BA9E59FB300B254C6741CBF46AB97CCF85404070852E6C0DA93\
+747D93995D7868A62E6BD36A69CC126BD4C7A5C6E7F603045DCD615E1740DCD1\
+5CF508DF5C9085A4AFF678BB0DF1F4A45426729E61FA86CFE89EA1E0C74823AE\
+5A90AE750A74188905B192B27FD01BA662072501C7C24FF9E8FE63958007B426\
+CCD126B6C43F9ECB8E3B2E4416D3109A9508EBC8CBEBBF6F0BCD1FC8CA86AAEC\
+33E669F44525863A22944F00236A44C2499733AB36140A7024C3BE043B79A0F9\
+B8E776292283D7F294F44149BA5F7B07B5FBDB031A9FB64CC22E374049C33816\
+E24F7782B0684C711D57619CD94E5499471328733CBB0090F34DC90EFDE7B171\
+D31579BFCC262FBDAD6C50696C3E6D809AEA78AF19B20D4DAD0407AE22904A93\
+320E369B1B46BA3BB4ACC6D1A231533B2A3D45FE036110851769A678CC6C8749\
+53F98010DE80A2416AC33202AD6D3C5600715106A7BDFBEF3CB59FFC487D537C\
+66B04923C447100EE56C7413E6C53FAADEFF0744DD561BAD0977FB5B12B80D38\
+1737357B9BBCFED47E8BDA7E5B04A722A731A12086C71B99DBD189F494A35369\
+8DE7E874118D74D60737919FFD67503AC9E1F436D5A047D1F9E539A331AC0736\
+23F866181428340FB8D0E729B3044B550141B2758DCB96853AFBAB2B9EFA5820\
+441FC014227561E8AA19CFF18256F4D7787B3D5FB39E0B8A5750DB1741654DA3\
+02C99C9C53FB39399B1D7224DAB739BE133BFA29DA9E54646EBAD8A1CBB336FA\
+CB4785E96138BCBEC500382A54F7C4B9B3D37BA0A0F8727F8C8E820EC61C759D\
+CA8E6187DEAD80D2F5F980EF1575AFF580FBFF6D1E25B740616A395A6AB531AB\
+978A19894440C0A6B44E30327B13E767A98B5704C201A6F42899AD2C76A378C2\
+4AE6CA5C506AC1B0624B108E7C1743B317661C3E8D69F05A71F597DCD145DD28\
+F35DDF537B11E5BC4CDB1B516BE9FB3DC1C32CB971F5B6B21336798053E8D3A6\
+0AAFFD5697F7408E45CEF8B09E5C3382B04456FC0509E92AAC2680141DC83A35\
+4C8297FD76B7A90A3558798E0F66EAAF516C09A96E9BCB9A3147A02F7C71B44A\
+11AA8C66C564E63A54DA246AC441654682A00A0F5FFB25D02C91A7EEC4810786\
+755E336997E42CA89D9F0B6ABEAD98DA6D9441DA2C1E89C4C2AF1E00050B8360\
+BD43EA15237FB9ACEE4F2CAF2AF3DFD0F31931BB4A74841752322C7D61E4CBEB\
+80381552CB6FEAE5739CD92469C6953221C811E4DC36D7933866FBB27F3AB9AF\
+31DD9375788A2C94871A58EC9E7D4DBAE1E54DFCBCA42A14EFCCA7ECAB430918\
+D3AB68D107994447D683853B30EAA96B63EAC407FB432FA4AAB0AB0389CE3F8C\
+027C8654BC88AF75D2DC6317D326F696A93CF1618C1118CCD6EA5BE2CDF0F1B2\
+E535901F854C765B66CE44A4329FE67B716E9F5815677287648E3A4445D476FA\
+C2F6EF8505187A9BBA4154ACF0FC59123FDFA0E58A65FD3A628D832C03BE0576\
+2E5349979433AE408115DB6EADAAF54BE39870DFE07CCDDB02D47D2FC1E6B4F3\
+D70D7AD9239E872DCE87ADCC72050029DC737F64C1150EC2DFA75FEB41A1CDEF\
+5C50792A5656718CACC0795069CA593265F254E4523876D15EDE269EFB752E11\
+B510F41773F589C74F435C8E7CB90552244099FE9B850B6C223E8BAE86A1D279\
+05686BABE34149ED15A18D402D61DF1A59C9268BEF304C884B10F88DA6929F4B\
+F3C4530B895D2892CF78B2C05DED7EFCC012235F5A7886436E27F75AA76AED19\
+04F0B312D1BD0E896EBC96A8D849399F7E67F02E3E01A9BAEC8B628ECB4A7043\
+C7C2C4CA820373E911DFCF54EAC9B09551C0133D9205FAF4A934C8CE6C3D54CC\
+C4AFF1DC114426A2AFF185757D0361684E78C6927D867D77DC7172DBC6AEA1CB\
+709A0B19BE4A6C2AE2BA6C649A1328DF8575E643F68708686EBA6E799F04BC23\
+50F6335C1F2425BE3347804556A3A7D77AB1340B903C9CAD445F9E0E9DD4BD93\
+5EFA3CE0B0D9EDF3D62EFF24D8716CEDAF55EB22AC936832055B47DDC64ACBC7\
+10E13C921AF323782BA1D280F412B1208FFF2635DDFBC74E78F12D501277A860\
+7C0FF5162F63702AC096804E0AB493355D1D3F56F72FBB9011168FA2EC47BEAC\
+56012656B18CB210F91ACAF5D1B7392063F169204F13121F5B65FC98F7C47ABE\
+F7264D2B847B42ADD87A0AB4D874BFC1F06EB429A3BBCA4667706A2DCE0EA28A\
+A987BF05C4C104A3ABD445438CB602B041C8FC443D59AA2E44212A8D889D57F4\
+A00277B8A6A0E6755C82653E035C298F3855AB3326EF9F4352FD68AF36B4BB9A\
+5809091BC36546461DA7941823502CCA2C551997019D933B6386F2036745D272\
+28526CF4E31CB51113F1EB21C7D956822B8239BD6954ED62C3E2DE73D46A12AE\
+13217F4B5BFCBFE82BBE56BA688B9AB16EFABF7E5A4BF1AC986585D19353D37B\
+09DD4B106D84B01365BDCF5209C485E284741565B7F751AF55ADA4D122547094\
+A01C9041FD99D75A31EFAA25D07F4FEA1D5542E549B0D046623643B282157550\
+A472EB54271F8AE47DE966C5F153A4D10CEBB8F8BCD4E2E7E1F84BCBA9A1AF15\
+83CB72D03379002D9FD7F12E1E10E445C0753A39EA68F75D1B738FE98E0F7247\
+AE350A317A144D4A6F47F77E916E748B2647F9C3F9DE70F561ABA9279F82E49C\
+89913F2E6AFDB549E9FD59143649406D32D88542F3A5DF0CA827D754E2632FF2\
+7E8B8BE7F19A953543DC3AE4B6F4D0DF9CCB94F321A07750E2C6C4C65F09645B\
+9290D8E1D1ED4B42D737AF653D1139B6248A60AED61EBF0E0DD7DC960E65754E\
+29069DA4513A10638F1707D58E3CF428005A5B0519D8C06CE515E49C9D719D5E\
+94291AA780FA0E3303DDB73E9AA9261837A964084D945A88CA35CE8102E31F1B\
+891A7785E3416D324219237DC873EE25850DF83125791B6F7925D2D8D423FDF7\
+82366A0C462215E9FF724191917D3AB7DD659970F68D84F867152011D6B2557B\
+DB87EEEF55892A592B078F438A593C018B6554A166D538BDC630A9CC49B6A81B\
+B8C00EE34528E2FF419F7E7CD1AE9E253F4C7C7CF4A8264D5CFD4B2718F96176\
+48BA0C6BA94DFCF53B357E2F4AA9C29AAEAB860989C9C240392C81B3B81767C2\
+0D324A3A6781D71A3452C5DB0AF56339EA1FE17CA19EC135E3B1184567F92238\
+95D9343486C6419415F95B41A6878BF8D5E11BE25BF38610FFE6AE6976BC0DB4\
+09900CA2650CAD74F5D7FFDAC1CE85BE00A7FF4D2F65D38C862D05E8ED3E6B8B\
+0F3D838CF11D5B962EB19CC298E170B9BA5C8A43D634A72DC992AEF2A57B0549\
+A7333486CAE49623765BF2C6F15128427BCC768FFAA2AD31D4D67A6D252554E4\
+3F5059E15C05B72748BF07EC1B13BE2BA1572BD5ABD7D04C1ECB719BC59085D3\
+DE59EC71EB89BBD00950E1163FFD1C34C31CA110775398EFF2FDA50159C29B26\
+C742D949DA582B6E9F5319767ED9C90E68C87F512242EF49A455B636AC09C731\
+88154B2E8F3A08F7D8F7A8C5A933A645E4C49476F30D8F7EC8F6BC230AB64CD3\
+6ACD36C2905C5C3C657BC2D6CCE60D87732E7179160663280915D88938383DB5\
+421C0824F72AD29DC8CAEFF927D80786F7430B55153F9F83EFDC499D2AC15462\
+BD9B66559FB712F31B4D9D2A5CED87758726EC612CB40F89B0FB2E685D15C78D\
+2EC0D9ECAF4FD22529E8D2262B67E9FC2BA86796121F5B96C61453AF44EAD6E2\
+9498E412934C92E018A58D2DE4713C474CF7E6479EC068DFD4F55A74B12B2903\
+1907AF90625C6898481611029DEEB49BE5427F08FD16320BD0B3FA2BB799F929\
+CD20459FB31A5DA2AF4DE0BD420DBC74999C8E531AB43EBDA29A2DF7F8390F67\
+63FC6BC0AFB34B4F55C4CFA7C804113E1432BB1B3877D67F544CDF75F3072D33\
+9BA820E17B12B5F3EF2FCE72E52460C130E2ABA18E1109A8213344FE7F353293\
+39A7AD8B7906B2CB4EA95FC7BA7429EC93A04E5493C0BC5564F048E55799EE75\
+D6790F66B7C65776F7B7F39CC560E87F8376D60EAAE690391DA6326A34E355F8\
+58A0587D33E02239446487865A2FA77E0F38EAB030CC61A56A32AE1EF7E9D0A9\
+0C324BB54928AB852F8E01363852D0BAD60278F80E3E9C8B6B45993F5CFE58F1\
+5C9404E1F5186D51B25D1820B6C29A421DB3AB3CB63A1303B246824FFC64BC4F\
+CAFA9CC0D5A7BD11B7E45AF66F4D4D54EAA49866D4223BD38F3447D97CF4723B\
+4D0277F6D6DD080A81E186893E56103CBAD7818C08BC8BE253ECA789EEC856B5\
+362CB203BA99DD7C48A0B0BC9133E9A8CBCDCF595F1F15E256F54E0135274577\
+47C8BCCB7E39C19728D384FC2C3EC8AD9CF88A619C28AAC5992043859DA5E28B\
+B8AEEBD0320D527809563FC7D87E26FC37FB6F04FCFA9210ACF83E21DC8C2116\
+7D676EF6CDDAB69823AB233CB210A0535A569FC5D0FFBBE4983C691EDB388F7E\
+0FD29888818B4567EA33F1EBE997552ED9AAEB5AECDAE168A89D3C847C053D62\
+878F032128950C8925224AB093A950A22F576E184219540C5567C61149F45CD2\
+E93DDD8B48712100C39A6C857428834A1B3105E10692E7DA85737845207FAE13\
+7C330622F483F9353F6C71A84E48BE9BCE8ABADABE2808F7E2148C71EA72F933\
+F2883FD7BB696C2919DC84CE1F124FC8AFA504BA5AABB0D9141F6C689839897A\
+D9D82FDFA8474A25E2FB33F45978E16885CFFE5920D4051D8099AEBCCAAE0F2F\
+6543348E7EACD3932FAC6D143D0207709DA4F31B5C36FC017334850C6CD6F1BD\
+3FDFEEF5D9BA56EFF49B6BEE9F5A786D3219F4F7F84C690B4BBCBBB7F285AF70\
+75246C54A70E4D1D01BF08ACCF7F2CE314895E705A9992CD0184C8D2ABE54F58\
+E70F2F0EFF68EAFD15B317E6B0E785D8232E05C7C9C4461FE19E492023244D7E\
+2965FFF4B6FD1A85C416ECFCEA7BD62C43F8B7BF79C085CDEFE198D3A5F7908C\
+E97F806BD2AC4C30A7C6616CD2F92CFF30BC22817D9312E40ACDAFDDE8AB0A1E\
+13A427C35FF74BBB37094B916F924FAF52EEDFEF096FF75C6E1217726357C7BA\
+3B6B3832731B9C80C17AC6CFCD35C06B311A6BE9D82C293F96FBB6CD13913BC2\
+D2A3318DA4CD57CD133D64FD06CEE6DC0C2443314057F17217E33A636D35CF5D\
+974059DDF73C02F71C7E05BBA90D01B18EC030A95324C989846DAAD0CD91C24D\
+91B089E2BF8344AA287223A0C2ADAD1CFC3F097A0BDCC51B8713C65B598DF2C8\
+AFDF1195:\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+
+[Turing]
+0000000000000000000000000000000000000000:\
+696626BBDC6E09F6DA9ABAB5B56C14878246DF18:\
+74657374206B65792031323862697473:00000000
+
+000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000\
+00000000000000000000000000000000000000000000000000000000:\
+B64B97325A32BBAA3A967545D99A50889D7EFAC385A4A20E3C30C87D799DD84173802D01\
+6513022FE0FDCAF79625DA0FF7F66E76DA56926D3115D9F87A939E1C1B27A87386006244\
+B1A5360B0E5BAE03FC64C766B348A4FC18C9D95516B4BBE0F4BBAE2B:\
+42A6B922EC35FC7709EAE8CA0F6AA212DFBC0D6C:FFAA3441
+
+000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000\
+00000000000000000000000000000000000000000000000000000000:\
+0847AA490901FC9BFB07F12590622DC3E672ADBD42813B79BB28B4C4DDE2A519751363EC\
+00EBEDBB684E4D1FFC02CBDD1FA2E3F8E593AFEE8648461DCC054D32192A6517F41AA4D6\
+C3B75DFFBED80CEEA3D28397D6B86722185CA6BABB64088D13A75DFB:\
+53A6B922EC35FC6609EAE8CA0F6AA212DFBC0D7B:FFAA3441F4BBAE2B
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000:\
+833E62C8D5E8B0B723F8ADAC68340288319D6F73762E7655EE35F2AA8E2E21DDEC2C1D2F9C48A1\
+BC05DA8E7A87A650114C6A065E21DCE06142D4E6C40B4616AEE65E869C1D3A1040C7DA1A44E6AD\
+F49C51B12058824D79B7622614C0F8E1B968F7F99A94959ADF845B7BED3B5771B6F7E30C32C2BB\
+A8463B2FFDEE4C4623CB69C66A7AA4E1CFADD429DFFA3F9BFAE9C9CBBA44246765699B2F7211E5\
+4AB6793969835AE9F5EB2F66DA83EE07701031DA84F357B2DE473D7A7952462AB42940294E6349\
+C73F6B91BD769E07B0FD9A212D551A66E7D9B7C6F8077D16DEDEF30EA0AF61226DBA8333293870\
+C8693C8AF52E5D097CCD94AD9BE287139A5F5AC9E3448A1CA781B068F76B64D362AD99080B38F7\
+5506A5E81BAC8F4BD82A4F35A8526909D35023C3C7D9F13F54CAB1D16413774815F20D07CD98DA\
+EA8200D4399C43494F769000C84752A9B95561B23626E8DE135FF44651C7243488C1DCDCEC0A6E\
+C8FA9A1A6FF8706EFA6AA8A664727A4BD2EA3416E0631F4911F1D135CA96A227004930D8BD4135\
+56697B941F03519489DEEF118E44F54EADA077F1E253C33740CC79305F869CE1E857D368A7E0AD\
+8F1714FAF0BF4756295E9A5A57BA1CE7DF4CB44C324B62A78534CAA2FE00913638A740AD9225C1\
+6D29096DA4DE452AC6C1A2BF0CF1C5F135A1D214E2730246724A1FB37D7AE6BCFB19F3D191E1C7\
+5B024B8442:\
+C3B75DFFBED80CEEA3D28397D6B86722185CA6BABB64088D:\
+0847AA490901FC9BFB07F125
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A1D8F7780442DCF29F883A8379319273C91B3297E87441290B3121B7FE0F72E68D9D507703159E\
+457942A4F6A7E6C5C0D6B82204FC70605B16641376AD819C8268F208A3E727DE352FC57CAB0DC4\
+2FC9863C9952BEEA6A79D059FA52DCE5BC1815C1E3B2018E3A5CC93E86D162787C9A38B30808:\
+510D879D383902C3A1287F58ABC5FB35
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+8D8EA275C14DB64CB19760D598A38073E3BE840A016889DCCD5387B3052483E8B72AF6FC590FB7\
+C2365AE8F64EACDF07163D24EC80F390A714BFD910A15A7187CFFF1CEBB7F9A07E187C5E7D24BE\
+21B468CC90F6387D63FCD4EB8244921395C5104964AD85B8A4815BE83EA6D77DBEC292F50F8B:\
+0F57C4CDFE6F6317EC7C50CBE8100603
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+3D220053B6F702E7CAEB74DB867FA24D792968D4C2A59CCA308F806C3A5C00147A00293309248B\
+8A6EF0C50B7214B442E440E44991E419D4723CB59B6E42C53864A9AB62ABAF837DB330A5E1FA86\
+3FD5EF5D2ECACC9F04382807E537859E97D2615A9FA70B1BA046C006A37EA20FF3DF6123D0D2:\
+197F3A50A197CCB854AA6C85D608F93D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+DF9C919108DA643347B191C2332715F4AC01AA13CAFF0CA525E214659E928F8C2903673BADF322\
+C52BA8C60E6D682BF4447704C8B653AA386562B7F20D880B23A73E573FC5E6E1FA797307B0541D\
+42BA1DA70A7096235F28F059325F4B02A178360D14CCA63E1ECF4F24DCB06872416D72E8BCD2:\
+743C96AD88706814461A15FB11EBCA52
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+54B42471FFFD76D364CEE2013A5FB8B145915408860C3E3F6F56F75E41031CCEB973FA92C9E67F\
+DE4A0FBA7AEABFAF65DDAD8C6CA7AF13656867BA72ADCA70373F304E4CE9081367F179FC65988F\
+5224E6A4ECE1C3299C9ED1D0B699E4C5481D907877441F5E4B02526A91EB134DC7BE551137E5:\
+AFB5E81BC51672AB968B33AAB54E40FC
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+35108EA6DFCB3251ACFEA14C7978A1AE729E3E20D1AED75FCC26713DD2416855C1F03F0121A0DE\
+010C1CCA302706DFDBC5F0DFF3E6B3F6C0A6C90BA96DEC940616FCBD4406662B822ED87A5F826D\
+14C612C8A5BAA10A4757BC278C0C3638C8AEFBDE11608E30087B08D957B23A0FA7C73FBC4981:\
+ACCADB90F6DBC430AF5B9CACC069C58C
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+C77753E149061AC705815FBC5E6DF1E6B022BF45CEA31959D671A1938A0FA7622ABB2FFA8687F2\
+05A7DB417F61CA5968A88E6E5447CF2639BB8813C66DD0A12A8FCE3C4FC893AEC2B2A5786AA1DD\
+27BE50633198341E224BB3761381F8E5CED9B17CEECB08D2017D4800B584F4E078A33BC75BC1:\
+76DAC1C77B73EC50F7380129345991BF
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+E3D437F8F4E2B5C79BED77075E618682EE2823BA800F59FCE2E6F18C355314903FE3CD41349931\
+323413F3B85248D0EE4F79BB4AA67DA37CAF06902C99EFA396A79DE4AA2CB3B0E67A0B87356D63\
+261ED20287425AB3E7455375AF21453536085D529D3D07525FC578455D9E43D529A7230A2510:\
+6E35E3D8E6D332E27C0BE03C8A5471A7
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+334554121BFE766D9E1D99C66E66E9580C9362D6A239A8A392153FB052BC9D5BDA4AA20B28C90A\
+16A40BB68240A41A55D5FC245FD5CEDEBABAE81E92171B850E50695CFE6E0AF004FEBE4D8AFBC7\
+8DC82D270CF66176F0B00BEB5F14D2FD261AFEE2A2B49370E6298EAE5DEBB86750E8EFF5974F:\
+C8E48F6BBCB573B8006B0A6B0523FAE5
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+631D5CF348368BC46C49DEF8FC8BE88FB53A3D0D8B6B19D9B4296D556B9DAF82D9D3830DBDFA74\
+6E09EABAC61E54878916966ED13F55570A76794B52366494D46B0418927116B5F466BC262F1655\
+FE2325D89FF2087F6545F0CE710CA99F603DB5B7D967A3EF00694F07EEF4D19920E30DFE3640:\
+39B1805E219B7784D334E1DA137B71ED
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+44CDEDD31F2EB9D7E5C52BB62E3D89272472981B6A56B0D0056A6210A836F4C7CE02BCE4120FDC\
+B1F8346810D4273CE45A957FDB4534B332D05DF7BD67D2B116FC0355AD416C77D8A42FEFF6CD9C\
+D4986F5CFFA6E85F30B5968D2D11BC407309B7908C7EA28451B85B3EDF3B1081596E300890AE:\
+A783DB338CA910BC771BE1BDFFF3D7D1
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+8F5BF391BB2FA4A3D727122BC05DEF4473C936FFBFE6E0A37276657418F18235A84C9B1B817BD1\
+63DC8D414F61AF31E1CFA51CF692952CBB501F117643F2EBC7470C3F870CB173C55D93CF810D4B\
+BA9AC41570A93ECA91CBB204A006A484956AF9473C50FE281BE39EF0A23E324137BABD00C4C6:\
+DE89AD958277237ABF4143BCA129B902
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+92A18810C64D4598C7CE3FF3D2CBAB42CB3DFE4976DE40D95621134C4BE3C066D11220B2E68DC3\
+054CAF977838AB5684214FAA05D27E5E110ABC7B719F184A64EE825A730D9B390D35195E452FA3\
+362B0E6880E547F983ED4C7199D321680497C9722C930D61EB11FE15807CFCBD81036D4AB6B6:\
+9BAFD22926AFE2BB782E07E3E9713A47
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+BDC0B3934130AB769D5FA9A2D43BCF3B3BFBA90CD76F04AB3955B287058298C4E627C2AB7F3951\
+B5BC44DEBAB33E3DCCC471E17162338C3BB42E418B7E33D5275547715BC7AFB94669BC5E3D30DD\
+A55C91D2BA23396ACCF20094D2CBD425CE273BACD304EFE61A01768C077DE5D4BD38307C25F0:\
+9AE5CEA10D25D4980E0D848D14166BD3
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+BB0FC7E77790B8922EC54D8EE7B74764C057B6066CA342FD2BA2FF5945EC9EEFF49F568011C64A\
+039CA7256ED642EC7CA86715293D8A94D3ED32E6EA74B4E437948187C29B5EDA90468FD52B6AE2\
+711D9B72B97534914D73C6E4F24D8B8D4B78328C891801FA94C6058EE687BCC0FAC6AB3E0775:\
+5DC3289BDF8E0AC2E11A6A846D6D3555
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+749223E6659B4990E3FBD44C422131460CDFDDDA81A0A90426114C09183B308FDDA2668540E468\
+3F0D2DA5BA5225CE30BBF4BA350441123E390D85C0A90CA5C34BA7D4624024807BC42666894A00\
+D2A3AECC60308117F3C7E14859CEC97553145FAE37796DC3DD869AF7CCD112450DE85A13FE5F:\
+9028DC083356F6539CAB46B85943CD28
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+7F55CF196A7704A73CAD784B3C9747615CF0AE344F576614CD5C4448979D1F2F58787B25DEE890\
+4A6DA1907ECD3B9BF7CA2399C794FA099380D1E9396D170B2CA89D1540469003405160DE22F403\
+E09D75DBB55AF8C8F346260569D7B09242EE7AAD06BE1B46C26DD9F72E6B7F99C83DB9B7C194:\
+119830CB54051CF9515FFA349A97EAC9FCD97433
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+66881BEF696C04B312B95D664FE71EEBDC95EE998C85B57D6237769EFE0D7D471DA4D2FE41053D\
+4DFDE1442C8A3EFD14F22C41292749375A902746A86B117929F46BED63F16D94073836DFAB3201\
+419E728F2A8901E4E543A5C7C021FFB321F275A4921FEA3F3A2CC54E05CCC985AE50BA731B6A:\
+1A1412B8FB13AEA84475FB158B5EE83A99DC560D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FD771ED1DBF5BC652A502E75BF74251FB72F67DD83276D6238C8A88A9BC667BFE7FF46AE6B62A5\
+BDA67499001617893DE1CB83BC08793DC6DAEF2A294315D53F3F6E7AC704350C456460A4FDAF4A\
+6F683664CBE88C476F2AE6F47C7B23AA1F024D13AA1DAB8F952D4142B51C984E55C2899862E8:\
+A6E318E21447AAB02FE846D51CD0CAFE6D020F6C
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0523E8B622F04A650A50AEE32CDDBD3A4B25DF714094A6CB5783898C7323DCA8986477FE389AF9\
+42668A44CFA42ECEE4652A1709BED798154E5131F6840726E3EDD8F7A5374ACB66B25B60E193CF\
+6D2D7E1212FB04E841ED5595B9C38020433D9CB390BBA523118206A0BFF01DC67E0D46AFEDF6:\
+28845F13275E38336B32B99554E6F3A195D1AB28
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+1142B12772A584401A94ADF193D301C320382C62038452064C10B06B8A1B311678CCC4D0D2BBCE\
+25DD343DD733D4D7FD5EFB6D9456C7F690F9EFCB28862E2789316CF649A3D868A6273B915EEED7\
+A5EB401E59740D7899A7E7306E2563F086FF419A4827143DB9550E145D468876C67F33BFD092:\
+FFB05F0DC00FF74F159CFC3CE7B1BA5A09779483
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+02B4201C31F165C497154DB1EAFE1C082F88931B9010FCAF8E110926985C37A9BEC4DBC680ECB7\
+B9F45D024D521299466AB9246E7F4E40F8C5B402B5DA0A318248675B6A006B67E5B02198EF6063\
+24CAD5173E6A6684715CA91479B352E1A5711F6DABDA6C835BC1674E74504E02717EEFEB26E6:\
+FD79C0D751B8B9DA3C40C85B944EC105EB3BDC1B
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+5E3AA5F59F746A8481F1F1CB6D63822AB4ED3D4B7F94304A1C0E9DDD9646C617287038AEF0933E\
+90C523BBD736905EC5FD0332356C24E4D6B006D0FABCE86C09EFDC958EE748926D6AA9BC37B1EC\
+879FDA063FD134705AB21439768CA8791A6F7D996A722B45707904BD13984D61A4E5DCD587B2:\
+18A0DCE520BF4DD0724F5173022106C8EB370B5A
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+6CE98801210B00DE4F71DE0CB62E2D281C98D932C96CB34A009E1F3430F50FE287D66CA2FFCBED\
+C97EEA7CF2FAB70E3592C5CBB8625723B91A13D078C8DE1279F393D277419FF78E84B49180E7B4\
+E9B3E48F0F66579AC34566A271CE963581D7DE48E747D79660C78ADC308347597DD7862FC72F:\
+7480690DA8C0E3393A161E29C312139B007131A8
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+32E8CE4394B86237E45BF3CBE2AE3355FECE63BAFADB0ADE19C6EBA100ABA5FC1777688CA8FF0A\
+79F3657688458E4BAA47E9D7AFD9A4C1243F5F083809E367C59DDEF9A515D3CF395FB5C0AC44B5\
+F5D96884AF0BF1368C4D00EB8E06F0D805496219D9D8E8866E901C592D60E1449CF50D20E983:\
+0E31E26B5374E9DE11F528A6E7E57B03CB6B983B
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F76855E776AF2E29D139ACFF506BA0C1C917265A172242A2A5652FBF9D8A90872503A12F9A4620\
+11E0894D9E34CFF08D979F37CB2553889A2CD0B8932C2B7A47130C0F724DDA8EA904F8D9FA5127\
+498ECAFA9D94D392642EABE1BDD8433A1CEC7ABB0BD065D9AA0FD04B68368E49A0FF08D10117:\
+B4B6FA36F7F42D89DBDB51D887475D5376CC27FA
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+7E42E03FDB2966552705EB79ECF02C652B2A62EFB7DC204E25439E7BC5C41D80F90D756C14A6AC\
+F0C79C15975B713E547623F71F225A073FFA501202031C6AEFD6D794B093A56E1F88A5BD8E76D3\
+E25921E1BD75B33D9604820A5F92415A3BE2C028BE60D4C764890F7FA8F89E9911DA716E36C8:\
+C2D17692AEBC93A9CD87248FA0496EE027B354CA
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+295C77B2D2CFCF4376DF06D4CB168A5FD315A46816986A024030685D35D6BBB62E0519B8753ED9\
+E6919BB94A828A172B9C01DCB6058915DF9889D1AA0AEEFDA89724D25FAC07BBE1208BEE8A3CB3\
+5509CB9A12AAB14B75C4B0FF0A8C0F444AA96D6C9E3457669C3BFE0AED6E17599A53F614EAC4:\
+1DC5682D883D41FFB9C6D9146A19DE5596351DAE
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+D2252875127726975223224C5B4E66ADFB573582539A796770B84C86FCE47B886A1CFBAD755C15\
+C49EDDC9932D3C0CF4FD41EBBA79D46C1A883F1B3B2B1626BEFD26B4708A26995C896B90354300\
+F1BBA09945D441C7DFD1EF152154520C1FA86D435C6B3205AE6FBE012F835C6B621A73A98B71:\
+DBAD2FE9A4B89C17AA39AC48BA3A1709543ACA62
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9CFB54F9B1D66A5A96EDF432EF62841E52D33E90E399E049C554DE679B887E056A8F78D0653206\
+B6B80E0DB45C0AF1A36303159F4D1EF034B28A4835D04EDF61251F9C40493CAE5695EEC6E10AA0\
+91B760B7146159A491CAB476CCA1E39DD1D1B3A08FBCF327C15122D83197909B8BE0F72485A2:\
+E4C4AA2357758D79D8528C833607FA757CA50D6D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+8F0A8C023B79F012A1A2788B5A20E5861397481AAAAF72E70467C06209B0049E7C3FB8762A31CC\
+F8D2C939C49FB5A0D31D8C64C78B2412EEE0185A846A8AE5974A1A0D55DFCEDEFEF3644845BA9D\
+17229FBC258C59605F75071F356C01C4959F7F1BD8FA294D65037C077AB2CF6C58B62759E8D5:\
+3264792868880D91C28949655BF9EBF87779DE78
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FA183B4B91F78B2D16E8B7289D2D86259362F253CDB65B0D1C2FE45CF7B78921EA7BBB516327B7\
+454EAB0E3138AFFC09BD0DC6BD85D264321D33429496098DBA7B5F7F677077FC907A717E93E141\
+732FAE7E4B68DB130A928CEFC90062865FD8F83B071C3F22539AFA812955CE00B156E34426EE:\
+1D297636D3B1B64BC13420645E9A6CE6C6699289
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+AEA85A57F3F752FACE718C71531426067D6FC70DA997D59AB23013635D77F65D92864D76272491\
+71B2E655CDEF807E85D86A42B7722047DD38434975FCD6BB71A56292938FF230C75FDB57D9161E\
+DD6C64252AF0B39930DC8E38748B0BF399B93728189AEC248F9322455DCE6E9555B9EA097E42:\
+F0E946A71123EB5A6DE6B8BC44F843FD45285564ECC20881
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+B36A7DB00583F48EEC653314FA1C7D2B052F34251507FD176F12D955F31528A6E9FAE66DF4BA7F\
+2787982E95CCF1FC600F2C3DD7546CF2B0ECEF1A4E02111F391C99E6E9C51BA359F8BD211D2554\
+89F1C85D57D867CE43377B4674EF4C626CD7F40AE55584C390D4CB226DD71C379A0D0C930425:\
+BBDE3BFB69D2301556CDDC0C34DA8827D10217F607DAE9A1
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+6D608E00EBD99EBD4E2CB2C8159969EF2E9B21212FF4A1FC4165E4E048A4569BC1EAD2D943EB96\
+19D68BBB806F72A5C0ECD1584CE7B0CA6F322AB0467B64318E3041E5B0468D88234BEDFB91FDA8\
+026551BB4585E423D6C2D6AD0A0909B9849A6C329F9F44CB53B8AE2A7C00E3C3AA1F42DCBA84:\
+D09DEE33E299290B4FF3262A259BB29BB52F584A25723F0E
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+95CFA8627DF9A518B3ED1A5DC93BB27AF30A9B37C46E1313FEA680F94B434B5A39A4DD74C75C9F\
+9D1B2EBB7F154436027F3A6C6EDF84DBCFF604536409CA6B8FF2A66501B02AB95BA0268A41B511\
+0342976B9DC96E5F2B4F7E32979B4F6C275D3BD0CBF7871AD03FBF78E383A8EA9E7C9E9082A9:\
+65298E00B106B798D808647F16572A09C15927E24B8F7DB6
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+94D2C237DBF27F6D25B1F22735AC74BF4F92D0A7F8378DE493F82153DD3A28EFEA69B99A4EE1EF\
+ADDE786134327D0AC17585C66F1245466FF98F6B41F69D84333121603DBBF76B654135BD4271D7\
+19DA93196511B5DE8B5256A906EB4341C029A016382C40B726B30BC46B6CBDE97CE6F13739EF:\
+0681EB738C45B44BC134112E8CB420A1C3780D71A8413422
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+160B99E09742B020BFF397E0FB1890052D1A03B145C8905FF61A604B19AE0F5F7FE6A8AE1E75B6\
+502AD879DA2D081F5C6CCEF60C2B1E4B3C5023D9271857BA043585E87F2B480556295410C0AA55\
+642DC4B3426210D7899369976E11F4D5CFA86C27FF10A5C261EEB6D70A093F20733C34EB3C76:\
+75E916E939A8B762371C349082B56F7CA5342D240FC310FA
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+2E8039CFD8E4BDC9BF718E5FF80E19723F9E67042D4160106E50620362550632C08DBEED7B2CDC\
+71DC56C452ABC0766D883B657A04538F7353D9ED5B5BCB65FF035D8CB97051D2A5FD2C96EE1BF6\
+AECAD901E005D2B6A62F9FCEA63FF6CEE0E1AD27468D175217C50FE00F44C23F777CF551009C:\
+B76EDE68222C46E013F96F2112E6ECC52C079050BDC7BDFD
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+200B3DA16D1089B0EAE8814400688690E611FA120459AC843EF81AC08FFF4589B5DEB62944C851\
+667E6CFA21323B1BB063B4F803A11AB28856FC81D11C4097E2FA710B2AAD0AA0101F7E8B575F63\
+E74960AD851D055039411CA2F3029AFAF2E8A8B85EFB677958BB66D7F8D28483DC2F3AAD2ADD:\
+C119544812869B717339FCA3EBC5DDFEE645DB6193E6010F
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F3B0AC1ADB198D82D68845EC4C0F354948FA2834A3739C8C8BF95B674A5D7A2C811AF0B517BCEE\
+62D9D5365F44A0A5B5C3B75F952383AF0248CE8E728E64959B672162D44E15CCAD0DF0D80EA2C5\
+1BC163F25AECB4E49359C93BA9338DC57C5AFA50FD7371EEDA38EC1BD0D77913C64BCFC93D5C:\
+E866DA8B4439CEE798D394FADEEC2108C5C2802829C1486F
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+E01640C6FB90ADE04D5F4BC99A42EC5C25E27E4EB59B2991FEE3B3B90119357A5F6E6FD4EF2EA7\
+52A79FB92A3133541EF6DF00E8B243A47F93485BF4110DD61AFBDE83EA7C0EB4A338849130D9FF\
+FE2F18EE7E32F3359464A488128559A7A61DAD85DFB909D4A4C95D321656D2C7F3B6D9876453:\
+B1A1E8A1CDD487E053E8EA1A85366A956116B0BBF3DBA2D0
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F94EE0B40A4E97A792FB8CE1A09E0E2F1577D29FA6A7EB0517DA02AAED5A952150F57E105B9D55\
+EF9440F591A19931965F78D326A0F45E6BC179AC8B826872D3BBD1478F43B62C22B471EDF82BF4\
+E6ACDAF260BE3CB14F4A70BF947F0F70ED5C133FCFE06A805F06CE41FD4340A02CCED54C46FB:\
+D7C76ECF8F3E333986D0727FEB74A933FB078ACDA732E8A5
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0194823D67E3D53DFAADE5625420EB0BE7E58C254E47A54858C52F42427005D6DE162DC1FDAC14\
+3780C202F6E1A0573250C2B050B4985B147440F024E0F7222794D70EDE913CAEDCF4F997E32402\
+25B5EBF179D179E1F1B35146250D42FF59431BDCD213DC2E0E7AE0FA4C20B1483B72A225C9E5:\
+4043315440250D9D80D6CDD850AE06BB000B2CAE4CF3E4EC
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+DCA07BDA8327FFAF65A6200C0163ABAF7B267BF00665319154CE603BCF1D971923D8F6A877D3C3\
+C991CE741F92AD78DAE00B6FA8A07F4B5521E9607D248B25EE2A6ED0A2E62032E3536FF5D420D4\
+C3197D24F79019ED6F98D0A91D424738E82FE4DD2F6EC8C35C5DF2A36D0A5F6911C3247F3FD2:\
+2B9B3D6C5CCA6FF1CB13E304A3E33E359AE5698C43BAF498
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+4ED372793A4B85C9D0FF69654D4BBE78DB2B4258A385DC046C094629AE232F136E63EF18FD3150\
+E9EB93504D06B5B2D354D1D3DBDBAF1B99599435B4DCC0419F278868465B43658ADA435E6492C2\
+0438DCE19435323B5E6485F384CBFF46D166E6E3CF97F32095C03F388BBF4E627A26BF35B9A2:\
+6D7A73687DEFAA9FA22344CCD67BAD74B4BA6A058DC7BA9C
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F3D3E04261645CEDD6B423A102168281535EFB7B43EE0F07B925B710FD6171E8C38F815992A133\
+DC16B6EC99FDE8BECBB29205C185DDACEFABBEBA824424C1F910DF7FFFB81D934FA2FD1D41344D\
+7397BCA30D26BA0EE1CD7A430FCBFEE31483C6EFC9D577A2E3CC0B8C5A1F6619A1C0F85B0B16:\
+C49C6CFB09608BD78CDD826009220526AA030F2216DC6229
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FD3866800048B2E0BD760ACDA846843D421B61204EBD31097EC45C6CAACE840CF611F01A9F5EE7\
+DEF380269A1C805239080B88549F19FC30365129B8B75117C2FE3C8B8F98D85CFA9FEC85BF5D95\
+D196F939E8A6140EAF06834DF13F0D1D4A3630E350666BAB04582DC7C6DDB08A6CEB8C54DAB3:\
+55D7A1004D57B763ADAE222CC95C90D91453EC7A006D922E
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+647281CBDEC5661CF5B3BDDA1E711505F4422309C4079F9D1B3AE4A49866D9DE180402A5300CA4\
+F65603DE7A797F497C326342B6F1DFB91B247094C99358C0BC875367F3407ED1E7BEEAB674E575\
+9ED55ABF01FED9AA360F4F049C4DFB60EE680C6AADF6880C5A52AC4592A6BD8A02653231900B:\
+9E232577306C0F1B81125646AE9D18C4C9CB5A41BD1F49C2E7213C31
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+5657DD6E9316DE1934E7C04681F88549FF92BBDC43E1DE589C08AE609119E05357EE5A5FA205C2\
+ED588E7EF53C316E3C5023923E1185352DF17605E0AD8CFDE15BF56B2B3C4015142B3D9B3B4893\
+241150ED83E5B956034F91033FC7C83749A77B08C37AED9E919781265E7A41CBC32154E45FE0:\
+64FC422E55B6DE470C8EFD59F894D238F566B94BDA07916ED9A7EC97
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+53368F208092A0D7B842B885D2E910F22E9BAFA33DFAD2548139B6FFD845C1AF579B77D40840A6\
+95A6BC0FFF8FFDA411A42153D7A349C6C61C21C78D9F664ED84AD1FDA1CA7FAC8676525E8011E0\
+CB22E89F8BA394B962F84CCB0C7117388CDB6B0F6C4C1E0A466F48395472F3BF02363C24E81F:\
+5834B00FEC3DD4650BFAE554545628CF93E2C4CB47310082888295BC
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+4E4E29CE1CE2A1BB216F6BD85844244731E8E2998886BC15234DB5E95DA1FDF09DA6F8491590A9\
+AF2719ECA6860F7BD1D2DB7FE6BB05C1C38DC2402A95DCC6EE556524E373EBC003D56EF2A03B91\
+DBEFDB3EB0BAF3BD0058B9BD77AAD361655B42229791D6C6684D1DC62BBB8A69E0B9B3577DEA:\
+AB02C30031CB74190E31F994D3EED4CB516002717F7F259BFC8CAA00
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+358996611F1464D8F0EC63833E3354C9258D358EAAC807DB66841FD48F5711495FF4C4A278018D\
+3AD15E14613B4EC54AC78DCF4A7EDC299AC237213882F10BCB027B01DB9B453BD0D33BD88531B4\
+0F9977FA9BB54B9448E1BA9EEFA984C826A65CF0D241863B945B8684F59E006449A740C92D58:\
+9C697CAA308F7E76DFDDA9588D9002E9B28C8FF79858C7E02D4BDDC5
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+873EF326CFBDEE5506BA5BD86EF7C37CFE5F649A4064716E38135C9FFE206C1267CBF14A1646B8\
+3CA770B1F86D1EA1438C216E753234C2AA08475B42883DAD3A2B67892E01D6D2DBB8CAA21D1A1C\
+87B66B895842D4E3F3A2E3753FF936AC8AE734D9A2EFE9789830DEEC38ED8AB0F15F1A91ECAF:\
+B2F3D97249C90040B9D09F0CF30DAA31BF586A7717E911D1333060A8
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FAD37FCF8378422A2257170B1B87DB04076E366910CBB6381B822A8F66CF6FDAEE1953F4A5B36B\
+211B0B73B7E93E3566DD9CE06004F49B683E803D443E601938E8C84C6E2757E4C1666002B9C915\
+412CB719129DDBFF748E1D379B724C09082DCA39B056691B9ED21F47A4E3857C498C63E9E91F:\
+39D944EDA34DE7D3E92BCB1996196BDBE7D0D6AEA85F540333252008
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A63D061A64D62DB78C51E8DD7A293BF15CDC65FB4A182296B8804A902D039925F13D5D9DE52702\
+7A116D581D2F77FD306C6D675D13526A4C3505364670C16139FD5D479F9B9363919E86B6C33A56\
+28FCCA1970EDBDF2B683FB9E54BFEEAFEC001551266133F0A5E72FDB8A0D8670EEE71F21BBE1:\
+59ED6E2136849971FEE7F5DDC529B7CE30C18A05A2308480FD792A5D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F8B9AC6B917837E768DAD946B8274C1A1623846A88ADB68D5A75934E8C3BF3447971FA635FBD24\
+0E626F226E5F00E5F5A11F5297BFC67711C557B308FEAD4A9FBE170793814F0E78FCE0FD18A91C\
+88B93E38BA31EA1AF2A173582DC432C5A00D1B08BD87D6AD25A11A902A9AA761911E894C8E15:\
+60BD44AD1B7E9895CF569D087BE7F8AC9EE737169C0861A0B0097A5F
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+417152A3907586B9E8F59D2F62CCEA5FF9556A6B286B61FABA146B067FB56A1B549D9E9409228D\
+5C5FE54B577F6902ABC9D4D5F0258D6ECFBB214E0A08A361DA479DADDA854C96EF80CFBE8BD277\
+A1D01D801F7079F94B4B92F3A42587104B44259F894CA375C0E4597926EBF769203C922AFB0E:\
+7F050CD0C1D36397C06231716434969D8D0514E92FCC1D550B4B2933
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+B2EB626B3C6A8485425F75273E8B771B263F1CBFAA40A0786ABB5042D04C7D6AF7FF96B63842F8\
+E8FBACF665538964881BC1BD0A0F0D33CB038DBCBCBEE96459282054BDE39AB31E82E7409CC564\
+B2166E6C03DCABBDA449E99BD094A32942ED21BA03A3BFD93620DEC36A86F299B7B018F4D325:\
+63320839C85CE863EE1FBC962C057C623EA2531B9854B58C3AB10216
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+076777CB3F25CB914EC32439031667DDFAD29EA5EC4DAD2A8CE97134966A4B21CC2374D4C31103\
+6CFC8175C55A9C4D1647589B73A8866EFC30BA1E3F7B7688F2F819B868B884111A12E90D78B3BC\
+350C41BF9EE79DA16D27C1C28ABF12932AF23E6F57F50DEB79682829A5FB4D95CCBCEE8BF01E:\
+09292F664BC64AE5A21DBBE7DA2E2EDBE3F6D87446A0BBEA9CE7E6E1
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A4ABC46FC552EC00DA3745959C1198733C064521B7BB0E8F7F5384051A4A23C6FA5CACB2A762E7\
+5E8FF44DC41DB1B1B3A72BFF0116DCECEEA3257E88FC863E562C32B9BD55112CE7B2825DA8BA6F\
+ABE9458BE0ECA65901A671FBB7369B62A3579C47029F6212F775E01ED3BB9E2A70284D49C9E3:\
+56D4718FEFD691064778EAB35BCAC749ED62931F9A5B46137BF6C4CD
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+8D8AB1E9E8385824E18C6560872C73D7B2D567B9B4061EC447B0694B3109D05D89955A4AB47541\
+2223BE082AF95066146D77E22EAA042DFE360AAE8000FA375B4185DC1A056E48DE3E6282F4FC2D\
+9BE215BF09C7C5ECAB95CD29E9286542C35654AB23982221C2BF5352358D8FF27A6BBAA34AB6:\
+E48054A763E7A3EA9CD093B565D664248218A872E58DEBBBE1419B91
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9287CF8EF16BFCECA5ECEAD6AFCEF50FEB39FB637DD78E0C875EB68B162A70EFF53C08FCF888E4\
+14E4EF0AF8793BDB5F5641671BD8616E1610264B364E4BC5584EFF564FFCBCED53A9AFCBCD205F\
+8A7C60F2125550D93102121A25E233DA212FAEFBC7A453DC8CE2F2BAB2D3D02CC1F41F7B677D:\
+F0549B6B0B6F1382593F986E3AD9BBC541AE11D1ED9A2C4D7CECD236
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+2DC8D0716265CBCBFE491B26B0CE8144C51636D7A5E45F4558DB6EA78AFE5CC65EABB4CE1D3E4F\
+D2D1C7266767DB75B331635DF7CF3E46432C2D37ACF08BEFC73C9A544B121AF5B48FAF56944357\
+2FA4B3B4F9FCFF215D0D813116E398C1945F2B072251A92FF2ACC078DD82E298B63AC9FDF2CE:\
+81580051D3030AD104AB6D1D0A03E00AD011BD5A2C48B407DFE79188
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+6188BAF16DE19FFCE9051A868B3746988E699825AFDDA484C242FE08867E19F2BD27C3AAFC51E3\
+856BD6ECCD5CAF43F79B4192ADF5EC7B13CD476D6F8566044646DB685B32AE0E83F23A33E31DAB\
+A93585272646A9CFEE0626AC517DF92642DFBFAA26BA5E2158D7101A7E3E319AA200DBD0ADAE:\
+7BC01C35F8977BE59CAF0D4139A65D1D52A3088482C72B3DCDFB30558B1BFE0F
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+35F87088FDE70BEDAFF51621580A0032902AE95DFC7BF73466EFA2CC5FD2ABC72F4B958352FEA3\
+3CDCFE675A0E971A9CFE809794E1DD4C951548BDD9A6EF3A2ECBF2C404E291BEF95A42A1A4EF22\
+85304E7F23157F4509BE3B482F59067143BD503210208C6D0AA05DBED3640F30926C04D0CEFD:\
+B0E8BF51536BA3FEAB51E6480730F80114F50DE1A41EF73A477DC524809CDB98
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+91682FF67AF5D75F08768D1385CE7257FDD619992DD1634F6E6118BA4CE94EF9D8F6D620E94296\
+C523B8C780BC50F2761EB35B0F243788EAB761951FAB2F7742DB766E80E96D1080E5C0C6513D68\
+25885B9F865398D7A5CC7CCF1A9A976302B4933EACC4CE9E1E213C7D95326D70BDD34CDED8CF:\
+EBBE1D35F01304D1CB6B400664B70E57C80FAF6B630A6719826DD79E4FA8200F
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+607A183B7C5F03BAC0D00D7DADC446255AEB8C78078DFAE6B167CB43A25815C295FD4D134EF8EB\
+9A5858240E39CEC6D4C9519D681BF884274248346639CE90DCCFD55990174B960817ACEA2508B4\
+9C9263ADD321F11F794C681CD8D191F57911C60D9B7AC6018837A8A13651E6BA4DEF8E890070:\
+F9BA1DFA6B93C46AA579CA6BA81AAD50B1E9B1EBD81D26FD36B20C0EE2C251B7
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+82137497F0E3EDB4C6AAC483924F051E5460B8E91947E0A3FF9CEECC7645E519D262A4F1E0611B\
+CD3760C4D1E8293E814713C61A07AA7C12F1C0F206C97DBEFE191170FBA988347B52DB7241594B\
+252800B7667BD1DE9042F4B88A51B13F507925254C0A03C7AE3C704A7B4F9AD96AD5992E9997:\
+DCC24C1F5D2C7240EDD9BAA530E1BDD68739F0CFE59226977C508AE8D4C87323
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+CCF9B2CC2419FAE9D04C92E246385E4CDD87E29213092C677B9D699B7905AAE392AA270DC013B3\
+FB7DE8AE837C81023C8EDFB0F03DB6A548D4D460075490507AF6DB17A32F48C1F99A6069CA94E9\
+75D1FDD78271EA47AC9EC196F37286B53A8B540E44A8B8835709DBEBC7A7EB246971DD0F4722:\
+917D882FEF03ADFD6669CE45EC62CDDF5FF1C03721FF3193C21C5930CF1272EE
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+05164B3F11E848547D665D426B1145559B69322F8FBF7D28B4E0E96E59390132AEAD0D39375B38\
+3C216728DADAE7279CB9059E725D3EE4772CC41BA8058B88C5A0DDC3B5E8F710C2D4CB55B4A680\
+7243B569440FD548A13F2996269F1BCD38911F7B811AD2204D35DE8E99FF129E9248CBCDE2FC:\
+1FE748157BE5CF6DA0AEC0DCA0E7720BC1EFEA43BD409F719FD2A7BADF8794CC
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+6ED1A789681A608231E66A5E07023C61DC71901C4EBE810A22D1416C011702CC66D33C06365F65\
+055ED9CC152B7F6729F9A69FC5957D89FDFDCF7955156D0C688D94588FB73DFBCD5B7CDF9E0FC7\
+8BE9389158A395028ECD0D91353E3692192481C676503FB1849082FF38BB90DA4FDE760FE5BE:\
+2C6825ED9252193DD2F4F96CCDD9223DAB33524EBA2DD3D254852D8F40A4FC6D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F4B7357D06DB0100897B838AF028EA1148D7D955653E1ACCC1FD919BDDAC4981329DFF1288E06F\
+0E2805468F6BBBE88F3E27ED6C5B73ECC63D946C4B90D841BE5D3007AA205E2685EB112C7D10D3\
+6E3F0449A4D2F773379722846F4CFBD85060025C41650E7AAFD97D348959AE3652A8E93F80DB:\
+0ABBCDAA3E91D88CBF4C38CB284BA3306FE470A1388C2B96E46936BBECE1CC3D
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0CD874631E7080D093A47992DF9816EB03F83A23D9CFF79FE7FD068403FF3E0DC3D4D881952B10\
+7BABE1C83FA226A0D37DA5621161F478BE0E986E76D477ADDC2CBCCE3CA94BB29DF6E4387AD9D6\
+2CB8550553EC5D19A24BE2E7E386AFF65331483662E155F38EB3DDE79F54A1C75B0AB9F83E7D:\
+800A51F252F9E6D431FA3DCDB426E3D4BC3E1A34AD5706385F8D063FF5B716B6
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+1B907B35122B8E5D9CB6EC43BB6BF6F0F5C2FD7B65E98AE1F4360E4B4A9EA3165CDD59342B0A22\
+54AF793A09E2AC76F6230413ED204ED47B9836EAB4DF6D82469CFD1B5393E39DFF9E0DA74EB56C\
+99BA357439F1B01C158742C9CBEE4F7CC8E15AB181DAC526380A2CC650F7125C93D20AF80640:\
+E14E65EBFD403DE7EF39C663AD4E08B99ADB01D00B2AD024176E0EE35CF11A42
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+FCFFF45F031BE2C3D6B85032C754D39B83688D3470587ED1D13D9DFBC74CDE191F33D5567BEA4E\
+3665F0058AF27C7C8FFC45EE5F012CF340B836824D508EAE7145BA2067B6BC926C5007F7803FD4\
+67084B06EE858F1A1059C9EF0CBC85E9BD7C454010AFF2B0CA04A9AEEEC54F07AA48634A5F53:\
+8FA304D1DFF976D5649AF564FC3E3917AAFFA59F0E4D560D415F27490FBBEC37
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0F34E8E8517206BB8EB2426A684694052AFCD7DBCDD3419303973A24113B58CD08530000527098\
+E72A0EDDDDD78380DBDFD60EBE30D5150475ED2C95CCFBE860DDD94BB45F6E40E81C5263C7B2CC\
+B79F1C6CE75AF6D2F1E572B43823EE63A3CA73E1256AF44FFD6F0C67E396348D489CA663E478:\
+FB9E93C4F43B223837F9EA773DA68A03842496B8E2BBE7141673855DC3F73114
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+32EEF5793FC730D20B8A8B9DAF7E54BEFC79B9713F8B19FE252194831E8A2DDFBDE392C5190573\
+62EE1171331F1256120D693CE463D187A5ED1F8FDAF5D5BB9D483C3E912DE8ABECD2E70EF9D921\
+E1DEBA85FE051BF3D25297AA9EFA0C8A836982184254703ACF1694C65A1B2BAD491D9395FA1F:\
+C506703121027BCAC2DC90AAB30B5CD30AA87773B98D3B182115B8F1E32F4BE7
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+5E779BE50FD31E25442C0B04D5FBF92E83FDB492F22EA12899A435E468C9CBE839CE66A349B299\
+1DE381389A310F653D85D972B9D9F2C875468EF1ABBE2C9F8DECFE452055164A1EAEFF4DE0962F\
+B3E34848672D1D1CC1F91CD4332D520254C0A9B49525608C462292CC4F189B15F4FCE120555A:\
+18CF7B4A85C5D9901E1D92DEB6487B6292C0A94589183151575207C4F776F4C6
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+3586BB52787EBFE1033261802E9C88E29933425EDFBB199C7650FBC56A2223EF0F12A7450DA282\
+93812ADAA43E5EF663440EC16905BF2EB9E4626F539D94D41D0CB11231D1BBBB145A3A19E384FD\
+645667CA2104A0C1D56F90848508B2D37D194AF882EE2C198EBA68A10B112A3EC9E6265B6726:\
+45DE118319AA726809A10C56D46915A88595811603B9A146DDF183D24DD0EF1B
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9ECF899E3F58E481103B201C076C52EB93148CDE72B6EBDA0EFCF452E13195D89FC48BEF1A9117\
+7364C49DAA87F296CB8B91B67E40635648445984928207379C85E8126D94015A223F2DBF696FF5\
+3958AE5FD52E9CB8F5575730A874CFABB1E097F85E69177A47776EFB1C1CF90C1A1D62CA34BD40\
+10006E432403F8F16012F6F4B440854A19A208629AE54BDDD860A4BE4A1159BAF061E3FA861339\
+636815C3DE489782D7895BF4472AE48DCEB1D3836EDEDFED8EEE4F86879E4A9864100BDDFBB854\
+8CD4C7109FB0DEA6E8709A89F6704D0741E69538D11F151D67C991B84A257710A8A22E42BE4E68\
+065E77FA1F2A6F5F2CE7C09FB221C86CFE8299501E547ABC79AB1EB9F7C3BD2418E2EA3205BD51\
+51163CDACE8E334EF82E8970164D0CDE7E0A86817387078B10FA562A09820E0BA2ECB8D6342227\
+0E18370B0DE7F5D5B875B226A365A3CA40835E84C3743A50632615AF9ADD11B8D2FA4D0E4DD885\
+2DAE6FD3C24CEC2CEAFBE759627B59FC7AF5CF91A5DF974ECD1FCA9B062DABC4A1809D80C18931\
+C713820DD4C5F6FB09E02D419E4E461E4419C20686E7269A2BFAC1F114D9943B96E26D4509A44F\
+E5D9EA4E2D50F0AF4B7AA476AD21EEECDEB09DC1CD19B3E501C2C42EDFC830DC94E35EFD7C461A\
+21E05A3EA4EA83D7496CFEEB0D44A25D756A09367D353F1D0B694533D57801AD0D9CB03D3B4072\
+EAEF914C46CEE34201C25DFAE244612AC425B5F1E932A0E4FCB73EE2209872BC107F77DF5828C9\
+58E22CFD979DB435337F6FBF85133A5534E685E3C07EC607F92CB8FA7AA5CF2E1A8C52F69462F0\
+07BF759DCC4E51D183D88A541829A279AE3B4EC70822B6E6A3C6CF08E9145B84AF7FA76C6A792E\
+35C6F39992C568D6846C5987C9CA1EB7E730F6E298D199A6F0609D6BEA3473321261253EC5B276\
+0FCD458B6766123F0BAEC522ED99AA9AFFEF817A491F41CFCFCC0882D3E0C3E7E6E1E3F948464F\
+95CC9C9BC8E4543BD50C305A1822063224697AB2AA2FB210F776FB705C326530E50AA5CAB2929E\
+5F972BC45A3F8056078BDB203E75531A58AA279A3EE84615DA808E2018EA49A3FCE1CF6AB487CF\
+ED6EEB611182D1FB2D5B6E050C443F6C61833B0A16CED574DC2A72676F55AED91CBD5B3D518D06\
+678BBF5300CFDE4E39A35A3291A270D5442EEA2459B76EB8611F37388ACB558A76E8CE5C5C08D4\
+21809FC3A15BEAA37361A80D58D5CE60E5119D6B8173E464EC4F01EDE72F3D1BA6D4E7089A606D\
+CEEC5CB5181C7AEC6ED1CBB84F1779D3CCC2F54C341B96F96A8E2042AD7BD3FC5819EE1B741179\
+211588106D5561334180B4EF9476ED01B44140C4594D2C0D6EFEB0C167BDCB20772505B894A2:\
+71CFE52667B4A931A046532C71D60787
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+24660DFE3352E0C6FBC9FBB3A981589A2873679C88693EA1D12022A3BD95F693FE99CDEED2B828\
+347414BC75DB4907D60AA1DD9C54DAD229F29351BBA0646A668FA57FC06FDC44E04E40CF9CCD47\
+1A82976F14AE7CE835F89E27BD607CFDCE54464C4871BE8CC4A2CB9D62760CD08F7896648BB032\
+18EE30D5855A20114081CFB5B402461E098B5B2F561E628EA3FE0E8313CB955B077BA58B756522\
+3ADC84576F10BDC0608800003EB5E5D705A563399341550047C1265FD9A30C4E5A3A8B603CE2F7\
+7D6EC6168A6598278FE662FF3B7B923F54348E12FDEBE2A74E070D4F4A7A75A3949FD36F393D83\
+D48B80604A5CC32762E72916EA951C4D8FC4114B9699C092F316078C1AD390CB8374653F0F3977\
+15FC80908894FF89FCA4FD3E27F8CB15CFF26239FD79F212B91084031C45110C23BE81BFF98180\
+25ABD3190C767075B4284A433FB87ED5C551DCDC30F9FF937918BE347FA95DAD0C5BEA42C24C61\
+22F476253A0C976874F57E824C3C15FDCCDC225CB2B74D4CF0C9439ECE94417A805C91FCB399AE\
+5127B28D6B5FD82C24496CCC901F265EC169AFE8B5ABB4BE5BF98831EA1D5BBD95CD30194FF346\
+1E04353450DC7B82E48A796B1C5A5871A1DF22E5558887556CDE9FB342D420F338E5C5E0FE9DCC\
+F97679FC22F743F4E853FE459E3C8FE402BC05B22F2E429511D3EEE94F422037527140CB914C58\
+0FE1E0AD937869A4E246A83DEE4E65D63DC109EA44F6081F45D08590D0CC30397251BFAF74F981\
+09D052C92EBA9C3C1DF373B52A5DE581A212405AD9AB62B2BFF1395DD26BE790A9591C21238881\
+AE8E4F034E389CEA9E7960AE05A097C4AF623B4EB14017E42940ECA45483D78F40BE6BF986FE7E\
+7CF75AF15E5840CA3DB75B9877D2895435252395C1659DFB195335FCF2DB3DBB6400077D9860D3\
+8F9D93984136BDF8542C46ADC71434B17B9D5FED0785D282C44FE6D08C5CFEC856DE0EA33D6A92\
+CB313D17074966436A757F94402164D3883A7353D65AADFA2B39EC9E979E574AF9964A34BA636D\
+761B448CEA9A10B5B7114B3B1B53AF5F5793FADD06BE1465114519C2829F3D23329D11F99018F0\
+1FF9F9855A744A97494B90282288022ACCCC58D6AC48BEF73B7504715B6565578EF875A9ADB904\
+CF1B53B933FF6F0F19FCBB3FFB87443B64DBAF472A16FF3A29ED5CEFC6179AFC478707D7C4E58E\
+8F3C82A9AB4696FB14C4403CDB6F2F5D423F39A346F809E7EC5CB2A21C9A5949E4C4F888FA0A98\
+4A5F2324C1A810887D0E960BE3728173F9B8BDCAEB471B8CCE8B837C6D424468D92831C06DA69A\
+4505F2CD98DA06F73326839FA913974172E4EF2BF1D8BC9CBEBC8943768EEA1D49FF05C2D86C:\
+98DBAC0E4C2624FBC6474652ECEFB1E7
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+9633FD518CFCD7EE436ADAAF7276B57B740D98BB4395362FF04485A69735B816A59C1237481A70\
+948E0948F354DD4EF220A1D066975A00E758D87159D5A5A9B0F76BED463F27A7E2F9628E38A749\
+F96A446CCCA40A70E387D39CCE3192A6C090FDD3C70160B51EE3B2FFC39B46E6B443C778776CC9\
+65D691D35E61298F41ECEDC4D80C28CF72484D79782336B56A95B282279EB2DBE7F1300E0509F2\
+55BFC7ABEAD61C6628F4EE410D12D1A8B48FFCF3021D95A6002D8E2C0E1E8F4291855D941AFD86\
+6F5D93E43EF630AF63AF7DE546B518BB8FA0E7936CD2CD59FF48F542B1795B1AAA36800ECB054C\
+CEEA862418E33AC76697996B627B8F9A15344685E2BC087FC9DFFE48C8A842AC70E5BFEF0A8D32\
+5E86C7BE2A217A2581D37F2D185D07E09C4B859D98B325D03C399C0B36D1FC8B46BC20DE9F1985\
+EE87362797B984E3E5D5B5DB580CDC916012BB40F3C97DA934DED61996882A00A0EA65C2C3DCC9\
+4B5E88733EE2E8664275FE26810707EE2D8C8BCC3E4A42614AA1DAAA7DDAE0434F9137A9B4B88F\
+E89D12B99684C58906260DA869EAA396BFBC71F9367F191E475AAF4A0CB8831CD39BE94C51D95B\
+2ED63987DB37E4FA59E48DD7FC4B9E524208EDA0D5896199DAF89A645D6B419EC27899AA1A64DD\
+496B2F7914B69952DBD6927D191FA74A7561EC6C577F47CC115D8F24C738406E1E51698AA45266\
+2DFFFF81807CF1429C754C6ABC3CFED8E7697F08267A4AB6F403EB167FD42A2BC386A07BDB3ED8\
+D59D98E8AA85A92B5EFA2B9D3801B81AF1A12F351DB4F275A30CE635276068AC86597337AA1AC6\
+810EE0658EAEBA4CB872C5CCC2FD5525B81EAA690498DE590BF4ACE022E9AFF53C533D40A938A2\
+C9459E0EE809F9ABE118E143CD40C284E986E053F7250D2DA54E77139E2BB248EAC2403AED1E46\
+0C4CCBA8AAFE729478F180754A9330F8CCF999580D63B9AD63142DD865A94920E1F37B974EBD18\
+F6246820370B0E85E9FB9BB27FA4F98F48B10E659F9849B51DBE89E62A545EBAC0E91087928643\
+4E303518E0F19B19293D7F70A91CC0FA7EBE39C0A4DF4D142D9060451D6D4EE029473441C20C06\
+81CC5ED84AD7F8E0712DFFA9D3FDFC319030253AE11330023B3C74990DB102523234562664DCFF\
+AD0A26B3AC1418E97C08AEC16EF934A61FF508593360275021294969A0BB17EEBDEDF8A63FB4B6\
+C2C64FD875D472CD6CAE8B6085F3FD30237D3B31297A4BFD1235296CB0146DCCB8526BCBC776D8\
+347C21BF4D716FE3070227D72C3C70B3F0BDD0172FDC73F69C37DB9512D1323FE57D60CD1B99D7\
+7BC95FC0021F9D98FFE142CE8CC764549039520F7479F092AE10A2CAFA06AEC496FA24331F5F:\
+FBCAE48796A9AE72E0A4D218BDC0859B
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A14B6E9A9551094EB317924F60FF52AABC369053AACF65FC84B5A49A1CA7EA17F874EEDB3B622B\
+04415EA80821203CFA4C6E7F5C0F88CE49DC7E49DC58FDF15DAACE114BF7FFC13666F3C5954795\
+4A664FD9DD0BCC5779EE33B858B767B155A167DF2A3C93A5735C8D54F0E29E1037386EA2BE9277\
+CF1E1618F96F1164DEAFD2F6FFE62E550B1D7DCDC737AE66E2DB6032559946110742036201CAA3\
+6E3A0897AC470DF4CA78134266302F15307EF18A0E21146F3404B5BEFD22ADF97E5888A2207D9C\
+F9A16E329171558C83D5270A3BAB99CB941E36C4B308A4F27FE98FB8AA84818B63FCB44DD6FA97\
+C30A86D87E8B7656CD05D722A7B3483C9C338FB12D7581EF94FCE7639221DF785C9CC52DC27CB6\
+CD2FB396066AF964065ED0A9FDAE5A8B202336378EAE2B5CBFA463C9F7668B0656B0DE6EED47BF\
+B062DE72E8E721EA5C3363CE2749FD0F3A67899E532B19EC5E54FDD399CB2BECF16CF0A91FC404\
+364C0A8E46D52389D7D1B2B7CA0270A650713D8F6F812DBAA7F06CCFA24E200B7C8438B04323F9\
+D29C163E0F734B40B0389B1AB5D0EA77265B2F189650164661AC14B1B49287AFEEF33014D52C59\
+FA06540E5F7090DCE8C77ECA6CAEF38E9293A79875E9E04DC2B79C8B2FD9A7419A9522DF5FE5C6\
+66D6EFDFD8253EB54E6FFB41AB6ABF957784FD88646AED00672DCF495A777AD8A0A4F91C9F4FAC\
+F930949F2B59008C2A1CBB2D3E5FE0D4A8E0CEB63AF23E4758C995382178C4FD07D0777906DCA8\
+A919FF9B38CF2F9F7CD9FE276F12FC7B0DE1DD31F3042DC74654ABCEADFF0D196644FF8175854F\
+8EE3C65178C45AF19E6E43659CF1DC46409336A48EC5935E941593300FDEB7FD738232A5417F1A\
+2B3CFA16CD08A3835FA08FF233208A385723D566952C7385192BBF1C2E73A2B1376015B7484998\
+9CBAD04866DF8D5EF484C09B640D543635852DDB3A80F2F85926D4154575F999714C4C88AE7435\
+EAFB151BC90A5BC7951BD6E4A1CDD568B5D0AB42F9B1E1CDE0E7D42F6C29337359AC383168F001\
+F43A79DC440E153EC16E62D5218EA23C2F8CB80201EAD61131BBE1EE5C85414FBF0D0BF50F2B74\
+B89A94C391E567229745C15B8E7459BE663C6AC83DA708F5BA562608F5814A3713D040A7452513\
+C8EB36A3F5088F09C9CCBF9A1B26F1211ED41F33DDFDB77CA9E5319DDE52A749C88CC7E0907BE5\
+0802C63EBDF5702B93E09CA89EF9FDEF41A8A47352D166401FAF92A8B35DDF43ED66B98417E304\
+29DBB317C8718D39BA5C364597F6C034B20F585271958AB284D184DA758650AE8C9DA359BB922E\
+DE4450DA14666AD5F02ED6135DCEDB532ECD6CEA61B071FDD364421B941E03DE48ED1DBD73DE:\
+BB1B359766D442D2E9FF3F7995A26473329055F8
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+5ABDB1C683F4DC2946F45916427260563A2B99D6A45693A684DCB02ED3FAEA19867E3D4199CBC5\
+906A4416E1AF936E3277F5B46722A7EB85DB2502C830C49C39B526DBA34EFB08B96C161ABC60AF\
+3466751BF5F1974E29DA846F9FE0A77A7528CD2EC911673301A5FD70708A088739D4D2CD991515\
+4BD06BBA1A0CC682CCE16BD1D0C68A72D2C85CCA0B33F6091DE098A599C3444FAECF15E7DA5769\
+1B7BAB3E458069D5F03FB5BC7C068B80B47DB1EFBCB075CD860D3B391158F615935EE977193625\
+61C99D06F0763F9DB85C987801CA9D44D66E8EF8B64B45289BDFEA52B514DA12A2359451B92641\
+983991F17F4F9DDD0AC174054CAB0F70171083A18A103405D861BB4F2530D077BA68C528058C46\
+E497006CA82E7FD407A3B78EF7C7A8FBC4359ED109337083DC8EA9F6CDC9AA694C353642CCD20A\
+344A5B47C42F31F25EEB82EB1368A2171B5DB13E4CADFA21558D0DDF10EF45E7E79E8143C556EC\
+DAAD047CEF149404902521DD965CCD0BC9B8354967CEF3C1C50779443B08BFA82AE49BE9927330\
+609AADDFB49E7DE339447B73BFDE525DF8A4D54D2D7C4FF0FA285D39DF0F2DA25E66F0A77DDA50\
+913CC00E5531B449D8499198E0D326D07740A29D438E2393D9D6F49606573F35F924F3125A3727\
+F5C3BC485CCFE6DBA28CC7688B6D8B88C7AA62F405F38887F2970FAE4BB38DDA60531011DF615B\
+B58207BF10BB0E3087E0F1736A1192BDE595668AE6B4D7A370ED2572C388901C23122A8684E025\
+6BA3AC3F7F547028E31AB28EC0EDB31E922F3FC3BA1265ADB8C19A87774A89DEFE0D51B0B70047\
+0321993E671224CB07D017C4C0C057AD7DC2DCD634CD88C53E74454248C4D562707EA3299E6C14\
+5C4A86EFCFC3567678B24E5B8D7481CAF2BC6D2194490B29C0F2A6A19CD33240114F44D5AA852C\
+69B12951B89E599A36E42C32020DC5D45E1080B510E898BD08784FA7418D6DC1BF8D089206684A\
+EB0513A0F4D431C44423B4E2666B9BBDAE879C0F1DEFCABFFDA4A45DA816AC4C6CAF1DE1F35D19\
+5C88F05733D60509E20301CC64FFC1AC3B07DEFFB364A65B6C58EC10E588FD5420189FC3D5A3D6\
+7CAAAA3C6B85986F29984B11A81CCD904E96290EE31DC937D26C84C0E19BE0097952E8F5D0312E\
+D44AAA311C09EB98D275268AB6FA7075D60C8881AB1CC3516DC79563F7E04D4136221E41827589\
+DA880A812D85D91AC9A8DB37B547524CEB835F033B1A452587A39DCEA47C26C9AD418749C82786\
+C96927B8BDEF0DC2149F38836D3A3522904E08288300A69B16F0F5E7F5DA6B6248D7D2800786E0\
+CAD44E36E32F89870A28B8D9D6685DA341A85F9DA2AC526B39E9A9326E5AF5D3E38D8C99976C:\
+05C3DCC6D59016C8A56E2A005CDC423B9E79B2E1
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+66E3E90396ADD580D0CAB8120EBA8B827B94F8EB5CF151E6DE08F163F540E902C98F6B069D4952\
+B8F0D4469C3B90D67FF87A60DC75063B69AF405A72B3045A7A878820804ABB23ADCB1D4717C9E8\
+9BB90ADA72714255F3DFADE1CFDCAC240F4AFA5D5AC955106390AED2E72E673EA8B45E2A92A166\
+C6131B5EDC7F3FAE3C256E586C56ED9CEACC32CDC249E6F812D4EDB4783ADF31CE6C83BC81F77B\
+6705C1ED1C37061A9D3BC91D7C0F889F5C91E574D80E3CFCF19754201CE5FD4379EF087369CEC7\
+F68587907915FAA2195544490DAB9D3434AE49832556232A77CAA32A1D6FB6D797F0E388DE8A98\
+D7A7B2D5FD71BB4983BC4790A652F8FB99D4A7D0E18DF328BF376FCEBD2FE8EBEB67AAAB608881\
+85706F0E320765BFF8516280F45F53677BCEBDA244DF9F5604FB8C816E21478F25E44DF83903D2\
+A3CA94BD8AB15565B60A4D41B08A155C42E7AB92922505C793C1796EF03CDE688F1FD0E4527888\
+6F0098A72FE0AA2FBE87F56DE1D2F2B8A3EA2533FEACD41880067FB69FEB8DDB8C9B7276ADDF0F\
+5DCDFF1FEE3D4A9DC8E66361AA16931D1C737F08CFB7F5A874F1294B25BC2DCA5757F65603B8C7\
+2E7985723628AE7A6D9A0B5BA1BBA655F639410C681C80B0A9C3FEE24752FCDDCE948314E3D341\
+22270608F563A623569412F5BA073E54B59EB379672DCC5A85D6247648397804EBE8311FA5070E\
+1DE5CD66EF2FD736D5598791BDFB0F6EE30C617B3471E9BCB49759A679D8BD1D8FA86748F54C7E\
+A97556AFF98F0F49A1EDEC49F97652C197C5D6618E227306DED51DD5F44D800B23DB2FA2BA2599\
+A215B7DE3F34AFF7ED3911A5C6F7F57CCFEC6A47C7DAF1F2728FB58AE10400C3D8B29E4B1DC819\
+14D3890C1D09B6F52019D4D28A1701A9CC86EC9150ED845BBC5DBBD1DC26318B0420C64A1825DD\
+9AA0C8E1B47836F5C8C4C2B70F6B758476E9BE624FB42EF954DD94F8E326B8EF51666861702A5D\
+1D65D62135F89E3564D3A913061AD00A3EBC3C5AD3C52CB732304792D0FD2F14BD0644A5E3BEDA\
+6491E35EB1B0CD52FA3FF75228F55230FA20444C272AB54DC0C0DBA7971C923AB8CD6E72148284\
+019321302E2B1A3580A20A4923BB6B6E104529D948B5770E18BD2C6CF34B389F1A4A9BDBC464CF\
+8FCE544891145D980293DF4F0FE6F35DF22117939BC26C89735D027541B562A93D0C611BD7CB87\
+1B556A3E3F0FCDF1F5DBC7A9D795C1B45E1DF6D91E6C7AFEA00E00E44CB6D25CB6C2D658D0032D\
+67C7609A8598BB427FA9B8767FE3E3BE1733CB352318E6099F7EBD3B1025DDA5FEF1F4BBB7B173\
+5828D291B77236E7660A23393F116EDFEF8CFDE2DDDC3017480B4E6D8A16AFC5EB4955AE855C:\
+0C68CEDDD3BFF23048B47C9BD966A19E46F7E2D4
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+99350D7C2BCCB1F021C0E1269D7B764B0C3015839F0645127820CD4A8413E987892E8704AB3C3A\
+E99150F2BDBF9FB7745E7BBD3FC99B573C5DCED0E842D98242D8F31E5DD69B6A8100C7DA0C0E33\
+ADDEE224B9A7ADD35ED065743ECDE4D38A47D67B3553FBA06C4D2F5B7A53B423C367DEE0AC3CF9\
+4B9A7C620743609E27F16EF8AADBE74FED3A727B00F8666562461D126038067B44B3CF1D7D41AB\
+BFCEEF122F6BAB5403EC7AD66B8B60F790DF1DBAF330A040B1E542E783DDED48C1D8E196A9FE32\
+A5B7EA6F63446E9BFF93B0B3892CAF044F87002381F92D9CCD7FF554E07EA42CA7A44577C47B54\
+97A212157EABCC342D650A41F3CEDEC99E5207FD0AB916697D85A619BFDE3AC899FF424AB3EFE1\
+7C9C8B96F58AAA9362DE3DDCF097D7E88EA3006BE01FEF9BD9481CF9E1DA674FA133D114D5910C\
+4D61523CF20FE135CA48F3379C0A29D0B05AD4A41E782968A1520BA8DC6268830C55BC92D19232\
+EFFCC65F351194430EC4F25DF2413DFFC08783876B87A0F6AC630CDF04A4FE19EC6C56CCE07515\
+4866E7CB687FF5537C880679DF8DEB23D7278ABD4AD260D445388132F6848D8B6191FCF90D0D66\
+D4B95B3EAC5439D6C6303CAAA73B968FC385EBB727B6A5526B0162E2AAC32401C62B3FB150C598\
+846241854996E412E99873BA2CAF040B137250F7706EF5376ADAD52FF13B812DD74A8792E2474D\
+ADB993C2239494C9CFBF860F1216EF02246911AA8FEE28042A22A5BFE311406E9C1F4EF8233587\
+10A6E55C07A31F59B19D70500835FE15B3B36BB119A4971A67D66F3BE04E27175069C21EAB2F28\
+737C5F564552CAAF7D45CA4BD7FFCBA429E7593E603975EE81A97E8BDBD2C5CADB1C18818DD494\
+D7186D36B36F289118A834297C2B8C3BEA35F716435F49E32559DDF80910C3767CDBAD107070F7\
+37EC37DC47F5E3529F863096FCAFFA389E848D8F411B54CAF289C382C0AAAC6C781C03E78BAB1F\
+D299C8C14D2A37916F2287D6B5B1195D0A176613065D8C3038096A5ED63DCA5F9EFA2E3A5D5445\
+87DE1BCD995CE4CF371873D0F5032AED6B1A08686E4134B1EC63BD9E755863771B885CA610E03C\
+86DB96CA77E9E7CC0C4D97A185297501C20A5953D70664CE9712D4143B0F8CA7941BF6F114F8A9\
+2ED16C5ACAE4B2BDB940CC573B86AA7918167BA3AEA93AF833B51590A09D4CA299DFF975C2F1CC\
+B2E3112CF5684C60344917F6400D1B1B6FF0A986A1CB955987354EA8B69B4203A664882F6F1544\
+F71B5E89D104CBE8AC412E4FFE927F9181F54F1DC4A06B488D7058FF1B59D67A47B42276E9E4F5\
+5807CB1131340C5C7D5FA901A75999B3EEA02E853868E6DC4DA82A2DEF303E2473A8D7D6C0DA:\
+D9A5B1BDEAA3E8DEF14E7692D97F502C48A9ED21C2429BE6
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+354FBDA4E986570038B707CD6A79CCB72E00640B07DD1418643F2EC5BD5B281D022EBA2413CB38\
+0D061EA457CD4F60208F7A99412F0CC511005371CA55BDCEEA21DFC3AB42CC654E0A5E0BDE063D\
+63E4080AB120959D0B298273F02A070BE9355CE28583844CB85049FA9813DCB0A1762322501073\
+4578E48A543AFC3BAB1F7D50E3A2FA561440D08488BC6135EE12047E89EA92A22E175F1FBF370B\
+E1C4B596E14F77BB4462F34418F6BCC1526173FC8F030A0604F24ADB94AA01C9602745803BA767\
+255721F0907B2F387A5F31C3B45780CB1F8F526169E5D710CA88901C5585CA980B4B39D8DC6EE3\
+D563EFF3725E3E149D6EBA1B2239662304D504FDFD53619D17F35D6C2597BBEF1257CF40608548\
+4540FE0FC2FBAEA3955F49A6BC71028D984804F7DB46C6E2ACCF9CEA144781D795BD4F65332E3B\
+0FCCE28A63028ABA2EA2D03C8BBF76BCD8DCF50343FA40D53C133736A632E78B11D3D5CFE6A990\
+4CD9598CE9DED58F3350BE38937867F59B66115248946F701998A9A3724185595B114E696742DB\
+0EB92398CD9E93BD93AEEC0006B9449EE5EF94D7DDDFF9221336ABF8280738617170D89D2B6B5B\
+8BE4570430F6721C2DF50A94679A7FBC3D6D5E32953D93F8C2192C70CF945B2EFC73D3BF5AB1E5\
+EBA34EEE60B755918E2C3E71CF61D666607FF099D2594AE8EC91B9882DBC27FCD235C4AD01A568\
+CA39B426624948D732F7DB11F277EABE1F53AB877F9841B4DDC3C1886FD6F37B20F3D80BDCB874\
+8E99F3A30F12E5D3FC5407D40D95BFCEEBB41515C4120267A543892D115C1830220964F841AEC9\
+563368DDE3E837C3721DB4B5E082073FDCCD87914D495AAF07890B1673FD8A614E5873634EFCE9\
+E223C2F5B83DE8453B773A86E4346DCEEA885D7BBD5D9B50EA3275A7C7A9459F5FF974AC0296FD\
+6F2B7DDB178E123112D56463F2B048829D3680020B549D16AF318C8FEBAB7CC6798AFD96F67347\
+BA86EFF75BA5425833F1FB581E9BBB3EB668F80A441C69F61FE290D03830AC59E2B9805677995A\
+DBBE6ECB0DF9166385ED4F896D4F4A8A12B94EB26001D7429D4A81EC3FE613DF395E08D2A59D56\
+ABA82F9E7196EF2B9CD024CFD3DBA7D50863344BE7E291B8295B46E8DCB765078DAD3C3C2DF539\
+84BDD216BB5BB596A5CE204762737AF55328AD03D0CC0BD11823E89A59802FD2D774C830DBB16B\
+2AC25EF359454F853FB85142BE2745A6A325F421FBBB41F6EFA4F4F931B01707E137B5E66F96B2\
+C76A34F866940F0C34CC8B6560D55C18B468BACBE4220440B5A07228F4BC635CAA92325BC5F670\
+BF0BF3F1C48AF93A85A7A245FC4EF214ABA06CDA6351920C3229468C547B0BF9C7CE3CC7142F:\
+57426DC52887DADEDA58D6297A1680E85C1E65EFB9285D99
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+B01557E5B83A7C68993572EC916B133F1EFD32358EBAA3ABF519CE1FF7BAC100E603DA5A16DC49\
+FD5ACF9B04DE9C4ED5A862AEE3C9E301392D32246461D3DA41DD69240B47C4554D6B036CFFE7A8\
+3C67D32785D77049A056A4BB9AAC1B94A43516D56C2B23DC4F0F8BC203614144E296F48065ECFB\
+812FE28B0622A24EA973B6BA4D35F9CC1263D6B6DE14FEDA3A2B62B7608A84BE07743F1C911806\
+EAD62CBC130C55DD6465960C8041D17AB27A2EB0661D2D6FE03B284773D84EEFD68AE37BAAE934\
+0621D3656785CC409846E61D7D44B327F2D5CE6247740929C42C193EF515A283365A6C22368518\
+9F32522C12F8D6FD67BBCCA7D5BFA7275E0E1877C3A16033CBD35CF07C7655C9D1AAB6F08F984D\
+5FC420F07B498BCCF77C310DB9358BA43E015780F0C79E42CAFE0AFFA5F7A47ACBF79D5921EA8D\
+3869E74D7A56CF05A3BAA75C8E6A38F78BD7638AD9842CD095A9E6D5140184C99A35AB3DC6A0BB\
+CA717014ED032FA09C4AE182183113594BC6D78731A0211D82C91F41F6262FBEF6D1EDD2FF973C\
+1173C70071A6F516DFC34FBF6EDA87CD097EEA24A693F19D8474E6E53B02B5B682B4B77D25E159\
+2DDC9B9EAA12B19D166F78F3990A1F557CB6DC795754C00E8066A7607861779237798C100D0BD9\
+75354F1E307BA6E10870817482E4DBF633293B67670E27E81C88BE245C0FDFBBECD2668B1300E9\
+1D53D0011BD0F67399EEE363FD6B63C8BA86807A866F3B5A00A2C0224C40CD6838B717BD2A58A2\
+4115CCC0D8CF174C3ACEAB7D98482AA1E29F29DE27F7C3B60BD5D991B73803345EC59347C1922E\
+CE2896A6D8772BC7451D665B210E7A7CD1631EE2C55893214111CFD2CC3944080F212AC85CAA45\
+9D44C669B36CB59D6A09E15B2146A0739EA5AEC2275000E5CE45A3EC36921C2917DB20042A7635\
+2C28B32D912665FA5857C7D6961BDE4FC9F9279EF39D9EB2B826D77293280730231B0F530BABF3\
+C3A25DFDBB5E5348C5AF8690844DC8CBCB55754F5E5D5BF3C6B0EB639038D58BE4F631299600F8\
+781906ED42D6603A432037BCB72FF07592497A288F9AA7AA379358395F7BE07602E547D6C37DA0\
+C3F22C395068BBC799E2BD00BC306CC5624D00CC55CF46C0BA5CE9D722051C9BE866BD244197FA\
+CB9DC70A124AF897396877B92DBD891C57E6439F51168D9F43EF740A7E810966EF6009F8973663\
+E695FC97946184BCD39D13130B4DCF218087F16A7344036AC7FE0111C7050464A4D32EDE1081CC\
+EAB6A15777D9CCA0BC644CC82EC660BEA8F416B53DC14421E811436C4088A37CB1B46B83A95A35\
+3BBC54FBB836618D1640AC53A2BF916965A81F6E1149C0EA89D50D182B652D97A810F5B43819:\
+55255DE499962F4597F5C976155D223EEA3740A7544D6BD9
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+23AC39460E6746D760C584C6B35EE1F579B43161AFB94B725AE5E3D1DB9B5E85D70068A81161F9\
+CCEC724CE1D2ACCC9C5CF21AE056BF733F9134AD16B2121F16644E43CF1D38C498DB715F134FF2\
+677DEEB796B43641C9C508103016F94B91EAB0311DD2C8E81D4E1F4115CB329B63F34F68D62314\
+BA4C77EBCA6DEA17438B9689537CD849CC08AA11665FF59BE715E2341072DCD3BD6FC12E21E176\
+FDF969CBA0FC63705250609BB745E8578BE290B74E990993E2D09F8B3EAB2DD36F360734EACC54\
+E03A4A588ECE8C622DB610C0CA883A699EE4E97E31F6BFA1F0771AE380A1502D178AEFC0916BED\
+F4A0BF876B18C23245C9FAA024CAF00832A60A083052D17E6BB8A6FAAA99CA1272CA2D166A3CFE\
+60D19AC01F1A0101E8E39508BA99E10D66D0611F01E4F212434642A2742A6B454E948EA7B55BAA\
+AD242420C052EFBFB531BEAD83C60B7015B4FE943FD6962B08B1FD6CF2767D5E045EB1F223011D\
+83B061F0AE6653F7BFA64C0774AC423C74F17877C7BE62669B095DEFE73F389D4C25C8BD78CD4A\
+C76DF63C36A19082C97473B08B3F2FE8C5D89143F4D8177E9372414673D340B301A85C5D9200FF\
+B36D5BB12ECE203CF00181AA5034C09A7BCF3843F98E22A02EDFC1A50F896774252D1CAC93F578\
+9BA684431BDF3C7978F3647696DEF4489DA921B76E56D46E208E31F2B320DEB6196E723698CBF4\
+3204E68EC8B86DF48344E2575F3E9F1818A334C66A942EC3C3D6439CDDF970D4419EFD0206E413\
+C99ADD9D48527676672C96B268683F49832EC8C1B5750B900715A7955DBCF06A2AA6995475D15C\
+7D5EB440E228899315101E6A8A45842EDBE41785AA4B2808956731BEE81AC9ED8741884052DC10\
+090FF82CD9CCCB2CBCDAEF343143C5D7ABD58A730AF8229825EF2591A253FB52F1A21C8E5CD64F\
+E327FDD55BA792CB1E8AE92A3EF84F035D72F808976350165ABA7675D8A520B9EF9CA7D04F3D26\
+B8ECD7E5CD61A19D0CC13DAFEF2283808B808B4C5DD01E9A6DE54662D4FD21083120723D84EE76\
+2C197D33277E0D87E777FB2B619A597DBDEC83A93F87ECCAAF64D3223CA1E2CD2F7A46092EC5FB\
+0CA5350D575828AA20D60DA75379C7D883D662A0F66880C7170E11BAFCFCA74556A180F140E173\
+6612FF94CA2B5782FB8990408CC77D39FA68262C738A607F27CB5247A00482A7C17C19CE01147E\
+536898826372F81157939C70BF693C9A194619BFD5F9D56B5C63C0C61B3AD6AFA5F03BA313E4DC\
+69C6E0F1DB8FF4A3019C5A4E990886197D5C1A31A7C108D94B285FAC00C617D68B177C26576CDE\
+8F621A6FDB021FC25C9534BF7E7E1755611200C59193D8C28C7B2CDF47A05CE9D7A3D89E6103:\
+2AE43BAFF61783491A33341B26F65F7CBA8E393B19C1E97BE420FE58
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+040AD7CC43206F37EF55970D545AB43710E0BB8AB6FB66F7E7CF60869F5C61C018E869CA7FC0E6\
+E3798649BA2A1B7CBEFB1C59EAD2A3117AD370CC3CC9D5714430429A002BB092098BCC6DFDB593\
+E1DE2546D8E410773F3EEB2E10A15AD39D51F7A87EB244818BDF53DC3536C955982A733B5121B7\
+2BD5FCBA34D479F246F505BDABFC6A0D95CB0FA64EF6287052A0BC26133718958D19C7387BA152\
+10DAF602037E407A731B918F681FC2005A6CDDE141E405493BA0987978424C7B189C94B13BA8A3\
+0865241C1D6EF06A8E3EF3DFB9D0E2443B7F47A4FDB1D02B5FE31BCEC51086CC38BFC7CFA2ADE3\
+A75ECDC3B4D01F3A9FD71EAD8E5A0E9870C605DC4A6F1BC3932937EDF7F4C72794978C582A4819\
+2C12156B142D9F8D00D837057296D2E1263BD7939D56F56D31FBE031BC7B1194E2B19A7E3A83B4\
+82BB57AADF5FC8FCC653227ABD1C895CB3CC7FCD5B7BDF86FEF7C55B78323DE51E2BCFC370880F\
+A872BFFD4CFC0909A9F79B8089EF50E7E93239E679E158D6D518F7C5555F325953A36221C1269A\
+E5F235CF338BA7A8615EB1D0B54CDE65291F6EDB3C2FE41FCBDE0457CF050E5E30149C857A91FA\
+F767743C968C56B94FF79A4CD6F798356F20091174187EF169210706E84FCFADF57D96B7077433\
+CAB883C73C060475C207E611E679B9A795428FDD891626CFD6B868203714F71BB158086F93D86C\
+A5499C0B9B8109E1CD0F7E6FDA5B0840CC3FF0C1EBB4CEA6DC5562BD64BF08EA6E675EC6298C9D\
+5E1296B327B4EC150C0373580011D105DB11CD4E8FC8F3E49A64E2AD9D1D2261C85FAD9A31BAB8\
+6C7D92837FC297CA387E945DC82CD10255D14ACC503606C0A9BA7E2F4F1C72A5E17801091ED1BC\
+B2B9BBE91EC4EDEE5A908EB3BDC51EC443BECA0E99F5BB8A2656702B49723B0A3B37F6C7443BF3\
+E85F77CD3DDC39A7B016F1F53683E75C103A4C78217D2CF5D5E156E2293507E25E17CDC7B22136\
+92E0A15C0ECDAD687DA2ADD96D59B609A7A9956DB3705C22E38460933FF5302343C5B36ACE8DDF\
+022127C5F1046EB03B4CF2BA625989C2EE484D365D04D69DE3612D3961491FEE3F101A9CC66543\
+BD52D0BBA41819CA542E56C58F1B2861C224EF4A9A50AA4CA7CEEFBD3BFFEDBE82D5FDACB315A6\
+B9A4F99A01BA7B09FB9D826DAF4AC7B913D8A9EE93894B834B8F2A9B242F515D7D6C3A2FE9FE59\
+7583497785A299DA86185235FF8D255A17BF45851C67DCCADDDBADB5D5B49D1E357793AF60FC39\
+E15F201B6082999E5252B6C34B542003C209A8F28DDAA58BEA27763AB060510D132219BFBB5CE7\
+D8F6759D64E2D25604156E4657E3EA764B2C3D2A0710EE44D5AD6EB9C7407FF852C2DC161D46:\
+2372F9B0FF27B8B5FCF2735FA58AEE77083942303E1378D777407E0C
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+063AAC01A9FD95C649CB7891779D91D9DD1EE283A256083007C910D584A8A967412B486E9C302F\
+EFA2E4B3EAB48160CDFB924C3E4818315C2E8939BE010349D20A80E34886BE789BEB3403CCBB3D\
+A87FAC97F60EE091656565843AAC43EBDE6B7A65FA71AFE86DD8B00431A75A84F7B40231061806\
+491AE5E20143F09949FF991997C93950E209313E28D1B1F17FD790AA03F6E9530C934566A44FFA\
+4F059C681DD6C9018E1FADD0DE1D3F48E6CAE065013B1CDE175A6714DC64ADC360700D2E36C120\
+70BC591FD06A4DD02E5555B26E9A319F9AFCF1FB446183DA03C53631D97DA89925ADFAADDBABBE\
+11B118FADEC43A6B726F3FA10087E6FF75AF9DBE1D0BCDC29F88CF2C31492CCD38C834F237FF58\
+709ECFAEAB5688C3287D1632CCECA70ED625840256F93BF7D21F05E7AA3E4F10117C980826B9A9\
+6CA135C510BC1413A1A2ABE79DCC335667771EB5D327DD9FD8659D8385A79526AFCF88D15529AB\
+76955E6D5D4C3E452CD22EEDA7576ED1ABDEE5D75A003D24307F861DF68335A2E071010F5F74E9\
+C5CCB0ABCA73B474E7EFFDFE50F8171B4BF4322E7B5E1B555E50B16F27F078BFBD7EDCC55E7E4A\
+D0752925226E2EF083AF2BDDAF3F49AE3E4BE98D174F9EFDB42FF413B336248FB6551ED9AD42EA\
+2F619B25E9BC3C26F7C29733692A091C754C23B60925EC99E013D002EAC4234BFD35BC420B7AB2\
+69419BF731E1680E6715D7B268C463298FE1CFC554CE6A0875D09177E679035A9E4980E828B894\
+87CA9D8AEE9406943EEB4AF2B715EAE982C0B129655B392F765C4BC59CE9AF4049FCDD52C50600\
+D4423045D61D4F917B2BBA7D20CE7086ADA6786000CFCE344BCFB937F829FFBD9388553B5F4E90\
+71BF8AAD6326859B78E4BB9F96FED01D84E0C22AA6FF48FD3A2171DA8BD32556E010E8FD120C65\
+02EFCBC0FE8F3BCF58A021B1CDE9156EFE82DA463805504309D515A7DF571BA206508CAD4B9715\
+8130576BBEEB5757F166E7ABD74CCA2F68417DF7076E2F7DA29AB4A4242545B41EAF240F1018FC\
+12E581A9C023FE555AFD6FB4E08D6016A465B03566EAAA4FC5B6583366639DA696CEB701B446BB\
+B320E649536C14454B091840C0DED9BF51111E3EDC26E7644CB8CD342FE5F19E8D81D9F21FAB9B\
+5B4C0FCB020E4468C8D5C4C6C42312745827DF00E8BAC1DCE0838BCBDEF39C05A50489D8E0B9D1\
+230729F544C5ECFE071F67900A394C2B5F3E993F0B1EFE487DF0C92B0C9C378D6ED097C4DD09CF\
+59A5470EA59E0CECD91129D26BB8FF8A145E2FA70C1F2AF7AA615712797E24546B22ABF8542FEB\
+F3C7948C328E7D8470AAE32E44A4E71FEA0974CB76B7775617CC450999BDBABEB98CECCD756B:\
+6951EF357C02124B4D1E31E956FB7A3E1F8EECAEA99C2E3F379D9F10
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+5E45AD93CA54638C779AA42B69C9CA40E659E8169C53F968126C05D39F08C5794136E206FC9CCA\
+51F496C6E781AAD51424188D80CC2AB68745A5B277538ACC82AF5F9C2F7E24A2FBA1801DDD7E2D\
+FB8D1C0A599E6E7DB9EE28483E9A2F1E02CF0C0640988C66B57F4B60018D1A7E251D4FD87D8D15\
+2BCC74BDDACBA9AF2460C3738505DB119029B4261A96BF5A95F385420713C283E843BE2797DC28\
+1C3F1A77548E97BF9B6D764C523D2C462F77DFE2121A9BE7B436CC4B4D6D00D8810E1B80DA3D53\
+C28D20B06272CC48E665150A309DC80B8E4B2C8457C73E0A81B734F82F0431877167F116306954\
+6FCBB7D0C828A8F92C60F28B679825CCDB9AD1FE0C20B184753AA2357B04DB9EE3AFC26615DC80\
+B7A080748709D2237CC22ADF374D74B3B4A1CD4265FD247E4B138C9E8AA4FEE4DAB218090D9C4F\
+6CE5CA6C092F109C5D0740F0D9BD298FE75979B5EB122E3EDC0F1B5829F87E3D92EF91895B00B1\
+5CBB36CA712BF71FBAE7D5FA4F912C324C6BF8C7E2F35441F9F38982E6D33299160B058843CECD\
+911A64473CFB46683B3AC23AC940E2B4E253F47B160522A76558CB8F487C87CE670DAF81E5650F\
+FF511DBE2DAA34344B1133E57DF8E7455569FD89C2763D7D3214E7B158320E795FCCC78AB535ED\
+A3FBEACB25CDC81EF7DDCB0A7C7579F78D6585DDBF6EB1234357495EB8A36B7B7F81F50B3CB7C4\
+185C208425DF40950363DC9917D129A681466B1C8F0F02ABD5A45BF240ACBD2263C74E8AA2D9E0\
+DEF480ED29773AA0D6BF518C0FCB8B6B005A2A41A04FAEC5C650EB280B3E92326244902DCEF85A\
+581517EC6CC917BCB2A69F2A070F9D8E0AC15F79790B0DCE9E508A8C55512E2C1476BB63018D01\
+4E101F13FA8B0B5CE0D5D6531DB60BF1E0C709C5154BEBA3CB74D8A7FB21C65857E692B2438722\
+8E48CC4EF259E94C2BFBD7B8D6EEF502E5B30227D08F8D9B31F61804220CD7C0B36FAE7567E664\
+FDEDFF60C3021B1E4FBC8234EEE749E01F0E3E4D6AB2AEFE5B170C01CE7C7875F12D8DF551EC46\
+46D9AFEB43D5A47C8D9CDCC2200BAD5D32624492444BD7552B7E0077292AD15CE6B26A8FA036C6\
+7CB71338BEDEB6E9AB0A17C1452256AFCC6F9E457525F9D285DE4BD16FC66309A047260C932EBF\
+F33E2E3E6EE3C0B3E54301E0FB5382498995E9C5D8078560A539CEB8BD22600486BEF999F8C506\
+E3B40BF2062D3DFA98A3303C52423C8134D713B2E7F5DF254237460655B4FC668AF7B3886EFF4B\
+9214ABBCDA6D33DC7E7C9FB9D67B056B9ED2ED7FB31892EDDAA32BD99C77C533223B4E85808F3A\
+0C50A2B196A6B091C1E876587E9631959BC0FE1A6711242D52AFB80664397C4F00A14017A2A7:\
+3CA260A152BCE7AFBC673137B4B258DFCBCE5E4946B909468F727B54AE3171B6
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+85DE284F504C0C624AE145B4AB67FB7D91EC26D0E9C3873106C16D5C09BC7CE453B4D495199873\
+BC375B31ED963978074F6F28ADCEFEF618DDD53B2393D4C99F6FE8F09B307403538EEBAC5B7647\
+449323301689751FADA050BD6C8B8AC14C0B645B0847957C803D9F336229D9C59D3A276491D4C6\
+06FE6CC1F936A97246F1EEBF398A4109D75DE8BCF372F8966579CAAC9A254C14DCB573F6868C08\
+E8D932A63905C8E318E28DEB26134CCA2CDD631389B130B1D0469B86C462BAF826EBD48CC9B775\
+CC5D0002D87CCFA7DF9F0E90A80B1DCC0F0741A3CD6F39E51FC10CA683DF6611D3ABE6C453CC27\
+675F825AC3DFF2F7A521D132C71E230E84C520BFCC1437905624C398B4C5908A0260E7C17D8C7A\
+DFBF75B059EEA93B87CA731D82A0505C590587796C7FDD614DBCEEC4A984E0612EDDCC055B63BA\
+DD66DA0541D35E4AAC9E766CD67CEE5CD75177387C5C8D94C86434ABC1B14639FA2599812532CC\
+CF2D72B3443145F5DBF2312C74263A48D8B7D09E8E622D9FA1723029C84C6D904609C253AF8FC3\
+0D574559247BE10029265C2DE89E12C4C4505434969E8703AF5906A278AC9F3E7E01D2A8FE09F5\
+2C121CB3A97C7C3A4B9BE17D146E8BC2213189A356E4D9959DB4170F1D004BB2D4FAA7B56FF489\
+8AF5DEAA337B1807B52C63B474E1FEF110AFACC1D57ECA33A2DD248BD830A16309CD9549BA44BF\
+D33724FD447D217E5E543AFE7DBE74C503383C5BAC4CE75D20632BBB92FF02DB888DA566BD7E59\
+4B613C3754E1FFCEB7D53C0BBE678399BA448B9E35F0F2BB0477B767B1488EC90CB4733F1956E9\
+6E1845535BA97224E569799551F07B8CEA084FA8852B17A9D8B34C0047A15F8D2754011C3B523E\
+3E5F5763EDF6A06269AA3FD281B8F9F1B263705A9F5170C34B9E7C46F40A3048E7B98D21CDBC6F\
+721250670E82DC60DA8326427708105C297BC05D8BDE97B0F78E55E00D5B65C65DB5B11849290A\
+6D58FF4F3B88697879993509FC7A5092AD6E194C35BBBAA74C2452FA12150CE3B6F1ED8DCEA0BD\
+600F529EE4D4A84400EB8E756770E7BCB7E279626F9EE6B30B9E9F952DEC4150CC71B0F9939809\
+C7D2DEDF98D01112A9A58821A0BC96D267AB9A2B77C21AE53F1135F9FD390FEDACCFA9A6817121\
+FA5719ACE8C079DBC8391C1B4BE6AF67ACDD52016933A99C9F2BF62093D5299D093EEE7226C49D\
+5BD519ABCDE8AD8230E3B3652F374ECDA7F0A6BDB84A8EBC9C657213B402EEA5EA5FF2F426BF8E\
+189517255E38E19ACC793971CB4492E8D346D25C10EB626CD709DD670631B2F19C95752879DAF3\
+DCD2A07109625F4D8403B6E153E3536521B78B6D6AA7ACCAA42B0A2CF47048099441A5823F64:\
+003776133C69B7D16F80023FFA5657C44DE96400BCF49A7F7ACE7BA18B224F21
+
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+000000000000000000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+09CDB68A29150A0DABA207A6515339A0AA10470318DD7C6C9CFE89F8DD520B6E5DC9A612C6E365\
+91159E162592D695B03300A2C5C4C28C8912DAD980E9AE05533ED8D7F05A5B55A8DBE01418C1A7\
+1F01FFC89ECE38B0B457FFE586AB48780E0F297EFBC7A27F713FC54D0E8217D760D545C6A384F7\
+5865C02F0DDF49B0FDFA7D920F57D988B3220DC1BDAFE0325EDCBB37E94C09EBD0E17E42FD0E91\
+F86B958D9BCDCCF525F8FC4F16ECF2404077257EE35C6E86DE6264910E33621535316C30752500\
+EC0D52BF3256BBE976B38390BEB6F960A6EB1954356F8D94EE248AB021CA09192F808F8026C34C\
+C95DB1C5FAC16255C518A2E3B0283EAF066F6B31A03B2170377C08C1D83D350762347E61365B04\
+D8DADA99FBADBAEF87D8008BF09EFA3153CA0C79321C0EEA989E74252CCE2E2A34F0FDE7AF1394\
+D94E2DC52E98B25680E5DF6A1F99E6178580F3FC6FB1217385E5BAEE4AAD33B434CD74F56CB95A\
+8F9F263A0CB5CE04D5939AB62077A5852F7F1EF8E7AC72A8DB2C7B13616B061262BB6A18970CAA\
+340A469BA8F86EE8D1776B3B5E2F20F64E4D02F6A3571C7B5DB810746252B6C51E584787925164\
+67B0B564A6C92935C7F05A856AA6080AF0BDB0639921A281983FCC406E3612B0A3626805ABDBD9\
+01C7E0E93B69505170CAEDD8B811AAB18698F3ECC6B6B0856FAE92B7D72CFE805931CC3C8BB65C\
+784162C1B88D53C50BEC2370982C0F4F0419D26D17CFA4E6757C782605B9419134FDA2F09C568E\
+50BCF07626B9E6B401F55B43036C72A339570652EA50EE4BA5CE3AC1E098F61AD23300D51F95F3\
+AF334CCFBBE3413D418A1009137CB9EF22ED141680CDA3FF7727BAEE26C2E35780F9FA8B63F122\
+9B24CAC1DEE900F52C03B734F54CE6F5E5F32D89E4C991D3788786DAAFDAC3C262906DADE08612\
+FB9F8EF1364ACD2EDF23416F1AD0BC3E23D5A5EFD11C3838D3E4694D065E04C349F97AB5B9B4D8\
+C0272CBA7AFE0998BC6CD51F1614476285F11163D20470073BBCE0A06EABD199EDD2523C9D595D\
+47D211D844929E3D614C26A75F7CB90734DC3B9DC7005DFBB66101D9B0C3DFDCB03F972087D093\
+4EBFCDD1C9BAC0F62D50C5437E5A9834DA80FCD750D8C577DF7703A63B847D75B9505C522FD241\
+10C1237F7A2DA2C6610661E154FCA6326A0272BDD16BB78C9891D3F94B1BCF064A1E0DA24B582C\
+962FB807C3A69B4489AF0EF8488C59530EA5D92A95A12B7C00F28889AAB6A91E0D9D6593944AB4\
+C89CF11AAFDCA2D72A1C0C793CB4C18ABA658207517B041C7830B3799BA802841623F3EC6C3D6E\
+2E1A11E0E33A1D1F97A4E6D771D120B11C52736AFF0AD3FEBA59FF03FCC087F50E36839B4119:\
+085A85EFA966BC844824B45AE82708DB927709623911A1FD7877636C62EEF2C5
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+0C79B2CE647574C631FD55BCCB1DB3BE69BA847E0F23AFB00C21B7D41794C10F3B8F61929227:\
+1510BFDF958D2C4BEC1EDBFD675ACE6F:6D1DDDEEC1BA73C15CE4851DE0B6CB0E
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+DC61600D30CAE1E33CCB50E4F7CBFCF7C889CE9DC780B264CEACDD1C21133B49F9E1BC4EB879:\
+0ABF45AC5AB91F794B98DFA5FA0CD894:00DA828DA37D94E0841A484A2EFA4C19
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+6072A1F5D942825E92CD02CD362FD79B209801622723A30DD7F99AB5D7830DD88DF4BBB29E24:\
+A6787289DDC9376947BB930EFD48CCC6:FD020136FC6D6B8BDFE9C13CC6E3F2F7
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+846C5C3DD0BE453FDA15DE04706DF957036BF8771305D35A99D57E5EEC0276A0F8C69928D05C:\
+15175F1FC90E93CF104366657D8BC80C:874B703E2D1AFA6A9DB2CE90DC30F76D
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+A134A7EA12EFCA03BB8B0D2420A2234C7CAB5F9D990A83D9C2E014F6DD6427F25044FAA47977:\
+51846E247DD72812FD39BE78E1B2F50AC36EA2E3:7487C24E287E5BCD87B20A15B9A5B7B7
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+69A0D15F8D18562FA4754B77601184755E99E3C42E618D497F8A165F25B393CEB6B00FC7B723:\
+3803A2009424E2AE8581075A53ED058A274EA8B3:E359E0E5888FE70D570BCF0AF6E89E0F
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+7876DE9ECF5FE512ED7E96B24466CB3C642EB6AF65FF7BC6151A92F08DA4BD8CF110866E698F:\
+936225367409CF84A999E6FEF051FD5E75882295:99EB3466CC3DD02A69420C158FB77159
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+BB7D4F56219322E943A1F8B23EDAE9D510760CD9F9F6DBFD8F4D88DCF237980B64AAD59747D8:\
+0EEFE7FA570C584A0A256B8192C964D86D37C3ED:4AFC9814F82675F50C84CC306E758A8C
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+C47122CD6BE53F777B20E91324A92307589A731711BC29FE6902935C307CB61BE8380E261794:\
+0DB2B86717F826082435438568139119BC66B0BCBEC2BE20:\
+B254D36F8AA0429EF8E197245B6B92CF
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+1050A35FD348E0EB6FF6FAC7CCA1A342B471FE1085B3B7928239E1926735E3832627FACEAC22:\
+31A10A2F283FBC4B9723794D41C935B03395746408A69787:\
+B69D21D86FE5C58FE8936043477CFCD7
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+F9D965BA84542E60148704BF612E95BEAA5F6E1747E22EA8F59DCA7FED5D4888431B1C0CF164:\
+8A8062489A1A70F9BE06B6FE1567CECACAE292DD7D7AD296:\
+B030A9DCFAF8393C46696F79D6599428
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+CF2485D29FB99F8ABB7BA07CCCA2982945BC033427EAB654711318911750AF51B560DB75B9AF:\
+1A738B670621D0F433D38AE8C527E3A534002882D5487EBA:\
+0B1211AB1B6266EEC19B7CE5EB1B2612
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+C5D1027641C9731930CBC636D34C027A561D787E008859E2C97FF3CDFADCE02A126298842372:\
+2273D359BE54CD6C8F5F3D5E0D5CF19D9247DFD19F5CC7F5F09076F8:\
+C9B2B798B7B4C57EF9EBC67C2DC036C4
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+1C50895355461A627EC16B84FE6B8490AE09CDA0DC6312FAC2402CEDCD7C3B211745083CEF54:\
+BECDF3EF2461DDC8BB7153C4DA7047CDB396DB9060A8C23746CE6089:\
+DE503503CB0418F161D46E03EF29FB53
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+E042BB60BDD972CBE0E76304378A5763AAD9E142FEDD3FF7501FA2EC0B49EEFAAA91F5ABCBB4:\
+0FF69687B5BAB2235F7F00BA631ABAA80623F7998C643B2C3CAEE314:\
+272EF1CC3DE16447EBC186209B8BC4B8
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+79A412224B54CC67A462A02A97E800CF052F39B083F628A6C2F2CFD3BD2028704426EE7ADF4C:\
+1CF78658191C43325399D78B8F88128629FD623ABC455944FED3EEC9:\
+B13E3072909CA56B16C01F27F5DE34A1
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+AFF10AD6FBD068C28D5E1F7A29149A49D6C29768996FBBB61142D6AD74C9C399A9133F3498D9:\
+FA90065E64D8493DB9C16ADD882D3BB51CA0C0B9C06B3FFBA5E04A2284D3AEF6:\
+95784AE2EAEEDD1AB38C40C810E66EEF
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+7E2060D913D10A1A1C936B7357A65449D590DF4E75DF36E4271F244E4A492A8EEE05475F8834:\
+4F0D8A0D3E14455A155BFFB5FE4ABEC0067C01E943FAE93E81983A0A76EAD0CD:\
+F919E073CE8C9205FD228079DB3F8BB6
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+C441EEAA8FA7661E14AD10F2B38D1210DA891FC230D298EEF4D9504C4C950B753D9D33E05961:\
+B2A5718C5A08671772836723C357A15BD6FDFAE38EE748ED2E94B5921DCFC1A7:\
+0A8B2DFFB1D0534252D8F20A35FC28B6
+
+0000000000000000000000000000000000000000000000000000000000000000000000000000:\
+1B7713FA6B8D47BB8EBFCF6F154788C0A47C5FA71A6EC061AE6D84EEC62649DB8DA7D8651CC8:\
+35758E318556EAF61FCF8B83E9C10F70DA4C1BD85336E087E3A2E72540B83177:\
+926F710B6040C8E755AA2F30F5A1F093
+
+[WiderWake4+1-BE]
+1234ABCDA0B1C2D31A2B3C4D55667788:0DF79CF5E34C6DCD0596ACEDD702AAD9:\
+1234567898765432ABCDEF0110FEDCBA:BABEFACEF0E1D2C3
+
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+0987CA45C360D114EB012D9E47459ED88C0B95B927E5B3B6D0A34A13C20A7A3C\
+B9B5A2BBFAA44A1924B40BF469E7CFEAE869CD443717A45F01AFC0A8231F8BE4\
+C6175BEC707A80826A73CCD57A2207C93B2A22C86DF66CB4823F11BF8C60F48C\
+16E1C18B95097CF2B4A762102D13E3F40D230FE8C183303AF32E43A6E4641B5B\
+792CEC33CCC1351E194899D7F6D9B35E921F1ADEB65C103717B3DF71792C4426\
+9DBFD7F7F76678F355ADBC402B1F4BC0AEE90ACC054888596CABC597EF56D8A5\
+2B0CAACB3147E5E450429990BE7D4267412600B4E700FBB3D0D3E5AE542FE5FF\
+46E5FB796080F4E03FEDB133D598CA782ED9353AC777BB7CD457A525A8163D68:\
+F234567898765432ABCDEF0110FEDCBA:CAFEBABEDEADBEEF
+
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+5C2AB1625BC271890886964C53FE7B994896042A9047059316035D4ADAB67AFC\
+C18414F17EF8891D3D49952D31CC01A4BCB98F2A81EB3D82602FD2AF18430681\
+E21DC6ED32E6F2A45FFAACD4BB81898FFFB504DFFA1E8B1953C474AA61FFFA97\
+0BE71A02E9ACC64DE7F2EECD5E7C1965548E290DB3108F79620B3F2E381143D9\
+D5ED2A7EE66C32D697E10ECDE7C7907FB011EB9E9862094B9384490484F3B3FF\
+E4B82648D57D9F22F2410F603BB12C3D22B48A9AA72215BDD62E849755A33B75\
+025252D67C80BA5FF8EAED75B62669428F791D1FA9B39789266E41C2848AF99C\
+90E10A1DAF45A4E1EBBE00C9E1E436D550DBC547BD0818E8E6E580BF911E879D:\
+00000000000000010000000200000003:0000000000000001
+
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+C65409182C9BE91884D6DA11EF91971717C3FBBA228B4088E616478FD11C5D74\
+076B8226F824AD7DB07B7F4FC38B8A442BC51F6AA51496911D9DA5E21083A7C3\
+DC45860D0385BFF75404A641581E2F87EC2BE542A2F70A075A10F4A2AE8DCDAD\
+4BD1396978866C9497F4DAAFBAF75A7B8437D09686800C0F819A6E7DE6BAEBF9\
+DBDFB5C4B3493AFB55311E06EFDE37C848CF99C0DC3832D2BE701FE121E1F27C\
+32563D559CA5E2CED8B66E4000FD280C8BE9116E91DE032E8D3C20760AC5FA5F\
+0611667720ADBF0DE5CA79A8DA58D5EF9237C2E722840AA596444BDA66B15AE7\
+C513431DDD22D67ED170ABE6A3E7CCB9EF8D7D5D44897C5916FE0EFAA827E86B\
+0C3FCA6A413F8C7D8BC7735A649AFE06CD64DD4086A6F3E80FE6CD663D61C0D4\
+00BA48E6FFDD1C971DBD4BAF46B5D6502A6EAA6096C48D5DAB484CB9095F5942\
+199B35DDFCEDAB9E573B19417829347087C111D2F87D3FBBA5EA2160055B1F56\
+234254251868D5EADE48F0DF21C1182ECBD201220251B080342B4AAC08C1AE8F\
+9F8410D93E732360ECCBB3D2105C3273CBF4772A4477E95BA924DD2C61AA8719\
+1FF467AF970B323BA61DEC5E08FF012E51F3E6D5EB8599C76E29BCF6B07190E3\
+E37FEFEAF3A1D0B0431A0795F319A1C9DC09500D648481C645F7C268691D465D\
+46BA742B49241BE0E46E7164493F78E523DCEFD1063487133D7D10C408AB5655:\
+771C23C6FE5A4873C5185CFFF61F58EC:59C17CCD08C4D7AB
+
+107C217F5AF5E15ED2C0AC85FE26742C53A70D8ABBB47DFC319F2E307A3327ED\
+C74ADD0C982C5D438852743889CA15742B5A1272F1FA85889F100D294D3A0C36\
+3F7052CBCF23E9FBA30FC8CB0AD7757FFB40166AF2A1509611AC6EC8438D2FDE\
+66046532C346EA79CB1840BACB9850050368FF5EE1790011244522A20B1C3B30\
+61FEF9DC132E74BDB37E835298E698FDFA60DDB9FE72DE583494621734609855\
+C5C99B58E863A0B3CD6A82BBF59D2F3EE03AC6464AB98EA087D33B978C505E55\
+2210EEFBA7D0F81B7435BD4FB9340C0BC75F7AABC90DE789CE3FF899058CA40B\
+F57502AC6ECE700381443577C6F807809212CE91E70DE4A5272A5FF11E403F9C\
+7CDE160D7A14C13BEA47C8CFEE4E6E6576A7B7A93C0E203D947ED5CD9A124434\
+914A0907B68A5DE1061D537956FC3A3C3E2CFB82641F2C33000361DC665FAA61\
+5EDDA3862DC54B463D5138E2CE68AFD0DF520F999FB0A0CDA0B09455BBD7BDE0\
+ABBE9939479EDBDCD2B9812207400EBD486234FA19ACD819F2DBA6C09F930EC0\
+4665EE163597B69C6B5C13B1026517836BB23679E9C308B1AB119D52DB48682C\
+2776E2524C00233D69435A201BC7E01AAAAE6CECF70F25F26D253AAD23B15DF3\
+79A48EB973434FBBCF807AFC7BB6C5B5CED51F8E8BD47C45A26594F89E32F36B\
+2A8D28791625DAC0993548A49C2011B4CDF4730D7C85C93CCEE16C5926A9D67D:\
+CF329218A3A3B6B08B89B0D9D8889F488B0CE31E621EBFE7EAFC5E45814E82A6\
+A2FBDB762922BEF71F969E5FB2F0C81060AD765E86A4A664B77C4E028535809C\
+3D6B78CBCE1D5D4F9D75D0198D3A7E7BC9F5B24D617821DD5B5386DA2E629FD6\
+0DA58E4810380E18D3D6F056B5117F29067AF8AAE29BC6E591DC2F7D38C3EBC7\
+6760A297D351EE92513D2296F3B2656C7B360717D51BA235B3C6581AE6264FE4\
+0494C2DD159935A7F36F040252DE647C0688B1DAB9853A47DA378A04065B3E72\
+CD57D1C52085C3E7EE99A33BDD305E318184A1E132BB8C673ACEBBCE7DBBB261\
+B66039AB388D3D94DD625058B0B582D1C261A61DFF23D6078E7B4114958AE0E9\
+7FE3F4E9D88289F57C9B31B31CE8F8B8F72EEA086314F9B117F3EAA024393125\
+298BE358444E34BDDF2B4DAE77870588F8C92199AFDB218A15E8D88361483B65\
+DEEBB0C33C0B5E0674CA4296996E756439BA809A180FE192A3ED89BDB5207956\
+1D2E935E5AAABDF04F7C5562BD371C41844CE9A29CEB6E5D3E1781C86689C59D\
+E57276567EE3F08D0EAB63B67DD949B58E47C22162E263B84EFA4EC6534AB0D2\
+2931F5F89B405147B2057BD37C1C93F45BC65EC64019D70F6BA6BC684239E12F\
+E164DECAE9A2640F47E0A1D8C0F4CB70B4C2B1417CF1D4E82CD79599BD4208CB\
+786EC8499954410D58756D21551223987BAA744DCBD4DC1709F392ECD3FF30FC:\
+50E3C199E9D556552E79026253E2E9FD:69EF9A725A8DC78C
+
+83A1729A280FEEB72DDCFBAB631C322C6A5FC558A49879F144A35FBF8B0636A9\
+CED7D1C96B6E86C406387C67A2395675FA362408F088811AF5EDDC95BB2190BF\
+2E06E34D00BC54058E4BA434F8DD1FC932CF1FA4C06EACD36938631FE67A7EF4\
+7542F6B566F6819C3D77FEF2CA072ED30F8A98D7CDD8D292190C61CF27BCC49D\
+5407E2C84F7B24148AD89ED31ECFF089ADE4DD97D7D23DDB13A980D9CD54759F\
+3B7FC287D63BEAAAD241CF4C3237E4751D5FC96BFF9EDD91514D1A598D5B7056\
+AF1EBAD0F908841D07B0D848316C181BB48212034E5FF696CD3212C605720A6A\
+B7606370BD2996C80FE30E924D2A9AE0D6F432446CC9033740A41A9F749E49BE\
+9E1307F7F1012F13DED442835C6E961F47879D259871E763EBC1F8EAEE02853A\
+5409E6E207C48F16AEE1973F517ACD71990CA26888B71621EC7B4435649E9277\
+1F842DBB87F52C6C0AF908B99050C4C5BD774F40AC9055CA2D869DF5D837A484\
+8C43F70600297A4BFE9D5D91077557C9C67D186473DABD022483CDC96890A8C6\
+AA1411048B646BC3499597BD6AA8BF9BFE2FDCB050CF2F2701C6F06ABFD4FF7D\
+80A6074511E975B628A3C185D76864D198383B69312536831889714CDAF904B8\
+A518B47B5FD89C0D5900A1043BEA33351929710F4ED6F85A0FB03607942C48EA\
+047371A191EEA22447D88C200D5A0D10C62528C83329D0BDCF9122DDA3C01C65:\
+AEC06F99E3408F738F040C16DD934157ADBDD9489B19727298BB426433A5D1F4\
+2CFD9CA4D5C946D31C069DEBC1BD9BCA52FB28BCA8EC84A32218DE629231D46D\
+F052558743E60F3A7042AC71D917C979EFEB8794006F0929B853F5C8D9C1741E\
+44EB8B85880BAD4C013F2047FD2ABCD06708D5A1483E9AE03B48F197D1BBECAA\
+B7C18F7F8332CF797A4E969AA032827D37BC63F49A64644DDDA852FCE8BBF890\
+A0E03DB5EA89CA05B11466A40322E2A1DB398120A8C84C522871357E92F954B8\
+87F86E14841A127E74D102178CCA7F83F2D5B142A9D05A9F224F27E93CB70C33\
+24D7C783FF0D3C475195CCD7535B9631DD1B520924EF14EA0A9BD5EC8380C39A\
+774234E41624D3A7E89FC2051F3EAD8DDB37DC8D9350452887DA9E7585949D6B\
+BA846A6AE0F3F2B469DB68F3EFFB3D52F828D91ED02234A17F4AF974B9DBEC92\
+B11813F0CB8289CA2F4465DD1A6182C3570AAEADCAF50632754986FF2B550780\
+DD069775FCEF49156422A63DA7CCDDA14DDAB1FC0DE5DAC3D8793F605E093B11\
+76407E3EF5B326DD3361BC4AE824B96237E34B67BE42BDBFEB7332D19DF1CFE6\
+ADE42FE5ED3CC3460FE6D1046A38E83B7FFC3BCBD26A49AF2FE5EE09C558D474\
+D0A2EEC22DCCF56BF208D7A1DA1CDBCDEE3A71CFFE3C205A8913D555363E3362\
+31D766F1DD3E0C78931F8D5FA9CBD3213BAB06929A5D9EE04E772646D32832DD:\
+ED507AEA3196727632963F503ED26A50:D5A58B8F626130C7
+
+# Checksum format is input:checksum
+
+# Randomly generated by reference code in RFC 1950
+[Adler32]
+:00000001
+35:00360036
+5EC8:01860127
+679496:02F60192
+B32AB23D:04EF01CD
+8CA9455795:07770267
+D37EAD077220:0B3B0298
+E2210CD33A1068:0BB90295
+5BB33F53C9D00795:111503D6
+537A0E6291C9DF5E4B:130F0420
+387900E329FB770A78FB:167204AD
+0CE184B96C789E7E0A6EEC:207D058F
+773870CD456F8797BC61EB73:2547063A
+E5FB7B41CDAA1C4FB21D195467:33B00622
+60D382B3CB4341FB141360855BD8:367006F2
+E48EBC5C8730639FFB47C12D238856:41FA0775
+4A25B557982801088B8B4E45AFD7DC0B:30AC065B
+A864D51DA8BE2CED6E2498FFB1E56C4EAF:54D809A6
+580E32B4D34F21CC2978076EB3A6D0FCCFC4:47CB092A
+5B32E288EE8AA4E866678D65DDF844F5B3CAB1:70720BF7
+B014940A8D58C8550E9E1BAB1E96540ED0AFA6DB:54DA08ED
+2A085FB051FD798552D6E1F60DE222AC5F595AAF73:6F340A7E
+C1A30E3E8EEB24B5350A75D1D38255FE834CFE6C638D:7D950B59
+A8BE4CC3005FD904F6E58D5DD60AF8AAC3928F2FBB2B45:97790C37
+C6D1E2B2B546867A22ADD3A422F2111ECE6ED49CE85F0ABB:B12A0D68
+A28FC69AE1044743338EAEB08DD876267B9DE4780182568D82:A7F70C7D
+5C575A7D25204220C994D3E130B48E14650477D64FE646890033:8F750AB6
+C3AEDA730EBFBFE54DCE695AD46CA06C4D2D197680C4C42645D60E:D2A40DBA
+D28292D1255B080A66BE9CD5C213844C2564DB843A95416E5A8DC215:BE1F0CA8
+A8E22320693BCB2368267AC0F4D448825F36A080CA2C6DFD67DA66D124:CFAD0E6B
+
+41BA45D14C618EBE7C0AE0150F1D18EA457E54164DD6E3FE8227EC874D65A085A5BC9B06\
+C5399B4C5D47A5D639B9F2E1C1211C46DDD56728D2269C7FBC1E9EA82B1DB5FE2974AF83\
+D33F5E7039E3C44DFCD9359492DE314514068E483EAF1637ABD215117D53755229962A37\
+B91176170EFD1AA0DC751B53059D32DD4FAB3C0AAF52375854B9FFD2BBB303CCF617874B\
+60CA368AF6AA6C149BABF22885F443F0D2870EE9A8E5E429BC00B7AA0942025838D8ED14\
+89114D4BBA666678BCB6C75B66902559186BA330ED378EA5905DC8B41C474ACAF54BF191\
+A0B20FCAE96DABAD046241C58324A6C1CCA5F50D1FC4C35FD565B53693D0FBD874D5959C\
+8327CCAFF79760FCEDF5C0CDE1721054B443FDE8D771B5621A9AFB0F935409F5C63638FA\
+AFB99BD5A3519408A30452A5BFF41AA62DD077AEF418942F076F730D10277ECDA8C1A71A\
+4E16FDA1F61FE45660AA554E530D31562818EC961EB116AD5161687A23B8DAD5E0F016BD\
+7AE0AB63E710B20AFAE8928C616292D5DF207042617BE830401C30A49FF8308D9060AB7E\
+124417B139FAA303AD73C7B102DF81D763CD239C5EEF3A5FB60C374216263A48B68C9CC0\
+2121CF90AE72F906BE21C87315FD88A24237215A725992F4B18855D2217A4D033F459744\
+0567736AE9BCCA4A7187479399B03E75CA828736614209FE0D3F71A9C90CA6310BBBF387\
+F983BE221729763B290C986B8B43BEBE7F3AF9A895BA29663C4B204935C0F7182549E96D\
+96252DA545ED4C54EEE6C1A174AC74CE9C22DF29159F8EB12771CB8396E6F07D0FC43EAF\
+930C0AF228D53527235637E5408A234B785A9E2CC8A30C7E27E1FC55FE6FAB0B3465616F\
+5EFC59B1B52F2FE8A4BCEA7EE470AC47E148165CF025B99808494865D5FFE9263150821C\
+10BD916423101EE3B8640CFAA74A4EEBC86349DB8C8726ECFD1F4B603E6755FFA0586304\
+196A11EFDB7F892B5C7E0EF1A41E99ED60ABE3402D5017240869A26F0447017A31392293\
+2FFA53E56BE913A0EA465A95E0370C0B5A8418733BCC2FD7D294F23C474E3C3D331E2B7F\
+42051E7BAF2026295B56837F497865D4D60B02EB2E76058756D2E306519046B6A3B71522\
+36D73B2C698A8F0155C4E8F1D634D5737C3D7005B5557E2FDF1EC77B2B16239B5C21D105\
+AF86B8BE5BFBF52E00D63349568CBE25E6735BABF057E3B01CAB9520D5D03D2C4F7CEDBB\
+7C6FE4943B95B27CECF671AEA54B8740074445D4F14C17C9B9A12E581B559CB17149A131\
+613FD35ADF9ADE4DE981DD01E45262002B480B2FD524E39B307BD5A6D1CF9178B59B98F2\
+B43EA4CDED27513AAC550E1754DD6452A9434BB59B1186F9DA61E174D6610C2B286AECDB\
+AE9E6CBD4D2BFCABE0B83627A13F87288ABE927A891E372163A87A437CD1F4AFC91A940F\
+F55F5DC6CFA5AADF689946192050BE7C:9DA7EB84
+
+# Randomly generated by reference code in RFC 2440
+[CRC24]
+:B704CE
+A6:47CC72
+E5B0:5AB692
+C52385:9B469A
+8E69FB27:2B8005
+4A87C90369:452CCE
+DC10A8E4AC5D:60375E
+6B48125403AF14:D8948C
+0BDE9946163348C4:6DC026
+384EB1EC12064AED51:29B27C
+AF4F16B80F0AC808B595:1158E2
+0C571D708F3CB0A234196C:24D7C1
+7FE77AEAD433AD02533EFEFD:E25DC7
+D990831F658D306DEF60A10D5C:E0C845
+826CE458F0983CB46E68BA73D27A:BB86BD
+995BFA6433F4185E76DC67F6D30C35:AEC6AB
+C7688868D06251C906A919F011ED7FFE:B9B9EF
+AA1E9FECA8E4FE3CE31928FC262A4015B8:ED74AD
+5273E2B97EC0AB37B1F3004C1BF69E7A0C77:BE8A43
+2F68AA285719E8F8B6C1C01227EC83F2C6ABCB:A852E2
+CFD75FCCDAF1980008AD554AC7FAEE2E60317121:D6F9B5
+29AD5BCF5F4FD710F0CD859DF62AD678F66DEFC0FF:3C15F4
+C70CE8FB338D808338FA51A0125FA9537206EB6961C9:A210AE
+141240BD7DFAF34FB8AA5ED107A899AE8CC29201B4CF32:822081
+10C4F0E357A90F7FAC078282A92E9E10E347D356199427B9:D7C1A5
+A982A5BEB78D751C6999B8F487F2A186CE587A0B558F3BD39D:1AC0DF
+D6AA6D70B1E5DC2985D0952FCCDB6227F1AEB01CE24B8B2C2F3B:6BF464
+C95155A2CB524B40F1F7DE80D2E0718406B309FE818AF6580B88EC:BB641B
+6E68D0055FA2B284183000188682F36D31B26F8D04950E381F965DBE:C62516
+260D0ECAA0E8E9F595C5AC8E1D7EEA2DA7603A96BF83251B3122C80D07:876037
+80E559D244C4188ED223ACF70E358CDE3110B6161F70C3289266873E7802:B8184D
+637C9217C88420128CB3CACFF911FAAA2257CB093715B882AE7B708E2EFE46:E39818
+
+D2272C22FDED6F8F1012F230FD29B56622D8B25864101E801EA80AD0038577D043F299B2\
+CFF639EFF4E083808D8C9A11DA0C6BDE91B58A6E1BD6F6E17D860E4860493EC7B90D3884\
+73A85332E39DF103D0133B7B3CE83BB88DE9333D80C09837B882B231DD2D1C33676BFD77\
+D5596B6AD4BDA0BA63150310FED783496BF0E10107889E10A95D81CDEC48C06319492BB6\
+AD17EC9D13A29294EE578377D772377E18727C38D96952322791143F63D4B8B849808448\
+400D2DF85E9722BD8E766A4A33F53F77F2DFD3BDF8AF16153886C9CC7B47D62CF957448E\
+326DD9E3E01C558F1D68230EF8D0B8F8D9CC427C94EAB99CB5ADBA109ECF52604CE483D2\
+CFCB12A11486900BEE7A78B9FDEDEE60E00DE69703C2AC0756D3A0D74A155BB6FAE5C78A\
+CA3137FE28928AD124742449F9B874E8C10B159C4E508771B6848F9A71DC4F16F42D8EAD\
+F4B0ACDC38D83A9F1A1E73A6D46C437A82B575D287AA0339F3A3390F9DA40897F6C9EF94\
+F4816234B9C92F9FD7D0E4D29F21D97A1465EC5341516F8E7614190D9CCA97DB96AAF91F\
+EA4420DAE08C43289775FA96156F8DCD8CD02B34C01297A79E2CD34EB211F3464463D33B\
+07DB91519C4C53AE9A8911E5740CB564F628344203A830356E106C45DAE9BD29CFEC398D\
+D7DA04FE67CE1A7DBCB8B0B35373DD241690A391899940833F570972AB9F49726DEB55B9\
+5F60173E7B32E81BB67B9141826862646F96BCB8331A8458615C2614076F5FA8C860DAFF\
+2684570384716CACBB375813E2331F809C4A7BBC3134858E69032814812D90BA2AD8CFE2\
+C5DDF24B8C802F857CC424842A1B9340A00A6824C6CCA9374DF99A882401B466C72BC690\
+2E467C9932061A27FA3DD75253DEE2F9FED87FC9E5963B1674628B3D227F2B476DA8CE3B\
+CE3C845B582A51D46D975A86D0C347A0ABED6AD55E24941FED982ED0BD92A01097E02ECD\
+E37F00442050B8F5FC22C295B4CA3EB66CB4A424E490CEAD354B263F2E0EDD0DA0D6BA6E\
+7F0CD84C13667958F936FF18938C657B0CF0951A554C06934C132030FABA32C7B038266A\
+91DADC4C5D65EFF7EBC76E16969D5A7BF0FAB573295CEB76C8623A79922EEA61B9C48E40\
+2AE547381D412F5C2C4590452A2651921E3BA8C5E3AE5313E1B61D83624DF2DB092834C2\
+9185DE44355B2D5E4B90AA81769040AAB8CF59F91776FFA86A7AFB78BA67BF90F71C9996\
+296C497ACC2AAAFCF6DF4BB59D1657C97D189E4CF4C14F834E562F55D0A2D2A0B3576E89\
+6A7F6D567BB78B8956AE4924FB573D509A5BAE3C75065D76EE5ED2B5D4AF0B55F17A4406\
+BCF38DC7302D8E68C3A34A5211F06BBB555525BA3312E4BFDA85CAD2BCD5F08C45010D51\
+00A0AC4679B54E518DE2FDAFCA039AF8E02DD713813A91292FE6CFAFA1E92712C2652586\
+1D3C48D2A0253AFD14A952871052130C:97E8E2
+
+# Randomly generated by reference code in RFC 1952
+[CRC32]
+:00000000
+AB:930695ED
+9112:DA3AD8EC
+7814EE:CCBFF8D0
+B833E34A:3CF5EA01
+E82355DFC9:E26E344C
+0AE1C79DBDCA:31666AED
+E03ABB0006E852:4B755129
+6A9F7E0C99AB3BED:3E3D892D
+901D636199E6900216:A627CC4B
+B56B114E357B346E3248:83845B2C
+9F85F4ED02899207CE7EDC:CF52BD20
+37548C6B4F99996A9E243790:90D9C1A6
+183C1DF8F8808870F6DA2A3FB1:079BD60D
+6213908DA80D4FB2DF29ED8737DC:994C68CD
+8852141FB4405E0C3CC6A14EAE64D6:256409AF
+B8BD524FF91CD2699195636E7035B241:AE189D30
+F1BA35E6503D50A6DACC2B3B3038B6261C:130A8886
+E3F51AA78DFE8C2083C0721BC280EDA90F4E:A10398A4
+BBEF661E8064936B079B7D398137C7DF7E9B50:67A1B46A
+172949BC62843B24357BB0BE815A231E076011DE:B1FC384E
+B81EDF9309B0FEAFD9D3C33DE2AC278A39604A5F5A:4F204EF1
+8B93D005AC5CB91F7422B1BB110070442C9B9D3DFED3:F2E02E35
+C2AAA8A9116EF67071A7B89BD930219A0D93B4D429222B:9DD0E0B0
+7EABAB1422497A99C6B99F91F6E69DE1915A3A87DD71E637:72EC609E
+CD3FCB8FFC0DD5E163E8B6CD76A39C2804BBE91821D780576E:ECC18144
+DA267A57335B8E73F77443B2C74596851407D4C5122F1B22B055:A0B5C467
+EFD26D48E020D6C8014ED651A47ECB61142BD1E10A0EA69D41ADA5:74E5B3B7
+3A2A70233F5A5BFAFB76A58B9131C877B6C1691F05D7B79AA7F1AB28:E84AA432
+21D411056F80656AD1077C1F785F4C44A8BB8C87FE5DFE14469890B52B:CA157CA5
+
+# 1K of random bytes
+ECE01CE672A42EC6007EF3FD6298DD8554BD3D01BE8C8D9A945E150F087A1567BB17266E\
+EDF2DE3BE79C0A14ACA1E02C247C4C5E126C941F0F123546BF6AA6B15C1639215C38F79C\
+1E441E8AF2F812ECFC89F2F9A358AF8D65F29A63AA49F42028B232F6AF3EBCB80E2CADC0\
+07A62879A065B0253239468043504C081FD6B5FBE1184F69C4D157883BC25E9D5985C0DD\
+0DF137D0AF6278B07CD9935F5397DD98FF1DDF2F47485CDDF642ACC901174F664D218770\
+D1C05246FE7E51B5435626A55C41900DD97663951FDF2EFC18F3087C24FDF23603676D73\
+2B7BE9A00E55DEE023077196114D9F516BBA13C93DFF4930F045484193B2FC6D41B7C9FC\
+1C6F362232ECB643CB5F74B637DA845D9510B881049FB651A47D1439D187020A89F48581\
+5D683509EF570023DD9D6E60DABBB244E7B94D56D2FE9E37D3ECD2CBC4EED7FD9840FFA5\
+47B44C06AF2102BEB08616C22FB45994372CCB9EF1AE5FCEBEBC7DB1F0A74EA260A50C32\
+32A36084CAE7A95FC54A61CC7B022096DA821428D9DD21A0F108A5885AFB11D777ABCD63\
+62FE011CDB7E2B36FC943C3548AC643357AE81917A7FB508202255727707E87B801C5594\
+3769152ECC6A8BD98D4ED4CD74D823D4176A66D3B059D711A58F7BA890E93933E81AA735\
+27FA1B7044406C8A38F14C19936C26A09FB1F4C380210E55A55A03557D72EB7EF1D9FC77\
+45817BDF4A328CAF340E7F6AF05182C08DA2165806263A28B0748FB5E33AEB8ADB4D4C95\
+5C998CA82998C26049CC549F77A77756A08986A2AE5C84E0C1EA8A7E9EA9E44F653A0C90\
+FD5BF615AA8F7E5398063BCE72E1EE15A32A7A96EFCB6D5365FA7E33CEA17CF0CA310DA1\
+67C6EEA1494A4C581420AEC2489ACE5F67F92F92D8D871B96F6583C7619E156495828C9A\
+3A08A33FCB4980522E2BCD7A9D5994C841A7E684F132BF8AEF668C1045BCED0C6C7E5B0D\
+FC46E24190B2A28EF0C34B5C14E16D36BDC3A87089297360A47D6B6121475274128D9C9E\
+BB10CD0220A1BE87A8A015DFACF19578075572836B4D2E54190FD709D95636BBBDFD2420\
+F893AF11AB4B33F489EB2C884AC4EF3505072162663698361A1FD5E9980236481A23EEC5\
+10EEE798AD558ECA4067C363B5E892A489A9913DB71506241C2B743F2402DF8D75F07F55\
+1B9E2CEF1ED9667BA421E658ACB9B10FF4531C0174C34F17D96F869DE142FE6A56EE1DDC\
+F0FB3CF47E856E3718ECEEBEAC912CD0A057C81C46F806AC8814F3F66B29B2433409129B\
+23224FFAC15ED1F21FEA148C41DE6B6F6157251B60B4A5E3CE91961EC36618BED42759B7\
+0403EEF65388F0E5AA28F305B48E66DE1E21D0891D64EBEF281DE976FA877324DDBCB104\
+02926EF8B6D0F7B73C55759E8B35756B393F12190E5EB0495DE818334F3459B6286D7FF6\
+D8C1D4BD9C3086F1FDA0ECD33C4FFAFF:72D73FE9
+
+# MARKER: Hash Functions
+# Hash function format is input:hash
+
+# FORK-256 vectors generated by the implementation in Botan; there is only one
+# test vector, and it only covers the compression function, not the entire
+# hash. The implementation of FORK-256 used to generate these vectors did pass
+# the one known official vector, but there may have been problems not found by
+# that vector.
+[FORK-256]
+:E6A3C4881D6B1EE37F70847D9C8424A3E2AC408079570ED5ED9D20D0214D7599
+
+1D:90753CE547CE7FAE1A736D6D38E8C6F14D93897D106FA63CA32BFD1219E06A62
+
+3E07:D5C380F39876FB9836D492ED520E2F6929C302133BCB9F2A5080204DECE3583A
+
+A8F001:13428BD3C7368C8EB0B890A0FA3461ADD5202FD23257EEAF1559079344123046
+
+EA8F7A2C:65DD3204D3C9E9CE5EF21CECB3421F59351D5ECF0B928D199887BFDAB1906A0F
+
+2E19859C9E:DC5DEF85475A372F3E16A0893302A3C77218C4EFBCF6D9331DB7A2D3CEC5E8C4
+
+2AF0BDBB8363:88AFC377D3630E6B686EC48F9030DCC78E64F7DA1023CC34D49F01861487525E
+
+82F8A36D0A7979:\
+9D96C6B2ED8B50A2153A89BBC861718C4744547F2AF24F648235E553BDC03E13
+
+78F37E4B9235DFFB:\
+CB3367A41C64D73EE024FD9F9BCB59ED66F6F9CB370BE0354D9C6ACFFFEE5D6A
+
+FB85C864108365961B:\
+B657CF6B34422A945A870FEED5468FE052F046626A4D9EA8DE0F6C9837E72429
+
+793BA844BCDD71B1B750:\
+0371387237C9300AC6E4CDBB1E33904561225D3DCBED9E9EDDE710BE34C72084
+
+19781F1B1394459A3EF407:\
+B53815CC5F494D0983475EF4FCA87AADA732D10DE1E89E62BE397BEB53496545
+
+55B5FD2344A64809C7608A57:\
+3BC33C0FFD68E3DE47D5C1E85AF732C94EA390999B0D10C428CE655A023699C6
+
+AD14F3D82E4349DC3B8C1B2A9B:\
+428111A57BF802669AC9EC7BAEF3929036FCAD03979F2151CE3F8C19B7430529
+
+7C6FCD56927F530DD8E27C661ECB:\
+098FF664FDD45068D5B51F2AAEF738BF35AEE8945270663A179FBD8C62184D97
+
+270303C1B3E754DB1B8A388632B79B:\
+BD6E8FE6F4F0D67FE6EA76774F8049FCB3E9FB9C490467CEFAE793900AA86C2D
+
+70B7BAB2A9BB809F9A74311B562BF43D:\
+611DFAC246B16D3D6A359FC580E477D474751C24A78225D93009A910BEFC7A5C
+
+5E01E5540B5B6F371F642D15B4F412C190:\
+DD75FD419466A998B7B460E093224A7DD82A630B6E88BBC8437589FE68764E4F
+
+3557FD9C93B37B3E484E55242105EEF9EB64:\
+D86D755CAF29D6DD1E339F4F3D8DA2FCFA26FAE62FF27851F8DBBA942DB8093E
+
+C851F162EDFB2E5D9CF7BEB5369B423B049120:\
+10095694CF4940D5512FA27975FADCBEFB4F96C4DA321A3F35F6B24DE2A2C879
+
+D5DDEFF9F8C8921DCA1820C4368F28C4945B0402:\
+D0235CA1FA883DC7BD2F8E018FC51739FC644D49BD9B6FCF0D4434873C7F466C
+
+8F5D3CCFA13AE2710E293638068A8936D9B2887D8A:\
+5135B14FD4DD8BA1BCBB0E613F71077EBD6B41B0608F495365D442D213ABB5D4
+
+F4247F6724C9832FF65B9D98EBBC091241DE8C9CDC57:\
+FD9A2FE9D7D59F793BFF7BE343A6EA70C37DAAE0B0162B9BD8050DB99975DE8A
+
+C8A3DFBFAF08F34B258C6BC33E826ECD5F808CEEB88E43:\
+CFDD70E8344315DA659697E6B929F7E5410BBF2BFAA46D911CA4D548F6A80648
+
+3F40DEC3198D7EF8D7AF8DAAA86C6246B464BCE6878D7D91:\
+A6A0D6461C505C70050235F89E88EC7C0E6B3DE130E198E2EFDCE562D4E354A9
+
+5D61E8C5431A0578175AF50F2D0D27D41D16E1C397F73EFF15:\
+DB064D53411169A3928C8C7B62CA538BBA5276FD83E93667195735F88EC4A7EA
+
+8DA080EC9907AC188208DED4D7F634DAC6B1382AE3BDB721B665:\
+ADA78594D6230C9587F0EE87F17AA21CFBF4C82DFDFB8473A8529F3DE6C14895
+
+865F5D01E678E4FEA91ED39B8B9B1C4B8B17459BC4B4A3D677BC49:\
+2641A6AA41499952DD1ECBF5AF4426A4DAAD233127F3AC56F308B2E9D5F25B7B
+
+D787FFA504B1470076F898CC0D2CB65CC23B5B02437539F54826BA61:\
+D29DF8910ECE7FDE01B2FA5D8641DEDE6E8DBDA44143ACC58AA2CE01D2406455
+
+595199257CB4178EF928983A6E822846C1B024328A3B1FFB6E242E3661:\
+AE72575D2EF2664C75E0538165AEACB24B80A3B28546096DABB2642A7AE959F7
+
+5EFBD43D66A7A1D23382E1757241AA5679B4C0F9F78419985B65D70A6E8C:\
+F707AB7EBCFFB3F78EF1AAB7FEB832D2651E82889AA95FD02958F326AF975D93
+
+32C2BF9FBF3871314F84F17949882E4BBDB530C8808FB58648BB811ADDCB8C:\
+8D3E1FE5840130D141A68991C9321719F4D50E13C52ACA0BBF6D218773871544
+
+7820ACB94D6A8A2E7B7273C6C528E2088F60B6E57CB4494BDAAA4B7877202862:\
+DDE3C2EDE2D0AEB9F80FC6F8C54CC6A108F5F693EE8EDE2C755AD20FCF011C1F
+
+A14BAAC3891D78465A9798ABC984407072BD209D80A7550DB1FA63EB922300F43B:\
+FAD764D75BB72296BE85979A4F57C89E51D9AEA8280DD87D18CA5ABFFD3553A2
+
+1166A4CEBBFA31E715B19FEB15D4FF84C35112E4876D7182E3EF97147606760FD23C:\
+57B507F04922E9E2ABE3D8DD8205579715AD0276F2179360C092966D3E335B1B
+
+AE7C2882888543E7206BD57350F33985322DED8508BBC70BA961C3ED35075CAD439732:\
+DA545CEF32F141181F07AE275FBFA6C9D8A299FD40660EEF3C344657EB22E8B3
+
+48F1A035DC0FE6D0BE1F2D1233B08714D404682DD8CB39F66E8FE163AAC79F7241E9BFC6:\
+20ACC36E9788C4E7484BA8C166E93953124F703ECC15369943BF81AF10062D2A
+
+ED596E8DC5A9AF7FF123D886589592D5FA0FF86151B8634DF4C4C1F1450E5323D6228BBEDA:\
+6E85CCA98D2CD2591018E303330ED12F3434DD9706A1194ACA4E60866F78291B
+
+EABAEFE3421D3BFB668B390430ACBA72E4EE6F2C92142A93F0BAC595906579C64E2A3EA33D0C:\
+7A7564C0053A3630FEFA5C3A2DC80B99341C05903BFB6765777112F96DE7D3AC
+
+F71C08AFD45891723E61BD9241DAC454A2333D2ACF21B3848EA47BF01FE524E4E6E1D47A635A\
+F8:04A03842A1E8E916781CBA312A65C3C99DC949895CD48567FC3C836F39CF8EEF
+
+E2895A841C03629710EFB16B6C921E31B86A882A56C63914E631446A91FA0092A2AA570DCE0A75\
+2F:737E62D552B437F0E46EBD69A2BBC3B8AC4A4992AE64830077B8E0A9946B0454
+
+002E5C6DF7AD9BFF9E6E08AE68EDE886B39BF6365CA081A25576741708ECB5B64D80F640EB26AB\
+69F5:609CE0C785C2BE58F1E76CDFBD903C48BFE385EE035C7604715CA86EF9B38D1C
+
+FEA76D123D4EA976912A521763F6588E56D694791398C6DB760E5BFF381A6506EF4280008A5948\
+5B5943:53598D2271C83D3238AA9FD90DE0B5037525854770337FEFBA0FB636A1623E1E
+
+AD53132CD9C61018CEC4B07278D5667DDFB4EE9A839DBF584962D1880345951007DEC5E0F52FFD\
+9AD0FD9B:E8FF3DDB2CBAF8B220DEC63B5F1320E02A47A5ED02297FDE7C0788E5A7306082
+
+D11C82ED861EB312B69AF9A372B8F41D0BD9B0BF2F03D9F1F13D54CAFC475B97C39A169369EEA0\
+D92606377F:544180FA5E0FDA3054596B7ABC0C6B7F0CF5ED755C5C490E7C93FC00B4CB0C8C
+
+7C438726B3E3AC24D06F1AC23494F030655A4E5DC5D523641B0BCBBD8339B3DD8A0632520BDCCC\
+29DE6654B5FE:\
+5F00EC9E215EBC9F7669627B6C91FEA12DE0E4D475F49AED7EA937AF490A599E
+
+9D934509A19691DF7555BEA1A244AB503D278918AE8A0D984300CDF5ED7962A8FA5EDB01E8D38E\
+830976BD4F6800:\
+40135DEA3BC67E8C4295856C8B30B9AADAA904A5106CCE597A49912DB64CC8E0
+
+9C0EEBCE97B82482CF742A88F3671F85A84239D70A9A03D07B67876FE7C103A787A941955D2149\
+662F57CC29C93ACA:\
+8EE3D2595A3427BA24E14D610246CDF354FFE1704C42B1CA50B22E400AE0321A
+
+D159C512621C4E59F0F2D63534E62E66C0AC8665F37FE51213305598A53148A28F410DACAA103F\
+F204372EA0CA1A0023:\
+C0148D8A4688A49E35014EBC61786F00743788A4B9529C2C02ECCFED5B00BB08
+
+89724F1F0A6377DD6AD938CDB297F247BF09CEFADEBA43F5769799948D6D5D160DE142A7417315\
+6FCA9A237573076D1655:\
+4DD08B4E2401168ADEC0E05A341EC69A27890D0DBE48D898C9B657AA6D753860
+
+89308DC7FABEB7E264E283819D6742A1FA9DFA076CF7D607D7B10E9996F3C1349404D01737FA32\
+ED58555A00935F54C309F5:\
+0D8E3B5C1C8876DF9021ECCAF0D0221E4F156A9EA75624335C39DBD7F96960FC
+
+41FB354861A111C2169C18F5E29824E0E80A47CB8C30D828369C6C2456125B685B8CF11D092532\
+E844D55C8A492D660504C908:\
+4BF1967D6772CBD680C01F244EBCDE85EBD402E6CF9B5EBCE8A00B0733D09132
+
+3B4D0D2D8926B376A5CE3421CCE1F4E5D4A1818ED55996CF2EAE935D0E41CA7621CC009BE7FDA4\
+AB371594177DBA06670A521321:\
+A0146AFB474623D6559E8011E112F1DA7E3F0140327B2C8205899C2A0B611022
+
+2175F02F451F59DD84156218AE9A949ADDC0428FFD980F23CAC66570160637A40819481F528C62\
+A4A7F1B5A092C7FB4B9101C5E8C1:\
+44787DF2F8F0E4203E3EBAF8304744DFBE6DF6D53C33D4BB6B9A3A40766A2CDE
+
+9F836DC75A54F209E4FE423F6C08A1E3565732E8642DEA0C17E59D27C63A8ED80C6E18E48DAEDC\
+5FAD99E27DC63F426C6F6BE02EE03B:\
+0379CF92A8627230F274731CB269E5DE24A91435D39E7C461E9E0AEC9CA1C30B
+
+FB1678C2D4A5262046B0B7A9B11B5F069E4C0297C1698DC6766AEDF936303B3DBA1FC229F1C1F1\
+FAF54A32D72400514274A741B7AB3F43:\
+08826C3E6319A2E9CC3B23E0ECCD3AD2CAF30640D1250158D8E4ADDB46217AD5
+
+24D4117E61379F5E55CC6C311B140CA4FECC300909BB3BC05FDB68B961187F3DE2BA18FF7F4522\
+012DFA073122902D691A824F6EF08AC9E8:\
+36D90AAF4107C7790231FEDD5332027AA45540908F7881BFA6DBF6CA26CD220A
+
+1C4052964E9796FC030EED644C4661F242BF0AA3D2E93141B85D0383AB29C0025FFB160EC413F0\
+4591B18F3F892639EA57B5558ED8DA358961:\
+CEE495F4969D81025AEFDCF40A20E54B060F13B755633AC2350569DBAB97BF35
+
+00743CE2A53D08393B32BF3F8EEB081FB684DE4905834AEBF966ADD0EC484FD5F0D15131E5674B\
+15380C11554EF823838D931EC010BCCBF928CD:\
+BB7279D1120515D472EC9CE71BDC32BC7CFE8F3BA7D5CAA371816C3AD23DAAA9
+
+6C7D10949194F2C22BB9CE620FBBFDEF0B61BA1960B580BCB29DDE81A3D5F0BD6722046191823B\
+2297CB1017503342A353D2523B427086BB2DF313:\
+199B856E5AD193591859688E316E09D6942582DFA984CD8EBB8FA262920F2645
+
+8D2789C6885A275FDEC50B7B37065B6F681BCDC0030E1C582BCF3247133D293834443A3FEB8F38\
+8D67C729F92633AAC54CAF6D8857C1B0FA151064BC:\
+FB6A7F1878E278BE80564FFC190097724A870F09660FD3BE72878713BF13E618
+
+1235B88BA03D232060450C91F3374A44FD4C40A03BEB54523AF85F7A5ADE59E31E23AD0B0FAF7A\
+438D5F3F981C03D2C900BC2A9C5B1B979145ED3C7214:\
+B8089EF455C50D5F3C4DF616C032E6A593CE74D05990FFC9CCF5BFED8C7B002F
+
+511DACA4F9FDD439D14FC91E3350CEA754E8B32E1CA9B45C27006967D86C2D5A826D6606588E63\
+3781411F627127DD135DE7CBC03025CC34B5601D4CB7B5:\
+CE0F3874027B7573BB829CC054E63EEB9EC46BEF340213DAF5333791C3D3556B
+
+08AA26D82CAFC07026B19DE0EE09D74B84C4AEFE969D60F76B7A819E4E8F1CF8A687E2E9CC4124\
+041DE331A4D078D836881C430101A89FD89BCAF6C3AB425C:\
+BFD882A8BA5A0A22CD63466958A9C169F40068ACBF7514B71B79438855E004E4
+
+530E88B454E963D5C46F2D58713BA9CD1792D1B262BC4696BF8AF0451D4E34555F7CF83C94B7D6\
+ED1FF924603F80F36CE994A41D308F5D4367C895104BCB1E7CE6E16E6EA1991B245851BA28D915\
+86FBFA9B295EFC15C5277711D738F8B061ABC5F8A2257F85F4BEC0E37B53A42B7A3A10D11370FE\
+B4DCB29E6C0E17E15EC41BC695C72B7200785C7B3DACADB7682441E29DD3D0029AAB241CADB2A4\
+DD92997A93BF01DF6605A8CB776789F12A5D402A1DDC4DCED50FF449CEE65EE7296E88D61758A9\
+7D0DE90F9CD9C44D165C504F61F32800CC48DE51CC1FDB3CBC5E2C3F200733B2E266049945CFAB\
+F41A665A3CF8C65E13D784E3C5D40AFDB1E1526DA87B27035CA65CB368457E627A6EB5962DE24C\
+FFE29A723F03A7A0409BD1ADD5B6A2D0B39C2372E29686CE5032CE1473CC1661B06A3243714265\
+698667B7BE6688922676AC9042AB6A1785D732B2F4EA288DE4AE8CEAE26DE59231FF04ACFB447A\
+71679EB96320B22BB0F730E17DEB159B661D8DC6D397B5C9ECC722BE2AC48000B830CF7DA06572\
+8138A8EDFCBD04E97E6915825CA08A7AA4B5BF96CC2FCA7E391222C6B3247830E77BE9AE10230A\
+2A97099A4344A7203F47689418C72626435DCD59208E679C6B387AC88B39D50335E3479FA62CE6\
+94E4E3CF65018A0938911BBCA21A28C8B54BB43C42B9A868309428A89930CCD71D74A425A30578\
+2CDAF4847500035E53985472F4CA1C4A78240BA9DC9E2E4FAA636871D827B02454CB8C209F9F2D\
+F5D7A62D3B720CF9D9B21B1FAD6FBB34FB6B3A7E89014C54927044135465F0F42AFBF6E77AA6A8\
+498B7917D130DE7E7035577BA4C9F6400ED183767155348A9A2C1A4BD63D1CB9ECACC34ECC2D80\
+E2CA077B0B53A9FDB225624E6774D3ADA17688B6040C53D39D3545C4B20D6C4A0432C18B0A1E3F\
+3AC14CB7E90E4642A1A890FED7D8E725065D52C8DA6942BF9CE0916F3538EF63C327594940BE98\
+7F36764AB59BB6B42CC4C42DC3F7BE7DA7B8AD1DA51462C0A72B9ACBDE65029B2DE0809C1AE230\
+B76014F42A41E1B7B3332851DC46E82704B01CA0F1417539AA8C0BAA547838A6443826E12CF993\
+C891BF6F303C4C20D2DFA07DD14B7560C608CC3B8FD8AB7D825EC2834D08289360B613C7F435F4\
+78A641D7DD115940BF1C5200D6DD54F612DF6136DAF5F95FF6BCB9D9480E60BC8020B9C9154B25\
+4860EBB4FD3112B33A18FCEA742487D79401CBCB07761EC3874663A4791D5508BBA41CB14BE22B\
+98826462194D7943C61E2C3C01A8868E121429B4C49D9B42EFBB10685CB6AFB1B11EC17D7CF2E7\
+1482325F3C16F9C25EC3FC7229B4DC3F82162E3E2E04DFA670AC617E4274D73163D24E43D06687\
+47D1017948E4BE0D0722B6830F415A409DC7A2B15B521FB19790B9EA07883AB000D13AE2E6D62D\
+99DA32577B6037338E5E:\
+06308BA4E79A2CF117A1D5BC027A7492F50138FE4750DBF51F08913ABC40CCE5
+
+83F47CEEFB4E8306A59CEBC0BBECBB88174E17497C1BF33E9047B74D486A255EF79F1555E8E889\
+D0311CCA0B9EF678D976AA02103EDA58CA7A33CE9B7C994348A1641B3954FFCC1AA97832248C47\
+3187D69CCD10A4F553CF73964DBAB05006F0BAC17226E7E98DA3FFA0B8A8F241FFE54A0FD5CF4E\
+B9E5327CACE16B445A65FCA2CF6F9F99B000B0A18D7F3634A00AE49B9A79753C61E3C1453C6C0C\
+F210D6FEA9EEDB12D8F79275FAA4438B765DA316DCA0A8C5E084BB422883C2C195BF49130FFA10\
+D291D69FA362E2B96A6E2A4C9695154BC6A4C4CB194420D3AFDE1035A2CF57E54FACAF2DEAE3AC\
+790A0FEF68290DEE590DF70DB61AA7BB94015F18E6DDFBDD50602110D7FCB5B97612E6FFE5EC16\
+CE738BDDDF71726972E80860BC04CDBFCB67C5AE91E7F4F7913C16769A043F46A986AEF327C5D3\
+FE4AE2525815C162565048D99C559A8F0E9DF8BF88E178E339AC39EA836A9652955B3F440E090A\
+D28A8E14E29E78711A1744E8CAE85F55FA7EC643F4CD1989323F0E049A3BFCBBF254F2583361A2\
+798BAC6411D1FD837D7B64C7A7D93DE278E1D8562621D8B04BBD0CD4D7425C6FA909B3A6241FE8\
+C1A8D67FE616802C69694A318A5D47F97555458F753A960CA9A1DFEC13C8716EAB62603C07A10C\
+67CFFEACE6A1D81A4C4558258C8C14CE75961482B2A34BFB1C81C8474151434186ADF205855DB5\
+F5CEBCB7280C4C9D6CF08167DC2B5B1F112EC3AEA996953465377DD883889D164DEEDD33A012AE\
+3F474417384EFB98D8FF3B757F2B8A8ADE184D443AD1945C14273D4733108083DAB38811AF3708\
+79F8702780D041238B6E5D4AC6D5506AE03B5EC0C76CC16C15E33EFFBCBB877151AB79F2F13F2C\
+AA51ED3B441B7AD204CD209AA19E569B7B5D67EA549F70572ACA4CDC3F438EC78AF5C4B832415A\
+CBE71E1E918310EC9685595F1A62FBA2BC7FC933CEBF1EA6FC00151E33FAC0BBB121C168E7AC9E\
+C4F78B18B7A122D1801298C5D1268AA66CEEC75A5795F3048E6763762C98746CF763A2AD9E78E6\
+30D9402C482656223F21958AA045CB90027338858363EA97A639F239963A8D76622D42E069E813\
+ACD776879FA1344A2C08522D0B53C62E4377FD8504817778CBCCD074099E097A2E361F138FF7FC\
+B60ECCEC6029549F0489022379145A5EF7A7781A1B201B6012E125F9969D57459ED08D21773718\
+AB2B58F7EF41E2FF850AD8194D37324F59B50E85123AA972AD28587C526F05D81057A6BED26AF1\
+E174AC90645BA624287209AA108C6CA3FC6D3532AC28D8314939C1E320A04146D0A68EAE82D5CB\
+8B368E69CAE0040A33BDC3D0DABFA26D70E99D4A40E7675443E22FE51FD2FB5AF0091060DDF96E\
+4C4024D1F1359A95C1B93CCB25DDA483363AD73C4FA952C433809B4C1FC0F3D140E3A6856C9CEA\
+46EA438CED188E0BAD7BF4:\
+226404B39155EC9D9CAF51BFC6A7F0115355FD83104FF66FBBDEB5BF0370EA99
+
+70BEE2D1E703CF4D8872E6E63BFA59A218F8830FEEADE6D2412507386C9CC90EA83312D4565E84\
+9CC6FFFD58A90D3719D1C0AAC147B20033E9F40E515CAA938453CC2EA6D848801B8F6A31721334\
+DAFEF40DE5C8E7C33B1190DC6A33F66CDA2D7174E2CAC423C96DA4BCB399863760EDB44990C2F1\
+D0031D56A9DE624FF3658FF14D33CEF67D9752678A9F18AB64E4551EBC54F96688856AE25C13EA\
+C5A2E92A43E32590509705DA31F7B5A750E6D493D6F3BC7CA0F5E9B1782100E9BB6A4DF4E5934D\
+97BC0D75C1A2341B93024AB1D997F270922C7E2A8D1F6F453FF2C4AA73C69A4D16B50DBF8C1FCB\
+27B1002E4EDD5C3EAAE1DE241214F2E50457551EA42A9A6D515B7224011F9F51D20BCE07FDC533\
+080AF6A0217A2F679D60FBACCDE2659F637481BA75FABC1E224C52B77F74379BDD6002AB917A8F\
+77CEAAC83B134EA14A5AD92780C84CFD08CE4956659900D9F57278A2F074648AB857089F204150\
+899CAC987F522E5CFF41C2289F7DC079B1E7C9F10E41E3B31CEE52195B3E49AB6C4D2B5613BD0B\
+BA01A76E824408BADAECE8BF22AA0469506DC88AE469AD679BFA254ECD06C99F8453B720D4BF05\
+36F3C6272CB8FD8B0F1B995FE75E0DE6DCEBA87EAB8C822325951FB024D0230A569E4CCE190F72\
+A16637A3D3865D33C0ABBC0A3182C915AAD6B4CB22A648703F164026481E6505C6D80A5C7BFC0F\
+32557704563399317F1A1DCF0CE425F20E9290FECE77831D60FF3472874C1F4BDFE18A0A00218D\
+0B428EC195BB221D1C49FDDB68039980AFFE6EDD7C166E944AFB71499CDFC96EC95BC28DE747EA\
+72E031E83D8405A8DB1B6AAEAD15087FE75DB7471E2BC49F9E9418C6BD52B32D747B2ACC1F0F7F\
+0B21EC4DE2879B249D6FBDDF5B85FFF8A4861FE7206F9F84F5B761398055038FC100794FCE09E9\
+96794DB1CB30FBFAE4B183D0BB0D1C10920DEA7B7D3234F6FCB682375D8C36401A9F67FB3A8615\
+E3F649B7AE4D6586865A1D8CAD6DA45B694977B4F378FE610C4F943D41A223BC7318ECF98515B9\
+2168DCCBA7411AFB84AA6E35C473D6F595ACE62336AF52298040FEB2DF462FA30E039FC4AD80AD\
+D3B420D8CE0675E0DEA46884AAB203699B65DB309E71615728A44E80EAC271541C6D85A3160C7E\
+5274F624DD288C387DF342619B751E15615E464249CEC80FF132FFBFDAB5827CC4DE01FF506F29\
+CEABD8DB256DEBD26D519F6210E3956F95D7ECF1E48DE31839360C2985815348D1A451FB4683EE\
+5C06C362725C97E8BA8F9926691B32B38441D49B4032D9239033A72288FC98B26BEE3461F6147E\
+1C6C1D93A4B857E53A5B9B25AE03E5741C673E7D1757B165F36B21170A5B3B9DDACC015554E132\
+38B987DF9F236A689FC79450CBF3B611660267816D3152CE6B75A2D6EFBCFDA900AA3DDCD5B684\
+5448DF2F0C089A436D3C7290:\
+93F020C6617AEF37E1E53D0558AE8E8731E9B79DDEF0C3BF931973955175D957
+
+20BE956038BE1F4F76697367DA55A382B082DCF66A6EBEE838E10D41AD87D0F1A83723467AAD5C\
+4AECF39480ED5E47A9143AE6F9AC5BC46E7AC83428DE404E1A89D3783FC38BA0B16FD912D118F8\
+3C4631375D39CC220A278485BEE01F8B45AB57C9564566F49C3584C455919095713A75BA91CF03\
+CC9BE013CF9D69266071EAE64C2C07DEA0C117271D349DB1A940BF3B2C91F3AAF407DBB97FACA4\
+7B909ADC6F1EDC1398015048359E0A831AADEA251F8BDFB88C6B9EA073BB238134483952D0F8B0\
+E9C0629E55E5F5DD47072E9C5D0FBD6B4C5326C11CB2734CA4DAD6E2D8BBA212F6E67F570290B2\
+1F1D69D146A140C57125D169EAF6B91913E5841F2442E0AB40BA77D8F376E4C45C95BC9B4797F8\
+DBF941C66252539E63E001D139FD4A59E7AC4817B73879A2522714979F536F481B76582653B482\
+4DD76A1441A8A1525E8192F1F273F95DD564CDB4853B682E87693EB2B544950BCCD27BB664E323\
+1080A486884F235DF20A7E6639B40DF4D63D0A2112B5E6BBA21838380DD4E49C1F4965B45A335C\
+557860EDE58AA283CD176285DAB929DBA3260B5FEBA261FD9814D09BE315FE1493A5AEE3CE6071\
+259982EEF9716409A09E28091F23E1DE08E7B89962CF354201247C15D75281ACB079A51A9F3992\
+F9BC88727658E8E1BA6932C18184EC3BE572B98642BBD886242F781AB13362B389423B39B27E69\
+E6D91488A280E1040110E037FB0D55B12DF029B7D577B0F7FC7BE884D3FDCC066A57D1A0DC86F4\
+12BAC3079696DA7AB3DA894BF399D9B56685FB405FDAA681AE09D8B53D0CC661092F9A13F89173\
+1205CA3F7CF939DF632406D37C444ECAE7A2A293DCBA2F647FF9C775465B70D663878090B0FAA2\
+C48F5D681FA1B0FDCA11FDDC779B47AD2814657585C9A4EBC5748B48AD7B72FA5E07040DE0914D\
+4F8AE04806835879FC0BD0B5B150A157C0273192B0779D37D0B1AEE1043BECCECD80A8690EE4A9\
+207564E5B703559C79FDD16C040E8E60AC42DD4E2E9B66C14F2C44BFE7A360638ABBFBDF1C4B31\
+53B81BA783BDE2B41EAC104E24ABAA66C83D69F7F5143F776C359335AED8C5AB47256139834C32\
+085A351ECAC6AB4F8DC4F097B91FA156F093A93C7CD5EF5CDD5F4BC1A650C2FB0E7ABCC97947A8\
+7620D619DC999CEEC1796D0325B0533BC08E870DFAD00FD518CFCC38587CA225A965594C88B969\
+0D63F37231BE9BEFB54427F76E230792DB580C7835F60E4744D4B9FA2F8BCCD7CF35B6345666E1\
+753B538E276E09966D41F3B1AD3E249031775B448A1BF1C6DBFDC643BFC5F6CE3D670F4736ED9E\
+A546D9351429DFB9098FBB06EF908391A6BCDFDC6E1DD3C5CDDB0E157A26C8D7DF8BC9808C7032\
+9FB0CBDACF5B6D4BC7A5C69B231A145F15B1BCDD16F9BAC45EAD69D54281FE1DFAD35CECA9320C\
+068714F99A21BD61EFAC4B64D3:\
+7D08AD57B93CC590A028ED1EC9C32BE0713C82EDDF6A593616E681DA0F0E6E00
+
+95315A26C618D637F1A28403406D9E81C76D33F8BA62F55F2EDAC56883534DEBD8B83F2675C58D\
+455747473F92178B2A3E356B3D02455ABDBF32E9AA934A5A2D85BC87799F45C068C137E170E8D1\
+D26F2BAF3551CF367AF42208DC66316A93D4B594C96AE0D4C5B4843D80464C35357926A3FC7531\
+AB7E0A0C3FA899481B5EEDA5FD3193A13019DB382860EC6F6C842A1B5F9E90337403031FB4BAB1\
+F2AF12171793DBC5058E8D53675A6422A6BD9472828922FC36F05A4989FD48658AF04DD0B26FE5\
+D614BDBC05A2046E28502F531938AA3076200EA90641FBA11DAF84A670DABDCE3831D50D9DC46F\
+F3D302B339ECD9D2465EB65A6BD0C65220025DA2BA27AAEF32D4567884A76688322CC997AF5FB2\
+DC15EFEE3011E4069CFC3E04DE84D181C7D2FB48E156E0CF46B0B8A68E8A2F2EE49BF5F75FDFA7\
+B0E615A0B8311614668AB8EF68FFE2D72A074F3FCD5384F8482DFCCA534DF2434AEB2E2D3CA69B\
+D98BEB1479C48620A8AB64B31D94EE0934DCC3E1B459D3A5CA345A7B91DC0B797542BBC3AD3559\
+C5ECA7E85B427457299B57F236CE7D836BD850D8024C50165D3594B9F68464C0C16AD7997825A6\
+E0792D0277C21FCE28C34148D65C2CAF04C4A1852B79F365DDB50CC038B3C0B8CEA6B6BF64F083\
+0465724CE5A2CDE6EE03C4BBF6ED02F4385156AFF9EB9323B820AAF32B511DEA73226FF6514049\
+AFC462DD093267A861CB3C77DF626BE8CBE5C36AFF3ADEB4C51A4E58F8E2F2DE896452F49F4AE2\
+EBE07D9EBE7B84DA4AB48829451F6F0EFA6B0775991B3E8271C5F898514B47F5E1FFA24EC91AA9\
+E261E69EB9BBC77C75B928B6B70B8BDEBBCAE270B225D0E8FEF3451A202B82A6864776C3B4DFB5\
+6EF99D2FABD30D0BD00E2D77EBB1B47B6DE59C8D82D60149E772B2F8FF73898658207DBCCD402B\
+26BBE2F044AF68E05ED5835EC787B359C6BD4E10D13418E6552BF31F39F5B5F224F578AACE7CE3\
+1C4F19CE8ABFDF2F5CD1B2402A94A8B07B1A887A1AEFF95FBB0F1E4F56AEEB4E3861366ABAC0B5\
+F1E8B76A079F5835FDFCD9AEC107E68EB00B024FA537766BFB9EC7B211257CD894B74A216FAABC\
+7937742A8548FABB60417B467F9583D8800CE965305D56E17AB6E5A78593E07178F6B3CDEACB74\
+D39A909F7745033BAB6F048480375683F5595887F6CDD5476BCF016878CB991A5C2E05E5B7D08F\
+CC0388573D75284B1F374B97388792EBA1DB97206BA34377A5EC482B83A58D3D113D886464C9DA\
+F7FA3E7CC34C17BAF560FA1363BB766C4822DCCE82F391A759870E28BC0C3FEA07D85ED67AD2F5\
+7CA5868A38EE2582EBB3981044EB4C9DE914759BDFC48511611AD61A7E4DFFF23C55453E03627F\
+08CE2D8F8547E43C42892464A729DCBDD01B3E9C7ECD63853A7A6C0AFC21610AA3CE40E9ED5860\
+C1CB4A607255B9C68D211F3EBCA1:\
+4B34FD24F0F9938C0D3FE66CC29F90963B03543087D1C9D91ECBA5C963C3A5E6
+
+695E1DB4DBD8CAA02EE634A3FD177C3A2E9287C4A5B2AA19170E0BEB3BC064659412218EE812ED\
+18B44A23CAC021CA32CDE74239EBE51CD8A585B8349E3C93943F09997836A3835AEC57DAF7A828\
+D9B797F9D293CDD5357FD65F54C4FC525E442BF85319BD682308C7D72328E7EEB36CB926640EEA\
+F116EDC014A6933BE5ADCA3733F13CE240C41F50601930E14B3A26ACAAFA25F1B4D0971993D533\
+FC9698DC97F1A932A0A543596296AAA1E09C33B15086E5EBAC4733C3679AD7FECBAF9F056E82B4\
+A854A71AFD5C6BC51A938752346DEB2E06C54F11AE829B99880B8859C4779C33239B8B526E0E61\
+B75033A9C09DFC533D906C5AB6F617B46F199B42964E92D6FFCB31033930F1CAA74A74F41E64C0\
+03232C6D6D75E7209FF538DAFED90899BB6425E2FB77178CFF14863025D3503954B5FAFC7E4C02\
+FA8110B131E79BD7B120C8757E1BB9BB72856896CBDA5642F2624BE64404201515C493CC1A5906\
+CC6BF4370A5A60BE18F398C570B901CE0945C84AB2AC55627AAD6540BA461BE9848FD96F8B53EC\
+9DF4970C8831D2ABF0E92357437416AABA2FAC81470358B3C42389D6317ECF65F41B5EA676E06A\
+1BEC4C83CAE628349956608603AF32C4B292A05F518C6B5127F216245D80DF929BFD28C89DDD64\
+D9AB0A9ED24FBC60A75FFFAF8118160F75B64D7D5A3968D1200D484CB67ECE27FD2EC4299A2E3C\
+A58066570BF3B2F214A131377515FF589B1EAE4D78BCC68DEB1004244AB811252AF791E61E5589\
+CA07091F5F9117535592B3991A9BD27AD791732C777A15DFBE309286CC77CE61A2711DE5EA58CE\
+5EA5A60BE2BFB41C1EC7ABCA0D7C51E7045A0C01F07419E277BCBF7EB0EEC20D9D06156BCDC377\
+7BD3A56A1B58028E7CA20E1FD51F41C8DBBE7A9FDE46EB5DB3580DAB00B9637DF4E3BAD671564B\
+E93E73CAAC580A21566E9C7248F2A313B094BF03D904FCB1D04E64801A6A22A703DEF08DC0B540\
+20C31C0137C77A4CE189933C451216DF38569303FE75CC80DDACD26BF2E09A3D43683E7CB0AA52\
+6EDD2F88FD1D6EC54EADEB0734103D24BC58A158ED23B7CD05CF59F4427FC1AC26F2C4710389A4\
+E4F1818B25F19C59A742C6233D92B34F4490A5ED52A4151269CB7006F70A787CEA40C044088554\
+97BF0C3F8C24A19E8AEACA1367A8C37BD4AFBE2FF2A4BCDDE413616C245E2D50AABE967ACA4E0E\
+C6D5747265A38298BAB9B920F4DEE454377CD899A82536ECA7B3A021FF1E05648B6257D270F1CC\
+01A9CA609602D9284CDB17C65445D623108A9D5EF86EDFC2C85F2A27B005B85109E01A1E716B30\
+51B801484A1C1F7CCC30931F99F7FD41ACADD68BFD0F89487172A7971626DFF0A877974892DA86\
+F9A616DAF67F73DE452C6A984F9C82DA61FC023A60F43373AF900EEAE581AF403F55AB1A3CC12E\
+39E35A7785405E8DE5BCBDA2E7E734:\
+40F535BD7C0542A3ED6E30440504B78770B48D31F05A6AEF8747F4D280E47B82
+
+ED5F341CF8E2D40A804DAC57107019902C7598CD296923718AC8BFAA3952F9FFBBB3A47C460FB4\
+EE29C847B4E1CC22C4693C5C6903AF633FD73BA16A1D9F42EF3B4B5B16B7CD45AA5E83C4335AFE\
+14DAA263B267D7B01653335A99E69EEEEDBC93CFE453856850775A7A17CC27A2ACF82614BC4BFB\
+5118C937A52DE8FE4FCC7B0F8249B80620A17AAA8C103BB0A026F668BAB5A18F1AED0798CDC2F1\
+A77EBC8EB772046FF2327F4DF04DA3BC16B132AC76BF2E20723DADA7C4997702FA06AB191FC0EE\
+0B50EB2F9374B08F8CC4E06F6F57502AC3A55EDE1AE5D9FC28D95A1BBEC77503E443627458EEE2\
+18E87A3AD66E8D169D1F2544B8F4C6F4FC43B1A5795CF1E5D300B6038768303C8E6A3E983A9448\
+A5FC45C39B43E715FD87C63E4F593A420471E771083D0543FA834B6332372D7CC90AEBE96960F7\
+078D95A3F2785A918DCC9801269B7BB967C7FA40805FC91B83526E3B477C7F48D7535EB34193C7\
+2B14EB6A7E7933323AB52BA887BC91C497EA2AE61B824F9C17BCABDA07E35F9616BD75C89399FD\
+8A968EAD40B15B20A1B80334246EFDF3D651B5381988C1685CA229A01869CAAC03D41D2C7C2FF8\
+CC5628C66A749FC7EB69D8D462BFE87E2DD5D7C399377A8E5F5C06D6264D228389266F2EB78292\
+C429D7DB5667EDD578E4A87819069D912A3E2DBCE9D6ACA568A84F331B649F4D16596CA6500C79\
+3AD9FA82D8916A2077ECBB22ABBF5EA5C2B7CAB4C8BA0E360F3F4562C009DA71E23174A45A0457\
+A30A4B2A0B46DF213A64ACF038B1A882FD7E349DE10FF0F7D3579A75E15831AE597C2CB1C64834\
+9C4F5E340063B84361D94C5C4243D4C2A5818EFD0F043F424798932FD1F2DD6E44442DD3894AF1\
+D77549B146D43847293DE9BE5CC0069F341302409B33B0724C6D95A5566C267EBE623781595D72\
+A461FF8CBAA40B3C4259766D7F4F61ED404B2D8C651F6A38F6F757E219864500EEFB9DB9E9F1AF\
+0D5197A1A2D615A64C03DF7D7E15AD48CF22E75D1DEE51A44CA15025F4A9849C8D0126CD4B74FB\
+E444A0DEAEAAB2D11229DF6982F5F0AF95D672D0C84BB005D9FF5846E7C8703E439CA9941AE7E7\
+0E076E907BCBDC209C9284FBD6A1CF8549C90DDCA992E60FD29E876C30E6500EE8ED31FC752385\
+6F84C22A2553542F2494038953633ACB8FBE11B87646D81D366DE4657A85BAE1DD7EB820676928\
+227518C719A310C9AA97E5FB39FB4EF03631BF0D2F51C82565841B3E39C5E7D0CAF07D9BD49CE2\
+AAE1EFDAA9E8D9C6572B0155BD9C6474EE97B9FF7FA167A06DB2D3CF5C2FA0DC8CD780CB0E1F04\
+539E24D1559F0295DE3802DFAD3DCADA8274980C6620B39147B5BA75C7C1D65684573FA1FCF26C\
+4310D24ADBCD39FF34EB2D616A7FD997FCAF4BBAFF356978D675767E2CBCBCF772B55A71D94EC7\
+D50166EC608FC171BFD96DCE340D1446:\
+6D71EC68FF4949433604E7699092096B38169E18AC91CA5B24A2BD63011C031E
+
+C126AEAED489F433D325FA396A69920B4940CE3D8993369F8B776126CF31D9CDEAB316C3028342\
+8BFAD19CEFFE9AB9F9FC589FB7C0658C5FB58BD127F9A90C4C60311D4AC435AE0FEDD241A31091\
+C55B8ACFA4D89DD0053C43085E395C85935327040D950779B3D6E58BA668EBB191149331BA68CE\
+7AF35EA27CB68AECF9D6EFE29BC2072FB47E54DAD157DD17BBE7F09748AD257DF67B1A6553A366\
+E31BBBEB5D969D4B7CD348D1968D84813FB5E1981E873ACB17348D4B31C56690101AC361E5AD2C\
+4BEE75B3DD1AFB68512D30A226F514D38CE51A2047E53D3CA91A4794368F6FEC1C191E2C205915\
+E1B8056547C667AB77223BC7A22464FAE4F1F5058F5AEABA1461F4B4E97861DF37535CD487AA5B\
+9845DE89AF6DF844AB86BB5893D03ECAE0DBBF1ECCD04F8CC286C40A732E4C9373BEBB969609E2\
+3A236C3B74129B893DA55C114432032DD32DE7304FDDCEDDA0C6217C11EC9347D7423F7DB1B94A\
+1B8686EC6B626CC22198C1DA6FF01E7BF447F3AF32E55AF453CB500EF9EEA4C866CAEF142091C7\
+F11034C1A755E01A35D5C9C57770238239B7A0402FD8F0589B0596E019F8472A5173E86DFF657C\
+0A8B5A65F85DB43AEC400C9A0F7C26A489026CF8D59E7FA867EB5B3B89F01B77C371C96E65B52E\
+2F8F6C362C766C83582D51CF89040ADDABE70396E81569897BD21C5F6B50B95E62A6D10761A957\
+F172EBB30E28D192AB19AECF1FB8041B5C95B07FEE75AEABAF4668018A157F8C8246D886E30C29\
+4466209CA296AA79F01D99CA518196DC107CC73B4F1134BDAE068159C9D5D68BDCA71B2143E096\
+96209A597752DD880572082409D198A9DDB8257FAD0A47CDEDF80584FC5487BA94CE02271B21A7\
+8B371A2B8C9B6FF0EBBAFD608EB593255ADE224E213114F94BFDC985019D413065762A1D8738CD\
+EB84D5E24C6CDBB68F2C9BBB16C9ECBE2B796A51FE23BF5C945EE3519F50BE6438F83012492290\
+093E18D6BD69C677AE9A66EB25FA8FA22D080AD89B3BE356A0A9FAEFF764234128B11FD07F3CC2\
+E4D3921D0D04ED4BB1206EB63B7C17F173FCC2F88F47297BB33B7AB3D0DDBCDD1934988B87E089\
+B090EC6381CBE7EB07AFD0406FB11610305400B3C2659905542D98D697BDD7652BA039F9D8F8B6\
+22A41490A7CBD7E8EA4DB50E8225094ED8052165F3DB97366CAA3A97C3CED84F0DFE18FCE254AB\
+A0C8D12EB46E7713D62D404D67F9178FD13DAC633C7092A0E27B148BD972B0BAC0D7C8E61A56F2\
+C27E6E4A29B48029224A62F617A97B265F6AFA8DA77A7C0EF080BAD36F8124C787C3D2C318C7AF\
+B9974F596E38C9765DE921728A3C495D13FEF0D99CE269979AD075703F1C784BAA6FF6105337A2\
+70DF2244AD2F19EB243E3B623382260607546ECEF1CCF3C5B6A5425EE9D565CA8AA70A5E1AAF56\
+F3B93E5D7F8E763D4BC2EBD2C25997BF11:\
+84CE84165BBB95175543526DEA5F0C97A4308D2776108D22ABF842ABD1AE968D
+
+9F46C2E21D2366A40CAF149524BB4CC51DD7E8D221F86E68090EB9B72BCADF0DBD1E00C8167149\
+86EEC2CD8B9A38D8061746BEAAB4F81141CC57FBDB4DEFF3FF67439F451ACB4655A7A1665894F7\
+B01450E8CF23FD443B107B4CB83C62A0E4369584B59AA57A4AA758EF200D0B48E50D926A185C0C\
+691EAA2A5B30B1656469798120981393A2DE461BCFF6E78656C22E5BB599BF92D16AE1788D0DEB\
+2891083FE095D7B3A6C8257A07EBB59EB517E0090C372BCC0ED25DDE88803F35FDAF12C657717B\
+10C1C1B647EAF9787237B445B4BEA460F1541B44B2E288591CC75FBA04222946C2DBD9BDC674BF\
+5C8D4BFFAD17248881460C7A95EEDA2548902069A81A48C84D6366FA248F4751871EFB8F238B31\
+0965EEF21C1D0D0ACD5D50D059B6B66CAB482585125E46D5B637D937649D795911EB1DBC4C27A6\
+988AFAAAA23D79FFD1251F5B46BCDE7A0A19DD2F2597FE3BACDA148BC6244938846D9EA16455E2\
+6E1590B6B428025B8114AA60936C7BC904B47689A4F4451F0BB3210EC7BC65CEDB6621BC10D937\
+94DD969F5CAD5236A1F0E4ED224C6DA106EF63C175881F7EF4AA96B9D61666D30F643E53C9E3EB\
+701847C0A62263EEA4094338D8DF317FBD5C8D6339816D8F2BBBCAB7E8E877810FE89B6FBEC7C6\
+1A3F0BE7488096FBF807615CA8AF1057FFD467AB836956A1FCF4DE073FA1B8E2C55E75873AF1C3\
+4251CC288BF669F75157D2D0A79885FEB46791AD61E7459B3D532E88E04B564ED4FA72860A74CD\
+4342FC2E35190B1C588B997ED11148726D4B943A123F34B7C6248836D54EDFB9416F84106E4305\
+6CEB62618BDE8DE862D6F972069F7AA8B11D5380A13451B4E8AD998ACAE76E809465AA2BBD56E4\
+8F4EEBEC27BEC0CAF07CF00F9FB2CADD2E8E3E15B851F49B262277033C4F1EE0989D928EB93D94\
+654E389ACB8213A2FE8786D9C783E09EC9693E5916A1D5BEEBCEC342756971A8DC573960CD9A2E\
+50EE53BEC7EBB9B1C3789DB2290930771DE7149C13E192B9CAE5C81CF8D7551CDC7650243E3058\
+E4C3F9422C5E46764F10EE19B7346078F0CF3E4D65BBFAAFDEDBC55B91E9F071FF8E143F98B60D\
+669D8A80A9902080AA05657892BFBA92DED6852DFCC3805850E2D952C9E77ECDB2696F44E722D1\
+BFF3049E7F9F55491AF44FCA64F17CA6DC1C1A980371E9F43E4DA07B7D8C28E4C0A77FED054EDD\
+4C88C7635CD63539926C961C1182A243F680898E34BE3EAACC8DB4545BA623DB0F2DBA2C747541\
+01A952A8BE54C5F2985F088C98CB00527BB42984E8C609A73C5ACA0B575A2B4A914EA6B782B14F\
+CF858E1B3172624BA4CE0943DC70AF09029A755E8A613C66C5B29270494E1960080A0FFE8697BD\
+56019E4F1F42F99A83C23CB53DEEF877955A653E2621CD267C4705935569BFCDC2B87AA191E5AC\
+5588F0961E39E9B668825BE62DA329D6EC44:\
+0FBF1D93D23BF1474C044E9BD979EC7120F98604EE006EFFD8C33C0FC59C649C
+
+0F8D71AEFB9E58C7D41B456852145204B4F3D998EE65A47161815478CB2E88E94350135C331126\
+78D40A7585E9C519C25ABFF0F1927717DC9BF411E8D12ABA65F34B9927A652EDB8F129DACF3C74\
+4FFCDBCEC171E862164B241D63090DDAFADF41910C3A61EDE7CE62427950EE15A3368192038395\
+A98BCBC6FEC064241F165B645CE9B2974D854DFD1D8C3BA6B294B8AA91A049A7FBE85ACA6F224C\
+AE72DD42CCEDCF76159569DF29CA02F4DF914B875E87895FDF2740DAD1671E6866F9DD7CF173DD\
+FC88890B0235FA483873685DBAD323945CBD2448803D54AC79C16AA90D26DC70A84308AC019A93\
+93D78A09503F62B7819860C3397211E56C615621950361DB16D22BC8F9F316D12FB4D492AE142B\
+42DCE04958F6840D2A48F055A2F68C32F786597FEB04D1E1261DE7CBCA5D34A085025B66A7D78A\
+34F0DE8619A136C71ED86730834E88E9D2826CA87B016ADA70A9F06844D62D44A86D1EA8E872C4\
+06F4542CDE275D0CC9E6F8A4F05CD3814D8A50DBB8117C0E731E9A80AF34B6B3435000DBBE81B7\
+1E715962073057B2011637EAFC6B45C71CE5EE97558EBF171CC4AF74BF1D2747CE5DE49557F686\
+740BF993E3E208AF7C033C23FB2616047935E8AB73563FF47C7A1DF274CACC96EC77F5186E3E42\
+3625C817831B2F0BFAD273AE893E59CA08F8B9031238817781B52243CD6A382197C71140BF5A21\
+A3E2B3E8B6779AFF965ABE7EB135C87EE974D7D8AD3902FD65F55E01D8D9878F24F6BA4C1DE634\
+98ED65A2ACD9C29194F30B41FC5B2C0EA0C86758970EBA68AF455B358DFA3E9FFBEDE4ADFF9FCF\
+B184E99A70DE24D65B0019E98F9F00B0001E64BDD39B3D0866F6F1DFCE5A8160DC3520C940262C\
+24B2D06A461B48D1311FD2BD83FE229ED9617EA6B7C880D7852DB2B74966EF951D0B46F02D8F4B\
+E1603681B4ECCF17CB4F7BD3552BFD2EAD2C41001A52883707C2C4382576EECF0406FE84993888\
+9688061DA54EF59808CD947125D29C27DCA01A67B0C9DA4211EACF9EFE1B274BA4250AECD07C2B\
+5994E0997367818C2750447EA3E671911622B2FDC0C84CF11A1345420C2D2B9D1161E0760BF666\
+9A36D6F5A571B11B68C98E485CF2256A8DCB50CAA2FE74CF99530A1B51265D3EACAB5FDD27793E\
+18479B4EA782FA24901A80B6434108DD1DE0F1B4C80C665EF6B52B8403DBB3A553D550D43DF311\
+8BB7862D4AD002E87FADA601728DFA97ACA4A15590265D825BBBECA73ED15A4E62A3AB7DBCFA74\
+56CE2D1F3B1B6E8756E33F6DA52EF56C35BA574E6D250900841EC42C6596B8F135C3D61AD98C54\
+8E6448975FD5EB5C9E69BC7B6B646FAE0DE1AA96AEB2058491123B17BCFEF67DA21BD13027FF9D\
+1F36B2C91DB41BF756442C3B72326C6A02EE087A75A73552CBE231C06B5B0C7D3E9180F9445542\
+8FF8AE90B08F61E929BE4ABFA35D7CA39E8D74:\
+CB0A81684E5369ED90D222E5CE73E899DCE5CC763A044D908D99B9F754D915EA
+
+3B81E34BFDF7EB8F91A1BF748053E95D304B4857A563C8FABC509DB7C40F2D0C44F98FDCBD1711\
+164E186F885C720AE6FE4CFCB4DF85E4BBE30540FB472338CFF09DD725B88F4EAD30640A48C0CC\
+8F948CE70649946E6AECF38BD4228CBFA874E6D652B9728DF1FA08FC0E80BADEDCC74042A6ED13\
+D2A64E5E595946920CB7EFFA2960A2EEFE20871D215970233E1EEC8F2F3F1D7A32D5500414A2F9\
+D161EDB8CD2D48966532D4E091F704A440C3C35697D6C3199AEB839DBADCDBDDA8E08EBD440339\
+D1CBFCCAFBEA6C1EDFC9443BCBF692EE4052DCC014A1DD529FC86A4FA35D72E63A5A45783B3030\
+6F7609402DFC77787C360E400C0BDA451562CE098EA9F671C637BED7E254DB2E75C0E1D2C3A285\
+03007069F5F54EF776185F50A034D4A2AFD919EDD984139A9ED070DA9259C5C1A091334361C35B\
+5183EDCC7B312420993D2C7592A693491B6C0834EC293028112DFF0A5B8ACCFB197E996E97D594\
+DBD63DBFAAC2EBECD96F73EE3CED050282AB9053EC9B3463DDA1C5EC7C8936BAC9742E9DDA82D6\
+6D544CBA9B4F80CE8DC32C80AA430C00DCEF65EB9720ADA8B1B762E502C3C1F923F2679CCC74FA\
+430907ED37CE17B89ED75DA0A7B32A376D4345E7FE3587B43AD23FB380067C9AE736C65656610F\
+02F58D1F78D84C8EF058E6A7312932AF4A48E0E0BDAAA9C37F41E82276C3E2AC47F774F1422B2C\
+031BD6BC630168524604C5D65D00656F863B997C8FD9E8EC99B16016528C229EE81D0E20F01BB1\
+C5CD512A105BFAE82FDA1715F6DAF6F6E044184A09AFE96DBDD7D2EB7729D56440656989E0D4E4\
+21D951A5F68EB5B4E3FD4E5F1953A4ED29FE5E265F2D7BF56C3FDE493AECC8169AD265A38EEC98\
+6DF7934389040F52877221C34A846668F33EDD663E4B6D08ABDF66925EDD743DA3BCCCBBB98997\
+4201FFD633ED693131762B6D2790DC65AA050532E692CD7DD2E0FA793B5E4020C802717932D3C9\
+4163DCD84E1D93F3562D240E3FD74C28B014192F1520F5EB69ECB33D2904A76EB95947A7D74654\
+3A0E09E1362239838871FB117F4B1ED20E6CCF30524B3DAF592E3BD8F15002E0A10557C12DF27A\
+55374781AAB0B2A20A980BFBB72589333A3C16C3DDE19F727B324F3DED460062EB78402E303FB1\
+846ED84E6AA01CEFAF2C07569AC04CAC024F50B511AFF91D22391AA81E7C521DFFE12812BB34CC\
+6D0CE560820BB219D2063826614A9AE8557F34DD5C8E0DFC46AB1C321D3B3A4A7CDAC40BD1D728\
+0F2469FDCB6CBA607816D668057CEA4CA64F881CC31F9308A1FC84606C1C28E3E0BD7DBF45E430\
+81C04B07804F5E0F91B1EE298AA6B9DED88B1FD920D6804FAA8D6D0840A4476894ADBCA71B66C8\
+AB46DA39D0849FE4F1134220B4315A1C7BB622D95B6838D0561D65219D902989472ECDD0F9B31E\
+273C95B96BE1AE42089639F72915829E629A2E15:\
+F978717338E5BB3F578BBD8C4587CB0BF84D9A55A129485250D257338E1D5A5C
+
+88DA2C023A73898CC6EC26A0901F71C388B18D213699D1247A23C00704880C6B0CF835CF5C5CDD\
+6644D9FA95369B4A1E673162FE84065929B79E7718F53C7556B1A3A7BEDD95B68B57C5024070D3\
+0E73B48AB44D98A172DE22AC1CC28F0A64CD6ACF5A5CD6E1A7B42AEBD69D61209C32F942EEA253\
+0224ACF0A7BAED6CFD1CBCF074506D5AA20E1D8A8AF192C319F519753267599AD8C6E8BC1432C0\
+ED9302B3A72A77CB4109C2E312A3E2017CAD78425AC2DBF4E4286AA9411A98FE769E988FD60025\
+08B193D605499E120CDE012DBCDE8DCADE91A7978F7BB6E5071257189291951E6D2AF09EE0B435\
+B944AB4E2D9BB342EF570966448214389D1978B0AF8B9729E6200C583FF1926D998906628ABA8A\
+1AE58CA5BE7CEC73593B2E7CCD8E33C4803AE3FA07374F1DD5AD0D883A84C76E54A6C733BF9205\
+A9B6446E2F5015ACDDF52D7239C4DF8AE11F2BB02C09A87F88CB56CF63D5AB8451961C06B8361C\
+148785F6D7F2BA78E27B33785BE64C403A4C9DA51948573405EAB99C0778F3B1AC5B877B2CBB79\
+38833FC4DAC613D40352FE2428FCC6D3152F46F99E206FDD7618A3025112E6A4A1982CEC8315FC\
+59759EDC3C7D8BDB211A6BB5088CBF65F2A54D6E3B54D75DE5561041E2317EAE392E18847316B4\
+184A80D31C97109322095728728AB923210DA7734469E9B8E762EC28A2783A504EF57C84C1DAA9\
+F873AA7C968CA27D78DEE8CCF4BAAF24685803CF748456702899F3181A199C95E5878ADAF0AB52\
+37CE8D9BB3962B3BCF511826F20AF064A5B50420AC32C81937FE6A318009C4F92CE35FF501887E\
+0F902FD8D9B5BF7E0D30B40619D2E9832C6BA02A2872E57BA4B5A533659CCF034D8E72C9E23EBB\
+3778A0A7F102361C79F25273EDC27B7D63155C0A70644A0EBEC634954C7BECE6CE027A8A74E72A\
+BD1B7311D033DBA9F22B798518822A7383DCA72ED70D00700E9BEB677C5F0D5D3D110D179F407C\
+C1F00D06E67063DFCEA0E113C1D7F5822CB81CB9D89FC53B8A679FCD83A1774BBF2B76792819DE\
+03909AB7F38FE447600B453AF0E261EA5496F91E00BC594C9CD37ACA8F8D784D44766E58D9C36A\
+0C73EFF2C2D67014E6F80D3B55D77B8B97BA2C30DE7D3C4C0386771FB6AF3B21F433F102016409\
+BE94638452A9B2AA79B52F8A6D2439DB7C71F57E2AA1A6915EA0993E5D203BF85EF5E914A21C5F\
+8ED05B290DF3BE28A5861398402C4114DBCA88A17FA0ADEBCC223A86F35B989DD046E31F130282\
+D2FBA623636173B71AC85D45FCBCC39E4D71D817038BB50BE88E91717311E35AFE5C58B57392F3\
+D1443AD25483003F02573653878B0D3271931704EC0AC5E47ABBA1B57DE9BBD0611708E6A7B2E1\
+FB8A468814541357381A5D24BF1042AC9BF0CE48A674DF9CE54D5A0F107B7DE23E28D3F6B87E93\
+87CCEDA9C2402041E8C5454DDFF083F99A83045FBC:\
+503186570B08E394FF436ECE9E353A899D32506689AFD3343F0EA72AD6446D0D
+
+58755EEF96A6E5CB9904BBB82508C0D67040B90C60DDD27EF96586175B6F23E60D5B186CA6C2C4\
+EF08752D5D5F4A4FD8D62D5D108A2BA0471FC2E6DCA7C9E4C95812E50073EBC8A6D0E3F5D01E99\
+427428A0965E97FB5442F13755E19B575780D380A362D9EB6713550756AC9B2C2895614C865810\
+6E99A222ED710A0272B23C5AFE1EB3022B258D18CE4DCE181FEB79261497EE61A89178D332431E\
+C02065FFAC5FD76EC059D8A3C2BAA5E739D0EC020E4E0685047EAC4B53C54CFCF799753FF61552\
+DC1363C06DBF48F3598BD1E5ACFCB0E13F102614F6F4DBF2CFA197209ECEEA428F44FC74B83EE9\
+58BED64107E8FB6C18A5EDCC3F4888D5A872751A71B07591BE273788A656C4AE162E5A7B0EB43A\
+30295B61A8100B337D8483B62DB2414EA534A4E4C0F1D7FB13F25C0068E104B4A92E88F579B6BC\
+A424DA036227B5FFCF75D4BCCDC91A97D32ED8F781BDC33D0F572744DC1D1A2F356CC2ED23AE2C\
+B22B149D885461B61650E4BEBD3153A15B5064B3CB1863903D795A1986B6F13ACCE1B2026D431A\
+0F60306D35933C067C25B93C465D76CA117234057298840163E93C4BE77EEE2EEA24E398FF50AF\
+7702263FF34E88BEC7292973130DD3150C3BAAC695681B0D2C6804B40D80CDDA9C00C12B7D811A\
+7969888CE29FD20F897196471050DFA9985156F6732F66F3F4F128A84FCAA3A4C92E20543C4EAC\
+58AAF14FD6EF769306AD5C490C14AF969686FAC100CFC49570684423648F74F5D69F7917052465\
+B92453F934E911838BCA1021C71FD1390C2613127F93B31CC80B7DD2CD8EF58E341740F5467B35\
+19D01E2827FC0A65BF902FCBD94CE8B09BB78ABCAF6E7EB7E693994535D15E8CCFBC3D21AB82DE\
+DC3AC3081DA7D84BE13C8B0E99181E63E9E9FB1765DF1116FCBC2BF3B67C8749812ECEA1AA4964\
+29AAA8519F61DEBD2E6050ED9BDFFDBF2CF800321B5FBE37930873BFE189148F70D0A1ADA523CD\
+E42A1401D7E439D5324B045675466C3E8EC22845D19D368F0FCEAAC3FA7F3D5355BCF7ED8FC233\
+2A87A413744A010283EEA276D02C7CC6D6A50FBD8B66A8FAE9C67381C0CDDB56FA456F6DB4940D\
+28C76898DE93150073C348F450C497F259EEF6CE4D9B36DC8DFA4096CDE7AB1DC3E0B6282DFB42\
+ED2B85041FD7DB2AB1BE12F63EA15053BF6C665BE0E58D9B2D936C9070064CDAF4CD0709249D42\
+6060BCA9EBF9426CA3FC1DD5B68B8B9A37BBEFF5297717AE668A9E8E861532972DB6047442945B\
+84C639366863871129CBA3E20652D6D89899D2E8B7548F989C7BE81F4355E5619AEB4206A0E04B\
+D1227DDA12ACE2FED4168DF9DD025219F436CFF47D977BEAFFE1E3B7157D7AB7ACF8DB2152F8E3\
+10F5AAE7CECA51E70D402D4757D9349223619C345B83F2C74EE497B957362FEE549E991B84162B\
+8E232EAA6514E726226297C103D2638F2A1DC951B4C6:\
+CAA390A8A09EE7B7D32346D3644E95BBF77EDF017775B8AD47F58722C2BAAE48
+
+0ECFB8586C18DE7B9BB2E223D93ED47EE12964582480F8703D10F603BA655DD0DD21A9E2864972\
+FFF914E921857C6962717AC82518581241F1EE13FF515D0B73F6A13AAF4F69064E061112EB4CC5\
+DD30EE53438EB8E4A5A2E56DA0049A750341D23D660B69F43A976267C53781A47501173697213E\
+BF3AD79C394353E40B074B3F0D9B01E3E64234B81DDBB9442857AC36F8107283F53DC6EE173990\
+479EF5DD913A46F6CCBC3D8FCB0150FAA1C155020829A46CE3B24B4D91DF564058399EFA183D8B\
+0D9FC82B9BD1AD3A2BFDCACE47011E8B0B2C078CAF0BD1F58FBDFF27E6734BFB5ACB3E51A233D4\
+135BDEE26DC929B77F4A3CE2B62E6E95ABDC5D24EC56EA3E4524ED2B79AE43BCD61B7A0ED5DBB2\
+BE870F55D49276AB9B6868F28FE7A5127402DA1A153D69D9693AC5FA3894D8830D74E702FF0E52\
+4BDE87FEDFAD40D14995A7A94C881231B08C39E3BE535258C823A4F12B7F56797891458891B82B\
+6A8BB28932B942367FDAC0ACEED6854680CAB35EA9D0F9CC7143400BF1BDB654B84A9552925D99\
+623B5120F7A9A82E83D1A0668A5D1DD8D68F4B5DE34D4BBD34D4C0A84AEE897EE103CA6EE88356\
+5CBD2B0415CC668FCEF49DEA550EB569C31E4B565DD0E0AAC73E4C48460CFAA969F6D794828BC8\
+193AA0F30A08212FE5CBC05C89DFA5AC478A016921ECB0B963340276C2BF14A836C8CEC999AFC3\
+E0FC175867BF0BA0AA09617D5C38388B86E26611312368ABF78089A345B022E7E32B4E3156173D\
+10750D401B6C1D907CD127FC9734F64DABC1457C3AFFCF2F41D839AAF165D32BE40D8540C581FE\
+A39CF02779CFABF9C269B21A44F085AA077308D0BA7B398E727C1ED023F8F9B2571D0A0BAEF408\
+235F1FE5BD219F3B015AE66D3299BF1434012A60E004EEC076939D014DDAC568F374707F75538C\
+D717F232B9BF88112FE2DDF18CD0C25C0332E46426D4B5C119A805329BF1EAD2837B4984264060\
+4E4A11F21090007210B3DB6E40195ED9BD17D2B774AF08822CE3115E08FC5EE9A9CCDABA8DB673\
+ECAC0EB64CD155B6983FE4AC29C2C5EA52CAE6654FDF8FCA117B547865E13941C5672940FD26C7\
+2E44F5E84BF12D4774670FE3E7035F6D50E58FDB639B0783EBA8636B6398F3C7DBFD1DC70E793A\
+2E83C044F479C84A854CA26BB604064995A0DC9206D619D84F2EE6CF7B929FBB39B3C5AAD3E7C1\
+ED66EB66E93233A52D902FDFD603610B30F3C2E100DA258765CBEB21F698F9637E262D0142887C\
+E83227793AD5820C1B11F9D8D5C9A5E9AFFB91CEBF5E50223978D84AC944D3EB71F9F8F2BAEEFF\
+C8C1983C43998AAC89CC318BE364C3283632AC1A5E2712AD65B2E90E74570C93DA67B17A945C41\
+CC8829A11FF472471DEFD598A38A260EA7DD492A938C1E7457AC452AD7048A5731C89AC6444E9E\
+64DC461EE2138FFDB95E954BF30D2291161B68FB52FC1F:\
+61B399FB5C54FAD93B8082BA8F430F2183A77DFE3832947A0723E24751B51C75
+
+CC75458EDA82E7DA1DB1D8C48050DA95D2DDB8B775C56628D177CB6F28F5F871B0FDD75E39708B\
+774B9085151647FF25E1F0EAA4E2436693272EDAB0B2BAB5AD1B941D70969BE27AD7A11F5ECD79\
+535EEFFE45FD5E27D5558CA160336203A2D1313001BC8D964481258249FF971EF4F2175F19911F\
+4E68E20944C98C1DC5A68AA47DC67338FD3C8E706225BD68A51D7A424C844B38831D52D12C64BF\
+A254A7117DCA1D9A120B5A189E2B5575B2FE98D8066229DD4E2EF4177223993A789876DA71CF19\
+F083F07C9F0387F2F82FBE907030E7841AB2118EC834457F96DB059BD4CBB838AFA0E290406893\
+EF7AB07F94A5D741AD811B0CB67D4B51D360090F7A8AF937D29EDB1A7FD40C2DAEF57EC2CD4BBA\
+6AFF1E00B115BFB4D2F1DF4C70F6DF280415F1A0A90C63980AD1D9BED38C659D6FDE472D7A58C1\
+1F85F51DB3D63E278B33D1EE0C11275027B0C79434FFD766DB5AD2D622CFB40836A2BB5125C599\
+1FD19A9BF2B90538C79BB9800AD3D439135BEEC5C8444A9FBF4277D595C802490373BA05225093\
+1D3434C95B1FD268087621D4CA631700172101F1436E76BB8AD04A47EA6CB18C526352F1B4D9C3\
+E1B1C94D4C7C509532CAEC430BD31C12B7EB0BCDB1EB34C87F2D94873DAAF4BC88E6A9E76AF943\
+2A7D3CC1C823C3BE53B7673DB19E1258AC4615B50301B3D4D035DEDE43A87B7EDDB7633C52DA4F\
+E28B356A1494B139B440B8764A404F439CFDCB7D5C2FDD5EF4B997C65733C37AEB04B17305E8BB\
+66AD986036C067F53A3C518A92EEB7237F291FB3DB0F9AFF002225DF7D678124D43D2AF2657E6F\
+C9752D4FC23A2B570804E094A9126AA427D690AE6B5E2FCCE5553B70C6EDEAEADC230560DCC63D\
+E3AEB312922AFFC9AF8104A3475A19F7D11F52B4BCD0EDCDFFC7F1329836D859E23C8D8150EC77\
+F5995403B4E8049F39F6E755082140586C690B0DBB154B606E18B6CD57738C81C5855F06DE1896\
+031AD801D354F672803EBCCFF032EAC565743261433DB2226AC0E577B88A5C5DF0E6C618756409\
+FA394B4CDB92F0BCEF00DF610A649E3D5965E960B76DC2AC3350E05241DD98A6D3DA6485B133DE\
+91B0647C225EBDDBFD46CE214B2C16BC7F715B1387807EC2D9D589C7EA15208784E1D75F0B97D6\
+4AA6A32BF2BBC50977B10B3C06D9F1695DB9B424C9F9BC15B363BB5E1859E203ADDABEB9CB5375\
+3B1C546E5911ABBEB367AD4AE6846583A5D18AC6AEDD99987BBF7763278728447AAA34A1C01157\
+2DF0460CC1E95D184DBE871DD7EA76547BAAADCBCB0BBB9B548480895ECD2AB81BDCEC1B412B02\
+CC98F6501C5C68C509C26BF0FD8365AD8EEBF5C14BB36B4E8855CFEC2D324E27BD78A4EE9AAB20\
+088CA08BF8322C7F65E509744A729AA1ED5FE27E76E95C741FD3874C0AD86F647A90BB7E7A9885\
+784BE46D6C4B2294148024B853FFB33B313CC069D9258FFA:\
+1647976017C0CCEB3204A02B3578B65C2785CF95F141063637B3689135B01D71
+
+D2254E881D09E77C39BDD2BE668A83D6684172FC7F3A2E5602DF649F07756BC693BFD856F9D870\
+403954D3EDD0E48F8D071DF89FEC540A826AB52836CE9C39527452014BCDF128D53B590DA9B53F\
+39552AB49FF59EB60823ECA6BD51E0733CF0CDF4E9A0D4379000ACC56A27F0E0B9697590036776\
+0FCB86A88F86937AB2E04F2DE22B6A485776E548757C76BECF786C80C68A209F173AA1D5782AE5\
+F1DE25DD9DBC314A2DFF9A8CF318D41793A45AEE857ED30012407D8362FFEF338E04000E21546E\
+040BF8AE3643701B25B3A66A107B57B1529CCB3C88B8B781E68D578617F04261A1B467AE2D74D4\
+9A8A118F3E74826A5F2F3CE930EB3A96890CE4991FCD09CC331EDA16F60C8407EC5C9A91CD938F\
+55023445C113AF011516ACB603E93BD1C6B8977543C92C93811749978F977CEDA06A58B48F76F8\
+EE5FAEF76FA48F695A33725B45118E52106D581BA370D758B742861A87D86258623EAA359AF117\
+D028A923EFEA8194DF661409CFB75547590CEB3534A0FCED6E249792154727AB2024D3E9C7B379\
+97D811DB49761987C4E4B45C7B42DA3C1AE564D7A93ACA823ADD426374FDB3B5EFFFB5DACE925B\
+8908C7DBB125682B066C069C28CB8BCFC4888D78F9E3A001A00D8F83E1C65F596523905D142B86\
+9057301ECED09B0BDCF78FC734FD99A32D5605635806D4210637D21E617490D9FD43EECA5C0F1C\
+274A0B512490B42FE41113B4B24F8193D3DA1622F1A5D7CD43390367DFE2D80901FBBDE82CFCDE\
+4571B066D228A166FA8A873A5593E13942508EBBDE1624DC2D5E96A5B45853C54BC9D90D853D1C\
+2CE0D89C7B1F54B205712919F3053A8F8730F4D1D7749774607795DF5508D947521DB651D49700\
+A57EF2F1945AE6724AF0F81EE02F86D886702822DC4EFD421077F526803746E1782F680842BDCB\
+6F9C34D13C02AD04FC3E2C2510CA3955FD4202F40AC756EC07E6AC4EE19738BBDDB47EFD523B25\
+C1C524FFCF237800175DCAD9FBAD0141C7155BDAE41D756A4485B5BBCABC265EC4410EB8D12BC9\
+39EBE8E867843AE133D602760F7CD513AD11F94B9D85524C87135E6FCB9B402F31A32C202B8F61\
+6A4A8DB809881841C023A048A0336C58FF0176EE96B0BB64B148EB622D50CE34BCC89753AC1AA7\
+E9040FBDF789860C4C9D5AA74DB17B824CB7D13BDDBED24A6C80A118F05ED520A36CEFF13ADB15\
+5AEC3F97DA79B6C248C3375130ABE3A8FD0514F1D8624297898F3BF92B92EF363EDF7FF0D00E89\
+022EECE47A182BEB7915B98050CCE278EBEAAC31E4F721294D994FCA38A9401E8584EF5670CA70\
+6FB266F31034A36545C7C3586BDB47F9A2AEFAB724826432272F1F97B3B282E3F749089DF2E6D2\
+A6580B71BF5DF7A01F84396200B1764B09350220EF99B0BB244A044F486D2E8006F710AFCCE0AD\
+03F646C8B1A6711273D1D1A07D61D97A4A92AD6EADEC71BADE:\
+AB79BCD11952F3008FE2983D748A2C3E537BF3C7CD4F4378CB6FDCD3E607A848
+
+7EC32975F47F4F8DC2E7DC7A68F02771AAF5DF6A31AEB5E6E1EC58890C4AD5F8F19C4D2FEEA12E\
+169A73281A19F36A02EFFEC4BA14E9DDD877E7F911C0D3B77FC9FB24DD9919AB4B79DF64CACA98\
+DA52E91018F628399E1A2C043673D62F8D92758C4C903AC7DBAF65E8AF151ADDB6E796335F8A58\
+8AB7034ED3FD8AE9F034C3824B1310AAC10676F41017C04642582B1A9F7EAEC9DBAAEABAA6ABEB\
+B5E15EB8AB6C3AF58D848177DA5B512466839F196B894A1A7E7C62F8012D11A42EDCF544D3CAA5\
+8C251E0036EA602A4CEEB0EA33B6D8970668C75F4BFBA6835E6740D83A4A2D740E2841363ABF07\
+D7C74811E2D171DFDE54EFD7CE74E16AAED0144B08FBC244AAA7846637662FA298C153C99985F7\
+8964364619D7C4345B84CDE705F06061D2D63DE01C2D65713AA5FE447D4FF86F00AD983F6F9B7D\
+E54E6C770B9AA69685337E73BF6B4327C96F23B94930D7C75F8C242F64BA426F900DFFC8F8EF02\
+53690A4AFFC345C070D1B1046EF55F7804AE74C74696FED88046DC61B215B8079752E804445C29\
+D6D3A8EDCD7F2B506E9890355B38D3662098EEBCEEB0791F1D26D6BEAC8BD40EA3E318210405F0\
+0A6D3E17D7A501190B355588DCAC102C6C052EF33DC33BA9068B71A9B6A1BC289E3E108B1D023E\
+978E8BFF7BFE7F88D73E4DDF6D2C2A18FD027DA76782F1812F16BA73B3D534E5EDE512CDFA71ED\
+E2CAFAA11356C37D11BF4A066E825444D7EC7612B4240C21865AA29E19D02BE980CC85AA4ADE40\
+3B5C09ACD10701CD3AFC931B0473B351D27EADDC920791BC66A1203F666B3AE8FEB1565E69DE3E\
+547B9056DD8AFB6E2B88668A0C7E5593FA8D412007F8B3BF92C1C168D0254A5B6527ED2DACAC04\
+963D7CC93D6395346A5A3A04082BDAB11B4C0A0B72B1020CF0B048EB2BF9D8609DF27BF014E96E\
+CFE2488176FA3B93DD5068FDDBCBB9FC747B6B48DF5E989586C3D0A7E17E1B5F7EB695C0FC8D2E\
+09DF77F964F6FAFC6E5D090440AD393A2B8B5CB39CEE1196F08FCEC7BB7ECF5410FEC126311F1D\
+09DF4A9119C7B09115C57250FB78D718139CE8A8C37A91A17B4DFA87B614E318894E2F7598402A\
+FE826F6CB2BCCAB72A65565C64BBDDEEDF12337D7CDF0EEA143B40BF033C541672790EDD71DF21\
+FF50AF0729498390AA5923C6E1D295A3F8D41EDC60C81956800EAB6B115A9A99C30C17AC4CC800\
+64420101410E76DE2D74E7C5B3F3BC780BA34C4D289A23587624C6E31B3EFDF9C292F1F080E3B6\
+42C65AABA102FFC85BAE63CAA050F41EE17050D300BA5D0B952860EE5BD3ACF1163BDE54C6AFE3\
+D58772FBD2F3FDA85360F462071F2717CE2AECC75F311D2AC56264FD71014F20B49E2CBF17277E\
+E857FF6AC531C006F1A6DAA6C82A15B2140959328A1E9D2A40DD03A02B850069040902A9E2C3B7\
+A9C8B13845C8786137B9EBF3AB06D6130682780248F10BE7C280:\
+FFA92041D1819A20B97BE2ED14D6D9C95FF0A4CC4104CFEABD575058D8B7BA5E
+
+F2592D6041113B82E0391FF3D24189FDC98F210B8D9C9C348B45B9DBBA0C0369E6175CCA2C2C55\
+067299C1EC634478F3977A6039662F83D19E8DE9085D8E2B45F350C536CDFA12394D77026BD45C\
+41DCA426720C5BE90C85F012FCFD04F06A4365587732090E6F6C52CC141B8652E92139106993D4\
+5BA95DB0BE841AC7C5747BE9B2443E8C646A3F8902CB1785AB56D8D4AC65BFE839A8E7AE57F845\
+0ADA0C8610EB3651DCEAAA11C17EE362C727DF460E89087AAFFA9A3D100EED9CD76331DDD3DF73\
+CA89B98CC7A4108B51C465735D902F5FAFFA8A4AE6816CDD628E59DCE1FEA96DAF017816651390\
+6FF735948F234EED61BF8F462E8ACDAC526BE26FB27D8F2EADD5E7F3F5C526A90CF2ED04C3F192\
+C5B800DDE45F9B63B11B6E64D4CCF2894ABD6F3353B8651BC3687995F044323525303422918AD5\
+552E0DAA2B33CB0CFB57F5817F85E140C7AB1CC1FC8084A0E03FF8BA980FE0245F55354EFBD28E\
+7EF646600CEDD1788CBE5A80EB0106BA7C7FA86D5E6751D9143E23641937276654ED1DAFC014D7\
+D0CD7DC71EAE3310D6656C41B92A9F6668932631C66CF7B70A9FD8295E888FE1780305158319F7\
+B78635BB355A54A930BC15A0626F2F85817D442D105CEC47A721276B37E4B82C17AE043EE4E4BE\
+B40CF78B72CDBF10253CDD0350673C7B91AFEC2B4EA18EF4E5E2B5231E95242EBD724FC6E7CD34\
+C3866D8F0C90065B821FD324DC2A5AB68220C6E84A6A99B2804D2D34D69C69AB0B8E5387EA38D2\
+9790FB5BD56123EC22A554B4F1D5FD3BE0A94956C70E39896D0745AB0918CA91045C128087A8F5\
+DFA7CA84DF416F3616276BFAB9B8AE44C5CE25B9F85F160971189134327017F776BED33130D33F\
+FCE5622D8A6144EB4EF50011E895DF9F068716C810C27F94815421B8247802896106F647FFF5DE\
+7F64AE9E26411C76F7FE75ED8413E9DCC95E8804E93E9C388235610C41C7D627210FCD66E5306F\
+C11F9A9DFE688379AF64EE7AE958948A7DA7013B78AF8B01EEB4C2A6EB7EE8E6FFB178F5AF8A00\
+0E31B5ABF3E44BD7E45F5E218DF8FC14A19EDFD7E0DAFC455C7082F77D6176158704036A14061B\
+9A9D7D0647C7B16E20A8566A576025A7A7E9DA3182A9F6723CBE34E68388B7D56B7E902C584758\
+F5D07FFDB5619C82A035F269E16F255B746800D4B1A3B9FF83BEE4A59C74A69EDB9667F4EC272B\
+DEAA6BADF993402CF0D23B0D07216B9348110E680F92FF7230916D8357C7D79757BD337BF60925\
+CF8611D74FD3164E2648AF0CB2C002D18CAF2092C576CA4C95E62016C6119E7704F3A5B5B28B19\
+854C1B0A4BB7762496DC6220AE0A6F44C56CCF1B9C0E323BD233F31307642E206D0CD34D2DD8AA\
+980089034B81E0285910F141A3F29B40CB9F498A5646DF2258755B1654CBC8D6B80F3F0589EE4F\
+3330EA89CC0E6AD4A3D03162C82C5061404916E41C8C1EE316448B:\
+83E01C097F00DD5947FD07BE085E895903E7C71CFE764B6CEB89082B8D6E3374
+
+B1CDF8A2B282E91E1AE01820301C5F1DD5D0EBB570E138EB11FAA542A2B86DB01B4285F6BECA7A\
+85E2AD2D4B5753924B754E7EAB1DB2E0BEDA35E1B20377A54C8348C69AF9166646D0B1A2D8B1BE\
+0218A7259E920897260DFE80A53974A2E5D3B1CC45FCFC101A24F251868CC722FFA1B3283FB0DA\
+C1EBB74E6771A99B8CE08C86F28C745EAD0BB77A38BE99EED08354FF0B90D13779A43BF8499EC5\
+323F3ABECA3CFD7328D634F08E16D9FACCBCAAAF7F5A3ED47A4543983F3791CD0FC9562FC6516D\
+464C7936A7936A3BD8341C33332A724C1E89BC0A8CF968FCA37C70701675E6716AA77936E5B688\
+E09C7448F6CEBBA4E91792AB528BE434A90C3A984AB7AD43A82622EB7E7845251A9D93DB7E2779\
+73E8372EBF75AB4ADAD050C4CF43C57DBE7460D688D8205DA51B932DF163D800C0D687989990A9\
+946166B2C6A8F89FAC0D42FF69A0BAE0199189F2D8098D14334F4A99DCCACAF0182932FBF371ED\
+A4B197155AD1AC156370FB1B292949668A58AE03CD79215D8F1CCBB356ECC40D3669C5489F22C0\
+E9716BEC20DC83722BE2259DFB6640D6827756065E041ED0448C07E971F88BA783C41CDF68F4F9\
+5D7B5EE8630054BE9F1664D2E3A3EF027E59A0AC254E9E87A6DFC124C6A5E4798CD4504C496C19\
+C06B76B80AD8A2C66D96EEDD2104B83BB76904BDAE883F0EADE666C052D6AF802397579166ED76\
+2D6F4264747F655B9CDD88BA3595FA9580121B27E2AEACBDA2C95C6861181DBF457054381A30F6\
+FF7E8E62626B78F66B70BBDBA0F0B91892DFCCF1AB7813239A2B7EF6AF03407E0953D1116E1ED8\
+BAD1808BE008524A3C25244A5937528364DD85F055D0881B487C3CFE6272ABB894EEC92CE3FFE7\
+C34A60D6B1C23B2BF7AA3391B9090539D3EB5D7C51D85BD1A8E4F834F1C31B74BB45B6AAF31AA9\
+13DE1FBB5E65C2C7B731BDC491F270B884FBE9326CD3B6C0B1E2DDC4995E3ABA7447E457D724E8\
+999D54E881D4B79A992EA0BF6B8F60B53EA8ACD8DCDF9BB8238867A3A1BB90AC2B2D521591AB61\
+6E453D9E3CDBAC503AF94031D7CFD2858DE20E389B40EF0B677704BF95468ADA429E48984F7A49\
+74D534A3ADCE84EBFEE91263CC87317F9C465DA5E4EFCF0034A15278C6862168356B2BA5BC125E\
+4066154814295CD7957046E76FAACD30FABA296E1A78F7FF658669991C973FE25D4C51F8D1150C\
+8B3D5FE0B19C5C7A29C08445992B46ACF06008221B3FED8DABFA26B064D4DC92EBC1135E77905C\
+148FB5EEDE88A5A7D117ADC5406854774008ED44AE9CEB16EA398BDAE1E1BFFD6D7CD04CC2B3FB\
+AE1CCADEC9F6A58CE2FA4029434454A17081FCCF3323BBA91D26EC4C3C09DF34D6A02C6475B9B0\
+E9E31D7032441D89B2BD963A63CEE6068F965D94555B544648855BEFACE42CD49E302C1B6C43D2\
+20B1C8F677F8ACF89DABE4C265F55BC13BCF71F61CBCC2801259BF7E:\
+1331D84FDFB3161A753E6BE1C68BF78E2D8ECCB1281AEF8C1F12916352400452
+
+D0CC18AC8DEFDC7089C8F8DB0298A33BF79007BA72BB0E2C57E7FEC1CC27B8982BFC06DF3F7FD0\
+9F0D33F921FD4D7522173B56AB09C48D71F846BF4546B44E219CA1257633B17C50B23EE8D20C3D\
+02360D5C53F4A32AECBB40F821D06A18903DCFCE752CCB356228802EF85165C61C6A78B5A7C6FD\
+7FBB8A3B9B9B959B7CAEC308B027629F926EEB2970032CBC906F2EE71B0063D7CF184887138B8A\
+F53D8002D26A976837186CC35CD07A31F3121C5815FC18F5CA559E3A5B42D32D8889DD2BBCD931\
+790105EE9174D72CA975E310CC3C7EAD6EFBA9B6E59B45ED1AE587032721F126C0CA38A7DA0667\
+961AA98D1C161177B322A79E5C14DE1C74495357906A8D72C7D418956C83D09176143D797B446C\
+DBF864EEA1A1BB17322347E3326F8493DB05F57AE72A86129F019B44DA6854914FFF3533A58A4C\
+D359DA953CCE3E8A9EEE35FE94D7E0DD3F9CF24762B5893B648C9EC1E12FFF96CB76C91A20D01A\
+70A5CCB2903C444AE6C9E99521F0D2283CC458363F6A289FE7503ED53800E07545C04D27B6DA4A\
+7B400C6F3F0506C46CEBE5D0B2EA251A2B415FA70A6F57821D6948790B869DE010D533B6467270\
+E246FF80B75707D2E3710411ED327C35E8BF666EFCDDA33F4317C78AC8B09BF60C3FAB9408B097\
+356DC4383D2E2F1332764DA26E5256098372F2192689AE9CA20072DD1D04F84ACF52540EEAABC4\
+26E0477B78A1CFBB5B0254B9A9AD983F5AB84DCAAC930CB0A69006518927B90F19BE83780AAE58\
+4CAC65626B450775050C82F31E148BC94F8D6437F42333E73F83C7F48D4B6A7DB06202A754D636\
+7CD29C75C91ACAD7B0BEA07BA03B9F7AB7CF7B9D4C573125AE50D41C0F5A11E23DC1C09AD02A7D\
+7408EA411F43F1CBB7B147D1FDB761FE097887461A1AD241032B52E2A394268AA334C033DF5E27\
+23327EACAF1C01541746327212B8BCEB2790EA1B80DB34C3449B62043355F9E1FB82EBE9A6E3E8\
+819B3458941F9092F713619ACDC961F3D88BA4A28D63601612927AC1701210DB67736FB565F462\
+9B55F542DC1A124B2E57D89DDC4E1FFBB32BF9AE517C9655D57101689D925057BD83B66E03D116\
+1A3CCF6575909D94D6F8C1102067ECC4314B7C2D1B00A39A6DA544A15306F348BCAE7B7FAEFA53\
+E843305F73155C2F1C0BD3B84C935C2AF2F7463AA9EC10CFEF72669EA30AD2D8ABAEBFD8DF992B\
+0792C120E302F86E4C42629BE2F866382CB28E1C5F3E829D2562CFD1476FA8E4A38471BCD7C46D\
+DE3BB0DD0CB87B0A583E5F560374B7E85B5B6BA780EB872839B7BD84B4DB4979F5F579581DD6EE\
+126CD5D426C74E9AAC605B6D147EAE0DAFF0CD5F30C465D1801C2FD776655E0C7DEB8A8C39933D\
+7E441B90CE308CE40A6977F6F1DF6C7BE079F6641F3042C973197CD98E374021CC57245C25A34A\
+3004D7C26127118C035019C87A56BDA4FC3407005594976864D161B39B:\
+8874AAE5A4315343B396F469732C783B277FA0BE98C454056EF36E203DB18161
+
+7D3EFC597588B87152A6010670F36C8A900D6C217126F56D5903FD7ECFB23B5F06947272BBA7A2\
+E3C4084D2B49F82A2996F8AA26A1C8EC56DCC994101DEF03B15BD48B56DAB2A7DE37FA8FABC475\
+659B2E465FAAE217CFFB75513D40141DAF882B98AA009E1B98B360C74E3749535A553E829B595F\
+E14C0287B068C309DBD7D81F7C2A415E8107F3A9376EF901D3B8869D5FF5553567AA57992DEDB7\
+553E582E70BD2F62A22AC87A965D74FEDEF061A891A54D58D8E9046A4D6C7C6D4A0E78219C5E26\
+F93F9DA39E1F7F7619E931320C6AE0598FDEC957E8C2B055D428C822FDCA8C8EB6788BD957A2E9\
+87363C38DD83AB4E04B5EFCE9A69A09C14BDEBB72096EECF49E26DEA6CD0B3E8F8B347C1E217FE\
+9EBB2FD01C4345285A29DCEDCD0F5DC4C9DBC0CBC8A27AED672B20E085C3DCD5EE6BBF9E445A45\
+F9A1A247600AAE5B57BECF1539FE4C87D5929DBBFA1D6E5DEDF4FC358F49EE11D4ED73653042EE\
+D46B384B23307E01923F2E61D72A92B0BA66CEF763CD173C92730495359B3C939851884EFF82C8\
+1004217D3F27784C65C42A2040D72A8715E02FC3B33B596346DADAA94803244746079678A8B376\
+51FD1B39A1B677B69018CDBB656652249F91C139070C99BA849362B177054C28A55B385C4CF338\
+B13B232DB877930C22EB3F51CE070C4314CB679D4583E38931802E105FEA524BB2A2877ED178E0\
+4536C2F9679AE7C564A3E8A3EAC08E6F8B15EFCEA58942B5690DB34B507D7B111CEB47E8BA0875\
+2DE21A41F47147B7D507A3A1DF5E0F9B0DB36A7D05D84869745C4230680241E294D689653119A2\
+2F2FC5C0C9E98697A92E3513A6430908360FB0EE43A2F9718773DF7CBCBDD54E420A7193B95EB7\
+881C98CE177556BE37CEC861D56A11F77C656200EA7605AD5AF3FEB065EB8AB88E0A38034880F3\
+A2660784A701391E71A092B2DBDE145F6FAB54CFC39E3E79C3B9E54FB31EBD0AE42E0FBC9FB761\
+A3456557087C9BE253D179C6D08B90DF9F871BD29B125DD2D22F7FA4A104559699B1AB1A906C8D\
+56AE853A31607EA1EACB0B1D41F1D971C5ACFA4705F61D37CD1D808F8B0DECCCA66EF01AACE0B6\
+1974F49504A4FE7AF474CC338DB516302484B1CBEE0C8DF5143C42628AC09388C8E822775829B9\
+F5B3FB2F72448A5DE7265885A3B9DB6FCC0349B3863D01DD377BD60EFF49FAAF3C508576E34FC6\
+1A5E0F72494E45942A43FA424AF438F687DF4747632DCA34294813F6EA10009510005AA7A1FD60\
+12E94DB7CA439EC242F5C5FEEFE374EB967670D2D019589B3DCB4B41290AE70F339CDF7EEDCC71\
+927973AE9E25D8BDC0D74DC9C9E1AB8F2C648808A78FC88607C3D1BF59A5F1047F8F7419B18445\
+8742C16F7641DF79896B4BE4ECDF52BE5BB831530528D8FA0218ACC94357DF588DD027CF1C8E90\
+61DEB12D5FAF24CC59FCF6AC5A04D675AB809B88895C862BC3CBA615BC1C:\
+555F6602A47B634BEA410A9A92367748203B9FB16ECC130503F69616B66F011E
+
+42F3B684726E0A9E4FF5470A725DB94AB290A477DC9ADE1E3D42C4D68A3597D0E60875D1700269\
+1F5B62365CA19D4FAE96AB779E86D89AB13D46A3E90FF99DF8ADEE749BDC43EF6514241C57F32F\
+6FD153E5EC5A8854A18342639A8C0EDE6EDC6D4F50953440B939ACC3476120AFF3FDAF71663FB6\
+BE71563788668A87A106DC50ABE0158DFA0B173DDF032B44059B59E29BF438F3BCD47E4CAC0872\
+3B364BE9CDAA4AE88E54C6E2073C61F6397AFF910DF07DE05AACFEA0DC2A82C0F43D79EFC02355\
+735F3588FF13DB6D2FA5BB8D3E114B631212C560049ED9D31B890538E670B81C2E7E87D141539E\
+278A46A1E673DCB7410EB6F84CFD046665EE86FC8B256315B97262E5D90935F21E3DD17AF226A3\
+B3E2F035C64A1EEA1EE8A31E5930389A6057A1CEFB2E469C5692CAFBE39CEBF111C581A05A1AC9\
+30D3B9CFF0600FC1B96F98FD302CD691BDC5A2A24E003E67DC36D148F275E771CC2C3D9C2107A2\
+1095B4DB6AEDFF04D5AB06A2A4DEA65F4DBEC42A3843F67748DE61F00FCE264F38B28B9018FE80\
+C34788DC79674FAFB67CD49E7590159884967AC1917E6E3F27AB231BEDE67170EE458861F14843\
+6291FB892B3795F539FBBBF7115445CD8F08E2E383C85ACCD376B26507009F741D198AD4BC5CBF\
+CA3FF5D56E9202F5494B521B08799C890F3A6E6D6348817BDFD3BCCED8119D1A64EF2D02265A6F\
+C1B95BADCC295B8304804C30EBED369EF1CD253EC0025D15203F129D47394C1452DDF966408C73\
+88EB0AB7974A23D7291231F7D0C07CE2F8A66F51401EC8523F4F178B7C7473C50C67E7ABF06897\
+3D453A12C82210E922746CEFD08CA5664687D762774524B5725128CF8F29FE3C339793A1E1A0F7\
+B9BA698714AA282A4E298EC80E1550D6003B9309577940002A91AD200CE646A649784B17049758\
+473F48A9A5647CE099E65002B1B76EC05D3C81350088C7E4C043E542F2E883577AEAE24EA671F0\
+718C5A35758D07B71CAD44B7953E18A746ED7073AD9044F6AF4245424A792E09453B363ADD4226\
+F7FFD6E470D223AB12F65A9C917F3282E5D64A83DF20F22843BC9652C9C89EA22F74CC9BBB0097\
+61BBFC63FF7796C92E907537EEEB082711FAD82820FCFDCEB964B863259D049298B565112E4784\
+5595CA483E821F996512B3AB83A613A8E2F5296021302AA068CC59C8093BFAB264886C1060229F\
+E043B32E85EA44E15A81E6FC5DE4F05C91B714783D948F3E90D3B801F503F839319696FF956680\
+3FA407FB32FB6EABD2AEF94C76CA5D7D20FECE71E9E6AEDD6436FA194FC61B39495AB75EA40287\
+5686284F4D03C6DF78B95831D622859FA67B12EBC2DD1FFD5C40AE485AA971A87ADFED61D19AF2\
+F9671B8464E1F56733E3C1B98F4F70FC3CBB4E549B3437B1604163075B24D7208D4BFB11C66862\
+0CF8A291B9422AD7CE1551A65D82A2DCB00475552852D4D7C06831FD51B802:\
+D0D1561464EC8C59AE1313C89CAA89CDC2A7A0359C84B2516E873F5B19229C66
+
+780DEDF7FC6C135550F524F4D84B33B769F58E7FFECE6CB25F497A87D6E5FC912F4E8A60742920\
+8CCE5A4B6657AA2830DFC8C1E9492DE204B2ACB9B42DB884A6F194FFD517DCAA205647B27A0E2C\
+BCEFB357A55F3F0D35CDC83956CDA8A9D021D694FB178C44FBD9B4003D11BAE011FB4131635A27\
+FD26C75B0523EEE2ECE6D8AFB6C76280E0A3F2C1B0531539DC020698F7466F959D6CB6BD1B0F84\
+B17906120D40E6D8DB675873FCA7EDBC1409F0EB5A759767F9F5CC01FE006586EAC27A4D4115E2\
+FF92587DE3F2F6C09222738DD99945348B8B9F6427848DF4D31EAE22FFC4BBE21ACC896CD903C3\
+CC0DF9A49B9576465AA0D8FC4F40468B41481A5AB0FA47CE1E85BF7F9B418E90DABCE9B655D183\
+B06044C92CB050EA223D2F73778BBC1B90945EEBBBB7C7238A78BCAC9A0DF94CC2FC667E110936\
+DE714855F3AAAA3D60615134868BE0715C54F39D26E9A32019684299A71358125174C6A33385AF\
+5283801FCCE195913E56D7BF2F806633DFBF11674E970FEE95B53911D46045DA1F8FAA841ED16F\
+E850949CD69A13A3DEF631337958203B39D3C1C748F96AD7E0E8F24D23AACB23624A1981D845BF\
+89F56AF58FABA2E9E6513AF5DED200C62092EA5CEDB5330B0229B4667DDDFDCC635E381701DDBD\
+55480E935460D18E94C78C2B1D1D866801E203850B8833A2E0AE32E43FBB28AD255A3D31296A34\
+8DDDB983EECC0B0D84958D1B0D95EFC39EA075AAF25595F4FA794A0889EBFCA1E57E92E7C2180B\
+DF90946D6B2A8607DA10FCCA868F6E24AAACDBD3850B44C8D8D7DCA15499C6C33A7741BB5203B3\
+9D001C32177F7C060EE5B43AB4BA9F8A53AFF79E55A532F78832446216E5484519D87395A5C0F9\
+AAB59884F8163AB732F161CFA23307AA2646C3D4C9D129C2A9173E427741B4B7B23F8139354646\
+778B10F97781953C2473FC277D3F0DE097ED9359E83A33AB01DA298741CF9EAD9CD297C0A39AB9\
+BE72D5621A06D990FB175E7E10D460245AAC744965CC2CB520B93FCB02E25DEAEBA92E9EDD0AEA\
+6DD8264D1609F3AD1990627A4E33A73257723F2405A393F1FDE2EF7935F9A41506B437DD9D2813\
+752301AE513502281CFC635844D3F13F532F3DAF403E8AA70DF3CFF67520B00EDD0D0E53A78827\
+043511256A6464CF6E3FFFDEF8C0522FF17915189E4D6377B9CFD3BEB52CE73F4A63CF262AA071\
+6C2EB5F3D9FB5E5E39D072E55DB768498C80BBA3D11E1ECBB89ADFD7EBF73030AE102BD7D5D95C\
+B4599706A0A9348EF65D59FB0FB15143C0896EF64946BDE0E5AB7205F1AA5030CD960CB4F21081\
+E3A0AA1DF10CB6DF811B9E70E3F86581092928A25EF64929DDE63AEF555F4DF0E951AE6E3C41F5\
+C1B1E962E1DFBC1F30458B7574F35A3346103C62461384354DC9B2F98497D1C4987D3CD45D84E6\
+B392DF9E0A2AA8559EB4F597DD759E8323CAF7CAD0D41A69163871648927D6FC:\
+37494F0A17C7164E023F6409B4AE8248D25391910AA24BE3F116D4A44CCC02B4
+
+600BB1C53869CD6912501049B9A53E112B5E6694F39504B56C965C915DC20EF170CF0F1C9E638D\
+56BE11694156CFEA74E2BC7C14AEB360A984E29067A36D011EB1A3541B97009C5642E64916C357\
+7B4BA5C87AA36ADF41D712E22E94BD8EED81629BD548AA69624155A131654CFDDAA4D758341EC8\
+F8021B4239A1BBD9DD7AE777D903F0AE8CD332BEA85DED4A66B8140D1B694EC08E238417E00C5B\
+696008E5652C9884347AEBA3C28B58AB8B955C2849234A431C71B0C3A58BB2619BF2ACA0FFFCC1\
+710673C3EE0FEEE5E091ECCA5833F4F37E8509595BA2BF1BF7437988BE4F63C7E613FAB270149E\
+8B37FAEF45CB23E4106E6502D97135A5B7B36A7563BBDB18D4C37DF72EEE79CC4758D08ED7E0F8\
+24A3CF4C3BF116F4D7D7D60EA0A819E2FCF832E7919BEDE619C64228F9A32C885FE92A7600FCA4\
+B0C74C2BDB2B18A210A2CBEC520960EB5BD53EB6A53E01C4D4B16EC421449360841294CCA5BBB0\
+424CB8A6F6A87F26FA5A75E04BA9646D80574DB61A2D8C38534E9CEC4B85D36A105B3D3F9E2A0D\
+1C935FF8EF962F3EDB09FBD6F626C42E3EA08FC8A24122FEB53182B45098BC4644F64BDA83E2DC\
+0E6886167F03852A5783497FED6C5C8E41FEB1B0BE701139458529ECEE21F60C643CCC18ED07F6\
+95E54A3341128E1CA3A6C171DE7A2E1C50BB2C31CB0DCF5584B36CBB41B40C41E5F3719E7472AA\
+3D241FA27F212FACCD1D720B6F1D1DF4477D7A473C8347F73026E32BE78153BB975E8A61F888CF\
+60DB98888FFB5BAFED7EE92E3218747D83E5A248ABB756ACA331003C9BF27ADC5E273626060C34\
+C1E8E76306C9C7A6E4CAAE08BBDE5B1CFDB5007C10250862A4F2F5B8B58A7F8112EED4D0850CB5\
+BB2F9921C49776925D2B74F0E83ABD85E5BE986BE661C29266094CE3959232CEC6D9EBA553AF9E\
+1B70A55BD4C720D95366133576A11EEE942DAB0722538A7CE32F17B8EC2629F69483C90F3A7417\
+63CF953681E441D5E567341130A5EC5B8F36AC35725E23A6979907AC337D03FDF6AC75EF4856EA\
+D4E18738A26667196F6CD15488291F948539C8F8F018387528EC6B4963F0A3E2AFD1F4F56F1253\
+DE53F314CE4572CD6814B7E2B03EC0D88C1CD737952DAC1D85F8761E2FE3DDE9929C859B9AF957\
+FC8F78C5878243865983CB3E3CD76AD1038DCC5AD04C754FB649851A50DE89D76FFA4537BBEBA0\
+82017E5840D20F2FEECF4C1DD9B409EE4C9CEC91ACA81115BF90CF4784C998FA3A1FF18347520F\
+307E52D67C596742B677B6CCFEA597D787B63708181C765EE28328667516AB7B75F3A655810088\
+6E923F2B94D730C51A05874D9B944B458C95DA87E071D753EBADB54D0876CF387A70684ECAFCB7\
+0BE1FF16618F0DA96DB5070215B7BBCDB4AADCB7BA825538B3FDDE5D55C0BC91EF7E52072E62DD\
+1E3CD2764BAD4DB94F9C:\
+8E58A67D528725BBD8AB846914F9A31961C90BA68765F872F785FF59C4EF0D2B
+
+AAF2F5BD8D412040B7B7F0C638AB081C9B4F9EB542CDFDB53C0D156BEEDC811A9F9838CE32D42A\
+DB83BB1B5B83EFF374B4FC8D64FE26FC94BCA43E812079AD8C33923355C634004E10449309E9C9\
+0564887BD27A5CD0839F159CD56087913D05D48E6ED6B80350B09B3A8FF426B777FD8FCDC72C22\
+ED7308C448E6D4A28B3F0A1BC23C300E228E4C3530C98F507106D5D526253C7D49FBD5D84D20C6\
+67E346224E2F890C947F56AB6538B3AE6B297EA1AB5F33CD43A8C1654C1DFE7AACF7E7DD733C09\
+68DFF6718CBCB537FE742C68B220F243A750FB66419DB03F48AFBCCD68798CA4A24C2E49BCF380\
+004EF6B685E528F3C2FE79CD3DBB9CF88D7DE09557D10459823B5BA08F31865B5A055CB5FA58AF\
+3D849A4CEA6F7C23C9BAB07EE0F4B330FEE01BB3AC55FB5882895DD1DB086CA37064BD8558DAFD\
+B26F34ADC8A560A9B9E845BD3D18DF8C528261069332D0384C04A09CDC9AB9B631D88B06133E65\
+F1A8FDF4E5088BF2BE5C970FFC80DEA689EA3B67EABC5C097880594A0406F21963D9C2F3FB52BF\
+621019BD1F69CAAD6205E44B5D414B73AF9671088D6DAFD728351AB9F6D9C255D9700222ABEF98\
+14DE1571384DDDDD7362BDF06F3E5EA35FD56E0DA288DBC8C80CD585024F3BED4912E6D5CABAD2\
+0250A51F3FD1A25457ED07B3F652FDF0CD8F6DA583DFE780C6B5D92333DFEE4DFB22A3B4DDB141\
+BC385B0852D9B92198A8F2DA49BA0F119CF183E40EDD764B418AD5A880DE5FCCBAABE0785C8E13\
+4E03204BBE0F991A8B54A44633AF79D434BBFA0FAFDD1FAFE1071964169C712D51619C8E9EE8CA\
+DF9E54D7E61BBAB8548D9D2C53CA22A4938F8AA8EC5FDB5401276A081D7C0906556CE98AEABB5D\
+5989BD97C689BA83D2B2197298E155A0FCCA5A42355FBB6BA619783E6A1E343ADE8741349E315F\
+1BE78D1E3969F0FA6DC147C0880DAA7F066B18615F1F88307C515BC82CBE38A1967157D4592F63\
+C738C861D92348AEE550727735F0B04006CEAE3E083629855FF75332A9BDA43D2827AE97BCED1A\
+3E015AE79425237069D6F630A247B9E906D5352AC4BC486558572E876EFFC1BFBA7CF90A6C17AC\
+6AADA8B3C7D0374DEEF1D8D0CC8E4C2A7D86ABC5B6E0EF7D047AB30A6D801C91B3A84799202923\
+A7B6B1966884C50F9A2FE3A047AB588B86C70128B0A1D263751DF699C2D152A1F8B70EE6AFBA6F\
+F9EA240C4D6047EED74EA06FB885AD468E6C9D5ED4444FB1EB4987F966CC1EE51DBFC269CCFB81\
+47162965113DF7696A9FE1911E569A5E221F0B915EEB34E689F0FEA7655A179D9506E0787C205F\
+BD11CA9802E5A4D4B3F8E9D270BE51E75718BB17BF3099C8F68637059009757EAFC48010A66E1B\
+A572D774628B4C35E06F0ED0DF055F27C054B4A556B1ABEEB076D5D502390E1C31E28555BE7F6A\
+6ED4B49FD7CAB793E4BC:\
+B97C3815ABA1958CB4A6F64B3DDA017236224597101DD822F24A6A594F255973
+
+[GOST-34.11]
+# Using the CryptoPro sboxes. Generated by OpenSSL's GOST code
+
+:981E5F3CA30C841487830F84FB433E13AC1101569B9C13584AC483234CD656C0
+616263:B285056DBF18D7392D7677369524DD14747459ED8143997E163B2986F92FD42C
+
+730B3A80E44DDB0AD9A04D990D22F84009A86E5E8A2E00164EB168CEB279:\
+DF252A7F37EBDCF4995B5419394A6D3D2C782D30AB5FAE89F3665F86A4BBF78F
+
+67C6697351FF4AEC29CDBAABF2FBE3467CC254F81BE8E78D765A2E63339F:\
+EF35DA69225241950EBA3F20E6EE2D86A6286707EBE04819A81F79AD71DB62E2
+
+C4852EB81C5EEE208BBDCAA019F49142FC132197EDAF0E02374187066A9E25:\
+CEA05A7CA858638868FB64A1BBC015296980A6096B4EB09B03F1C8B075FF25EC
+
+12FC7387466C9687EF618EB38BEE08D4F67564BC48DFDE8A477EBBBC425C2C54:\
+D1E138CD1DB357091037E6041E6BBC7F58E32C4294F938868A9FF5E66E174EA0
+
+A040EE298C760CD98EB6467BC03D839A31598922758D475AA389881F465A8BE79B:\
+6AE26456D06C682AB63DE2DE3D0A8A932370B12204BAC4B04F78472665A350D7
+
+3679B590CDB17A11BB39575C88F02BA1EC7FD72A454D3A30E702073A9451F7CA\
+CBAC5B985ED5AA190E017597F2A038DE1F0F08655D429544459C7ED9EE75A4B9\
+21FF517FD4FB98E2FD0D79EFADB1CDCD:\
+F2D03BA660317AB8AE88490C6B25B79D74B2C307AF0DF128E82E98204C3504E1
+
+B3980FFE5331EE30B407FC8EFA18FF6CE35C841C1622C405C93A51CBE8B2EC9B\
+4AFC999E2D87CEE18FCA7089E26FF5C5CC7AE1E29CA6E766E03831C8EA1D6335\
+19FCD34683A128126B989C4D079113D30BF4B6A89A9D0E7AD63F42C05CA5F576\
+A1C8BC2569E437D47CD3228465355770290D18C4AB263E81658141C2263738C8\
+FFF4ED69D9243D55F85FD95D9431CDBE3EE682E90CC06A7241AC3468E36C30E2\
+601D4B3941898F39E868967D99643BD84ABDC1567D2CC8BFD8FC27BB68579DC9\
+74E902B57291EF5AFA85D793E9126B33CF2D8A4D59520C314F33ECB78A8980FE\
+7283B3E414A23F0E2816A211290D45F83ACF45932151C47084B0:\
+D8A200CD03364E0FB2A396FAB05E67E0EB1195672316B0F54D1D05425E2005D0
+
+D658E6C4786E9CA4E60B8961514C406336F46691F29A9B2B1C07784E7EDC6C55\
+355219ADC0B551A6C0DA07112748745D3CDAEE2E748A599091D2DF0FAE4B64E3\
+9D7D915D33E204F3BD0B05E45379418F542FBDC8B917594AE9385A9783BE7B20\
+3C0C7D6FEE8162AB8D678FE0E1D07035002DFDB94456042D8E5EC5111C403158\
+4CAFC73A302AE6BD91759E72460EA7463BA5FF80FB03AD8A61729B7EB2CDD6FE\
+7C9E39ACC81F6A599408CCDA167320511820D114237F9E85F13903A406D9A282\
+77DB2F3FFA99998FA16569B7D88A08F1AADA05CD59A3524ADC55EEE32F9165A6\
+6C94E6672D7FF6CEE45F85BCE98EAD9368B261C155B30B3209FA15388B7ADEF7\
+0FC45E3C43540B27B490E49D1E913186449247994553CB4E4DE086D85B65CF6A\
+292EA66D82B194364278D4600A05E74E972EE7DC81B32BCE93B1A6EE16765840\
+A4FFAD26B0415DF2BA3153C4363A12CD68F9A9EAACD4B840865F2E9CD587DC79\
+86899F36CBFC29852D7C4963B65B301E54DA0801AEC14134206FD1F5F6AD6E7C\
+370DB3020ADC873758D09B0E2BCB2C7FA5358054F6C1881631590B270779A43E\
+8657409033C7C88B976399C22EC541D4FAC228F083B006B40A11DC118A804F11\
+D78FA10A566995EDCC2EAFFBF3F0CFEEB2F7DE36A7E5EAB1F6C6C2814611921D\
+A03327F69DBCE369EA9264DE8333CC352AAA6BD28F5683861C460763579980F8\
+CCA8EE6964D2D34F64372DE76BF91D95A3886733DEEBB9FB31C05E8859DE8025\
+866F8FEB41623AA599678D0460AA9A0332013611ECEF0C1DAF6AA60848262ECF\
+95BDBAD61FF47CB85B09BDBBB357BEE558F5F645E40262946C089CB52FCA84C4\
+873E9BA632175F8D201C48D37306B8CBFBAF10E0B173741E7B10D3AADB576F62\
+950A09C721685441849C14F7A2CCC29E7BD37E2D46F24BC1021E6CDD75DB400A\
+E549D106B1254735C15B2C6327EE01A3C17FD007711BC974393551AE1091B8F5\
+DA89FB8BAE42C06F9DECD2C4DBD4679C5337A4C5526D398BA28A39B21CF1A7F6\
+7AA28228E44297812F6A450A3EADA691E44A5637B78FC2591AFC0B36EDB22C68\
+54AE9038F128B92092FF2AD0ACD061901BB8C7D2478A2C6186379773EAC4DB3E\
+726C7763943083262FADF6DB7E576C990F336B57BD97B843CF50B7B91492F786\
+FE6EEA929F6DB8CE1BAEAA9906163215499D6C0735254A047501BD8994B40F92\
+23F925C267DD90828C3A1B92504DA79AEA14A11F39EB23AEEDE03781954613B8\
+40387AA7160A29A24544349591DB2F7BEFD09B28BCBED6A99F0D2A34543DEC94\
+76663B8C70642EB5A8624B393D7AB42D4B4F55070E2CB0AD39DAE18D17CD218D\
+335C19A3C0475968A9A4A1E71E561469A56970B3952060CFFA415C120E7E9F41\
+DAB9E59B003E03AAE2A59100FBA56AA00EDA54A4FBB473F5F6CF07044DA74628:\
+12DF46E869E72CB058629D3554917D7ABA7C6D9D432751F58600138DD5862BFD
+
+# From TTA.IS-10118:
+# "Hash Function Standard - Part 2 : Hash Function Algorithm (HAS-160)"
+# Telecommunications Technology Association, Republic of Korea, Nov 1998
+[HAS-160]
+:307964EF34151D37C8047ADEC7AB50F4FF89762D
+
+61:4872BCBC4CD0F0A9DC7C2F7045E5B43B6C830DB8
+
+616263:975E810488CF2A3D49838478124AFCE4B1C78804
+
+6D65737361676520646967657374:2338DBC8638D31225F73086246BA529F96710BC6
+
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+596185C9AB6703D0D0DBB98702BC0F5729CD1D3C
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A616263646566\
+6768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+CB5D7EFBCA2F02E0FB7167CABB123AF5795764E5
+
+313233343536373839303132333435363738393031323334353637383930\
+313233343536373839303132333435363738393031323334353637383930\
+3132333435363738393031323334353637383930:\
+07F05C8C0773C55CA3A5A695CE6ACA4C438911B5
+
+# Not implemented - how I wish the test vectors had intermediate values...
+#[HAS-V(40)]
+#:475974BED7EA137D982D1DF5B2583B1AC4D5941D8D557BB303586742D889178\
+#8943A9668A9DA68C3
+
+#616263:A70AB818294865CF9C9697D69715235370381B833F8F1A42E01505888B002E43\
+#05FE6405519F595C
+
+[MD2]
+25:A248ABDA0C79140E2D99170DAD36CBC8
+3386:43C980AD45E7B3B1CD75CA4E7D9A723D
+A0A806:0D4596E208051A05DFF8116455562630
+7664BC7A:E561C90B5534D750BC251EB77A9E7870
+94A3C94A0C:2D8026BE7A76954A9E096343C39ECD8C
+2BA359656CCD:2C549D1C220B32CDFC242874E6807B0B
+F62E1519F7C123:7D473DB4CBC7B479443BE0F5BA34AB88
+731E26C302E41557:DFFFCBFDB186EDFC3174BD6118B9F4AE
+E96E54E58C275946D6:DDD255C1D97FFC23ADA446D630E648D8
+A05EF276F00ADD9AA737:7468B835B7FAB5B85E95BCEB563AF71B
+B2E29CEBCFE26335B65604:96CCB8AEB6DC5B5D0502CA2DD5795197
+4A926951A34CFF9612086FA1:CA2A050506C450FDFF20DD7E4EE5339C
+501771E1BB1766FD3FA714BCC1:FA6F95FB2DAF9E4E153D7D78590EE138
+07ED7EC95443B759D36E5699547E:61B549A5FB75E337A194E2FCA382DE25
+50AD2003A260C982EFECA7D5912BFF:6BA8E7DDD4019F159FF72514CFA156D9
+940866DDC4A37CD965DFFBE3E2B0C341:6A92E7EB476CB01F9C404494260E3777
+62F3333A791881457264348DA07FB6B7C4:61017AB161754960D3F1D1F1D10FE8F9
+E68EA199397AD1D0C9A76BEB4D96722CBDA2:B373D1E21455608FCA99654850ECFFD6
+A7A8C48263FC70A6A77374CD0E685773248D26:07FF45303EA30885D7AACAAD2E16BD50
+654C952DA2E3C7998473AFCA3C9AF2AE89B2DE45:C9444F92EE581185EF649354CA8F4BCE
+A4D93A05DF87F08E3113EA2D0CAF8F70CBC2BE4B2A:B46ADB25D38DA1F0E7F6F8C5DD129D40
+EA12AE41BE9B71EBA74C9010C4C884FE5DC9B0C5C65A:B6CFCF8CFDC2FE63CEAA66A5573FDA81
+C3AF0ABC9A2B464A1C4F629908D1EC556F20F64084E733:523441B8A2FB07E41E9B1B8CC5276660
+3C8BCC24A8DC88690F6B6C7CFB25DEF15D37335EC41C8C83:\
+F80ADCB9C78CF9DE5211091CEC3E310E
+65E2194B8A8B5B30F5C53D01F8431E8C20418EE6A06F89F87F:\
+5833781CF79E57F605F9D73D3B7088CC
+62FBD128DA286D5C6C5A3E73D463E5B31D7FB06F34DD050B3CDB:\
+987C1F6BB686F3A983D611C22C5086BA
+DDA05271A7C4860D49D2CE62A0B59B11BDCAAF272898EB8E18F1A8:\
+779D23550876E50A7C19F4777C84984D
+AA8DB1791C56E3C88122A1AB77A9D8BCE0D53240C01B789DE7FCD594:\
+9540F40D24417EAD9465B26D8A7746CC
+A1C7EAF91BBB251411A86595BC66D4E5CCF227FB2D9913F3EFB4E69B3E:\
+D67F49DE6E7BB44071947A6C96774E02
+611B90477FDC084652039E3E3F55EB74EE1A3E14BB49A08882AB67EABA73:\
+C7F8C0C4B53D40634A084A0E388186DC
+5E9F73521E348BFBF3ECC570012AF45C9832F673FFC61CB034908EB91A6672:\
+03B6F0BCB2A99CE4CE51D92DBC9ED3B2
+275C7EC5230978B84D4D87B929EE90C04269B91A32A69BFE2B30E84361CD8905:\
+72721B4138FEE747BCB950DD01291C37
+BFC3C421B77FDC497E417DF9A2E8A480CB975BED8E3B90F0BDFC567D66D8747D85:\
+92BCE15368AA8388D71E1CC5B4773536
+C2B801C8419027751EF0C9EDBA783BDD703259834E0D28F1CC18BA82A2D9DCDDCD5D:\
+7B194DE6324A19C54F9AFEB352EF9A8D
+787B37C5C74098B78B693D33E5DD5A12BC2D502D3F69852DCB5CD56D6263E846F96ED4:\
+F63A8C1958208D999F55917D9A1F3228
+0614889EFFDC294287D820C8A4459FA44CDD02CB1DE0F678493C959E7DD1DF90257AAF0F:\
+1E20FBB25E31606B0B22FDFDD2639C71
+60D169B12C1ECC464591BA572EC74B454D417BBDC49A82F01B9A4FD1273404F6FEBB575E51:\
+C23B75350BA0174D6A4BD629A8E43311
+642350615A9C6CBC8894D72176AB2EE4AF3413D15C4D4D9B38D071C95FC620FBAD6AB37FB8E5:\
+3D0C91CA852FB8C51AB9441D5A3C1F94
+C6299D1B98BB473500364EC66A3DD9238DCCEA4F281005FF630E99B5C8D2A7AC5FB1\
+3C693ED05D:E2B2458ADCFB7D0BCD4789EB9FC0D2CE
+9D5AA26103830005ED7C966E120253DD7ADF49C56BD89B211B6B0D5B491066A52498\
+736122A325F7:C8F205DEC0103264BEF4FA0501CF007C
+7E038B83083785FDF4696310B579D3C0D98A0092FF2D71808C620225FC54E6973B90\
+7E5ED4A50BBD5F:91F01747135E4E9B18A95666FF4C8801
+CBD41D36CC3F85C7427E3D04DB05E66D32FE7E9683A35B9ABC5B06185E24A867B954\
+DDC4FD41E0379423:96110102BF17E3CB91AF30EB0B527851
+61F01942CFBDCC748AAB816527D49848CF698A8AE5E5EDE8C3C9178EA5719EFBA60E\
+B1C4C3324C6B1AFB2D:94EBDFBB3060FA8E7FCE7A4538CD6829
+3E96A6186BD855DF00FCE2693B1394151594448B516DE0B9C8D15396984222497B15\
+EE0DFCD47AFBD8AC3F83:D39A82F44F8E7D8384938DD8C42C28AA
+9C8CC760D830780DD8671282D6A2909E9D163BC54A04119586404BCBAF5489C79491\
+AB236A4F9781CA58E58408:1F902D98C973B382D084FBB40F0920AB
+00A530B70C406BFD533C2642B94FF767EF4C7BCB28EA5CB69C62F52A01AC1A25F1ED\
+D918719004757463E6663340:C7FA3641EC0626AC66FADE4B77FFC795
+8DAC93EB30AF1242B93B4C1C8D7D2A8E1320B2738C3D40E623E7380AFE596A783A90\
+2B6A19DF17D15356C24CEFBD66:437FF6F86D68E35D5BC507AE88C8B0D3
+C3D2DA59D6435405406E342683A324DE6844C527687521E43066270CDF8534C110FE\
+EBD79B5F2FB00FA3B9A31E1D548F:7B4E56A2014BC8127D6DB1699128310D
+D178D2623180FA605C3379B2EF0D5A3272593EE49588708303F5744E8A26DC7F4E3B\
+4435B85A8E68B5ECC40AC7DCB2039F:CEC9CC7590DEAFB05FDA5D42C5CC3A71
+4B2C6190EBE39D5282026FDB3124D64094108DA1237FFD3A52ACA1BD96FBE752C4C3\
+631C33913BD5DB067AB234C4628B2ED9:E0CABDA82227CE74EA7550053F942E74
+9A75285DE0B739BBEC8AF7A791FEF5375A8E722134B6299D6FF167F43BF80F5CCD83\
+8F76AC2278C6CA5BE7E5C339ACEB8BF77A:117451E0A38EA5E87D6817003D9DC6B1
+A2ABD527204652A5DC3C672A1E47F5CA34FB1D7F300580F63B463959991DE6DE1472\
+EB21CAD19D4636C26B0F1FA99CBE6DA4CD70:EDBEAC9A8676D1BA66949F71B7BE5005
+FB2063EF9B211AB8ACF3D1256DEB4E30D1B6DF1882308FD7F80F27C2141DA8A89551\
+B878410D914C4099DB464738EA337335828434:4DF72B07A43EF126FBDEAD01E51ABAAA
+41DEB68691AFCB42C865CF29EC0C2698CE621594ACD0D3443B8D025F6A4547DFD058\
+740A837867A2C1E204CCEB27740C343BDA0AB6B2:83A4F9739748D0402BA738757FCC517A
+38C8C56CE471F839B8FD15AB3AF0E1D1A3FA494E7DFE660D5224E1C8D43907E5CBC5\
+6CECCCBB44CEC1AFFF26EA7594E33D05789DC49E76:07A7A27D722092692035AAF579751495
+6AAE2909D84B75F7AF3155E85660A1CB224DF40A4EA6CEF0C0F28AD149F3486AC3E8\
+37E7283E07803522CCE7000D0213C73B09FE77500852:C7324E5968CC534F8B98406165C5ACF5
+9934BAEAF002C98F527AB248B8D44520456FD552409845CF1E666E41151DD3383E5F\
+658DD3AEE63DCBB94BF5ADE141D753B57BDC3BD22D6648:985711D04A1636B27B98EFC2DB61A806
+69C8BB8FB1ADA90D0B9739E62AA1090D12C750945EC15F28D03886BDD1ADCED71699\
+48E085B56996D4537A35F72FEB5313F3B7BB3DEBA66B2B84:\
+709578A0AA3DBF9CE4BE69AF71E1AECB
+1EEA19E3548286905BE1092F54EC9E372DBB9950E77EAF7E9C55031232D8D70AC9DE\
+C5D71FACC235EA339B859D54C4D3245F8702D535467E918F86:\
+26BC86988B1C278EEEFA648345431254
+24215B243E36C2EFC561CABA961A170C0EC406344AD712DF5DFF62CB80B4A12C08FC\
+009E4A359306601ADDF31845A88F927BD86566634466BA15E5BA:\
+2BB96ED578D8C61B39DEA925DCDE859F
+4B6AFF3B20CA5685D3E173AD26E443D38748340B209D63E60F26988AA4C31FEE1427\
+83DA23BDE5D322C6AF97599C63183EAAC6B9DBC3611E6C2C32054A:\
+F54BBB34D01EDA10B43753BE8BB9C219
+26C82DDB40254A854F3FDD1334F1A191101730DCE43972881706FFA4D307D7D91598\
+93252B25732F3976DE9675C7128990D7E321CB023221E2A89BA7E066:\
+951FBE39B9172884541297FC8DD4C2BE
+F357FE7BE2CFC971379457338EBEB69A40286C9C0FE5DB16888E2E270EAD23BCF7F7\
+0031770B08B5C7C4CFF2E49C6BF9844F773B3F84C49C575173C691CAFF:\
+C2AE33C5E43079851FC8D2671F5F4CB9
+F5A11AC76D127223FD9E95B3E743B7EFD13BDE1E502D0E81E33EC85852420EFB3535\
+95BB7591E11E3A79FAE079239EE4C87FD141BAE6C6B7019B9A57BB6498E0:\
+45F83BFC62EBAFF4EA00678A138D7E7B
+CE9C44FA430FCB3BACFF6B384A2A6C2B0617C0737DB20B0B78D86C6F7C341D19801A\
+C2E4400822DAE74DFA40A4468CF5D1081D3290FF35AB4775790E22FAA58BCB:\
+882D31790CC7FA4B512EF4A00B1F5180
+BE2FBB79CC864E84C625D71F9886DC29F9D5D387BBA4AABC2DF2C8C75FA45C759E19\
+2E0EE1A31BCD51618402D8898E8EB937630F6211734AFC590F99AA67BAA0DA69:\
+497353E9FFE29110092E859CEC5B366E
+53726A30175CCB0EEE5B91B542E7FFA6EC7C2DD20784563D5D379B0DD5F632060B9B\
+9FB6264AC792830B6555767F91BD0D6808134624E7A2D8901A6BA01F558BE4A549:\
+2CADCE7ECC0BC5DF4043C9A3F4F838B7
+
+:8350E5A3E24C153DF2275C9F80692773
+61:32EC01EC4A6DAC72C0AB96FB34C0B5D1
+616263:DA853B0D3F88D99B30283A69E6DED6BB
+6D65737361676520646967657374:AB4F496BFB2A530B219FF33031FE06B0
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+4E8DDFF3650292AB5A4108C3AA47940B
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465\
+666768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+DA33DEF2A42DF13975352846C30338CD
+31323334353637383930313233343536373839303132333435363738393031323334353637\
+38393031323334353637383930313233343536373839303132333435363738393031323334\
+353637383930:D5976F79D83D3A0DC9806C3C66F3EFD8
+
+91F1999647F001F7B4D4452CF7C07B64A994EFD25DCDBD9F6B260A77C8855AEB3EE8C65EAEE6\
+397DF26F58A1729BF7A12ACFCF1C4C07A760B829D4158164A57037C15FBFCFFCD85C987C9FB5\
+319AEF44484965425FDEED7D182861A0F3F9BA42BCE7CA288355DF484BC4476B1C587C401BD6\
+196A401A9A99BEC075E8B99CEC15B3E9292F6399F61E00B27837AF4CCCDAAFB235E90282A08C\
+979628E084C66FF24E6E180AB9BE50E274861E174FB511760CB2EB48A2A50D9D70C97B864236\
+BD6AB8C2D9BE95E44FD317FBE6135B800C00E2422068F399F6F9427340AD4ED5CAA1DD96C76E\
+FA688679F577FDBC02624F7D936A199A9CEFBB4F2A9FD15A1A81ABD5703A55FE3911455C8F0B\
+BDB6C6479B24BF8501654DE0593F52713A53929E46FCECBF708ED4EF00768352682B8BF7731F\
+2682991D3CE26497BD4419B6BD67A04907C6A1D84B2B7C2B8C622EAE73AE49D978DEEF8214AA\
+CCDFDDBAE1F10D19AB6BB7D38D5BEA2A6141A55BEF2BEFB605FBF01A88BB7294E4952283731B\
+E737EC395B8B537558BE7889CC9C43C855F6CBF4131FB2FA17D72E334F775466F1B9C70A4325\
+DFAFF502D71ECC73E113871EBED295D9FD66EB2F8CCF456075666C9FFC121BFAD286C457AC11\
+91354CD5AFC3F8678CCDC3371B2D86F378182B7F40517FB36DB0194A0D517D9CF235D91001FF\
+E86F7386717B9CDA393C712E3E2628768EA5FB41B1E26B11615B6187E0CE73015FE6811420C1\
+A2CB00D69399C91AE4A21F759B31CCE31CF01F0F9D1E40162130EDE0ADC73B641121F1286FE0\
+3619B2768E1FA021311CEDC5B124EDD6B1AAED550CC3AE65E0DDE172F9A8CF136D417C859DA5\
+C1B6F2166810AA46BFBBC2C13B1D23EECA6159CB09D511233A50FCE4DB27E3D35728CA1F35C1\
+A5D538BC4B1F2D95C8B8B424B346FEC0EDBE78D727B9E982EC2DA3CC81238D2317648CCDCEED\
+1C887E97FDAA0E764807F5503FC97A555D99B417185F75F06CCE3646E6C1900A64DAB07881D0\
+74FDCB400043275A4D23C5AB64FA7ABA88D225EFA9AA399A7C18640B09D37F189D5B8AE4256D\
+20A50B5BC26DB9DD6B2A81436A098DB8283BC6BC64C07B0F700A2BB0A4440DF1BB4B63197EEE\
+B31039AEA6B2517B54D5B6F93F9432D94E5C6755F4B847635C8E70E7B66A2ACC479B36BEEF51\
+3B583CEBBB97310DA9B96111B137E37A3DB5656A1E3C2F7DF8F7A84857FF376F6AB085C80A3A\
+3733D519677805DC1AB9F0278C78A2A55026EB6998761E8F1853EEE64B843B74714CBA56B578\
+766942B241D32000384C9634E09BCC45E80F5CBC32B86C33AF2E96E0602CD081DC9174B33F15\
+06951A560C0141F940E3F2E84133C137F7002F0C7CBD7D86429963C1B5F8BC3996685FDA856C\
+4548F3317904D4EFE606070F783E7BD746537170A9EBE29967C36A2CA8ED8AC08114C24CC860\
+013195:\
+3A1237D02204327A5D2CB7CEDF024363
+
+[MD4]
+:31D6CFE0D16AE931B73C59D7E0C089C0
+44:AAE7B2D482382AAAD75FDE64DF8FF86F
+0246:CB386D6A1189CD159F4458A1CEF7B28E
+A7EEB6:1C4E79A284594FBCCAF9C67B4C41A7E4
+93C40129:FCD8841C546F832310476AAAAF7E40BB
+D9CFF9DFE7:E05B135D5DDF92FFB6E85F95E1B246AE
+6C69618F2E04:9FDB803940A796F1A3812C3FF149FD92
+51CB4187084217:EBB806618D65266CD195CCD4B00E5CA4
+7FEEC81F78691BB8:E1C8A1F598A1465C30B180731D134572
+D9F6B614968646FFDC:D27628156A0EF18309EC5085E67097E0
+747F01DF7F723DC311AF:FE1F19114FFA1695A28B92315F6911C8
+E933B52C2E88CFA8E26F3E:18B8AB7B5B7610CD6262A05417AD467F
+A1483E3BCCDAC94A9A2B1A63:39F0B4AD11180EAAE992489347AD13C2
+F1C7365D2B16368DB23EC806DF:A2CF9BC244949E0B9917AFDCD0EACC65
+8DBAA281D14C19F35C2AAD537F7C:F2E6FDDD6568EA8AB316111E5946CC9F
+785D55E2AD30E4960E6AA3482B648B:A01DA0D565A3753717D1D81ADE3166B0
+BEE8FFE30FCF0BE745BA22215B320F66:68A5FF4E4CE33D50E8F42B49505279E3
+28BAE5F8B5ACD3BE26521E0CAB1C9A6541:93B775F3BCCA2F2BE24D5CC63BBB3224
+2A7415DBFDF5FEDAD4E8DCD96543FA6D03E8:2BC3478938FD5EF823D2974302E61ED5
+285A585DCA6B4B4D59554C80BDF8B19491984E:C7C6E691B1785C64D8CEDE5B6F6B98ED
+C7FD53B9E39B4A447442C45B7AB3FD0602C57DE4:3DA2CF785958E6C115D8843BEFAD1979
+D83F308D3AC2F0D82C3E69A08CE8BD97AD02E3492E:82F6CA7BB64799BE36AD89714AEDEB83
+936800D2940A8A22A5D54804B451F59668FDE5187416:6E4F874F35C5BD38617A31F9EC693B44
+C7D740B0DF155D9C1F11D1F6AB708A22FA1F2146D48953:E72B78BCA0A764CDAD13FF69B48B2A8E
+EF7CF50DFD9B72E8CA0099BF631BB334CABDF76192CB951A:\
+9E7B7A7458B016BD68736D1512995585
+F5A46EAEFF6B9A9F01653E35E90116342C470425CAF7B942B7:\
+CC032DAA2546C0C2BADCC0BD77EB12C1
+D8AE0DE315E449498FEAF2FBDB1971A09B7BF658AA70AC782E15:\
+AA1E5DCDD854DF06B715DEAB33E62E0D
+A1EC5E04538FE815D26B6B3BD9A889A43416F301064B15BCB480B7:\
+CACCEDF21D2BF863F1F4719B4B83F18F
+97EA99966751703402F57A2B5B6505BAFD1C440B8147C87EEC246F0A:\
+ECCB8D37D12527CBA6D493169AF12159
+01864FB76236CB325D893BD1C7778E017284ABE61217C9B5C6B41E55A7:\
+BB7EBA4B6592A688CD29C782FDB74EB7
+976A837D0AD29D030D376C3D8BDFD37F4E0AF1C4BB72B043EE3B6AF44AFB:\
+4B814B19C0DCBFA31405AB495034A4EA
+6E72B873F63F61E03EE166E6E988951ED02398094FB6DB178B2AAC3A56E248:\
+95BE77F915BA362E80430F4911DAEB22
+894B431AA20CC3AD8CC34C95895E0BC2DE6599FDDC863040ABF7735FA2128905:\
+4CE468F58CFA95E789D74A47FD8BA37C
+C79F893B67218FF1672939A1BFE5F7E48A5E81E502585DAA16378B95F853251EDC:\
+777CF61193AAEE17EF6B68B5168AFD48
+DA074189254813206E7A3F4483CAE746550F5658A8287D0250E988FF49E3EEBFFA81:\
+011542927FD9263EA2CA86D668DBBF10
+E881A6FEBD17422B451CA7DBC1D4A7D9878970CD3E7FB0274247654279FF837886C68B:\
+2AAA877A05C4D944ABF15C603C8AB6D0
+0ECF376EF3EAB389E65F415D4247031420792C988E47D63A354481B52C31ECD552728A79:\
+B817B64F224083D701A6BBF838AB7796
+888941D7E809DFDDC49BA6B2EE804DE1AFBA451126F0CF8B9BAB1D04A78EE28D98A4A90288:\
+B320402832D24B4EF38ABE044B521EF4
+9634A438BD14D8DDC3AE525A04C37E7BCCD803570C1A9123F714614B365017360FC50F280936:\
+8DF996A89A7D2BC860ECA7FAD90B34DB
+A9B5ADEC5616B4BB3DC89A5996A4977DA8C1AD36910143C267ADDA0BD80F9054F4DB\
+BF02CF585F:98EC309FAD45969BF125350868669D39
+CB76A9EA278044A520757E020ACDED18A5417D096796B8E8119DE09ABF5F17F95E82\
+6AD61E39858C:F29AB28DC618F5E4FB8525387B00836B
+914502535D0F05A72A316F15BE8316BF9E579EDE86C591B8037D1EC036D95F8CFEA2\
+65032029F6B696:CC09BE6F76C27424ADA44C52554F05AF
+A273736D5BEC5C75463FEFCB2297388BAAF202111517DE2506D331BF7F560E020D34\
+7848C2A1459423FF:9AA76F6791DC4ABA5DAF67B4A62CBB47
+F6DFBD94D04077E328166DD05FF54E6C7BEF77E104648951895771BD4897B2B7216E\
+F6A66A7B18BEC8A639:A90B980820FF501957009DF700451D78
+6B5B94AF15D1F60A181925BBF0372528964F79D5F2AE04850AC53105D9D732F3EF69\
+9DFE26FBBDDF43E17CA2:BADED5524542AF6A21F796EBDA1A096C
+520817840BA40BB5AAE8709ED60F89D7642BC81C7B7D68A52566E353AE869D0EDABC\
+D8B3CFD3200851AEC7F632:BE5618463DA165C84B7E1C8307A5A301
+3F793FECECC4896206D2A3F960394DDBA4405615D3DC17453036958DCD2042AB4B6F\
+AB256522ED1EFD38C22D9FDA:9914518E9351F15DC4D60B243CDA1B58
+2F859EE93CAF6F3944D1AED1194A53C236D95B721FB892D5EDBA47CCBA6D95EBD498\
+5086A8E3C0D7E84831C41ED70E:99C81ECD5B50F43DE3385A9E0D482CCC
+ACCA7AA450D9FE5AF957C5C9FC152822D0A7FA9322B044666B3264ED488656A805D9\
+FD95EC243FDBAF0937BE9460D77B:400ADD0630AD12EFD9695BB69AE126CA
+E84D9DC677B38B6A9646D2648441E12D7DF7BB3DC0AC0CC20C2783CF0C1C45B93272\
+9C33042D0B013B562DB482D50C24F2:8CBECF75DBDAD10C9D480579B476C6C0
+07C14E13B62BB89468ECDA029F66EA279EC9AAFB7BA7C80FFCD9946F88CB80F32317\
+7B77C65C1CE9397775C980A02B481C92:320C6C79226261DFA3D2B9BAFC51A3CF
+7F999F347589D4E2901BC1CA533E8DA0D3BCFC39564DE20FF0537759CEC5DB807D6E\
+B2C9D4587AAD0297BA6CB0BA6BD436CAB0:0FA0F71F8E8B9F47A966283F3C8BA4E3
+3099FBBB801C8B27A26B549FE23A834966A9AEB9C59EC76E6EAC7C20D934370C6B42\
+3DA31582F8BADBF3CEEDFFE69D3333A8E15D:B2CE84058F967E45000D287500C9D81C
+839ECEAE837ADA0AE91E52343B095B9CBE6E1529B090677C36F4CEA1FCACD1067977\
+88954417C61F951D678B6B1E8EED9FE7E0D2DB:7498590DBBF71F17EA3F4EEF7FD68641
+A4F122E71DAB34E6E35A27BECA6F3753E9DE662FA23E4B6492A1A0145AE3CA7362F0\
+1258670B9C955F55A300BF2F7D22B0A020E5CA15:98754DE80336A4BD012F8A05617532BD
+6FD5D1E011D2C155BF4CE63FDA59BFEC91755D6DE6F646CBE774BF96FB8463B8C880\
+6BE81F1238C5F9AD1F77A2A277D2694D12C3E5E9CD:C31E7ECCD70786BA1E2301239E2C9EDF
+F1B68A476C7738A656E25FC954AA7A42CB7E6BDD3142523F6566CF5B838D13E0E011\
+263407ACC6BD74B0FBBEB9B918529FC5848031896C0B:90FF6B4BEE1A2B833982850E2F06FDEC
+D223A6E65743997A871BE50E918F03AFE9B9847464A465BE1EE852BFDB1501989576\
+95F18A7928B0041575BCF5A095B3291242DA05D766E1AE:72C28BAFBEB177406866743F1B8A2B6D
+784743D4AE588AFBBA7425AA095A1E757017EE0F126683CEA69901458D237A7A69CD\
+2235FAD6A1DDCF1E4FC98017B3FD2081BFB6E3F801B46FED:\
+D956EE28E490B90B9C57CDC723A310FB
+3F18CF84A687A40725F32352824C9C2AA7444A4888E68D6892C8778D478EF4A5D97E\
+64F0D4D6D2C8A20AFEDAE41F7FB30EAA293AB43DBB16FBD9AC:\
+51678626D21DFDF58AEB6B35E977730A
+D7BBA140CA4D4C398732FED7CCD574C326FB498E8750177DCC9347110E43C82B9CED\
+D9A3BE266A6F93C1D5CFE5C6EB2D2768C5841F562EE01A4770B0:\
+B9DD09BA8E4A8B4200E943F928420368
+C6B516FD918CA874B08B446C7F421AB01532E12D4ABD34CF1B7E9AB6B478D04D21D3\
+98C9E486223A803003E93EA6FDB6323FA52634383D5A9E43FAE4CF:\
+6D14138691FFC136B97C432E88AE1957
+4C4E1022271853F9FA261C3A52BF46E806A73ACB3E3AA25343D826B5291BF5DF1713\
+77D76285273B2AF7CD2E50A3D5D2BC08742817A29851AD5BD1F8EE02:\
+15AB1275F436B96CF1BCBFFAF15E6EBC
+3141EAD348142A07B4B7853471FA243511F1D8E6C633EA25BAE04CDA97B1AFFFD0B6\
+47131C67040986EBE78E86D89F1C86CF591365F7AB45865EDE0628EEFD:\
+B58A8F44BACCC511DE13227E98A69F3E
+CA547E696B455522A16EF1191F8C39196BBBF6EABA00693B69698DC1344416F6F3BA\
+1DF367B7EAE71D48165678F7C78B0096D6DD5EE2E7EB618E85758392EB7F:\
+8391004470075BF3CD8858C492E7184F
+2FDE680648A3CB7210D74BCD690A5F03B1DCF7EED861DA0F4C4E3FEB7B6B7D4B4988\
+F5605B30613B87E7DF8D3D6050721BE4F6FF0674EABEF58720685EDE942F82:\
+2CBBC00DD0EE6EA828221934A4605A93
+C6E48AA0604F18E1F579BC827779B850FAAABF96327FDACE8C10BEC830AF1EDEB2A6\
+46A5143AB342B9191FA5B02A581C4CE68880608B9D37120C2EC560B4AE309C94:\
+AB6200335E0B4DDBDB719BC4E36DAA07
+84600F3274F4ADE17F1C8C7AE3CF650D861269DA9079F2474DB121BD29FFB9A09D86\
+44A62E8E88C369722FF09108C430C8FA6B0E9EFF4DBDF1F353E1D25E5661AA3E92:\
+526A127BE8518E713CEA69D5147E9382
+
+:31D6CFE0D16AE931B73C59D7E0C089C0
+61:BDE52CB31DE33E46245E05FBDBD6FB24
+616263:A448017AAF21D8525FC10AE87AA6729D
+6D65737361676520646967657374:D9130A8164549FE818874806E1C7014B
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+D79E1C308AA5BBCDEEA8ED63DF412DA9
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465\
+666768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+043F8582F241DB351CE627E153E7F0E4
+31323334353637383930313233343536373839303132333435363738393031323334353637\
+38393031323334353637383930313233343536373839303132333435363738393031323334\
+353637383930:E33B4DDC9C38F2199C3E7B164FCC0536
+
+[MD5]
+:D41D8CD98F00B204E9800998ECF8427E
+7F:83ACB6E67E50E31DB6ED341DD2DE1595
+EC9C:0B07F0D4CA797D8AC58874F887CB0B68
+FEE57A:E0D583171EB06D56198FC0EF22173907
+42F497E0:7C430F178AEFDF1487FEE7144E9641E2
+C53B777F1C:75EF141D64CB37EC423DA2D9D440C925
+89D5B576327B:EBBAF15EB0ED784C6FAA9DC32831BF33
+5D4CCE781EB190:CE175C4B08172019F05E6B5279889F2C
+81901FE94932D7B9:CD4D2F62B8CDB3A0CF968A735A239281
+C9FFDEE7788EFB4EC9:E0841A231AB698DB30C6C0F3F246C014
+66AC4B7EBA95E53DC10B:A3B3CEA71910D9AF56742AA0BB2FE329
+A510CD18F7A56852EB0319:577E216843DD11573574D3FB209B97D8
+AAED18DBE8938C19ED734A8D:6F80FB775F27E0A4CE5C2F42FC72C5F1
+DB7BF252A4641FCA34866BCD5F:6EE7E13A9D83DA498EC31AB7F1AF2F9B
+8D62994630AEE95D4C2F192B3F7B:7BC1620BEBB0BA89F8E51454A2F90421
+BD68233EAC90E380907F13A3DB7A4A:529961E476F563084D25E0F981CAF73D
+8DF425048D0BC1CA3544975250B956CA:5127AEF56B982E136A90BB0617AB89DA
+D18ECD6B341CF10DE7AFF3CA82EE04FFE8:EBFD075F46B974E971971CE09CA3960E
+BC66823C5C3B9328940D2C1312B90DC92205:436D62CA86CBE2D645B728C3A3D012FA
+247E8B8F71BEFEFD1B001D34362851B71C2C5C:69D0CC38938B60E5308F62748C91FA78
+B2B8E155E9409960B216FF533647F1BEA88DF5E9:550C07A2545183EE4A46695CDE92CEFA
+87BBCDAB47CBD7A8DBFD46175E901B2F2014D2574F:AC1E96028760970301A2201C02E7BC2F
+E68232740643E72213C7CCDDF3FB6BBBF8FA91318E07:4ED55A365805C916A7B476F29161BC1A
+F0521C42DB4D92770C7BE97BC3BBCCC13936A72FB0ED94:ACE41D10A5771692320E8AEB0C6EE308
+9910BCA80E2A1E98D16871CAE15129D0E372F07CC0076C6F:\
+349B05E073186D50B8E98581C90C6254
+BFAFA136A48F1DEB19DFB707E34B495FB1C72CEA1DF6F47993:\
+31BB7F0CEE1528BE4FE0CCE8D140F622
+DE42D4B7A1FFDA4F086142F8D9C9A29F752A348E566F8CE53FE0:\
+6D7E9235A586970F8670FCE5FE7A4178
+45BDEEEF37A626381FD30D7AE7DA9DDB4AE8F5F17E919A8286AE2C:\
+9D1D7ABC247166C9508BB99934DAC532
+C5661640140037B16D5C98DD120AA50FAEB3548ABE84906DB82E0228:\
+0993CF5D2A56DF4D47F9FC2DD48F62E8
+B5B9EAE5DF6E2191C154D7128A2286E9C7E682B24CBC72962470BA89CC:\
+1BE6103887AB908F155C0EB3968F9E37
+264A4620BC5429260CB2DD0BD1639613F9AB513189F54467D46767B737F2:\
+828B112BCEE9225AAB202B54345F002F
+03BB178060230719B7AEBD628334EDCA158D062F3AEA6C0073370831FEAA32:\
+2C07E94CD50F9DDE6C9C99085573F6DC
+DF9A276CBECC9A28D999A67BD14D28E1C5827DB2F0B0D48BABA57F07BED49752:\
+3D39093BA64DBD00C07183177CFB4F18
+65ADA2267A286CF3490F5967574E707FC3C03E837D689C997B9A634E5B4710119B:\
+50C430128BF7499760DA8164F4FFB71B
+2954D2628C422A02C1B8A9D2950D177B508FBDF57DF94BE3447FB79E40B2F65845D1:\
+FD9242F1604EA977F5DEDE760AA9319C
+053F2617C86E5468D53D869CD260549392C53F6A7D8429685B86AFDA12CE4B611386ED:\
+929AEEC5B56780EC07B1455B1D2E0580
+FB55D0287923FEE055AE96937735BAAB47E488E3C24160E13B5FE2D06534A2E00F957FF2:\
+35C6713BF2E172D0A30A142869EB3B9A
+38AD3FEC103EEA5F808779233955B03EE4E7677A894A8159DE95E9FDCE9BC57D919C13C66E:\
+73E6A3F3BF0891DC4FA050936FFB702A
+765D5F0B37926C40D544BD7AA4052EC15BF4F367567C2F1ED21427C785724EEA29303B055A25:\
+D2DEDD1D77EB642E6CFBE87DA2537AAB
+86DBEF8CC3D93F340FB31E92C2324BC3301B9196ABF4292263AB0B883E002423F063\
+280B0F385F:92032B502AE736973AC4BE67E263809A
+B81F79B5B9B17DA768607C66B99976BAD8F53DEFC743EDC387B6C2584970BF5FDFEA\
+E48E99AE4C09:1CE836B431110C7E4099E5D8F8E54C0F
+8A8BC0EE1763CBB2081E774B282085DBCDB5F198DEDE350BFDF7B290BB097180BA50\
+318A833F5BD9A3:0B278644E43EBAD38FB5237405B31C35
+359AC2B44FCE85DECF35F5CF9536C7F6C48BE18F44731759A8D6C5DC2BB8374AF0E1\
+2A48F8D111286067:37FD5E056A2050789F8E95E9EEB8E564
+6213F3543EA1B634B8D9C86A26D08D1C8B7DADEFD9BE50721354395B1A99D653DF74\
+75A5FFC45A7E035ED0:79FB0A2C96B58FEA3194CD6FB3030C1F
+C2409DF528DFE67C1488D7E84970A82E006EA1B34D97728EC821FE0597D8204906DD\
+8396948C2CFD9A86E13A:E235122E1DB5E26DEAFA30C64C8FB5F9
+4E314E192FD989FA432E727083199163B6448C83CFB98A968189BF7F3DD69B635EFC\
+381BED87108A794C19336A:1C494D375150DCEF2FD51F84AA59D601
+2183108500C74144F21D67DBE132EF997B0DEB97513A381334D5413A6805733357A6\
+41A3EB2A72F0813C21589A9B:23D80B20EE33C33D8A75E485309ED45C
+F43753ADBFD4B2BD905C0F06D5450673D98AD6F50E192625338F5737DF8A0B375964\
+2FCA66CFFA9C96EBA5F57078CE:B176D8F4982A9CCE331366079033FC1C
+D04E4313C792988B8774DD759AD8BDBBF98306F4F6F7090F0E5F68FD8A2351544634\
+BD44F7423F30FE37881874F5B819:9BEA5C357BF5202B6976307713A903B5
+DB266910FB841658BB855DC312702CB639834C1E5C50AEC2AE199D352D2E4CA1DE6C\
+AF81968D586A31A3C5D65AD0F4912E:768434AC733C239B8DBCA7A459A2FB42
+43BDF85AE7C27AB66EEBF743F1D4B67F2BBC98EDB8B92F3251C81CCF54A219F6A684\
+E1B65ECEF7B3FC9C95AB3B5B7F374FEB:46956F7F64806E86C9973DA6CE2FBF90
+A87792462EA3BB903170039536B13C1617BEA2285FBEC835A7FB2CE7FCBAE27FF0ED\
+E753862E0AABF04DA01B74D95C042E1FF9:6D78DF86BBCBD8B08DD7FC648AD0DA64
+CFEE147442E699CF016714EFFB3579981230BEC61D7BD8CCD4CED1556278DE848627\
+C9D72FAA12AE7E00821839FFCDE8E2A421E3:67E9F45E71CA07B2E0D0D4B658B84228
+32CA147C83280D487ECBB61C3FEB34F0D44D6E5414E2A544EAA2C2992A19469090DF\
+86C2D98DC4350205A50416DC045A28580BE425:1136E79134EC1B4AFC61F39F9D0EDA2A
+03B674C177DD0E9D3C450FA48AC356417B319874C46B04F9387E823785FB6A2CB103\
+5B17F7B3B789BCC1721167BC393518737AD65A1E:CB5084C965F8433B3F739A3F85AD649B
+7538B43E81C97808AB82AB9BFAE52E2395185B3779E0631A11FE85B189C9F390BEFB\
+1087577AE977CD79AFE115D7462F60C4693BC16E0A:0D88491C0EA8F820A253F250B831BD26
+FD04FE966AC54F6A1BC4FBC86FA328248AA235D9F190C7D7D72C2382C094EBABEF78\
+72BBD5BA4611445B8374F0FC0269E5032392B95B8DDB:CD9965783D9A1EA097E9D9E2831ADCE7
+98948A1E28A1F7B97BBA154ACA43BB28C05A197E8471F1D35359F5744C66BB9D0FF2\
+34B7B5E2E73D533E5FC78C13FFF2B68B3C7DF94B860752:037A76A6C9B017AC440B3A9330EDD0FB
+06449B27F353990EAA0A81C4A0422079B5296FBF87209D084DAF4C81C796433E9235\
+71733CAE194EF225B12E67D1F5F21E0A50486F1A3E57C6C6:\
+75B70BBCEC3769FD56BB04D7FCAE220A
+75D4D3B833E659784D26E988145A3B7B01774CE6321F61A08B0A0C1A4645FDEBDAA4\
+9323B051B47C1F6B38185D60139CB7C22755FF6E2BB7FCB5BC:\
+2A087E2C8002DF98EF390183E96D52AA
+20DF7267729FD77DE12969F507383E240F39F018A0666E32A58846E0ECD9FD6D7A13\
+2BCD755F463846A1C861BD5593DFC71318DD7BDB905C315FEB72:\
+F414EFECC9C65E20FB175DB5C7FA2AC0
+E96C3DF4D195693DF4D3CCFACCDA4C6A18EF039F886F33B6980C4F1233A5C704B3DF\
+B205751A6B09145AB69E47A1653CBD69A593040AF6B3D6F5407267:\
+F14A6A40918BBC6901639C04C34C1B3E
+C44CC1C20FDE000FBD7F49453FE4519000E30AEE2BCC504B4FC0911807FDEDF488C3\
+BAF39A6D227A22D8888E9912C1AA9B37DDD2EE9C509B300E864493A1:\
+B82E59AA885C741BEAE1DD7FE19B1ED6
+B37A592ACDFC58C2E4E78FCECF067111846227CC1C53347B141F5F378B64FB5163DC\
+25149B88C28E6E390C561245D73485DBA5D616654EE17A76C20300E774:\
+EC58A5879BE2E425B1A126AD80E32FCE
+3104C2E23C21C174A512C7DF0DFA11DE82FF6D9B8CA86331970F8C29A5BD5F58DBFC\
+874B9F3F81136E8FB1AAC2D244C697637526C8A680B3072C86272FA684BF:\
+51E46388BBC048DF3914582F8ED32E0E
+D6EE0400EE5E1C18B170D309D17A8C79918449FFDD945F33C79DA666678C0EA732E3\
+1226BF56398B0C0BD654F286F00ACE0184C486440433D76E74E3ACBB933F5D:\
+E2592235FD61589C07E26861E34B75CF
+8910E1CA14F15DAE918DAABBC4C7555417ED6F8BED1950CF7B6B321E14D82AA49296\
+0DA9068F8B24A0C061EA41FF7C7DCBC797B4CB1E0A35C8F86E33CA0CD558E93E:\
+C0059500DCC36D2C1B8D07D521BF9047
+FB7B50ADDE9FF5D8DEB65C4764DD3FF42C15F498D65018583F224734DF414C8E0523\
+5B406BBF79FF32EAA14DC9599AEDB4A9F201BEF4AD2D324F1736EB95F9B70BCD1B:\
+0E2496AD1385C0695F1123141170F9DC
+
+:D41D8CD98F00B204E9800998ECF8427E
+61:0CC175B9C0F1B6A831C399E269772661
+616263:900150983CD24FB0D6963F7D28E17F72
+6D65737361676520646967657374:F96B697D7CB7938D525A2F31AAF161D0
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+C3FCD3D76192E4007DFB496CCA67E13B
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465\
+666768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+D174AB98D277D9F5A5611C2C9F419D9F
+31323334353637383930313233343536373839303132333435363738393031323334353637\
+38393031323334353637383930313233343536373839303132333435363738393031323334\
+353637383930:57EDF4A22BE3C955AC49DA2E2107B67A
+
+D9C7DD80BE463DCB2087E3BE65F0453BEBBE1B6A3440CD10CF26B60653F00C16B92CFAB17F4B\
+E6F2A7A5F463D1558653DEB907EEF6579BF86ECB460A252B7D92C6FEA35AE8267332E8169284\
+86B1AF0AC4F61238A8A2D37E7648A9B8F3E6E972CA989C6C6FCBECCA418650DD5D31EBD1E6C3\
+1288C0AD0EB3DE61EDF01863EC11C2BBC4D03D78407999EC1A33F606F1A49F6BF1E626FAA2D5\
+7E4FB2B6838B349C28B32E90377D71FDBDED640E21700A0FA6475F34462098FFFE1F76E3E824\
+09C86EFAEFCA4599E764B682FA4CAE0606D39F8F87CD29BE2ACAFEC9C0343A4ECCB8F43B1100\
+49AE7B74EBCF01567A86F3B3EF75D38874940BB142FD65DEFD1A0ED4C33086915E46F85306F3\
+4CB7A110D68365C830B822330784EA44C168D9428065B206B34721EBBAE49B840AA74B0354FF\
+B1D744A29451A6089C3C8B2C7F242BB9A83894F311ABCBAD2D0F614687D935E5703CE323764A\
+016AE97D841F7122BF6BD101343790FB3FF889DF86F770B4825BDA11FDDA93BC1CFD2C0D9CFF\
+907330BFEF4758BDEDC2012B025561A60B659B4E9E4FC458EF33F7D5529A64F10D87ECCDBD26\
+0AF5F3D76E069BE60FCD10274C7B4E199E8A9E85F0D6565939808E51B52684CA76D5F83B515B\
+8C4936ECF342B770E1D910C55347527EE495E6B16423369E781037CACBA212C5A7380789EE16\
+8A90FB2B291B975005F1ABA7DB3B9D950202E168CBC8DFF5FF951E28DC86E6FEF0371911CA1E\
+94CCEE27E42F7EE907273B2E87438D3520D1DE94C70057FA79816E5BAD7A840FFF881BCD3C68\
+0543BCC19E847A3136EB84EE7389E3978E122FF782702D6BFB1C26ADE57570D15DC8408CC132\
+E8D647D8B318FB76E8918D2513AA9E62F64E4EA3DC8D618E9A596F2B6EA8D0C55E2791A71392\
+8A7D6401B533CD86048E3581EA8F60FE8F94F6FD5B577B73BA339AA8C5B4CDD093AB895D6F9A\
+A5575BE5C9FCDC461A1E9DC50F31938779AE8BE160476AD65FC1F7FF9601B07E48CFE676686D\
+D772999737D0264EFDDF546167F4393BFAF26CF29801A4D4CEB04A5A551332DAE0014EAA9E09\
+0260CFCDB547883CD0A622102AD1C1B975353BBFD2F1C98C555BCC4DC26631AEC0E9FD70F609\
+8785748F5E2D3A1963F99355D05599C180FA35920E48CC0594CA3F3B1A05883B28B73EF43FFB\
+BD8A0AB4C4EAAFFE5793B415B957CFB27A46DABEF173B316BFBA466023C7C89EF4A5FDE003B3\
+602E722C9E2E3E624E2B130A024A2B6CAEC46FFF282412BEE4F28CA4ADC6822219D76BA77F91\
+1EF8F9AB52C5066806A1D47EBE40045F1DB3590BF0128A56CC86943670FF83E8D4E120F6E4D0\
+082386EBDF83488DFEE827371C773A2B7A03ECDAC24EB977A16361353DDB164ABBB1908CA2F2\
+BC694E141DACFCB241746786FB24C04D2DA7AC188436201B3556ED2D6874B0AF6227AA072B51\
+BF8699:\
+EB16D2E1DC85C8EC527FDB6BDF228A63
+
+[RIPEMD-128]
+:CDF26213A150DC3ECB610F18F6B38B46
+61:86BE7AFA339D0FC7CFC785E72F578D33
+616263:C14A12199C66E4BA84636B0F69144C77
+6D65737361676520646967657374:9E327B3D6E523062AFC1132D7DF9D1B8
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+FD2AA607F71DC8F510714922B371834E
+6162636462636465636465666465666765666768666768696768696A\
+68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+A1AA0689D0FAFA2DDC22E88B49133A06
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465\
+666768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+D1E959EB179C911FAEA4624C60C5C702
+31323334353637383930313233343536373839303132333435363738393031323334353637\
+38393031323334353637383930313233343536373839303132333435363738393031323334\
+353637383930:3F45EF194732C2DBB2C4A2C769795FA3
+
+[RIPEMD-160]
+AC:FAF1685349FE8B832BB2FF1CBA482583B3560F3F
+E9EC:C4EB5003F5FC64E122194EF6FBA841B30B1E8761
+74524B:D5904A1D8BA51B972BCF6D00681A5F0306C57AC5
+E233E3B4:9CEA3480EF59215C514C4FFF9B813677120AA8AA
+445A2F97AD:6AE5414CBE327CDD20FD8887F2F94D7B69222AB7
+A242802B76EC:5DCA1535835D75ADFA1B204C5CDE68C2CA8F1D67
+CBEC35D2FC21E9:C9809CA68C9013F34B7525936DB84B5737C591DA
+E8F3385F8B210A7E:497049F4D70E7B42A3F30582C27CC22DA5A51CD7
+61A82B5B622C48F6BE:DF01106CAF345F6E084DC5A46137EAD345D445D9
+4AC97BA5461EAF9228FE:C44507E89C39B4E9965FC9610B6B82985B1A2B57
+0E0B7D71B3CDF458B883B5:39F567E3B8A7AE93BE5AD8E35067D8B2AC81B9CE
+43A4A8265FB24F3279D6CDE3:F6342D8150996D93CA43369A69A502F14DDE041F
+5CC368C293058FA49906602624:893A6A07EE0A2669BAF707ED3BA2376125EF9654
+0A52FEEB91C5D0355FBB35E93F5D:5162732EF94AFE500679F550CBECF8043B70ADA0
+A3FC5E1467219DB6ADD73F59808955:3DD7B8C0D2278884B5A5C22A3CAA061131A5AD7A
+ED45B0BC151B3A739D710AB3AF72A32B:5BA207C3A45289463C98A21E2138C3758D2DDC4A
+AF7F01692A1AA195E2A3856DD936285F2B:D744FC79D37AA33E16C60DD7973B7E0D1E790828
+5028D7983E49966980AC8A564CAEDDCCE890:5906BECDAF00A5C700D548EFA92FB23FCD1C8D6F
+C17757BF03B8661B4407D06E4E47E8B6C678FB:2B7202910CDBD3CDA240AFFAA5929D6F82FEBC48
+5C4172923580ED789714245E42FDA873F405EE97:\
+053DAFE5970069C38F5575A54C4BBAD3FDC34DBC
+74F77522AD9FBC0E45DA88354EE4F5552EAC5F02F7:\
+0B72DF59FCC468CC4BEF4B0A77DA59DD4EA4486B
+33A75FB9CDBFBC9A257B122BE7ED337BD65CB1FFE9A8:\
+1B8A94BCEFE1E6CD9000A70AB342FE7930E62220
+8D7042CBDCD336C86E7732A1E633BDCC137380AFC37D25:\
+F18C667A28AA595890E689D6CD19FAE3F9FB7D7C
+D9419BA075C613F701E19DE6449E21A22FE4BB58067A5B0C:\
+D656A0F985E186388C2A211AE0EC8EA30B059505
+8E5A281FA95E7E9B42EC0CB0B9A35B54851257AC78494078B4:\
+AEBECEDAFAD9EDFDC204AC1303D14F549EE12CCC
+3E01A429466E67653B7B07751F8E497929A0DE5515FBA7D69FD6:\
+1640ABEE310D1860D7944F0B9929D3E4264AD358
+1CF65AB71AD544D423CB904F064A5D227A01761D6A6188296201E1:\
+0181503434C565B41EFF7C432E220BCC290F0A71
+5781599B64981D4657B3C4751DA4D7594BF446E386621EC838C30D84:\
+07D728840AB1449D31CBADCD5466D887EDFD4650
+44C392B435A8CE90062F7BA756D23FD7A3582F23C61DBE8A06BCAA2B62:\
+4ADACCC7626AABF56320040E42174BF284D4333C
+053AEE544BD93733C6FAA8AF9B89D1D7C1067832273F23EB6BB5D1D7ABF4:\
+A993D46BFD0705CB8692F6D6B88AE5DCB20CBCCE
+7A641E5243317176E497DDD286E47A2A36DEF6451A4A44AEBA12C03CFEFA57:\
+C0CEED6AC5A60323EF0B6D07535AD5264EEF0AFF
+3BD0AF34C27EFCA58CE047F265F1CFC8BE60280CBFA57225AFE6B353EC1B1B86:\
+AED53C23187ADCF3C2D85FE77AA3FFA7CACC85AD
+5C861109B9A1FDFB6E9B61737461F722E6582C94C9B406DED106DFF2FBACDF5B07:\
+CA900EED8F00A8144C60756317CA7B23FE5797DE
+D0416B0BA3B19EE355186AC2A09ACFE91964F229DE3D4119AD5AB4A09CF0FE10DD2A:\
+B2421A5314D8311C18773DECC2798300A36CE63D
+F7077210023297CF642C3755338EBD2CA234C22269FFAD31A7BC6B12EBBFFCCEDE293D:\
+797538F704EF4FB5D7E93DDE8B9C742EAB19010F
+169ED88895E743A171581730D9CE32B90E557C2AC178F00AD15C13B2639BEA59AB5CF95B:\
+2BA71C7B2BE43AF1825A3BBC7DCCD104A8F8AB74
+747EF1D2FFE2942444429B7B6D46631C7BC8C00A63D44176014E8594D9F2E09451E956B0F7:\
+5EEDCDDCCAB146BA30C9613D5B4825DDF6D0DF57
+546E13EFD694F71819385EE6F9A8022EB57B0E6173AD2042984AACBB6CF506102317DDDA6773:\
+5BCDE7DEE110935114F5422194178110A0C8558E
+8D0AD66F63EE8211654EB12362F5CE0F7A0672A3E77A0F3FBB6E6986C13ABD2DEBD6\
+E7F916FC7F:54FD721965D4C6DBEBE9E3D2B5A334957EA3F0BC
+6120F98D23DDABF5CA10022CF22A58CC89CD516F6B9AD1901A6C450B89569BD75B6E\
+D43D1AB1ED1F:560FD1CF282E07A4FBBCB495EA33C550CEC1CC1A
+7497FEA1D85825B29DBECE7C90F52B1B4760393693B31F56EB366571D49CB6B0EE85\
+4BDE58BAA64FBE:B61AA965CC9A9A1AE9A7CC0087E7417CF942A0A2
+2470B0926239D1A1B94F85204EDDE011000E3D08DB9F59E86A8CF7217C48C5DBE5CD\
+00480FFE00A22B89:81586567893FFA39A8079018F46B9FF14811C590
+56199F4131AF9AEF9BB9F1CEFD8552E75E1B607770A461E6DEBA3664972908DF469B\
+7E065D0DB531608171:6B74A4AB1C06E029004F14DB759C344DBB770B1B
+554809F00123973A8308B8D3D5F10EE4E5514DA51F615E1F606957E1FEBC87BA9C36\
+9F6ECF29F99CDD57733F:FBF816D9A81A8605487F6529255DDC43D031065B
+4315B59DE93EC8AB4BCD8EFD4FEE3B87CA4194C24211EA0E79055DDB1FBA7511203F\
+D56C0154AE12DB25ABB434:F465D07419A5F3AADE344BA5D64A5133EBA1B873
+7C2D0A5131F7C83789B1CBA64E5E6B3485E3340ADA2135008FBF1862BF711C7A6559\
+2FD4A49C511E29CF910003F5:C9D8494FDDF45D298164D5BDA3DF18AB29434D58
+7597DB5290120386E158890C7BCD70DFFFC100184A8339F98E7EBB17B23B6A88772F\
+4A05F2E0A7B2059DEA991BF154:CE9AB0CF93F471AB913043DF76270514AD281EF7
+B17BA36D07623609ADA5CF2D8F878025F02C3A4F578021BDEC12345A53780C71FF9A\
+D5F280BF8E1039E5643389F478EE:2B42FE8018B985141E4EC9604F2C75D454155EE5
+AB1FD81A1D2128A9767132079C36929BD76336157054FA889AD09B117DD753166CDC\
+9AE51EEA15DDF8D7B3113F8534DF77:22954D720F8259B5F04D288A453DFB54712BE71C
+53FF3194FD863938021F2033F2E31F508AF10E8D0B309FC2E3477495141732BDBDA9\
+CBA44F83B5459FCA222A894783741C7B:544E6CACE0C57A4AF18F0913D951191869EF933D
+160EA25128E0509398038A0F490BA73C62A03E58997174594FDA1B45924F406DD3BC\
+E56253021B446D27ED16CD7AC0EEFEAA48:6A56C5CB8CB5F4E64EF06FB32D94188884682A2D
+F18CE863EFD88F83ECDAA3ACC57786AD1A961B31446436D4E8F86F5999D475EA783B\
+A3473D09C60D0CA6FE3D8BC16D5B5460C296:\
+D85DC07C16A44C4DEFEF238EBFDB7FD14C73A788
+890D6A3EB3EAA9C75FB27D643257A8196387A5A49556CA3E81351B2668E56FE1D0E1\
+5BA1139C59B48F879664F6CB3B80A9BABA6DED:\
+50F41FFF64A49D8753883F71792305A0EB0ECBC3
+370A044BC71750BBCD57491DB54DD6335F426299A3FDD0FBF6C419856CF2FEC70FBB\
+AAF6AD0ADC2B31681BE7437F1DE7D02393034E00:\
+A31C9760489983399EA803BC7945914B7CA59142
+64BF8D78E7E1BA0F32F6D4D4F1AA68B12965A7F942B2B152A47869750DDAB6F1F33C\
+82BA1E75EF76F1B2D9769016CBAC063717FB06184E:\
+E2401F5AA89927A7F51D4D6345B482B135EDBD32
+F434CDF6BE6104121A533FB7F7D4F100FF1F0F6DDAA76297A32BDAE535CF040CB38B\
+E51CDDB96107E1045CF24444BF482D9EA131CD163A53:\
+D95AB29A9F3C2A2DB6374FF7A0DEECEE521BA792
+1B99BEB5458C96D9D402D85CB1ECB797D352AC8C04F3FFACA76A33B365CEEDCE9ADB\
+A53A5BF381ECA73D863DA273FBC47FB3F9A9F6F25829C7:\
+220F85E79731C094C8D457CF97296F89EFE404E6
+034A75357AF6255F0B55856FA240FDCDEBAFADBFBCB500D17E1830A3D074B252AB27\
+77333A9381D63DBD4DB685A72A67E41825B331F0E183DAA9:\
+A0671C3BADC8D07C59F6551017B00211B3C35B9C
+9C17DDD3617C5522491DEB7FF1BF56076ACD10EE7C482D606247EBD6D67F8062A3E9\
+ECF29D938E04879C062FFEA08C2F87F3BE840C50294FFA1DE9:\
+47FAD7E0D17A05345E130FDF458071900E90371D
+147C4FDD4BB30F38661C0A4C57CFCCF5DE5369B089EDCB74AF24E814AD4BC17A466F\
+BD2501E745AE16D2D0C976D3DCF2F93E2E7088733BC6F4013F28:\
+FCA67427FAC3BFFF73FBC789A4D8FC0058B1729A
+719F6946F69E185FBDD545EF118F9527630025ACF9B62DF5C38E69C9855C7B63E905\
+EEFD099E0635D2C40815A01B5EA79585DA3E4F1A2EC97C46DD1F00:\
+7EEF5539213A672C7599B489B0F80B954B0E9D1D
+997C62CF0780FDD3164780D38BA784905E4A87BF1DA252E13F6C320040193E5CAD1E\
+AB40A6DB7291DF54952C1DBE3B76541856D2B71591D0794435243372:\
+7E882963AFD9163AC13F7E4C1A7DCA9FC4C6CCF7
+D93D8E8987E0D01BDAA37B1AFC53A07C5A7F46273D1F77A472D83D0F9D9B241599AF\
+C51846C16E33D1C1E2E532BED264C49B2A9919F324834B097509933798:\
+FD21687491F7F8D2A8EDD82DB8F08137D6C1499F
+CC54B091B967D610BE6D6D889F909F843419091CDAE2C4447B8C830045B12760964A\
+D8D05EB0285A428BACA3E7B7398A37F7982238288732710EC97B5E32122A:\
+BB391A32D4F84199A444F6E9476B908209044624
+61B9077FD4A0E2E73060B4B26E86FC7A8131E0E305A5D874BBCD28BEDFA46FA84DD8\
+9431FEF6E16E4B5B3781956DFDFF1C1843DB12329F6C1C365F9A91B3A1F15B:\
+E3D6E5F7196B310A56089E76220A59D523DDA37A
+9CAFFBB1325C6579B094C4EE8F5B1EB9CCDC5EE861FFA090E055FF2CE6323295AFCA\
+2DE193F15E5FE64AB7AC655B9E99145CE1786F266BFAC834A0FF367FD174540C:\
+954D88771139F64710E8F31A0B990E8A1E569A74
+BC15671078B9AD440EB3C16FE28A33216DB848F19A289A6C805655053311A2299F9C\
+7D091D3AA130E0DF2E318E75402D54528A9C67FB4B14D754D4DC41E1C06787669E:\
+69F3A729309B288EE077582807DBEEC2ED5D4360
+
+:9C1185A5C5E9FC54612808977EE8F548B2258D31
+61:0BDC9D2D256B3EE9DAAE347BE6F4DC835A467FFE
+616263:8EB208F7E05D987A9B044A8E98C6B087F15A0BFC
+6D65737361676520646967657374:5D0689EF49D2FAE572B881B123A85FFA21595F36
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+F71C27109C692C1B56BBDCEB5B9D2865B3708DBC
+6162636462636465636465666465666765666768666768696768696A\
+68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+12A053384A9C0C88E405A06C27DCF49ADA62EB2B
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465\
+666768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+B0E20B6E3116640286ED3A87A5713079B21F5189
+31323334353637383930313233343536373839303132333435363738393031323334353637\
+38393031323334353637383930313233343536373839303132333435363738393031323334\
+353637383930:9B752E45573D4B39F4DBD3323CAB82BF63326BFB
+
+35B8A2F1B5F332F159AFB86212DCC4DE02B3FBA3794B0E5FE74A4ED9F1A55F55AE7711C6FEE3\
+178A410E3979D8B07594D769AD733EA00D64DCC1D601B871F918F1FDD914C2B6F9EC49B8AC13\
+A62A07E1091E0DD024E645BF3B602B4706583060CF9502E4EA6911AC9EB90E13816530B7683B\
+ABAAE225781440C35E8031515C45D5E4F5493FAED6B0457DD661B713895FB9D22646ECAD7C07\
+187B65AA508FE4F5B15A5C428264910143581512DCFBDA974902037D82451E4B1E12AD3364C8\
+F848E2B2A7D53D25F30C06AA6C62784DE8B8B6D097559C62D340C8103D51E0C303B1781F5A95\
+AA6AD1B7EFE3DB9E8D8BE9D1271AFC4DA9B0928642818965C922DDBB0B0A53E6D2ECE3672E95\
+68D0E285177BC5E5A9C2349788F8987267AD5ED26092A552AD3674344DE7FD79B9E33B855DA4\
+7F8CA0A70EE806945A6417C92C97CDC14C6BD9B7B25A2D89FEB62C594FD11A7CF3BEA1EF3018\
+B26B0E401EA8C7B8F07DAC07B77ACB78C3F45A73BA9FC32301EB3A19DFF000F3413AE0E92548\
+1D8F93D387CD458D749BA848BD4A92B9B7AEB0E244E479ABC4A85F50E94C7299E06BF0DAA158\
+7F49907CD94C426C33ACFC31E08D183A4353A36D8C6D39AAA1AF20519629C01A45BDCD60B115\
+CD490E9873D74FBEA994B75BB7FEE9F2167850AFAF42873D44543E3D6359A0A0A140705D4021\
+DE256AB12C38184BF822B9B69D7FB059C32EE332D86AB9DF26D1CF832381555CAD1688A362BD\
+B1F2982A55AAA37E5137B95B5961E8F354EA30ECB13B98DC697605556DF4C4EEDE6593016B7B\
+C30862C55C6651DA8A3589DD3E9EE42495374BA7E6C6BDEFF8CC078559DCD99581061348B13F\
+AE03259832EAD8BB84FAB48EBF725C6C5037539FC373791F21D34B56DE04A6CBC591B798B7CA\
+E2AD8BD5BF9E963559C981286F26802FD1A49A5A906AB814B34FB514A8ED0FEC7B67A550A59F\
+BEDA7B0685E69ADD13B68A69E070CF2C9E8D6CF4CAEE4ABA732BA20A8BA6C3DB8BFFD392CC2D\
+14D46367D451F0A3B77A411B128224AA473247C4A9A446606CEA8414E9C09DE13301C8E60B2E\
+E51E9801E1CFFC6E9EF283238E2AD209E5D48105D48044BFD28BD9F32C53D5D37CCB158FE597\
+983CBB45A05F1B9148F25772ECF3667554247CDB2A95A99E06275C36C6E4FD779DC9F8FA4575\
+16EA4CD020F6726E3A32DF65E34BD85DDFE16B285A0AFB0F3E2DD8954A9E636BCA5CF7FED181\
+B041D14D223F10AD0DE9E23372DD7A61718CAB6B9CC7C1D88D98697356811AC0B834228A299F\
+6EEF970E11D59E9FD307DACD40256AD7BEB203175CCABF70D9137BC29E2C7B0494C3FA6D338B\
+027BB993E870B02EC68A08EC8A24BD163D5AB43411AB7BCF1A09F64A7EAFE15A0C350F5D6F0E\
+68C1A83FECE5227112F8E6F8EF11149B3188970A279C9559BF11E7A4EF9F72C9C1E9B58EE48F\
+F880AA:\
+B48C57CAA63FFCC261E4B3532E75CBA497B4FB6C
+
+[SHA-1]
+:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+A9:19DA91F2603889267DFD77786E07A5B8F067D62A
+97E8:D617ED3AB073B4E7A53D2A238D7DC55F26EE3888
+D45C48:8E7E3C02A55608B637C8AD621E6AA933821C40BD
+AC42E6AA:FCB240AA79C665358ED174887E186220F0DA2608
+B520B2C214:0374FD36056476A85427EA2F7B1412D65A17D64B
+9E2D7971A47F:DA4106AAD290AE4430618FBD3C5D1FC6C66ADAD9
+F1EA1C9B787BAD:B234020692659C3DEE19F7E75390984DD7E7EBBB
+22BB11D0A3DA8661:A307CDBBEC5297114EC00193E056C0E30B15B499
+C70BCC3952C8330A17:57AFFC668D529B05EF9FDCE03448AE6B4848522B
+24B2BFC2E6D47E0467B3:393C606D9C41D743BD234EB62D36A381151FA8FA
+179BA867948A881232F2DF:F01A9954C602AD6A295512AB1FF58AC0AFA3CD1D
+0DF890F7B14B4A8D16B76AFE:5CEF1B50663EED91BBFBDA9EB7F34757AC5AB330
+B0DBE17E0D80568C0AEC5E39F0:22AA3BC193DC2986C10CEF2E5AA4C673883D32D4
+AFFF20DF4873A1AD68AA924DD5C3:21337165D43D02685C5FEC0CC1C73C44DD99A072
+BCA74FF24F139C9952074F9D16F6CF:9F48417F472141A2CD49CB3CBB4D3544EA76F949
+9779CC9003344147C0A718C6EF20987C:C7255A698F731CA134BA102982345CF0A305AAF0
+06CFC48642CADA4A5E1A4BE7D42AAEBCB6:044581EF47C9F2DE49F71B284B7D80631775A6E7
+8A68E58F72C5DE3A63FAA08DED9C89435372:E485D9B0FCED9EE033A4B4759D211023638BFAFD
+9AE8D4749CAB071975A18F45A49FA950B13A38:5BD5DECCAAC74D57D7CE628ECFB973409B364982
+F1413BFE7319315A7A7FE2D32F6E564C9186CD8D:\
+633002546668978822CA81A44E0CA113EC95C088
+58E747CCFD7781CA99755B24BA4EE7C13B59095796:\
+BBAB138D0A3369D67C9ABD0A1E0583EA6DD2B402
+90D6D80BADF7D52A7513892976D6C5BB28D8562E7748:\
+8F9D0D4F0E8F208BE8CEAD973776C9441C9202CB
+E033E25A7D550BEEBA3965753D86D4AB982EBF0621FA8A:\
+0B2EB3B57ED697BCA7D73E18A479FAD38EF99ADE
+0EABDACFCD5484F3B4C3D52D38E3E80CEE792B0CF600E2B6:\
+1F04BBA35687BA07375BFCC645E2DF26BAAC2294
+C6A3FABC7ECE7AE5592A107C437F80B1EA24488337F1AE6BA7:\
+A5E8F975C621FE415E49BFACC94C189E644261BF
+DD5CBDA778F532D63FFDFD67D0A5F4B0262B4C505B4BA0F25882:\
+CF03D0BA50F9E569103B85BDF43B949E907EF0C3
+389CFE2CDC0B55DF41C1C704FE9D58585B9E5757FD71415F73F073:\
+00B0AEF6D2BD6213175DDB6B4E7968039F70AF49
+45B1C7013FCF2AA9928B166F9666D3E76B61DF676DBBA7420A159BFF:\
+AB5CE29466A6BFB2DFD93DBDBAD389A0B7F97C1D
+1F1F4B688D24B30C8146D576156A7FC3149C66682B28C97EA157950B67:\
+18A9AF9587796E9E8493D20D8AE6F2EC82103352
+0F84EEC636A3381757004310399D3B3F12F97605B701A9038EC04B1CFC81:\
+AD05B1D89788743F97344D1C3AE3BA9499353371
+AEFB942B4B7A9BDFC9A97C447F7065E21A917F5393EF14150C5569CFC28DE8:\
+939EB0F17269FFA80738F66B3B45011A04A679A8
+8BCCF096CFB773326D7487A06D217A2471E709DC4C60614FB5A7E481381982DF:\
+3B69259D2E5E00F4208E8D2CC84D798A33CC1514
+232F3F1AFE834DD615BAC06A2510D1852E946F34B9E2085F7A36FD8844511F461F:\
+DFA0A9DB29A68171E01A6C7399B90F974A13F940
+704452E58745BD09D159F6AD40FA9B8C7419A2AA188D8B3AFFB00AC34EB2E304A0FF:\
+A099BC7BBED72769786FD913F61F655684031F93
+A62B2098C1D208024EA91470C903F8426E5D8F660C1DA268D0958E4BC11D2CD98F3835:\
+D2DEEC7774B67D924D131224BF6C908597F99178
+BF7E4F3FD269AC9CEEF6A08DBB5CB5BCAB5AF7080B8D675A7332F741EB9E17963E9BE157:\
+EEE037F1DA86921B491CBBF048B9BD872418DA9A
+FF94FEF100BD0056A37830E6B1DBCE8B832EBF819867932D46BD7495BCC5CE2E9DAF08F1CA:\
+97517C81813BCAA6BEC71CDE13DB4FA44CF4BCD2
+88EDF78F02C8E36CF0CDA3D07A9B1485CFA8AE44884E290461A22D599A7F30E3A88E52F019B0:\
+44FB2EC4643E984CDEAB550BA1383CD6E7847CF6
+7FE04629976A8EC967733E95F2BFB79DA1A126DC5CEF391291320A57DA487D49EE7C\
+4247F8A932:782C391A16A08F98C32C780D7A1F2570A7675FA6
+97807FE1CA7BBFD000A057A70A6F6F026ADD4EC3D50AEC664A2BF970C0D0D36001DB\
+B7231640ED9D:C06024CD60C3859D653B5ED18AE949ED7C43C05A
+98184A0CE7EEB9C8DFE36D6A19FD668A3B6F0C9A493835D63A70A4340AB6F8A7ABEF\
+0E5E09E4807334:7B7EA4D0E3AA0581B1DA3838ACC370E9394CDDF8
+33347AC8506D2C2F74C458B2AA0BE72CE38C752A4623A62DB758A9A6827287B364CF\
+D4C077F0D1DB9034:A1FF355DE693851B9A62D77CDC709826B27D6B3A
+7DB60CBEE84BDD9B357951A59C724A757B90D77D85D61F5B90FCD93D101DF697F490\
+4EA0F2FA1CA7BD7440:2409204F9658D8BB4C8BFD10420BD576FD7401FB
+AB8AEFD1533F3F07DA8BCAFB5C0C12E6BA7364A7EA2525796924B075242C22FA0028\
+F97B670DE6ADF935F082:B3837EB32A441C2C10E112677FF1569D2C6372F3
+890225FA3A7D120C325EEA0A0CF4050833C62C527B6A009CFFCA8DC2094135051B1B\
+C8ED9F9ED37B5DE16B4052:5AB7E0AC97C202630A54BB3BEA5F485BAE9257C0
+5D6F1CC0ECF25EAB98398A20D8278F84DE663FA9252361F01AA3F9A0D4FEA71CC86B\
+C63318A5E3019A6FD96851C2:2E3E5F3488A5D2C8C02A3B7E566844F35C0EC2D7
+0ED8D77EDA25AB5B9AF72F39A49B688B595D79363C563FE8F0265DE2FE0E490B4A2E\
+C86DC789CD0B05716993500C19:F4FC59ABA3C8D6F57DBA4F865DD24666251AA2E3
+89837C88BE7FE04FF3364AB6D455ACA1860D5C11FFBB56E16F817857CE0E3EB8106D\
+9FAC60FF571B181C86A830EDF292:31FB958B1D0935E46891EB09F8BFB99CA6809C5D
+D5E0D6AE8AB7A630EF2206D5160338C7AACC6A5CED2E8A3AA224626F1BD16DE547FB\
+822CD1FB0EA84C1259A427BD1AFCA8:69124A48D475B5110EE562C59131DA40707F897C
+A9CB3047ACAAF1A2AE06231A4DB46E28EB76694EA03A5FF78FD3C36797CB74259621\
+324F2897D80CC8C070454E55C341A3C8:53F6A0A6DD49C2D58413FE55A3CBF334D559A03F
+338ECBF06225FBA761755EF7F9147A1AB2AA696BDF2516584EBB948192C6BD240902\
+451FD5E6ABC48B017A71BC608C87DE1623:CD0AF641834C8DEC7CB735BA31CB674AF90EC3EE
+552150498BEC425BD0DBA052C9DD61714CDC22B1DA7F915FA7286C8CBB7D722342E6\
+91C877B748DBC369D4333F287587206EBC2A:\
+9B658AC6B9BA14176CD55F3AD40EF51722F25FE7
+6467642AE2A5C9D1A98BEAC2567A7097F00624AC9FBC1A7751487417EC33BDBE7E15\
+97E0205A7F85B10A06B7F8CBAF33E41B3FAE28:\
+48514214D5442EA393C2F29A0B632FC2C76B3221
+80C293CA96261C78EE05F7D666AA2D4C84D30A8B66EFDB0E34B0625E7CD2F691CD4A\
+92D07D66E22E837853F7DBD5D34BE1AE02501083:\
+E2E5864D1B24C5E8C1A2F8E54F80C942207DB2AB
+6FECF376F676C90422AD0A6440EE8EF2CE1F4A4F5AF46868F77013F8A582D465F09F\
+18ACB8F1052E603E4634AD345A63495C80ADD64940:\
+22C6DA67A1B13AB8D11DBA2989E88258CA12CA2E
+B6CFFE9D40FBA3830F2C20248690AB0862FBD8B1A5EBF832965F2AD7E8BF3C74A930\
+62C79F9CD16DE48043A69BFEA723035A2C81FF118184:\
+A517711BFA20D7324C710DBF3C5A955EF465926F
+47C63FF1E5AF57CDFC0307BCF453F528E5767CAE52117854E9036F20286D1C1BCA27\
+70645B4794BD5047EB59F0EA5F751243AD8EB5FA3F69F7:\
+533815F09B700B11A674EE0647F8E320F79A5ABD
+995C78E561CE4F9D9B9226C01DA4C55B5C4A1D5099027B1123AEE851AECA3B70CF54\
+BC7A74A4185D3781EAC76CD63718645A8F15CAD1911F529F:\
+62E81989C86A4AEE3A9DE5114AB72821AB7B1150
+F713F0C9CDF3A28629861AE19C38B73664352AC6939C976AF92A673857AE48DCEC04\
+E8967EC5AD8245CE062D8AD5FE5E92F39F5DCAAC9884F8B5CD:\
+79221ACEB0F387413AF24481A55633E54DE4232A
+DEF310EF52F8839F15BA13C8A5B90815867AFDEF25247FA10B6AD03E70952F5AD0B9\
+836012F119315C43C90DD6B5D018B3C75BB01659535588A4C17E:\
+136C5C9F49B4C0C41E87762878846279E167D8C5
+4FD13DB66F140B6DC804F9EB821FB82800976070D59EE4C035527EEECEC97E1EE5C9\
+973F1A25362A84BEC6EAA38A47078CBA24C6B7155CF76E30C22199:\
+988A4CE4FDEE20041D30AAED622BF1CA4E01C5AC
+57BD9E7BF1647FEAC33DA17BA902FEA19F7FD09E85CE23BA02EEC263A321580423DC\
+0872A9F794838EFB820A8D3D3D2AE81574F77825B70C569568A31EAF:\
+BD95E63B9EA0ACF05710DDFD13B77D518BE21CB5
+A222082AADDCA13A7CBDF9A9AD12BA723456BFD8B515A6A52F8F861226CF94D5C3AB\
+0B2A151A3B557DA8DA72585EFDF60FCA469AB30EAB12B51571E906557C:\
+03AB52978F19B3FA870D84814002A305AC58AC10
+89AA2C4D4F81CECE57B0485842B0AF8B857E7609CC0F29F0343A5B8A09181A63C8F8\
+4251C497136D1916DC5634DA842793C1B648A381B2534DA78E78E7898BE6:\
+BCC5DCB8FF9EECF6B282FDDFC8635B1923C2BAFA
+94CF076400B9C2911C2C2C1BBCBF30E50157EA88CEB3B4966E61A18BA2C58ECA65BA\
+C7952E5A629E0DF53F4B8A9B031765A639C87A4941E42CAF4A5572AC05B085:\
+EFD01DA5BC765BA961954C2D7E5FF2104B1FA58F
+B8847AA6FE095FA629D090307AA2D686C7D628B12D63BCFD8E4F6BE8CCE039E8CB69\
+683B8B70DE74DCBA93A019D0B459D707C4F2BE8EEC9B0280F6ED26D99BD454FF:\
+32CE1A1F18A2FEB9CF0189E37D8894E7CEB70CDA
+676DD8B7DDF731349BF6238C855E8136AD59E734B20ABB500018925966EA4E076336\
+90AFA11E57550766745BD3401459373A418A360D4C4B9275714679517C73F60FAE:\
+81D2AC8F3A2C92E190ED1AAA0F7EEF24579E697A
+
+:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+616263:A9993E364706816ABA3E25717850C26C9CD0D89D
+6162636462636465636465666465666765666768666768696768696A\
+68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+84983E441C3BD26EBAAE4AA1F95129E5E54670F1
+3AC0944F60DD6E0988CFD28AE2103952C6070DC0A97EF7AAD20B5F9CB8FBE054368BF91C6791\
+CE900B487B309615F29F1A045D210D226D2A018ADA22D27C:\
+968569B83FB232766A9967C9FF6E9B162BF49DC7
+E5EF4476F1A0C19631E317518F0E64A8AFFF579A264FB3B00B55C108F76F667919731882DE49\
+05BA0493AA17E1F39115D136F9A037C704F5D329CDC36CA728:\
+170A3BF2284128B2A02097800B6A3FFEE825BFE5
+AF500080F6905D82050886CB27371AD9BDCDE1D3858E66395CBD034D8A69198AD33A762534CF\
+9C7F39B22DE123AD03ED25BEC4E73FE05A1CC506B8D06D32B0F3:\
+B79E4B7FD2A3DBCF5E9BF50D91BF651FF713DC65
+0AEE08E2D291A3D500160C74FD6A8F4C64531FCB51297E503BC4ACBA07ED629AC3CE70D1EBE5\
+B4730DDF29DED06B9E9CF8EA963718CE4BE9373C35BC1188A5F054:\
+5CD361EC04BF2F526803FEEB81E729AF5807EDAD
+08D2CA90EB94205F40277F2D47DE7F52025B31B57F62DBD443BA005D6301FEE4F4DC57181C72\
+69F1FBA4210E26358C48887C09C4317CD890315BBD563C948173F6F1:\
+F788C706B2B67D4D698C2DCF99E45B1A8541D3DE
+
+F0B38F0505089A926595ECA3080BFFEE28929EF769577D91A8E5E2867B01EA4C58A4CE62101E\
+D2DA38D608C266346DFB5FC14800D618E958A8572B35B23393A11613C85CD443D2B4DE78D5A4\
+D641E70A23467D7CB4BBBE362AFF2AB35D1A075CA33EB619DDBC9AFC65586F077A3ADAE4B115\
+0E0FE9274280FB011F0420155E5848920D9E25D1BE66DCC670D4395FE2847848E04645C13B33\
+4E4BCB588E069510BA6D014115579706670D2D93E3080466CE6BBD07CDDB9670ACF68E4E36FA\
+17E03EC3F88910FBCE247128486B0475775AA5642812B44F444A14DC547E7D5D98527302261A\
+13FEB8BDB4A7A0FB221E1D08388B4353AE2DC7E3464969DCF12B17ED0A5E549B8FF8A8956FE5\
+FB69C1AB428BBA8CAE7E267F52CAFFFD2DCAE8F9B5D448AF548C7BE88443649254089A281A1B\
+7537896D7D4C97399F0513E3976981843E20C15EDF14378DC4425CAC30ABF7CB034B6D4AE213\
+360CCDD1C956ACC0D437C177C983EAEB9FB5F3A5DEB19CE3319C9368C2A7AF4B077A6B1BD417\
+F17E2CA36BBDA826718515FDEBBBEB5268801073457F8AC83ABD1EED888BBF218DCC4554F67E\
+FCE107A216B0540116691DAE98F34FB218969728E3165425C7EF1BB033329DDE4CD98A731772\
+7F4E6E24AFBDF39F79D71CF3C6B93E75E007500874BDD94F7484C15EC5F5A509FA4AB14828B2\
+895B0280C554600DC9834D23F824E1EC4662CC62CECDA8B9F9F31A6B4D589E5F95401644800F\
+FD2132F60CB45A91940CD420ADAA5DB3577F41E099EB79708F7A0C61D37923B503DE8810C55F\
+80AF43B4D87060070BBA4A948A41DE58E7A7DBDA9020D77F290A62F1DE6E47521C495B6EFCA4\
+0FC97FED9DE7389836F82BA05FEE66975121C38A6C7926EAED407E37CAB7E7005A891A93D88F\
+68DDE4DE9FEAE55D6FE86FF34CAF9CCD7263085C2CFA67A77FD28659FACC7AFB9734159D35C6\
+C96A755FCACB2048ACB7756696F4E481328A5A93A9D0BF8AFE0C31A98E1E6A4BED0C6CA661EB\
+7218F9C5792334121604587A86423B652FBFA1638C96CA1715164C7D074117ADB267923F06AC\
+AE45B493438BFAF384CDF7697AB0E0B75C6D21C6FF1139752143FF84F4652BAC47D44689E7A7\
+3A87E4491C0D9B8DC60D546E4350BC66BCF814ED004F202AAA9CE6E4638ADEA6B485CCAD2D55\
+FF7A597DE0662C746AEB34B36C7D46FD47A67DB75363D314B40672A6289B60F1D444090B606F\
+73A9CFE3BA46BBD3D5E629AD508D6F6592DA126E9400377D7DA41295DFA37E5654FA841A5616\
+E528C65952846DB40FDF29DB7317B8FEEE5B0F670EA0198520E58FABEBFB68BAD63709C5941B\
+A9F8DBB064EDC425B263DF4573EB6E3CADD080D9EF7BCCA048F60E163448DD6531B6B9F8CDB6\
+6CA368FE6AD9B651C51284E51253A3B64FFEE4806A0A88840BD61CA888345648D7743A060A36\
+105C88:\
+8395ABC1B17BA7BF947145EB1DF1A2050C8E78C3
+
+426F74616E20312E372E32332D707265203F3F3F3F2D3F3F2D3F3F0A68747470\
+3A2F2F626F74616E2E72616E646F6D6269742E6E65742F0A0A54686973207265\
+6C65617365206F6620426F74616E20697320746865207365636F6E642072656C\
+656173652063616E64696461746520666F722074686520312E382E300A72656C\
+656173652E2049742073686F756C6420626520737461626C652C2074686F7567\
+6820736F6D6520415049732068617665206368616E6765640A696E636F6D7061\
+7469626C792073696E63652074686520312E362072656C656173652E0A0A596F\
+752063616E2066696C65206275677320617420687474703A2F2F7777772E7261\
+6E646F6D6269742E6E65742F6275677A696C6C61206F722062792073656E6469\
+6E670A6D61696C20746F2074686520626F74616E2D646576656C206D61696C69\
+6E67206C6973742E0A0A466F72206D6F726520696E666F726D6174696F6E2C20\
+73656520696E666F2E7478742C20746865206275696C6420696E737472756374\
+696F6E732C20746865204150490A7265666572656E6365206D616E75616C2C20\
+616E6420746865207475746F7269616C2C20616C6C206F662077686963682063\
+616E20626520666F756E6420696E207468650A646F632F206469726563746F72\
+792E0A:\
+D233D919F2B5358520B725F427C4F35B5D866FBF
+
+436F707972696768742028432920313939392D32303038204A61636B204C6C6F\
+79640A202020202020202020202020202032303031205065746572204A204A6F\
+6E65730A2020202020202020202020202020323030342D32303037204A757374\
+696E204B61726E656765730A202020202020202020202020202032303035204D\
+6174746865772047726567616E0A202020202020202020202020202032303035\
+2D32303036204D617474204A6F686E73746F6E0A202020202020202020202020\
+202032303036204C75636120506963636172726574610A202020202020202020\
+2020202020323030372059766573204A65727363686F770A2020202020202020\
+202020202020323030372D3230303820466C657853656375726520476D62480A\
+2020202020202020202020202020323030372D3230303820546563686E697363\
+686520556E697665727369746174204461726D73746164740A20202020202020\
+20202020202020323030372D323030382046616C6B6F20537472656E7A6B650A\
+2020202020202020202020202020323030372D32303038204D617274696E2044\
+6F6572696E670A202020202020202020202020202032303037204D616E75656C\
+20486172746C0A20202020202020202020202020203230303720436872697374\
+6F7068204C75647769670A202020202020202020202020202032303037205061\
+747269636B20536F6E610A0A5265646973747269627574696F6E20616E642075\
+736520696E20736F7572636520616E642062696E61727920666F726D732C2066\
+6F7220616E79207573652C20776974680A6F7220776974686F7574206D6F6469\
+6669636174696F6E2C206F6620426F74616E2028687474703A2F2F626F74616E\
+2E72616E646F6D6269742E6E65742F292069730A7065726D6974746564207072\
+6F766964656420746861742074686520666F6C6C6F77696E6720636F6E646974\
+696F6E7320617265206D65743A0A0A312E205265646973747269627574696F6E\
+73206F6620736F7572636520636F6465206D7573742072657461696E20746865\
+2061626F766520636F707972696768740A6E6F746963652C2074686973206C69\
+7374206F6620636F6E646974696F6E732C20616E642074686520666F6C6C6F77\
+696E6720646973636C61696D65722E0A0A322E20526564697374726962757469\
+6F6E7320696E2062696E61727920666F726D206D75737420726570726F647563\
+65207468652061626F766520636F707972696768740A6E6F746963652C207468\
+6973206C697374206F6620636F6E646974696F6E732C20616E64207468652066\
+6F6C6C6F77696E6720646973636C61696D657220696E207468650A646F63756D\
+656E746174696F6E20616E642F6F72206F74686572206D6174657269616C7320\
+70726F766964656420776974682074686520646973747269627574696F6E2E0A\
+0A5448495320534F4654574152452049532050524F5649444544204259205448\
+4520415554484F52285329202241532049532220414E4420414E592045585052\
+455353204F520A494D504C4945442057415252414E544945532C20494E434C55\
+44494E472C20425554204E4F54204C494D4954454420544F2C2054484520494D\
+504C4945440A57415252414E54494553204F46204D45524348414E544142494C\
+49545920414E44204649544E45535320464F52204120504152544943554C4152\
+20505552504F53452C0A41524520444953434C41494D45442E0A0A494E204E4F\
+204556454E54205348414C4C2054484520415554484F52285329204F5220434F\
+4E5452494255544F52285329204245204C4941424C4520464F5220414E590A44\
+49524543542C20494E4449524543542C20494E434944454E54414C2C20535045\
+4349414C2C204558454D504C4152592C204F5220434F4E53455155454E544941\
+4C0A44414D414745532028494E434C5544494E472C20425554204E4F54204C49\
+4D4954454420544F2C2050524F435552454D454E54204F462053554253544954\
+5554450A474F4F4453204F522053455256494345533B204C4F5353204F462055\
+53452C20444154412C204F522050524F464954533B204F5220425553494E4553\
+530A494E54455252555054494F4E2920484F5745564552204341555345442041\
+4E44204F4E20414E59205448454F5259204F46204C494142494C4954592C2057\
+4845544845520A494E20434F4E54524143542C20535452494354204C49414249\
+4C4954592C204F5220544F52542028494E434C5544494E47204E45474C494745\
+4E4345204F520A4F5448455257495345292041524953494E4720494E20414E59\
+20574159204F5554204F462054484520555345204F46205448495320534F4654\
+574152452C204556454E2049460A41445649534544204F462054484520504F53\
+534942494C495459204F4620535543482044414D4147452E0A:\
+6ECC9C5DA3C61107935336EC58F3655DB0C210A7
+
+2020546869732069732074686520637265646974732066696C65206F66207065\
+6F706C652074686174206861766520636F6E747269627574656420746F20426F\
+74616E2E20497420757365730A20207468652073616D6520666F726D61742061\
+7320746865204C696E757820637265646974732066696C652E20506C65617365\
+206B65657020697420736F72746564206279206C6173740A20206E616D652E0A\
+0A2020546865206669656C6473206172653A0A20202020204E202D206E616D65\
+0A202020202045202D20656D61696C0A202020202057202D207765622055524C\
+0A202020202050202D205047502066696E6765727072696E740A202020202044\
+202D206465736372697074696F6E0A202020202053202D206D65617473706163\
+65206C6F636174696F6E0A2D2D2D2D2D2D2D2D2D2D0A0A4E3A204D617274696E\
+20446F6572696E670A453A20646F6572696E67406364632E696E666F726D6174\
+696B2E74752D6461726D73746164742E64650A443A2047462870292061726974\
+686D657469630A0A4E3A204D6174746865772047726567616E0A443A2042696E\
+6172792066696C6520492F4F20737570706F72742C20616C6C6F6361746F7220\
+66697865730A0A4E3A2048616E79204772656973730A443A2057696E646F7773\
+20706F7274696E670A0A4E3A204D616E75656C20486172746C0A453A20686172\
+746C40666C65787365637572652E64650A573A20687474703A2F2F7777772E66\
+6C65787365637572652E64652F0A443A2045434453412C2045434B4145470A0A\
+4E3A2059766573204A65727363686F770A453A20797665732E6A65727363686F\
+7740756E692D6475657373656C646F72662E64650A443A204F7074696D697A61\
+74696F6E7320666F72206D656D6F7279206C6F61642F73746F726520616E6420\
+484D41430A443A20537570706F727420666F7220495076342061646472657373\
+657320696E20582E35303920616C7465726E6174697665206E616D65730A533A\
+204765726D616E790A0A4E3A204D617474204A6F686E73746F6E0A443A20416C\
+6C6F6361746F7220666978657320616E64206F7074696D697A6174696F6E732C\
+206465636F6D70726573736F722066697865730A0A4E3A205065746572204A2E\
+204A6F6E65730A453A20706A6F6E657340706D6164652E6F72670A443A20427A\
+69703220636F6D7072657373696F6E206D6F64756C650A533A20436F6C6F7261\
+646F2C205553410A0A4E3A204A757374696E204B61726E656765730A443A2051\
+7420737570706F7274206D6F64756C657320286D75746578657320616E642074\
+79706573292C20582E353039204150492064657369676E0A0A4E3A204A61636B\
+204C6C6F79640A453A206C6C6F79644072616E646F6D6269742E6E65740A573A\
+20687474703A2F2F7777772E72616E646F6D6269742E6E65742F0A503A203346\
+3639203245363420364439322033424245204537414520203932353820354330\
+462039364538203445433120364436420A443A204F726967696E616C20646573\
+69676E65722F617574686F722C206D61696E7461696E657220323030312D6375\
+7272656E740A533A204E657720596F726B204E592C205553410A0A4E3A204A6F\
+656C204C6F770A443A20444C4C2073796D626F6C207669736962696C6974790A\
+0A4E3A204368726973746F7068204C75647769670A453A206C75647769674066\
+682D776F726D732E64650A443A2047502870292061726974686D657469630A0A\
+4E3A205661636C6176204F7673696B0A453A207661636C61762E6F7673696B40\
+692E637A0A443A205065726C205853206D6F64756C650A0A4E3A204C75636120\
+506963636172726574610A453A206C7563612E7069636361727265746140676D\
+61696C2E636F6D0A443A207838362F616D64363420617373656D626C65722C20\
+426967496E74206F7074696D697A6174696F6E732C2057696E3332206D757465\
+78206D6F64756C650A533A204974616C790A0A4E3A2046616C6B6F2053747265\
+6E7A6B650A453A20737472656E7A6B6540666C65787365637572652E64650A57\
+3A20687474703A2F2F7777772E666C65787365637572652E64652F0A443A2047\
+462870292061726974686D657469632C204356432C205368616E6B732D546F6E\
+656C6C6920616C676F726974686D0A533A204461726D73746164742C20476572\
+6D616E790A:\
+7B01AE4E25243CE9B4735729CEBB285C1853473C
+
+[SHA-224]
+:D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F
+
+61:ABD37534C7D9A2EFB9465DE931CD7055FFDB8879563AE98078D6D6D5
+
+[SHA-256]
+:E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+
+61:CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB
+
+616263:BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD
+
+6D65737361676520646967657374:\
+F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650
+
+6162636462636465636465666465666765666768666768696768696A\
+68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1
+
+3132333435363738393031323334353637383930313233343536373839303132\
+3334353637383930313233343536373839303132333435363738393031323334\
+35363738393031323334353637383930:\
+F371BC4A311F2B009EEF952DD83CA80E2B60026C8E935592D0F9C308453C813E
+
+
+8000000000000000000000000000000000000000000000000000000000000000:\
+84B3F13B0A4FBCCE4C3F811E0313E00DCBD27431C229EFF576598BE8D1AFB848
+4000000000000000000000000000000000000000000000000000000000000000:\
+94CE3F7973AAED52C6C446BCC59BD8D43B6695FA3FDB9E3D1CC47503A432D3D8
+2000000000000000000000000000000000000000000000000000000000000000:\
+6D0855A335802F0BC20946F3C48C05B6B98C14B578020D5F42A166B97FE6F59F
+1000000000000000000000000000000000000000000000000000000000000000:\
+56FD25956F759E64E853071FF01587C364EAF6286C97DA600E0BE78C701637DB
+0800000000000000000000000000000000000000000000000000000000000000:\
+067DC6A810183E9069F63C2020B692C122C8D58263ED7F5C0E531504DC3B6E06
+0400000000000000000000000000000000000000000000000000000000000000:\
+4B78063B9C224DA311BD1D3FB969BBA19E7E91EE07B506F9C4C438828915563F
+0200000000000000000000000000000000000000000000000000000000000000:\
+5778F985DB754C6628691F56FADAE50C65FDDBE8EB2E93039633FEFA05D45E31
+0100000000000000000000000000000000000000000000000000000000000000:\
+01D0FABD251FCBBE2B93B4B927B26AD2A1A99077152E45DED1E678AFA45DBEC5
+0080000000000000000000000000000000000000000000000000000000000000:\
+0CAD7906B177460EF96D15A612E83653862592A190F78FBB7C09F4AA89E616A7
+0040000000000000000000000000000000000000000000000000000000000000:\
+E30C1BA805347BC13F4E4E4E82658AB2C1C97BEF72C4F3D555590784C64B3587
+0020000000000000000000000000000000000000000000000000000000000000:\
+3B5C755FC2A3A868DA0A668B2704635B13E3DDA0ACFD386B4C025ACB644400C3
+0010000000000000000000000000000000000000000000000000000000000000:\
+9F911FC19889661AF03C2E9849208883BB606BEB75BB6C162FF63F65E4CA8157
+0008000000000000000000000000000000000000000000000000000000000000:\
+3EC07F4585EF5C91814F7DDCAE396DC42156DF82307C46C7AE977CFCDDBD04A3
+0004000000000000000000000000000000000000000000000000000000000000:\
+7E8BBD09E5C09DE409CDF71C4B39F59B350B4B5DEC4A45D0B6127FDF873B4602
+0002000000000000000000000000000000000000000000000000000000000000:\
+1616C4B5C8DBB446F269F2C9705B857B4A4315355A52966933E6B0E51DA74A76
+0001000000000000000000000000000000000000000000000000000000000000:\
+36258E205D83BFAD1642D88F39A6CC128CA554016DE9CF414BEF5C5C4DF31019
+0000800000000000000000000000000000000000000000000000000000000000:\
+9B885490F45E3558384E94FE2C64773323AE14BCB8F9E8E02B3FED18EB930A30
+0000400000000000000000000000000000000000000000000000000000000000:\
+3BFB6EFD3AFC93BCD7ECDE51304456C2DC0C697A337DE3FD611CBEC3B3BCC53C
+0000200000000000000000000000000000000000000000000000000000000000:\
+1D8052462938001AFE80A3A2DD04EA8B28AEA9F613849C5285401B7DF2E8D604
+0000100000000000000000000000000000000000000000000000000000000000:\
+C15F125ADA3B323C7D79FB6D1C96D87CA7890C468A209C66F80B5EA223E5E533
+0000080000000000000000000000000000000000000000000000000000000000:\
+4C49B88894D742530818A686961A640CA28692C2E2AD020B7CFD86DE3E594068
+0000040000000000000000000000000000000000000000000000000000000000:\
+85BFB6E1A0AA50099696212DCE8A0067F4FC8A2C4DA0946B6106BE1DD01D7D78
+0000020000000000000000000000000000000000000000000000000000000000:\
+5D5E9793D0F89CC3A709D2FFC1B488F1FDC7CAADE69BA027EA7B44F18BCD082F
+0000010000000000000000000000000000000000000000000000000000000000:\
+1EB50E78E6DFB0A4725FB71BA0443C3129A6822213F3D40DA2439FCD2BCED580
+0000008000000000000000000000000000000000000000000000000000000000:\
+F7B7700280839E9E0FF8AECCB3BE5C586DF0BD6B7BDB4AC8C8ED45AE3EEF3686
+0000004000000000000000000000000000000000000000000000000000000000:\
+2E0D44F2BE93B23ACCB8E7680FA0B58E25F48E33334481A9297C8F5E9428F326
+0000002000000000000000000000000000000000000000000000000000000000:\
+672504FFC411A43E4E9CAC5A44BB62DF4A7DA166D18E4D47607CEFAADFB667F1
+0000001000000000000000000000000000000000000000000000000000000000:\
+4A9F5FF8813D3465074FD633B060B49318D9EE98B3CF3B3F4A3C903E4AC66396
+0000000800000000000000000000000000000000000000000000000000000000:\
+C68386BCDCEF8EDF31D9ECCE2A34E006F49AE1652FF0BBDA847FF6601F762815
+0000000400000000000000000000000000000000000000000000000000000000:\
+A5FE20624689A0F3378834E922989DDAAEDAD5BF51D3B1F5E84D63778A8F43E7
+0000000200000000000000000000000000000000000000000000000000000000:\
+03DE22D278E3BE1E8FDB7DA3EE6679E6D514DEE8FC118FB27A91664CDEBED8AF
+0000000100000000000000000000000000000000000000000000000000000000:\
+D1AD35A94F018CCB8E40A06FED17DB11F0638DA3F3E638108ADE5D151ECCCE23
+0000000080000000000000000000000000000000000000000000000000000000:\
+4D205614446CBDF1A8160A7182BCB24EFB32D725E016BB91D84C1E7DF55201AA
+0000000040000000000000000000000000000000000000000000000000000000:\
+72171D3BFE9863D702B81AE9C69135AD007200A5A7B8DC419F884C944A309DD0
+0000000020000000000000000000000000000000000000000000000000000000:\
+3F0A6EDF24B8D9F9038B828D2F45F7625123F8A1B07E39892C86FABB2FE687D7
+0000000010000000000000000000000000000000000000000000000000000000:\
+C9BF3EEA4D22268BD1EF0027A5E1E398F0D6C4A8190BD99AD869A8796EB0CD4F
+0000000008000000000000000000000000000000000000000000000000000000:\
+5706ED5B0DB45898C5C01F4C4B5360043E1029CA00B33C33E684C27C30222A1D
+0000000004000000000000000000000000000000000000000000000000000000:\
+ECAB997B21788D277CFCCC07AA388C4B199AE63D6E606CDE28328EC209B794BC
+0000000002000000000000000000000000000000000000000000000000000000:\
+58D2C35FFAC68BCF336A44B98AFF5740823CABAEE65865C608D487FFCFFC95BF
+0000000001000000000000000000000000000000000000000000000000000000:\
+909F22C2B34103BF854580C5F2C4F64C2520AA57B492E422D1801A160B6C6E67
+0000000000800000000000000000000000000000000000000000000000000000:\
+A0FC0A816AB024C9DED26D9A474B53C66635376400FB3AB117BAB262321A1308
+0000000000400000000000000000000000000000000000000000000000000000:\
+9DEBEDEDB5B1B6A2A2FABE9104C8D3F425144F290490ED788D6B6A19994C703B
+0000000000200000000000000000000000000000000000000000000000000000:\
+CBBF98775780C3B92BBC871C1D5137107BE63933D0F3FE1BE7AEE434AA5509BD
+0000000000100000000000000000000000000000000000000000000000000000:\
+C1B245D91A44973947297E576511B7FC55CBCD06159CB0F111101E601B36843E
+0000000000080000000000000000000000000000000000000000000000000000:\
+6986E93DBC3B044D949945C0AF3BC35ED63915E0268E9395D552D4ACBC5A79B9
+0000000000040000000000000000000000000000000000000000000000000000:\
+5FF28A82880765E64116AEC484F2B3A0EC1DBEACEC2BBC78737E5504A94C2DF2
+0000000000020000000000000000000000000000000000000000000000000000:\
+76DBB5BA9EC438D93638BFA8F62664201E29BA84BC6B1AB704D9688E89431503
+0000000000010000000000000000000000000000000000000000000000000000:\
+80D3EB7836CB04382BBAF764EEC343F07C9618BDFE98E01FD2BA2958902253C0
+0000000000008000000000000000000000000000000000000000000000000000:\
+89FF132255600368DE253F025BF92BB5AF9BF4D1FFEBB25575CE30EB77E4E4A6
+0000000000004000000000000000000000000000000000000000000000000000:\
+2012053E7AE584DEEE9B71A412FCC9351C29961E9D3972615C10EA59329A1D3A
+0000000000002000000000000000000000000000000000000000000000000000:\
+414DAAED4DEFCABB5A3E4A82131B914E597522EFCE506AF7B294A14486B40ED8
+0000000000001000000000000000000000000000000000000000000000000000:\
+BC52EFFBBB3C6F7C66AD400B707CD98930A828F6B5BA3E0C71D706F42000E80C
+0000000000000800000000000000000000000000000000000000000000000000:\
+6225473F5D9BAB2A34928D9F3C9891C990982718319F2408D07670A7460D783D
+0000000000000400000000000000000000000000000000000000000000000000:\
+B2B2DEA4697FCEB6CC466A7859A30C2BF5C6E477F6F442A1918802BFE707990B
+0000000000000200000000000000000000000000000000000000000000000000:\
+873D4CB3F71AA7704660011B30E9B573AE0E839CF0B102633F197290F19998A7
+0000000000000100000000000000000000000000000000000000000000000000:\
+DA24CF903BB826BFC026106F54EACFE50C0E8319BE205B47E181642723DA2305
+0000000000000080000000000000000000000000000000000000000000000000:\
+AFE22988EC899E95704B9E87082EE375F78DB2687478CCFBC2DFDC1E121C49F4
+0000000000000040000000000000000000000000000000000000000000000000:\
+497D0D90F9A77F1D67F0567E67F7ED60F9D324CDE0DB266E51AFD4B25CF24FA4
+0000000000000020000000000000000000000000000000000000000000000000:\
+0845CA0AAAF8F899437303A1C4A24101437DA7C90D1147E653295BA68CED2D1C
+0000000000000010000000000000000000000000000000000000000000000000:\
+A1BD23817C23BA5910B9EE8404740A0CE3E81DF31A5AFCD172B4613ECB1A9B65
+0000000000000008000000000000000000000000000000000000000000000000:\
+13EA147D01F645B321E81F39D15CE4AEB9CF2E0373D6FCBBC1CA7CDCFCC40C29
+0000000000000004000000000000000000000000000000000000000000000000:\
+912E64C464286112AFC2CCD15E638707F293D8A8133E03D6795E96562D471183
+0000000000000002000000000000000000000000000000000000000000000000:\
+1AF94AA75BDB9B976831E1A6A1A7BBD14697F710E514AC4019B33815F167B555
+0000000000000001000000000000000000000000000000000000000000000000:\
+E13FCB8F649438F18530EC00DAA36A110FC641A226C3DDE990F82C4B561DA4DB
+0000000000000000800000000000000000000000000000000000000000000000:\
+C8387BF8DBADF1C9BA583A8D27B620F4BD13CEE4EA2EF98BCB0E1BDFD6F3D8C8
+0000000000000000400000000000000000000000000000000000000000000000:\
+79A257D3B1260EAE2C407B55A33C28E19777C185B5254AB051442D2353B35464
+0000000000000000200000000000000000000000000000000000000000000000:\
+6552EBE29B1B037562F1888498BBB208054638E97C0C625F127C1A203EFFFC65
+0000000000000000100000000000000000000000000000000000000000000000:\
+2D77A6F16003C7F09E6DAEA5CAF4E61B9CD822CDF21A33F300EEAF33264AC67F
+0000000000000000080000000000000000000000000000000000000000000000:\
+F5B8339CB1EFC7F3FCB94DCDF8BB3EC191EE016609082E47242EE6253A05DA9B
+0000000000000000040000000000000000000000000000000000000000000000:\
+BD7CDCC82D46856DB3E580548999DFBA0D8BD38E0EDBB797188DE335D933C8B3
+0000000000000000020000000000000000000000000000000000000000000000:\
+D340DBC1256765FEA41925FDA295BDFEAA1055CBFEAE0FDBA8608E3116D746DC
+0000000000000000010000000000000000000000000000000000000000000000:\
+49293309D25CAFC914C11063C2D1CD286A4500D519B11B4FC98500EFB85F6D9C
+0000000000000000008000000000000000000000000000000000000000000000:\
+6091339D451E8F830A46C5CE040717C9D06F36AA4C5A9A8A9F1622384A6EB694
+0000000000000000004000000000000000000000000000000000000000000000:\
+6CBD66038B54D94A931006EA23DB48C300E1384CE7FA0F7CCFB8EFE2FC0AC4F8
+0000000000000000002000000000000000000000000000000000000000000000:\
+8A1A30A8F415D71BBB03C5AE3DF4836CE54CBCFD78816BCE86E0B983B059E972
+0000000000000000001000000000000000000000000000000000000000000000:\
+8039AA16A81B23F2410448563996605C13766D1E7417F4BDFBD8AD5D0D33554E
+0000000000000000000800000000000000000000000000000000000000000000:\
+7549D699D3D1989D940600F25501C243E9AF21FE51EF2ADB8358C159C9E9663F
+0000000000000000000400000000000000000000000000000000000000000000:\
+831F3936CACEA264EF4FAE2E36B2110F6729BAF434E61A6EE379D0C014F2DAAE
+0000000000000000000200000000000000000000000000000000000000000000:\
+013EDBD6B8EA866D7AE7F553C079663CA22ACF4E21E64F0085ECE1B449BD10EF
+0000000000000000000100000000000000000000000000000000000000000000:\
+D9B846387CE55AC512A1E2807AAF6F8DCFBEB462ED6D4176CC56A0B0BDFE1047
+0000000000000000000080000000000000000000000000000000000000000000:\
+0528B59ED6EBBA187A69C3C41E88120B1315CEE497BB6731191DC05000CD1E78
+0000000000000000000040000000000000000000000000000000000000000000:\
+1EBA730823BA27ECADE25B38144D339053446006EC3F66131AEE473EA3FB9E04
+0000000000000000000020000000000000000000000000000000000000000000:\
+B8AE9BF4E323C6EF3BFE75B6969EBFA68FE6C14B06481CF06869D12C555DBFA9
+0000000000000000000010000000000000000000000000000000000000000000:\
+C89944EF4886967A517064A212E38BDA5FCA80CA54E18103A75D54A6E230C694
+0000000000000000000008000000000000000000000000000000000000000000:\
+452E5D0AF5DABFDC5C74868D916F1E390A7354937785F1F6D4D0B1D72F06BD8F
+0000000000000000000004000000000000000000000000000000000000000000:\
+87AD2F7F2E5DB1BE3BCC982EA058955AE34A3CF0CBF87DC4813AE5B0E6B3C517
+0000000000000000000002000000000000000000000000000000000000000000:\
+FB4635AC471CBEBE2EB3367F259232D7B62B8A6342E1BF73294FE447C3B8076E
+0000000000000000000001000000000000000000000000000000000000000000:\
+9ADA02E914EB181D22E7F6D9B3F39804A0F758BDA23995E567E3A1EDFF0B60E8
+0000000000000000000000800000000000000000000000000000000000000000:\
+D41BC420CD25BA9038A4E1D1C4CEB1B05D993D0B68095F46B4BB524B72F15287
+0000000000000000000000400000000000000000000000000000000000000000:\
+329954D9CB855DD7798E587403353DD69CEBF91A5020AE5FC4D742656E4CAD0B
+0000000000000000000000200000000000000000000000000000000000000000:\
+7FF37D832DB4DA7CC3473FC3F0B263949630F21DFD8522A544994C5A3B12644B
+0000000000000000000000100000000000000000000000000000000000000000:\
+7F27BEE720048484188F774D660D86276B6383AB2E40990F181E5349DC72FC52
+0000000000000000000000080000000000000000000000000000000000000000:\
+AAFCA0AC1D6C80EE40FB43FAD51F006D39DE0A101449B450A3E0FD9D44FE0230
+0000000000000000000000040000000000000000000000000000000000000000:\
+941A10F2333950E3501C6229C085A54185E55A1017C9B8DFD9187B614371884C
+0000000000000000000000020000000000000000000000000000000000000000:\
+FA7862ED967E19EC63F91344184684099C7BD734EDF810509E2FB308FE5DAF16
+0000000000000000000000010000000000000000000000000000000000000000:\
+E5C92E4C6590AD2F982267BE2B13E110C44D9C69E93516F594B7E433A0E93AF4
+0000000000000000000000008000000000000000000000000000000000000000:\
+0656DD98DED7D764BCDEE4E96A9699E70974AE77CF72F166B7A979B707F1878B
+0000000000000000000000004000000000000000000000000000000000000000:\
+1FA047EFED4A196A9B538C099E50B67A0F537897FCA6F0AEB386F43E65D48A31
+0000000000000000000000002000000000000000000000000000000000000000:\
+74BF1C0E1DA85358FA86ECBBAB419C9223F41D47702583593CD01539E861DB73
+0000000000000000000000001000000000000000000000000000000000000000:\
+846C472932FDA94B56483E7A903C6545B5CDE4FE5D0A2FFA03B52AD53570D54A
+0000000000000000000000000800000000000000000000000000000000000000:\
+E78743B610392B52CD122071F9071A8E9C35AABEC0BD63C73C5FD12171838B32
+0000000000000000000000000400000000000000000000000000000000000000:\
+4A435A44A2BE1F40D8E6A1F7C332C5330EDE4E0F55505304E571B4443255A5A9
+0000000000000000000000000200000000000000000000000000000000000000:\
+18122CF13AB2412FA65CB693713794DE6B30403B65688234A6FA940FC6D506FF
+0000000000000000000000000100000000000000000000000000000000000000:\
+BAE3E67A9D5505A5685EBB52B8510B44315C0FAA422F0EBFD4EF3413490248FB
+0000000000000000000000000080000000000000000000000000000000000000:\
+B7F300939FCC6EA45A8920C7B8D3F18E753C0076062E4A499B69AF96328CEAF9
+0000000000000000000000000040000000000000000000000000000000000000:\
+7E5AAFC21B6238FFFC561283AC2B592C1F5BB35237061629AC9A4AF7153CDB3A
+0000000000000000000000000020000000000000000000000000000000000000:\
+B98F3C9FA25CC07AA02F7456E15C7707DA6702628AB589351B8737A814DBCB9B
+0000000000000000000000000010000000000000000000000000000000000000:\
+B01668CF19C69B22737F7409EDE201CC37BF1B23FC0630FDA9364652171389AC
+0000000000000000000000000008000000000000000000000000000000000000:\
+A8BBE8B393AB0E3D0E822C8AB9F23B8F1C985E93E6EC17050CC6A0D82B27A078
+0000000000000000000000000004000000000000000000000000000000000000:\
+FB246A9EEC0AA00A971416718CF0BB789F44496183642024C5A3C8043C5E72F0
+0000000000000000000000000002000000000000000000000000000000000000:\
+5937034D4C6184BC32CEF38ACA4BCEA720F3D3061191D1E0EB5C84E242C7DEEF
+0000000000000000000000000001000000000000000000000000000000000000:\
+C0DEB1F9A2060A3CE111BC6C36DDFDEAED2713229EAC55C75608B9272E10B78E
+0000000000000000000000000000800000000000000000000000000000000000:\
+08CC99BD1C9E6C2AC03DD17C7BE3F0D744AAC4144D542D2F4D2F3366837E030E
+0000000000000000000000000000400000000000000000000000000000000000:\
+B5026F002368EFAB1FC2AA97BE628698C41DB381B44F8BC2C8BE3635C8F0BCFA
+0000000000000000000000000000200000000000000000000000000000000000:\
+98A020137D37236B11D0ACFEC699107679EAF0339E8C0AAB3AFF1538296F754E
+0000000000000000000000000000100000000000000000000000000000000000:\
+A30B09A7870D5FCF10704CA8A00083FF4ED2D0B78F530161C698A0DC272C5F12
+0000000000000000000000000000080000000000000000000000000000000000:\
+C4CEF7219FBA14B0515FF84CA552273E471EFB23A26274778C11D0FB61805A8D
+0000000000000000000000000000040000000000000000000000000000000000:\
+0F70F20E2513A79AD1D153C98981D5CD21DE4C134977658D1C9C4B4367A73F99
+0000000000000000000000000000020000000000000000000000000000000000:\
+690A81F1FE0464FAB24A2E9861C24E52087D902B2DFB344713B42285051E5C81
+0000000000000000000000000000010000000000000000000000000000000000:\
+403E430C39EECA88D967926B543A06FBB68654C348801FDE7466F34A5579E2ED
+0000000000000000000000000000008000000000000000000000000000000000:\
+715623D0A82109017F74E8DE00BF5B700BC6C161CA403CDEB9A09B659268B779
+0000000000000000000000000000004000000000000000000000000000000000:\
+6E367FF2768A6D4C980D7D1B75F312663CB816E5C0191A8839F6F9E50A44853F
+0000000000000000000000000000002000000000000000000000000000000000:\
+81F33A1BC1018F2C4886865F55AD2FDDD891160D06717805F2687155E26DC2E4
+0000000000000000000000000000001000000000000000000000000000000000:\
+1C074CA4ABAF8B662D0C75635F84FE4ED9011CE476C45F8214F798438E1CB9FD
+0000000000000000000000000000000800000000000000000000000000000000:\
+003D837BBB718E13778188399EACD53DF9781EE8AD3F77BBD35F5B617D38AB24
+0000000000000000000000000000000400000000000000000000000000000000:\
+37212E518E30D555EA442EC7467B1E95DC06371C9784705D0D885D1C61981029
+0000000000000000000000000000000200000000000000000000000000000000:\
+74119615B3146E59D08DDDF07CF0614264D73F2118CF4A5CECFBAA691B005F2B
+0000000000000000000000000000000100000000000000000000000000000000:\
+3269AEB6831504CB8679EA40F749072951EB1728CC5E21E45FD0D6B423F6FA42
+0000000000000000000000000000000080000000000000000000000000000000:\
+D504FD065F8D2BCD3D1D3A4B298328E09F1CB44E3106D156477E992AABE9812C
+0000000000000000000000000000000040000000000000000000000000000000:\
+8AA4012B4573828D21C20AC64D18A6EA73DA0347B5D1A71442091CA48655DB70
+0000000000000000000000000000000020000000000000000000000000000000:\
+650189D78DE4CF754ED237A9DDADD9686B58D85D06D82E937DF6075F4CC87642
+0000000000000000000000000000000010000000000000000000000000000000:\
+D140E61D738C3298875886B8D8DE576E48FF5C7E9F4D0E66D0149D0BDEE19F49
+0000000000000000000000000000000008000000000000000000000000000000:\
+59E7ADDB5E068640DE3F8FB015017E7AA7495430D2533F87D4ECE9F7EE548FA3
+0000000000000000000000000000000004000000000000000000000000000000:\
+5481B8528EF488D0A4ED259244306AFF83145B7D675E159EFECE21DEF7561297
+0000000000000000000000000000000002000000000000000000000000000000:\
+671EAA12D76BE21EB2CED2F61AC1E98DF94C1952C2CDFC047895C74F15A7F3FA
+0000000000000000000000000000000001000000000000000000000000000000:\
+6CC4F0E930B34481D03A4134331852EAED66667E3B3D8605F7CD3777551D2B6F
+0000000000000000000000000000000000800000000000000000000000000000:\
+58A971DF91F981284DFCA88C6A21AB89D4E6A12E0D8A1E12BB585EB697D597E3
+0000000000000000000000000000000000400000000000000000000000000000:\
+AFE25F910412D62DB9FEFBAC5CAF3D240153725FFF1B8D85FF835BD418028738
+0000000000000000000000000000000000200000000000000000000000000000:\
+AC99C31BFF7B16E8916E8ED5C969CE7DD1B7A4A009F2F03EA8FB240B1AB16CE5
+0000000000000000000000000000000000100000000000000000000000000000:\
+85A6CECFA95E645104A45E2E34E98F92039ED921ADF65E78631E270548521637
+0000000000000000000000000000000000080000000000000000000000000000:\
+1C686E808A38E9D3D800AB94F8EF98888FA959593FE9A78850EE01CCABF170B9
+0000000000000000000000000000000000040000000000000000000000000000:\
+058AE81BE2477D2BB0EF309F69713D68196A0A9D758BE3814B565088FD752AB3
+0000000000000000000000000000000000020000000000000000000000000000:\
+5B1919A40F9A5AEF568E1E24B414A85C0D60D1DCABAA2CCECA09A91D78A91D15
+0000000000000000000000000000000000010000000000000000000000000000:\
+FFD4927E8C35AFD614A39AEC5654A8CEF3CFB47B737BCD55342BFDA0B9D81E53
+0000000000000000000000000000000000008000000000000000000000000000:\
+D47A6B8BDBA65DDF5820DBCB3F1733018CFA0A3A278540C7FBD575E36E20F063
+0000000000000000000000000000000000004000000000000000000000000000:\
+9D8A03520FC2F2653AC52B7C0DA06F5436858A811E5F4B2DB0B2182C2C8F6D12
+0000000000000000000000000000000000002000000000000000000000000000:\
+13A17E3E7C07F58935075A41B2B5B332CC64F7099E320430DBEF41685DD95B27
+0000000000000000000000000000000000001000000000000000000000000000:\
+9250C7028C00AAD64F1A1140F4DE8812608FCF15F3E91AB886C911E71BD41324
+0000000000000000000000000000000000000800000000000000000000000000:\
+C019BC0605ED4157C8D3E4761BC74D403558E426D04403B17C9923AA5A732C48
+0000000000000000000000000000000000000400000000000000000000000000:\
+524FCBE1456CE1D535E6E75098F7A817EEB99F6D3B77A9705BF40674E84AEAF6
+0000000000000000000000000000000000000200000000000000000000000000:\
+F4A5E902E2633F78A4AD90C9305DCA8CCFF31A8CE6FE8DC3755A591D201BB51C
+0000000000000000000000000000000000000100000000000000000000000000:\
+BB242C3D49140119969CE07F0021E400ECDCBDEB3FC8C92459EFF346878A6FF6
+0000000000000000000000000000000000000080000000000000000000000000:\
+362B9130763C98696ACE92E946F2646EDB7A9D419CBE12ABF9CB40B9BBDB32DF
+0000000000000000000000000000000000000040000000000000000000000000:\
+6BF88E66479D09985823F2B87BD7DFDDA415442B5132B2482F9B092CD3FBAA4A
+0000000000000000000000000000000000000020000000000000000000000000:\
+DF6777DF2585349325132C5A6AB16481498BF9A1957EBC2F113095669C7AFE96
+0000000000000000000000000000000000000010000000000000000000000000:\
+37108D63C635FF214AF8A98DCA6A3E288FA14EA8F5E8C52A583B6F12BDBA3CF5
+0000000000000000000000000000000000000008000000000000000000000000:\
+C22FAEF7E57A7BF3E344132436FAE85BD59A9BF4AE01DA2545A6EE3779773AF2
+0000000000000000000000000000000000000004000000000000000000000000:\
+A1947F12BD61D72067884D47AC2C8DF8541FBB4A9EB2D0F1A8F6997207819AE0
+0000000000000000000000000000000000000002000000000000000000000000:\
+DDA4ABDAD1290FD66A171D9724A409B02612F8606C58D85D530F30E7CEDEA3D2
+0000000000000000000000000000000000000001000000000000000000000000:\
+658FCE7342D3C8E1EDEBD0EF0B72612346500B72CEEB1AEED11845F1AD1401F6
+0000000000000000000000000000000000000000800000000000000000000000:\
+518EE98053E9D1F1F42F9E59DD74A6D9AA0D1F1FDDDD4F799134B4C111226D98
+0000000000000000000000000000000000000000400000000000000000000000:\
+1F2513F0CD6195005B81727F7784B1F109C2F680A5E3343A9EA0FAC21F35BAB6
+0000000000000000000000000000000000000000200000000000000000000000:\
+2D05A4ED553CBD1F532EEA35D158F01F2867D49A7120ABE733A5F6C2E5C92C21
+0000000000000000000000000000000000000000100000000000000000000000:\
+0BFC42AE0F93D32617BB3C7CF8E4A6515AA8668922E05AF39A27CAE39F9CA221
+0000000000000000000000000000000000000000080000000000000000000000:\
+C3F2631B8F76C94534ABDE0EB456EFA47DC43B08F7CDBE379622621B28458915
+0000000000000000000000000000000000000000040000000000000000000000:\
+9C15E4A671EB6E390BDB67AC4441DA8CCC9E56AFE28B8BCC928FC6F3E552569A
+0000000000000000000000000000000000000000020000000000000000000000:\
+EFD7A7E53F7F21FE9B9D4A5BF3BE5AE7ADB0947F8412BE25F7E88A45743E6FB8
+0000000000000000000000000000000000000000010000000000000000000000:\
+A524AC0D0DACF565BBA3B84015D995202E1F67409D63FE16D442CAF5C72C3D3C
+0000000000000000000000000000000000000000008000000000000000000000:\
+80073614FB76A09C3DD701E83BE717117A3694D05331B032F8104CA241F11482
+0000000000000000000000000000000000000000004000000000000000000000:\
+C475A4C797002B5C66A21DEF4295CDC4C9DE4F045FB0FCE7A1BDB977224BAC97
+0000000000000000000000000000000000000000002000000000000000000000:\
+6D8547CABF8F0AEAF7A9B3598CBA769F545C61E8873FFD6D5E7EE9C1C5527F95
+0000000000000000000000000000000000000000001000000000000000000000:\
+7187108D9F4506C15B5E6AD523167BD2BADABE69242EB6AEBCFE52F70874E757
+0000000000000000000000000000000000000000000800000000000000000000:\
+A195EAA4E6377B4C0360C343D52F82704BD85BC5905D669C5E4ECA7C1F028C88
+0000000000000000000000000000000000000000000400000000000000000000:\
+72C72361133DFFEBFD3EBBB8FDC6B76DC530AA7FF5E22EE709B65BE866DACD86
+0000000000000000000000000000000000000000000200000000000000000000:\
+20F3BF2E8F3876FA733F41CECFDA7C641CE579B8ACE9DFE06A64A4BA72BFA901
+0000000000000000000000000000000000000000000100000000000000000000:\
+D3B0F2A184D2AEDACC760448DC351B63E975D5E48444320733F19381EB973659
+0000000000000000000000000000000000000000000080000000000000000000:\
+25D380557DDACD3761FED7B1EF2AD9B2CB25EF263DDDC08E34646EFBB696F718
+0000000000000000000000000000000000000000000040000000000000000000:\
+7DF39F3B439912E4859500ED516F4096EF60A96911F626052B3315416C307F90
+0000000000000000000000000000000000000000000020000000000000000000:\
+D05070BC61FC95F05359B8B36C70DB0E3D5FC077F73C02CCF4310A24C91A0F33
+0000000000000000000000000000000000000000000010000000000000000000:\
+CD3683D700693575FBB3355F844458ED60B1A45294CD27CD380A9A10E660E407
+0000000000000000000000000000000000000000000008000000000000000000:\
+AB19432215B64F93A344F7E6A46B386C4AC159924AB4A6F366FB8552A96DBCE6
+0000000000000000000000000000000000000000000004000000000000000000:\
+1F6B7158C0B0A4311FBEF86E39BD812BC94207D154B9CB2380433F16F6821B7B
+0000000000000000000000000000000000000000000002000000000000000000:\
+E65A4E3567D420D98EF51C29405AB004A019D794C51A67A680F6D54F21F08E5C
+0000000000000000000000000000000000000000000001000000000000000000:\
+53382A486C2390F7FF94A33BAFCE7285F382BDB5BED4FF076D7A161B169D6B4A
+0000000000000000000000000000000000000000000000800000000000000000:\
+9E36673A278E023992B653AA0683CE64BA7CCE51239E091C80D98BC627B45A00
+0000000000000000000000000000000000000000000000400000000000000000:\
+AD51CB9156C8CB66C202133E098061688A0360EA0E5B49A9F47EB00C346EB1F4
+0000000000000000000000000000000000000000000000200000000000000000:\
+9DD8990FD868111F6854AC54D85BA38B9B0BE3E02037B4A3DAD2D0D9E89DBCE3
+0000000000000000000000000000000000000000000000100000000000000000:\
+8A4A51AEB3BFE9FEECD9F4AF22D2D34C534F3A2B127E959236407206A4E1DB2E
+0000000000000000000000000000000000000000000000080000000000000000:\
+32F59D1C8E62EE49BEDCCF59007194EEBBC698B888050723C5325A746463E3C2
+0000000000000000000000000000000000000000000000040000000000000000:\
+FCCD7332FBD25CE39EE7522F432185F2322EF05CF1F5E36A2458272FF1397A0A
+0000000000000000000000000000000000000000000000020000000000000000:\
+62775BB6A290E509389C0EA6BAE5C8567A0E034A813F9AD62666B4871D8FACA3
+0000000000000000000000000000000000000000000000010000000000000000:\
+264AF724EBD387076F1427EAF7D7E94734A209DDFFAB1BF455528D8BFB548681
+0000000000000000000000000000000000000000000000008000000000000000:\
+96FC8FF80897ED6F514A67FB4FA5CF9D53814E305FED248BAE6B5761A331E0C3
+0000000000000000000000000000000000000000000000004000000000000000:\
+F98B7C970726889639C19C75FA4E63BFF6D48063806A19EA4584B84F3C40079B
+0000000000000000000000000000000000000000000000002000000000000000:\
+76CA7485A665D0B76ABBB2909B193D8F8572C8DB77F969256480F63728ACA867
+0000000000000000000000000000000000000000000000001000000000000000:\
+8004B9B6A39295D73D00759682C72DE9A49E7278189CA9A1D704FFFDE8F8AECB
+0000000000000000000000000000000000000000000000000800000000000000:\
+98177F21E631C18FD21733C5BCCF33243970AC5EBDBB19A257DC96BF43D5151A
+0000000000000000000000000000000000000000000000000400000000000000:\
+DCE21D3195A4B65B3B2C3EF0A954A157785C8CA4FD195AE15BD7F420D9D5CE14
+0000000000000000000000000000000000000000000000000200000000000000:\
+EDC0E40C3027D41914BF3144A08078742B337B96DA8E503D4FF84BB6A8E97D55
+0000000000000000000000000000000000000000000000000100000000000000:\
+013F21DD7052786E2C338B57F23EC2C7FEB0C12F7B3B28FBB5AFFACA27103F51
+0000000000000000000000000000000000000000000000000080000000000000:\
+BF8362CE587255D74A374DE2775680C02A02B2106D05EB9B1EB83BC88A9C97EF
+0000000000000000000000000000000000000000000000000040000000000000:\
+CA72BC9BB4F0F6E2DDD3D641D94A62163A066AF9D77AC3937CB00D134DFD46F2
+0000000000000000000000000000000000000000000000000020000000000000:\
+6B42A2D46EEBC60C0238517A9F2B78BA27CE4B87ED35261FB0A0DEDDD39DC753
+0000000000000000000000000000000000000000000000000010000000000000:\
+D441092F524AE16D1339E78FB13892732A5975705F90F82E54EE09D80448E49D
+0000000000000000000000000000000000000000000000000008000000000000:\
+C7F6DFA7F3E4F92D6C20AEEAE921FA209685D0C20714D69A95D1F94FA41D097C
+0000000000000000000000000000000000000000000000000004000000000000:\
+300223DF08C84B22C569FC15ECAC264F9D1CFDAD758962B406C757FCA69D0A0A
+0000000000000000000000000000000000000000000000000002000000000000:\
+FB81B52E00690B2F03F8D410A357E582F6F4367D4359FE7DD7CC6C6A3AD24CEB
+0000000000000000000000000000000000000000000000000001000000000000:\
+BD5ECECE8B8CBC564A91294968C3BE209B15730CF7594D2B79BEE0D44391BE7E
+0000000000000000000000000000000000000000000000000000800000000000:\
+80179FB24A6EEC0173DAF26891251C3054EA8D7280F88D4C57A3F52B5F1AA388
+0000000000000000000000000000000000000000000000000000400000000000:\
+59C6F16A4878FC819F3A3CDFCF7C5A8CEAFE9231CE259A7F9E377E3D8B41C16B
+0000000000000000000000000000000000000000000000000000200000000000:\
+B18656E3D9D293F342A9A4B88884BD9A650D72368C1703B74ABD2D4ADD1B6A5A
+0000000000000000000000000000000000000000000000000000100000000000:\
+A7213DAEEBA47277122DFC9FFADBB36881C6FA9C89293D2291407522639E017B
+0000000000000000000000000000000000000000000000000000080000000000:\
+33D62D3A60AF659D70978E12F6AE01D6D62686965288B584796B6AECC37167B7
+0000000000000000000000000000000000000000000000000000040000000000:\
+3F2F1919206CFBEBC68DB1BD552D78AFF61F5AD296AF45F15145E176CD4E93BF
+0000000000000000000000000000000000000000000000000000020000000000:\
+4ACA600624783F035871A05365EDFD0D01A67C9DD59D38A68117474D81F4A93E
+0000000000000000000000000000000000000000000000000000010000000000:\
+9B352CDE8F0BDEFCC8B1F37D34B3641FF6F55C05FF5193928402ED95C986D1CD
+0000000000000000000000000000000000000000000000000000008000000000:\
+B14B9519FE51B738F81BA61AE48723835412B544F41E8CA4D3C2BE8B8E7B7ACB
+0000000000000000000000000000000000000000000000000000004000000000:\
+AFF464673EDD86FED0C0CC97BE3DE9375E61503680B17AC4FD44AEDC02EF086C
+0000000000000000000000000000000000000000000000000000002000000000:\
+B600CCFEC9DDAE068109C82B0B7BA3632501857EB23CA7860FD26F3BC1335697
+0000000000000000000000000000000000000000000000000000001000000000:\
+884AA440D0320D6FB74A8B02BBE5F7DF50CC4B83571523CDC4A2683776AD6218
+0000000000000000000000000000000000000000000000000000000800000000:\
+C20D94291275F858E53FDC834B0E02FD496145B8713F53555E863425A61D1E88
+0000000000000000000000000000000000000000000000000000000400000000:\
+B1087C12C70D6224460202DA3FA5B985D3D2B130F2347D6BC7DC7668856EF5B8
+0000000000000000000000000000000000000000000000000000000200000000:\
+BE7F81F61289AFD0E08467938F054F69D2795E570D0F5C7577125BD37D72069C
+0000000000000000000000000000000000000000000000000000000100000000:\
+D7E79AEEAEF9CDC5889C68E98DCC7C1D85172D0F183A62815DF0104CA67F3068
+0000000000000000000000000000000000000000000000000000000080000000:\
+ABCAB82BD056C3A975C8CC78B160B1A726EA2D58DC8775EC9CC1E97B1887263A
+0000000000000000000000000000000000000000000000000000000040000000:\
+716A3871C88D6C0D6AB03C6C925CA5B0FEC9816CB393BE5226E387048DC379AA
+0000000000000000000000000000000000000000000000000000000020000000:\
+046284F44965FFE307372B5EAA47D0DCFC282B13B1D13FEE3786A0A2173CA034
+0000000000000000000000000000000000000000000000000000000010000000:\
+0316CC9C233290D72C53938CF8D216E24447D95114C3F9BBF2FA508EEA9E72CB
+0000000000000000000000000000000000000000000000000000000008000000:\
+388A34BA91711C31E14675BBA6CC29A157237E2B1B6095B02A49373A8ABF43B3
+0000000000000000000000000000000000000000000000000000000004000000:\
+CCFC11FC56D48DAF0F233275E9E591B76758CE6099465FA3E8B925FACC8C1D87
+0000000000000000000000000000000000000000000000000000000002000000:\
+F1C19314208EC565B4E50664B650FC0D256B4EB5A177ACDCCEFC78BEF7543A6C
+0000000000000000000000000000000000000000000000000000000001000000:\
+954A6575B642BDDDD05409CF5973BA837F25B2E391950BE91FA23334093D88F5
+0000000000000000000000000000000000000000000000000000000000800000:\
+D8C9AE155F36F1EDD6A9A0FBCE9D8A2D97EFC4896EEAB31FA4B2A267F10F83D7
+0000000000000000000000000000000000000000000000000000000000400000:\
+E1291A0E2D900F2D61C7B915EC60CB2F26C58DE63B0DA7F1AA1F40FB609C7261
+0000000000000000000000000000000000000000000000000000000000200000:\
+18DA34910AFFCD9B1F0B80D57B2B545DBD3FCBB9327B0744553B0AE309D01F2E
+0000000000000000000000000000000000000000000000000000000000100000:\
+0B07727D83B28795BD6CBBCCBEBEA5CDEDF3430C407723FD2F5270BED6F574B7
+0000000000000000000000000000000000000000000000000000000000080000:\
+6580335A2908A8845A95E26E793D522451579D91C90A4C92D8667361957C4FA1
+0000000000000000000000000000000000000000000000000000000000040000:\
+34B59ECBD01296EA9FE6C2F1E22AD83AE34AD9917F762E5AE194700A95F5B08B
+0000000000000000000000000000000000000000000000000000000000020000:\
+8C7809B15F5525F59885E518A954871A34A4850A0C5AC531CB5564C91D10FA81
+0000000000000000000000000000000000000000000000000000000000010000:\
+A1F386B9AE9B170E1F02E3FA611B991E4A383E1D998FC03F1026028B70C5FBB9
+0000000000000000000000000000000000000000000000000000000000008000:\
+25E947AAA44B7574BCE0D0AC4D91D63489A7837F6AF73764EAB3CC83EFF2B01F
+0000000000000000000000000000000000000000000000000000000000004000:\
+1B85D67D1481C20BACB50AEA0C506AFFA04B258C049A8CBA641DD4D3A0ECE1A1
+0000000000000000000000000000000000000000000000000000000000002000:\
+CBC332EC5110FEAE214FF569FECA4BEF1B3CEB809F0E2362E3924A762153785C
+0000000000000000000000000000000000000000000000000000000000001000:\
+0193D8FF39177FC604D8C0E60D5495222DA10CD84D4AE6D12BF84CA923158B31
+0000000000000000000000000000000000000000000000000000000000000800:\
+B6A210AEB8D431276712B83DFB27A338166436C37B13E533E6A664BC0696E21E
+0000000000000000000000000000000000000000000000000000000000000400:\
+F1337369C5303A28DA9132C4562C7D1D7381E3F30575F05C72DD3E969CFCA5EF
+0000000000000000000000000000000000000000000000000000000000000200:\
+5BF54EC3CE05919EFEDDEE2AE288118DB06A3AED340D89CFE279D0C6927CD336
+0000000000000000000000000000000000000000000000000000000000000100:\
+084E640FA57CBF5F097FD08636FE5E98E23839D95C532099EFE1A7A838DBAFCA
+0000000000000000000000000000000000000000000000000000000000000080:\
+63794A3BF8875AC2C32BA6238D27E7E15E56A3B794B8D2D6AEC82FAEF2360E3A
+0000000000000000000000000000000000000000000000000000000000000040:\
+D9ECE2CD2214F52C55DCD9BCA56A900EC79C1343F12DF8A60F0298D255896B61
+0000000000000000000000000000000000000000000000000000000000000020:\
+9633190BF775667487569D0F5E7ADFEBC899E55AB9D62AAABE9F8754A3FA9C20
+0000000000000000000000000000000000000000000000000000000000000010:\
+A3ECDE0C1D9DAA6B7A949C87A1AF7963C69CB2C412FB3086C495F14630C17B7B
+0000000000000000000000000000000000000000000000000000000000000008:\
+38DF1C1F64A24A77B23393BCA50DFF872E31EDC4F3B5AA3B90AD0B82F4F089B6
+0000000000000000000000000000000000000000000000000000000000000004:\
+E38990D0C7FC009880A9C07C23842E886C6BBDC964CE6BDD5817AD357335EE6F
+0000000000000000000000000000000000000000000000000000000000000002:\
+9267D3DBED802941483F1AFA2A6BC68DE5F653128ACA9BF1461C5D0A3AD36ED2
+0000000000000000000000000000000000000000000000000000000000000001:\
+EC4916DD28FC4C10D78E287CA5D9CC51EE1AE73CBFDE08C6B37324CBFAAC8BC5
+
+[SHA-384]
+:38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA\
+274EDEBFE76F65FBD51AD2F14898B95B
+
+61:\
+54A59B9F22B0B80880D8427E548B7C23ABD873486E1F035DCE9CD697E8517503\
+3CAA88E6D57BC35EFAE0B5AFD3145F31
+
+616263:\
+CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163\
+1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7
+
+6D65737361676520646967657374:\
+473ED35167EC1F5D8E550368A3DB39BE54639F828868E9454C239FC8B52E3C61\
+DBD0D8B4DE1390C256DCBB5D5FD99CD5
+
+61626364656667686263646566676869636465666768696A6465666768696A6B\
+65666768696A6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F\
+696A6B6C6D6E6F706A6B6C6D6E6F70716B6C6D6E6F7071726C6D6E6F70717273\
+6D6E6F70717273746E6F707172737475:\
+09330C33F71147E83D192FC782CD1B4753111B173B3B05D2\
+2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A616263646566\
+6768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+1761336E3F7CBFE51DEB137F026F89E01A448E3B1FAFA64039C1464EE8732F11\
+A5341A6F41E0C202294736ED64DB1A84
+
+3132333435363738393031323334353637383930313233343536373839303132\
+3334353637383930313233343536373839303132333435363738393031323334\
+35363738393031323334353637383930:\
+B12932B0627D1C060942F5447764155655BD4DA0C9AFA6DD9B9EF53129AF1B8F\
+B0195996D2DE9CA0DF9D821FFEE67026
+
+[SHA-512]
+:CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE\
+47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E
+
+61:\
+1F40FC92DA241694750979EE6CF582F2D5D7D28E18335DE05ABC54D0560E0F53\
+02860C652BF08D560252AA5E74210546F369FBBBCE8C12CFC7957B2652FE9A75
+
+616263:\
+DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A\
+2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F
+
+6D65737361676520646967657374:\
+107DBF389D9E9F71A3A95F6C055B9251BC5268C2BE16D6C13492EA45B0199F33\
+09E16455AB1E96118E8A905D5597B72038DDB372A89826046DE66687BB420E7C
+
+6162636462636465636465666465666765666768666768696768696A\
+68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+204A8FC6DDA82F0A0CED7BEB8E08A41657C16EF468B228A8279BE331A703C335\
+96FD15C13B1B07F9AA1D3BEA57789CA031AD85C7A71DD70354EC631238CA3445
+
+61626364656667686263646566676869636465666768696A6465666768696A6B65666768696A\
+6B6C666768696A6B6C6D6768696A6B6C6D6E68696A6B6C6D6E6F696A6B6C6D6E6F706A6B6C6D\
+6E6F70716B6C6D6E6F7071726C6D6E6F707172736D6E6F70717273746E6F707172737475:\
+8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018\
+501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909
+
+3132333435363738393031323334353637383930313233343536373839303132\
+3334353637383930313233343536373839303132333435363738393031323334\
+35363738393031323334353637383930:\
+72EC1EF1124A45B047E8B7C75A932195135BB61DE24EC0D1914042246E0AEC3A\
+2354E093D76F3048B456764346900CB130D2A4FD5DD16ABB5E30BCB850DEE843
+
+[Skein-512(160)]
+:B034BCC065B01B0C486159B3DBA3E03AA52FDD70
+
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+3DC1772828D7D723A170B0317CF3E4BC15A30ED3
+
+[Skein-512(224)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+2B718DF0B6C720A58F1875A0FA602247AA2563C51503229AB0310DE6
+
+:\
+7AA86748769C688C43B5DAFE45B267DC057B89FDE6BC3EBF5274D6FB
+
+CC:\
+E4E4D51523F7667C0204D4EFF24B12A77AC1E86DCAC42BD5F570C69E
+
+41FB:\
+C91BB6F83D34DC3202CA2D35902D3DEA2099A3A77C39722341AD1102
+
+1F877C:\
+7A606D82C208B19CB9C35793C91E7167FDA464E3056DC6F6EB4B7DBF
+
+C1ECFDFC:\
+7F1A5454AD65FA1DA2C35A6966F79B313AA3F7421F25E2B9C17ED036
+
+21F134AC57:\
+66FF42A3C5FD93FB3DC6ACF4BA936E7975A1101942BB96F86BE63598
+
+C6F50BB74E29:\
+C0732BA73E4E8F49D990000122AECCBC9DD7C62F1B84586C04B2CA97
+
+119713CC83EEEF:\
+BFC1F706A79037EE0FF2896FCBA0C2E891BB53EE00AB81A7187FB135
+
+4A4F202484512526:\
+657C8557A264BEED5F0E4D63821CD23DA9A141D40CE9E4EA5C494193
+
+1F66AB4185ED9B6375:\
+6CB0E36907DB405784B1B16027C1EE218881BF47E4665EB34D49F493
+
+EED7422227613B6F53C9:\
+210C03C1D282980FCDA5D3E99D8EB7C0EE6DF2A1EF88CEA189F3ED3B
+
+EAEED5CDFFD89DECE455F1:\
+BB6AAB5B0F5992493C54FEA44A7A62D135F28D0E146E114494006726
+
+5BE43C90F22902E4FE8ED2D3:\
+129D08AFAAC4997AA4EA9694F17E9B77B945A13A944A1A9D78BA0FBE
+
+A746273228122F381C3B46E4F1:\
+5A540119ACCE26D6B741802874D6B98F21794EA0588617B598126392
+
+3C5871CD619C69A63B540EB5A625:\
+568E96915FE801E45171A07D0A8CE3DBC4D5BEC71CCB3C06EB78647C
+
+FA22874BCC068879E8EF11A69F0722:\
+512F863E0C1FD2E4D916EC2FFDED958687964D5FE43E058EFF63B001
+
+52A608AB21CCDD8A4457A57EDE782176:\
+FE2AA246026EFADD6D4A3F8DE3C07BB4BC18CF260910E5A0B0B98CDE
+
+82E192E4043DDCD12ECF52969D0F807EED:\
+0A6FC81E4936511F0FD9186495B39A32B6867E7A524EF2AA05F55348
+
+75683DCB556140C522543BB6E9098B21A21E:\
+BB439DF50CE268CE0640091E2DB3BEAF3EBBF1373C247A2E90E2C989
+
+06E4EFE45035E61FAAF4287B4D8D1F12CA97E5:\
+0A5C2E588978B2A327D2115D425B9F407CFEC582F4939A849AC25CFC
+
+E26193989D06568FE688E75540AEA06747D9F851:\
+DB357210E767B9ECAF25D573ED94DC1B6CD3D523B576025A77CB6CB5
+
+D8DC8FDEFBDCE9D44E4CBAFE78447BAE3B5436102A:\
+FDC36CF68208BFF974D8AAF9B2ABDB59E2C9CC5F2154973F7B4254A0
+
+57085FD7E14216AB102D8317B0CB338A786D5FC32D8F:\
+427AEA70DC9605EDC313D273E3568F0A0E87BD74FE1A5E8AE5334E1B
+
+A05404DF5DBB57697E2C16FA29DEFAC8AB3560D6126FA0:\
+45BD02D8656C555D555F995C223AFE9C823D2B181201A81EC548FD23
+
+AECBB02759F7433D6FCB06963C74061CD83B5B3FFA6F13C6:\
+54D7D4AB57C5667FCB59B63446D9AA67422F9A0AD7518D9B35E7BB08
+
+AAFDC9243D3D4A096558A360CC27C8D862F0BE73DB5E88AA55:\
+72FA8FD765194C88C7002C8CA45A24FDA914F69D270B8454A2D97FDE
+
+7BC84867F6F9E9FDC3E1046CAE3A52C77ED485860EE260E30B15:\
+7BD3F6187F506186720893AC14CDA6E96D269A024187594557850A37
+
+FAC523575A99EC48279A7A459E98FF901918A475034327EFB55843:\
+B0B459577B499D2C5ABA619CD5C6A5732D6F6D78BB33312D4C930CEC
+
+0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E:\
+64CFC989C1EC79DB84A51B7DE6F40E5B7A900AEE4F6B5751D8886A65
+
+A963C3E895FF5A0BE4824400518D81412F875FA50521E26E85EAC90C04:\
+81435B887DCADB952F24B6CA67FF30C377B00308BA0A6F8278334368
+
+03A18688B10CC0EDF83ADF0A84808A9718383C4070C6C4F295098699AC2C:\
+E1CB3E09E5916D2EE42E633F8DA30448052960A95B21B45911BDAECE
+
+84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29:\
+7FAC333FCDF52F5833E55D0DD4C783DC61B1727C1EF9A02C7AE201BB
+
+9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10:\
+4B235F8557EA5C202C9C5168206D349060A2781E21DC958FE679E3E1
+
+DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE0\
+46:\
+AFFE2914DD6072CD980960FFDFC599D7CDA52F09920A8DFA62EA4EEB
+
+62F154EC394D0BC757D045C798C8B87A00E0655D0481A7D2D9FB58D93AEDC676\
+B5A0:\
+3997E91CF25CE17CA8B035B2353D1AB48EC90ACEFE72CEB096F250EB
+
+B2DCFE9FF19E2B23CE7DA2A4207D3E5EC7C6112A8A22AEC9675A886378E14E5B\
+FBAD4E:\
+75F4072F0F0A284A8D24766E933AF709E1FE3AF385F4C6875A1AC11B
+
+47F5697AC8C31409C0868827347A613A3562041C633CF1F1F86865A576E02835\
+ED2C2492:\
+7B6333A603FF632E9CFE01D0D64D0AAC13C1E5EFDD97224A79DCA121
+
+512A6D292E67ECB2FE486BFE92660953A75484FF4C4F2ECA2B0AF0EDCDD4339C\
+6B2EE4E542:\
+BFA0D6B54B8A045434E722394DF84B664F28016D235B2F48F5EA588D
+
+973CF2B4DCF0BFA872B41194CB05BB4E16760A1840D8343301802576197EC19E\
+2A1493D8F4FB:\
+C395991E0D4727E0AB271C1321A020EAF5DFAB9631F389900D6595F9
+
+80BEEBCD2E3F8A9451D4499961C9731AE667CDC24EA020CE3B9AA4BBC0A7F79E\
+30A934467DA4B0:\
+B5CEDF4D9504DF3D9171F8BA96090B45BB90F3E8A911402A1C3E00E3
+
+7ABAA12EC2A7347674E444140AE0FB659D08E1C66DECD8D6EAE925FA451D65F3\
+C0308E29446B8ED3:\
+3E6E936755C1D9836B3FC379B4C6D18F439CA6A1DC78AEB1D50AE837
+
+C88DEE9927679B8AF422ABCBACF283B904FF31E1CAC58C7819809F65D5807D46\
+723B20F67BA610C2B7:\
+84B0632239E55E830F2AEC7D6687868CE4C054F5E6A2BC085D062895
+
+01E43FE350FCEC450EC9B102053E6B5D56E09896E0DDD9074FE138E603821027\
+0C834CE6EADC2BB86BF6:\
+9273DC67961CFE9E6D86A432D40FF797F501B53B5EAC00123FF0BB88
+
+337023370A48B62EE43546F17C4EF2BF8D7ECD1D49F90BAB604B839C2E6E5BD2\
+1540D29BA27AB8E309A4B7:\
+9A34A7E5F29932359C7ABA6F7A4ADE7041DDE12428DE78D3B8A085BD
+
+6892540F964C8C74BD2DB02C0AD884510CB38AFD4438AF31FC912756F3EFEC6B\
+32B58EBC38FC2A6B913596A8:\
+FC35B4F43134B30F500F76B9C52213DF9A4DC3796B5C27010012BC51
+
+F5961DFD2B1FFFFDA4FFBF30560C165BFEDAB8CE0BE525845DEB8DC61004B7DB\
+38467205F5DCFB34A2ACFE96C0:\
+01B761AC903AE54A0F16F9F38F721A32ACE7E86E222B41DE11CBCA00
+
+CA061A2EB6CEED8881CE2057172D869D73A1951E63D57261384B80CEB5451E77\
+B06CF0F5A0EA15CA907EE1C27EBA:\
+B207ED6F58D136D84844531CCD9EAFB23DB225F10AF02B2A919DF59F
+
+1743A77251D69242750C4F1140532CD3C33F9B5CCDF7514E8584D4A5F9FBD730\
+BCF84D0D4726364B9BF95AB251D9BB:\
+D708038912881BCA7D358F3BA8B08251AFD4CA8F7357AE8A5D65967F
+
+D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7\
+C7F157298EABC4DCE7D89CE5162499F9:\
+CFB39569FDE7249D935C5AB4B68090BD8BD79B15D22984F6325C5DB2
+
+BE9684BE70340860373C9C482BA517E899FC81BAAA12E5C6D7727975D1D41BA8\
+BEF788CDB5CF4606C9C1C7F61AED59F97D:\
+D6C7ABC171CF6DF6BFE29C363980A9E21470BA4CE4B2CB425ABEFDF7
+
+7E15D2B9EA74CA60F66C8DFAB377D9198B7B16DEB6A1BA0EA3C7EE2042F89D37\
+86E779CF053C77785AA9E692F821F14A7F51:\
+13EB1D3594D54BC55D647C5B9BBA4A6D2D4B6E0E76D3FE7840706A34
+
+9A219BE43713BD578015E9FDA66C0F2D83CAC563B776AB9F38F3E4F7EF229CB4\
+43304FBA401EFB2BDBD7ECE939102298651C86:\
+D8FEA9C7267C4E94BACF948079D921AB4C3F4E7C5B90FA5E24C15F47
+
+C8F2B693BD0D75EF99CAEBDC22ADF4088A95A3542F637203E283BBC3268780E7\
+87D68D28CC3897452F6A22AA8573CCEBF245972A:\
+3A0FD6E34B2CC7EE17C03E889FCCD3C1EE541730A65DBD9C1C572BF5
+
+EC0F99711016C6A2A07AD80D16427506CE6F441059FD269442BAAA28C6CA037B\
+22EEAC49D5D894C0BF66219F2C08E9D0E8AB21DE52:\
+6BDE585863AFBCEF2C0E1E201AF3204F64ABDCB6C091C2262F7D2A17
+
+0DC45181337CA32A8222FE7A3BF42FC9F89744259CFF653504D6051FE84B1A7F\
+FD20CB47D4696CE212A686BB9BE9A8AB1C697B6D6A33:\
+CBBA015CD7BA55FA3485825C6992FB0D25E988DC0E880D4881050DAB
+
+DE286BA4206E8B005714F80FB1CDFAEBDE91D29F84603E4A3EBC04686F99A46C\
+9E880B96C574825582E8812A26E5A857FFC6579F63742F:\
+F6FB0931870DC9EDA2A28A78198DA9B35127F783DCC6660481BCBF19
+
+EEBCC18057252CBF3F9C070F1A73213356D5D4BC19AC2A411EC8CDEEE7A571E2\
+E20EAF61FD0C33A0FFEB297DDB77A97F0A415347DB66BCAF:\
+CD301B7C9DC97E379F80A2F023526E5E614CE47899A625141198B113
+
+416B5CDC9FE951BD361BD7ABFC120A5054758EBA88FDD68FD84E39D3B09AC254\
+97D36B43CBE7B85A6A3CEBDA8DB4E5549C3EE51BB6FCB6AC1E:\
+2B8B782A4DC25125B11F24D82A0B50B63C2A9E1DCA26C94AE31B877F
+
+5C5FAF66F32E0F8311C32E8DA8284A4ED60891A5A7E50FB2956B3CBAA79FC66C\
+A376460E100415401FC2B8518C64502F187EA14BFC9503759705:\
+0C3BB1C61319B57D59AF6B27B179F1AF198D275EB9EC34F6F729F3F3
+
+7167E1E02BE1A7CA69D788666F823AE4EEF39271F3C26A5CF7CEE05BCA831610\
+66DC2E217B330DF821103799DF6D74810EED363ADC4AB99F36046A:\
+A6692363E7C4179B699F8726BA0508842C159FC91936DE9E57E94424
+
+2FDA311DBBA27321C5329510FAE6948F03210B76D43E7448D1689A063877B6D1\
+4C4F6D0EAA96C150051371F7DD8A4119F7DA5C483CC3E6723C01FB7D:\
+26514934EA8D7A27A910535F2494D9F03CFA2219926547C72140F301
+
+95D1474A5AAB5D2422ACA6E481187833A6212BD2D0F91451A67DD786DFC91DFE\
+D51B35F47E1DEB8A8AB4B9CB67B70179CC26F553AE7B569969CE151B8D:\
+AF0857642D2D1AA057948D790680BF7C40592BAD4F1E78E6757330DF
+
+C71BD7941F41DF044A2927A8FF55B4B467C33D089F0988AA253D294ADDBDB325\
+30C0D4208B10D9959823F0C0F0734684006DF79F7099870F6BF53211A88D:\
+15F49CE92772067F0A4445B264660694A7449833404212316222565B
+
+F57C64006D9EA761892E145C99DF1B24640883DA79D9ED5262859DCDA8C3C32E\
+05B03D984F1AB4A230242AB6B78D368DC5AAA1E6D3498D53371E84B0C1D4BA:\
+1F3E4A237EB8B7E279A0CBD95CE4FBABE205558017B87676EB90877C
+
+E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\
+E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\
+7DB6E11E9B3F884611DEEEAE357D22EAF55445D713470990F3A2BD90
+
+16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652B\
+DF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC\
+00:\
+82DDEFF26BC92AD8C3A498E4AFE52B38AE7640D439C11DA0967216EF
+
+FC424EEB27C18A11C01F39C555D8B78A805B88DBA1DC2A42ED5E2C0EC737FF68\
+B2456D80EB85E11714FA3F8EABFB906D3C17964CB4F5E76B29C1765DB03D91BE\
+37FC:\
+9B073BD1543742361400C9C1608113025E9770A7CDB2600411BB37D7
+
+ABE3472B54E72734BDBA7D9158736464251C4F21B33FBBC92D7FAC9A35C4E332\
+2FF01D2380CBAA4EF8FB07D21A2128B7B9F5B6D9F34E13F39C7FFC2E72E47888\
+599BA5:\
+18D2007C0AF3099B220AC755A34AAF3365B946F00C9817E718D54907
+
+36F9F0A65F2CA498D739B944D6EFF3DA5EBBA57E7D9C41598A2B0E4380F3CF4B\
+479EC2348D015FFE6256273511154AFCF3B4B4BF09D6C4744FDD0F62D75079D4\
+40706B05:\
+3C072B8543E6A1169A8B45C0C8AA28D3331A41C16124E9E0178378F9
+
+ABC87763CAE1CA98BD8C5B82CABA54AC83286F87E9610128AE4DE68AC95DF5E3\
+29C360717BD349F26B872528492CA7C94C2C1E1EF56B74DBB65C2AC351981FDB\
+31D06C77A4:\
+17FA4ABDB577A8343A630FF1EC1BDCF2B4F527EAA6F63F8E391D1ABB
+
+94F7CA8E1A54234C6D53CC734BB3D3150C8BA8C5F880EAB8D25FED13793A9701\
+EBE320509286FD8E422E931D99C98DA4DF7E70AE447BAB8CFFD92382D8A77760\
+A259FC4FBD72:\
+C003A198B3E1D0AA2640E20369BF26804EFF011AB1BBC680183633E8
+
+13BD2811F6ED2B6F04FF3895ACEED7BEF8DCD45EB121791BC194A0F806206BFF\
+C3B9281C2B308B1A729CE008119DD3066E9378ACDCC50A98A82E20738800B6CD\
+DBE5FE9694AD6D:\
+44A844061000C61661C3A362BC808C22DBD4962F18CBB9A5B5DCA05C
+
+1EED9CBA179A009EC2EC5508773DD305477CA117E6D569E66B5F64C6BC64801C\
+E25A8424CE4A26D575B8A6FB10EAD3FD1992EDDDEEC2EBE7150DC98F63ADC323\
+7EF57B91397AA8A7:\
+60DE15C6C9BCB169F1407FEB77D534E55BC47DCD59E66437D9E4F70A
+
+BA5B67B5EC3A3FFAE2C19DD8176A2EF75C0CD903725D45C9CB7009A900C0B0CA\
+7A2967A95AE68269A6DBF8466C7B6844A1D608AC661F7EFF00538E323DB5F2C6\
+44B78B2D48DE1A08AA:\
+54F2168C3C3207201F22E1D861B8C629CE0F01112CC931E29AECACC4
+
+0EFA26AC5673167DCACAB860932ED612F65FF49B80FA9AE65465E5542CB62075\
+DF1C5AE54FBA4DB807BE25B070033EFA223BDD5B1D3C94C6E1909C02B620D4B1\
+B3A6C9FED24D70749604:\
+1F63AAC1832C1518F6FEC037E49FF7FE2155BF3EABA503FEAEF8395E
+
+BBFD933D1FD7BF594AC7F435277DC17D8D5A5B8E4D13D96D2F64E771ABBD51A5\
+A8AEA741BECCBDDB177BCEA05243EBD003CFDEAE877CCA4DA94605B67691919D\
+8B033F77D384CA01593C1B:\
+6FD05F307E9CC34FD41E3AFDA497BE0BA444BBC11C3AEC0525001F93
+
+90078999FD3C35B8AFBF4066CBDE335891365F0FC75C1286CDD88FA51FAB94F9\
+B8DEF7C9AC582A5DBCD95817AFB7D1B48F63704E19C2BAA4DF347F48D4A6D603\
+013C23F1E9611D595EBAC37C:\
+F63D918DB69CCA874196DA64486DDAA5A1E33BFA58128FB2C7088F36
+
+64105ECA863515C20E7CFBAA0A0B8809046164F374D691CDBD6508AAABC1819F\
+9AC84B52BAFC1B0FE7CDDBC554B608C01C8904C669D8DB316A0953A4C68ECE32\
+4EC5A49FFDB59A1BD6A292AA0E:\
+761B70CCFF0047701D60E9A63666DA44574A146D1CBE6221B0455EBC
+
+D4654BE288B9F3B711C2D02015978A8CC57471D5680A092AA534F7372C71CEAA\
+B725A383C4FCF4D8DEAA57FCA3CE056F312961ECCF9B86F14981BA5BED6AB5B4\
+498E1F6C82C6CAE6FC14845B3C8A:\
+879CAD70F8A95E75DADD8C1F98B5F26D5151D615385FC2F08E3C65AC
+
+12D9394888305AC96E65F2BF0E1B18C29C90FE9D714DD59F651F52B88B3008C5\
+88435548066EA2FC4C101118C91F32556224A540DE6EFDDBCA296EF1FB00341F\
+5B01FECFC146BDB251B3BDAD556CD2:\
+EEAF23D57EF12AA5D5C6E8709B4ABDF65045B096D76B31059288C1DA
+
+871A0D7A5F36C3DA1DFCE57ACD8AB8487C274FAD336BC137EBD6FF4658B547C1\
+DCFAB65F037AA58F35EF16AFF4ABE77BA61F65826F7BE681B5B6D5A1EA8085E2\
+AE9CD5CF0991878A311B549A6D6AF230:\
+09AF148CFEDB3CE21A4C1283806D9C31F2A6551CAA4C65E1095CCA65
+
+E90B4FFEF4D457BC7711FF4AA72231CA25AF6B2E206F8BF859D8758B89A7CD36\
+105DB2538D06DA83BAD5F663BA11A5F6F61F236FD5F8D53C5E89F183A3CEC615\
+B50C7C681E773D109FF7491B5CC22296C5:\
+1FF12E3B3F1C0F1580DE3B2B434317B1094145D4D5F88D49C2899913
+
+E728DE62D75856500C4C77A428612CD804F30C3F10D36FB219C5CA0AA30726AB\
+190E5F3F279E0733D77E7267C17BE27D21650A9A4D1E32F649627638DBADA970\
+2C7CA303269ED14014B2F3CF8B894EAC8554:\
+864EC0649750A7E91E90E841BC32466DE974DB33D4045B029BD1AC4F
+
+6348F229E7B1DF3B770C77544E5166E081850FA1C6C88169DB74C76E42EB983F\
+ACB276AD6A0D1FA7B50D3E3B6FCD799EC97470920A7ABED47D288FF883E24CA2\
+1C7F8016B93BB9B9E078BDB9703D2B781B616E:\
+9961608B85AAACB8CFD7183AF1FE84620BC077208EE7F2A3A206930D
+
+4B127FDE5DE733A1680C2790363627E63AC8A3F1B4707D982CAEA258655D9BF1\
+8F89AFE54127482BA01E08845594B671306A025C9A5C5B6F93B0A39522DC8774\
+37BE5C2436CBF300CE7AB6747934FCFC30AEAAF6:\
+B62124BCCC2FDCEEDCFCA7475F33EDDB5BE61B6AF0F85A7F6BF2272B
+
+08461F006CFF4CC64B752C957287E5A0FAABC05C9BFF89D23FD902D324C79903\
+B48FCB8F8F4B01F3E4DDB483593D25F000386698F5ADE7FAADE9615FDC50D327\
+85EA51D49894E45BAA3DC707E224688C6408B68B11:\
+13BDFB31B626629662B4956552B1037163D3734CA3E84F1AE1E41E0A
+
+68C8F8849B120E6E0C9969A5866AF591A829B92F33CD9A4A3196957A148C4913\
+8E1E2F5C7619A6D5EDEBE995ACD81EC8BB9C7B9CFCA678D081EA9E25A75D39DB\
+04E18D475920CE828B94E72241F24DB72546B352A0E4:\
+D9111963E738F28B6FB70970B83E41FEF4CC2D5129ADA2069318F4A5
+
+B8D56472954E31FB54E28FCA743F84D8DC34891CB564C64B08F7B71636DEBD64\
+CA1EDBDBA7FC5C3E40049CE982BBA8C7E0703034E331384695E9DE76B5104F2F\
+BC4535ECBEEBC33BC27F29F18F6F27E8023B0FBB6F563C:\
+24ADCC7FC40FC12041DAEA110672AFC9EA7F2231D36E8828AD12D107
+
+0D58AC665FA84342E60CEFEE31B1A4EACDB092F122DFC68309077AED1F3E528F\
+578859EE9E4CEFB4A728E946324927B675CD4F4AC84F64DB3DACFE850C1DD187\
+44C74CECCD9FE4DC214085108F404EAB6D8F452B5442A47D:\
+45A994D0D305EFE61B91C658206E092586D3ACA33195839B20E97868
+
+1755E2D2E5D1C1B0156456B539753FF416651D44698E87002DCF61DCFA2B4E72\
+F264D9AD591DF1FDEE7B41B2EB00283C5AEBB3411323B672EAA145C512518510\
+4F20F335804B02325B6DEA65603F349F4D5D8B782DD3469CCD:\
+CE9A443639BD043B3F0001B015332E22CE98AAF237CE8610E98B40D0
+
+B180DE1A611111EE7584BA2C4B020598CD574AC77E404E853D15A101C6F5A2E5\
+C801D7D85DC95286A1804C870BB9F00FD4DCB03AA8328275158819DCAD7253F3\
+E3D237AEAA7979268A5DB1C6CE08A9EC7C2579783C8AFC1F91A7:\
+423AC9DD5A9B573EF657C306448D3EEA618E3621631E20D1859B4446
+
+CF3583CBDFD4CBC17063B1E7D90B02F0E6E2EE05F99D77E24E560392535E47E0\
+5077157F96813544A17046914F9EFB64762A23CF7A49FE52A0A4C01C630CFE87\
+27B81FB99A89FF7CC11DCA5173057E0417B8FE7A9EFBA6D95C555F:\
+ECB8B0555265D47CBABD9A3259E254E5C57E2C1913FA8D4F6D50C0A1
+
+072FC02340EF99115BAD72F92C01E4C093B9599F6CFC45CB380EE686CB5EB019\
+E806AB9BD55E634AB10AA62A9510CC0672CD3EDDB589C7DF2B67FCD3329F61B1\
+A4441ECA87A33C8F55DA4FBBAD5CF2B2527B8E983BB31A2FADEC7523:\
+129803DF866AE32F3FD4E9883A2920FC1C0E1854E312CA7E1BF2769B
+
+76EECF956A52649F877528146DE33DF249CD800E21830F65E90F0F25CA9D6540\
+FDE40603230ECA6760F1139C7F268DEBA2060631EEA92B1FFF05F93FD5572FBE\
+29579ECD48BC3A8D6C2EB4A6B26E38D6C5FBF2C08044AEEA470A8F2F26:\
+1E3FADDC3974593E6294539CA73D22278CA2A7862D17D19E9BC3E17D
+
+7ADC0B6693E61C269F278E6944A5A2D8300981E40022F839AC644387BFAC9086\
+650085C2CDC585FEA47B9D2E52D65A2B29A7DC370401EF5D60DD0D21F9E2B90F\
+AE919319B14B8C5565B0423CEFB827D5F1203302A9D01523498A4DB10374:\
+E75807D47DF0CC8590C1474FFE018C541FB56772676E5446B87BB347
+
+E1FFFA9826CCE8B86BCCEFB8794E48C46CDF372013F782ECED1E378269B7BE2B\
+7BF51374092261AE120E822BE685F2E7A83664BCFBE38FE8633F24E633FFE198\
+8E1BC5ACF59A587079A57A910BDA60060E85B5F5B6F776F0529639D9CCE4BD:\
+2FE934932126411F9E760CB06C98E6374F762325A8F40D3559861CFF
+
+69F9ABBA65592EE01DB4DCE52DBAB90B08FC04193602792EE4DAA263033D5908\
+1587B09BBE49D0B49C9825D22840B2FF5D9C5155F975F8F2C2E7A90C75D2E4A8\
+040FE39F63BBAFB403D9E28CC3B86E04E394A9C9E8065BD3C85FA9F0C7891600:\
+C9746187BB2681AFF066D735B325E1CFF02F4EC585FBBDC730BB3705
+
+38A10A352CA5AEDFA8E19C64787D8E9C3A75DBF3B8674BFAB29B5DBFC15A63D1\
+0FAE66CD1A6E6D2452D557967EAAD89A4C98449787B0B3164CA5B717A93F24EB\
+0B506CEB70CBBCB8D72B2A72993F909AAD92F044E0B5A2C9AC9CB16A0CA2F81F\
+49:\
+990766FA326BF1793AB5C2140A8820AC93DC68CEAC0847FE07C07A1B
+
+6D8C6E449BC13634F115749C248C17CD148B72157A2C37BF8969EA83B4D6BA8C\
+0EE2711C28EE11495F43049596520CE436004B026B6C1F7292B9C436B055CBB7\
+2D530D860D1276A1502A5140E3C3F54A93663E4D20EDEC32D284E25564F62495\
+5B52:\
+A881E5D1CFE74CE904C948D0496C392E8805E5C550B56B0B09415EB0
+
+6EFCBCAF451C129DBE00B9CEF0C3749D3EE9D41C7BD500ADE40CDC65DEDBBBAD\
+B885A5B14B32A0C0D087825201E303288A733842FA7E599C0C514E078F05C821\
+C7A4498B01C40032E9F1872A1C925FA17CE253E8935E4C3C71282242CB716B20\
+89CCC1:\
+85E3D7307FABF376B894EB810CABAD829F7B0A40F0058AE43C37947E
+
+433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B982\
+14B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784444F\
+22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53E7E084\
+6DCBB4CE:\
+46DEBE450ABA22B5D4FA8422B4E9259CE416CF3F428C83E9947A9E68
+
+A873E0C67CA639026B6683008F7AA6324D4979550E9BCE064CA1E1FB97A30B14\
+7A24F3F666C0A72D71348EDE701CF2D17E2253C34D1EC3B647DBCEF2F879F4EB\
+881C4830B791378C901EB725EA5C172316C6D606E0AF7DF4DF7F76E490CD30B2\
+BADF45685F:\
+0E79C3B35616DE0ECEEB3B9E669B600E42A4EEE291F570114122A8A9
+
+006917B64F9DCDF1D2D87C8A6173B64F6587168E80FAA80F82D84F60301E561E\
+312D9FBCE62F39A6FB476E01E925F26BCC91DE621449BE6504C504830AAE3940\
+96C8FC7694651051365D4EE9070101EC9B68086F2EA8F8AB7B811EA8AD934D5C\
+9B62C60A4771:\
+014200515103F199DD4FDF17443AAB936A0F51CF2CCC6697BF47F3AD
+
+F13C972C52CB3CC4A4DF28C97F2DF11CE089B815466BE88863243EB318C2ADB1\
+A417CB1041308598541720197B9B1CB5BA2318BD5574D1DF2174AF14884149BA\
+9B2F446D609DF240CE335599957B8EC80876D9A085AE084907BC5961B20BF5F6\
+CA58D5DAB38ADB:\
+45149B32F55F93F61D2DEC87B926A4B7EA17D49891F65EF14EB3B7D9
+
+E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486\
+F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D\
+B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A\
+21691E1069413848:\
+FAF24398B32371FD680CF6B652173C812B5FEA2C08218F3AE1046189
+
+64EC021C9585E01FFE6D31BB50D44C79B6993D72678163DB474947A053674619\
+D158016ADB243F5C8D50AA92F50AB36E579FF2DABB780A2B529370DAA299207C\
+FBCDD3A9A25006D19C4F1FE33E4B1EAEC315D8C6EE1E730623FD1941875B924E\
+B57D6D0C2EDC4E78D6:\
+02F3B34DAC38A5850EBE9604E7EA1AA4BD87AA3C1860C55F9786C255
+
+5954BAB512CF327D66B5D9F296180080402624AD7628506B555EEA8382562324\
+CF452FBA4A2130DE3E165D11831A270D9CB97CE8C2D32A96F50D71600BB4CA26\
+8CF98E90D6496B0A6619A5A8C63DB6D8A0634DFC6C7EC8EA9C006B6C456F1B20\
+CD19E781AF20454AC880:\
+23CFE985DAB39A2627F5CA6E67D15F6F7EE1381FEFAAC5EF4F7D3F74
+
+03D9F92B2C565709A568724A0AFF90F8F347F43B02338F94A03ED32E6F33666F\
+F5802DA4C81BDCE0D0E86C04AFD4EDC2FC8B4141C2975B6F07639B1994C973D9\
+A9AFCE3D9D365862003498513BFA166D2629E314D97441667B007414E739D7FE\
+BF0FE3C32C17AA188A8683:\
+82D16C2A021675F4E9F2ED6E34349EBE7047001F84F56F26D47FE571
+
+F31E8B4F9E0621D531D22A380BE5D9ABD56FAEC53CBD39B1FAB230EA67184440\
+E5B1D15457BD25F56204FA917FA48E669016CB48C1FFC1E1E45274B3B47379E0\
+0A43843CF8601A5551411EC12503E5AAC43D8676A1B2297EC7A0800DBFEE0429\
+2E937F21C005F17411473041:\
+3F9960493D89F2DD6A8375BE0673AD4C64D9AB396F502159628A2AD5
+
+758EA3FEA738973DB0B8BE7E599BBEF4519373D6E6DCD7195EA885FC991D8967\
+62992759C2A09002912FB08E0CB5B76F49162AEB8CF87B172CF3AD190253DF61\
+2F77B1F0C532E3B5FC99C2D31F8F65011695A087A35EE4EEE5E334C369D8EE5D\
+29F695815D866DA99DF3F79403:\
+C1799D6E48834E5E893359B1F8C8799040AD9D7BEA701CFEC0DAC204
+
+47C6E0C2B74948465921868804F0F7BD50DD323583DC784F998A93CD1CA4C6EF\
+84D41DC81C2C40F34B5BEE6A93867B3BDBA0052C5F59E6F3657918C382E771D3\
+3109122CC8BB0E1E53C4E3D13B43CE44970F5E0C079D2AD7D7A3549CD75760C2\
+1BB15B447589E86E8D76B1E9CED2:\
+5FBE11E1A85A635033A97920BD48337210339E9EFB9221EF5B519EB4
+
+F690A132AB46B28EDFA6479283D6444E371C6459108AFD9C35DBD235E0B6B6FF\
+4C4EA58E7554BD002460433B2164CA51E868F7947D7D7A0D792E4ABF0BE5F450\
+853CC40D85485B2B8857EA31B5EA6E4CCFA2F3A7EF3380066D7D8979FDAC618A\
+AD3D7E886DEA4F005AE4AD05E5065F:\
+7677527F993D3E84C2EBF650EAA373FC32526FAA1A078D02DAEFE5E2
+
+58D6A99BC6458824B256916770A8417040721CCCFD4B79EACD8B65A3767CE5BA\
+7E74104C985AC56B8CC9AEBD16FEBD4CDA5ADB130B0FF2329CC8D611EB14DAC2\
+68A2F9E633C99DE33997FEA41C52A7C5E1317D5B5DAED35EBA7D5A60E45D1FA7\
+EAABC35F5C2B0A0F2379231953322C4E:\
+8D2CA9D933106BD1D2659B029DD8306248091212CF231A7FD3FD5AAE
+
+BEFAB574396D7F8B6705E2D5B58B2C1C820BB24E3F4BAE3E8FBCD36DBF734EE1\
+4E5D6AB972AEDD3540235466E825850EE4C512EA9795ABFD33F330D9FD7F79E6\
+2BBB63A6EA85DE15BEAEEA6F8D204A28956059E2632D11861DFB0E65BC07AC8A\
+159388D5C3277E227286F65FF5E5B5AEC1:\
+3DAACF14099A70A48EB6CC45A996881326FBE0ACB4B3EE92B5134A94
+
+8E58144FA9179D686478622CE450C748260C95D1BA43B8F9B59ABECA8D93488D\
+A73463EF40198B4D16FB0B0707201347E0506FF19D01BEA0F42B8AF9E71A1F1B\
+D168781069D4D338FDEF00BF419FBB003031DF671F4A37979564F69282DE9C65\
+407847DD0DA505AB1641C02DEA4F0D834986:\
+1EC1B0284FB0B7AB356726338A66082E96F943D57C2B5F2898B2AA9E
+
+B55C10EAE0EC684C16D13463F29291BF26C82E2FA0422A99C71DB4AF14DD9C7F\
+33EDA52FD73D017CC0F2DBE734D831F0D820D06D5F89DACC485739144F8CFD47\
+99223B1AFF9031A105CB6A029BA71E6E5867D85A554991C38DF3C9EF8C1E1E9A\
+7630BE61CAABCA69280C399C1FB7A12D12AEFC:\
+A0CBCD5C15B59946971CFF0C0B0BE9E8898A3237FC8B28FBE8789B51
+
+2EEEA693F585F4ED6F6F8865BBAE47A6908AECD7C429E4BEC4F0DE1D0CA0183F\
+A201A0CB14A529B7D7AC0E6FF6607A3243EE9FB11BCF3E2304FE75FFCDDD6C5C\
+2E2A4CD45F63C962D010645058D36571404A6D2B4F44755434D76998E83409C3\
+205AA1615DB44057DB991231D2CB42624574F545:\
+28C9DF2DD04C5F97381E2485A6A2D75250ACD6D19AA778E057B3C0BD
+
+DAB11DC0B047DB0420A585F56C42D93175562852428499F66A0DB811FCDDDAB2\
+F7CDFFED1543E5FB72110B64686BC7B6887A538AD44C050F1E42631BC4EC8A9F\
+2A047163D822A38989EE4AAB01B4C1F161B062D873B1CFA388FD301514F62224\
+157B9BEF423C7783B7AAC8D30D65CD1BBA8D689C2D:\
+B3B4ACC18B310D480A3AC74B524B9B87EFA6AEB2CDC4ED9F5CCD78DA
+
+42E99A2F80AEE0E001279A2434F731E01D34A44B1A8101726921C0590C30F312\
+0EB83059F325E894A5AC959DCA71CE2214799916424E859D27D789437B9D2724\
+0BF8C35ADBAFCECC322B48AA205B293962D858652ABACBD588BCF6CBC388D099\
+3BD622F96ED54614C25B6A9AA527589EAAFFCF17DDF7:\
+39EF2D06DA8A9C035D46F3DC432DC5CDF6EBA2A49047220308B91FDF
+
+3C9B46450C0F2CAE8E3823F8BDB4277F31B744CE2EB17054BDDC6DFF36AF7F49\
+FB8A2320CC3BDF8E0A2EA29AD3A55DE1165D219ADEDDB5175253E2D1489E9B6F\
+DD02E2C3D3A4B54D60E3A47334C37913C5695378A669E9B72DEC32AF5434F93F\
+46176EBF044C4784467C700470D0C0B40C8A088C815816:\
+C62D2148CA179988D3B80A00A08977E0A67445EA480D115B73CCB96C
+
+D1E654B77CB155F5C77971A64DF9E5D34C26A3CAD6C7F6B300D39DEB19100946\
+91ADAA095BE4BA5D86690A976428635D5526F3E946F7DC3BD4DBC78999E65344\
+1187A81F9ADCD5A3C5F254BC8256B0158F54673DCC1232F6E918EBFC6C51CE67\
+EAEB042D9F57EEC4BFE910E169AF78B3DE48D137DF4F2840:\
+DF5ECBCC94DA5D734E989C47EE11FB8C5BCE9B9E6E676672823D0984
+
+626F68C18A69A6590159A9C46BE03D5965698F2DAC3DE779B878B3D9C421E0F2\
+1B955A16C715C1EC1E22CE3EB645B8B4F263F60660EA3028981EEBD6C8C3A367\
+285B691C8EE56944A7CD1217997E1D9C21620B536BDBD5DE8925FF71DEC6FBC0\
+6624AB6B21E329813DE90D1E572DFB89A18120C3F606355D25:\
+ADE2FF5F07E85FB9A8002728B9033797BF432405E47C4B8AF10A7CC5
+
+651A6FB3C4B80C7C68C6011675E6094EB56ABF5FC3057324EBC6477825061F9F\
+27E7A94633ABD1FA598A746E4A577CAF524C52EC1788471F92B8C37F23795CA1\
+9D559D446CAB16CBCDCE90B79FA1026CEE77BF4AB1B503C5B94C2256AD75B3EA\
+C6FD5DCB96ACA4B03A834BFB4E9AF988CECBF2AE597CB9097940:\
+F133DAA776EF321565DA24BDDFBAB376D8F60D54F75BF24466CCEDA7
+
+8AAF072FCE8A2D96BC10B3C91C809EE93072FB205CA7F10ABD82ECD82CF040B1\
+BC49EA13D1857815C0E99781DE3ADBB5443CE1C897E55188CEAF221AA9681638\
+DE05AE1B322938F46BCE51543B57ECDB4C266272259D1798DE13BE90E10EFEC2\
+D07484D9B21A3870E2AA9E06C21AA2D0C9CF420080A80A91DEE16F:\
+75395112E1313F0CE6C4FE6B8AAFE6E1ED4191F7F6A65E47CBD73E35
+
+53F918FD00B1701BD504F8CDEA803ACCA21AC18C564AB90C2A17DA592C7D6968\
+8F6580575395551E8CD33E0FEF08CA6ED4588D4D140B3E44C032355DF1C53156\
+4D7F4835753344345A6781E11CD5E095B73DF5F82C8AE3AD00877936896671E9\
+47CC52E2B29DCD463D90A0C9929128DA222B5A211450BBC0E02448E2:\
+E8F832C631891E973C6AEDF2CFDB6D6F75864571D94F18D3B90803D2
+
+A64599B8A61B5CCEC9E67AED69447459C8DA3D1EC6C7C7C82A7428B9B584FA67\
+E90F68E2C00FBBED4613666E5168DA4A16F395F7A3C3832B3B134BFC9CBAA95D\
+2A0FE252F44AC6681EB6D40AB91C1D0282FED6701C57463D3C5F2BB8C6A7301F\
+B4576AA3B5F15510DB8956FF77478C26A7C09BEA7B398CFC83503F538E:\
+E8333A5AA6735D8D778970DAA70435A126380122F02459F51A143EAB
+
+0E3AB0E054739B00CDB6A87BD12CAE024B54CB5E550E6C425360C2E87E59401F\
+5EC24EF0314855F0F56C47695D56A7FB1417693AF2A1ED5291F2FEE95F75EED5\
+4A1B1C2E81226FBFF6F63ADE584911C71967A8EB70933BC3F5D15BC91B5C2644\
+D9516D3C3A8C154EE48E118BD1442C043C7A0DBA5AC5B1D5360AAE5B9065:\
+9694E0383F0DF8B31E1FD0BF0E7B355C7842D008D4752B8F5DB2E06C
+
+A62FC595B4096E6336E53FCDFC8D1CC175D71DAC9D750A6133D23199EAAC2882\
+07944CEA6B16D27631915B4619F743DA2E30A0C00BBDB1BBB35AB852EF3B9AEC\
+6B0A8DCC6E9E1ABAA3AD62AC0A6C5DE765DE2C3711B769E3FDE44A74016FFF82\
+AC46FA8F1797D3B2A726B696E3DEA5530439ACEE3A45C2A51BC32DD055650B:\
+D2634E1D88ED5681B6446054CB7469CEF40A245BCF9DEECEEB8A0CDE
+
+2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\
+29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\
+E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\
+98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\
+FBDCBE127DF0838CAEAED3A8EA1C006C7D070A858567FC0153E9E3CB
+
+10DB509B2CDCABA6C062AE33BE48116A29EB18E390E1BBADA5CA0A2718AFBCD2\
+3431440106594893043CC7F2625281BF7DE2655880966A23705F0C5155C2F5CC\
+A9F2C2142E96D0A2E763B70686CD421B5DB812DACED0C6D65035FDE558E94F26\
+B3E6DDE5BD13980CC80292B723013BD033284584BFF27657871B0CF07A849F4A\
+E2:\
+7E5F9CE032AD6FB15D6E18719F60FCA5C1FB8FD79342297EE4456D7A
+
+9334DE60C997BDA6086101A6314F64E4458F5FF9450C509DF006E8C547983C65\
+1CA97879175AABA0C539E82D05C1E02C480975CBB30118121061B1EBAC4F8D9A\
+3781E2DB6B18042E01ECF9017A64A0E57447EC7FCBE6A7F82585F7403EE2223D\
+52D37B4BF426428613D6B4257980972A0ACAB508A7620C1CB28EB4E9D30FC413\
+61EC:\
+24550D634FBEB66AB3677AF8C5ECC003347610773AE28B5414056C86
+
+E88AB086891693AA535CEB20E64C7AB97C7DD3548F3786339897A5F0C3903154\
+9CA870166E477743CCFBE016B4428D89738E426F5FFE81626137F17AECFF61B7\
+2DBEE2DC20961880CFE281DFAB5EE38B1921881450E16032DE5E4D55AD8D4FCA\
+609721B0692BAC79BE5A06E177FE8C80C0C83519FB3347DE9F43D5561CB8107B\
+9B5EDC:\
+09991E8F4691292A12E67810B26F33E3B48CDCCE5B4F92750F8995FF
+
+FD19E01A83EB6EC810B94582CB8FBFA2FCB992B53684FB748D2264F020D3B960\
+CB1D6B8C348C2B54A9FCEA72330C2AAA9A24ECDB00C436ABC702361A82BB8828\
+B85369B8C72ECE0082FE06557163899C2A0EFA466C33C04343A839417057399A\
+63A3929BE1EE4805D6CE3E5D0D0967FE9004696A5663F4CAC9179006A2CEB755\
+42D75D68:\
+666EA481FD0857DF57653199108239DF721FEEDFC485B117382DB4BE
+
+59AE20B6F7E0B3C7A989AFB28324A40FCA25D8651CF1F46AE383EF6D8441587A\
+A1C04C3E3BF88E8131CE6145CFB8973D961E8432B202FA5AF3E09D625FAAD825\
+BC19DA9B5C6C20D02ABDA2FCC58B5BD3FE507BF201263F30543819510C12BC23\
+E2DDB4F711D087A86EDB1B355313363A2DE996B891025E147036087401CCF3CA\
+7815BF3C49:\
+03E39562FE1C30F00F44031F1DB1C8240E859A7267C24A795B5713B7
+
+77EE804B9F3295AB2362798B72B0A1B2D3291DCEB8139896355830F34B3B3285\
+61531F8079B79A6E9980705150866402FDC176C05897E359A6CB1A7AB067383E\
+B497182A7E5AEF7038E4C96D133B2782917417E391535B5E1B51F47D8ED7E4D4\
+025FE98DC87B9C1622614BFF3D1029E68E372DE719803857CA52067CDDAAD958\
+951CB2068CC6:\
+0115CE3021E490ACF0BCC43A69581007196DE30CD63571CEF8D3E87A
+
+B771D5CEF5D1A41A93D15643D7181D2A2EF0A8E84D91812F20ED21F147BEF732\
+BF3A60EF4067C3734B85BC8CD471780F10DC9E8291B58339A677B960218F71E7\
+93F2797AEA349406512829065D37BB55EA796FA4F56FD8896B49B2CD19B43215\
+AD967C712B24E5032D065232E02C127409D2ED4146B9D75D763D52DB98D949D3\
+B0FED6A8052FBB:\
+AEDDDAA1BD1EBC5C77F956A3D45516C8DCD71A598D9EAF31228D969C
+
+B32D95B0B9AAD2A8816DE6D06D1F86008505BD8C14124F6E9A163B5A2ADE55F8\
+35D0EC3880EF50700D3B25E42CC0AF050CCD1BE5E555B23087E04D7BF9813622\
+780C7313A1954F8740B6EE2D3F71F768DD417F520482BD3A08D4F222B4EE9DBD\
+015447B33507DD50F3AB4247C5DE9A8ABD62A8DECEA01E3B87C8B927F5B08BEB\
+37674C6F8E380C04:\
+F22DF9B555059C00C4C6B34443241E2BE287C4228423E2E3BAB2C658
+
+04410E31082A47584B406F051398A6ABE74E4DA59BB6F85E6B49E8A1F7F2CA00\
+DFBA5462C2CD2BFDE8B64FB21D70C083F11318B56A52D03B81CAC5EEC29EB31B\
+D0078B6156786DA3D6D8C33098C5C47BB67AC64DB14165AF65B44544D806DDE5\
+F487D5373C7F9792C299E9686B7E5821E7C8E2458315B996B5677D926DAC57B3\
+F22DA873C601016A0D:\
+B64C633AFFC4FB95643811604DC92A0D177CB0CD8F4210AA9E236E66
+
+8B81E9BADDE026F14D95C019977024C9E13DB7A5CD21F9E9FC491D716164BBAC\
+DC7060D882615D411438AEA056C340CDF977788F6E17D118DE55026855F93270\
+472D1FD18B9E7E812BAE107E0DFDE7063301B71F6CFE4E225CAB3B232905A56E\
+994F08EE2891BA922D49C3DAFEB75F7C69750CB67D822C96176C46BD8A29F170\
+1373FB09A1A6E3C7158F:\
+4937F05A98AC41F57ED57F05D539C791AC867B9AEEEBA56241831036
+
+FA6EED24DA6666A22208146B19A532C2EC9BA94F09F1DEF1E7FC13C399A48E41\
+ACC2A589D099276296348F396253B57CB0E40291BD282773656B6E0D8BEA1CDA\
+084A3738816A840485FCF3FB307F777FA5FEAC48695C2AF4769720258C77943F\
+B4556C362D9CBA8BF103AEB9034BAA8EA8BFB9C4F8E6742CE0D52C49EA8E974F\
+339612E830E9E7A9C29065:\
+4A679F2369429C49AC06BBC518534DE41B0EBDFCC9B2DF08E821215A
+
+9BB4AF1B4F09C071CE3CAFA92E4EB73CE8A6F5D82A85733440368DEE4EB1CBC7\
+B55AC150773B6FE47DBE036C45582ED67E23F4C74585DAB509DF1B8361056454\
+5642B2B1EC463E18048FC23477C6B2AA035594ECD33791AF6AF4CBC2A1166ABA\
+8D628C57E707F0B0E8707CAF91CD44BDB915E0296E0190D56D33D8DDE10B5B60\
+377838973C1D943C22ED335E:\
+35273B8FA54F9A70BC75DB4552F60C4A514368A7A9402879EEA0162B
+
+2167F02118CC62043E9091A647CADBED95611A521FE0D64E8518F16C808AB297\
+725598AE296880A773607A798F7C3CFCE80D251EBEC6885015F9ABF7EAABAE46\
+798F82CB5926DE5C23F44A3F9F9534B3C6F405B5364C2F8A8BDC5CA49C749BED\
+8CE4BA48897062AE8424CA6DDE5F55C0E42A95D1E292CA54FB46A84FBC9CD87F\
+2D0C9E7448DE3043AE22FDD229:\
+C92798112891E82FBCCD7D9B9A4B1718E7D42C15806585073CD4712B
+
+94B7FA0BC1C44E949B1D7617D31B4720CBE7CA57C6FA4F4094D4761567E389EC\
+C64F6968E4064DF70DF836A47D0C713336B5028B35930D29EB7A7F9A5AF9AD5C\
+F441745BAEC9BB014CEEFF5A41BA5C1CE085FEB980BAB9CF79F2158E03EF7E63\
+E29C38D7816A84D4F71E0F548B7FC316085AE38A060FF9B8DEC36F91AD9EBC0A\
+5B6C338CBB8F6659D342A24368CF:\
+94DDDB9B3114070645DBDBB1481EB403204A7AD591D503980C69CC3F
+
+EA40E83CB18B3A242C1ECC6CCD0B7853A439DAB2C569CFC6DC38A19F5C90ACBF\
+76AEF9EA3742FF3B54EF7D36EB7CE4FF1C9AB3BC119CFF6BE93C03E208783335\
+C0AB8137BE5B10CDC66FF3F89A1BDDC6A1EED74F504CBE7290690BB295A872B9\
+E3FE2CEE9E6C67C41DB8EFD7D863CF10F840FE618E7936DA3DCA5CA6DF933F24\
+F6954BA0801A1294CD8D7E66DFAFEC:\
+94338025D8F19FF359D26A8A0DDC47979D3C6F66128FD183C18772DD
+
+157D5B7E4507F66D9A267476D33831E7BB768D4D04CC3438DA12F9010263EA5F\
+CAFBDE2579DB2F6B58F911D593D5F79FB05FE3596E3FA80FF2F761D1B0E57080\
+055C118C53E53CDB63055261D7C9B2B39BD90ACC32520CBBDBDA2C4FD8856DBC\
+EE173132A2679198DAF83007A9B5C51511AE49766C792A29520388444EBEFE28\
+256FB33D4260439CBA73A9479EE00C63:\
+F42AFC3BE1202040D2145385038A9CB2E28609388F443884014A8A26
+
+836B34B515476F613FE447A4E0C3F3B8F20910AC89A3977055C960D2D5D2B72B\
+D8ACC715A9035321B86703A411DDE0466D58A59769672AA60AD587B8481DE4BB\
+A552A1645779789501EC53D540B904821F32B0BD1855B04E4848F9F8CFE9EBD8\
+911BE95781A759D7AD9724A7102DBE576776B7C632BC39B9B5E19057E226552A\
+5994C1DBB3B5C7871A11F5537011044C53:\
+D6E224CF1ADEE925664DAE5BEE27C9B0EA249A267882F955C4C92ACE
+
+CC7784A4912A7AB5AD3620AAB29BA87077CD3CB83636ADC9F3DC94F51EDF521B\
+2161EF108F21A0A298557981C0E53CE6CED45BDF782C1EF200D29BAB81DD6460\
+586964EDAB7CEBDBBEC75FD7925060F7DA2B853B2B089588FA0F8C16EC6498B1\
+4C55DCEE335CB3A91D698E4D393AB8E8EAC0825F8ADEBEEE196DF41205C01167\
+4E53426CAA453F8DE1CBB57932B0B741D4C6:\
+6B14C7A19F6B14AA1CD6CB4218DB66716E994E78C2D5A43DD4464273
+
+7639B461FFF270B2455AC1D1AFCE782944AEA5E9087EB4A39EB96BB5C3BAAF0E\
+868C8526D3404F9405E79E77BFAC5FFB89BF1957B523E17D341D7323C302EA70\
+83872DD5E8705694ACDDA36D5A1B895AAA16ECA6104C82688532C8BFE1790B5D\
+C9F4EC5FE95BAED37E1D287BE710431F1E5E8EE105BC42ED37D74B1E55984BF1\
+C09FE6A1FA13EF3B96FAEAED6A2A1950A12153:\
+64A7FDC77F564F849A72FA360B6441CB068C99F90AD16A7937755E02
+
+EB6513FC61B30CFBA58D4D7E80F94D14589090CF1D80B1DF2E68088DC6104959\
+BA0D583D585E9578AB0AEC0CF36C48435EB52ED9AB4BBCE7A5ABE679C97AE2DB\
+E35E8CC1D45B06DDA3CF418665C57CBEE4BBB47FA4CAF78F4EE656FEC237FE4E\
+EBBAFA206E1EF2BD0EE4AE71BD0E9B2F54F91DAADF1FEBFD7032381D636B733D\
+CB3BF76FB14E23AFF1F68ED3DBCF75C9B99C6F26:\
+68807BF2E0A3AB42C258B3031A74D4870AFEF475D231434F957B14EE
+
+1594D74BF5DDE444265D4C04DAD9721FF3E34CBF622DAF341FE16B96431F6C4D\
+F1F760D34F296EB97D98D560AD5286FEC4DCE1724F20B54FD7DF51D4BF137ADD\
+656C80546FB1BF516D62EE82BAA992910EF4CC18B70F3F8698276FCFB44E0EC5\
+46C2C39CFD8EE91034FF9303058B4252462F86C823EB15BF481E6B79CC3A0221\
+8595B3658E8B37382BD5048EAED5FD02C37944E73B:\
+1F0B5A43F9E9BB7F34C253133CA52B5CBB4111D4226F1F81F7243707
+
+4CFA1278903026F66FEDD41374558BE1B585D03C5C55DAC94361DF286D4BD39C\
+7CB8037ED3B267B07C346626449D0CC5B0DD2CF221F7E4C3449A4BE99985D2D5\
+E67BFF2923357DDEAB5ABCB4619F3A3A57B2CF928A022EB27676C6CF80568900\
+4FCA4D41EA6C2D0A4789C7605F7BB838DD883B3AD3E6027E775BCF2628814280\
+99C7FFF95B14C095EA130E0B9938A5E22FC52650F591:\
+CF61ECF3F61415CF44D166A289A597A88F752C3D2AD546A27C00E764
+
+D3E65CB92CFA79662F6AF493D696A07CCF32AAADCCEFF06E73E8D9F6F909209E\
+66715D6E978788C49EFB9087B170ECF3AA86D2D4D1A065AE0EFC8924F365D676\
+B3CB9E2BEC918FD96D0B43DEE83727C9A93BF56CA2B2E59ADBA85696546A8150\
+67FC7A78039629D4948D157E7B0D826D1BF8E81237BAB7321312FDAA4D521744\
+F988DB6FDF04549D0FDCA393D639C729AF716E9C8BBA48:\
+DF256A3D4CD87130377616F00727CAC501317FD8EDCBDFE0F530A83A
+
+842CC583504539622D7F71E7E31863A2B885C56A0BA62DB4C2A3F2FD12E79660\
+DC7205CA29A0DC0A87DB4DC62EE47A41DB36B9DDB3293B9AC4BAAE7DF5C6E720\
+1E17F717AB56E12CAD476BE49608AD2D50309E7D48D2D8DE4FA58AC3CFEAFEEE\
+48C0A9EEC88498E3EFC51F54D300D828DDDCCB9D0B06DD021A29CF5CB5B25069\
+15BEB8A11998B8B886E0F9B7A80E97D91A7D01270F9A7717:\
+484A17B4E7F8B00935ED84391EA0874D5D8AAB59B833051EBB49CB15
+
+6C4B0A0719573E57248661E98FEBE326571F9A1CA813D3638531AE28B4860F23\
+C3A3A8AC1C250034A660E2D71E16D3ACC4BF9CE215C6F15B1C0FC7E77D3D2715\
+7E66DA9CEEC9258F8F2BF9E02B4AC93793DD6E29E307EDE3695A0DF63CBDC0FC\
+66FB770813EB149CA2A916911BEE4902C47C7802E69E405FE3C04CEB5522792A\
+5503FA829F707272226621F7C488A7698C0D69AA561BE9F378:\
+D337A2B8AB0AF673676067BE9BC271D3CDC033B72B83934211ADCAD3
+
+51B7DBB7CE2FFEB427A91CCFE5218FD40F9E0B7E24756D4C47CD55606008BDC2\
+7D16400933906FD9F30EFFDD4880022D081155342AF3FB6CD53672AB7FB5B3A3\
+BCBE47BE1FD3A2278CAE8A5FD61C1433F7D350675DD21803746CADCA574130F0\
+1200024C6340AB0CC2CF74F2234669F34E9009EF2EB94823D62B31407F4BA46F\
+1A1EEC41641E84D77727B59E746B8A671BEF936F05BE820759FA:\
+9457724687C625B7F1F23F27514A04AFB1FD9A9FC0DD603A392A82C4
+
+83599D93F5561E821BD01A472386BC2FF4EFBD4AED60D5821E84AAE74D807102\
+9810F5E286F8F17651CD27DA07B1EB4382F754CD1C95268783AD09220F550284\
+0370D494BEB17124220F6AFCE91EC8A0F55231F9652433E5CE3489B727716CF4\
+AEBA7DCDA20CD29AA9A859201253F948DD94395ABA9E3852BD1D60DDA7AE5DC0\
+45B283DA006E1CBAD83CC13292A315DB5553305C628DD091146597:\
+91D56808DFD6F719BC8D80668C53994122CC2596C9B1763B12BBF78C
+
+2BE9BF526C9D5A75D565DD11EF63B979D068659C7F026C08BEA4AF161D85A462\
+D80E45040E91F4165C074C43AC661380311A8CBED59CC8E4C4518E80CD2C78AB\
+1CABF66BFF83EAB3A80148550307310950D034A6286C93A1ECE8929E6385C5E3\
+BB6EA8A7C0FB6D6332E320E71CC4EB462A2A62E2BFE08F0CCAD93E61BEDB5DD0\
+B786A728AB666F07E0576D189C92BF9FB20DCA49AC2D3956D47385E2:\
+84769A9F80414A9A9FC161E2543CC6759769210D42042F6904FB259B
+
+CA76D3A12595A817682617006848675547D3E8F50C2210F9AF906C0E7CE50B44\
+60186FE70457A9E879E79FD4D1A688C70A347361C847BA0DD6AA52936EAF8E58\
+A1BE2F5C1C704E20146D366AEB3853BED9DE9BEFE9569AC8AAEA37A9FB7139A1\
+A1A7D5C748605A8DEFB297869EBEDD71D615A5DA23496D11E11ABBB126B206FA\
+0A7797EE7DE117986012D0362DCEF775C2FE145ADA6BDA1CCB326BF644:\
+E2164A2FE936AD8FD9B736D8FBBC5E5BB5716756E7F4BF6B193AC39A
+
+F76B85DC67421025D64E93096D1D712B7BAF7FB001716F02D33B2160C2C882C3\
+10EF13A576B1C2D30EF8F78EF8D2F465007109AAD93F74CB9E7D7BEF7C9590E8\
+AF3B267C89C15DB238138C45833C98CC4A471A7802723EF4C744A853CF80A0C2\
+568DD4ED58A2C9644806F42104CEE53628E5BDF7B63B0B338E931E31B87C24B1\
+46C6D040605567CEEF5960DF9E022CB469D4C787F4CBA3C544A1AC91F95F:\
+B917878D9BD7BBBA6FD213B92F17D729702916088B4E15AA0F8F2EA0
+
+25B8C9C032EA6BCD733FFC8718FBB2A503A4EA8F71DEA1176189F694304F0FF6\
+8E862A8197B839957549EF243A5279FC2646BD4C009B6D1EDEBF24738197ABB4\
+C992F6B1DC9BA891F570879ACCD5A6B18691A93C7D0A8D38F95B639C1DAEB48C\
+4C2F15CCF5B9D508F8333C32DE78781B41850F261B855C4BEBCC125A380C54D5\
+01C5D3BD07E6B52102116088E53D76583B0161E2A58D0778F091206AABD5A1:\
+29E930630830092DF0D4E19D63939750F11B79B9FDAD2EBC1B036C92
+
+21CFDC2A7CCB7F331B3D2EEFFF37E48AD9FA9C788C3F3C200E0173D99963E1CB\
+CA93623B264E920394AE48BB4C3A5BB96FFBC8F0E53F30E22956ADABC2765F57\
+FB761E147ECBF8567533DB6E50C8A1F894310A94EDF806DD8CA6A0E141C0FA7C\
+9FAE6C6AE65F18C93A8529E6E5B553BF55F25BE2E80A9882BD37F145FECBEB3D\
+447A3C4E46C21524CC55CDD62F521AB92A8BA72B897996C49BB273198B7B1C9E:\
+BFA7E3153C86ACEF9C12F5B918C8F33395ED19FC49F81D7F428A46AB
+
+4E452BA42127DCC956EF4F8F35DD68CB225FB73B5BC7E1EC5A898BBA2931563E\
+74FAFF3B67314F241EC49F4A7061E3BD0213AE826BAB380F1F14FAAB8B0EFDDD\
+5FD1BB49373853A08F30553D5A55CCBBB8153DE4704F29CA2BDEEF0419468E05\
+DD51557CCC80C0A96190BBCC4D77ECFF21C66BDF486459D427F986410F883A80\
+A5BCC32C20F0478BB9A97A126FC5F95451E40F292A4614930D054C851ACD019C\
+CF:\
+738DC6B191C7EAE75A2A432876ABD8E4BF4849B818BCAFDACA17653D
+
+FA85671DF7DADF99A6FFEE97A3AB9991671F5629195049880497487867A6C446\
+B60087FAC9A0F2FCC8E3B24E97E42345B93B5F7D3691829D3F8CCD4BB36411B8\
+5FC2328EB0C51CB3151F70860AD3246CE0623A8DC8B3C49F958F8690F8E3860E\
+71EB2B1479A5CEA0B3F8BEFD87ACAF5362435EAECCB52F38617BC6C5C2C6E269\
+EAD1FBD69E941D4AD2012DA2C5B21BCFBF98E4A77AB2AF1F3FDA3233F046D38F\
+1DC8:\
+73FAFCF89E546762076C9535A215A79B1E4B8628F7D4E19D42761790
+
+E90847AE6797FBC0B6B36D6E588C0A743D725788CA50B6D792352EA8294F5BA6\
+54A15366B8E1B288D84F5178240827975A763BC45C7B0430E8A559DF4488505E\
+009C63DA994F1403F407958203CEBB6E37D89C94A5EACF6039A327F6C4DBBC7A\
+2A307D976AA39E41AF6537243FC218DFA6AB4DD817B6A397DF5CA69107A91987\
+99ED248641B63B42CB4C29BFDD7975AC96EDFC274AC562D0474C60347A078CE4\
+C25E88:\
+13257FC53DC8829C29AAAA1035788815F7117C03AEA369B1AFB1FFAE
+
+F6D5C2B6C93954FC627602C00C4CA9A7D3ED12B27173F0B2C9B0E4A5939398A6\
+65E67E69D0B12FB7E4CEB253E8083D1CEB724AC07F009F094E42F2D6F2129489\
+E846EAFF0700A8D4453EF453A3EDDC18F408C77A83275617FABC4EA3A2833AA7\
+3406C0E966276079D38E8E38539A70E194CC5513AAA457C699383FD1900B1E72\
+BDFB835D1FD321B37BA80549B078A49EA08152869A918CA57F5B54ED71E4FD3A\
+C5C06729:\
+395D486F2C3489278E96BC494CDEC507DA9AD166B42FA084EC044371
+
+CF8562B1BED89892D67DDAAF3DEEB28246456E972326DBCDB5CF3FB289ACA01E\
+68DA5D59896E3A6165358B071B304D6AB3D018944BE5049D5E0E2BB819ACF67A\
+6006111089E6767132D72DD85BEDDCBB2D64496DB0CC92955AB4C6234F1EEA24\
+F2D51483F2E209E4589BF9519FAC51B4D061E801125E605F8093BB6997BC163D\
+551596FE4AB7CFAE8FB9A90F6980480CE0C229FD1675409BD788354DAF316240\
+CFE0AF93EB:\
+2C90DCD95DAF28199E8D44A61ADBBE0D2AFDCE6E1EB8DD5EE7CE8419
+
+2ACE31ABB0A2E3267944D2F75E1559985DB7354C6E605F18DC8470423FCA30B7\
+331D9B33C4A4326783D1CAAE1B4F07060EFF978E4746BF0C7E30CD61040BD5EC\
+2746B29863EB7F103EBDA614C4291A805B6A4C8214230564A0557BC7102E0BD3\
+ED23719252F7435D64D210EE2AAFC585BE903FA41E1968C50FD5D5367926DF7A\
+05E3A42CF07E656FF92DE73B036CF8B19898C0CB34557C0C12C2D8B84E91181A\
+F467BC75A9D1:\
+F3B9C6B3CC0B3A1680B7834E341D26CA4CB6869EB91BA61EE7BA860E
+
+0D8D09AED19F1013969CE5E7EB92F83A209AE76BE31C754844EA9116CEB39A22\
+EBB6003017BBCF26555FA6624185187DB8F0CB3564B8B1C06BF685D47F3286ED\
+A20B83358F599D2044BBF0583FAB8D78F854FE0A596183230C5EF8E54426750E\
+AF2CC4E29D3BDD037E734D863C2BD9789B4C243096138F7672C232314EFFDFC6\
+513427E2DA76916B5248933BE312EB5DDE4CF70804FB258AC5FB82D58D08177A\
+C6F4756017FFF5:\
+ECFE64459ED2FFE61B8DB24E3655C59173A9E44294EA3FD2E3981905
+
+C3236B73DEB7662BF3F3DAA58F137B358BA610560EF7455785A9BEFDB035A066\
+E90704F929BD9689CEF0CE3BDA5ACF4480BCEB8D09D10B098AD8500D9B6071DF\
+C3A14AF6C77511D81E3AA8844986C3BEA6F469F9E02194C92868CD5F51646256\
+798FF0424954C1434BDFED9FACB390B07D342E992936E0F88BFD0E884A0DDB67\
+9D0547CCDEC6384285A45429D115AC7D235A717242021D1DC35641F5F0A48E84\
+45DBA58E6CB2C8EA:\
+13A162EE3FAFC7D305DE4E705A901C91BCBDBFB80E43439237998445
+
+B39FEB8283EADC63E8184B51DF5AE3FD41AAC8A963BB0BE1CD08AA5867D8D910\
+C669221E73243360646F6553D1CA05A84E8DC0DE05B6419EC349CA994480193D\
+01C92525F3FB3DCEFB08AFC6D26947BDBBFD85193F53B50609C6140905C53A66\
+86B58E53A319A57B962331EDE98149AF3DE3118A819DA4D76706A0424B4E1D29\
+10B0ED26AF61D150EBCB46595D4266A0BD7F651BA47D0C7F179CA28545007D92\
+E8419D48FDFBD744CE:\
+301F2A019345965B60A17A2B04068492FF16F5BD1730EE3A3CA56C6E
+
+A983D54F503803E8C7999F4EDBBE82E9084F422143A932DDDDC47A17B0B7564A\
+7F37A99D0786E99476428D29E29D3C197A72BFAB1342C12A0FC4787FD7017D7A\
+6174049EA43B5779169EF7472BDBBD941DCB82FC73AAC45A8A94C9F2BD3477F6\
+1FD3B796F02A1B8264A214C6FEA74B7051B226C722099EC7883A462B83B6AFDD\
+4009248B8A237F605FE5A08FE7D8B45321421EBBA67BD70A0B00DDBF94BAAB7F\
+359D5D1EEA105F28DCFB:\
+B3FE0C069F44C79AEC45357012C26F3351304B9F5DD67C860867465E
+
+E4D1C1897A0A866CE564635B74222F9696BF2C7F640DD78D7E2ACA66E1B61C64\
+2BB03EA7536AAE597811E9BF4A7B453EDE31F97B46A5F0EF51A071A2B3918DF1\
+6B152519AE3776F9F1EDAB4C2A377C3292E96408359D3613844D5EB393000283\
+D5AD3401A318B12FD1474B8612F2BB50FB6A8B9E023A54D7DDE28C43D6D8854C\
+8D9D1155935C199811DBFC87E9E0072E90EB88681CC7529714F8FB8A2C9D8856\
+7ADFB974EE205A9BF7B848:\
+EED8BF12A5609A417E4BC6B215F9A1814D86A57C79F5F768C85BC0AE
+
+B10C59723E3DCADD6D75DF87D0A1580E73133A9B7D00CB95EC19F5547027323B\
+E75158B11F80B6E142C6A78531886D9047B08E551E75E6261E79785366D7024B\
+D7CD9CF322D9BE7D57FB661069F2481C7BB759CD71B4B36CA2BC2DF6D3A328FA\
+EBDB995A9794A8D72155ED551A1F87C80BF6059B43FC764900B18A1C2441F748\
+7743CF84E565F61F8DD2ECE6B6CCC9444049197AAAF53E926FBEE3BFCA8BE588\
+EC77F29D211BE89DE18B15F6:\
+38B126F85C57E8E30BE3DE75D09225BB317BC9D2F59FD5408CDA73E1
+
+DB11F609BABA7B0CA634926B1DD539C8CBADA24967D7ADD4D9876F77C2D80C0F\
+4DCEFBD7121548373582705CCA2495BD2A43716FE64ED26D059CFB566B3364BD\
+49EE0717BDD9810DD14D8FAD80DBBDC4CAFB37CC60FB0FE2A80FB4541B8CA9D5\
+9DCE457738A9D3D8F641AF8C3FD6DA162DC16FC01AAC527A4A0255B4D231C0BE\
+50F44F0DB0B713AF03D968FE7F0F61ED0824C55C4B5265548FEBD6AAD5C5EEDF\
+63EFE793489C39B8FD29D104CE:\
+44695E9983D11A5A83EFD4E5D65D4AC3F7751C84B9CFFB74CF8D5092
+
+BEBD4F1A84FC8B15E4452A54BD02D69E304B7F32616AADD90537937106AE4E28\
+DE9D8AAB02D19BC3E2FDE1D651559E296453E4DBA94370A14DBBB2D1D4E20223\
+02EE90E208321EFCD8528AD89E46DC839EA9DF618EA8394A6BFF308E7726BAE0\
+C19BCD4BE52DA6258E2EF4E96AA21244429F49EF5CB486D7FF35CAC1BACB7E95\
+711944BCCB2AB34700D42D1EB38B5D536B947348A458EDE3DC6BD6EC547B1B0C\
+AE5B257BE36A7124E1060C170FFA:\
+51B4A0AE4D12D2D8275B81DFF10C09FC8F650FCCE3E216CB8AB2F191
+
+5ACA56A03A13784BDC3289D9364F79E2A85C12276B49B92DB0ADAA4F206D5028\
+F213F678C3510E111F9DC4C1C1F8B6ACB17A6413AA227607C515C62A733817BA\
+5E762CC6748E7E0D6872C984D723C9BB3B117EB8963185300A80BFA65CDE495D\
+70A46C44858605FCCBED086C2B45CEF963D33294DBE9706B13AF22F1B7C4CD5A\
+001CFEC251FBA18E722C6E1C4B1166918B4F6F48A98B64B3C07FC86A6B17A6D0\
+480AB79D4E6415B520F1C484D675B1:\
+CBA2209C564DF70242EEC7DA8962EF2089592F623B6D35ED70BD9E86
+
+A5AAD0E4646A32C85CFCAC73F02FC5300F1982FABB2F2179E28303E447854094\
+CDFC854310E5C0F60993CEFF54D84D6B46323D930ADB07C17599B35B505F09E7\
+84BCA5985E0172257797FB53649E2E9723EFD16865C31B5C3D5113B58BB0BFC8\
+920FABDDA086D7537E66D709D050BD14D0C960873F156FAD5B3D3840CDFCDC9B\
+E6AF519DB262A27F40896AB25CC39F96984D650611C0D5A3080D5B3A1BF186AB\
+D42956588B3B58CD948970D298776060:\
+945C6513694D0ECE506D195FA100FB28AA9141D6ACCE2696CD1F877F
+
+06CBBE67E94A978203EAD6C057A1A5B098478B4B4CBEF5A97E93C8E42F557271\
+3575FC2A884531D7622F8F879387A859A80F10EF02708CD8F7413AB385AFC357\
+678B9578C0EBF641EF076A1A30F1F75379E9DCB2A885BDD295905EE80C0168A6\
+2A9597D10CF12DD2D8CEE46645C7E5A141F6E0E23AA482ABE5661C16E69EF1E2\
+8371E2E236C359BA4E92C25626A7B7FF13F6EA4AE906E1CFE163E91719B1F750\
+A96CBDE5FBC953D9E576CD216AFC90323A:\
+C54C64C65C2DD6AD413D0D412897F29BC220D50481A8E584C7EEF205
+
+F1C528CF7739874707D4D8AD5B98F7C77169DE0B57188DF233B2DC8A5B31EDA5\
+DB4291DD9F68E6BAD37B8D7F6C9C0044B3BF74BBC3D7D1798E138709B0D75E7C\
+593D3CCCDC1B20C7174B4E692ADD820ACE262D45CCFAE2077E87879634716806\
+0A162ECCA8C38C1A88350BD63BB539134F700FD4ADDD5959E255337DAA06BC86\
+358FABCBEFDFB5BC889783D843C08AADC6C4F6C36F65F156E851C9A0F917E4A3\
+67B5AD93D874812A1DE6A7B93CD53AD97232:\
+FC3ABB92CC894EE736B19F12C03FE79789AB4A84DB6103FE9B989739
+
+9D9F3A7ECD51B41F6572FD0D0881E30390DFB780991DAE7DB3B47619134718E6\
+F987810E542619DFAA7B505C76B7350C6432D8BF1CFEBDF1069B90A35F0D04CB\
+DF130B0DFC7875F4A4E62CDB8E525AADD7CE842520A482AC18F09442D78305FE\
+85A74E39E760A4837482ED2F437DD13B2EC1042AFCF9DECDC3E877E50FF4106A\
+D10A525230D11920324A81094DA31DEAB6476AA42F20C84843CFC1C58545EE80\
+352BDD3740DD6A16792AE2D86F11641BB717C2:\
+3DA07988CC99EC6D87DBC8904DA8876D8E0A73976BB8489C807B3375
+
+5179888724819FBAD3AFA927D3577796660E6A81C52D98E9303261D5A4A83232\
+F6F758934D50AA83FF9E20A5926DFEBAAC49529D006EB923C5AE5048ED544EC4\
+71ED7191EDF46363383824F915769B3E688094C682B02151E5EE01E510B431C8\
+865AFF8B6B6F2F59CB6D129DA79E97C6D2B8FA6C6DA3F603199D2D1BCAB54768\
+2A81CD6CF65F6551121391D78BCC23B5BD0E922EC6D8BF97C952E84DD28AEF90\
+9ABA31EDB903B28FBFC33B7703CD996215A11238:\
+F1CBE43C4AB525B2A6CB836476E4FE3DC8FB41052F0A72C56843B09C
+
+576EF3520D30B7A4899B8C0D5E359E45C5189ADD100E43BE429A02FB3DE5FF4F\
+8FD0E79D9663ACCA72CD29C94582B19292A557C5B1315297D168FBB54E9E2ECD\
+13809C2B5FCE998EDC6570545E1499DBE7FB74D47CD7F35823B212B05BF3F5A7\
+9CAA34224FDD670D335FCB106F5D92C3946F44D3AFCBAE2E41AC554D8E6759F3\
+32B76BE89A0324AA12C5482D1EA3EE89DED4936F3E3C080436F539FA137E74C6\
+D3389BDF5A45074C47BC7B20B0948407A66D855E2F:\
+257A1A08B24AF74D0FBE5637A736F6E1526301961D20B9C2F1323FBA
+
+0DF2152FA4F4357C8741529DD77E783925D3D76E95BAFA2B542A2C33F3D1D117\
+D159CF473F82310356FEE4C90A9E505E70F8F24859656368BA09381FA245EB6C\
+3D763F3093F0C89B972E66B53D59406D9F01AEA07F8B3B615CAC4EE4D05F542E\
+7D0DAB45D67CCCCD3A606CCBEB31EA1FA7005BA07176E60DAB7D78F6810EF086\
+F42F08E595F0EC217372B98970CC6321576D92CE38F7C397A403BADA1548D205\
+C343AC09DECA86325373C3B76D9F32028FEA8EB32515:\
+13C10F28096473B2C9CF8C6B44ED9A10491919C911450831658E6B0B
+
+3E15350D87D6EBB5C8AD99D42515CFE17980933C7A8F6B8BBBF0A63728CEFAAD\
+2052623C0BD5931839112A48633FB3C2004E0749C87A41B26A8B48945539D1FF\
+41A4B269462FD199BFECD45374756F55A9116E92093AC99451AEFB2AF9FD32D6\
+D7F5FBC7F7A540D5097C096EBC3B3A721541DE073A1CC02F7FB0FB1B9327FB0B\
+1218CA49C9487AB5396622A13AE546C97ABDEF6B56380DDA7012A8384091B665\
+6D0AB272D363CEA78163FF765CDD13AB1738B940D16CAE:\
+561AA276D17621468FDC21ED81BD9EDA4711F9524CAF054AA1CFC1EB
+
+C38D6B0B757CB552BE40940ECE0009EF3B0B59307C1451686F1A22702922800D\
+58BCE7A636C1727EE547C01B214779E898FC0E560F8AE7F61BEF4D75EAA696B9\
+21FD6B735D171535E9EDD267C192B99880C87997711002009095D8A7A437E258\
+104A41A505E5EF71E5613DDD2008195F0C574E6BA3FE40099CFA116E5F1A2FA8\
+A6DA04BADCB4E2D5D0DE31FDC4800891C45781A0AAC7C907B56D631FCA5CE8B2\
+CDE620D11D1777ED9FA603541DE794DDC5758FCD5FAD78C0:\
+6830C20140483E52232218E34F30803CF8BC981C3D0B755AA4F4F22D
+
+8D2DE3F0B37A6385C90739805B170057F091CD0C7A0BC951540F26A5A75B3E69\
+4631BB64C7635EED316F51318E9D8DE13C70A2ABA04A14836855F35E480528B7\
+76D0A1E8A23B547C8B8D6A0D09B241D3BE9377160CCA4E6793D00A515DC2992C\
+B7FC741DACA171431DA99CCE6F7789F129E2AC5CF65B40D703035CD2185BB936\
+C82002DAF8CBC27A7A9E554B06196630446A6F0A14BA155ED26D95BD627B7205\
+C072D02B60DB0FD7E49EA058C2E0BA202DAFF0DE91E845CF79:\
+7CB804CC3A8FF2E2BEDC28643E81D9F926A9B94E7E6AC031AEAE01B9
+
+C464BBDAD275C50DCD983B65AD1019B9FF85A1E71C807F3204BB2C921DC31FBC\
+D8C5FC45868AE9EF85B6C9B83BBA2A5A822201ED68586EC5EC27FB2857A5D1A2\
+D09D09115F22DCC39FE61F5E1BA0FF6E8B4ACB4C6DA748BE7F3F0839739394FF\
+7FA8E39F7F7E84A33C3866875C01BCB1263C9405D91908E9E0B50E7459FABB63\
+D8C6BBB73D8E3483C099B55BC30FF092FF68B6ADEDFD477D63570C9F5515847F\
+36E24BA0B705557130CEC57EBAD1D0B31A378E91894EE26E3A04:\
+CC8B8FCE54C49DDFA044FDB1C2588676B086C3A002B689551235833D
+
+8B8D68BB8A75732FE272815A68A1C9C5AA31B41DEDC8493E76525D1D013D33CE\
+BD9E21A5BB95DB2616976A8C07FCF411F5F6BC6F7E0B57ACA78CC2790A6F9B89\
+8858AC9C79B165FF24E66677531E39F572BE5D81EB3264524181115F32780257\
+BFB9AEEC6AF12AF28E587CAC068A1A2953B59AD680F4C245B2E3EC36F59940D3\
+7E1D3DB38E13EDB29B5C0F404F6FF87F80FC8BE7A225FF22FBB9C8B6B1D7330C\
+57840D24BC75B06B80D30DAD6806544D510AF6C4785E823AC3E0B8:\
+5613CA11E7014D81F4CB33DFFFD67F57895837FD9FB1438A0647A6CD
+
+6B018710446F368E7421F1BC0CCF562D9C1843846BC8D98D1C9BF7D9D6FCB48B\
+FC3BF83B36D44C4FA93430AF75CD190BDE36A7F92F867F58A803900DF8018150\
+384D85D82132F123006AC2AEBA58E02A037FE6AFBD65ECA7C44977DD3DC74F48\
+B6E7A1BFD5CC4DCF24E4D52E92BD4455848E4928B0EAC8B7476FE3CC03E862AA\
+4DFF4470DBFED6DE48E410F25096487ECFC32A27277F3F5023B2725ADE461B13\
+55889554A8836C9CF53BD767F5737D55184EEA1AB3F53EDD0976C485:\
+DB93BE7FA7F15CB5C13611BFACEC7CB602BA218A8174E2C166A6BA67
+
+C9534A24714BD4BE37C88A3DA1082EDA7CABD154C309D7BD670DCCD95AA53559\
+4463058A29F79031D6ECAA9F675D1211E9359BE82669A79C855EA8D89DD38C2C\
+761DDD0EC0CE9E97597432E9A1BEAE062CDD71EDFDFD464119BE9E69D18A7A7F\
+D7CE0E2106F0C8B0ABF4715E2CA48EF9F454DC203C96656653B727083513F8EF\
+B86E49C513BB758B3B052FE21F1C05BB33C37129D6CC81F1AEF6ADC45B0E8827\
+A830FE545CF57D0955802C117D23CCB55EA28F95C0D8C2F9C5A242B33F:\
+08C09E713A7EB4DF5246CC69366E8D1697B5EB173FD0C44205A80F73
+
+07906C87297B867ABF4576E9F3CC7F82F22B154AFCBF293B9319F1B0584DA6A4\
+0C27B32E0B1B7F412C4F1B82480E70A9235B12EC27090A5A33175A2BB28D8ADC\
+475CEFE33F7803F8CE27967217381F02E67A3B4F84A71F1C5228E0C2AD971373\
+F6F672624FCEA8D1A9F85170FAD30FA0BBD25035C3B41A6175D467998BD1215F\
+6F3866F53847F9CF68EF3E2FBB54BC994DE2302B829C5EEA68EC441FCBAFD7D1\
+6AE4FE9FFF98BF00E5BC2AD54DD91FF9FDA4DD77B6C754A91955D1FBAAD0:\
+24EDABEB8415BDCD3607B5BFE50696D0296D334DA195C8667E1756BA
+
+588E94B9054ABC2189DF69B8BA34341B77CDD528E7860E5DEFCAA79B0C9A452A\
+D4B82AA306BE84536EB7CEDCBE058D7B84A6AEF826B028B8A0271B69AC3605A9\
+635EA9F5EA0AA700F3EB7835BC54611B922964300C953EFE7491E3677C2CEBE0\
+822E956CD16433B02C68C4A23252C3F9E151A416B4963257B783E038F6B4D5C9\
+F110F871652C7A649A7BCEDCBCCC6F2D0725BB903CC196BA76C76AA9F10A190B\
+1D1168993BAA9FFC96A1655216773458BEC72B0E39C9F2C121378FEAB4E76A:\
+671CEE30617D425D03059E1AD4E732FC1B935F00B789DB7697C95305
+
+08959A7E4BAAE874928813364071194E2939772F20DB7C3157078987C557C2A6\
+D5ABE68D520EEF3DC491692E1E21BCD880ADEBF63BB4213B50897FA005256ED4\
+1B5690F78F52855C8D9168A4B666FCE2DA2B456D7A7E7C17AB5F2FB1EE90B79E\
+698712E963715983FD07641AE4B4E9DC73203FAC1AE11FA1F8C7941FCC82EAB2\
+47ADDB56E2638447E9D609E610B60CE086656AAEBF1DA3C8A231D7D94E2FD0AF\
+E46B391FF14A72EAEB3F44AD4DF85866DEF43D4781A0B3578BC996C87970B132:\
+4C33B12F057C7F95062BFD138EBFCF995A482E427653EF09A9CA91A9
+
+CB2A234F45E2ECD5863895A451D389A369AAB99CFEF0D5C9FFCA1E6E63F763B5\
+C14FB9B478313C8E8C0EFEB3AC9500CF5FD93791B789E67EAC12FD038E2547CC\
+8E0FC9DB591F33A1E4907C64A922DDA23EC9827310B306098554A4A78F050262\
+DB5B545B159E1FF1DCA6EB734B872343B842C57EAFCFDA8405EEDBB48EF32E99\
+696D135979235C3A05364E371C2D76F1902F1D83146DF9495C0A6C57D7BF9EE7\
+7E80F9787AEE27BE1FE126CDC9EF893A4A7DCBBC367E40FE4E1EE90B42EA25AF\
+01:\
+670B25B14DB350162266995D7FE07C35C65EDE762D04F5360DC17FD3
+
+D16BEADF02AB1D4DC6F88B8C4554C51E866DF830B89C06E786A5F8757E890931\
+0AF51C840EFE8D20B35331F4355D80F73295974653DDD620CDDE4730FB6C8D0D\
+2DCB2B45D92D4FBDB567C0A3E86BD1A8A795AF26FBF29FC6C65941CDDB090FF7\
+CD230AC5268AB4606FCCBA9EDED0A2B5D014EE0C34F0B2881AC036E24E151BE8\
+9EEB6CD9A7A790AFCCFF234D7CB11B99EBF58CD0C589F20BDAC4F9F0E28F75E3\
+E04E5B3DEBCE607A496D848D67FA7B49132C71B878FD5557E082A18ECA1FBDA9\
+4D4B:\
+A439D6AB94388991C1BAEBC8E009295CE012CC1378D0733C9894F37C
+
+8F65F6BC59A85705016E2BAE7FE57980DE3127E5AB275F573D334F73F8603106\
+EC3553016608EF2DD6E69B24BE0B7113BF6A760BA6E9CE1C48F9E186012CF96A\
+1D4849D75DF5BB8315387FD78E9E153E76F8BA7EC6C8849810F59FB4BB9B0043\
+18210B37F1299526866F44059E017E22E96CBE418699D014C6EA01C9F0038B10\
+299884DBEC3199BB05ADC94E955A1533219C1115FED0E5F21228B071F40DD57C\
+4240D98D37B73E412FE0FA4703120D7C0C67972ED233E5DEB300A22605472FA3\
+A3BA86:\
+6A36CC8B19BC8C7A319237B2A97D0943A286EDD5D5D51F334CBC28CF
+
+84891E52E0D451813210C3FD635B39A03A6B7A7317B221A7ABC270DFA946C426\
+69AACBBBDF801E1584F330E28C729847EA14152BD637B3D0F2B38B4BD5BF9C79\
+1C58806281103A3EABBAEDE5E711E539E6A8B2CF297CF351C078B4FA8F7F35CF\
+61BEBF8814BF248A01D41E86C5715EA40C63F7375379A7EB1D78F27622FB468A\
+B784AAABA4E534A6DFD1DF6FA15511341E725ED2E87F98737CCB7B6A6DFAE416\
+477472B046BF1811187D151BFA9F7B2BF9ACDB23A3BE507CDF14CFDF517D2CB5\
+FB9E4AB6:\
+DEDB114F80BEDC104D53AD842F53950A940D3B70E92C01181CC987E6
+
+FDD7A9433A3B4AFABD7A3A5E3457E56DEBF78E84B7A0B0CA0E8C6D53BD0C2DAE\
+31B2700C6128334F43981BE3B213B1D7A118D59C7E6B6493A86F866A1635C128\
+59CFB9AD17460A77B4522A5C1883C3D6ACC86E6162667EC414E9A104AA892053\
+A2B1D72165A855BACD8FAF8034A5DD9B716F47A0818C09BB6BAF22AA503C06B4\
+CA261F557761989D2AFBD88B6A678AD128AF68672107D0F1FC73C5CA74045929\
+7B3292B281E93BCEB761BDE7221C3A55708E5EC84472CDDCAA84ECF23723CC09\
+91355C6280:\
+129FBF7A9C1833F1701EB37002CB26D44781F2F63D69E264E42F9308
+
+70A40BFBEF92277A1AAD72F6B79D0177197C4EBD432668CFEC05D099ACCB6510\
+62B5DFF156C0B27336687A94B26679CFDD9DAF7AD204338DD9C4D14114033A5C\
+225BD11F217B5F4732DA167EE3F939262D4043FC9CBA92303B7B5E96AEA12ADD\
+A64859DF4B86E9EE0B58E39091E6B188B408AC94E1294A8911245EE361E60E60\
+1EFF58D1D37639F3753BEC80EBB4EFDE25817436076623FC65415FE51D1B0280\
+366D12C554D86743F3C3B6572E400361A60726131441BA493A83FBE9AFDA90F7\
+AF1AE717238D:\
+A2A2143D652583E19A42A0D8809175DF172DEE12E923661FDAFA6FCE
+
+74356E449F4BF8644F77B14F4D67CB6BD9C1F5AE357621D5B8147E562B65C665\
+85CAF2E491B48529A01A34D226D436959153815380D5689E30B35357CDAC6E08\
+D3F2B0E88E200600D62BD9F5EAF488DF86A4470EA227006182E44809009868C4\
+C280C43D7D64A5268FA719074960087B3A6ABC837882F882C837834535929389\
+A12B2C78187E2EA07EF8B8EEF27DC85002C3AE35F1A50BEE6A1C48BA7E175F33\
+16670B27983472AA6A61EED0A683A39EE323080620EA44A9F74411AE5CE99030\
+528F9AB49C79F2:\
+677C274FFD58E155E9FBDC416CB01FDBB913851A319D884AC922D018
+
+8C3798E51BC68482D7337D3ABB75DC9FFE860714A9AD73551E120059860DDE24\
+AB87327222B64CF774415A70F724CDF270DE3FE47DDA07B61C9EF2A3551F45A5\
+584860248FABDE676E1CD75F6355AA3EAEABE3B51DC813D9FB2EAA4F0F1D9F83\
+4D7CAD9C7C695AE84B329385BC0BEF895B9F1EDF44A03D4B410CC23A79A6B62E\
+4F346A5E8DD851C2857995DDBF5B2D717AEB847310E1F6A46AC3D26A7F9B4498\
+5AF656D2B7C9406E8A9E8F47DCB4EF6B83CAACF9AEFB6118BFCFF7E44BEF6937\
+EBDDC89186839B77:\
+35917E2DAA15F615DF9664E5238DE6A0E89594EC741C4FED59617AC1
+
+FA56BF730C4F8395875189C10C4FB251605757A8FECC31F9737E3C2503B02608\
+E6731E85D7A38393C67DE516B85304824BFB135E33BF22B3A23B913BF6ACD2B7\
+AB85198B8187B2BCD454D5E3318CACB32FD6261C31AE7F6C54EF6A7A2A4C9F3E\
+CB81CE3555D4F0AD466DD4C108A90399D70041997C3B25345A9653F3C9A6711A\
+B1B91D6A9D2216442DA2C973CBD685EE7643BFD77327A2F7AE9CB283620A0871\
+6DFB462E5C1D65432CA9D56A90E811443CD1ECB8F0DE179C9CB48BA4F6FEC360\
+C66F252F6E64EDC96B:\
+4FBDCF7E5B9B841BAD1E8B5CBD4BB21F60C51264285C1133AD0F5C17
+
+B6134F9C3E91DD8000740D009DD806240811D51AB1546A974BCB18D344642BAA\
+5CD5903AF84D58EC5BA17301D5EC0F10CCD0509CBB3FD3FFF9172D193AF0F782\
+252FD1338C7244D40E0E42362275B22D01C4C3389F19DD69BDF958EBE28E31A4\
+FFE2B5F18A87831CFB7095F58A87C9FA21DB72BA269379B2DC2384B3DA953C79\
+25761FED324620ACEA435E52B424A7723F6A2357374157A34CD8252351C25A1B\
+232826CEFE1BD3E70FFC15A31E7C0598219D7F00436294D11891B82497BC78AA\
+5363892A2495DF8C1EEF:\
+29A3738DCC1C867454E299ED3697E44C51524B930501AD8BDEC2D727
+
+C941CDB9C28AB0A791F2E5C8E8BB52850626AA89205BEC3A7E22682313D198B1\
+FA33FC7295381354858758AE6C8EC6FAC3245C6E454D16FA2F51C4166FAB51DF\
+272858F2D603770C40987F64442D487AF49CD5C3991CE858EA2A60DAB6A65A34\
+414965933973AC2457089E359160B7CDEDC42F29E10A91921785F6B7224EE0B3\
+49393CDCFF6151B50B377D609559923D0984CDA6000829B916AB6896693EF6A2\
+199B3C22F7DC5500A15B8258420E314C222BC000BC4E5413E6DD82C993F8330F\
+5C6D1BE4BC79F08A1A0A46:\
+79EF7589A255610B4AB00F33A79E1DA9BFABDE45C0D9302111553A3A
+
+4499EFFFAC4BCEA52747EFD1E4F20B73E48758BE915C88A1FFE5299B0B005837\
+A46B2F20A9CB3C6E64A9E3C564A27C0F1C6AD1960373036EC5BFE1A8FC6A435C\
+2185ED0F114C50E8B3E4C7ED96B06A036819C9463E864A58D6286F785E32A804\
+443A56AF0B4DF6ABC57ED5C2B185DDEE8489EA080DEEEE66AA33C2E6DAB36251\
+C402682B6824821F998C32163164298E1FAFD31BABBCFFB594C91888C6219079\
+D907FDB438ED89529D6D96212FD55ABE20399DBEFD342248507436931CDEAD49\
+6EB6E4A80358ACC78647D043:\
+77193DBA1277B4728F2835B36A01A860C9C4B080E8DA52416C4B0974
+
+EECBB8FDFA4DA62170FD06727F697D81F83F601FF61E478105D3CB7502F2C89B\
+F3E8F56EDD469D049807A38882A7EEFBC85FC9A950952E9FA84B8AFEBD3CE782\
+D4DA598002827B1EB98882EA1F0A8F7AA9CE013A6E9BC462FB66C8D4A18DA214\
+01E1B93356EB12F3725B6DB1684F2300A98B9A119E5D27FF704AFFB618E12708\
+E77E6E5F34139A5A41131FD1D6336C272A8FC37080F041C71341BEE6AB550CB4\
+A20A6DDB6A8E0299F2B14BC730C54B8B1C1C487B494BDCCFD3A53535AB2F2315\
+90BF2C4062FD2AD58F906A2D0D:\
+C6D41623D719DF195B26C29A55372678AF6AE0036B3A583726FBDFE8
+
+E64F3E4ACE5C8418D65FEC2BC5D2A303DD458034736E3B0DF719098BE7A206DE\
+AF52D6BA82316CAF330EF852375188CDE2B39CC94AA449578A7E2A8E3F5A9D68\
+E816B8D16889FBC0EBF0939D04F63033AE9AE2BDAB73B88C26D6BD25EE460EE1\
+EF58FB0AFA92CC539F8C76D3D097E7A6A63EBB9B5887EDF3CF076028C5BBD5B9\
+DB3211371AD3FE121D4E9BF44229F4E1ECF5A0F9F0EBA4D5CEB72878AB22C3F0\
+EB5A625323AC66F7061F4A81FAC834471E0C59553F108475FE290D43E6A055AE\
+3EE46FB67422F814A68C4BE3E8C9:\
+A82DFC36AFC499EC5CCB239C4EB3E3CC53B396885F207C7DE21DEB63
+
+D2CB2D733033F9E91395312808383CC4F0CA974E87EC68400D52E96B3FA6984A\
+C58D9AD0938DDE5A973008D818C49607D9DE2284E7618F1B8AED8372FBD52ED5\
+4557AF4220FAC09DFA8443011699B97D743F8F2B1AEF3537EBB45DCC9E13DFB4\
+38428EE190A4EFDB3CAEB7F3933117BF63ABDC7E57BEB4171C7E1AD260AB0587\
+806C4D137B6316B50ABC9CCE0DFF3ACADA47BBB86BE777E617BBE578FF451984\
+4DB360E0A96C6701290E76BB95D26F0F804C8A4F2717EAC4E7DE9F2CFF3BBC55\
+A17E776C0D02856032A6CD10AD2838:\
+25FFB9AFDD43FA70BE51020FC95E55499591F4FCFC37ACC4C9A77EEB
+
+F2998955613DD414CC111DF5CE30A995BB792E260B0E37A5B1D942FE90171A4A\
+C2F66D4928D7AD377F4D0554CBF4C523D21F6E5F379D6F4B028CDCB9B1758D3B\
+39663242FF3CB6EDE6A36A6F05DB3BC41E0D861B384B6DEC58BB096D0A422FD5\
+42DF175E1BE1571FB52AE66F2D86A2F6824A8CFAACBAC4A7492AD0433EEB1545\
+4AF8F312B3B2A577750E3EFBD370E8A8CAC1582581971FBA3BA4BD0D76E718DA\
+CF8433D33A59D287F8CC92234E7A271041B526E389EFB0E40B6A18B3AAF658E8\
+2ED1C78631FD23B4C3EB27C3FAEC8685:\
+5FCC4B77DCECC27B77EDDEF1CB0639B13FFFCEC5FF64070AD2857E7E
+
+447797E2899B72A356BA55BF4DF3ACCA6CDB1041EB477BD1834A9F9ACBC340A2\
+94D729F2F97DF3A610BE0FF15EDB9C6D5DB41644B9874360140FC64F52AA03F0\
+286C8A640670067A84E017926A70438DB1BB361DEFEE7317021425F8821DEF26\
+D1EFD77FC853B818545D055ADC9284796E583C76E6FE74C9AC2587AA46AA8F88\
+04F2FEB5836CC4B3ABABAB8429A5783E17D5999F32242EB59EF30CD7ADABC16D\
+72DBDB097623047C98989F88D14EAF02A7212BE16EC2D07981AAA99949DDF89E\
+CD90333A77BC4E1988A82ABF7C7CAF3291:\
+DDA1BA567A97E1A2196AC1F3E7F91D285666B386CBD499DEA3582A19
+
+9F2C18ADE9B380C784E170FB763E9AA205F64303067EB1BCEA93DF5DAC4BF5A2\
+E00B78195F808DF24FC76E26CB7BE31DC35F0844CDED1567BBA29858CFFC97FB\
+29010331B01D6A3FB3159CC1B973D255DA9843E34A0A4061CABDB9ED37F241BF\
+ABB3C20D32743F4026B59A4CCC385A2301F83C0B0A190B0F2D01ACB8F0D41111\
+E10F2F4E149379275599A52DC089B35FDD5234B0CFB7B6D8AEBD563CA1FA653C\
+5C021DFD6F5920E6F18BFAFDBECBF0AB00281333ED50B9A999549C1C8F8C63D7\
+626C48322E9791D5FF72294049BDE91E73F8:\
+EE4588DB80183DB94B4AD3EBA30DD9500FD788EA99CB75753B4E9014
+
+AE159F3FA33619002AE6BCCE8CBBDD7D28E5ED9D61534595C4C9F43C402A9BB3\
+1F3B301CBFD4A43CE4C24CD5C9849CC6259ECA90E2A79E01FFBAC07BA0E147FA\
+42676A1D668570E0396387B5BCD599E8E66AAED1B8A191C5A47547F61373021F\
+A6DEADCB55363D233C24440F2C73DBB519F7C9FA5A8962EFD5F6252C0407F190\
+DFEFAD707F3C7007D69FF36B8489A5B6B7C557E79DD4F50C06511F599F56C896\
+B35C917B63BA35C6FF8092BAF7D1658E77FC95D8A6A43EEB4C01F33F03877F92\
+774BE89C1114DD531C011E53A34DC248A2F0E6:\
+EB074053888780F9FDAACAF71E2CD842AF1DA574CB0211A023AF67C0
+
+3B8E97C5FFC2D6A40FA7DE7FCEFC90F3B12C940E7AB415321E29EE692DFAC799\
+B009C99DCDDB708FCE5A178C5C35EE2B8617143EDC4C40B4D313661F49ABDD93\
+CEA79D117518805496FE6ACF292C4C2A1F76B403A97D7C399DAF85B46AD84E16\
+246C67D6836757BDE336C290D5D401E6C1386AB32797AF6BB251E9B2D8FE754C\
+47482B72E0B394EAB76916126FD68EA7D65EB93D59F5B4C5AC40F7C3B37E7F36\
+94F29424C24AF8C8F0EF59CD9DBF1D28E0E10F799A6F78CAD1D45B9DB3D7DEE4\
+A7059ABE99182714983B9C9D44D7F5643596D4F3:\
+4792D0DE0EF6C17AA8E4F39D9A644DBE49905B2041DD61A90639BFA6
+
+3434EC31B10FAFDBFEEC0DD6BD94E80F7BA9DCA19EF075F7EB017512AF66D6A4\
+BCF7D16BA0819A1892A6372F9B35BCC7CA8155EE19E8428BC22D214856ED5FA9\
+374C3C09BDE169602CC219679F65A1566FC7316F4CC3B631A18FB4449FA6AFA1\
+6A3DB2BC4212EFF539C67CF184680826535589C7111D73BFFCE431B4C40492E7\
+63D9279560AAA38EB2DC14A212D723F994A1FE656FF4DD14551CE4E7C621B2AA\
+5604A10001B2878A897A28A08095C325E10A26D2FB1A75BFD64C250309BB55A4\
+4F23BBAC0D5516A1C687D3B41EF2FBBF9CC56D4739:\
+6E86F86F524EFC4475D352A0D0D815B451DD9990800D07BF98DC1BFD
+
+7C7953D81C8D208FD1C97681D48F49DD003456DE60475B84070EF4847C333B74\
+575B1FC8D2A186964485A3B8634FEAA3595AAA1A2F4595A7D6B6153563DEE31B\
+BAC443C8A33EED6D5D956A980A68366C2527B550EE950250DFB691EACBD5D56A\
+E14B970668BE174C89DF2FEA43AE52F13142639C884FD62A3683C0C3792F0F24\
+AB1318BCB27E21F4737FAB62C77EA38BC8FD1CF41F7DAB64C13FEBE7152BF5BB\
+7AB5A78F5346D43CC741CB6F72B7B8980F268B68BF62ABDFB1577A52438FE14B\
+591498CC95F071228460C7C5D5CEB4A7BDE588E7F21C:\
+C90152A748421620F1755F7BFB09A49618797B7DF70223AF51BB97AA
+
+7A6A4F4FDC59A1D223381AE5AF498D74B7252ECF59E389E49130C7EAEE626E7B\
+D9897EFFD92017F4CCDE66B0440462CDEDFD352D8153E6A4C8D7A0812F701CC7\
+37B5178C2556F07111200EB627DBC299CAA792DFA58F35935299FA3A3519E9B0\
+3166DFFA159103FFA35E8577F7C0A86C6B46FE13DB8E2CDD9DCFBA85BDDDCCE0\
+A7A8E155F81F712D8E9FE646153D3D22C811BD39F830433B2213DD46301941B5\
+9293FD0A33E2B63ADBD95239BC01315C46FDB678875B3C81E053A40F581CFBEC\
+24A1404B1671A1B88A6D06120229518FB13A74CA0AC5AE:\
+F55877B8BC9872EADD1E8C0687C00CF352D4F454EC48D1F29E697CB3
+
+D9FAA14CEBE9B7DE551B6C0765409A33938562013B5E8E0E1E0A6418DF7399D0\
+A6A771FB81C3CA9BD3BB8E2951B0BC792525A294EBD1083688806FE5E7F1E17F\
+D4E3A41D00C89E8FCF4A363CAEDB1ACB558E3D562F1302B3D83BB886ED27B760\
+33798131DAB05B4217381EAAA7BA15EC820BB5C13B516DD640EAEC5A27D05FDF\
+CA0F35B3A5312146806B4C0275BCD0AAA3B2017F346975DB566F9B4D137F4EE1\
+0644C2A2DA66DEECA5342E236495C3C6280528BFD32E90AF4CD9BB908F34012B\
+52B4BC56D48CC8A6B59BAB014988EABD12E1A0A1C2E170E7:\
+A9B9968B4AAA65C0A35B08D83AF3A113274F8897F20FF18B4994A0FD
+
+2D8427433D0C61F2D96CFE80CF1E932265A191365C3B61AAA3D6DCC039F6BA2A\
+D52A6A8CC30FC10F705E6B7705105977FA496C1C708A277A124304F1FC40911E\
+7441D1B5E77B951AAD7B01FD5DB1B377D165B05BBF898042E39660CAF8B279FE\
+5229D1A8DB86C0999ED65E53D01CCBC4B43173CCF992B3A14586F6BA42F5FE30\
+AFA8AE40C5DF29966F9346DA5F8B35F16A1DE3AB6DE0F477D8D8660918060E88\
+B9B9E9CA6A4207033B87A812DBF5544D39E4882010F82B6CE005F8E8FF6FE3C3\
+806BC2B73C2B83AFB704345629304F9F86358712E9FAE3CA3E:\
+7C569414A62DA6C017BFCC6260E7F63616A4008DBF78BD3816A04D1E
+
+5E19D97887FCAAC0387E22C6F803C34A3DACD2604172433F7A8A7A526CA4A2A1\
+271ECFC5D5D7BE5AC0D85D921095350DFC65997D443C21C8094E0A3FEFD2961B\
+CB94AED03291AE310CCDA75D8ACE4BC7D89E7D3E5D1650BDA5D668B8B50BFC8E\
+608E184F4D3A9A2BADC4FF5F07E0C0BC8A9F2E0B2A26FD6D8C550008FAAAB75F\
+D71AF2A424BEC9A7CD9D83FAD4C8E9319115656A8717D3B523A68FF8004258B9\
+990ED362308461804BA3E3A7E92D8F2FFAE5C2FBA55BA5A3C27C0A2F71BD711D\
+2FE1799C2ADB31B200035481E9EE5C4ADF2AB9C0FA50B23975CF:\
+48E0F383E46F71E07A4EF6AFBF71F6641C934E348CEA4841CFC867F5
+
+C8E976AB4638909387CE3B8D4E510C3230E5690E02C45093B1D297910ABC481E\
+56EEA0F296F98379DFC9080AF69E73B2399D1C143BEE80AE1328162CE1BA7F6A\
+8374679B20AACD380EB4E61382C99998704D62701AFA914F9A2705CDB065885F\
+50D086C3EB5753700C387118BB142F3E6DA1E988DFB31AC75D7368931E45D139\
+1A274B22F83CEB072F9BCABC0B216685BFD789F5023971024B1878A205442522\
+F9EA7D8797A4102A3DF41703768251FD5E017C85D1200A464118AA35654E7CA3\
+9F3C375B8EF8CBE7534DBC64BC20BEFB417CF60EC92F63D9EE7397:\
+2B91E8EF41B40B6940A9454025A1418547B66823E2955382260EAC1D
+
+7145FA124B7429A1FC2231237A949BA7201BCC1822D3272DE005B682398196C2\
+5F7E5CC2F289FBF44415F699CB7FE6757791B1443410234AE061EDF623359E2B\
+4E32C19BF88450432DD01CAA5EB16A1DC378F391CA5E3C4E5F356728BDDD4975\
+DB7C890DA8BBC84CC73FF244394D0D48954978765E4A00B593F70F2CA082673A\
+261ED88DBCEF1127728D8CD89BC2C597E9102CED6010F65FA75A14EBE467FA57\
+CE3BD4948B6867D74A9DF5C0EC6F530CBF2EE61CE6F06BC8F2864DFF5583776B\
+31DF8C7FFCB61428A56BF7BD37188B4A5123BBF338393AF46EDA85E6:\
+AA71E9EF7E7047FAC9A6F14FF1DE7C18E53903C5D646F8848C3FC220
+
+7FDFADCC9D29BAD23AE038C6C65CDA1AEF757221B8872ED3D75FF8DF7DA0627D\
+266E224E812C39F7983E4558BFD0A1F2BEF3FEB56BA09120EF762917B9C09386\
+7948547AEE98600D10D87B20106878A8D22C64378BF634F7F75900C03986B077\
+B0BF8B740A82447B61B99FEE5376C5EB6680EC9E3088F0BDD0C56883413D60C1\
+357D3C811950E5890E7600103C916341B80C743C6A852B7B4FB60C3BA21F3BC1\
+5B8382437A68454779CF3CD7F9F90CCC8EF28D0B706535B1E4108EB5627BB45D\
+719CB046839AEE311CA1ABDC8319E050D67972CB35A6B1601B25DBF487:\
+F6D0F2DF20E815C332C4D85735F4BFA8782197474B5323EAC15E4E9C
+
+988638219FD3095421F826F56E4F09E356296B628C3CE6930C9F2E758FD1A80C\
+8273F2F61E4DAAE65C4F110D3E7CA0965AC7D24E34C0DC4BA2D6FF0BF5BBE93B\
+3585F354D7543CB542A1AA54674D375077F2D360A8F4D42F3DB131C3B7AB7306\
+267BA107659864A90C8C909460A73621D1F5D9D3FD95BEB19B23DB1CB6C0D0FB\
+A91D36891529B8BD8263CAA1BAB56A4AFFAED44962DF096D8D5B1EB845EF3118\
+8B3E10F1AF811A13F156BEB7A288AAE593EBD1471B624AA1A7C6ADF01E2200B3\
+D72D88A3AED3100C88231E41EFC376906F0B580DC895F080FDA5741DB1CB:\
+622EDE6C66F1CBA304B603D7B0AE6B515F858D4E9108F13C5F5E1DDC
+
+5AAB62756D307A669D146ABA988D9074C5A159B3DE85151A819B117CA1FF6597\
+F6156E80FDD28C9C3176835164D37DA7DA11D94E09ADD770B68A6E081CD22CA0\
+C004BFE7CD283BF43A588DA91F509B27A6584C474A4A2F3EE0F1F56447379240\
+A5AB1FB77FDCA49B305F07BA86B62756FB9EFB4FC225C86845F026EA542076B9\
+1A0BC2CDD136E122C659BE259D98E5841DF4C2F60330D4D8CDEE7BF1A0A24452\
+4EECC68FF2AEF5BF0069C9E87A11C6E519DE1A4062A10C83837388F7EF58598A\
+3846F49D499682B683C4A062B421594FAFBC1383C943BA83BDEF515EFCF10D:\
+3FC1F106F8950B3D229E42D5F90C803719C455703EF6D54F1CDC33A3
+
+47B8216AA0FBB5D67966F2E82C17C07AA2D6327E96FCD83E3DE7333689F3EE79\
+994A1BF45082C4D725ED8D41205CB5BCDF5C341F77FACB1DA46A5B9B2CBC49EA\
+DF786BCD881F371A95FA17DF73F606519AEA0FF79D5A11427B98EE7F13A5C006\
+37E2854134691059839121FEA9ABE2CD1BCBBBF27C74CAF3678E05BFB1C94989\
+7EA01F56FFA4DAFBE8644611685C617A3206C7A7036E4AC816799F693DAFE7F1\
+9F303CE4EBA09D21E03610201BFC665B72400A547A1E00FA9B7AD8D84F84B34A\
+EF118515E74DEF11B9188BD1E1F97D9A12C30132EC2806339BDADACDA2FD8B78:\
+67A3D063540E800E8615128D159DC079F0EA702AE773D69F7EA8329D
+
+8CFF1F67FE53C098896D9136389BD8881816CCAB34862BB67A656E3D98896F3C\
+E6FFD4DA73975809FCDF9666760D6E561C55238B205D8049C1CEDEEF374D1735\
+DAA533147BFA960B2CCE4A4F254176BB4D1BD1E89654432B8DBE1A135C42115B\
+394B024856A2A83DC85D6782BE4B444239567CCEC4B184D4548EAE3FF6A192F3\
+43292BA2E32A0F267F31CC26719EB85245D415FB897AC2DA433EE91A99424C9D\
+7F1766A44171D1651001C38FC79294ACCC68CEB5665D36218454D3BA169AE058\
+A831338C17743603F81EE173BFC0927464F9BD728DEE94C6AEAB7AAE6EE3A627\
+E8:\
+C425F8DCFA3A78973900971F89AE8F200CD3A124966B6EB467B69E85
+
+EACD07971CFF9B9939903F8C1D8CBB5D4DB1B548A85D04E037514A583604E787\
+F32992BF2111B97AC5E8A938233552731321522AB5E8583561260B7D13EBEEF7\
+85B23A41FD8576A6DA764A8ED6D822D4957A545D5244756C18AA80E1AAD4D1F9\
+C20D259DEE1711E2CC8FD013169FB7CC4CE38B362F8E0936AE9198B7E838DCEA\
+4F7A5B9429BB3F6BBCF2DC92565E3676C1C5E6EB3DD2A0F86AA23EDD3D0891F1\
+97447692794B3DFA269611AD97F72B795602B4FDB198F3FD3EB41B415064256E\
+345E8D8C51C555DC8A21904A9B0F1AD0EFFAB7786AAC2DA3B196507E9F33CA35\
+6427:\
+49BC279888DB44BF436B0219079928FF292573957C9599CC447CC6E8
+
+23AC4E9A42C6EF45C3336CE6DFC2FF7DE8884CD23DC912FEF0F7756C09D335C1\
+89F3AD3A23697ABDA851A81881A0C8CCAFC980AB2C702564C2BE15FE4C4B9F10\
+DFB2248D0D0CB2E2887FD4598A1D4ACDA897944A2FFC580FF92719C95CF2AA42\
+DC584674CB5A9BC5765B9D6DDF5789791D15F8DD925AA12BFFAFBCE60827B490\
+BB7DF3DDA6F2A143C8BF96ABC903D83D59A791E2D62814A89B8080A28060568C\
+F24A80AE61179FE84E0FFAD00388178CB6A617D37EFD54CC01970A4A41D1A8D3\
+DDCE46EDBBA4AB7C90AD565398D376F431189CE8C1C33E132FEAE6A8CD17A61C\
+630012:\
+340304F2A3C16806EA7A03520497327549D910369FF047C3DA55D0BF
+
+0172DF732282C9D488669C358E3492260CBE91C95CFBC1E3FEA6C4B0EC129B45\
+F242ACE09F152FC6234E1BEE8AAB8CD56E8B486E1DCBA9C05407C2F95DA8D8F1\
+C0AF78EE2ED82A3A79EC0CB0709396EE62AADB84F8A4EE8A7CCCA3C1EE84E302\
+A09EA802204AFECF04097E67D0F8E8A9D2651126C0A598A37081E42D168B0AE8\
+A71951C524259E4E2054E535B779679BDADE566FE55700858618E626B4A0FAF8\
+95BCCE9011504A49E05FD56127EAE3D1F8917AFB548ECADABDA1020111FEC931\
+4C413498A360B08640549A22CB23C731ACE743252A8227A0D2689D4C60016066\
+78DFB921:\
+DBD5AE8F4DE149A3B6A1F4C0AA9D3D6B5F89EB04BA4058B31A261BCF
+
+3875B9240CF3E0A8B59C658540F26A701CF188496E2C2174788B126FD29402D6\
+A75453BA0635284D08835F40051A2A9683DC92AFB9383719191231170379BA6F\
+4ADC816FECBB0F9C446B785BF520796841E58878B73C58D3EBB097CE4761FDEA\
+BE15DE2F319DFBAF1742CDEB389559C788131A6793E193856661376C81CE9568\
+DA19AA6925B47FFD77A43C7A0E758C37D69254909FF0FBD415EF8EB937BCD49F\
+91468B49974C07DC819ABD67395DB0E05874FF83DDDAB895344ABD0E7111B2DF\
+9E58D76D85AD98106B36295826BE04D435615595605E4B4BB824B33C4AFEB5E7\
+BB0D19F909:\
+128ADE79B19D737A49FEE5759CB0E44DAB715A0AA030E1F3A587925A
+
+747CC1A59FEFBA94A9C75BA866C30DC5C1CB0C0F8E9361D98484956DD5D1A40F\
+6184AFBE3DAC9F76028D1CAECCFBF69199C6CE2B4C092A3F4D2A56FE5A33A007\
+57F4D7DEE5DFB0524311A97AE0668A47971B95766E2F6DD48C3F57841F91F04A\
+00AD5EA70F2D479A2620DC5CD78EAAB3A3B011719B7E78D19DDF70D9423798AF\
+77517EBC55392FCD01FC600D8D466B9E7A7A85BF33F9CC5419E9BD874DDFD609\
+81150DDAF8D7FEBAA4374F0872A5628D318000311E2F5655365AD4D407C20E5C\
+04DF17A222E7DEEC79C5AB1116D8572F91CD06E1CCC7CED53736FC867FD49ECE\
+BE6BF8082E8A:\
+F038461526E684F9A24F3CF2C87BF4BA625ED69A3F559F687CCAE651
+
+57AF971FCCAEC97435DC2EC9EF0429BCEDC6B647729EA168858A6E49AC1071E7\
+06F4A5A645CA14E8C7746D65511620682C906C8B86EC901F3DDED4167B3F00B0\
+6CBFAC6AEE3728051B3E5FF10B4F9ED8BD0B8DA94303C833755B3CA3AEDDF0B5\
+4BC8D6632138B5D25BAB03D17B3458A9D782108006F5BB7DE75B5C0BA854B423\
+D8BB801E701E99DC4FEAAD59BC1C7112453B04D33EA3635639FB802C73C2B71D\
+58A56BBD671B18FE34ED2E3DCA38827D63FDB1D4FB3285405004B2B3E26081A8\
+FF08CD6D2B08F8E7B7E90A2AB1ED7A41B1D0128522C2F8BFF56A7FE67969422C\
+E839A9D4608F03:\
+B8CB35B78354C1F2E2298748B224D344A897F0D3B159E070673DBA19
+
+04E16DEDC1227902BAAF332D3D08923601BDD64F573FAA1BB7201918CFE16B1E\
+10151DAE875DA0C0D63C59C3DD050C4C6A874011B018421AFC4623AB0381831B\
+2DA2A8BA42C96E4F70864AC44E106F94311051E74C77C1291BF5DB9539E69567\
+BF6A11CF6932BBBAD33F8946BF5814C066D851633D1A513510039B349939BFD4\
+2B858C21827C8FF05F1D09B1B0765DC78A135B5CA4DFBA0801BCADDFA175623C\
+8B647EACFB4444B85A44F73890607D06D507A4F8393658788669F6EF4DEB58D0\
+8C50CA0756D5E2F49D1A7AD73E0F0B3D3B5F090ACF622B1878C59133E4A848E0\
+5153592EA81C6FBF:\
+B108DC459A46A7DB743312E9897D88C44FA07C810960865BB91D6802
+
+7C815C384EEE0F288ECE27CCED52A01603127B079C007378BC5D1E6C5E9E6D1C\
+735723ACBBD5801AC49854B2B569D4472D33F40BBB8882956245C366DC3582D7\
+1696A97A4E19557E41E54DEE482A14229005F93AFD2C4A7D8614D10A97A9DFA0\
+7F7CD946FA45263063DDD29DB8F9E34DB60DAA32684F0072EA2A9426ECEBFA52\
+39FB67F29C18CBAA2AF6ED4BF4283936823AC1790164FEC5457A9CBA7C767CA5\
+9392D94CAB7448F50EB34E9A93A80027471CE59736F099C886DEA1AB4CBA4D89\
+F5FC7AE2F21CCD27F611ECA4626B2D08DC22382E92C1EFB2F6AFDC8FDC3D2172\
+604F5035C46B8197D3:\
+2C91FC3830D6FBAAC0DC820849578BC6CC1717F90EEC3DD9E1BCD4C8
+
+E29D505158DBDD937D9E3D2145658EE6F5992A2FC790F4F608D9CDB44A091D5B\
+94B88E81FAC4FDF5C49442F13B911C55886469629551189EAFF62488F1A479B7\
+DB11A1560E198DDCCCCF50159093425FF7F1CB8D1D1246D0978764087D6BAC25\
+7026B090EFAE8CEC5F22B6F21C59ACE1AC7386F5B8837CA6A12B6FBF5534DD05\
+60EF05CA78104D3B943DDB220FEAEC89AA5E692A00F822A2AB9A2FE60350D75E\
+7BE16FF2526DC643872502D01F42F188ABED0A6E9A6F5FD0D1CE7D5755C9FFA6\
+6B0AF0B20BD806F08E06156690D81AC811778CA3DAC2C249B96002017FCE93E5\
+07E3B953ACF99964B847:\
+8DD2447F7DF47F51DB05745E5B3A539A15DC43FB4F67F05DFEBE02ED
+
+D85588696F576E65ECA0155F395F0CFACD83F36A99111ED5768DF2D116D2121E\
+32357BA4F54EDE927F189F297D3A97FAD4E9A0F5B41D8D89DD7FE20156799C2B\
+7B6BF9C957BA0D6763F5C3BC5129747BBB53652B49290CFF1C87E2CDF2C4B95D\
+8AAEE09BC8FBFA6883E62D237885810491BFC101F1D8C636E3D0EDE838AD05C2\
+07A3DF4FAD76452979EB99F29AFAECEDD1C63B8D36CF378454A1BB67A741C77A\
+C6B6B3F95F4F02B64DABC15438613EA49750DF42EE90101F115AA9ABB9FF6432\
+4DDE9DABBB01054E1BD6B4BCDC7930A44C2300D87CA78C06924D0323AD7887E4\
+6C90E8C4D100ACD9EED21E:\
+396A16C8BA8E29A02F5349BF53BBACD1698AFCCB30F70F31F508A724
+
+3A12F8508B40C32C74492B66323375DCFE49184C78F73179F3314B79E63376B8\
+AC683F5A51F1534BD729B02B04D002F55CBD8E8FC9B5EC1EA6BBE6A0D0E74315\
+18E6BA45D124035F9D3DCE0A8BB7BF1430A9F657E0B4EA9F20EB20C786A58181\
+A1E20A96F1628F8728A13BDF7A4B4B32FC8AA7054CC4881AE7FA19AFA65C6C3E\
+E1B3ADE3192AF42054A8A911B8EC1826865D46D93F1E7C5E2B7813C92A506E53\
+886F3D4701BB93D2A681AD109C845904BB861AF8AF0646B6E399B38B614051D3\
+4F6842563A0F37EC00CB3D865FC5D746C4987DE2A65071100883A2A9C7A2BFE1\
+E2DD603D9EA24DC7C5FD06BE:\
+AC03967249EAA1365AA489D3962FCCAFEC07AD981A54986706785FEE
+
+1861EDCE46FA5AD17E1FF1DEAE084DEC580F97D0A67885DFE834B9DFAC1AE076\
+742CE9E267512CA51F6DF5A455AF0C5FD6ABF94ACEA103A3370C354485A7846F\
+B84F3AC7C2904B5B2FBF227002CE512133BB7E1C4E50057BFD1E44DB33C7CDB9\
+69A99E284B184F50A14B068A1FC5009D9B298DBE92239572A7627AAC02ABE8F3\
+E3B473417F36D4D2505D16B7577F4526C9D94A270A2DFE450D06DA8F6FA95687\
+9A0A55CFE99E742EA555EA477BA3E9B44CCD508C375423611AF92E55345DC215\
+779B2D5119EBA49C71D49B9FE3F1569FA24E5CA3E332D042422A8B8158D3EC66\
+A80012976F31FFDF305F0C9C5E:\
+51554A3AFBC30F302F7FA4133C5B8E131CF9B9BBC50B2CCB7D884193
+
+08D0FFDE3A6E4EF65608EA672E4830C12943D7187CCFF08F4941CFC13E545F3B\
+9C7AD5EEBBE2B01642B486CAF855C2C73F58C1E4E3391DA8E2D63D96E15FD849\
+53AE5C231911B00AD6050CD7AAFDAAC9B0F663AE6AAB45519D0F5391A541707D\
+479034E73A6AD805AE3598096AF078F1393301493D663DD71F83869CA27BA508\
+B7E91E81E128C1716DC3ACFE3084B2201E04CF8006617EECF1B640474A5D45CF\
+DE9F4D3EF92D6D055B909892194D8A8218DB6D8203A84261D200D71473D7488F\
+3427416B6896C137D455F231071CACBC86E0415AB88AEC841D96B7B8AF41E05B\
+B461A40645BF176601F1E760DE5F:\
+F336B69FCD40BFB5085A641A78088169971FADCF691C4C57BE585BBD
+
+D782ABB72A5BE3392757BE02D3E45BE6E2099D6F000D042C8A543F50ED6EBC05\
+5A7F133B0DD8E9BC348536EDCAAE2E12EC18E8837DF7A1B3C87EC46D50C241DE\
+E820FD586197552DC20BEEA50F445A07A38F1768A39E2B2FF05DDDEDF751F1DE\
+F612D2E4D810DAA3A0CC904516F9A43AF660315385178A529E51F8AAE141808C\
+8BC5D7B60CAC26BB984AC1890D0436EF780426C547E94A7B08F01ACBFC4A3825\
+EAE04F520A9016F2FB8BF5165ED12736FC71E36A49A73614739EAA3EC834069B\
+1B40F1350C2B3AB885C02C640B9F7686ED5F99527E41CFCD796FE4C256C91731\
+86C226169FF257954EBDA81C0E5F99:\
+AA93E8FB2E8220F092EE64BFCC1DED1EB810240CD908376B0ED41E21
+
+5FCE8109A358570E40983E1184E541833BB9091E280F258CFB144387B05D190E\
+431CB19BAA67273BA0C58ABE91308E1844DCD0B3678BAA42F335F2FA05267A02\
+40B3C718A5942B3B3E3BFA98A55C25A1466E8D7A603722CB2BBF03AFA54CD769\
+A99F310735EE5A05DAE2C22D397BD95635F58C48A67F90E1B73AAFCD3F82117F\
+0166657838691005B18DA6F341D6E90FC1CDB352B30FAE45D348294E501B6325\
+2DE14740F2B85AE5299DDEC3172DE8B6D0BA219A20A23BB5E10FF434D39DB3F5\
+83305E9F5C039D98569E377B75A70AB837D1DF269B8A4B566F40BB91B577455F\
+D3C356C914FA06B9A7CE24C7317A172D:\
+D7A472FDB42739B3613BAD3D579F786C01BD82D0BE7F8CDCB4612B18
+
+6172F1971A6E1E4E6170AFBAD95D5FEC99BF69B24B674BC17DD78011615E502D\
+E6F56B86B1A71D3F4348087218AC7B7D09302993BE272E4A591968AEF18A1262\
+D665610D1070EE91CC8DA36E1F841A69A7A682C580E836941D21D909A3AFC1F0\
+B963E1CA5AB193E124A1A53DF1C587470E5881FB54DAE1B0D840F0C8F9D1B04C\
+645BA1041C7D8DBF22030A623AA15638B3D99A2C400FF76F3252079AF88D2B37\
+F35EE66C1AD7801A28D3D388AC450B97D5F0F79E4541755356B3B1A5696B023F\
+39AB7AB5F28DF4202936BC97393B93BC915CB159EA1BD7A0A414CB4B7A1AC3AF\
+68F50D79F0C9C7314E750F7D02FAA58BFA:\
+B94E392A8B74D2A51C09E9E9754CDB078A0A1F402A09B47ED3BB8ABC
+
+5668ECD99DFBE215C4118398AC9C9EAF1A1433FAB4CCDD3968064752B625EA94\
+4731F75D48A27D047D67547F14DD0FFAA55FA5E29F7AF0D161D85EAFC4F2029B\
+717C918EAB9D304543290BDBA7158B68020C0BA4E079BC95B5BC0FC044A992B9\
+4B4CCD3BD66D0EABB5DBBAB904D62E00752C4E3B0091D773BCF4C14B4377DA3E\
+FFF824B1CB2FA01B32D1E46C909E626ED2DAE920F4C7DBEB635BC754FACBD8D4\
+9BEBA3F23C1C41CCBFCD0EE0C114E69737F5597C0BF1D859F0C767E18002AE8E\
+39C26261FFDE2920D3D0BAF0E906138696CFE5B7E32B600F45DF3AAA39932F3A\
+7DF95B60FA8712A2271FCAF3911CE7B511B1:\
+26A3734EC5BDA57A5CE90DBD16FFE9366937E2B95C630ED2D5BBEF3B
+
+03D625488354DF30E3F875A68EDFCF340E8366A8E1AB67F9D5C5486A96829DFA\
+C0578289082B2A62117E1CF418B43B90E0ADC881FC6AE8105C888E9ECD21AEA1\
+C9AE1A4038DFD17378FED71D02AE492087D7CDCD98F746855227967CB1AB4714\
+261EE3BEAD3F4DB118329D3EBEF4BC48A875C19BA763966DA0EBEA800E01B2F5\
+0B00E9DD4CACA6DCB314D00184EF71EA2391D760C950710DB4A70F9212FFC548\
+61F9DC752CE18867B8AD0C48DF8466EF7231E7AC567F0EB55099E622EBB86CB2\
+37520190A61C66AD34F1F4E289CB3282AE3EAAC6152ED24D2C92BAE5A7658252\
+A53C49B7B02DFE54FDB2E90074B6CF310AC661:\
+AE9E408B69CD8003595B8AACED7426A7A2692009F5B4B797A60A0DA4
+
+2EDC282FFB90B97118DD03AAA03B145F363905E3CBD2D50ECD692B37BF000185\
+C651D3E9726C690D3773EC1E48510E42B17742B0B0377E7DE6B8F55E00A8A4DB\
+4740CEE6DB0830529DD19617501DC1E9359AA3BCF147E0A76B3AB70C4984C13E\
+339E6806BB35E683AF8527093670859F3D8A0FC7D493BCBA6BB12B5F65E71E70\
+5CA5D6C948D66ED3D730B26DB395B3447737C26FAD089AA0AD0E306CB28BF0AC\
+F106F89AF3745F0EC72D534968CCA543CD2CA50C94B1456743254E358C1317C0\
+7A07BF2B0ECA438A709367FAFC89A57239028FC5FECFD53B8EF958EF10EE0608\
+B7F5CB9923AD97058EC067700CC746C127A61EE3:\
+7A6A0B6B4B669ADF9370CFDE5C9655B6500B7BAA52884398FA7E3A71
+
+90B28A6AA1FE533915BCB8E81ED6CACDC10962B7FF82474F845EEB86977600CF\
+70B07BA8E3796141EE340E3FCE842A38A50AFBE90301A3BDCC591F2E7D9DE53E\
+495525560B908C892439990A2CA2679C5539FFDF636777AD9C1CDEF809CDA9E8\
+DCDB451ABB9E9C17EFA4379ABD24B182BD981CAFC792640A183B61694301D04C\
+5B3EAAD694A6BD4CC06EF5DA8FA23B4FA2A64559C5A68397930079D250C51BCF\
+00E2B16A6C49171433B0AADFD80231276560B80458DD77089B7A1BBCC9E7E4B9\
+F881EACD6C92C4318348A13F4914EB27115A1CFC5D16D7FD94954C3532EFACA2\
+CAB025103B2D02C6FD71DA3A77F417D7932685888A:\
+6DE44F673AAC9C6B219D98E1DFF1D239FFF771F4365758EDF14BF04D
+
+2969447D175490F2AA9BB055014DBEF2E6854C95F8D60950BFE8C0BE8DE254C2\
+6B2D31B9E4DE9C68C9ADF49E4EE9B1C2850967F29F5D08738483B417BB96B2A5\
+6F0C8ACA632B552059C59AAC3F61F7B45C966B75F1D9931FF4E596406378CEE9\
+1AAA726A3A84C33F37E9CDBE626B5745A0B06064A8A8D56E53AAF102D23DD9DF\
+0A3FDF7A638509A6761A33FA42FA8DDBD8E16159C93008B53765019C3F0E9F10\
+B144CE2AC57F5D7297F9C9949E4FF68B70D339F87501CE8550B772F32C6DA8AD\
+2CE2100A895D8B08FA1EEAD7C376B407709703C510B50F87E73E43F8E7348F87\
+C3832A547EF2BBE5799ABEDCF5E1F372EA809233F006:\
+92D860929D7B3EC9EA2FD7AE4FB26BACE1CA6AB5735F88157F4C3194
+
+721645633A44A2C78B19024EAECF58575AB23C27190833C26875DC0F0D50B46A\
+EA9C343D82EA7D5B3E50EC700545C615DAEAEA64726A0F05607576DCD396D812\
+B03FB6551C641087856D050B10E6A4D5577B82A98AFB89CEE8594C9DC19E79FE\
+FF0382FCFD127F1B803A4B9946F4AC9A4378E1E6E041B1389A53E3450CD32D9D\
+2941B0CBABDB50DA8EA2513145164C3AB6BCBD251C448D2D4B087AC57A59C228\
+5D564F16DA4ED5E607ED979592146FFB0EF3F3DB308FB342DF5EB5924A48256F\
+C763141A278814C82D6D6348577545870AE3A83C7230AC02A1540FE1798F7EF0\
+9E335A865A2AE0949B21E4F748FB8A51F44750E213A8FB:\
+D4E7DC30605D852F428ACC224875FFD94BEB06B71CE5152C9C287C80
+
+6B860D39725A14B498BB714574B4D37CA787404768F64C648B1751B353AC92BA\
+C2C3A28EA909FDF0423336401A02E63EC24325300D823B6864BB701F9D7C7A1F\
+8EC9D0AE3584AA6DD62EA1997CD831B4BABD9A4DA50932D4EFDA745C61E41308\
+90E156AEE6113716DAF95764222A91187DB2EFFEA49D5D0596102D619BD26A61\
+6BBFDA8335505FBB0D90B4C180D1A2335B91538E1668F9F9642790B4E55F9CAB\
+0FE2BDD2935D001EE6419ABAB5457880D0DBFF20ED8758F4C20FE759EFB33141\
+CF0E892587FE8187E5FBC57786B7E8B089612C936DFC03D27EFBBE7C8673F160\
+6BD51D5FF386F4A7AB68EDF59F385EB1291F117BFE717399:\
+88D5879FB2468072F08244B2D67F9CE2733F4F16472748770F5A705B
+
+6A01830AF3889A25183244DECB508BD01253D5B508AB490D3124AFBF42626B2E\
+70894E9B562B288D0A2450CFACF14A0DDAE5C04716E5A0082C33981F6037D23D\
+5E045EE1EF2283FB8B6378A914C5D9441627A722C282FF452E25A7EA608D69CE\
+E4393A0725D17963D0342684F255496D8A18C2961145315130549311FC07F031\
+2FB78E6077334F87EAA873BEE8AA95698996EB21375EB2B4EF53C14401207DEB\
+4568398E5DD9A7CF97E8C9663E23334B46912F8344C19EFCF8C2BA6F04325F1A\
+27E062B62A58D0766FC6DB4D2C6A1928604B0175D872D16B7908EBC041761187\
+CC785526C2A3873FEAC3A642BB39F5351550AF9770C328AF7B:\
+6EB4FEB861D45200C6585A69D9BFADFC6794915420D3DD79BD7E6EAF
+
+B3C5E74B69933C2533106C563B4CA20238F2B6E675E8681E34A389894785BDAD\
+E59652D4A73D80A5C85BD454FD1E9FFDAD1C3815F5038E9EF432AAC5C3C4FE84\
+0CC370CF86580A6011778BBEDAF511A51B56D1A2EB68394AA299E26DA9ADA6A2\
+F39B9FAFF7FBA457689B9C1A577B2A1E505FDF75C7A0A64B1DF81B3A356001BF\
+0DF4E02A1FC59F651C9D585EC6224BB279C6BEBA2966E8882D68376081B98746\
+8E7AED1EF90EBD090AE825795CDCA1B4F09A979C8DFC21A48D8A53CDBB26C4DB\
+547FC06EFE2F9850EDD2685A4661CB4911F165D4B63EF25B87D0A96D3DFF6AB0\
+758999AAD214D07BD4F133A6734FDE445FE474711B69A98F7E2B:\
+A76B0EE363B13AC6C8EDA94F4DEC7298CEFDBB8E62FB36509F25D18B
+
+83AF34279CCB5430FEBEC07A81950D30F4B66F484826AFEE7456F0071A51E1BB\
+C55570B5CC7EC6F9309C17BF5BEFDD7C6BA6E968CF218A2B34BD5CF927AB846E\
+38A40BBD81759E9E33381016A755F699DF35D660007B5EADF292FEEFB735207E\
+BF70B5BD17834F7BFA0E16CB219AD4AF524AB1EA37334AA66435E5D397FC0A06\
+5C411EBBCE32C240B90476D307CE802EC82C1C49BC1BEC48C0675EC2A6C6F3ED\
+3E5B741D13437095707C565E10D8A20B8C20468FF9514FCF31B4249CD82DCEE5\
+8C0A2AF538B291A87E3390D737191A07484A5D3F3FB8C8F15CE056E5E5F8FEBE\
+5E1FB59D6740980AA06CA8A0C20F5712B4CDE5D032E92AB89F0AE1:\
+E8B706D7B3247FB728DD0182ADE8DCC37FA246FE447AC561A412401E
+
+A7ED84749CCC56BB1DFBA57119D279D412B8A986886D810F067AF349E8749E9E\
+A746A60B03742636C464FC1EE233ACC52C1983914692B64309EDFDF29F1AB912\
+EC3E8DA074D3F1D231511F5756F0B6EEAD3E89A6A88FE330A10FACE267BFFBFC\
+3E3090C7FD9A850561F363AD75EA881E7244F80FF55802D5EF7A1A4E7B89FCFA\
+80F16DF54D1B056EE637E6964B9E0FFD15B6196BDD7DB270C56B47251485348E\
+49813B4EB9ED122A01B3EA45AD5E1A929DF61D5C0F3E77E1FDC356B63883A60E\
+9CBB9FC3E00C2F32DBD469659883F690C6772E335F617BC33F161D6F6984252E\
+E12E62B6000AC5231E0C9BC65BE223D8DFD94C5004A101AF9FD6C0FB:\
+6059E9FC165CAB929FEC72F5F4A943B599A0D8841E6AA0717A46978C
+
+A6FE30DCFCDA1A329E82AB50E32B5F50EB25C873C5D2305860A835AECEE6264A\
+A36A47429922C4B8B3AFD00DA16035830EDB897831C4E7B00F2C23FC0B15FDC3\
+0D85FB70C30C431C638E1A25B51CAF1D7E8B050B7F89BFB30F59F0F20FECFF3D\
+639ABC4255B3868FC45DD81E47EB12AB40F2AAC735DF5D1DC1AD997CEFC4D836\
+B854CEE9AC02900036F3867FE0D84AFFF37BDE3308C2206C62C4743375094108\
+877C73B87B2546FE05EA137BEDFC06A2796274099A0D554DA8F7D7223A48CBF3\
+1B7DECAA1EBC8B145763E3673168C1B1B715C1CD99ECD3DDB238B06049885ECA\
+D9347C2436DFF32C771F34A38587A44A82C5D3D137A03CAA27E66C8FF6:\
+25D9CC7C7BCE962346D37CB7FD26EA399F8AEE643095A5F189043E73
+
+83167FF53704C3AA19E9FB3303539759C46DD4091A52DDAE9AD86408B6933598\
+9E61414BC20AB4D01220E35241EFF5C9522B079FBA597674C8D716FE441E5661\
+10B6211531CECCF8FD06BC8E511D00785E57788ED9A1C5C73524F01830D2E114\
+8C92D0EDC97113E3B7B5CD3049627ABDB8B39DD4D6890E0EE91993F92B03354A\
+88F52251C546E64434D9C3D74544F23FB93E5A2D2F1FB15545B4E1367C97335B\
+0291944C8B730AD3D4789273FA44FB98D78A36C3C3764ABEEAC7C569C1E43A35\
+2E5B770C3504F87090DEE075A1C4C85C0C39CF421BDCC615F9EFF6CB4FE64680\
+04AECE5F30E1ECC6DB22AD9939BB2B0CCC96521DFBF4AE008B5B46BC006E:\
+8E0887B79F61D0C7013D4755ED0653B314093C33C199F767947A2938
+
+3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5\
+623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A\
+15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0\
+A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764\
+B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43\
+C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D\
+817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08\
+5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1:\
+529902444F790393A2425B8A2E8D6E35CE7A1EA1F232BEEB3B3DA09B
+
+724627916C50338643E6996F07877EAFD96BDF01DA7E991D4155B9BE1295EA7D\
+21C9391F4C4A41C75F77E5D27389253393725F1427F57914B273AB862B9E31DA\
+BCE506E558720520D33352D119F699E784F9E548FF91BC35CA14704212870982\
+0D69A8287EA3257857615EB0321270E94B84F446942765CE882B191FAEE7E1C8\
+7E0F0BD4E0CD8A927703524B559B769CA4ECE1F6DBF313FDCF67C572EC4185C1\
+A88E86EC11B6454B371980020F19633B6B95BD280E4FBCB0161E1A82470320CE\
+C6ECFA25AC73D09F1536F286D3F9DACAFB2CD1D0CE72D64D197F5C7520B3CCB2\
+FD74EB72664BA93853EF41EABF52F015DD591500D018DD162815CC993595B195:\
+209B7E757D298DF854604E0CE41E605E737828130A271D8DDB78385F
+
+3139840B8AD4BCD39092916FD9D01798FF5AA1E48F34702C72DFE74B12E98A11\
+4E318CDD2D47A9C320FFF908A8DBC2A5B1D87267C8E983829861A567558B37B2\
+92D4575E200DE9F1DE45755FAFF9EFAE34964E4336C259F1E66599A7C904EC02\
+539F1A8EAB8706E0B4F48F72FEC2794909EE4A7B092D6061C74481C9E21B9332\
+DC7C6E482D7F9CC3210B38A6F88F7918C2D8C55E64A428CE2B68FD07AB572A8B\
+0A2388664F99489F04EB54DF1376271810E0E7BCE396F52807710E0DEA94EB49\
+F4B367271260C3456B9818FC7A72234E6BF2205FF6A36546205015EBD7D8C252\
+7AA430F58E0E8AC97A7B6B793CD403D517D66295F37A34D0B7D2FA7BC345AC04\
+CA1E266480DEEC39F5C88641C9DC0BD1358158FDECDD96685BBBB5C1FE5EA89D\
+2CB4A9D5D12BB8C893281FF38E87D6B4841F0650092D447E013F20EA934E18:\
+6FC3891BAA6F667E4227CE803DBC698A14E872001525F3ED52ADED81
+
+023D91AC532601C7CA3942D62827566D9268BB4276FCAA1AE927693A69616526\
+76DBA09219A01B3D5ADFA12547A946E78F3C5C62DD880B02D2EEEB4B96636529\
+C6B01120B23EFC49CCFB36B8497CD19767B53710A636683BC5E0E5C9534CFC00\
+4691E87D1BEE39B86B953572927BD668620EAB87836D9F3F8F28ACE41150776C\
+0BC6657178EBF297FE1F7214EDD9F215FFB491B681B06AC2032D35E6FDF832A8\
+B06056DA70D77F1E9B4D26AE712D8523C86F79250718405F91B0A87C725F2D3F\
+52088965F887D8CF87206DFDE422386E58EDDA34DDE2783B3049B86917B46280\
+27A05D4D1F429D2B49C4B1C898DDDCB82F343E145596DE11A54182F39F4718EC\
+AE8F506BD9739F5CD5D5686D7FEFC834514CD1B2C91C33B381B45E2E5335D7A8\
+720A8F17AFC8C2CB2BD88B14AA2DCA099B00AA575D0A0CCF099CDEC4870FB710\
+D2680E60C48BFC291FF0CEF2EEBF9B36902E9FBA8C889BF6B4B9F5CE53A19B0D\
+9399CD19D61BD08C0C2EC25E099959848E6A550CA7137B63F43138D7B651:\
+E32A2A6158317D0841BF689FA15A93F35C3B0E0DAC8A7AA6FA6EB571
+
+20FF454369A5D05B81A78F3DB05819FEA9B08C2384F75CB0AB6AA115DD690DA3\
+131874A1CA8F708AD1519EA952C1E249CB540D196392C79E87755424FEE7C890\
+808C562722359EEA52E8A12FBBB969DD7961D2BA52037493755A5FA04F0D50A1\
+AA26C9B44148C0D3B94D1C4A59A31ACA15AE8BD44ACB7833D8E91C4B86FA3135\
+A423387B8151B4133ED23F6D7187B50EC2204AD901AD74D396E44274E0ECAFAA\
+E17B3B9085E22260B35CA53B15CC52ABBA758AF6798FBD04ECEECED648F3AF4F\
+DB3DED7557A9A5CFB7382612A8A8F3F45947D1A29CE29072928EC193CA25D510\
+71BD5E1984ECF402F306EA762F0F25282F5296D997658BE3F983696FFA6D095C\
+6369B4DAF79E9A5D3136229128F8EB63C12B9E9FA78AFF7A3E9E19A62022493C\
+D136DEFBB5BB7BA1B938F367FD2F63EB5CA76C0B0FF21B9E36C3F07230CF3C30\
+74E5DA587040A76975D7E39F4494ACE5486FCBF380AB7558C4FE89656335B82E\
+4DB8659509EAB46A19613126E594042732DD4C411F41AA8CDEAC71C0FB40A94E\
+6DA558C05E77B6182806F26D9AFDF3DA00C69419222C8186A6EFAD600B410E6C\
+E2F2A797E49DC1F135319801FA6F396B06F975E2A190A023E474B618E7:\
+3581EF73FBF527AE22060E928439AE30D8E61EE8642E9C9D03E957D1
+
+4FBDC596508D24A2A0010E140980B809FB9C6D55EC75125891DD985D37665BD8\
+0F9BEB6A50207588ABF3CEEE8C77CD8A5AD48A9E0AA074ED388738362496D2FB\
+2C87543BB3349EA64997CE3E7B424EA92D122F57DBB0855A803058437FE08AFB\
+0C8B5E7179B9044BBF4D81A7163B3139E30888B536B0F957EFF99A7162F4CA5A\
+A756A4A982DFADBF31EF255083C4B5C6C1B99A107D7D3AFFFDB89147C2CC4C9A\
+2643F478E5E2D393AEA37B4C7CB4B5E97DADCF16B6B50AAE0F3B549ECE47746D\
+B6CE6F67DD4406CD4E75595D5103D13F9DFA79372924D328F8DD1FCBEB5A8E2E\
+8BF4C76DE08E3FC46AA021F989C49329C7ACAC5A688556D7BCBCB2A5D4BE69D3\
+284E9C40EC4838EE8592120CE20A0B635ECADAA84FD5690509F54F77E35A417C\
+584648BC9839B974E07BFAB0038E90295D0B13902530A830D1C2BDD53F1F9C9F\
+AED43CA4EED0A8DD761BC7EDBDDA28A287C60CD42AF5F9C758E5C7250231C09A\
+582563689AFC65E2B79A7A2B68200667752E9101746F03184E2399E4ED8835CB\
+8E9AE90E296AF220AE234259FE0BD0BCC60F7A4A5FF3F70C5ED4DE9C8C519A10\
+E962F673C82C5E9351786A8A3BFD570031857BD4C87F4FCA31ED4D50E14F2107\
+DA02CB5058700B74EA241A8B41D78461658F1B2B90BFD84A4C2C9D6543861AB3\
+C56451757DCFB9BA60333488DBDD02D601B41AAE317CA7474EB6E6DD:\
+2EB421F1A6C9B3F3E08F59A7CFDD8AC7CA45778F964603228AE94B17
+
+D1890B4704E169C28E44DDF62A1091450404910539FC2DAEB26E8ACF4533B024\
+E5215C2D02820DD8FB2CFC1743955CBACFF0F8F35DFBB5E3F942F36247F68211\
+D518F3F601AAE12A1CDC000BAB43D4C973F287E80741DD1FCF6C34F2E6B4B6C3\
+13D01C4FF3CBF9166F26946F18EF2D58271BA9233F09A6B77BFD4F48B36EB3D7\
+3D1133C4F842A7DC3907F680B0B773242C11E3DD973A44327EA7CEA9C0F8E07D\
+682B6651E506B587559FE01ED721000BAF570A16FBDD9EA29FA3DEF4BE912058\
+321A8B720C5C102E48A6E7ED6F8838D400DD57D06EEDBCD15323F86D855C94B2\
+1E41B14EC9E1BBC8019211FD88138C91F9ABBD9BB3914D26C1DDC21673D2D512\
+63B39D66E741D924CF2B192C5D2C1A140126A3D64A2C77BE6C2C6EBE8599978A\
+E90BD36CBB9AF64D078910C4094AB3BF399C34F2AB8EF843E9FE1BF88BF443BA\
+21E4377E5F49C07FD9653B526E14562237F02D11B904BCA6AC31AE721A43E3C4\
+910A24AF6F4D80C031C109FC0FE49F15274BCA92BDA04C3B4196C192F6CE489C\
+63A806ACFC895AB52CAD657C1783B528E12D0ED856E1F8FC91F2AAFDFA0A9249\
+8D68530772EE73B359FCF1418D1096C46B34DCF90E5B468BBB2970BECBD70089\
+CFB039D64CC50FFF5EEF26384D34F24515A6558B06A1FDD88F1050C5BD78CC6E\
+D83D4C2B0E882AEBCF84AFB0430D0BF09F2FB42B8B4589158093A7709AAE75A7\
+90910E211EE1333FFB6FD80778DA3BF73858978E9DD647978841B18001DBAAEA\
+43CA0C0A03DBB9BCF30CE76A6F4B2CF2A9B6531B3E4051E7E05090CD421BC66C\
+4731E7122AD129FC42DEDC83BB460E3F889992FBD3CA072686E56B72C720FBC9\
+8D723EF7F247286F77CCDDC728738E941B1A74D4F16671C21FDD5643A115DDBC\
+B88EE7EC67EA66FD2BCE718DF6E085D4B5FC71A72696636A8F7B3A68AFA51A89\
+6771FAAA7F1F827430AC5E8089DBC0D4175E1B22A057BC5F1724EADC1A41E78F\
+A3ACAA8B97E5F2E19EF9D59AE12B04E7F0E8A621E098A66910E2A5ED2102B824\
+CD3EA044A854F1CD0B33E61E7F737414B2953549F25DD34D19AA1981DE7CD564\
+9FF6C6364A4F25312EF62395A747AB88AAD722C05AEC40DEEA8EEE5E779EF458\
+A68840BC6BD5D29AD40F98B3AE010B6213372ABB7BB8B8:\
+31BE6FE35784081DA23627B566BCD60A966271D44E9D370A7023CBA1
+
+4FA3DF1DEA75AD4B9C379206A95FED930000482E5B683FD2B17DC8E7D5C4BC1B\
+73186CCC13C9FF2DD09FC1D4F68034D120E84CA73A00B71A3B46D1EFC6FF88CF\
+2EDA65810B098CC5E651D9CF064E87076D5A871849F3B405D3D58EF5B1F10520\
+A9FB4FC84A81A87B13DBFBF9D8674943E28C257E46D8AD7BE1785F1DC7C9B1BD\
+574AD1DDA48F0255C853D2490BD3D63DA22A8369CFD02594999A2EF443308FB8\
+298266A11EFA177102C75DC674E89FC9DCC1A0D3C863BC26141102175D2678EB\
+6E13D90BBD9A5EB89AE8C0CB47D7F340D3D32042A2762BC9BF2B40EB40E87FB4\
+2610FE7E357051F01494704FBFF73321B47301A0799B7EE3FE5E62200F397A61\
+ED4509A62F7106ED0EFB0ABD6AE9E4A1FE9B02C092DCDC75015CF602F3B9A898\
+8B609E6C0D1C5C3E219FF57875C2EF01615F89447EA602DFC94EEC17A398C014\
+BD346691FE209A002771DC8164422CD166AFB457A8B3071282178A3EBD201D9B\
+07B27E711E7EE7D33AA5210ED4E4E92486775D14A6CED092E34A7AC826709399\
+48FEC149F9C018FCAAD3FC597D315713F44FC5E1725F448ECAED40E8D841BD02\
+F1E81C019B08F99412E360C0BD378391C67D964B47F50C26F0A483ED66402361\
+6B0FC9AFE43620DBE9CCFE070EF295C049EAC754C2123130C6B2C0232F6403AA\
+7F0DC35A5999BF95D34AD612234C6289277ADB60E4F72EC2DF570F05395B3BE8\
+A0A3C78B732821AA08927C524E15D65F66A3DB8C1C96FB70BC0686AAC310051F\
+469FC5EF880C0F66947C1C328F97684EA24CBE63BAED8D114F40507C2901034E\
+6AB3893F366D53F1CFCA309309218CABCECA4722FA9CCBC7249B87C12FF8397F\
+40487EB00082E7F551D27E301C3BC7B5389F7042534BF7E692DFEA4DA24F7C34\
+B8D2FF145F54B517FC97134EC5AC2CB925C508D7A6BD01FE7B764648274972BF\
+08560D30802E0EB7EDCC57AF4797BBF92E8688268606B0F1BC901FCC22136281\
+665EC16393FA9601C4FBDB18CD1D1EE382BC07973903E91FFA87399D1141D49F\
+4F0C064ACF3AC9897891DF10BCA0116F2C3FEF180FE6A8E937C478F2EF293AE9\
+186DCB1F76B6E48101DF64E57EA7C64C5C0025E221C8F5CBA5CC92D9CEC62814\
+0996B26D17F439B780F59A999301122F82D0495F8AB5AE1EA5790F45E992DFE0\
+0D5F82A7FF1354AEFDCEFC0D2D1731D22FA2B75AFD4FDA25AB194055FA962838\
+1055247C8C7587D22E73C60136C4282452D47AE03AA035FEBC26FCCD42A1CB79\
+CF866DB6418A49FD8261E877DDBB839CC39514DDB87A8A40D795532626FEA4A4\
+C35D13E028F9ED1BC09B06BE999B8DDD2258AA0596BCBBF72AF67E10BEDD58D5\
+99B8D577A583D676BF5561F80CE5E9528729A92DF578FE75DBC70474B75747A8\
+D55DE70E57BDD62D4344DC2115ED4DD62F1FC98BFA1E7421FC0700025C46D0ED\
+1BEF35C3B778563211B9FA9E8BA4BBCBF01C2FB626AB7EF325CE9F468DF2CACD\
+B178D36557CD85D542C067C289E926C1EA2F20ABD329E984168BB6DEF1DDCCF2\
+14DCB6A53AFD462F0E7E7A19E8C88F049244125A6D7DD41E58BC9B2FF7FA2478\
+DF76AF73090CB1AB59E388BA20E2C297C967737A1AF61793B68ECD7439444C48\
+E28E2D09C48FADA5E0D1D15E5B340A52F8B3B854CCA479F0A598445E14F53B3B\
+A36891050C79673DF3E2B5825C955A29E5C9A22F3991D0AA785718CFEA1D2385\
+F8E47E4A75ACBC7988D0558D541D71C4E6C5F1CB15B60CEA0C34A67BBCE105D7\
+A896025E0254DE7D7AF724C9027D44B8642192A08AB8E1EF3046DDA6014DF7F4\
+C9E63C635E48AB2E70B640D480998EC9357E665F99D76FE5529EF23C1BDFE017\
+C3A66CD4EB2DDB42EF85EA0CD65534:\
+4F02153C6F3B705628C62048C1B6615C98B18D436E1B1F9C552BC70D
+
+523DE8B1F4CBB65E81FF0B6CCD6EB8EF0A0F0A691ACAF4A77F25ACD2D66AD4B3\
+EFD25BE70308853C094412A518A32020E3020A9F6AB32F0CD60EC0D7A194917D\
+6C457B168A54A4B46F7B0D0C71BD61CD202F4C718776A701E0770B0EFA054187\
+70F98E4E79CD066366FB3300E8BE359A98B82B764BC2FBBF59C7E8F94A157B01\
+C6C7577B1428138CD422BC47330F8ED99F4C0AAB0D984287445539839389EE08\
+D6345108AF26ADED0EC1D7BE774CFB8C5205DFE07CF6CAF8C1AFE37C7A2E4FE6\
+013B93EB2463DE4E0971C7178D6A76B16A0E8960C984CE8BBE71B3B466EDF044\
+5B835F09414D01F14C7B6167FF78FF118127BBD5F812C27FACD57B3B120E2BCF\
+E87315C7A92B82EF5D50CA14A7174D1BEA7E056523E055A6AE42EA3765094E55\
+44E5ED003C989C2F98F38A17E3DDA74DBAF9C669A319638A2698B0E4A611480D\
+8AD3CF016792ECD1034925F42B9811A7214D623D047ABCA31997DDEB03275F80\
+DD21F40DDC80616E7AD3D481E8EBC0A1A6A398E16A78369215541ED10B75671A\
+DEB1AAE6E11142A1CF665FC1B7332DFBB0E10C21A2B48F78E57319AC9C58DFA8\
+B1C2548E2979EF1ACCFEB215AFCD6C2C1B46FE97DD491758378330EFFC728366\
+1D2CB84FA05281E9E517408508D24D042E7B9BCD34DB87CE972E4CBCDB98615F\
+B93093369DFEDC782F44BCD03E81CF93051318B2401FF29F753A264BDA65AF19\
+9E3FCBB8B5D39C838A67D6C7A3DB046DC56C323DDBB5340CBC229E47CFF8C9D2\
+9B7A49AC0EC8C1440AE498C7D150EF91C29BEA7DF3EFCC2871A13A1D72D139CB\
+4603D9FFFE85F6DDD544850EF63C3944FB35DBC00D4308CEAA6394B6E23F650D\
+323F8F7EF50DDB68F1486EABF989BF44451F620EC9485C0B52D1415D3C909A2C\
+FBE9D77DB19D069D33BAEE4D77292E63FCBF65C1EBA24BFFDDEFE95211EF0AAF\
+8ABFDA9F94445E582976F986F5382CB669506AF2B4A5A0C43000A3C72C5CA4AA\
+CDC9D3D39FC5C492A393B6C341B86DACBBF6BA8B465100CC683EDB2D9B9F83ED\
+F9C6A32645F51CC79ADC22A52A007BAACA618BE35E356D1FD1CFBDA73F1ED092\
+53039DEF609450FD2D5943B9CD49CBD52A318EE3510D7CF3FD8FB388AC6CB9C6\
+EEFEF3D3CAD8501B91CC04A888D33E16D6A4C9666F5F5F3B257193F2B46DEDDE\
+11842909D8C48ADE57775B0B272E2DC9CEF1A083EB2CE58F4D1F211922FD6ADE\
+D1B82FE6F5B11251CD396E5A3666ED9626036E4E356231C146BBA0A91AFD3648\
+EB7BFE0B9C14F15AF2F92309826F468945CAD0AC422DE3D6A773B76178422107\
+CE0270E7F580B5CCEBA82CA0184AAFA8341141E65E39859885768FBC5CE63B96\
+5A0604B659E71D9DA2C7A43646088D8071D76926163AAFC69E25355BB0A222B7\
+B2DA9F0A20C021ADC462E905A9C3BF31C16D87FBEC3F014F3957A720F1432E17\
+41553092052FB58A198640479ABCAA51B104CC93E2636E1460643EA812BD44E8\
+19C2166EB6B349BA5BDEBAD59078910B5C22A56F004B8D9E4B1224D8D204B48A\
+BE7355548A402736C5CB110F3A1476ED631FF168F4F3EFD89B38DE4751536548\
+647523D334FAD7CC2D142973F2DB3C1FE08FC5CF83F9F2BD2DAA524B37864816\
+AF29EE05951FA09D1C51D9D14EE4F72FD7BBF18B1A724FF5A0958A063947C430\
+142AD2356E4400AAECA442E163372A8F1CD36E2DB988E7781165E5D4E7074ACE\
+40858E8370E883694AF09977704347FB735C8717C42BC4EEEB2AAA50DFE637C6\
+40909CE379BFB9E2608F88751377038D1669F248178AD580A908D7A1B8DCC7E5\
+3E01801F1E485B5893F103F03E0F53B2B1440BE95644D85AA7F6EB7EDFBB4665\
+2196695EA23C08573397B111FF909025E20C5201293B4D223BF7AA01DE7CB28B\
+94714370434B9588097E2401B62C7A0DEF1FBF89809E810749FD3CE9EC3C07CE\
+4BF4C43DC966429B2BEB4D711FC6C448A12097B36F1E6817EAF4937A983F85D9\
+CF3E62CC1B2AC6AE1EC9EAA8CD8EE2C3322239CFE5DB3D4E8786282E630A7D25\
+9C2FEFECA03031C960A66A71E436A3ED6F2F3CFAB4BD77C660D14205ABF606FE\
+561A346F7D849B69475AC9F6822D80B9A2E56D5D495E4B309B0EA963C9FC5C7E\
+F94B217EE5337989AFBC7107D233A8B362AC27C4F69DF9E191CD65AE97D6EB9E\
+5484EB6F10349575E4CAE51452380151F902415AC9CF42C824EB23C9541D2DA1\
+C26DB85F53CDAFB06A12B8393CD580A8E494EDB6710C720DCAE30832967E33E6\
+303A92B1DF0841D7724284FFD2E00B95C6D623B168D21AC1BD3C675EDA33182A\
+2C22370998DE1E5EB905372CC6EF32D5B765F5C94870DF4842D011603BE4CDB1\
+C227E41EB2F2E8542CD325884FEDC9C5C7BB07A92D20D64B836215C59F162A3D\
+A8BB67D6FC13FEF97CAB6ECB8A29E431A6519A6261C4521CCB90E6E609869E6F\
+E398404AE047F64EC4263566DEFEE66329DD40AC985EB8A08D26529A544891B6\
+F57CC235C63C09057AB6B6ED720EF41A3C9AE65768B43F6DCF4962A103DD93C2\
+13171DC2C9194E43265C689B49331450281A3FEBC618D1AA4D65A135137051FD\
+46B568CE294C89:\
+CA5E9BDFDE3AEFB36B01D09BA9D8F8CDCBFD7012D8C72BE25A85D457
+
+F5080D4C59E804BF8F34B334CABBCC7D32011BDE3677F4B9069416AC204114CD\
+9DA7A0ED0F4B4D8344416336EEC15553EF526B6DEC267B1242657DD0B508AF81\
+FECF9CFF9C82A6A7A9539814DD7E097615EF15373836B5D2F765CC8D5F82E904\
+49F13AA741D5EE2FE63898E55ACD85116846807606FE1E2E29F98F9940B067D0\
+D1DF01F080211B2EE4B0A30803782A7BC2EAFDC5EBDBA91EB05F7D7DC8E34BF6\
+D44FEC05824F53418F235FB64E899EE147BCB403C8855E94AF378D182D79C3EA\
+F977CB4E9D4A16D990A6C388CEB567B97785E6F2BC6745102B99AE765E960B6B\
+32BAF01E2379CD6ECB74D3E1A56552F5976DFE5C742BC92BE596CA742FFC3D0F\
+A032AC29F9F7C1A5C43BCCA62DF7D9DE35D0C7C179DB2E1AA255CEDCCA55064C\
+2049FEE1AF2CE5EF696ED4BC46B7C55BDD51F2D44C8713FB2475C0B85246AC01\
+03CC3863B7EB026AE076A600313F6FB40A4DF62A2AF81B7E917951EA870ECB31\
+B3401928B5046D9A1E62D14B30FDEBAF262868517318FE17EC3C0D52524F4412\
+0ED8ED3BA70C643300CD0BC70DA72C964A88F52C3A91EC20BFEB5CAEFCD4D9C7\
+685D8407476B5F34676C5EBD1E88A6CFF1C625322F8CD59B9ED60CEFB21F9491\
+B95E72791F7AC7EAA3C16159FE9DF7A989ADD6C2282C47585E11397EDA9F47DF\
+2B40166E03BCDD6186B46C6835118268DDBEF19A28BBADE1BDE0228FFD7E8B3C\
+3C598D89E24B8CDEE79C940254DE26CC6814BA2722E42F7571600B7325E1FF30\
+0251D52A895B8CCBD049B2953B8D231445F68F7C26EC25A4B8695C8AC116F736\
+BE939EDD762C9B4743E463C9B9B2F88E0BC0CE78781CDDC3BCA825ACD463C7CA\
+C2AA6C430BBE820EA94AF9A40B1B5C006E9641A2FFA6E427379E1AD49C81B983\
+20B3431FF0030DC683D61026438BC6A6D34B2C73704D9F62EAEB13ABB3E4B056\
+2B4E0482CD6B2D7AEBC0367EA29A88F4A76F3D76FA1197E1DCA92C8216C84C1A\
+F9B8C78C9E3A7799A4A79A783033B0F5547E8E75E69CF3615AB04EF989FE1A46\
+3B1672C571D50AB56972896E8A50C242F22C7F6E27CA4CA793F627E79608680F\
+5421B28BDD2589F05E65430DF774EE873FCD1234064F7A33CF5A1FA4E368137F\
+F9C1597F1FA0FA36493F20538077669EADFD3B06F788C912C715FB5D334DB6BE\
+D133A8FDC40F5496E66AD63881F0BA3727416715865253DC5290327B515BF68D\
+A188DD5B4B0EAC7CA712CAFA8FCAE0C5503FE58A219182F1C30DA6D0C19CFEE8\
+97B7D837C97996A35F4CA8CF0537A01D17E7DE0CC9C129E4DA0ADAF1FDA85030\
+DF9127BE628263B0624F372C47C3AC87EB945A57F5C732BEEE81A74030017989\
+92F3DC944114FF3D54C4666AC5AC8C98D0D5596CBDEB420665F5EDAAE747D54C\
+F7EDD37B162E372249D135938CF17D174D12D88279CB4C32BD6F018C766DA698\
+3D4EA51D6BD8FF0A9B34E9A93BBDA70CF1B4B867D60A74811FD98D52FAA559B5\
+2C755CB70A76C94BD19654CAE7017CCD70222BF08C5D7AD1F5E4E6344FDB3ABE\
+703452C29A696F39F9826ED8BC510A4A148E5BF8A5DBE6B82D7220164F08011C\
+05AC5159D52CE9D45D758B645BBB248C2D341DBEFA1F8602C5D458A64F38F3B0\
+4DB39089807B6A10E1BB52770B92CE72E2D3BB0C2241CDED35054B84558D1CC0\
+99EF7B2296951951D5B6A22F93BF962AC5EF8FB55EC6CC2B316428EDF12078ED\
+1B66D525D022819CBD489E1BEDB02FFBD507D55F9B5D4E22F6396EA233453754\
+688D20151A09C70044B8A5A9AC033C3C3B847AD833D5C05B33407666EE82F958\
+1DF9034EE15A9CA67D52F1D9B634B84C1B8BA9E515F1F060A5AC5CBAE2DE75F9\
+4E112F7198E239DF08D3103F065627438995026DF511C6E5BFDEEE5667D511D4\
+181850C7C5D179107C1B86D24D5532A88A4149A2810DCAE73731B0E1247281A6\
+FD31613DF6891B4C17B7A6A9AD9B77468254B93F85958AA0F01CEFC10B25169D\
+C46E035D3F24557B4BF0E7D60174219108D916FFDC55E25BFFD9809EFD058E12\
+C14F39C69D8FB73D3EC6458F47F2F8DB901BA76C86550B11B54D0641D4DB3EB0\
+00057DD00F2E511FB7A47E959A4402A3AC5462234B40B184020FCF7A0396C4D0\
+0A987C8741A4537BC17102A5C42AFEAB9F71EA66ED4CBC7B5EE682FF04F56F4B\
+A1EA0BB326C4089930F9E3F3FFA3E06637CCE32113881A06CC3A13837448145C\
+2BD01307A580FDBC385D8F46FB92FFEDBC8918D269DD1871164D4B3E2023441E\
+C8B99C82A5F09821CDDF6B38C9ACC3BF3A38D5628016159588C33EAA29D9463A\
+537C000A16AD8C177DC4CF716E625F46FC4CA8C19FBD8EF320F1D680639195C8\
+B195B0A02738E0665F4190D6287E589CD6DD45B9E8CC23B08E1681BFC6F66B88\
+DE6B091E825EA4BBFBD697E10BC407570AE4F2A3EBE569554639C2B8E051656C\
+C30C837F5A92260EAD1D552B45801B6D28134166796C87F900225CFDC3CC49D7\
+2DFBC18D8D95B1E160ED3CAFD5C3467D48AFF87402CBCB1E1420E3FCB588AA19\
+C8F42753B59DB6FB6A9FDBA127CA806DBA7DD97F2488FC2E438EEF57A4CC85B8\
+8DCFDE76AE1FF61225A1CA8BF4A14F729950322EA681B16D6492902506702DC8\
+F348E4D3AE7FB55FAC1231FDE82091B34F1791B6AE37587B10325F6FF5E23B85\
+5845B86EAE90785B9D10D90A16644D01BB626F343B908A9591F4069B21822CA4\
+ECF985C1E710475F33DF9AF4764CFB0FFE649063775338F15BEA7CFF29F16467\
+8160960A80ED148C9B7FAA58E9139911D3DD9536F69646F718F083DC9029D629\
+4FC4C607688AA75AF350AC2C0B001A157D023D73D86ED8133809FCB9592D1208\
+9CBD7A1BB6BBA882FE227C09A53FF088907CB4BC2FB4B7F62D41D3D397C4FE0A\
+D12BB3964370E21712951C679814D506E738C0201E42181D231136A435AE0397\
+B61CCBC5E8BBEBF8EA77C8BC48BD6211F29248F9D498D818E2B544D28A5E60BA\
+727F32EF4BA2707962230C900076FB764D0ED5CE078C9DB14DE894BBB836C6DE\
+9E83202AE89F9A8D8CB0341E1C81B5FA8B16731B8E231E969C0F1EF95336D4E7\
+3EAD6DA23DE3AD1EB608ACCE4D4D93996DD76EC1F5F2C576F6B3B76E07BD8A81\
+0FF5D88B00FFE48C42700B61CC499336E7FB57AD72FF44FC631C7222C9A3D1AB\
+F6E77B5ED7FE2F7228FED6C849BF7142C4103989A80F7C15642AE61650CDCA7E\
+854EB25E9E72F4C3E3768E6CCC8BFD556B56D3507EDDE9E5C331DDEA75568B07\
+813D20E8F4C9547838ED28448F2E67158ACF0C00B131473847816C5E2DC215:\
+F43DB3485955A0F7EAB0D2FEED4E1D95043B4081996796BE9A7A4E67
+
+08944CB473B828B118A31986DB67FC757F238182E790553404B792AA4F0095A6\
+A83291E287CDD16521A3AE8C48F56FBC909DFCCFAA7BCC570C2159F26592DCD6\
+B15BC4DD55CC05595AC634B2C3DE15360B0F07A03B5957BC9333CC5097919399\
+DD9973ACE15E55940178C4C96BB5E0A0A10BAE175769548EBCE11E0D7D9DB296\
+47F197D4B87F7039F5D4E59E016531DBEBF55A797AC9A6835032CDF34240A7EE\
+7423E89C09124829CAFC5F89431C8AFC54FD979E50D48A82B47A53523C84B600\
+4DAA323EFB708203E5388A6A5110C6CE2E341048A65FDEADEB3837A03420F9FA\
+DDC3F02A544F1E46D96B07C90C7971A7040A179E8198E90AA019268E00367120\
+D5F3D98A5CCE82C885E77144B1AAD66EE682847776B04F01F501DCBEFE390308\
+0A8058B3B8F1D823D917ECF31FC2D5B0795BF95A55C7093ECA7C801DD0BD0DBD\
+BEDE7D56513128B29FC0B4D25A6240B24C99E017BDFF7ACAFC8F8DE9FAF5A294\
+4384AECE82BEA04DCCC6D51FC6E6F27AA38F131B7959B13681A09B311D242E62\
+22A1CE5687DE5C080508B1DB16B6F8290D33A3CC0D0138AC61FD9093825E9D37\
+52889E9F20DB9F80F92750EAC88B38AC81C0016D40371EAB4A87E845E91446B0\
+A07081B84F559CDB95340CB020AF22AEA1BFF2FDA12F7A42973FF163A1C6F33D\
+B8B8214AE27ABDF1C54F5B03E29310FA210125E1296E8AF93A2996DBAEFBADD4\
+C51C2C3B8A3E2BC9FE060C42BA32768F6992A99599206CD2291CCC5BBD50856F\
+7F8D2D0AE1EFB5892C15A799B77482DE4553736B162ABB06631F1688F6746E7D\
+7A37EE7EF24E6CC901175F04960C01990178F81E957E941DEAAC8846B3704E24\
+204F43DDB0765C433F3F7D4D201459CD65682B7DDF3D47E95CDB31B96A4CB229\
+07F08BA6E92A4A07703B2DCF150F922C4B7CF181380303FB72547847305999C3\
+C8F9AC877D05D9DC4159DEB8A13D36AD1D533A56950E20F906D29D51DDC45BD1\
+5C1773991707480E37B827044BDC6473181B760A9036E0D3FA491C2F08C55130\
+D8CDD5AC8E97D0813164AF3D28A585F0C2EC7004D498F95C6B62231A632A56C2\
+D0C48FC3A6992D4051957B9ED6D9A86DBCCD962A8883CF82CAF01DA2F51A203D\
+56B6089BC8FD0B1BD414C8063031ED469555E22EF872689C130B1C101034D572\
+FD8CD0EDDABEC9EF1503D7F728B0941EFE2B9512438C7DDB176BE2EC2D9FFCD5\
+6495A4511428DF02819CDDA18D1ED5D3B16C6F42AA0AC681A9FAB51E8A1A856C\
+15C51A3EC1031427142EA12543014DD4ACAC640B8A7729E63AB7DF1051112CDE\
+FD4B988A2258334FA9A7F5B3A87A02074B9F69DD81B83FC74089A91D76AA4041\
+259E80FA255F2084902AEB9E996AC2288AB464BDEC47AAB26A28A2A819498975\
+5D48FC9A5C9279285F2F1DBB8B8018F3E4E13115D78A879792E45A8F4F24ED4A\
+317440BA63E6929056EFC1D2529B75A709D6C0097DC2D97F646F334EBE6195EC\
+5630132FDE58E25DBC17DAD822D9FA0938A2A2C926B105D108403DC29CF371C3\
+504FF73BCE9C7ACF9A74C4954CE6A32DA96B21CF3211B3E49953DAB78C49C3E5\
+32A349003C59C62F7D40261CBA63A9EA21C89A38AA63CE431C43AE261C4D9999\
+B1CAF491FAB8E7BE6E8C3454F1BE8793B2D27141FC107DA599A4694C41353D77\
+85C05B5E31440458D17C6DB66FEB8A9C5C073FB946A67AC0312BB669D9B12FAB\
+AA5272CA6631379EF4ED420A4424A5CD08526384C047C33A84D5D7DC0C215366\
+3B54C73DD799A3568C01B818992CDF8143F1DADD6B50CAE6EAE13AC66F31FFA2\
+B362CC4D2880592B7FEE4B9E4CD6AA5E5DE27AAB9B5DAD9F7D39407AE927530C\
+AB2B61CD7394A21EF47BFB813B5EA6091458D239664923280ED0D5CCA8285BB2\
+281A2F9FB3FFECC8E9147E1E8FAC957D90C9E5F513738745A47C2AD0C31FD898\
+6EF3B6388C6E821F166513811D547AB4336B5E04643497FC9F8D6E380EF6478B\
+82B6E2F5F65DD98A63C68C32B94610E1D3B9538F13A7688FBB1EC3448BE9BD77\
+BB93A34546172AE8D614F85228988E7FEB18C9A0C9827699E8B3CBC69750BDFE\
+CDA8268F694F4C509BEFC1A1166F85C829725299D173F867A300987A2D36D1BB\
+BE37BE3208FB8EFE9152A41A5F0E931B6382FF7F9B18937958FB180E61F2A8C2\
+8F36C3C80C3722935AACB81C24AA17FB3E7A1026F7031A7449818ED62BA7705C\
+A27C2D3268F90B6322921683DFF800A306CFC186CF2A61B37F35837B217E3B2C\
+ECB0843D84EAC67431E3D689F01522D4A4C73618B7C2965C9DABB15C0BE637D1\
+0CEEF72271CF39A7B803B41767BC34433C3E6FF449A439AE13DA1EAFA038CB9F\
+2E1C84F1CE39C05DF56FE3D7B82386C4E628B6E27CBC5D575C66ADA3510C246B\
+D04DB48F4AFC2D7352966DA2266C2BC9831532F53655D8BE42B421AC0D70D8AD\
+1D3587257886DBF93668E907E861BA64F45999BADB0F766EADCE5238B5ED397F\
+265935194812C03C5769137BAC97140525303CF48D65F39004A3F59B1FAB0989\
+5CEE05335D15B9B12265892F4ABB92AB1DD2002ED00CF3562CB67DFE1055968E\
+4AB3306BB34BB87D0F64B26848812A2F7B50424A21FF94081A7F70F7B684AB0F\
+092B2B085DCF84CA38414CF7290F607BF79C37EA84253ABCA8D4184D2DBE2E90\
+0200B81479E1CE8B71DCF2BD6E3C557A8E431D627BA669C2EA03068E0F7EA62C\
+29777B22142D7A1D451BD541EF8EBDDBBA4E3BD8FFCD340E935BE7C66EFC14A1\
+3EA48134F655B0DE3180101F09D204C379743A357E6DF1268B55A9F7524398EC\
+F3A59849A27B142239059998083E8FA91785E91C4D220B2FB17E3389EBAA384A\
+49D89B5D78136DD2454F06CDE9837F096B744D53221127869904AC227CDF30BF\
+EA78CC5545583F999B9C42A1184E2FB9FF3EC095B9DA0D138205C4EAC4C8C480\
+C43153608849F63E161135C79D8B6C9CFE9B8DFD8AFAB559D8B595DDD4383503\
+3B4BBD391E028BB2A60832D9B697EE61408F149744DCE71AA11BB2B0436C1E26\
+26AC3A27CDA293366B90B9CDE2D927855130758D3946B867192DCF3FCE9A3B9A\
+5276E8C37B8CB136FC90A6DC22650F95E796A9886EFD3F424BE63A66DBB1041C\
+B3D4A06F4E7EEE89F0B6D15C36F9EA010C66B332011C8888E8E4AB2B3AB52231\
+91E1388613A0FD0F07C1B26D7CC7CDF1AC62A226454D6291B431CC3EF2DB2B24\
+42B37DEFB942117FA247096BEAE598611B8104F37BEBEDD8BB8B949A89B5BF8E\
+228ECA1D8F16BFEC75A02FFBB4EEE3A6D4A6087C43634D675311E72A9F3253BB\
+5DD364E07EB4B9C84F586BA267BAFFAEFEC79E03B83B18595FE06D7E063EE604\
+FF287004D141C1A43AF0CA7C5651D98F633FA875B4743353FB07BDE59B6567AE\
+25F7095F1D9EDF30570E2F7D7EC194216898D910F9E295A41DFEE072CB56F914\
+BB78CC9854129250F9874B63BB3EBE9A1CDC6EBCB0916E1C440354DED6AA818F\
+2811DA913912A21D3961AC94A39F0827D3A419616905DC45842C8E69A43004B8\
+AE922C8DE1E8CD0668674A7760153213835BC63FAE4F8D65614AFD74A34D42AB\
+AD5025B884B34639340B45D49CCED423771916E18AA077291923017CA50795F3\
+B7A3F349A3D29923833CE57801C631576E23B838A7767CA1BDA92B82AC502DB3\
+688FFC83C09A4E40CAC31D20D9D32FA6724A80BE7091CDE9C7A6560CFB326B46\
+7CADDB9E9B7A491EDA283EFB0B61B4A1116DD859D5C0897EAA2A3FB2CD82FFB3\
+3770BF9E08091363B6B81D23E61C2A647D2BE440C5C79EA89690656D9F10B1F0\
+7942834E1CB6E2D2DF106EB6D6A21FA23819E65028515E88BD279F9317BEAFFD\
+394EA51F8639371C3A89F11305A4CA35FB0711F5E2C7C3DD1659C79024581211\
+3204B4ED8AAE9FF09D43C6DDB13F5070D98831B2C7639FB6B9B01C288812DDFA\
+8861DB32DC8268C07D30CF969953042B3DAD530D9D744C06AABE7A886C0FE57B\
+09B7F42D193FB3E9C06329818251A2F7E6474462C95DED:\
+3F3AF252BC954FBC567A0CB6A5517AAB201D177D855E1BA5FFB14B74
+
+1A3DEAFCE70AF6F3F55D66AD9CE78D5F4D5C5F2638A810AFCD07D67E9F9A1380\
+D6B34BE482EF030C22F1E978F544609CCE35A74C5109EE7038495B6210CDBCA8\
+DC82C6E9E7B0D593FAD9665382B3C401AB8941DF71307DD77EBAF140AA66A1F7\
+6316478850E58886A9610631E9C722F459FA00C0B53124FB4F12778BBBA37608\
+26D3DBA67CD030A96B654AF93F8E395F5F439549489F8161683F124BC980E693\
+9C83A6085E4B6CAAF8BCD89A0E01ED70DB487166CC29735D9235A9CDC57B80C9\
+C2E591DF6322F5BEDD32937073F781A30389552AE83FBE147D1B3D3461A3DF96\
+C15CD96900C56718EAAE838417057579115936862679F5F2A45DADF65D14108A\
+F1641DF987B57986384FA1433789F5DFBE87E90BD4E9D8D4D0741FCDA7348322\
+B967B566B18612DBB8FE64F151947C3F7E361EE868676BCCD0CB3A1AFE046BE7\
+0057A05ADD3E65AF31E3FF414A627C0183E8FF583B41B75B203650420216E6DF\
+CAB289665F054CFE3EA0943647528518573BBB1D0F27E1449E98739EAF0D0094\
+32DF0C1EDC1625264B94A71DB762659FF5A3A7A867F182D1F1FD34B341A4A181\
+221870DC4A494013091A7E3B2B07E0160C438F1EE1E8A2B989C4FFEC36B5083E\
+A427606767C29672F44779A8505B422B25A56907F565B27690D011426A62DF00\
+36D57D967CD1D14E915BBC2691E7AF818C769D9E1F9EDD40894BE88FA1D7A595\
+2AFD898E837716ACD73953BF2D1D448123FD1A0276D2C2EBDC760A4B787416CF\
+AE5E963FCBDC8B551CB70F91DA0ED4A8090FEF178E879F2C34F3A269DFFFF097\
+72D44A13D7A17468B5834C460957D5243C325F63F05F89D4ED98D361E7F0AB8A\
+83948A64D0CFF8514841AA21C7F337920A9983E59BE4A0F1339E1E462F92DC1F\
+C070126206012458A499A8111FAE078E00B0CA3BC1D6C7087CD318D5603C1C7E\
+0425E6F729CEECA5F35B82F8A42E0E9B950EFB0904C5FB5C06D91D239913665E\
+D1F1EE4B82185A01BA86CA2D3EA94E5A8842231A94C05280183B7ACA28998410\
+3F122203EC2FBA4A382E6F5236D6F68DA05E3BB0C558421F0EFAB91DCEEF6D1E\
+CDC60F9B88F8BEFE31CDC3C2F024A1AF2C7336AA5D151E8CDA814A5FE898BADE\
+B9DD680E337E682EBC22BFAE445417E37D2D89A338659A280AB1206DB74DD42C\
+6F25639C1803BFDF2156DF613B0F5924D209F7F9003CE8794F989F4F27B82121\
+210F4F65EC5A1F7723305CEE438C41F793EE04496BBE337BBD2FD3023830B1C8\
+889C6F4D0C1192E364EDBE1CD987BA5D66224EE9C9405E1DFCEC0EEFFC5C73D3\
+123F6731C6295D1E6B854B884FD22B6A3BBBE5395312585CD138BCA67532C6AB\
+71BEBC6657C50DA87D2AC6068FA3970202C5E15EB7B4B3D2676C0134BCF1EAC2\
+B26BA46930B5E660B16060894884C88BFACD6779276B86F685AB6F17C6D53F62\
+1275FAD66D021D26D1D480AFAB4B5EC75E0E763FFC45F599EA02504DA5D91EB5\
+EFC3E4AE196F219E45E7CB05594958C876FF474A020EF73C1F09B1F7F7457E81\
+6D3AF51D86663D4D461754CD5E907456691E02446D6CACFD33516206A3187054\
+3D574592087773653D4086C2BDCBAB3C9B65CA11AD0D4E58DDDA8B4403099898\
+57103929549B7300CED42651D4086661694092C42875CB62858E6D1BE5F7274B\
+4BCD83AA4DA05CACA186A30902830790F9FFA24418E1F9DB00FA40477E83B05C\
+2D11AD7D81DDDB1E31F94A9DD5E9E13391C22479B570976E3AFC1BE41086D3BE\
+6689D87CA4326A7CDE8E5B396A678D3CDB2C80FECFBA2BC799AE8B1528E96D88\
+0CD098DDE910D097EAAE660AD4D7EA51C18F18AA1B39614299A172512521DFD2\
+31B9840909839EB69C892EE23F1BCEEC1FADBA75786C7DED93BC9983F74CEAB3\
+97EB8BA84F7E4130B34258D628594A6F9E2348FD91BA2594E07B8057E8A2AE3A\
+DFEA0EF919555385977041C5B6DC4F3880569171F7217AAA9A85F2F5BBDFE3FF\
+DF79248F2A35FD4DEC34980C67290339B1C0A5A6AB8838157AE2F5140B4A2492\
+4A6688AE5CE72A48103EE9029CE8A0F15B1FBB19A12FAAB80A7CD9C0E389FC27\
+75833E3190F1CF735ECDFE7F6B6C326506AA82613CBEDA8DD3691B81F4C1E3B0\
+FC32D7E6719CBFC12F4A26E0FC29D6417953ABC9568DB4ED9A294B9FD5F2A666\
+DDA546ABA301B1C60985033953EFD6F4538333B5C7DD3148814A3FD7927C366F\
+40B3D7ABBDEB2332DDB586AF80959097663CFAB2FEECAD6D368AE10EFF9663D5\
+F8BAB95935D25F45776F7F04B46817D05165A9DD4770509ABB92F8B9E7373CA7\
+80703569981754A51D6D376D65C57F55CD70E2DF5FDF5A6B829AE30CE3BF9428\
+15C8B4BE858DB58151D02A68AAB9FD373E047EFA51BD1A0CD1B61744D9E97CEB\
+A3334B3BAAFEA3BC9E43AE097CF2C3D713EECC247FF43EC74D54907D8BF45E45\
+B2E0E11D82B126A8179D3F66C055E11F69EA67AACC5FEE8AF01FAA379E51998F\
+5070F9EE0FD30A2EB22A925586FB1B39024EB5EB1E127C76A149E7F02AF1B73C\
+16E9E5A5DBE378E08A9FADF1194C625132AB3FDEFE8FE9A89BB8E0035A1A3AC5\
+278F5D3D0ADE0E41C81C6853A41C4AC45BE3F68180FE23F27F18BE2E339DE1D5\
+59D75DE63ADF7A32BAE42B037AEAA3E123A5314891BCD35CA48D57DF4C17540E\
+97202A8EA1328DA25B1FD6BE2B56AEC1E5DEB209F3B7A13ADB1CBE53EB645956\
+E577A7621D74E42376D70BC5C4AACD239A852FBB7B3F62CF59FE10438C1DC8E1\
+E46566325DA0CA43AAA63FB7E0B450A2DB3E3A2204704D894DB24B72B3078106\
+E096CD543DCF027650CB4965E38AC36A8AD588C5962B4E26548AB88F0BC20E10\
+ACC1C3FC00EF415B3C32499264552B14E2C0E789A3B8A8BFF9620FD939D0B34E\
+806177EC696A4B3B1CA4B32BA979B2690CFB3A6B17BCEE6877FFCE757E4116DA\
+01099FFE82ADD5A0C593E73449A96DB9CC2B9E846D166B095174F2CAF8B35DD8\
+78C836D9BB6EEEAF8E1BC5D0E149C739828CC480D731DC16B35B80D4AD82ED7D\
+29BD05018239EFECF8DEAE180C6A459DBCBFE4AAB9A5E2C1E1BC31418CF2EEEB\
+31FDF8BA02C9A91525E9163F672BAE2EDEC38C1BDB84EA237B4EF86BF5C0F0FF\
+E178E3761E82D94F66E5EA40BA8170BF768409E1B4177AAFD9937BCE3FBFF590\
+320D7C445372463FBBFB34F57447F42C16E026F179CBF82F617C86D1E8D42F6C\
+908F9C6B77E38D25D51303DBD781FFAB569B4CF31FD0B947C45E1768A2E9DFE8\
+369F520DC38D77937B69B821DB4FFEA8F50EBC404F0587B5598189F54B5A5B98\
+966FD16801C87DE2C3C7813DD70DC600824D426D88C55E89D47214D59206A7A6\
+5A65DA7CA2E42FA62ED17E7AA5B3ED446BCC71F17FEC8593BE96D2037BD07F94\
+76D4D732B32BC5DF8C921316B45699004716FC89F8D45BAE402C26DBCDF1A340\
+847B932FF882DBEAFBEDD252E126C89A1E1FDD8908A1F67D15D8E432DAD8E08E\
+950A3BC46B96CB89CC5BDAC703B3FA3E986EF1C6E7E6606E6845BA1EB2FBDCFE\
+E744B5E45206F4A419E1CB103C8490EB293EE9AEC1F0A0D294F9D3847737413D\
+30873F3C94740E8FD072817815EBBCE3F09EDEC9D1211A9E99547D620B2EC56C\
+89E9CB8144AE9E46636324BD13C6CCA3AB9CD9FD8F7F937ABABC598232384427\
+A2D4CE0CBF9765F7225E208C3CE128602B0AD08A1BAAB77EDB3111F0C6CA7BA0\
+EAC9D89D5B4378EB82C17F6EA08308A79A53D150D3F85EFAB77294F02EE0E288\
+5EE2AB2793392B87DB11FA77992F5B4FD75EF2F1A822E87407A4878894215AB8\
+9B6CC4A120F5A78B3C31AB80FFCC9ACEF53FC6F7F85685EB9D56D30D87C21ABB\
+F1652EEF8F32C7C567BD1F08623B09C29F33561D42727A5649A3850071AA6C11\
+735AE63C4FD31559CE560B27A362786A83353FE460B37074664A9421D3B2F6A8\
+64D5ACA087187B27E2B82F31CB3DF5E985CEA271C609B94B4E58356D40C7D5C7\
+FF2E5990FB39588154843EA5FCA92F120075D4C4D006661A0FA1B0585454BEA7\
+25473EEF7D58117D5840C8348999003736C5EEB7858FFD273A1C3EB2812F5697\
+C59110275B08F6BEFBE84C92497D5F73B7B6F794A849713B23AC5F29D5C7112F\
+B2E7A6E89EB54DDFA3122E6C79624C1BF25EBFB9FE5CE6DAA779F3ECB2984DA4\
+2F8C6ADC77B21DD291E684FCA50E46070962A2D4F00813D8DE1B8ED33FED9715\
+180C7EA8E2BB74FA65D9C7F6E142F3C81CDC59172E1020F62F65CA5A12CF2BED\
+9DEA04A4D8CABC2948F7BE823A3E792625275B3925A6C8D8E2B428C75A5DB0F7\
+120278CD7D6CAB768755C7FE2FBF89FDED1FB38AC7F76A2F8798CA36ED42CB7C\
+07F006271205F546A4812C20077F050D4CDC79459FA686E97F0704B7A9FF7DE1\
+6318E862C53D361BC635A55A264BE15016545DBFCE3C6D6849576ADEFB6884ED\
+D768214E0B438B0231B4F2692C2C0B5C177674F8A0DE236EACD9E0CEC7C8647E\
+4E9A5861B957EC834A2F8572F01304C3FD6A06019E5F1499B62BAA8670B65246\
+7FA9A4F10F053263BFE9743CC7D933F86136AAE3A6FB56754D7D238397A0030C\
+EBEA87CB255AF36138C373DBBAC41DD4A697032E4796C552AD9C9B3FA713C3A4\
+E09E0EC5581E94BE7F31065157662F9E9C678B1EF1B8B8A847C51789C22B1841\
+BCFC855820AF3258AF9E08231090B45D10046A00178E89BD515616B8A44E77BF\
+57795DABAF40687B2CDA7A5014168F:\
+4C2E08F08D72B88D5CD8F1F8AB534FB52B5E3D8FB7EFB339CB33E45F
+
+1633256AB03B20CE079196B708A1C02D1B6072219070712C8589EE21341D5075\
+2ACB6CFDA17E982D828BBD6CDF54BC7232FD418A323D64939928597B9B52F07C\
+F488250C5E42BFD3AB48012D709F8D747225839296386FCE5FC5AECC4BA7A107\
+6D089DEA8ECEFAA0CF66FCA8602395719C12A04F929321784D7AB8239FCE2FF3\
+BDAE046A266132B5C2AD9F7261F3014E87B389A6695978693D9371D0B1FF9C40\
+5F338C2FDE4687359603950A54CF4B9CDD9B24480B239ACC5405C14C886BBB03\
+78391CEF0662A38882BDD09E3866AB9A66CFBD28EB5EE4F8009BDEFC4AEB1670\
+0EBA7DC557B489190A71FDA75E85F7EF841697F70FFD4FEA185E7A67C81C5B8F\
+273BFB97B2CEF695C1C74446C4B425BE6B2E66DC0AAACB247E4467B7C7D84EC3\
+3B6B5AB8FA1979F503008BDCFF948CDBF1226B1B066CBCF34797298F3BA8C60F\
+A01E0AC8B803223C656112FB91435D75453BAE4707B63330467DD13E0A4B992E\
+6F7E46995899A2D95D23F4AC3D0802B2A6E7D024DEA19CA408C4BBE053F14C9C\
+E264F129724A18BCB18F385B1CA091A11434EA96D98C8D0602E98EDC8DFA1414\
+1AF93ED0BA66E885E9FA108591AE59E109AE34D6B9F5586E4B4D75E7DF7C3295\
+8A65E88A9BAF41082A0A3F11539DC4EA2CBD9E1C6C3C439B622F1DE574FA7547\
+0C8C939B51D2D1C2A7204B859881D43086BFD8FB90346218D099C5AB36846F3B\
+98A7C847318BDFA01E09717943FCD864C5A8A17B6CEB89D98E872D388F20ADC2\
+BE5E2006846904F41682FB1283214F3D20DBC9FC9E0FF571844A1282E88590D7\
+C085B2C568EC5ACC4462B389FEAA5757F7033187E2DE31955FCE55FEDC909255\
+048B327CCAB2E582BBC9D8054BF5CB45145C7D3A3AF9CD5CF6ECBA490C634ECF\
+00E646BF95E8642C43A4978EF08A574EF1F78F6CE57C3B34B5A123D123617FC8\
+EC9B2AC0F9B70A7F6062D38DD7B8E9FB4ECCEF13DED5C0477483ADDAE4F1CC0C\
+FCA274B1307ED0DE72FBCB819154CDA897D7575213042615F1741A8CB646A39F\
+8D134FDF9E60E000EB8220F65CC30F5FA52C431B9E3B6101B96E25B8D0440B96\
+E572A18A01747C02AFCD7513542F7AACE194632099D16274F31EBABB60DDD94F\
+E43DACCE900EC0902EB5E686D48ED8D09AE63DA0E15C736809903A0297A92DE8\
+4E0260F11F446E1FC448E0EBF59FAEA3C726F97925C57CBDF85B1F77078D3625\
+7C85D56CBBEDCE180FE12B687ADA2DC9912FAC60334166BD2CEF06B089ED5C95\
+63844D71D8FEAD2F3A93F3C07C52537336A8A70BF5B596B9007B9FDF2D082000\
+F20E6B70D2A7E6C7ED27C4146895A6D85A246F623C1B9258A2F891F823ADE4CE\
+FFD59D4FFAD077351E2F506E9A5BDD3900F0204B9E8969AFE72F5DCCB9CDF986\
+D197AE4C4DB53014041AE6221B750E5290E307AD292C8DE6B899235212EF8CE9\
+54785537DC9435AF11E0F3427A9C7B22EFA752EA0B7EADE5F6EB4093BACB7867\
+6E506698139E4F774423B8942166F9A7D22480D814FC0AE19CF4960FBF6E01FF\
+A65C8DA5BED4F1AE2B9ECEC5BE7B3C38DD4045B0C93EE6CC77A7E61E85D331B2\
+3C0D164B104518B3405497054445A353E9B48F2AC5E8E96298D6655614336CFF\
+E6D8C9C915E387391519AD2632366AA3BC935030FD12927EFCA17505ED74C946\
+50C778539004854DF6C24269AAB9C273A493D3E5B0B1D687C33C2FACE46B4BB3\
+742D6DF743D09164D2E0EE7F6BA128BD5FBA2E3B33C199AE80FA9DEE3AD811D0\
+2BAA3D42A6362B2AD47BBA8A2C5CD00B46CF22CFE367281488A4852EB8B7FACE\
+79F0CA6F8E78D32578DFEE01711C4DCF3C26D0BA13F3075478E708C5C5315AFD\
+C2E4C0062D16458213BEC506A9E991A61825FF78DA9BA1BAABBEFA56B4A8C9E2\
+E7B60EC4B7B541C8E0F79C86BB5F03F736761A37169B2AAB8884EC6EA217B02C\
+59035F5BB327243D126B78D4AAB430212439B5A75B80618DAFEB66AA3AFF866C\
+4DAEE47D374B512E74ADA933EF24A841BA271C6F02C870E8AB950FE06E93C91D\
+F0E99165DC01BCB190E411ECCD85358FD4A88127A22E4CF4266A90845124BF97\
+B25D7B1C46D3A0D68A684F84E2A638C692A52CB6E8C651A3AC492B0460004073\
+D5349E35552359CA37660F77B2770D6B2B3F7B1922424AC4A8598B4C61A6DB50\
+7608A72A6A7D573CC055206276E14005A28A0EC41F28D7E260611D40F089FFE5\
+E529375691412F4E9E12E62C3BE2C563C26D2444EA9C69E6C935FEB4DC4E802E\
+5FE3906F8ACEF4798D940C3CD574BB5E74506C3E0B70CB62454A25F589EADB6B\
+0709FE3B50417CD1D98F08E08B7CF68A04CCCF8D6588F9FC2F31E533CDA6159B\
+AA4297FA446450D71C16EA2324EC09773E7C8817ECF680ED12F64A04863EFE3D\
+9D8760F34DE5B0860B3991FF0EE5EDBA22C4D69120DE19D5429E4AAE91C9E7CF\
+05CC807159A58F13B480872AC1609D87E7009DEDB71C09CEAAB640A2B6135855\
+CEAE4AC2954933A0255B425D9FDCD9C246F82AEB7C3BB78C6E73E03DB7AEC424\
+5A28693FBD36EF4938D59CCE19EAFC00671A0851612406A075713C5D1154D8E1\
+3B59B7C5B0902239D4BACFA386AC817AC5EE02A181A9A47C622B3ECF287E1484\
+3D452AF347110498A620B34AB4E116308D976062C9EE9CD35DB6CB79805B93AC\
+9A15AFBCB52F1ED4309879D1924A4BA190B0B86E60A516E77D34B4E0A49D4EF2\
+CEF3CC2F410FD8EC901363FC9EBD75EB460D4D8910BDF27CE26A8B4AEB94F9F7\
+6242401DC35D0644842B99FB6C439B82D82ECFE1AF0D01F9BECB15BEC83F13B2\
+60F7F714AA381032923FDE8F8018F3518547451435C9A5207294D08A907C7369\
+6F6CB000745E072E25B73B3EE11595433D27A1F11468686F08094F1D31F5ADA8\
+1F11F0677A29D72EBB2E1C4792CCC607CB938647E1F153F9EEF03D982595C631\
+E49B6B7C1FA003A6EB8D59CB8892CD0888B05240F12701753F89007C859515A2\
+FEF944BC60B36003A26702AC6FE04D2E942978FC31A97EB29871D6752399D352\
+1720729007B6A7215A4282B2A4EFC2C56BD129E74C9B00847692B96FCC71CF7A\
+7F19F3FD6B45C519FD73B4860880A2DD74E5727B31A93F0A87F0078155344AE9\
+F7BDBF00D83393B634B5DCA88A398E42C320EB95C4A826ACEA90B65E4767B2EB\
+A748F97C247568393E2FD3A66075CC12935B6D7EB5C2FF5282185CB62C73972A\
+37B3CA508004B4F796BDF82B83B5BDF90D6BFD32B5089B0CA2683DC7FB2337DE\
+42E650ED911DBEE1EF98257F9BA5AF54B1A54B04C0087A5A64BA779D86461BA1\
+5337C2E7D4955FDD777A025DE226306A17C384F1C52CDB5946FB0B46DD5C13BD\
+7A55FE2E27E4C6D40D61D6FFC024468F8EDFC7C7992DF5DC5D05063FE7231992\
+24F53678E48F25250EA28BDF1089718EB8B730D1C06735C2F871164E2EB5E885\
+A8DFD2A083BE97EDC94159CE9BF75D2433F1D782762F771903CBF9A1C9D13F71\
+0BA0E151B079DC0A8262BCEB1DBCBBC0F35DF6EECF7BAA7105B9808745853C96\
+B4372E95E482035916B726DAC7BE95A72B19DAD48DB1B19E6EB2EDAB5AC1B301\
+3839E7806625ABC129F41813E6D71EE4AB2040D81E42E6ED73ABBA64FF2EB433\
+B910EA7D4F5ED3D8D27D39BB454EC019DF6114F544D7B155549D0C56D14551FA\
+F353994A80F30F3C97E863A4F2AF316468A568038EB4D799350A6FACAFF90ECD\
+44E0F44EFB6DC42EE4B0DC2C59EA9C1827326DF08C0A6E55CF4F9C3EA0E78CFF\
+3635F5D08E44F1400D20F638D56BA84B4832090454DE57EF04B6C8805A36F63E\
+5CCC6E830C87FFC164647CED20E4C486D09DE7A5F9E4B68D5456CDB22B0DDED2\
+B95B3BCAE529215C2D25D6823C7D66A4FAE0A1E9F022BA5663204F2314DFA51A\
+1F10E11D6D62A8BA6C28B6AE7DA1DEB5B57F2B65D7456059AD9F03DC5A524054\
+DA39DD100D74EB657DE219795E3C45A0E4C762BA22F9DA9D8159E425A1EE783B\
+4B22C250D8894CBEC706CE16D5CA393404FF478F141BE7CC69E45B077BA1955F\
+1F49EFBE4847C795347F703300F672334F490ABF8B644A34B56DA00EC45A3503\
+14B9ADF27CAF7C51CB7DBA0C5477E7D37662F4F23247BCB8F7DD5F3E9CB8BDA4\
+0FA97568832AF0ADC68F71422E412254A6BFC8943BB465B01FCC8DE0B957677C\
+78BC1F7566953E9D2446239F602C682A521C14F741FEA98C7E27AABEC339B6F5\
+B94C78287A894AFDAE971F8DA7C7E4A4C92C8DA47BE82DC2532EC2DA9BACEDD2\
+BE6DB2B2FB34DCCDCB34116507376578CBCA105E5E443BEC0F2EF23BE34CDF86\
+2EDAB34F0FF21335E3ACD92F59688B419F824EA61EEA82BC80E3463452192377\
+131BA51FB0795E089FC077D0ECA8012E58B0637AD7022206887FE9EC00EE5DF7\
+AD2E26FE819EE35C7A179C579098AA3DF645D9064CD557DA90BDD21F871CEB04\
+8CA56DF9653A10ED60F5E9F0ED7F8D89BCF5C22D1143CF44718FF2DFD8E10CEF\
+8AABB67D2305F18177C1426BD4CD03F2625E459CE905067826A214E08E56D8F9\
+455593E6B324E72DEDCC429D3BEFE2AE0599E360DF95E80D453A3A849E48389F\
+A745635BEDE30E7932DE6A3816E31A2217F98D5E40238963D0A36C159FD4EC32\
+D8A5CF59D433DEF3378634AF6887FDB3F3EDB96FC8840FE1B538C329674AE810\
+E8C8B2B46DB208716D38E9D1AEAB097068AD83ADD7DD2647839B3A7388B0615B\
+DE26F8692E9C07D8ADECC2A875203C3D3A9C6CB1D7D06307E9E1D9C3BC536DD8\
+EB271E9A2159C904E61E8C9357FE759F36366AEF5A3D14CEE82913CD2708AA60\
+69369CED763C8E830D70924E82E9015C2998E86EFC1DCE6AC2EBCB49455542A6\
+D7DAB265AD6D7381FFEEE1AA40F8FAC0659B6FB56BB03CD8CAFAACD48D13672F\
+7D524EB9684CFED4DBB7476E99149C28EC08F33BA6AFF839AA178F86B8EEAF17\
+39C829177BA78547AD394136AA3FAD451A11E9642506568B39668B2436610E06\
+EA45FA11D04D3759B033B5382645F15B3C39270B81B80487643913A24F2F1C1A\
+1ED57C85CCDDC8CD6D59B62FA67CC80572968C8FD01894F0153634C88792A7C4\
+A407A4A4CE46CEC5FE5D2569F95A27DE242444EA0C715B357518CAEA23E767E8\
+545983F0D3A4DF66111B4AA1D399CCAFD796D7A80E592D5A51D2B3F60B5B04F8\
+D9C009CA56CBD4DD84127A29B72ADB7645FB7279C9818B2B43963BD605F45B65\
+75A5E2E369E0B401F5EC10EC703F1179B0AB9D4A89D6F096573952E513827364\
+A84D38922734137E969D8167D6959B70F42F2BDA37E4C989ABAA8024C1A84ED6\
+BEB74780927F78B32EA736B9B2B4A795C355C0319811729D9CC399D235197303\
+38D62E16E5035FC52A817090703FE776D65EF9FEF5BA5F4FFEC3CC8E9EB2E312\
+C50A479BDD4E6AB0A56C18C2DF69ED408417BEE28BB41DD13F8366FF6EDA4B34\
+090FC9BC045271:\
+52CF6C4ECE275EC1339D6FF1AC8CDCA0F2FBA3AA150C6DBFF58E500E
+
+[Skein-512(256)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+11E6AF5061A8DDD426A5B521A649FEA5A485A3259F71B4E72EFA860648AD692A
+
+FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0\
+DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0\
+BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A0\
+9F9E9D9C9B9A999897969594939291908F8E8D8C8B8A89888786858483828180:\
+E47A51E65137FDA22CA8A671AC8AC255E8C81730E798BCBF6B8F277E20D23D3F
+
+:\
+1E00D0BFCD14E4C7B457A003451D7A8C60EF00D410A5C443F5F03BB2D0848AE3
+
+CC:\
+429ED7E0FE04482E0F43B187D07B086BF10A19D1911E61034CBDCA8021831328
+
+41FB:\
+A2369D570355FC404C4217115037AAC1D035B05904FAC6ACDFFEF7E4285B501D
+
+1F877C:\
+87F4667094586DF08223586830B1BC38C26EC17CED50B5163F80F0BBD6C60B10
+
+C1ECFDFC:\
+082BBAB29E8701472EDF7C74A030AC8C0AC7555AB41BD5DFA189BB79E3F6FB0E
+
+21F134AC57:\
+A06AE1CDB0D4E3B8DE64F864B96BCC84B78F0C653933E1AFFB4101C1E08DD869
+
+C6F50BB74E29:\
+318BE56C77DE6E24CB0E4EF43919D066E7A923E41278EDBE9B6B991C5869F24C
+
+119713CC83EEEF:\
+95D9EBF047786083304434F6D1041B5DE80F084D9211753848A4BD2F215674A0
+
+4A4F202484512526:\
+7A3C3DA19B30342096945112E074A544424AA93749014FB8D1446E25158E8E34
+
+1F66AB4185ED9B6375:\
+91B959E639D30CA556E69B28CF31A158552D8C3CE53C97A805EC5412D9AF55F9
+
+EED7422227613B6F53C9:\
+0C1B6AA53E1D148E677BC8DDE229A65147FE4BBFDE5A0C538F46AF787DB08C57
+
+EAEED5CDFFD89DECE455F1:\
+D5C9F69AD4584B582D209E30B7C43B234032AAAC5AFB2F4285EE16B8D45FDBF0
+
+5BE43C90F22902E4FE8ED2D3:\
+4A57C843E89574E4BFCF5BCBAD48E7B988CD87865065B60E076219BE4C9FE2CA
+
+A746273228122F381C3B46E4F1:\
+8A6177C2AAA181A6A3DDE78EB56007FEE7E3065B38123326D60050B96B34FC07
+
+3C5871CD619C69A63B540EB5A625:\
+4214355B444E57D04496A6D39C8A0630161F91BFC5D4E7F5F3ACA78FBF455745
+
+FA22874BCC068879E8EF11A69F0722:\
+E39C0547168F39A68E1D3D65F2594E1EFA882F7653C58D5DADAFA1A7E4BAB82D
+
+52A608AB21CCDD8A4457A57EDE782176:\
+4693D075D7CA346A069D1DFF49742179E575BC5512EC671D174DD48139B943F0
+
+82E192E4043DDCD12ECF52969D0F807EED:\
+A8BE7D54BA61A7DAC908CCD37CC0766D92ECB2ADF268846964E55A42049B0523
+
+75683DCB556140C522543BB6E9098B21A21E:\
+FC413AC58A0BB74D815062E24CCFAEF3498D64BE273530ECF4326A7032D54385
+
+06E4EFE45035E61FAAF4287B4D8D1F12CA97E5:\
+B689A1979B693189EBB188EF921F57CDEAA0012E36A1A2A82B0DEA4E09C453CA
+
+E26193989D06568FE688E75540AEA06747D9F851:\
+E1CCA81865E969E82AFE93F3AEFA79D5E05D58FCA4AE3093427FF45ABC17C006
+
+D8DC8FDEFBDCE9D44E4CBAFE78447BAE3B5436102A:\
+47180B3B11DAA5FBC2885A395C9F8999BD4DEA2DBEA9E47D3EEDAB1F98CCCD84
+
+57085FD7E14216AB102D8317B0CB338A786D5FC32D8F:\
+74C3CC2BB5D0A0203D38912AD50A75D68601D6FA22A95776642B1CE1F795A127
+
+A05404DF5DBB57697E2C16FA29DEFAC8AB3560D6126FA0:\
+A1AF63F102E6F131A30E5FD853FCD4041B2F913AFBC2D44242B1CB379736B478
+
+AECBB02759F7433D6FCB06963C74061CD83B5B3FFA6F13C6:\
+40E2925E88F97C2FEB577532A9DFD61FFD6DCECD6403F2D2C681D0B64724AD8B
+
+AAFDC9243D3D4A096558A360CC27C8D862F0BE73DB5E88AA55:\
+94C5B5D4180F38383C119B13A2C17254DDDC12A72742C9C16695EB769EEBC60C
+
+7BC84867F6F9E9FDC3E1046CAE3A52C77ED485860EE260E30B15:\
+DC5F762FFFC40D395EC14BE6A81811CC5C18865EE4DBA4315CF7FB48D85D32CB
+
+FAC523575A99EC48279A7A459E98FF901918A475034327EFB55843:\
+F566BF5EDD063970417EA77DFCBB2816B85F56AA3E2216652E76A8C175226612
+
+0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E:\
+F61113B65011BF8782745E07CFF7EFA1032C2906B621C0472AEF159F7F569C26
+
+A963C3E895FF5A0BE4824400518D81412F875FA50521E26E85EAC90C04:\
+666AF4BBA1A0B1D3AB3D1D8F82EE3FB77A4D11B78F6898EFEB3123EDE176B670
+
+03A18688B10CC0EDF83ADF0A84808A9718383C4070C6C4F295098699AC2C:\
+207FA3956CEE3A92FE0BA467085C64FAE6ECDAC553D296ADF05061F471FF43C5
+
+84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29:\
+7117BA37EDAD8F9DF63BC321AAD902BF7B1827D131C62B70466C95F9F77FA49D
+
+9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10:\
+39D51F70B8356741939916230EB0E2C114580056562B5BCC66B6B4AA058305AC
+
+DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE0\
+46:\
+66AA19E2F0E39447A702379FD38E79FE869B378C8C60A495E89F6427EC50E568
+
+62F154EC394D0BC757D045C798C8B87A00E0655D0481A7D2D9FB58D93AEDC676\
+B5A0:\
+9E6D3AC9CDB3D47603D7BBB80BA6EC09A01F5FBBBBCD8AA6D397AED067457F2C
+
+B2DCFE9FF19E2B23CE7DA2A4207D3E5EC7C6112A8A22AEC9675A886378E14E5B\
+FBAD4E:\
+6C48FBF9DD4E943D208E6CB8BBA3D87D2989DA9271E21368312AC0E7BD365C84
+
+47F5697AC8C31409C0868827347A613A3562041C633CF1F1F86865A576E02835\
+ED2C2492:\
+78851F942E1FFF92D5AD70039518206F3A652D65D9BE7C63F87BD2A42542EFBF
+
+512A6D292E67ECB2FE486BFE92660953A75484FF4C4F2ECA2B0AF0EDCDD4339C\
+6B2EE4E542:\
+4712546AC21934811FDA8AC878D7B533D8877F8FC6238B6E6E243CC6AAB888BF
+
+973CF2B4DCF0BFA872B41194CB05BB4E16760A1840D8343301802576197EC19E\
+2A1493D8F4FB:\
+A29A6ABFEDB0D6811FCD7FA629196C60AB3C38FE73FAA6982B9C99846EFBB8CD
+
+80BEEBCD2E3F8A9451D4499961C9731AE667CDC24EA020CE3B9AA4BBC0A7F79E\
+30A934467DA4B0:\
+0883758BFF55B86AEFD6DA96FAEA0623CBA4C004130DA6A46A2C3B57CC7125F7
+
+7ABAA12EC2A7347674E444140AE0FB659D08E1C66DECD8D6EAE925FA451D65F3\
+C0308E29446B8ED3:\
+44D8C15A4DC68DF41C46BC911B5B9AAE144827FA04F7960B370C05B5BA6D8E84
+
+C88DEE9927679B8AF422ABCBACF283B904FF31E1CAC58C7819809F65D5807D46\
+723B20F67BA610C2B7:\
+21C8AA3E384349C7B181879521190AC9A919409CC1DB0F2AB4FDAE929E6A5FD8
+
+01E43FE350FCEC450EC9B102053E6B5D56E09896E0DDD9074FE138E603821027\
+0C834CE6EADC2BB86BF6:\
+2D461A1A25482258F203BBC8E4545CACA1416D0766291FB01245BCA30F4AC58C
+
+337023370A48B62EE43546F17C4EF2BF8D7ECD1D49F90BAB604B839C2E6E5BD2\
+1540D29BA27AB8E309A4B7:\
+3A0E64622960E6FC6485034A0AC5DA480B41B9BE631709ED051AFBEFE4FE75A8
+
+6892540F964C8C74BD2DB02C0AD884510CB38AFD4438AF31FC912756F3EFEC6B\
+32B58EBC38FC2A6B913596A8:\
+7B871134DDE8454E2E81C7DF011BAACA0618AF97D079C7A166275211FAE31F81
+
+F5961DFD2B1FFFFDA4FFBF30560C165BFEDAB8CE0BE525845DEB8DC61004B7DB\
+38467205F5DCFB34A2ACFE96C0:\
+16E3DBC25596D513C4F299738A85675AA0162D51AAF6628D0CA6EA2B28E6BED6
+
+CA061A2EB6CEED8881CE2057172D869D73A1951E63D57261384B80CEB5451E77\
+B06CF0F5A0EA15CA907EE1C27EBA:\
+D6D8C9191769D23706AB3730B13CF4073FA7BBBF9644D8F0DE53A03A92BBCE40
+
+1743A77251D69242750C4F1140532CD3C33F9B5CCDF7514E8584D4A5F9FBD730\
+BCF84D0D4726364B9BF95AB251D9BB:\
+E6828FAECDC944FE7A36B8E5EAC866D9657B7DFCC39A40F5DADDA7EDFCD149E3
+
+D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7\
+C7F157298EABC4DCE7D89CE5162499F9:\
+5DC506190AC68FA6E271EE4C401598C14BDD9B0A627CBF80156A1B81FAEAB320
+
+BE9684BE70340860373C9C482BA517E899FC81BAAA12E5C6D7727975D1D41BA8\
+BEF788CDB5CF4606C9C1C7F61AED59F97D:\
+BB4813A3E3A65DE6EDFA6BB732DDAB477EE2660A03725AA292ECD0ED9974790E
+
+7E15D2B9EA74CA60F66C8DFAB377D9198B7B16DEB6A1BA0EA3C7EE2042F89D37\
+86E779CF053C77785AA9E692F821F14A7F51:\
+75B7D09CD1BF9D4C472D3EC3381961092B084AA42CEC1A4B8DC2BA8A2EE8D9A8
+
+9A219BE43713BD578015E9FDA66C0F2D83CAC563B776AB9F38F3E4F7EF229CB4\
+43304FBA401EFB2BDBD7ECE939102298651C86:\
+A54CDFA819DBFACF5281A8B1234F70DC71360D45FEF9249B164C424682D96286
+
+C8F2B693BD0D75EF99CAEBDC22ADF4088A95A3542F637203E283BBC3268780E7\
+87D68D28CC3897452F6A22AA8573CCEBF245972A:\
+A07CE23C1891BFD785C59AD1275590859169D9D3D586E5D9E71376E1DAB59220
+
+EC0F99711016C6A2A07AD80D16427506CE6F441059FD269442BAAA28C6CA037B\
+22EEAC49D5D894C0BF66219F2C08E9D0E8AB21DE52:\
+89C3D08C43BBF3449F9FEE260F5CD56E988BF82556F4600A91716E5F9F87C5E8
+
+0DC45181337CA32A8222FE7A3BF42FC9F89744259CFF653504D6051FE84B1A7F\
+FD20CB47D4696CE212A686BB9BE9A8AB1C697B6D6A33:\
+B890D474B371A3B3C1BF791AE023D4BD038212B3E58759D3B8003C0463B831E3
+
+DE286BA4206E8B005714F80FB1CDFAEBDE91D29F84603E4A3EBC04686F99A46C\
+9E880B96C574825582E8812A26E5A857FFC6579F63742F:\
+CC76AEA3EC11317C28A10C81EBC12B0547BF206B95F7394B58A434C5A6F6F13B
+
+EEBCC18057252CBF3F9C070F1A73213356D5D4BC19AC2A411EC8CDEEE7A571E2\
+E20EAF61FD0C33A0FFEB297DDB77A97F0A415347DB66BCAF:\
+4051594D6F14620838A8DA93116C90178F271F4DA8B65646A60F62069E8DED86
+
+416B5CDC9FE951BD361BD7ABFC120A5054758EBA88FDD68FD84E39D3B09AC254\
+97D36B43CBE7B85A6A3CEBDA8DB4E5549C3EE51BB6FCB6AC1E:\
+51696697631BAFD6F411AFD2A53968662BFD3BBC66253B276484566044780C19
+
+5C5FAF66F32E0F8311C32E8DA8284A4ED60891A5A7E50FB2956B3CBAA79FC66C\
+A376460E100415401FC2B8518C64502F187EA14BFC9503759705:\
+0239EE74B056C2D65D372856ECA2D5949D595D3EDA70085AC7490574A2D01EE8
+
+7167E1E02BE1A7CA69D788666F823AE4EEF39271F3C26A5CF7CEE05BCA831610\
+66DC2E217B330DF821103799DF6D74810EED363ADC4AB99F36046A:\
+8052F0E9D52F64ED9DEA11270404E99778226ABCA4D9E3D4086C7A120DD4B573
+
+2FDA311DBBA27321C5329510FAE6948F03210B76D43E7448D1689A063877B6D1\
+4C4F6D0EAA96C150051371F7DD8A4119F7DA5C483CC3E6723C01FB7D:\
+12463A357E0C2ABE748693BFE81D52BFDB782C7F3AD5A381BE92DA1D5EA0BA87
+
+95D1474A5AAB5D2422ACA6E481187833A6212BD2D0F91451A67DD786DFC91DFE\
+D51B35F47E1DEB8A8AB4B9CB67B70179CC26F553AE7B569969CE151B8D:\
+4EA1D6958DA1A7AA6DDE7A1973F2296697B98326DF10D26BF83026C3EFB3829C
+
+C71BD7941F41DF044A2927A8FF55B4B467C33D089F0988AA253D294ADDBDB325\
+30C0D4208B10D9959823F0C0F0734684006DF79F7099870F6BF53211A88D:\
+8AE7D93A38166DBED49B6144D58664C0A188ADBD9AE18409479579E82B556E7A
+
+F57C64006D9EA761892E145C99DF1B24640883DA79D9ED5262859DCDA8C3C32E\
+05B03D984F1AB4A230242AB6B78D368DC5AAA1E6D3498D53371E84B0C1D4BA:\
+27551CE7545CD33AF7D6B80908E65C76DCDFCC2220D47C2DEF878E93281D184B
+
+E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\
+E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\
+511C87F11C0FC63BCD6BDC79110E2A3DC9E9E8E274ECAA92021F3734F059D5B2
+
+16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652B\
+DF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC\
+00:\
+C7F53C3BE9A3ADF6FCF6B1148D900175C3AE29701558A17800B0995536C1579D
+
+FC424EEB27C18A11C01F39C555D8B78A805B88DBA1DC2A42ED5E2C0EC737FF68\
+B2456D80EB85E11714FA3F8EABFB906D3C17964CB4F5E76B29C1765DB03D91BE\
+37FC:\
+E05CFFD265344EAB2A47E42D4A0380B1C7C8D41DFA87CF6F2CC69F378DD11960
+
+ABE3472B54E72734BDBA7D9158736464251C4F21B33FBBC92D7FAC9A35C4E332\
+2FF01D2380CBAA4EF8FB07D21A2128B7B9F5B6D9F34E13F39C7FFC2E72E47888\
+599BA5:\
+0AB68A3A20A5539B3D93BA80BDAC33473ED509CD015F9E1F97596641C7543BE2
+
+36F9F0A65F2CA498D739B944D6EFF3DA5EBBA57E7D9C41598A2B0E4380F3CF4B\
+479EC2348D015FFE6256273511154AFCF3B4B4BF09D6C4744FDD0F62D75079D4\
+40706B05:\
+D32A031715109945CCA49ED388F685509299968D56F9A74BD283EABFB93A640C
+
+ABC87763CAE1CA98BD8C5B82CABA54AC83286F87E9610128AE4DE68AC95DF5E3\
+29C360717BD349F26B872528492CA7C94C2C1E1EF56B74DBB65C2AC351981FDB\
+31D06C77A4:\
+7DD01BEE13227DA797EAA4D954BEF62953B88596C83177D0F7FA99C0B0000C36
+
+94F7CA8E1A54234C6D53CC734BB3D3150C8BA8C5F880EAB8D25FED13793A9701\
+EBE320509286FD8E422E931D99C98DA4DF7E70AE447BAB8CFFD92382D8A77760\
+A259FC4FBD72:\
+61ACECF69E5B1A9C2C2E18B0C1F030FCDF0092929D2D35CAD3B531C288214792
+
+13BD2811F6ED2B6F04FF3895ACEED7BEF8DCD45EB121791BC194A0F806206BFF\
+C3B9281C2B308B1A729CE008119DD3066E9378ACDCC50A98A82E20738800B6CD\
+DBE5FE9694AD6D:\
+CB7007F2B749D27412428779B903D02FABB36C36BC7CBE4F15849BE17212C363
+
+1EED9CBA179A009EC2EC5508773DD305477CA117E6D569E66B5F64C6BC64801C\
+E25A8424CE4A26D575B8A6FB10EAD3FD1992EDDDEEC2EBE7150DC98F63ADC323\
+7EF57B91397AA8A7:\
+A74E554018C7FD1CB9FD5071760076EC60CB1129179E1359163D00E6BF77DB18
+
+BA5B67B5EC3A3FFAE2C19DD8176A2EF75C0CD903725D45C9CB7009A900C0B0CA\
+7A2967A95AE68269A6DBF8466C7B6844A1D608AC661F7EFF00538E323DB5F2C6\
+44B78B2D48DE1A08AA:\
+6F94293899915204CC387F419C3ADA24BBB210151983AA2182AC0AACF3A3A5A8
+
+0EFA26AC5673167DCACAB860932ED612F65FF49B80FA9AE65465E5542CB62075\
+DF1C5AE54FBA4DB807BE25B070033EFA223BDD5B1D3C94C6E1909C02B620D4B1\
+B3A6C9FED24D70749604:\
+C6FA8A35628FC4FEB4C791929D151B083DAE074D6A56B8774B439EFD670646F5
+
+BBFD933D1FD7BF594AC7F435277DC17D8D5A5B8E4D13D96D2F64E771ABBD51A5\
+A8AEA741BECCBDDB177BCEA05243EBD003CFDEAE877CCA4DA94605B67691919D\
+8B033F77D384CA01593C1B:\
+143EA9E408A52C8B61F156A4CA40CBA6B3957D8406A3EC6E11CD47AF7937F9A2
+
+90078999FD3C35B8AFBF4066CBDE335891365F0FC75C1286CDD88FA51FAB94F9\
+B8DEF7C9AC582A5DBCD95817AFB7D1B48F63704E19C2BAA4DF347F48D4A6D603\
+013C23F1E9611D595EBAC37C:\
+C95B94E144B3A01562AFE7DE278BB9E563F91309BEC413E2AD1688DFE9B63A54
+
+64105ECA863515C20E7CFBAA0A0B8809046164F374D691CDBD6508AAABC1819F\
+9AC84B52BAFC1B0FE7CDDBC554B608C01C8904C669D8DB316A0953A4C68ECE32\
+4EC5A49FFDB59A1BD6A292AA0E:\
+1273AE0047382469F025CB8DDF56B627AF5701000113907C36C888346182D5E2
+
+D4654BE288B9F3B711C2D02015978A8CC57471D5680A092AA534F7372C71CEAA\
+B725A383C4FCF4D8DEAA57FCA3CE056F312961ECCF9B86F14981BA5BED6AB5B4\
+498E1F6C82C6CAE6FC14845B3C8A:\
+EACCB48C714CB1A01FEECCE044B643289AC76BFA33109B9FC610110BEB171903
+
+12D9394888305AC96E65F2BF0E1B18C29C90FE9D714DD59F651F52B88B3008C5\
+88435548066EA2FC4C101118C91F32556224A540DE6EFDDBCA296EF1FB00341F\
+5B01FECFC146BDB251B3BDAD556CD2:\
+4494D1708CF9CB3F9481E0DDCE684E70007731F42352969EF22AE2E9455DAE93
+
+871A0D7A5F36C3DA1DFCE57ACD8AB8487C274FAD336BC137EBD6FF4658B547C1\
+DCFAB65F037AA58F35EF16AFF4ABE77BA61F65826F7BE681B5B6D5A1EA8085E2\
+AE9CD5CF0991878A311B549A6D6AF230:\
+74B01863854AE0C659805A9DBEB0C0DD35393F251F379384AF58ACFEC09E95DD
+
+E90B4FFEF4D457BC7711FF4AA72231CA25AF6B2E206F8BF859D8758B89A7CD36\
+105DB2538D06DA83BAD5F663BA11A5F6F61F236FD5F8D53C5E89F183A3CEC615\
+B50C7C681E773D109FF7491B5CC22296C5:\
+BC2794E929371BB9A8559CAD010B68F5DF2D3622129928ACFB27CAC307ACD339
+
+E728DE62D75856500C4C77A428612CD804F30C3F10D36FB219C5CA0AA30726AB\
+190E5F3F279E0733D77E7267C17BE27D21650A9A4D1E32F649627638DBADA970\
+2C7CA303269ED14014B2F3CF8B894EAC8554:\
+A628B977C2D1A95BE0F4D08D7EE8CD788F0D5BEAE3E32085292328272A7ACB7D
+
+6348F229E7B1DF3B770C77544E5166E081850FA1C6C88169DB74C76E42EB983F\
+ACB276AD6A0D1FA7B50D3E3B6FCD799EC97470920A7ABED47D288FF883E24CA2\
+1C7F8016B93BB9B9E078BDB9703D2B781B616E:\
+94B6A16A64E79AA8A0465902C245F71618D3D552358E3DA304808686D0557AB8
+
+4B127FDE5DE733A1680C2790363627E63AC8A3F1B4707D982CAEA258655D9BF1\
+8F89AFE54127482BA01E08845594B671306A025C9A5C5B6F93B0A39522DC8774\
+37BE5C2436CBF300CE7AB6747934FCFC30AEAAF6:\
+8A003E1C23979216574C13FB6AD09984F7B931BA8B0F4BAEDD58A73F2598E822
+
+08461F006CFF4CC64B752C957287E5A0FAABC05C9BFF89D23FD902D324C79903\
+B48FCB8F8F4B01F3E4DDB483593D25F000386698F5ADE7FAADE9615FDC50D327\
+85EA51D49894E45BAA3DC707E224688C6408B68B11:\
+BCE45B4D7735D0807E818E0025646391E147C30E3F53934439F12FF71C98777A
+
+68C8F8849B120E6E0C9969A5866AF591A829B92F33CD9A4A3196957A148C4913\
+8E1E2F5C7619A6D5EDEBE995ACD81EC8BB9C7B9CFCA678D081EA9E25A75D39DB\
+04E18D475920CE828B94E72241F24DB72546B352A0E4:\
+ED0B018161DD4209702F8AC7709FB36367D3F368D262F25AB9862AC67CF27A80
+
+B8D56472954E31FB54E28FCA743F84D8DC34891CB564C64B08F7B71636DEBD64\
+CA1EDBDBA7FC5C3E40049CE982BBA8C7E0703034E331384695E9DE76B5104F2F\
+BC4535ECBEEBC33BC27F29F18F6F27E8023B0FBB6F563C:\
+205F82F248A0BED634985E5B7B90CBE09CF4453A490C01596F3510739F077ADD
+
+0D58AC665FA84342E60CEFEE31B1A4EACDB092F122DFC68309077AED1F3E528F\
+578859EE9E4CEFB4A728E946324927B675CD4F4AC84F64DB3DACFE850C1DD187\
+44C74CECCD9FE4DC214085108F404EAB6D8F452B5442A47D:\
+B20CF7C5DF1E854E092AEC3696D17302EDBACEE9D98F9F37663465B0C4F669F2
+
+1755E2D2E5D1C1B0156456B539753FF416651D44698E87002DCF61DCFA2B4E72\
+F264D9AD591DF1FDEE7B41B2EB00283C5AEBB3411323B672EAA145C512518510\
+4F20F335804B02325B6DEA65603F349F4D5D8B782DD3469CCD:\
+6B37499CF7E5C8DAE33148F8E2A19D4A8ADA17D49761F0A81F6698DE11F413C5
+
+B180DE1A611111EE7584BA2C4B020598CD574AC77E404E853D15A101C6F5A2E5\
+C801D7D85DC95286A1804C870BB9F00FD4DCB03AA8328275158819DCAD7253F3\
+E3D237AEAA7979268A5DB1C6CE08A9EC7C2579783C8AFC1F91A7:\
+40EED4722ED52B5A839A4818AE20A643792EABCB7C0595F6F11590411F4702E5
+
+CF3583CBDFD4CBC17063B1E7D90B02F0E6E2EE05F99D77E24E560392535E47E0\
+5077157F96813544A17046914F9EFB64762A23CF7A49FE52A0A4C01C630CFE87\
+27B81FB99A89FF7CC11DCA5173057E0417B8FE7A9EFBA6D95C555F:\
+6E57E65EE1C4356C7BD4E33C61E0494BCDA0039178DCAAF08337C21E35E0A9D4
+
+072FC02340EF99115BAD72F92C01E4C093B9599F6CFC45CB380EE686CB5EB019\
+E806AB9BD55E634AB10AA62A9510CC0672CD3EDDB589C7DF2B67FCD3329F61B1\
+A4441ECA87A33C8F55DA4FBBAD5CF2B2527B8E983BB31A2FADEC7523:\
+4CD15803384770305889D50B73E6FA8E0C713F07EEB43C28D5F07CAA0470A6CF
+
+76EECF956A52649F877528146DE33DF249CD800E21830F65E90F0F25CA9D6540\
+FDE40603230ECA6760F1139C7F268DEBA2060631EEA92B1FFF05F93FD5572FBE\
+29579ECD48BC3A8D6C2EB4A6B26E38D6C5FBF2C08044AEEA470A8F2F26:\
+D139EE1C13D44DBBDCF8431E5595061ECC781F861081ED0E9A22066BC91FA311
+
+7ADC0B6693E61C269F278E6944A5A2D8300981E40022F839AC644387BFAC9086\
+650085C2CDC585FEA47B9D2E52D65A2B29A7DC370401EF5D60DD0D21F9E2B90F\
+AE919319B14B8C5565B0423CEFB827D5F1203302A9D01523498A4DB10374:\
+8B993DC3236D3078C2F4B917435CB2DD73BAD44AF196FA1CBA53A0C4343E804E
+
+E1FFFA9826CCE8B86BCCEFB8794E48C46CDF372013F782ECED1E378269B7BE2B\
+7BF51374092261AE120E822BE685F2E7A83664BCFBE38FE8633F24E633FFE198\
+8E1BC5ACF59A587079A57A910BDA60060E85B5F5B6F776F0529639D9CCE4BD:\
+F1B43FAC50156FECF5D859EDF896A9AA011E827E42790A458538EAAB47ED7BA0
+
+69F9ABBA65592EE01DB4DCE52DBAB90B08FC04193602792EE4DAA263033D5908\
+1587B09BBE49D0B49C9825D22840B2FF5D9C5155F975F8F2C2E7A90C75D2E4A8\
+040FE39F63BBAFB403D9E28CC3B86E04E394A9C9E8065BD3C85FA9F0C7891600:\
+18013D6955E1364A8847F431351546B61F2B4F24C384A9ED60A7817432A2C20E
+
+38A10A352CA5AEDFA8E19C64787D8E9C3A75DBF3B8674BFAB29B5DBFC15A63D1\
+0FAE66CD1A6E6D2452D557967EAAD89A4C98449787B0B3164CA5B717A93F24EB\
+0B506CEB70CBBCB8D72B2A72993F909AAD92F044E0B5A2C9AC9CB16A0CA2F81F\
+49:\
+D2916C3A168C2D9D79C3F91FFBDA71B2092FB62D5BE7AC23235B6245BCBABE0E
+
+6D8C6E449BC13634F115749C248C17CD148B72157A2C37BF8969EA83B4D6BA8C\
+0EE2711C28EE11495F43049596520CE436004B026B6C1F7292B9C436B055CBB7\
+2D530D860D1276A1502A5140E3C3F54A93663E4D20EDEC32D284E25564F62495\
+5B52:\
+5FC0CFC99C9C57812FAD19416A6F7C3E81FC1A854FBC2E60A723B803B35862E5
+
+6EFCBCAF451C129DBE00B9CEF0C3749D3EE9D41C7BD500ADE40CDC65DEDBBBAD\
+B885A5B14B32A0C0D087825201E303288A733842FA7E599C0C514E078F05C821\
+C7A4498B01C40032E9F1872A1C925FA17CE253E8935E4C3C71282242CB716B20\
+89CCC1:\
+EC7120A58FDD192138B64D8DDE1C9BA3904E18AEE30580A61EC82567BB117435
+
+433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B982\
+14B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784444F\
+22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53E7E084\
+6DCBB4CE:\
+AD1F3CAE6974D135666842BAC782589BCC775A52D9D38E1F8E986DF9380E0AE8
+
+A873E0C67CA639026B6683008F7AA6324D4979550E9BCE064CA1E1FB97A30B14\
+7A24F3F666C0A72D71348EDE701CF2D17E2253C34D1EC3B647DBCEF2F879F4EB\
+881C4830B791378C901EB725EA5C172316C6D606E0AF7DF4DF7F76E490CD30B2\
+BADF45685F:\
+EE5E4A142053D19B10DE3DC20E44695AE745751B941E3D15EE8C6123E89D7D85
+
+006917B64F9DCDF1D2D87C8A6173B64F6587168E80FAA80F82D84F60301E561E\
+312D9FBCE62F39A6FB476E01E925F26BCC91DE621449BE6504C504830AAE3940\
+96C8FC7694651051365D4EE9070101EC9B68086F2EA8F8AB7B811EA8AD934D5C\
+9B62C60A4771:\
+C64F497DBADD60A772053B5E95660E8CDF349BDEB9AAB57A8EC18D2D4E56A2B3
+
+F13C972C52CB3CC4A4DF28C97F2DF11CE089B815466BE88863243EB318C2ADB1\
+A417CB1041308598541720197B9B1CB5BA2318BD5574D1DF2174AF14884149BA\
+9B2F446D609DF240CE335599957B8EC80876D9A085AE084907BC5961B20BF5F6\
+CA58D5DAB38ADB:\
+CF9599A2A65BF618E5B89A14C1A740B0BF716FDD04F7E2738FFC58BFD1A3F15F
+
+E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486\
+F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D\
+B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A\
+21691E1069413848:\
+9103BB40BD80708918784FA2B5B24D0F5E45C78367D313823798455D88A3DDAC
+
+64EC021C9585E01FFE6D31BB50D44C79B6993D72678163DB474947A053674619\
+D158016ADB243F5C8D50AA92F50AB36E579FF2DABB780A2B529370DAA299207C\
+FBCDD3A9A25006D19C4F1FE33E4B1EAEC315D8C6EE1E730623FD1941875B924E\
+B57D6D0C2EDC4E78D6:\
+15A8C8709617C4995D19DC7CF349E29E6E1183E7EE3543D7759B3442B46DAE43
+
+5954BAB512CF327D66B5D9F296180080402624AD7628506B555EEA8382562324\
+CF452FBA4A2130DE3E165D11831A270D9CB97CE8C2D32A96F50D71600BB4CA26\
+8CF98E90D6496B0A6619A5A8C63DB6D8A0634DFC6C7EC8EA9C006B6C456F1B20\
+CD19E781AF20454AC880:\
+89EFA7391173D1DFC34DA1E5261F08E6DCFF33D6B6B63A9F30CCBFC66E89171D
+
+03D9F92B2C565709A568724A0AFF90F8F347F43B02338F94A03ED32E6F33666F\
+F5802DA4C81BDCE0D0E86C04AFD4EDC2FC8B4141C2975B6F07639B1994C973D9\
+A9AFCE3D9D365862003498513BFA166D2629E314D97441667B007414E739D7FE\
+BF0FE3C32C17AA188A8683:\
+5DE806282012D68B1AD059E0049317DDD521F9B0297A72EF04DCEA3B9DB1A54C
+
+F31E8B4F9E0621D531D22A380BE5D9ABD56FAEC53CBD39B1FAB230EA67184440\
+E5B1D15457BD25F56204FA917FA48E669016CB48C1FFC1E1E45274B3B47379E0\
+0A43843CF8601A5551411EC12503E5AAC43D8676A1B2297EC7A0800DBFEE0429\
+2E937F21C005F17411473041:\
+CDF48A0C99695521F9A6C47E868E95300AEDBE25E22CBDC0966849843CE4AC86
+
+758EA3FEA738973DB0B8BE7E599BBEF4519373D6E6DCD7195EA885FC991D8967\
+62992759C2A09002912FB08E0CB5B76F49162AEB8CF87B172CF3AD190253DF61\
+2F77B1F0C532E3B5FC99C2D31F8F65011695A087A35EE4EEE5E334C369D8EE5D\
+29F695815D866DA99DF3F79403:\
+1B359EC23B574C684D0511DD875B52E771D23472AB7542147E525E5596639C68
+
+47C6E0C2B74948465921868804F0F7BD50DD323583DC784F998A93CD1CA4C6EF\
+84D41DC81C2C40F34B5BEE6A93867B3BDBA0052C5F59E6F3657918C382E771D3\
+3109122CC8BB0E1E53C4E3D13B43CE44970F5E0C079D2AD7D7A3549CD75760C2\
+1BB15B447589E86E8D76B1E9CED2:\
+1C621F37EF11339275EFC9AB1109D29B3141791D870DE33684BCCA055E2AB99B
+
+F690A132AB46B28EDFA6479283D6444E371C6459108AFD9C35DBD235E0B6B6FF\
+4C4EA58E7554BD002460433B2164CA51E868F7947D7D7A0D792E4ABF0BE5F450\
+853CC40D85485B2B8857EA31B5EA6E4CCFA2F3A7EF3380066D7D8979FDAC618A\
+AD3D7E886DEA4F005AE4AD05E5065F:\
+010BF6553870870E6D3AF084A2E6EF3E5775827B78DEF9FC4160B49E3DE7D789
+
+58D6A99BC6458824B256916770A8417040721CCCFD4B79EACD8B65A3767CE5BA\
+7E74104C985AC56B8CC9AEBD16FEBD4CDA5ADB130B0FF2329CC8D611EB14DAC2\
+68A2F9E633C99DE33997FEA41C52A7C5E1317D5B5DAED35EBA7D5A60E45D1FA7\
+EAABC35F5C2B0A0F2379231953322C4E:\
+F87862441FDBE4FA75EE1EE8A6444B6EFB75A49EA0A16DB7F40E17287699CC83
+
+BEFAB574396D7F8B6705E2D5B58B2C1C820BB24E3F4BAE3E8FBCD36DBF734EE1\
+4E5D6AB972AEDD3540235466E825850EE4C512EA9795ABFD33F330D9FD7F79E6\
+2BBB63A6EA85DE15BEAEEA6F8D204A28956059E2632D11861DFB0E65BC07AC8A\
+159388D5C3277E227286F65FF5E5B5AEC1:\
+F69B7CBA54F6E77FCBFBFC6B1F8380F2EF4ADE3926F1BC31895006DB749D8213
+
+8E58144FA9179D686478622CE450C748260C95D1BA43B8F9B59ABECA8D93488D\
+A73463EF40198B4D16FB0B0707201347E0506FF19D01BEA0F42B8AF9E71A1F1B\
+D168781069D4D338FDEF00BF419FBB003031DF671F4A37979564F69282DE9C65\
+407847DD0DA505AB1641C02DEA4F0D834986:\
+535C6FD93EB60D3568BAB26B5E051645255C685055BE055BC3C28418EBBB4273
+
+B55C10EAE0EC684C16D13463F29291BF26C82E2FA0422A99C71DB4AF14DD9C7F\
+33EDA52FD73D017CC0F2DBE734D831F0D820D06D5F89DACC485739144F8CFD47\
+99223B1AFF9031A105CB6A029BA71E6E5867D85A554991C38DF3C9EF8C1E1E9A\
+7630BE61CAABCA69280C399C1FB7A12D12AEFC:\
+8A2E48C852367E48C791F4D4AC2413827EC428BE0BD7729D014F4EF790C0C3ED
+
+2EEEA693F585F4ED6F6F8865BBAE47A6908AECD7C429E4BEC4F0DE1D0CA0183F\
+A201A0CB14A529B7D7AC0E6FF6607A3243EE9FB11BCF3E2304FE75FFCDDD6C5C\
+2E2A4CD45F63C962D010645058D36571404A6D2B4F44755434D76998E83409C3\
+205AA1615DB44057DB991231D2CB42624574F545:\
+9E5A063FF56228999FF3B254BBF4FACDC4D99620838C321542A9EB3471D35A62
+
+DAB11DC0B047DB0420A585F56C42D93175562852428499F66A0DB811FCDDDAB2\
+F7CDFFED1543E5FB72110B64686BC7B6887A538AD44C050F1E42631BC4EC8A9F\
+2A047163D822A38989EE4AAB01B4C1F161B062D873B1CFA388FD301514F62224\
+157B9BEF423C7783B7AAC8D30D65CD1BBA8D689C2D:\
+03E26068B45B974F4164CEE5C4B9F4F603B4161FDCEC240E08D1771379D7187B
+
+42E99A2F80AEE0E001279A2434F731E01D34A44B1A8101726921C0590C30F312\
+0EB83059F325E894A5AC959DCA71CE2214799916424E859D27D789437B9D2724\
+0BF8C35ADBAFCECC322B48AA205B293962D858652ABACBD588BCF6CBC388D099\
+3BD622F96ED54614C25B6A9AA527589EAAFFCF17DDF7:\
+7608A56E7911B370F079D5F31FECF145A2CF5BAF9E5B043BA654B071846A7ED1
+
+3C9B46450C0F2CAE8E3823F8BDB4277F31B744CE2EB17054BDDC6DFF36AF7F49\
+FB8A2320CC3BDF8E0A2EA29AD3A55DE1165D219ADEDDB5175253E2D1489E9B6F\
+DD02E2C3D3A4B54D60E3A47334C37913C5695378A669E9B72DEC32AF5434F93F\
+46176EBF044C4784467C700470D0C0B40C8A088C815816:\
+66485D9843D6D2B6E1AAAE7B5A1D23666868F8913911E3BA6D51CFCDEDBACA3B
+
+D1E654B77CB155F5C77971A64DF9E5D34C26A3CAD6C7F6B300D39DEB19100946\
+91ADAA095BE4BA5D86690A976428635D5526F3E946F7DC3BD4DBC78999E65344\
+1187A81F9ADCD5A3C5F254BC8256B0158F54673DCC1232F6E918EBFC6C51CE67\
+EAEB042D9F57EEC4BFE910E169AF78B3DE48D137DF4F2840:\
+738940EBCC4D58E1F3B00342BAB5B105AFD5DF42B5C6C82DA77784822CFBF53F
+
+626F68C18A69A6590159A9C46BE03D5965698F2DAC3DE779B878B3D9C421E0F2\
+1B955A16C715C1EC1E22CE3EB645B8B4F263F60660EA3028981EEBD6C8C3A367\
+285B691C8EE56944A7CD1217997E1D9C21620B536BDBD5DE8925FF71DEC6FBC0\
+6624AB6B21E329813DE90D1E572DFB89A18120C3F606355D25:\
+9AAC97A6E044E8069A60EF9C892E43C39BC053920E43231C064587F3408B138E
+
+651A6FB3C4B80C7C68C6011675E6094EB56ABF5FC3057324EBC6477825061F9F\
+27E7A94633ABD1FA598A746E4A577CAF524C52EC1788471F92B8C37F23795CA1\
+9D559D446CAB16CBCDCE90B79FA1026CEE77BF4AB1B503C5B94C2256AD75B3EA\
+C6FD5DCB96ACA4B03A834BFB4E9AF988CECBF2AE597CB9097940:\
+30DC38C1C43E8E7115681B122857CCB6B8937DA6A1F818B3621ABAFD0EF70100
+
+8AAF072FCE8A2D96BC10B3C91C809EE93072FB205CA7F10ABD82ECD82CF040B1\
+BC49EA13D1857815C0E99781DE3ADBB5443CE1C897E55188CEAF221AA9681638\
+DE05AE1B322938F46BCE51543B57ECDB4C266272259D1798DE13BE90E10EFEC2\
+D07484D9B21A3870E2AA9E06C21AA2D0C9CF420080A80A91DEE16F:\
+A9AAC496D31FA2E4C9E64E10183E9CCB73C331F0414D3FF6709E1FD16EECA32E
+
+53F918FD00B1701BD504F8CDEA803ACCA21AC18C564AB90C2A17DA592C7D6968\
+8F6580575395551E8CD33E0FEF08CA6ED4588D4D140B3E44C032355DF1C53156\
+4D7F4835753344345A6781E11CD5E095B73DF5F82C8AE3AD00877936896671E9\
+47CC52E2B29DCD463D90A0C9929128DA222B5A211450BBC0E02448E2:\
+9EA9F15C82857BFF45A9C23FCDD4173F719415DCF81A80312CFAF4DB2A66DE4F
+
+A64599B8A61B5CCEC9E67AED69447459C8DA3D1EC6C7C7C82A7428B9B584FA67\
+E90F68E2C00FBBED4613666E5168DA4A16F395F7A3C3832B3B134BFC9CBAA95D\
+2A0FE252F44AC6681EB6D40AB91C1D0282FED6701C57463D3C5F2BB8C6A7301F\
+B4576AA3B5F15510DB8956FF77478C26A7C09BEA7B398CFC83503F538E:\
+EA93962E7E6A1A9C6B02B35C581112958B36274F3C3C573F48B292C7C89DE5E0
+
+0E3AB0E054739B00CDB6A87BD12CAE024B54CB5E550E6C425360C2E87E59401F\
+5EC24EF0314855F0F56C47695D56A7FB1417693AF2A1ED5291F2FEE95F75EED5\
+4A1B1C2E81226FBFF6F63ADE584911C71967A8EB70933BC3F5D15BC91B5C2644\
+D9516D3C3A8C154EE48E118BD1442C043C7A0DBA5AC5B1D5360AAE5B9065:\
+DDACCEB467A0D6373D99E4B8ED84AB60FBEEA00958136497BECBE206F2EF80F5
+
+A62FC595B4096E6336E53FCDFC8D1CC175D71DAC9D750A6133D23199EAAC2882\
+07944CEA6B16D27631915B4619F743DA2E30A0C00BBDB1BBB35AB852EF3B9AEC\
+6B0A8DCC6E9E1ABAA3AD62AC0A6C5DE765DE2C3711B769E3FDE44A74016FFF82\
+AC46FA8F1797D3B2A726B696E3DEA5530439ACEE3A45C2A51BC32DD055650B:\
+121E3D0FE6AC51609FA92D5533F03DCEA2449DD7DD8151D1CC23A9533471F421
+
+2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\
+29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\
+E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\
+98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\
+EF98FDE255F2522CA53A7165ABADEFB0CA15C1CF46787627B3C73DE98B7068A9
+
+10DB509B2CDCABA6C062AE33BE48116A29EB18E390E1BBADA5CA0A2718AFBCD2\
+3431440106594893043CC7F2625281BF7DE2655880966A23705F0C5155C2F5CC\
+A9F2C2142E96D0A2E763B70686CD421B5DB812DACED0C6D65035FDE558E94F26\
+B3E6DDE5BD13980CC80292B723013BD033284584BFF27657871B0CF07A849F4A\
+E2:\
+1DDC1375806D28D594FCC4E89EB7FC882B83E4421E98BD7F0A3BFFC03F55402C
+
+9334DE60C997BDA6086101A6314F64E4458F5FF9450C509DF006E8C547983C65\
+1CA97879175AABA0C539E82D05C1E02C480975CBB30118121061B1EBAC4F8D9A\
+3781E2DB6B18042E01ECF9017A64A0E57447EC7FCBE6A7F82585F7403EE2223D\
+52D37B4BF426428613D6B4257980972A0ACAB508A7620C1CB28EB4E9D30FC413\
+61EC:\
+F69C19A5CE68C4B8713300DC064A9EF2974B6B25F167892921FEEF057523AED2
+
+E88AB086891693AA535CEB20E64C7AB97C7DD3548F3786339897A5F0C3903154\
+9CA870166E477743CCFBE016B4428D89738E426F5FFE81626137F17AECFF61B7\
+2DBEE2DC20961880CFE281DFAB5EE38B1921881450E16032DE5E4D55AD8D4FCA\
+609721B0692BAC79BE5A06E177FE8C80C0C83519FB3347DE9F43D5561CB8107B\
+9B5EDC:\
+3EC08D73A250AA726C7D2DAFCFD943D28EDE8E7DBD8AE82D653CE98B837D43B2
+
+FD19E01A83EB6EC810B94582CB8FBFA2FCB992B53684FB748D2264F020D3B960\
+CB1D6B8C348C2B54A9FCEA72330C2AAA9A24ECDB00C436ABC702361A82BB8828\
+B85369B8C72ECE0082FE06557163899C2A0EFA466C33C04343A839417057399A\
+63A3929BE1EE4805D6CE3E5D0D0967FE9004696A5663F4CAC9179006A2CEB755\
+42D75D68:\
+4B4FB44BA4355B4A8B9B7EF07407919F0791E39F4A13D62D015CD3361AEE586C
+
+59AE20B6F7E0B3C7A989AFB28324A40FCA25D8651CF1F46AE383EF6D8441587A\
+A1C04C3E3BF88E8131CE6145CFB8973D961E8432B202FA5AF3E09D625FAAD825\
+BC19DA9B5C6C20D02ABDA2FCC58B5BD3FE507BF201263F30543819510C12BC23\
+E2DDB4F711D087A86EDB1B355313363A2DE996B891025E147036087401CCF3CA\
+7815BF3C49:\
+196488E73E0B92CDC9AB00ACEBB980FA89E0E68408C504FD0F7EA293049EEDE3
+
+77EE804B9F3295AB2362798B72B0A1B2D3291DCEB8139896355830F34B3B3285\
+61531F8079B79A6E9980705150866402FDC176C05897E359A6CB1A7AB067383E\
+B497182A7E5AEF7038E4C96D133B2782917417E391535B5E1B51F47D8ED7E4D4\
+025FE98DC87B9C1622614BFF3D1029E68E372DE719803857CA52067CDDAAD958\
+951CB2068CC6:\
+656CAA5587FBBB782CAA71A9F136C38BE5F7B566C86D9BCCC4DF2DBE1DAC2A55
+
+B771D5CEF5D1A41A93D15643D7181D2A2EF0A8E84D91812F20ED21F147BEF732\
+BF3A60EF4067C3734B85BC8CD471780F10DC9E8291B58339A677B960218F71E7\
+93F2797AEA349406512829065D37BB55EA796FA4F56FD8896B49B2CD19B43215\
+AD967C712B24E5032D065232E02C127409D2ED4146B9D75D763D52DB98D949D3\
+B0FED6A8052FBB:\
+FAACDE40E4EF8945E9585FBDD745CE646BB421E73C2BB1D36E1CFF48818127B9
+
+B32D95B0B9AAD2A8816DE6D06D1F86008505BD8C14124F6E9A163B5A2ADE55F8\
+35D0EC3880EF50700D3B25E42CC0AF050CCD1BE5E555B23087E04D7BF9813622\
+780C7313A1954F8740B6EE2D3F71F768DD417F520482BD3A08D4F222B4EE9DBD\
+015447B33507DD50F3AB4247C5DE9A8ABD62A8DECEA01E3B87C8B927F5B08BEB\
+37674C6F8E380C04:\
+C6F6F5CD1EA117D1EFD66143AEF6DD498AAED8D5675EF3A3DA9344CC1C0F78C6
+
+04410E31082A47584B406F051398A6ABE74E4DA59BB6F85E6B49E8A1F7F2CA00\
+DFBA5462C2CD2BFDE8B64FB21D70C083F11318B56A52D03B81CAC5EEC29EB31B\
+D0078B6156786DA3D6D8C33098C5C47BB67AC64DB14165AF65B44544D806DDE5\
+F487D5373C7F9792C299E9686B7E5821E7C8E2458315B996B5677D926DAC57B3\
+F22DA873C601016A0D:\
+C1C68FE2A1C8A299BE50FD321388B66D5331B6A62105069AD48FD8861388B3C0
+
+8B81E9BADDE026F14D95C019977024C9E13DB7A5CD21F9E9FC491D716164BBAC\
+DC7060D882615D411438AEA056C340CDF977788F6E17D118DE55026855F93270\
+472D1FD18B9E7E812BAE107E0DFDE7063301B71F6CFE4E225CAB3B232905A56E\
+994F08EE2891BA922D49C3DAFEB75F7C69750CB67D822C96176C46BD8A29F170\
+1373FB09A1A6E3C7158F:\
+A0CA92610633D90B4AE83290F367318CCED1EF8AC4AA89F8B706366E7C1DC495
+
+FA6EED24DA6666A22208146B19A532C2EC9BA94F09F1DEF1E7FC13C399A48E41\
+ACC2A589D099276296348F396253B57CB0E40291BD282773656B6E0D8BEA1CDA\
+084A3738816A840485FCF3FB307F777FA5FEAC48695C2AF4769720258C77943F\
+B4556C362D9CBA8BF103AEB9034BAA8EA8BFB9C4F8E6742CE0D52C49EA8E974F\
+339612E830E9E7A9C29065:\
+9415005A00BBB5B648E0875C62109C2D2619D4AF352300D32B9283C49BF365B7
+
+9BB4AF1B4F09C071CE3CAFA92E4EB73CE8A6F5D82A85733440368DEE4EB1CBC7\
+B55AC150773B6FE47DBE036C45582ED67E23F4C74585DAB509DF1B8361056454\
+5642B2B1EC463E18048FC23477C6B2AA035594ECD33791AF6AF4CBC2A1166ABA\
+8D628C57E707F0B0E8707CAF91CD44BDB915E0296E0190D56D33D8DDE10B5B60\
+377838973C1D943C22ED335E:\
+96CBB359587B2DE3686157241CCE9C198BDE88412BABEA7E3421FE05156FBEB9
+
+2167F02118CC62043E9091A647CADBED95611A521FE0D64E8518F16C808AB297\
+725598AE296880A773607A798F7C3CFCE80D251EBEC6885015F9ABF7EAABAE46\
+798F82CB5926DE5C23F44A3F9F9534B3C6F405B5364C2F8A8BDC5CA49C749BED\
+8CE4BA48897062AE8424CA6DDE5F55C0E42A95D1E292CA54FB46A84FBC9CD87F\
+2D0C9E7448DE3043AE22FDD229:\
+FC5D94CE94A9DEFBCD5B8739C3EDCD2496D690617EAE7CE67DFE51896CDAFBD6
+
+94B7FA0BC1C44E949B1D7617D31B4720CBE7CA57C6FA4F4094D4761567E389EC\
+C64F6968E4064DF70DF836A47D0C713336B5028B35930D29EB7A7F9A5AF9AD5C\
+F441745BAEC9BB014CEEFF5A41BA5C1CE085FEB980BAB9CF79F2158E03EF7E63\
+E29C38D7816A84D4F71E0F548B7FC316085AE38A060FF9B8DEC36F91AD9EBC0A\
+5B6C338CBB8F6659D342A24368CF:\
+77BC570C7F1001D4F2D7404F9DD50AC370BC7AB2BBC50707BC7154AE7C8C8A16
+
+EA40E83CB18B3A242C1ECC6CCD0B7853A439DAB2C569CFC6DC38A19F5C90ACBF\
+76AEF9EA3742FF3B54EF7D36EB7CE4FF1C9AB3BC119CFF6BE93C03E208783335\
+C0AB8137BE5B10CDC66FF3F89A1BDDC6A1EED74F504CBE7290690BB295A872B9\
+E3FE2CEE9E6C67C41DB8EFD7D863CF10F840FE618E7936DA3DCA5CA6DF933F24\
+F6954BA0801A1294CD8D7E66DFAFEC:\
+1CADDC9DE421B45C733D039F6BB45FC9B2F9A527CF28513C8F3F60FE3413C845
+
+157D5B7E4507F66D9A267476D33831E7BB768D4D04CC3438DA12F9010263EA5F\
+CAFBDE2579DB2F6B58F911D593D5F79FB05FE3596E3FA80FF2F761D1B0E57080\
+055C118C53E53CDB63055261D7C9B2B39BD90ACC32520CBBDBDA2C4FD8856DBC\
+EE173132A2679198DAF83007A9B5C51511AE49766C792A29520388444EBEFE28\
+256FB33D4260439CBA73A9479EE00C63:\
+B66818877735C0FC3E982A4FC004C8231B2F332F24FA0BD4CED033CBF56C0695
+
+836B34B515476F613FE447A4E0C3F3B8F20910AC89A3977055C960D2D5D2B72B\
+D8ACC715A9035321B86703A411DDE0466D58A59769672AA60AD587B8481DE4BB\
+A552A1645779789501EC53D540B904821F32B0BD1855B04E4848F9F8CFE9EBD8\
+911BE95781A759D7AD9724A7102DBE576776B7C632BC39B9B5E19057E226552A\
+5994C1DBB3B5C7871A11F5537011044C53:\
+F4110D27E8E7C4C4C5A3A5AD6C4DB25785AB43FD57BD60CC7643BA5D43130202
+
+CC7784A4912A7AB5AD3620AAB29BA87077CD3CB83636ADC9F3DC94F51EDF521B\
+2161EF108F21A0A298557981C0E53CE6CED45BDF782C1EF200D29BAB81DD6460\
+586964EDAB7CEBDBBEC75FD7925060F7DA2B853B2B089588FA0F8C16EC6498B1\
+4C55DCEE335CB3A91D698E4D393AB8E8EAC0825F8ADEBEEE196DF41205C01167\
+4E53426CAA453F8DE1CBB57932B0B741D4C6:\
+9E588689BC703D11FF99CF6A45F6C03DCD79B030E21ECFF55A76438CDB5456FB
+
+7639B461FFF270B2455AC1D1AFCE782944AEA5E9087EB4A39EB96BB5C3BAAF0E\
+868C8526D3404F9405E79E77BFAC5FFB89BF1957B523E17D341D7323C302EA70\
+83872DD5E8705694ACDDA36D5A1B895AAA16ECA6104C82688532C8BFE1790B5D\
+C9F4EC5FE95BAED37E1D287BE710431F1E5E8EE105BC42ED37D74B1E55984BF1\
+C09FE6A1FA13EF3B96FAEAED6A2A1950A12153:\
+59F1F0F50D57DBDCD98FC3E93D280287E8B4089414C2EDEB9BBF7633DA5ABA23
+
+EB6513FC61B30CFBA58D4D7E80F94D14589090CF1D80B1DF2E68088DC6104959\
+BA0D583D585E9578AB0AEC0CF36C48435EB52ED9AB4BBCE7A5ABE679C97AE2DB\
+E35E8CC1D45B06DDA3CF418665C57CBEE4BBB47FA4CAF78F4EE656FEC237FE4E\
+EBBAFA206E1EF2BD0EE4AE71BD0E9B2F54F91DAADF1FEBFD7032381D636B733D\
+CB3BF76FB14E23AFF1F68ED3DBCF75C9B99C6F26:\
+704C9F0BDBDF7FCE94984DBA0CCDA0742E76A7E1A313241CA71BB675E3E6520F
+
+1594D74BF5DDE444265D4C04DAD9721FF3E34CBF622DAF341FE16B96431F6C4D\
+F1F760D34F296EB97D98D560AD5286FEC4DCE1724F20B54FD7DF51D4BF137ADD\
+656C80546FB1BF516D62EE82BAA992910EF4CC18B70F3F8698276FCFB44E0EC5\
+46C2C39CFD8EE91034FF9303058B4252462F86C823EB15BF481E6B79CC3A0221\
+8595B3658E8B37382BD5048EAED5FD02C37944E73B:\
+32C533DD299AF65FF382A5639842A230EAF2F87E601ACE1430877296EFC3C039
+
+4CFA1278903026F66FEDD41374558BE1B585D03C5C55DAC94361DF286D4BD39C\
+7CB8037ED3B267B07C346626449D0CC5B0DD2CF221F7E4C3449A4BE99985D2D5\
+E67BFF2923357DDEAB5ABCB4619F3A3A57B2CF928A022EB27676C6CF80568900\
+4FCA4D41EA6C2D0A4789C7605F7BB838DD883B3AD3E6027E775BCF2628814280\
+99C7FFF95B14C095EA130E0B9938A5E22FC52650F591:\
+A330F9BEA0E6798447529A215A1910C9F14EFB3B1093AFBCFFB99AF34C85E942
+
+D3E65CB92CFA79662F6AF493D696A07CCF32AAADCCEFF06E73E8D9F6F909209E\
+66715D6E978788C49EFB9087B170ECF3AA86D2D4D1A065AE0EFC8924F365D676\
+B3CB9E2BEC918FD96D0B43DEE83727C9A93BF56CA2B2E59ADBA85696546A8150\
+67FC7A78039629D4948D157E7B0D826D1BF8E81237BAB7321312FDAA4D521744\
+F988DB6FDF04549D0FDCA393D639C729AF716E9C8BBA48:\
+CB146217DF22A6BE48BE40B830316D8CF8B52CB867150729B7D6F447F1CD86B3
+
+842CC583504539622D7F71E7E31863A2B885C56A0BA62DB4C2A3F2FD12E79660\
+DC7205CA29A0DC0A87DB4DC62EE47A41DB36B9DDB3293B9AC4BAAE7DF5C6E720\
+1E17F717AB56E12CAD476BE49608AD2D50309E7D48D2D8DE4FA58AC3CFEAFEEE\
+48C0A9EEC88498E3EFC51F54D300D828DDDCCB9D0B06DD021A29CF5CB5B25069\
+15BEB8A11998B8B886E0F9B7A80E97D91A7D01270F9A7717:\
+E9F33B20CA61B4AF6D351554754C125A8B00BD11FA9E13EB87F4149E028DFAB7
+
+6C4B0A0719573E57248661E98FEBE326571F9A1CA813D3638531AE28B4860F23\
+C3A3A8AC1C250034A660E2D71E16D3ACC4BF9CE215C6F15B1C0FC7E77D3D2715\
+7E66DA9CEEC9258F8F2BF9E02B4AC93793DD6E29E307EDE3695A0DF63CBDC0FC\
+66FB770813EB149CA2A916911BEE4902C47C7802E69E405FE3C04CEB5522792A\
+5503FA829F707272226621F7C488A7698C0D69AA561BE9F378:\
+DD5595C48CD407A0CF3B083B173D41DC8D040C8384281F77EA74098836BB4F6B
+
+51B7DBB7CE2FFEB427A91CCFE5218FD40F9E0B7E24756D4C47CD55606008BDC2\
+7D16400933906FD9F30EFFDD4880022D081155342AF3FB6CD53672AB7FB5B3A3\
+BCBE47BE1FD3A2278CAE8A5FD61C1433F7D350675DD21803746CADCA574130F0\
+1200024C6340AB0CC2CF74F2234669F34E9009EF2EB94823D62B31407F4BA46F\
+1A1EEC41641E84D77727B59E746B8A671BEF936F05BE820759FA:\
+A23D49330B489EE5865CF3EF8A50E3D907AF5A466352486959BF363377D37584
+
+83599D93F5561E821BD01A472386BC2FF4EFBD4AED60D5821E84AAE74D807102\
+9810F5E286F8F17651CD27DA07B1EB4382F754CD1C95268783AD09220F550284\
+0370D494BEB17124220F6AFCE91EC8A0F55231F9652433E5CE3489B727716CF4\
+AEBA7DCDA20CD29AA9A859201253F948DD94395ABA9E3852BD1D60DDA7AE5DC0\
+45B283DA006E1CBAD83CC13292A315DB5553305C628DD091146597:\
+4FABE0509494DC148CB5124EFB102CF46A6E1EBFF1F7B8E0E1CBA26D821202C0
+
+2BE9BF526C9D5A75D565DD11EF63B979D068659C7F026C08BEA4AF161D85A462\
+D80E45040E91F4165C074C43AC661380311A8CBED59CC8E4C4518E80CD2C78AB\
+1CABF66BFF83EAB3A80148550307310950D034A6286C93A1ECE8929E6385C5E3\
+BB6EA8A7C0FB6D6332E320E71CC4EB462A2A62E2BFE08F0CCAD93E61BEDB5DD0\
+B786A728AB666F07E0576D189C92BF9FB20DCA49AC2D3956D47385E2:\
+5AC11CB4A0AA3D2F562C6601774B72731F230D8B2283975E7D4EE397C22C453F
+
+CA76D3A12595A817682617006848675547D3E8F50C2210F9AF906C0E7CE50B44\
+60186FE70457A9E879E79FD4D1A688C70A347361C847BA0DD6AA52936EAF8E58\
+A1BE2F5C1C704E20146D366AEB3853BED9DE9BEFE9569AC8AAEA37A9FB7139A1\
+A1A7D5C748605A8DEFB297869EBEDD71D615A5DA23496D11E11ABBB126B206FA\
+0A7797EE7DE117986012D0362DCEF775C2FE145ADA6BDA1CCB326BF644:\
+0B54924DEC7DDC42E8BF6ED7F498E5875CED195115448D3379E46D72D346C509
+
+F76B85DC67421025D64E93096D1D712B7BAF7FB001716F02D33B2160C2C882C3\
+10EF13A576B1C2D30EF8F78EF8D2F465007109AAD93F74CB9E7D7BEF7C9590E8\
+AF3B267C89C15DB238138C45833C98CC4A471A7802723EF4C744A853CF80A0C2\
+568DD4ED58A2C9644806F42104CEE53628E5BDF7B63B0B338E931E31B87C24B1\
+46C6D040605567CEEF5960DF9E022CB469D4C787F4CBA3C544A1AC91F95F:\
+3C6162A88D4E9DBB17271204B5C7EEAD685FE1FE594FADE341235B2CBC68CEC0
+
+25B8C9C032EA6BCD733FFC8718FBB2A503A4EA8F71DEA1176189F694304F0FF6\
+8E862A8197B839957549EF243A5279FC2646BD4C009B6D1EDEBF24738197ABB4\
+C992F6B1DC9BA891F570879ACCD5A6B18691A93C7D0A8D38F95B639C1DAEB48C\
+4C2F15CCF5B9D508F8333C32DE78781B41850F261B855C4BEBCC125A380C54D5\
+01C5D3BD07E6B52102116088E53D76583B0161E2A58D0778F091206AABD5A1:\
+946FCDEC1F60A84B0D6B2AF0C756B28F9D0DF5BE05A907674CA43BB62D74E950
+
+21CFDC2A7CCB7F331B3D2EEFFF37E48AD9FA9C788C3F3C200E0173D99963E1CB\
+CA93623B264E920394AE48BB4C3A5BB96FFBC8F0E53F30E22956ADABC2765F57\
+FB761E147ECBF8567533DB6E50C8A1F894310A94EDF806DD8CA6A0E141C0FA7C\
+9FAE6C6AE65F18C93A8529E6E5B553BF55F25BE2E80A9882BD37F145FECBEB3D\
+447A3C4E46C21524CC55CDD62F521AB92A8BA72B897996C49BB273198B7B1C9E:\
+B84EA6716092FC94C53E11FA506D35339F24DD09A5E114E9753DEC8B7C7E5604
+
+4E452BA42127DCC956EF4F8F35DD68CB225FB73B5BC7E1EC5A898BBA2931563E\
+74FAFF3B67314F241EC49F4A7061E3BD0213AE826BAB380F1F14FAAB8B0EFDDD\
+5FD1BB49373853A08F30553D5A55CCBBB8153DE4704F29CA2BDEEF0419468E05\
+DD51557CCC80C0A96190BBCC4D77ECFF21C66BDF486459D427F986410F883A80\
+A5BCC32C20F0478BB9A97A126FC5F95451E40F292A4614930D054C851ACD019C\
+CF:\
+BC33DAE57720B9B0C4112E0C301F0BC4155DA8B254DE306CACAD9354CE598F2D
+
+FA85671DF7DADF99A6FFEE97A3AB9991671F5629195049880497487867A6C446\
+B60087FAC9A0F2FCC8E3B24E97E42345B93B5F7D3691829D3F8CCD4BB36411B8\
+5FC2328EB0C51CB3151F70860AD3246CE0623A8DC8B3C49F958F8690F8E3860E\
+71EB2B1479A5CEA0B3F8BEFD87ACAF5362435EAECCB52F38617BC6C5C2C6E269\
+EAD1FBD69E941D4AD2012DA2C5B21BCFBF98E4A77AB2AF1F3FDA3233F046D38F\
+1DC8:\
+3CBFB2D8628C0DFCF709F2406E226DD7551254D7EDC884595021950C003439E6
+
+E90847AE6797FBC0B6B36D6E588C0A743D725788CA50B6D792352EA8294F5BA6\
+54A15366B8E1B288D84F5178240827975A763BC45C7B0430E8A559DF4488505E\
+009C63DA994F1403F407958203CEBB6E37D89C94A5EACF6039A327F6C4DBBC7A\
+2A307D976AA39E41AF6537243FC218DFA6AB4DD817B6A397DF5CA69107A91987\
+99ED248641B63B42CB4C29BFDD7975AC96EDFC274AC562D0474C60347A078CE4\
+C25E88:\
+0FBE3BD588D17869B12B9398EF32071C60470366B3434C3CBEA2DDB66E2AE915
+
+F6D5C2B6C93954FC627602C00C4CA9A7D3ED12B27173F0B2C9B0E4A5939398A6\
+65E67E69D0B12FB7E4CEB253E8083D1CEB724AC07F009F094E42F2D6F2129489\
+E846EAFF0700A8D4453EF453A3EDDC18F408C77A83275617FABC4EA3A2833AA7\
+3406C0E966276079D38E8E38539A70E194CC5513AAA457C699383FD1900B1E72\
+BDFB835D1FD321B37BA80549B078A49EA08152869A918CA57F5B54ED71E4FD3A\
+C5C06729:\
+02338A8F5C73C951EA04098AA488914FEFEDE9FE73ED58B8FE9B3050981BA8D8
+
+CF8562B1BED89892D67DDAAF3DEEB28246456E972326DBCDB5CF3FB289ACA01E\
+68DA5D59896E3A6165358B071B304D6AB3D018944BE5049D5E0E2BB819ACF67A\
+6006111089E6767132D72DD85BEDDCBB2D64496DB0CC92955AB4C6234F1EEA24\
+F2D51483F2E209E4589BF9519FAC51B4D061E801125E605F8093BB6997BC163D\
+551596FE4AB7CFAE8FB9A90F6980480CE0C229FD1675409BD788354DAF316240\
+CFE0AF93EB:\
+B91FE78406406F7729C81AD744E460E3285659039A65427F40520D9D9A6147E8
+
+2ACE31ABB0A2E3267944D2F75E1559985DB7354C6E605F18DC8470423FCA30B7\
+331D9B33C4A4326783D1CAAE1B4F07060EFF978E4746BF0C7E30CD61040BD5EC\
+2746B29863EB7F103EBDA614C4291A805B6A4C8214230564A0557BC7102E0BD3\
+ED23719252F7435D64D210EE2AAFC585BE903FA41E1968C50FD5D5367926DF7A\
+05E3A42CF07E656FF92DE73B036CF8B19898C0CB34557C0C12C2D8B84E91181A\
+F467BC75A9D1:\
+B17D0DB11C55BF13127FA695B3864C394F46BDD9BA777B1ABC73E419083B2696
+
+0D8D09AED19F1013969CE5E7EB92F83A209AE76BE31C754844EA9116CEB39A22\
+EBB6003017BBCF26555FA6624185187DB8F0CB3564B8B1C06BF685D47F3286ED\
+A20B83358F599D2044BBF0583FAB8D78F854FE0A596183230C5EF8E54426750E\
+AF2CC4E29D3BDD037E734D863C2BD9789B4C243096138F7672C232314EFFDFC6\
+513427E2DA76916B5248933BE312EB5DDE4CF70804FB258AC5FB82D58D08177A\
+C6F4756017FFF5:\
+4AC28E88BBCF2FC39280FB67E882E1EF7705CCB24B3F856BC8FAA7A02BE6DD29
+
+C3236B73DEB7662BF3F3DAA58F137B358BA610560EF7455785A9BEFDB035A066\
+E90704F929BD9689CEF0CE3BDA5ACF4480BCEB8D09D10B098AD8500D9B6071DF\
+C3A14AF6C77511D81E3AA8844986C3BEA6F469F9E02194C92868CD5F51646256\
+798FF0424954C1434BDFED9FACB390B07D342E992936E0F88BFD0E884A0DDB67\
+9D0547CCDEC6384285A45429D115AC7D235A717242021D1DC35641F5F0A48E84\
+45DBA58E6CB2C8EA:\
+BC4AE5A53728E73D1EE3D8E9AEDEA6791575B542BDC92C4E9E0617598309478D
+
+B39FEB8283EADC63E8184B51DF5AE3FD41AAC8A963BB0BE1CD08AA5867D8D910\
+C669221E73243360646F6553D1CA05A84E8DC0DE05B6419EC349CA994480193D\
+01C92525F3FB3DCEFB08AFC6D26947BDBBFD85193F53B50609C6140905C53A66\
+86B58E53A319A57B962331EDE98149AF3DE3118A819DA4D76706A0424B4E1D29\
+10B0ED26AF61D150EBCB46595D4266A0BD7F651BA47D0C7F179CA28545007D92\
+E8419D48FDFBD744CE:\
+B203F5364F28DBD5D4411B4619411AACDD3C32D1BF432B9F9802617C1C2B4BE3
+
+A983D54F503803E8C7999F4EDBBE82E9084F422143A932DDDDC47A17B0B7564A\
+7F37A99D0786E99476428D29E29D3C197A72BFAB1342C12A0FC4787FD7017D7A\
+6174049EA43B5779169EF7472BDBBD941DCB82FC73AAC45A8A94C9F2BD3477F6\
+1FD3B796F02A1B8264A214C6FEA74B7051B226C722099EC7883A462B83B6AFDD\
+4009248B8A237F605FE5A08FE7D8B45321421EBBA67BD70A0B00DDBF94BAAB7F\
+359D5D1EEA105F28DCFB:\
+510D0553E4E438B8D994496CC91487412F67A311ADDCC798E4D47D09E4C13BAE
+
+E4D1C1897A0A866CE564635B74222F9696BF2C7F640DD78D7E2ACA66E1B61C64\
+2BB03EA7536AAE597811E9BF4A7B453EDE31F97B46A5F0EF51A071A2B3918DF1\
+6B152519AE3776F9F1EDAB4C2A377C3292E96408359D3613844D5EB393000283\
+D5AD3401A318B12FD1474B8612F2BB50FB6A8B9E023A54D7DDE28C43D6D8854C\
+8D9D1155935C199811DBFC87E9E0072E90EB88681CC7529714F8FB8A2C9D8856\
+7ADFB974EE205A9BF7B848:\
+435139166C6E7EA175C46B26FE1F240204D77EF9AD3985E79CB37A32AD886229
+
+B10C59723E3DCADD6D75DF87D0A1580E73133A9B7D00CB95EC19F5547027323B\
+E75158B11F80B6E142C6A78531886D9047B08E551E75E6261E79785366D7024B\
+D7CD9CF322D9BE7D57FB661069F2481C7BB759CD71B4B36CA2BC2DF6D3A328FA\
+EBDB995A9794A8D72155ED551A1F87C80BF6059B43FC764900B18A1C2441F748\
+7743CF84E565F61F8DD2ECE6B6CCC9444049197AAAF53E926FBEE3BFCA8BE588\
+EC77F29D211BE89DE18B15F6:\
+CFF89A7EB8137D51D182FAB2B119860DC11A4D8F9F6F3B5CE51A63631CC31821
+
+DB11F609BABA7B0CA634926B1DD539C8CBADA24967D7ADD4D9876F77C2D80C0F\
+4DCEFBD7121548373582705CCA2495BD2A43716FE64ED26D059CFB566B3364BD\
+49EE0717BDD9810DD14D8FAD80DBBDC4CAFB37CC60FB0FE2A80FB4541B8CA9D5\
+9DCE457738A9D3D8F641AF8C3FD6DA162DC16FC01AAC527A4A0255B4D231C0BE\
+50F44F0DB0B713AF03D968FE7F0F61ED0824C55C4B5265548FEBD6AAD5C5EEDF\
+63EFE793489C39B8FD29D104CE:\
+B0CAED5E052B52D9CD6F537D68453D6B67C02BB3C2D5277E7243AF289FFC30D7
+
+BEBD4F1A84FC8B15E4452A54BD02D69E304B7F32616AADD90537937106AE4E28\
+DE9D8AAB02D19BC3E2FDE1D651559E296453E4DBA94370A14DBBB2D1D4E20223\
+02EE90E208321EFCD8528AD89E46DC839EA9DF618EA8394A6BFF308E7726BAE0\
+C19BCD4BE52DA6258E2EF4E96AA21244429F49EF5CB486D7FF35CAC1BACB7E95\
+711944BCCB2AB34700D42D1EB38B5D536B947348A458EDE3DC6BD6EC547B1B0C\
+AE5B257BE36A7124E1060C170FFA:\
+021C8CAD21920F53F068C7AE3AFD9ED5941633CFE9574265B1E47B637581BBBB
+
+5ACA56A03A13784BDC3289D9364F79E2A85C12276B49B92DB0ADAA4F206D5028\
+F213F678C3510E111F9DC4C1C1F8B6ACB17A6413AA227607C515C62A733817BA\
+5E762CC6748E7E0D6872C984D723C9BB3B117EB8963185300A80BFA65CDE495D\
+70A46C44858605FCCBED086C2B45CEF963D33294DBE9706B13AF22F1B7C4CD5A\
+001CFEC251FBA18E722C6E1C4B1166918B4F6F48A98B64B3C07FC86A6B17A6D0\
+480AB79D4E6415B520F1C484D675B1:\
+70C70C7F71EF0F7AC0C26F1F3EDB538FB7EC1539B452882FD9F6C24306D54398
+
+A5AAD0E4646A32C85CFCAC73F02FC5300F1982FABB2F2179E28303E447854094\
+CDFC854310E5C0F60993CEFF54D84D6B46323D930ADB07C17599B35B505F09E7\
+84BCA5985E0172257797FB53649E2E9723EFD16865C31B5C3D5113B58BB0BFC8\
+920FABDDA086D7537E66D709D050BD14D0C960873F156FAD5B3D3840CDFCDC9B\
+E6AF519DB262A27F40896AB25CC39F96984D650611C0D5A3080D5B3A1BF186AB\
+D42956588B3B58CD948970D298776060:\
+45788795247613C2EA7016DA14152F103C0F2F2798148BA2CFD9083F128698C7
+
+06CBBE67E94A978203EAD6C057A1A5B098478B4B4CBEF5A97E93C8E42F557271\
+3575FC2A884531D7622F8F879387A859A80F10EF02708CD8F7413AB385AFC357\
+678B9578C0EBF641EF076A1A30F1F75379E9DCB2A885BDD295905EE80C0168A6\
+2A9597D10CF12DD2D8CEE46645C7E5A141F6E0E23AA482ABE5661C16E69EF1E2\
+8371E2E236C359BA4E92C25626A7B7FF13F6EA4AE906E1CFE163E91719B1F750\
+A96CBDE5FBC953D9E576CD216AFC90323A:\
+3A49DD62D76CF4657FDC786479E584669CAD59F9A5B94EBBEB01EB9D020CD529
+
+F1C528CF7739874707D4D8AD5B98F7C77169DE0B57188DF233B2DC8A5B31EDA5\
+DB4291DD9F68E6BAD37B8D7F6C9C0044B3BF74BBC3D7D1798E138709B0D75E7C\
+593D3CCCDC1B20C7174B4E692ADD820ACE262D45CCFAE2077E87879634716806\
+0A162ECCA8C38C1A88350BD63BB539134F700FD4ADDD5959E255337DAA06BC86\
+358FABCBEFDFB5BC889783D843C08AADC6C4F6C36F65F156E851C9A0F917E4A3\
+67B5AD93D874812A1DE6A7B93CD53AD97232:\
+B2BDD3B5EBF32DB12AD4D6FE6C49CBF3BC9125D52DD17978FFA8FEDD4398947C
+
+9D9F3A7ECD51B41F6572FD0D0881E30390DFB780991DAE7DB3B47619134718E6\
+F987810E542619DFAA7B505C76B7350C6432D8BF1CFEBDF1069B90A35F0D04CB\
+DF130B0DFC7875F4A4E62CDB8E525AADD7CE842520A482AC18F09442D78305FE\
+85A74E39E760A4837482ED2F437DD13B2EC1042AFCF9DECDC3E877E50FF4106A\
+D10A525230D11920324A81094DA31DEAB6476AA42F20C84843CFC1C58545EE80\
+352BDD3740DD6A16792AE2D86F11641BB717C2:\
+D6B4D9E7B448B67E15093D3FDDD1D473C742EA5A13BB311A4DE1D79AAC72A57E
+
+5179888724819FBAD3AFA927D3577796660E6A81C52D98E9303261D5A4A83232\
+F6F758934D50AA83FF9E20A5926DFEBAAC49529D006EB923C5AE5048ED544EC4\
+71ED7191EDF46363383824F915769B3E688094C682B02151E5EE01E510B431C8\
+865AFF8B6B6F2F59CB6D129DA79E97C6D2B8FA6C6DA3F603199D2D1BCAB54768\
+2A81CD6CF65F6551121391D78BCC23B5BD0E922EC6D8BF97C952E84DD28AEF90\
+9ABA31EDB903B28FBFC33B7703CD996215A11238:\
+E3B800D89C4DD23DC554D9B78D9B96125DCF6E89A371186D27808B5D797BBF5C
+
+576EF3520D30B7A4899B8C0D5E359E45C5189ADD100E43BE429A02FB3DE5FF4F\
+8FD0E79D9663ACCA72CD29C94582B19292A557C5B1315297D168FBB54E9E2ECD\
+13809C2B5FCE998EDC6570545E1499DBE7FB74D47CD7F35823B212B05BF3F5A7\
+9CAA34224FDD670D335FCB106F5D92C3946F44D3AFCBAE2E41AC554D8E6759F3\
+32B76BE89A0324AA12C5482D1EA3EE89DED4936F3E3C080436F539FA137E74C6\
+D3389BDF5A45074C47BC7B20B0948407A66D855E2F:\
+A8E2A468FE0165C5F8905299D2C155A54E52E24B45886AA23371E0F7F6EFF00E
+
+0DF2152FA4F4357C8741529DD77E783925D3D76E95BAFA2B542A2C33F3D1D117\
+D159CF473F82310356FEE4C90A9E505E70F8F24859656368BA09381FA245EB6C\
+3D763F3093F0C89B972E66B53D59406D9F01AEA07F8B3B615CAC4EE4D05F542E\
+7D0DAB45D67CCCCD3A606CCBEB31EA1FA7005BA07176E60DAB7D78F6810EF086\
+F42F08E595F0EC217372B98970CC6321576D92CE38F7C397A403BADA1548D205\
+C343AC09DECA86325373C3B76D9F32028FEA8EB32515:\
+C3B0543C39039856058A98B18953AED843E9B359D94BDBC000348B319740F448
+
+3E15350D87D6EBB5C8AD99D42515CFE17980933C7A8F6B8BBBF0A63728CEFAAD\
+2052623C0BD5931839112A48633FB3C2004E0749C87A41B26A8B48945539D1FF\
+41A4B269462FD199BFECD45374756F55A9116E92093AC99451AEFB2AF9FD32D6\
+D7F5FBC7F7A540D5097C096EBC3B3A721541DE073A1CC02F7FB0FB1B9327FB0B\
+1218CA49C9487AB5396622A13AE546C97ABDEF6B56380DDA7012A8384091B665\
+6D0AB272D363CEA78163FF765CDD13AB1738B940D16CAE:\
+B630FF7E906FE7AF98DCA85BF1A1CF9817DA235AC13D2970F071C91516A29634
+
+C38D6B0B757CB552BE40940ECE0009EF3B0B59307C1451686F1A22702922800D\
+58BCE7A636C1727EE547C01B214779E898FC0E560F8AE7F61BEF4D75EAA696B9\
+21FD6B735D171535E9EDD267C192B99880C87997711002009095D8A7A437E258\
+104A41A505E5EF71E5613DDD2008195F0C574E6BA3FE40099CFA116E5F1A2FA8\
+A6DA04BADCB4E2D5D0DE31FDC4800891C45781A0AAC7C907B56D631FCA5CE8B2\
+CDE620D11D1777ED9FA603541DE794DDC5758FCD5FAD78C0:\
+F86E73D19616F1B3DAF93E969CBD88B1617669D1D63367DD553AC8C3CC784606
+
+8D2DE3F0B37A6385C90739805B170057F091CD0C7A0BC951540F26A5A75B3E69\
+4631BB64C7635EED316F51318E9D8DE13C70A2ABA04A14836855F35E480528B7\
+76D0A1E8A23B547C8B8D6A0D09B241D3BE9377160CCA4E6793D00A515DC2992C\
+B7FC741DACA171431DA99CCE6F7789F129E2AC5CF65B40D703035CD2185BB936\
+C82002DAF8CBC27A7A9E554B06196630446A6F0A14BA155ED26D95BD627B7205\
+C072D02B60DB0FD7E49EA058C2E0BA202DAFF0DE91E845CF79:\
+667E4CA173E8E2E52D1840664B8C20D0C87B4D67579BCEC686B084FD84C6BD0D
+
+C464BBDAD275C50DCD983B65AD1019B9FF85A1E71C807F3204BB2C921DC31FBC\
+D8C5FC45868AE9EF85B6C9B83BBA2A5A822201ED68586EC5EC27FB2857A5D1A2\
+D09D09115F22DCC39FE61F5E1BA0FF6E8B4ACB4C6DA748BE7F3F0839739394FF\
+7FA8E39F7F7E84A33C3866875C01BCB1263C9405D91908E9E0B50E7459FABB63\
+D8C6BBB73D8E3483C099B55BC30FF092FF68B6ADEDFD477D63570C9F5515847F\
+36E24BA0B705557130CEC57EBAD1D0B31A378E91894EE26E3A04:\
+BE2006B2F5521B05D0B862C93EA896B7E08E55EBB9DAB65C197666EF565FB698
+
+8B8D68BB8A75732FE272815A68A1C9C5AA31B41DEDC8493E76525D1D013D33CE\
+BD9E21A5BB95DB2616976A8C07FCF411F5F6BC6F7E0B57ACA78CC2790A6F9B89\
+8858AC9C79B165FF24E66677531E39F572BE5D81EB3264524181115F32780257\
+BFB9AEEC6AF12AF28E587CAC068A1A2953B59AD680F4C245B2E3EC36F59940D3\
+7E1D3DB38E13EDB29B5C0F404F6FF87F80FC8BE7A225FF22FBB9C8B6B1D7330C\
+57840D24BC75B06B80D30DAD6806544D510AF6C4785E823AC3E0B8:\
+499DF5B0D7521A5F8A25E75956F52E6981589873874647B97C26B6E8FED86D30
+
+6B018710446F368E7421F1BC0CCF562D9C1843846BC8D98D1C9BF7D9D6FCB48B\
+FC3BF83B36D44C4FA93430AF75CD190BDE36A7F92F867F58A803900DF8018150\
+384D85D82132F123006AC2AEBA58E02A037FE6AFBD65ECA7C44977DD3DC74F48\
+B6E7A1BFD5CC4DCF24E4D52E92BD4455848E4928B0EAC8B7476FE3CC03E862AA\
+4DFF4470DBFED6DE48E410F25096487ECFC32A27277F3F5023B2725ADE461B13\
+55889554A8836C9CF53BD767F5737D55184EEA1AB3F53EDD0976C485:\
+A9B83C7A64FDC954C9AFDF05BA59AAA62A00C3AC15AECCC652F32CB093D54E86
+
+C9534A24714BD4BE37C88A3DA1082EDA7CABD154C309D7BD670DCCD95AA53559\
+4463058A29F79031D6ECAA9F675D1211E9359BE82669A79C855EA8D89DD38C2C\
+761DDD0EC0CE9E97597432E9A1BEAE062CDD71EDFDFD464119BE9E69D18A7A7F\
+D7CE0E2106F0C8B0ABF4715E2CA48EF9F454DC203C96656653B727083513F8EF\
+B86E49C513BB758B3B052FE21F1C05BB33C37129D6CC81F1AEF6ADC45B0E8827\
+A830FE545CF57D0955802C117D23CCB55EA28F95C0D8C2F9C5A242B33F:\
+5A876086C025566D3579CF97B0A19204024059DDEC59E12284C191F70A7AECAB
+
+07906C87297B867ABF4576E9F3CC7F82F22B154AFCBF293B9319F1B0584DA6A4\
+0C27B32E0B1B7F412C4F1B82480E70A9235B12EC27090A5A33175A2BB28D8ADC\
+475CEFE33F7803F8CE27967217381F02E67A3B4F84A71F1C5228E0C2AD971373\
+F6F672624FCEA8D1A9F85170FAD30FA0BBD25035C3B41A6175D467998BD1215F\
+6F3866F53847F9CF68EF3E2FBB54BC994DE2302B829C5EEA68EC441FCBAFD7D1\
+6AE4FE9FFF98BF00E5BC2AD54DD91FF9FDA4DD77B6C754A91955D1FBAAD0:\
+FDC7006493C501533937B301734A4FC03062932BE2B85121CFAB77704F328770
+
+588E94B9054ABC2189DF69B8BA34341B77CDD528E7860E5DEFCAA79B0C9A452A\
+D4B82AA306BE84536EB7CEDCBE058D7B84A6AEF826B028B8A0271B69AC3605A9\
+635EA9F5EA0AA700F3EB7835BC54611B922964300C953EFE7491E3677C2CEBE0\
+822E956CD16433B02C68C4A23252C3F9E151A416B4963257B783E038F6B4D5C9\
+F110F871652C7A649A7BCEDCBCCC6F2D0725BB903CC196BA76C76AA9F10A190B\
+1D1168993BAA9FFC96A1655216773458BEC72B0E39C9F2C121378FEAB4E76A:\
+0AEF5D9189B8C1FCBB8879177AD9541148CC3FD096A4B18736AF524BA7F82862
+
+08959A7E4BAAE874928813364071194E2939772F20DB7C3157078987C557C2A6\
+D5ABE68D520EEF3DC491692E1E21BCD880ADEBF63BB4213B50897FA005256ED4\
+1B5690F78F52855C8D9168A4B666FCE2DA2B456D7A7E7C17AB5F2FB1EE90B79E\
+698712E963715983FD07641AE4B4E9DC73203FAC1AE11FA1F8C7941FCC82EAB2\
+47ADDB56E2638447E9D609E610B60CE086656AAEBF1DA3C8A231D7D94E2FD0AF\
+E46B391FF14A72EAEB3F44AD4DF85866DEF43D4781A0B3578BC996C87970B132:\
+2DC25921699467CA5CB104B49EE27FB9F5850005C68D10E459044B6C048C00D4
+
+CB2A234F45E2ECD5863895A451D389A369AAB99CFEF0D5C9FFCA1E6E63F763B5\
+C14FB9B478313C8E8C0EFEB3AC9500CF5FD93791B789E67EAC12FD038E2547CC\
+8E0FC9DB591F33A1E4907C64A922DDA23EC9827310B306098554A4A78F050262\
+DB5B545B159E1FF1DCA6EB734B872343B842C57EAFCFDA8405EEDBB48EF32E99\
+696D135979235C3A05364E371C2D76F1902F1D83146DF9495C0A6C57D7BF9EE7\
+7E80F9787AEE27BE1FE126CDC9EF893A4A7DCBBC367E40FE4E1EE90B42EA25AF\
+01:\
+DE5ADE0B0E304EDA2439C7ABAFD62A8C3EE0F5BCC5B3B5C78EEAAD4BA58A57B8
+
+D16BEADF02AB1D4DC6F88B8C4554C51E866DF830B89C06E786A5F8757E890931\
+0AF51C840EFE8D20B35331F4355D80F73295974653DDD620CDDE4730FB6C8D0D\
+2DCB2B45D92D4FBDB567C0A3E86BD1A8A795AF26FBF29FC6C65941CDDB090FF7\
+CD230AC5268AB4606FCCBA9EDED0A2B5D014EE0C34F0B2881AC036E24E151BE8\
+9EEB6CD9A7A790AFCCFF234D7CB11B99EBF58CD0C589F20BDAC4F9F0E28F75E3\
+E04E5B3DEBCE607A496D848D67FA7B49132C71B878FD5557E082A18ECA1FBDA9\
+4D4B:\
+9066FCB7FCE7505C662B46E921A63B864F300402B6DFAE82789B1A05D63A378C
+
+8F65F6BC59A85705016E2BAE7FE57980DE3127E5AB275F573D334F73F8603106\
+EC3553016608EF2DD6E69B24BE0B7113BF6A760BA6E9CE1C48F9E186012CF96A\
+1D4849D75DF5BB8315387FD78E9E153E76F8BA7EC6C8849810F59FB4BB9B0043\
+18210B37F1299526866F44059E017E22E96CBE418699D014C6EA01C9F0038B10\
+299884DBEC3199BB05ADC94E955A1533219C1115FED0E5F21228B071F40DD57C\
+4240D98D37B73E412FE0FA4703120D7C0C67972ED233E5DEB300A22605472FA3\
+A3BA86:\
+C97FE695E0A6DDC215810AA2DAC517878ADA7D2B186DD9B37482C31F4E532A0F
+
+84891E52E0D451813210C3FD635B39A03A6B7A7317B221A7ABC270DFA946C426\
+69AACBBBDF801E1584F330E28C729847EA14152BD637B3D0F2B38B4BD5BF9C79\
+1C58806281103A3EABBAEDE5E711E539E6A8B2CF297CF351C078B4FA8F7F35CF\
+61BEBF8814BF248A01D41E86C5715EA40C63F7375379A7EB1D78F27622FB468A\
+B784AAABA4E534A6DFD1DF6FA15511341E725ED2E87F98737CCB7B6A6DFAE416\
+477472B046BF1811187D151BFA9F7B2BF9ACDB23A3BE507CDF14CFDF517D2CB5\
+FB9E4AB6:\
+AE47EF5C61E6AC58497ECA06052012A1CA14B86B605BC8A593326A7CF2286046
+
+FDD7A9433A3B4AFABD7A3A5E3457E56DEBF78E84B7A0B0CA0E8C6D53BD0C2DAE\
+31B2700C6128334F43981BE3B213B1D7A118D59C7E6B6493A86F866A1635C128\
+59CFB9AD17460A77B4522A5C1883C3D6ACC86E6162667EC414E9A104AA892053\
+A2B1D72165A855BACD8FAF8034A5DD9B716F47A0818C09BB6BAF22AA503C06B4\
+CA261F557761989D2AFBD88B6A678AD128AF68672107D0F1FC73C5CA74045929\
+7B3292B281E93BCEB761BDE7221C3A55708E5EC84472CDDCAA84ECF23723CC09\
+91355C6280:\
+83642CFED259EAB056914DF8825ABCD930E0199B43A624A4513FE4DFC60765E9
+
+70A40BFBEF92277A1AAD72F6B79D0177197C4EBD432668CFEC05D099ACCB6510\
+62B5DFF156C0B27336687A94B26679CFDD9DAF7AD204338DD9C4D14114033A5C\
+225BD11F217B5F4732DA167EE3F939262D4043FC9CBA92303B7B5E96AEA12ADD\
+A64859DF4B86E9EE0B58E39091E6B188B408AC94E1294A8911245EE361E60E60\
+1EFF58D1D37639F3753BEC80EBB4EFDE25817436076623FC65415FE51D1B0280\
+366D12C554D86743F3C3B6572E400361A60726131441BA493A83FBE9AFDA90F7\
+AF1AE717238D:\
+63C10EB69F4BA9A18A0E0D620D5F059E95F49623FAEAD0F158C716DD72E4CCE9
+
+74356E449F4BF8644F77B14F4D67CB6BD9C1F5AE357621D5B8147E562B65C665\
+85CAF2E491B48529A01A34D226D436959153815380D5689E30B35357CDAC6E08\
+D3F2B0E88E200600D62BD9F5EAF488DF86A4470EA227006182E44809009868C4\
+C280C43D7D64A5268FA719074960087B3A6ABC837882F882C837834535929389\
+A12B2C78187E2EA07EF8B8EEF27DC85002C3AE35F1A50BEE6A1C48BA7E175F33\
+16670B27983472AA6A61EED0A683A39EE323080620EA44A9F74411AE5CE99030\
+528F9AB49C79F2:\
+BED58E843BA10C20F0D37EE1CA553B81CBB6F8347B8DE1B90A0FFF2701D76C3B
+
+8C3798E51BC68482D7337D3ABB75DC9FFE860714A9AD73551E120059860DDE24\
+AB87327222B64CF774415A70F724CDF270DE3FE47DDA07B61C9EF2A3551F45A5\
+584860248FABDE676E1CD75F6355AA3EAEABE3B51DC813D9FB2EAA4F0F1D9F83\
+4D7CAD9C7C695AE84B329385BC0BEF895B9F1EDF44A03D4B410CC23A79A6B62E\
+4F346A5E8DD851C2857995DDBF5B2D717AEB847310E1F6A46AC3D26A7F9B4498\
+5AF656D2B7C9406E8A9E8F47DCB4EF6B83CAACF9AEFB6118BFCFF7E44BEF6937\
+EBDDC89186839B77:\
+00CC683A0853D9E81A193D351B10F9859AAA51F73D38C8CDDC713E85F0488BEC
+
+FA56BF730C4F8395875189C10C4FB251605757A8FECC31F9737E3C2503B02608\
+E6731E85D7A38393C67DE516B85304824BFB135E33BF22B3A23B913BF6ACD2B7\
+AB85198B8187B2BCD454D5E3318CACB32FD6261C31AE7F6C54EF6A7A2A4C9F3E\
+CB81CE3555D4F0AD466DD4C108A90399D70041997C3B25345A9653F3C9A6711A\
+B1B91D6A9D2216442DA2C973CBD685EE7643BFD77327A2F7AE9CB283620A0871\
+6DFB462E5C1D65432CA9D56A90E811443CD1ECB8F0DE179C9CB48BA4F6FEC360\
+C66F252F6E64EDC96B:\
+B1B86AD854EF99D676C1BA60D99919878054C601620478494B6C589F099172FD
+
+B6134F9C3E91DD8000740D009DD806240811D51AB1546A974BCB18D344642BAA\
+5CD5903AF84D58EC5BA17301D5EC0F10CCD0509CBB3FD3FFF9172D193AF0F782\
+252FD1338C7244D40E0E42362275B22D01C4C3389F19DD69BDF958EBE28E31A4\
+FFE2B5F18A87831CFB7095F58A87C9FA21DB72BA269379B2DC2384B3DA953C79\
+25761FED324620ACEA435E52B424A7723F6A2357374157A34CD8252351C25A1B\
+232826CEFE1BD3E70FFC15A31E7C0598219D7F00436294D11891B82497BC78AA\
+5363892A2495DF8C1EEF:\
+D28E2F5F5A8C6E99542E127EE08A3C0CE367BC9389440CD4B0621DB3D175AC00
+
+C941CDB9C28AB0A791F2E5C8E8BB52850626AA89205BEC3A7E22682313D198B1\
+FA33FC7295381354858758AE6C8EC6FAC3245C6E454D16FA2F51C4166FAB51DF\
+272858F2D603770C40987F64442D487AF49CD5C3991CE858EA2A60DAB6A65A34\
+414965933973AC2457089E359160B7CDEDC42F29E10A91921785F6B7224EE0B3\
+49393CDCFF6151B50B377D609559923D0984CDA6000829B916AB6896693EF6A2\
+199B3C22F7DC5500A15B8258420E314C222BC000BC4E5413E6DD82C993F8330F\
+5C6D1BE4BC79F08A1A0A46:\
+E6029498E687D6F382AC1FF7CC4637873ACE78E7646A44DEFA98DE0FC66D13C7
+
+4499EFFFAC4BCEA52747EFD1E4F20B73E48758BE915C88A1FFE5299B0B005837\
+A46B2F20A9CB3C6E64A9E3C564A27C0F1C6AD1960373036EC5BFE1A8FC6A435C\
+2185ED0F114C50E8B3E4C7ED96B06A036819C9463E864A58D6286F785E32A804\
+443A56AF0B4DF6ABC57ED5C2B185DDEE8489EA080DEEEE66AA33C2E6DAB36251\
+C402682B6824821F998C32163164298E1FAFD31BABBCFFB594C91888C6219079\
+D907FDB438ED89529D6D96212FD55ABE20399DBEFD342248507436931CDEAD49\
+6EB6E4A80358ACC78647D043:\
+316D41DB4674159E7B3CAA356BDB3E89F9D2533CBC5CE7060CD068044ACE705C
+
+EECBB8FDFA4DA62170FD06727F697D81F83F601FF61E478105D3CB7502F2C89B\
+F3E8F56EDD469D049807A38882A7EEFBC85FC9A950952E9FA84B8AFEBD3CE782\
+D4DA598002827B1EB98882EA1F0A8F7AA9CE013A6E9BC462FB66C8D4A18DA214\
+01E1B93356EB12F3725B6DB1684F2300A98B9A119E5D27FF704AFFB618E12708\
+E77E6E5F34139A5A41131FD1D6336C272A8FC37080F041C71341BEE6AB550CB4\
+A20A6DDB6A8E0299F2B14BC730C54B8B1C1C487B494BDCCFD3A53535AB2F2315\
+90BF2C4062FD2AD58F906A2D0D:\
+23564BE9C1E771F667072B641CFBF98B6DE366921FE06D5800D09A78D1B2ABA0
+
+E64F3E4ACE5C8418D65FEC2BC5D2A303DD458034736E3B0DF719098BE7A206DE\
+AF52D6BA82316CAF330EF852375188CDE2B39CC94AA449578A7E2A8E3F5A9D68\
+E816B8D16889FBC0EBF0939D04F63033AE9AE2BDAB73B88C26D6BD25EE460EE1\
+EF58FB0AFA92CC539F8C76D3D097E7A6A63EBB9B5887EDF3CF076028C5BBD5B9\
+DB3211371AD3FE121D4E9BF44229F4E1ECF5A0F9F0EBA4D5CEB72878AB22C3F0\
+EB5A625323AC66F7061F4A81FAC834471E0C59553F108475FE290D43E6A055AE\
+3EE46FB67422F814A68C4BE3E8C9:\
+811181C74DC99406B541A02D7613B488A6DCAB5A418C8F9E9A65A5D287CEEEC4
+
+D2CB2D733033F9E91395312808383CC4F0CA974E87EC68400D52E96B3FA6984A\
+C58D9AD0938DDE5A973008D818C49607D9DE2284E7618F1B8AED8372FBD52ED5\
+4557AF4220FAC09DFA8443011699B97D743F8F2B1AEF3537EBB45DCC9E13DFB4\
+38428EE190A4EFDB3CAEB7F3933117BF63ABDC7E57BEB4171C7E1AD260AB0587\
+806C4D137B6316B50ABC9CCE0DFF3ACADA47BBB86BE777E617BBE578FF451984\
+4DB360E0A96C6701290E76BB95D26F0F804C8A4F2717EAC4E7DE9F2CFF3BBC55\
+A17E776C0D02856032A6CD10AD2838:\
+DF0E92A55BC924854CE90A3231CA437352800FAC355A0303E59AF719AEBCF928
+
+F2998955613DD414CC111DF5CE30A995BB792E260B0E37A5B1D942FE90171A4A\
+C2F66D4928D7AD377F4D0554CBF4C523D21F6E5F379D6F4B028CDCB9B1758D3B\
+39663242FF3CB6EDE6A36A6F05DB3BC41E0D861B384B6DEC58BB096D0A422FD5\
+42DF175E1BE1571FB52AE66F2D86A2F6824A8CFAACBAC4A7492AD0433EEB1545\
+4AF8F312B3B2A577750E3EFBD370E8A8CAC1582581971FBA3BA4BD0D76E718DA\
+CF8433D33A59D287F8CC92234E7A271041B526E389EFB0E40B6A18B3AAF658E8\
+2ED1C78631FD23B4C3EB27C3FAEC8685:\
+29C0D8CB45FBF24A93E94A5D444AA4DA86A35FC1EBC3A1D074F9A4F9FDC8C33E
+
+447797E2899B72A356BA55BF4DF3ACCA6CDB1041EB477BD1834A9F9ACBC340A2\
+94D729F2F97DF3A610BE0FF15EDB9C6D5DB41644B9874360140FC64F52AA03F0\
+286C8A640670067A84E017926A70438DB1BB361DEFEE7317021425F8821DEF26\
+D1EFD77FC853B818545D055ADC9284796E583C76E6FE74C9AC2587AA46AA8F88\
+04F2FEB5836CC4B3ABABAB8429A5783E17D5999F32242EB59EF30CD7ADABC16D\
+72DBDB097623047C98989F88D14EAF02A7212BE16EC2D07981AAA99949DDF89E\
+CD90333A77BC4E1988A82ABF7C7CAF3291:\
+4FDB760C7C304E04EF821770F27D965AC2B0E3413F354264A48E73AAC00A11A3
+
+9F2C18ADE9B380C784E170FB763E9AA205F64303067EB1BCEA93DF5DAC4BF5A2\
+E00B78195F808DF24FC76E26CB7BE31DC35F0844CDED1567BBA29858CFFC97FB\
+29010331B01D6A3FB3159CC1B973D255DA9843E34A0A4061CABDB9ED37F241BF\
+ABB3C20D32743F4026B59A4CCC385A2301F83C0B0A190B0F2D01ACB8F0D41111\
+E10F2F4E149379275599A52DC089B35FDD5234B0CFB7B6D8AEBD563CA1FA653C\
+5C021DFD6F5920E6F18BFAFDBECBF0AB00281333ED50B9A999549C1C8F8C63D7\
+626C48322E9791D5FF72294049BDE91E73F8:\
+E5D2906B09C4EDA48F1DC1F97FB281BA919A1781835F79CB66F97DFA5EE9A6AE
+
+AE159F3FA33619002AE6BCCE8CBBDD7D28E5ED9D61534595C4C9F43C402A9BB3\
+1F3B301CBFD4A43CE4C24CD5C9849CC6259ECA90E2A79E01FFBAC07BA0E147FA\
+42676A1D668570E0396387B5BCD599E8E66AAED1B8A191C5A47547F61373021F\
+A6DEADCB55363D233C24440F2C73DBB519F7C9FA5A8962EFD5F6252C0407F190\
+DFEFAD707F3C7007D69FF36B8489A5B6B7C557E79DD4F50C06511F599F56C896\
+B35C917B63BA35C6FF8092BAF7D1658E77FC95D8A6A43EEB4C01F33F03877F92\
+774BE89C1114DD531C011E53A34DC248A2F0E6:\
+CB499830195004278E91515FC1B5677947F56C5D435079C115611C56B1114826
+
+3B8E97C5FFC2D6A40FA7DE7FCEFC90F3B12C940E7AB415321E29EE692DFAC799\
+B009C99DCDDB708FCE5A178C5C35EE2B8617143EDC4C40B4D313661F49ABDD93\
+CEA79D117518805496FE6ACF292C4C2A1F76B403A97D7C399DAF85B46AD84E16\
+246C67D6836757BDE336C290D5D401E6C1386AB32797AF6BB251E9B2D8FE754C\
+47482B72E0B394EAB76916126FD68EA7D65EB93D59F5B4C5AC40F7C3B37E7F36\
+94F29424C24AF8C8F0EF59CD9DBF1D28E0E10F799A6F78CAD1D45B9DB3D7DEE4\
+A7059ABE99182714983B9C9D44D7F5643596D4F3:\
+C528029336E2DB222F7DF18E81350AE44C0DC06B91E51ABE095236607012250F
+
+3434EC31B10FAFDBFEEC0DD6BD94E80F7BA9DCA19EF075F7EB017512AF66D6A4\
+BCF7D16BA0819A1892A6372F9B35BCC7CA8155EE19E8428BC22D214856ED5FA9\
+374C3C09BDE169602CC219679F65A1566FC7316F4CC3B631A18FB4449FA6AFA1\
+6A3DB2BC4212EFF539C67CF184680826535589C7111D73BFFCE431B4C40492E7\
+63D9279560AAA38EB2DC14A212D723F994A1FE656FF4DD14551CE4E7C621B2AA\
+5604A10001B2878A897A28A08095C325E10A26D2FB1A75BFD64C250309BB55A4\
+4F23BBAC0D5516A1C687D3B41EF2FBBF9CC56D4739:\
+6384F4F86B59E42CE0C2A67521C83DD2D31E4F2EEDABEF5572A6DD2613525F83
+
+7C7953D81C8D208FD1C97681D48F49DD003456DE60475B84070EF4847C333B74\
+575B1FC8D2A186964485A3B8634FEAA3595AAA1A2F4595A7D6B6153563DEE31B\
+BAC443C8A33EED6D5D956A980A68366C2527B550EE950250DFB691EACBD5D56A\
+E14B970668BE174C89DF2FEA43AE52F13142639C884FD62A3683C0C3792F0F24\
+AB1318BCB27E21F4737FAB62C77EA38BC8FD1CF41F7DAB64C13FEBE7152BF5BB\
+7AB5A78F5346D43CC741CB6F72B7B8980F268B68BF62ABDFB1577A52438FE14B\
+591498CC95F071228460C7C5D5CEB4A7BDE588E7F21C:\
+945B8718D14494DBCD296611D2A32B2C1FB8DA19FAAAEE4CA5E8C6B6535F10B8
+
+7A6A4F4FDC59A1D223381AE5AF498D74B7252ECF59E389E49130C7EAEE626E7B\
+D9897EFFD92017F4CCDE66B0440462CDEDFD352D8153E6A4C8D7A0812F701CC7\
+37B5178C2556F07111200EB627DBC299CAA792DFA58F35935299FA3A3519E9B0\
+3166DFFA159103FFA35E8577F7C0A86C6B46FE13DB8E2CDD9DCFBA85BDDDCCE0\
+A7A8E155F81F712D8E9FE646153D3D22C811BD39F830433B2213DD46301941B5\
+9293FD0A33E2B63ADBD95239BC01315C46FDB678875B3C81E053A40F581CFBEC\
+24A1404B1671A1B88A6D06120229518FB13A74CA0AC5AE:\
+E6258B0788EBF57D030C625000B6350BC122800B0EBEE25B6A05736743F4517F
+
+D9FAA14CEBE9B7DE551B6C0765409A33938562013B5E8E0E1E0A6418DF7399D0\
+A6A771FB81C3CA9BD3BB8E2951B0BC792525A294EBD1083688806FE5E7F1E17F\
+D4E3A41D00C89E8FCF4A363CAEDB1ACB558E3D562F1302B3D83BB886ED27B760\
+33798131DAB05B4217381EAAA7BA15EC820BB5C13B516DD640EAEC5A27D05FDF\
+CA0F35B3A5312146806B4C0275BCD0AAA3B2017F346975DB566F9B4D137F4EE1\
+0644C2A2DA66DEECA5342E236495C3C6280528BFD32E90AF4CD9BB908F34012B\
+52B4BC56D48CC8A6B59BAB014988EABD12E1A0A1C2E170E7:\
+CBDE4B2715DB042840E80E20AAF54CAF7770026C49140A13808610318FB1B74F
+
+2D8427433D0C61F2D96CFE80CF1E932265A191365C3B61AAA3D6DCC039F6BA2A\
+D52A6A8CC30FC10F705E6B7705105977FA496C1C708A277A124304F1FC40911E\
+7441D1B5E77B951AAD7B01FD5DB1B377D165B05BBF898042E39660CAF8B279FE\
+5229D1A8DB86C0999ED65E53D01CCBC4B43173CCF992B3A14586F6BA42F5FE30\
+AFA8AE40C5DF29966F9346DA5F8B35F16A1DE3AB6DE0F477D8D8660918060E88\
+B9B9E9CA6A4207033B87A812DBF5544D39E4882010F82B6CE005F8E8FF6FE3C3\
+806BC2B73C2B83AFB704345629304F9F86358712E9FAE3CA3E:\
+DA60848F1B6606F72B9C2F0946A17DFE1B6DE31B6FC0A1D20EBFC1BBF969EDF8
+
+5E19D97887FCAAC0387E22C6F803C34A3DACD2604172433F7A8A7A526CA4A2A1\
+271ECFC5D5D7BE5AC0D85D921095350DFC65997D443C21C8094E0A3FEFD2961B\
+CB94AED03291AE310CCDA75D8ACE4BC7D89E7D3E5D1650BDA5D668B8B50BFC8E\
+608E184F4D3A9A2BADC4FF5F07E0C0BC8A9F2E0B2A26FD6D8C550008FAAAB75F\
+D71AF2A424BEC9A7CD9D83FAD4C8E9319115656A8717D3B523A68FF8004258B9\
+990ED362308461804BA3E3A7E92D8F2FFAE5C2FBA55BA5A3C27C0A2F71BD711D\
+2FE1799C2ADB31B200035481E9EE5C4ADF2AB9C0FA50B23975CF:\
+50425B8A6993AF09C8E6AE22C136C04386D61E9437008741A067E97957060D4A
+
+C8E976AB4638909387CE3B8D4E510C3230E5690E02C45093B1D297910ABC481E\
+56EEA0F296F98379DFC9080AF69E73B2399D1C143BEE80AE1328162CE1BA7F6A\
+8374679B20AACD380EB4E61382C99998704D62701AFA914F9A2705CDB065885F\
+50D086C3EB5753700C387118BB142F3E6DA1E988DFB31AC75D7368931E45D139\
+1A274B22F83CEB072F9BCABC0B216685BFD789F5023971024B1878A205442522\
+F9EA7D8797A4102A3DF41703768251FD5E017C85D1200A464118AA35654E7CA3\
+9F3C375B8EF8CBE7534DBC64BC20BEFB417CF60EC92F63D9EE7397:\
+872DC8B8F7B200D83101677E6E5E0E90661FD8A591E84536F872E330B2D288E7
+
+7145FA124B7429A1FC2231237A949BA7201BCC1822D3272DE005B682398196C2\
+5F7E5CC2F289FBF44415F699CB7FE6757791B1443410234AE061EDF623359E2B\
+4E32C19BF88450432DD01CAA5EB16A1DC378F391CA5E3C4E5F356728BDDD4975\
+DB7C890DA8BBC84CC73FF244394D0D48954978765E4A00B593F70F2CA082673A\
+261ED88DBCEF1127728D8CD89BC2C597E9102CED6010F65FA75A14EBE467FA57\
+CE3BD4948B6867D74A9DF5C0EC6F530CBF2EE61CE6F06BC8F2864DFF5583776B\
+31DF8C7FFCB61428A56BF7BD37188B4A5123BBF338393AF46EDA85E6:\
+E5AA12FB17C67075DCA98DB2DA1395A2D738629826CD69C28F2ED438D0742C29
+
+7FDFADCC9D29BAD23AE038C6C65CDA1AEF757221B8872ED3D75FF8DF7DA0627D\
+266E224E812C39F7983E4558BFD0A1F2BEF3FEB56BA09120EF762917B9C09386\
+7948547AEE98600D10D87B20106878A8D22C64378BF634F7F75900C03986B077\
+B0BF8B740A82447B61B99FEE5376C5EB6680EC9E3088F0BDD0C56883413D60C1\
+357D3C811950E5890E7600103C916341B80C743C6A852B7B4FB60C3BA21F3BC1\
+5B8382437A68454779CF3CD7F9F90CCC8EF28D0B706535B1E4108EB5627BB45D\
+719CB046839AEE311CA1ABDC8319E050D67972CB35A6B1601B25DBF487:\
+03C7BB658E15EF862405999D673EC243DA44432412766FC0FE7DBD2DE0C0953B
+
+988638219FD3095421F826F56E4F09E356296B628C3CE6930C9F2E758FD1A80C\
+8273F2F61E4DAAE65C4F110D3E7CA0965AC7D24E34C0DC4BA2D6FF0BF5BBE93B\
+3585F354D7543CB542A1AA54674D375077F2D360A8F4D42F3DB131C3B7AB7306\
+267BA107659864A90C8C909460A73621D1F5D9D3FD95BEB19B23DB1CB6C0D0FB\
+A91D36891529B8BD8263CAA1BAB56A4AFFAED44962DF096D8D5B1EB845EF3118\
+8B3E10F1AF811A13F156BEB7A288AAE593EBD1471B624AA1A7C6ADF01E2200B3\
+D72D88A3AED3100C88231E41EFC376906F0B580DC895F080FDA5741DB1CB:\
+A26A94B2A5FB0B847E0B691CA58C56C249B68B6966C1C57ACAFC69BCB59588E4
+
+5AAB62756D307A669D146ABA988D9074C5A159B3DE85151A819B117CA1FF6597\
+F6156E80FDD28C9C3176835164D37DA7DA11D94E09ADD770B68A6E081CD22CA0\
+C004BFE7CD283BF43A588DA91F509B27A6584C474A4A2F3EE0F1F56447379240\
+A5AB1FB77FDCA49B305F07BA86B62756FB9EFB4FC225C86845F026EA542076B9\
+1A0BC2CDD136E122C659BE259D98E5841DF4C2F60330D4D8CDEE7BF1A0A24452\
+4EECC68FF2AEF5BF0069C9E87A11C6E519DE1A4062A10C83837388F7EF58598A\
+3846F49D499682B683C4A062B421594FAFBC1383C943BA83BDEF515EFCF10D:\
+C860C4C6C0D8E68A61F98E4F2FDA791F4F8C67327A3411545A9E5C6D37E7876F
+
+47B8216AA0FBB5D67966F2E82C17C07AA2D6327E96FCD83E3DE7333689F3EE79\
+994A1BF45082C4D725ED8D41205CB5BCDF5C341F77FACB1DA46A5B9B2CBC49EA\
+DF786BCD881F371A95FA17DF73F606519AEA0FF79D5A11427B98EE7F13A5C006\
+37E2854134691059839121FEA9ABE2CD1BCBBBF27C74CAF3678E05BFB1C94989\
+7EA01F56FFA4DAFBE8644611685C617A3206C7A7036E4AC816799F693DAFE7F1\
+9F303CE4EBA09D21E03610201BFC665B72400A547A1E00FA9B7AD8D84F84B34A\
+EF118515E74DEF11B9188BD1E1F97D9A12C30132EC2806339BDADACDA2FD8B78:\
+F8A4EBBB9408DE592BBCE7DAFB7C3099F2A40421F30A6A8B91DCAD915617EECD
+
+8CFF1F67FE53C098896D9136389BD8881816CCAB34862BB67A656E3D98896F3C\
+E6FFD4DA73975809FCDF9666760D6E561C55238B205D8049C1CEDEEF374D1735\
+DAA533147BFA960B2CCE4A4F254176BB4D1BD1E89654432B8DBE1A135C42115B\
+394B024856A2A83DC85D6782BE4B444239567CCEC4B184D4548EAE3FF6A192F3\
+43292BA2E32A0F267F31CC26719EB85245D415FB897AC2DA433EE91A99424C9D\
+7F1766A44171D1651001C38FC79294ACCC68CEB5665D36218454D3BA169AE058\
+A831338C17743603F81EE173BFC0927464F9BD728DEE94C6AEAB7AAE6EE3A627\
+E8:\
+04B0412F27BF62A6E5D67D6BC51405A31D4B68B0975ABDD8D7BF6F1F7580037A
+
+EACD07971CFF9B9939903F8C1D8CBB5D4DB1B548A85D04E037514A583604E787\
+F32992BF2111B97AC5E8A938233552731321522AB5E8583561260B7D13EBEEF7\
+85B23A41FD8576A6DA764A8ED6D822D4957A545D5244756C18AA80E1AAD4D1F9\
+C20D259DEE1711E2CC8FD013169FB7CC4CE38B362F8E0936AE9198B7E838DCEA\
+4F7A5B9429BB3F6BBCF2DC92565E3676C1C5E6EB3DD2A0F86AA23EDD3D0891F1\
+97447692794B3DFA269611AD97F72B795602B4FDB198F3FD3EB41B415064256E\
+345E8D8C51C555DC8A21904A9B0F1AD0EFFAB7786AAC2DA3B196507E9F33CA35\
+6427:\
+B8EDB1D60863BE7151070547291BCC11EFBDA4D6909E528016BAF99A3E30DFD1
+
+23AC4E9A42C6EF45C3336CE6DFC2FF7DE8884CD23DC912FEF0F7756C09D335C1\
+89F3AD3A23697ABDA851A81881A0C8CCAFC980AB2C702564C2BE15FE4C4B9F10\
+DFB2248D0D0CB2E2887FD4598A1D4ACDA897944A2FFC580FF92719C95CF2AA42\
+DC584674CB5A9BC5765B9D6DDF5789791D15F8DD925AA12BFFAFBCE60827B490\
+BB7DF3DDA6F2A143C8BF96ABC903D83D59A791E2D62814A89B8080A28060568C\
+F24A80AE61179FE84E0FFAD00388178CB6A617D37EFD54CC01970A4A41D1A8D3\
+DDCE46EDBBA4AB7C90AD565398D376F431189CE8C1C33E132FEAE6A8CD17A61C\
+630012:\
+610136223FE73B3BBBFC6981807986215ABA21EA75F67AA5483DDDF702F06ED4
+
+0172DF732282C9D488669C358E3492260CBE91C95CFBC1E3FEA6C4B0EC129B45\
+F242ACE09F152FC6234E1BEE8AAB8CD56E8B486E1DCBA9C05407C2F95DA8D8F1\
+C0AF78EE2ED82A3A79EC0CB0709396EE62AADB84F8A4EE8A7CCCA3C1EE84E302\
+A09EA802204AFECF04097E67D0F8E8A9D2651126C0A598A37081E42D168B0AE8\
+A71951C524259E4E2054E535B779679BDADE566FE55700858618E626B4A0FAF8\
+95BCCE9011504A49E05FD56127EAE3D1F8917AFB548ECADABDA1020111FEC931\
+4C413498A360B08640549A22CB23C731ACE743252A8227A0D2689D4C60016066\
+78DFB921:\
+BF9E2E277D79ACAF2FFB995CD7B2A9A59768F20705490CF1EA51F2EA91129E34
+
+3875B9240CF3E0A8B59C658540F26A701CF188496E2C2174788B126FD29402D6\
+A75453BA0635284D08835F40051A2A9683DC92AFB9383719191231170379BA6F\
+4ADC816FECBB0F9C446B785BF520796841E58878B73C58D3EBB097CE4761FDEA\
+BE15DE2F319DFBAF1742CDEB389559C788131A6793E193856661376C81CE9568\
+DA19AA6925B47FFD77A43C7A0E758C37D69254909FF0FBD415EF8EB937BCD49F\
+91468B49974C07DC819ABD67395DB0E05874FF83DDDAB895344ABD0E7111B2DF\
+9E58D76D85AD98106B36295826BE04D435615595605E4B4BB824B33C4AFEB5E7\
+BB0D19F909:\
+665AB405F342E3652D427A13BC5C69B7E5863CBA2B65691B7952AC6573A87B44
+
+747CC1A59FEFBA94A9C75BA866C30DC5C1CB0C0F8E9361D98484956DD5D1A40F\
+6184AFBE3DAC9F76028D1CAECCFBF69199C6CE2B4C092A3F4D2A56FE5A33A007\
+57F4D7DEE5DFB0524311A97AE0668A47971B95766E2F6DD48C3F57841F91F04A\
+00AD5EA70F2D479A2620DC5CD78EAAB3A3B011719B7E78D19DDF70D9423798AF\
+77517EBC55392FCD01FC600D8D466B9E7A7A85BF33F9CC5419E9BD874DDFD609\
+81150DDAF8D7FEBAA4374F0872A5628D318000311E2F5655365AD4D407C20E5C\
+04DF17A222E7DEEC79C5AB1116D8572F91CD06E1CCC7CED53736FC867FD49ECE\
+BE6BF8082E8A:\
+ACB07139B29E569BA65C4B40A850554D30E863F5681AC7D9B8EE35CF81763F84
+
+57AF971FCCAEC97435DC2EC9EF0429BCEDC6B647729EA168858A6E49AC1071E7\
+06F4A5A645CA14E8C7746D65511620682C906C8B86EC901F3DDED4167B3F00B0\
+6CBFAC6AEE3728051B3E5FF10B4F9ED8BD0B8DA94303C833755B3CA3AEDDF0B5\
+4BC8D6632138B5D25BAB03D17B3458A9D782108006F5BB7DE75B5C0BA854B423\
+D8BB801E701E99DC4FEAAD59BC1C7112453B04D33EA3635639FB802C73C2B71D\
+58A56BBD671B18FE34ED2E3DCA38827D63FDB1D4FB3285405004B2B3E26081A8\
+FF08CD6D2B08F8E7B7E90A2AB1ED7A41B1D0128522C2F8BFF56A7FE67969422C\
+E839A9D4608F03:\
+5D08215314B5C56908FD7488C5FFE47BE95FD6CF7D8C6014E51532F4E751CA6F
+
+04E16DEDC1227902BAAF332D3D08923601BDD64F573FAA1BB7201918CFE16B1E\
+10151DAE875DA0C0D63C59C3DD050C4C6A874011B018421AFC4623AB0381831B\
+2DA2A8BA42C96E4F70864AC44E106F94311051E74C77C1291BF5DB9539E69567\
+BF6A11CF6932BBBAD33F8946BF5814C066D851633D1A513510039B349939BFD4\
+2B858C21827C8FF05F1D09B1B0765DC78A135B5CA4DFBA0801BCADDFA175623C\
+8B647EACFB4444B85A44F73890607D06D507A4F8393658788669F6EF4DEB58D0\
+8C50CA0756D5E2F49D1A7AD73E0F0B3D3B5F090ACF622B1878C59133E4A848E0\
+5153592EA81C6FBF:\
+116E8D8C5AF649C0D15F2194CDD3291A15F222A6F88A3761943E846F33FCD9FE
+
+7C815C384EEE0F288ECE27CCED52A01603127B079C007378BC5D1E6C5E9E6D1C\
+735723ACBBD5801AC49854B2B569D4472D33F40BBB8882956245C366DC3582D7\
+1696A97A4E19557E41E54DEE482A14229005F93AFD2C4A7D8614D10A97A9DFA0\
+7F7CD946FA45263063DDD29DB8F9E34DB60DAA32684F0072EA2A9426ECEBFA52\
+39FB67F29C18CBAA2AF6ED4BF4283936823AC1790164FEC5457A9CBA7C767CA5\
+9392D94CAB7448F50EB34E9A93A80027471CE59736F099C886DEA1AB4CBA4D89\
+F5FC7AE2F21CCD27F611ECA4626B2D08DC22382E92C1EFB2F6AFDC8FDC3D2172\
+604F5035C46B8197D3:\
+2C0AA5EF88459A493BDD073DBA18CF4977633CCBBA580CBE604BA6FB3E922DB1
+
+E29D505158DBDD937D9E3D2145658EE6F5992A2FC790F4F608D9CDB44A091D5B\
+94B88E81FAC4FDF5C49442F13B911C55886469629551189EAFF62488F1A479B7\
+DB11A1560E198DDCCCCF50159093425FF7F1CB8D1D1246D0978764087D6BAC25\
+7026B090EFAE8CEC5F22B6F21C59ACE1AC7386F5B8837CA6A12B6FBF5534DD05\
+60EF05CA78104D3B943DDB220FEAEC89AA5E692A00F822A2AB9A2FE60350D75E\
+7BE16FF2526DC643872502D01F42F188ABED0A6E9A6F5FD0D1CE7D5755C9FFA6\
+6B0AF0B20BD806F08E06156690D81AC811778CA3DAC2C249B96002017FCE93E5\
+07E3B953ACF99964B847:\
+4A911F2687A33F5C8E754829044058F87FDE6A72907DE042560A5AF51554D20C
+
+D85588696F576E65ECA0155F395F0CFACD83F36A99111ED5768DF2D116D2121E\
+32357BA4F54EDE927F189F297D3A97FAD4E9A0F5B41D8D89DD7FE20156799C2B\
+7B6BF9C957BA0D6763F5C3BC5129747BBB53652B49290CFF1C87E2CDF2C4B95D\
+8AAEE09BC8FBFA6883E62D237885810491BFC101F1D8C636E3D0EDE838AD05C2\
+07A3DF4FAD76452979EB99F29AFAECEDD1C63B8D36CF378454A1BB67A741C77A\
+C6B6B3F95F4F02B64DABC15438613EA49750DF42EE90101F115AA9ABB9FF6432\
+4DDE9DABBB01054E1BD6B4BCDC7930A44C2300D87CA78C06924D0323AD7887E4\
+6C90E8C4D100ACD9EED21E:\
+DAD360AFFE0E7B3D1157BCB4657177775EA28B45557D6A65D2641E2046166F87
+
+3A12F8508B40C32C74492B66323375DCFE49184C78F73179F3314B79E63376B8\
+AC683F5A51F1534BD729B02B04D002F55CBD8E8FC9B5EC1EA6BBE6A0D0E74315\
+18E6BA45D124035F9D3DCE0A8BB7BF1430A9F657E0B4EA9F20EB20C786A58181\
+A1E20A96F1628F8728A13BDF7A4B4B32FC8AA7054CC4881AE7FA19AFA65C6C3E\
+E1B3ADE3192AF42054A8A911B8EC1826865D46D93F1E7C5E2B7813C92A506E53\
+886F3D4701BB93D2A681AD109C845904BB861AF8AF0646B6E399B38B614051D3\
+4F6842563A0F37EC00CB3D865FC5D746C4987DE2A65071100883A2A9C7A2BFE1\
+E2DD603D9EA24DC7C5FD06BE:\
+6032B5B05F13DDAAC2D93D57A5EFAF1B1C1CC49CE84CCAF2EE1286D1F1EBF96E
+
+1861EDCE46FA5AD17E1FF1DEAE084DEC580F97D0A67885DFE834B9DFAC1AE076\
+742CE9E267512CA51F6DF5A455AF0C5FD6ABF94ACEA103A3370C354485A7846F\
+B84F3AC7C2904B5B2FBF227002CE512133BB7E1C4E50057BFD1E44DB33C7CDB9\
+69A99E284B184F50A14B068A1FC5009D9B298DBE92239572A7627AAC02ABE8F3\
+E3B473417F36D4D2505D16B7577F4526C9D94A270A2DFE450D06DA8F6FA95687\
+9A0A55CFE99E742EA555EA477BA3E9B44CCD508C375423611AF92E55345DC215\
+779B2D5119EBA49C71D49B9FE3F1569FA24E5CA3E332D042422A8B8158D3EC66\
+A80012976F31FFDF305F0C9C5E:\
+9B9FEE76015A257580598089FA621E0CA05E7DC2AABF7CE9CCFDCF061871CB7D
+
+08D0FFDE3A6E4EF65608EA672E4830C12943D7187CCFF08F4941CFC13E545F3B\
+9C7AD5EEBBE2B01642B486CAF855C2C73F58C1E4E3391DA8E2D63D96E15FD849\
+53AE5C231911B00AD6050CD7AAFDAAC9B0F663AE6AAB45519D0F5391A541707D\
+479034E73A6AD805AE3598096AF078F1393301493D663DD71F83869CA27BA508\
+B7E91E81E128C1716DC3ACFE3084B2201E04CF8006617EECF1B640474A5D45CF\
+DE9F4D3EF92D6D055B909892194D8A8218DB6D8203A84261D200D71473D7488F\
+3427416B6896C137D455F231071CACBC86E0415AB88AEC841D96B7B8AF41E05B\
+B461A40645BF176601F1E760DE5F:\
+DC8CFB916B692D02DF855014C611DEFDAE743EC8451DAA9C7B1CE3935FE41C16
+
+D782ABB72A5BE3392757BE02D3E45BE6E2099D6F000D042C8A543F50ED6EBC05\
+5A7F133B0DD8E9BC348536EDCAAE2E12EC18E8837DF7A1B3C87EC46D50C241DE\
+E820FD586197552DC20BEEA50F445A07A38F1768A39E2B2FF05DDDEDF751F1DE\
+F612D2E4D810DAA3A0CC904516F9A43AF660315385178A529E51F8AAE141808C\
+8BC5D7B60CAC26BB984AC1890D0436EF780426C547E94A7B08F01ACBFC4A3825\
+EAE04F520A9016F2FB8BF5165ED12736FC71E36A49A73614739EAA3EC834069B\
+1B40F1350C2B3AB885C02C640B9F7686ED5F99527E41CFCD796FE4C256C91731\
+86C226169FF257954EBDA81C0E5F99:\
+B1A50F01F62F4B06B9596EB0AFAAF5E1D0E8C067D0B49023D9E747998F23DF43
+
+5FCE8109A358570E40983E1184E541833BB9091E280F258CFB144387B05D190E\
+431CB19BAA67273BA0C58ABE91308E1844DCD0B3678BAA42F335F2FA05267A02\
+40B3C718A5942B3B3E3BFA98A55C25A1466E8D7A603722CB2BBF03AFA54CD769\
+A99F310735EE5A05DAE2C22D397BD95635F58C48A67F90E1B73AAFCD3F82117F\
+0166657838691005B18DA6F341D6E90FC1CDB352B30FAE45D348294E501B6325\
+2DE14740F2B85AE5299DDEC3172DE8B6D0BA219A20A23BB5E10FF434D39DB3F5\
+83305E9F5C039D98569E377B75A70AB837D1DF269B8A4B566F40BB91B577455F\
+D3C356C914FA06B9A7CE24C7317A172D:\
+77C88F224D467CFFEDDA4DC6E2277694EC4223ECC318C24EF3E45E4350F2C921
+
+6172F1971A6E1E4E6170AFBAD95D5FEC99BF69B24B674BC17DD78011615E502D\
+E6F56B86B1A71D3F4348087218AC7B7D09302993BE272E4A591968AEF18A1262\
+D665610D1070EE91CC8DA36E1F841A69A7A682C580E836941D21D909A3AFC1F0\
+B963E1CA5AB193E124A1A53DF1C587470E5881FB54DAE1B0D840F0C8F9D1B04C\
+645BA1041C7D8DBF22030A623AA15638B3D99A2C400FF76F3252079AF88D2B37\
+F35EE66C1AD7801A28D3D388AC450B97D5F0F79E4541755356B3B1A5696B023F\
+39AB7AB5F28DF4202936BC97393B93BC915CB159EA1BD7A0A414CB4B7A1AC3AF\
+68F50D79F0C9C7314E750F7D02FAA58BFA:\
+2163A2543C14FCC35C3A89DE438ED5673AF2C7694D465A9B4543D8E32DB7EAFF
+
+5668ECD99DFBE215C4118398AC9C9EAF1A1433FAB4CCDD3968064752B625EA94\
+4731F75D48A27D047D67547F14DD0FFAA55FA5E29F7AF0D161D85EAFC4F2029B\
+717C918EAB9D304543290BDBA7158B68020C0BA4E079BC95B5BC0FC044A992B9\
+4B4CCD3BD66D0EABB5DBBAB904D62E00752C4E3B0091D773BCF4C14B4377DA3E\
+FFF824B1CB2FA01B32D1E46C909E626ED2DAE920F4C7DBEB635BC754FACBD8D4\
+9BEBA3F23C1C41CCBFCD0EE0C114E69737F5597C0BF1D859F0C767E18002AE8E\
+39C26261FFDE2920D3D0BAF0E906138696CFE5B7E32B600F45DF3AAA39932F3A\
+7DF95B60FA8712A2271FCAF3911CE7B511B1:\
+8E6502BB8EF5E3891B1A9F51D5617066B9FD4F4F5FE65359EF0A1D2F4C6A710A
+
+03D625488354DF30E3F875A68EDFCF340E8366A8E1AB67F9D5C5486A96829DFA\
+C0578289082B2A62117E1CF418B43B90E0ADC881FC6AE8105C888E9ECD21AEA1\
+C9AE1A4038DFD17378FED71D02AE492087D7CDCD98F746855227967CB1AB4714\
+261EE3BEAD3F4DB118329D3EBEF4BC48A875C19BA763966DA0EBEA800E01B2F5\
+0B00E9DD4CACA6DCB314D00184EF71EA2391D760C950710DB4A70F9212FFC548\
+61F9DC752CE18867B8AD0C48DF8466EF7231E7AC567F0EB55099E622EBB86CB2\
+37520190A61C66AD34F1F4E289CB3282AE3EAAC6152ED24D2C92BAE5A7658252\
+A53C49B7B02DFE54FDB2E90074B6CF310AC661:\
+F7B1D93134A0CC838E869BEDA32CA2D9D9BEC6E7A7A45875DE05EB68B0417F73
+
+2EDC282FFB90B97118DD03AAA03B145F363905E3CBD2D50ECD692B37BF000185\
+C651D3E9726C690D3773EC1E48510E42B17742B0B0377E7DE6B8F55E00A8A4DB\
+4740CEE6DB0830529DD19617501DC1E9359AA3BCF147E0A76B3AB70C4984C13E\
+339E6806BB35E683AF8527093670859F3D8A0FC7D493BCBA6BB12B5F65E71E70\
+5CA5D6C948D66ED3D730B26DB395B3447737C26FAD089AA0AD0E306CB28BF0AC\
+F106F89AF3745F0EC72D534968CCA543CD2CA50C94B1456743254E358C1317C0\
+7A07BF2B0ECA438A709367FAFC89A57239028FC5FECFD53B8EF958EF10EE0608\
+B7F5CB9923AD97058EC067700CC746C127A61EE3:\
+9A6FF92A2AE3BCD719D5FB66B029F67798C929B4E67AA91F9C9F8CEE6B54C36D
+
+90B28A6AA1FE533915BCB8E81ED6CACDC10962B7FF82474F845EEB86977600CF\
+70B07BA8E3796141EE340E3FCE842A38A50AFBE90301A3BDCC591F2E7D9DE53E\
+495525560B908C892439990A2CA2679C5539FFDF636777AD9C1CDEF809CDA9E8\
+DCDB451ABB9E9C17EFA4379ABD24B182BD981CAFC792640A183B61694301D04C\
+5B3EAAD694A6BD4CC06EF5DA8FA23B4FA2A64559C5A68397930079D250C51BCF\
+00E2B16A6C49171433B0AADFD80231276560B80458DD77089B7A1BBCC9E7E4B9\
+F881EACD6C92C4318348A13F4914EB27115A1CFC5D16D7FD94954C3532EFACA2\
+CAB025103B2D02C6FD71DA3A77F417D7932685888A:\
+13BA5049059F654500FA455A7E5A44D3ED0E2335169F96357FCEE1D6FBD659D1
+
+2969447D175490F2AA9BB055014DBEF2E6854C95F8D60950BFE8C0BE8DE254C2\
+6B2D31B9E4DE9C68C9ADF49E4EE9B1C2850967F29F5D08738483B417BB96B2A5\
+6F0C8ACA632B552059C59AAC3F61F7B45C966B75F1D9931FF4E596406378CEE9\
+1AAA726A3A84C33F37E9CDBE626B5745A0B06064A8A8D56E53AAF102D23DD9DF\
+0A3FDF7A638509A6761A33FA42FA8DDBD8E16159C93008B53765019C3F0E9F10\
+B144CE2AC57F5D7297F9C9949E4FF68B70D339F87501CE8550B772F32C6DA8AD\
+2CE2100A895D8B08FA1EEAD7C376B407709703C510B50F87E73E43F8E7348F87\
+C3832A547EF2BBE5799ABEDCF5E1F372EA809233F006:\
+06C6B67E13014CCAC898010F86BC8FDDFBF694EB88934FBBAB86FB6B6396C2EC
+
+721645633A44A2C78B19024EAECF58575AB23C27190833C26875DC0F0D50B46A\
+EA9C343D82EA7D5B3E50EC700545C615DAEAEA64726A0F05607576DCD396D812\
+B03FB6551C641087856D050B10E6A4D5577B82A98AFB89CEE8594C9DC19E79FE\
+FF0382FCFD127F1B803A4B9946F4AC9A4378E1E6E041B1389A53E3450CD32D9D\
+2941B0CBABDB50DA8EA2513145164C3AB6BCBD251C448D2D4B087AC57A59C228\
+5D564F16DA4ED5E607ED979592146FFB0EF3F3DB308FB342DF5EB5924A48256F\
+C763141A278814C82D6D6348577545870AE3A83C7230AC02A1540FE1798F7EF0\
+9E335A865A2AE0949B21E4F748FB8A51F44750E213A8FB:\
+1DA0A375209C2882A102714BE037FF04128D072FB5C6431CD258D9A1D59AFFC8
+
+6B860D39725A14B498BB714574B4D37CA787404768F64C648B1751B353AC92BA\
+C2C3A28EA909FDF0423336401A02E63EC24325300D823B6864BB701F9D7C7A1F\
+8EC9D0AE3584AA6DD62EA1997CD831B4BABD9A4DA50932D4EFDA745C61E41308\
+90E156AEE6113716DAF95764222A91187DB2EFFEA49D5D0596102D619BD26A61\
+6BBFDA8335505FBB0D90B4C180D1A2335B91538E1668F9F9642790B4E55F9CAB\
+0FE2BDD2935D001EE6419ABAB5457880D0DBFF20ED8758F4C20FE759EFB33141\
+CF0E892587FE8187E5FBC57786B7E8B089612C936DFC03D27EFBBE7C8673F160\
+6BD51D5FF386F4A7AB68EDF59F385EB1291F117BFE717399:\
+706229A0AA969CAA09A896C2FA90F7917E3A18D05D1EB5682053D8BDCF512C6A
+
+6A01830AF3889A25183244DECB508BD01253D5B508AB490D3124AFBF42626B2E\
+70894E9B562B288D0A2450CFACF14A0DDAE5C04716E5A0082C33981F6037D23D\
+5E045EE1EF2283FB8B6378A914C5D9441627A722C282FF452E25A7EA608D69CE\
+E4393A0725D17963D0342684F255496D8A18C2961145315130549311FC07F031\
+2FB78E6077334F87EAA873BEE8AA95698996EB21375EB2B4EF53C14401207DEB\
+4568398E5DD9A7CF97E8C9663E23334B46912F8344C19EFCF8C2BA6F04325F1A\
+27E062B62A58D0766FC6DB4D2C6A1928604B0175D872D16B7908EBC041761187\
+CC785526C2A3873FEAC3A642BB39F5351550AF9770C328AF7B:\
+49D1A717356298D5B8E2B07735716C363099CB0431A3A677F4AD33965117582F
+
+B3C5E74B69933C2533106C563B4CA20238F2B6E675E8681E34A389894785BDAD\
+E59652D4A73D80A5C85BD454FD1E9FFDAD1C3815F5038E9EF432AAC5C3C4FE84\
+0CC370CF86580A6011778BBEDAF511A51B56D1A2EB68394AA299E26DA9ADA6A2\
+F39B9FAFF7FBA457689B9C1A577B2A1E505FDF75C7A0A64B1DF81B3A356001BF\
+0DF4E02A1FC59F651C9D585EC6224BB279C6BEBA2966E8882D68376081B98746\
+8E7AED1EF90EBD090AE825795CDCA1B4F09A979C8DFC21A48D8A53CDBB26C4DB\
+547FC06EFE2F9850EDD2685A4661CB4911F165D4B63EF25B87D0A96D3DFF6AB0\
+758999AAD214D07BD4F133A6734FDE445FE474711B69A98F7E2B:\
+922B6E073DDDA9E57F15F6D65B66667921BACF94B229CE0041E7150894826956
+
+83AF34279CCB5430FEBEC07A81950D30F4B66F484826AFEE7456F0071A51E1BB\
+C55570B5CC7EC6F9309C17BF5BEFDD7C6BA6E968CF218A2B34BD5CF927AB846E\
+38A40BBD81759E9E33381016A755F699DF35D660007B5EADF292FEEFB735207E\
+BF70B5BD17834F7BFA0E16CB219AD4AF524AB1EA37334AA66435E5D397FC0A06\
+5C411EBBCE32C240B90476D307CE802EC82C1C49BC1BEC48C0675EC2A6C6F3ED\
+3E5B741D13437095707C565E10D8A20B8C20468FF9514FCF31B4249CD82DCEE5\
+8C0A2AF538B291A87E3390D737191A07484A5D3F3FB8C8F15CE056E5E5F8FEBE\
+5E1FB59D6740980AA06CA8A0C20F5712B4CDE5D032E92AB89F0AE1:\
+829618746241EA263BF89B5A908E7ED475B7EB53B9B290A20134C2670F7A2496
+
+A7ED84749CCC56BB1DFBA57119D279D412B8A986886D810F067AF349E8749E9E\
+A746A60B03742636C464FC1EE233ACC52C1983914692B64309EDFDF29F1AB912\
+EC3E8DA074D3F1D231511F5756F0B6EEAD3E89A6A88FE330A10FACE267BFFBFC\
+3E3090C7FD9A850561F363AD75EA881E7244F80FF55802D5EF7A1A4E7B89FCFA\
+80F16DF54D1B056EE637E6964B9E0FFD15B6196BDD7DB270C56B47251485348E\
+49813B4EB9ED122A01B3EA45AD5E1A929DF61D5C0F3E77E1FDC356B63883A60E\
+9CBB9FC3E00C2F32DBD469659883F690C6772E335F617BC33F161D6F6984252E\
+E12E62B6000AC5231E0C9BC65BE223D8DFD94C5004A101AF9FD6C0FB:\
+2ED33A40EE546F0D5BF182AE69258B4632FDE6501C4319AF4E348334DDCBEA9E
+
+A6FE30DCFCDA1A329E82AB50E32B5F50EB25C873C5D2305860A835AECEE6264A\
+A36A47429922C4B8B3AFD00DA16035830EDB897831C4E7B00F2C23FC0B15FDC3\
+0D85FB70C30C431C638E1A25B51CAF1D7E8B050B7F89BFB30F59F0F20FECFF3D\
+639ABC4255B3868FC45DD81E47EB12AB40F2AAC735DF5D1DC1AD997CEFC4D836\
+B854CEE9AC02900036F3867FE0D84AFFF37BDE3308C2206C62C4743375094108\
+877C73B87B2546FE05EA137BEDFC06A2796274099A0D554DA8F7D7223A48CBF3\
+1B7DECAA1EBC8B145763E3673168C1B1B715C1CD99ECD3DDB238B06049885ECA\
+D9347C2436DFF32C771F34A38587A44A82C5D3D137A03CAA27E66C8FF6:\
+325F7F78EB55A3AB1C9DF0C79AD6B325F1DE2EC4513CD0C50074D96A4952E704
+
+83167FF53704C3AA19E9FB3303539759C46DD4091A52DDAE9AD86408B6933598\
+9E61414BC20AB4D01220E35241EFF5C9522B079FBA597674C8D716FE441E5661\
+10B6211531CECCF8FD06BC8E511D00785E57788ED9A1C5C73524F01830D2E114\
+8C92D0EDC97113E3B7B5CD3049627ABDB8B39DD4D6890E0EE91993F92B03354A\
+88F52251C546E64434D9C3D74544F23FB93E5A2D2F1FB15545B4E1367C97335B\
+0291944C8B730AD3D4789273FA44FB98D78A36C3C3764ABEEAC7C569C1E43A35\
+2E5B770C3504F87090DEE075A1C4C85C0C39CF421BDCC615F9EFF6CB4FE64680\
+04AECE5F30E1ECC6DB22AD9939BB2B0CCC96521DFBF4AE008B5B46BC006E:\
+068C2325A49AFC18068DC7780138370FE1556719A3614B4CBEECE37BAD97B5BE
+
+3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5\
+623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A\
+15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0\
+A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764\
+B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43\
+C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D\
+817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08\
+5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1:\
+A43DD35DE780E9DDBC86390E83529C7AC0717A351CDBF9719AA5F45677187AC3
+
+724627916C50338643E6996F07877EAFD96BDF01DA7E991D4155B9BE1295EA7D\
+21C9391F4C4A41C75F77E5D27389253393725F1427F57914B273AB862B9E31DA\
+BCE506E558720520D33352D119F699E784F9E548FF91BC35CA14704212870982\
+0D69A8287EA3257857615EB0321270E94B84F446942765CE882B191FAEE7E1C8\
+7E0F0BD4E0CD8A927703524B559B769CA4ECE1F6DBF313FDCF67C572EC4185C1\
+A88E86EC11B6454B371980020F19633B6B95BD280E4FBCB0161E1A82470320CE\
+C6ECFA25AC73D09F1536F286D3F9DACAFB2CD1D0CE72D64D197F5C7520B3CCB2\
+FD74EB72664BA93853EF41EABF52F015DD591500D018DD162815CC993595B195:\
+8B451F3F47238313FC8D2E289193BB7EACFE3D0EA42162E2BF6480EB19DFE24B
+
+3139840B8AD4BCD39092916FD9D01798FF5AA1E48F34702C72DFE74B12E98A11\
+4E318CDD2D47A9C320FFF908A8DBC2A5B1D87267C8E983829861A567558B37B2\
+92D4575E200DE9F1DE45755FAFF9EFAE34964E4336C259F1E66599A7C904EC02\
+539F1A8EAB8706E0B4F48F72FEC2794909EE4A7B092D6061C74481C9E21B9332\
+DC7C6E482D7F9CC3210B38A6F88F7918C2D8C55E64A428CE2B68FD07AB572A8B\
+0A2388664F99489F04EB54DF1376271810E0E7BCE396F52807710E0DEA94EB49\
+F4B367271260C3456B9818FC7A72234E6BF2205FF6A36546205015EBD7D8C252\
+7AA430F58E0E8AC97A7B6B793CD403D517D66295F37A34D0B7D2FA7BC345AC04\
+CA1E266480DEEC39F5C88641C9DC0BD1358158FDECDD96685BBBB5C1FE5EA89D\
+2CB4A9D5D12BB8C893281FF38E87D6B4841F0650092D447E013F20EA934E18:\
+108619224EBBA468F3E2166F8567E8F65798BE63D27911829941DEFB9F41FCA6
+
+023D91AC532601C7CA3942D62827566D9268BB4276FCAA1AE927693A69616526\
+76DBA09219A01B3D5ADFA12547A946E78F3C5C62DD880B02D2EEEB4B96636529\
+C6B01120B23EFC49CCFB36B8497CD19767B53710A636683BC5E0E5C9534CFC00\
+4691E87D1BEE39B86B953572927BD668620EAB87836D9F3F8F28ACE41150776C\
+0BC6657178EBF297FE1F7214EDD9F215FFB491B681B06AC2032D35E6FDF832A8\
+B06056DA70D77F1E9B4D26AE712D8523C86F79250718405F91B0A87C725F2D3F\
+52088965F887D8CF87206DFDE422386E58EDDA34DDE2783B3049B86917B46280\
+27A05D4D1F429D2B49C4B1C898DDDCB82F343E145596DE11A54182F39F4718EC\
+AE8F506BD9739F5CD5D5686D7FEFC834514CD1B2C91C33B381B45E2E5335D7A8\
+720A8F17AFC8C2CB2BD88B14AA2DCA099B00AA575D0A0CCF099CDEC4870FB710\
+D2680E60C48BFC291FF0CEF2EEBF9B36902E9FBA8C889BF6B4B9F5CE53A19B0D\
+9399CD19D61BD08C0C2EC25E099959848E6A550CA7137B63F43138D7B651:\
+94357E4E74ED684DA386A7B2DBD8F611C21408F77258222B92DA7DEA603B3B48
+
+20FF454369A5D05B81A78F3DB05819FEA9B08C2384F75CB0AB6AA115DD690DA3\
+131874A1CA8F708AD1519EA952C1E249CB540D196392C79E87755424FEE7C890\
+808C562722359EEA52E8A12FBBB969DD7961D2BA52037493755A5FA04F0D50A1\
+AA26C9B44148C0D3B94D1C4A59A31ACA15AE8BD44ACB7833D8E91C4B86FA3135\
+A423387B8151B4133ED23F6D7187B50EC2204AD901AD74D396E44274E0ECAFAA\
+E17B3B9085E22260B35CA53B15CC52ABBA758AF6798FBD04ECEECED648F3AF4F\
+DB3DED7557A9A5CFB7382612A8A8F3F45947D1A29CE29072928EC193CA25D510\
+71BD5E1984ECF402F306EA762F0F25282F5296D997658BE3F983696FFA6D095C\
+6369B4DAF79E9A5D3136229128F8EB63C12B9E9FA78AFF7A3E9E19A62022493C\
+D136DEFBB5BB7BA1B938F367FD2F63EB5CA76C0B0FF21B9E36C3F07230CF3C30\
+74E5DA587040A76975D7E39F4494ACE5486FCBF380AB7558C4FE89656335B82E\
+4DB8659509EAB46A19613126E594042732DD4C411F41AA8CDEAC71C0FB40A94E\
+6DA558C05E77B6182806F26D9AFDF3DA00C69419222C8186A6EFAD600B410E6C\
+E2F2A797E49DC1F135319801FA6F396B06F975E2A190A023E474B618E7:\
+764303D3B9B470A4DEB78DB588A4FA505570337515A372143AFB2604CD51319A
+
+4FBDC596508D24A2A0010E140980B809FB9C6D55EC75125891DD985D37665BD8\
+0F9BEB6A50207588ABF3CEEE8C77CD8A5AD48A9E0AA074ED388738362496D2FB\
+2C87543BB3349EA64997CE3E7B424EA92D122F57DBB0855A803058437FE08AFB\
+0C8B5E7179B9044BBF4D81A7163B3139E30888B536B0F957EFF99A7162F4CA5A\
+A756A4A982DFADBF31EF255083C4B5C6C1B99A107D7D3AFFFDB89147C2CC4C9A\
+2643F478E5E2D393AEA37B4C7CB4B5E97DADCF16B6B50AAE0F3B549ECE47746D\
+B6CE6F67DD4406CD4E75595D5103D13F9DFA79372924D328F8DD1FCBEB5A8E2E\
+8BF4C76DE08E3FC46AA021F989C49329C7ACAC5A688556D7BCBCB2A5D4BE69D3\
+284E9C40EC4838EE8592120CE20A0B635ECADAA84FD5690509F54F77E35A417C\
+584648BC9839B974E07BFAB0038E90295D0B13902530A830D1C2BDD53F1F9C9F\
+AED43CA4EED0A8DD761BC7EDBDDA28A287C60CD42AF5F9C758E5C7250231C09A\
+582563689AFC65E2B79A7A2B68200667752E9101746F03184E2399E4ED8835CB\
+8E9AE90E296AF220AE234259FE0BD0BCC60F7A4A5FF3F70C5ED4DE9C8C519A10\
+E962F673C82C5E9351786A8A3BFD570031857BD4C87F4FCA31ED4D50E14F2107\
+DA02CB5058700B74EA241A8B41D78461658F1B2B90BFD84A4C2C9D6543861AB3\
+C56451757DCFB9BA60333488DBDD02D601B41AAE317CA7474EB6E6DD:\
+3CBBEC1BA9409A694E4513DEBBDA2223CA1A91376D97298C26FD920A7AC730D6
+
+D1890B4704E169C28E44DDF62A1091450404910539FC2DAEB26E8ACF4533B024\
+E5215C2D02820DD8FB2CFC1743955CBACFF0F8F35DFBB5E3F942F36247F68211\
+D518F3F601AAE12A1CDC000BAB43D4C973F287E80741DD1FCF6C34F2E6B4B6C3\
+13D01C4FF3CBF9166F26946F18EF2D58271BA9233F09A6B77BFD4F48B36EB3D7\
+3D1133C4F842A7DC3907F680B0B773242C11E3DD973A44327EA7CEA9C0F8E07D\
+682B6651E506B587559FE01ED721000BAF570A16FBDD9EA29FA3DEF4BE912058\
+321A8B720C5C102E48A6E7ED6F8838D400DD57D06EEDBCD15323F86D855C94B2\
+1E41B14EC9E1BBC8019211FD88138C91F9ABBD9BB3914D26C1DDC21673D2D512\
+63B39D66E741D924CF2B192C5D2C1A140126A3D64A2C77BE6C2C6EBE8599978A\
+E90BD36CBB9AF64D078910C4094AB3BF399C34F2AB8EF843E9FE1BF88BF443BA\
+21E4377E5F49C07FD9653B526E14562237F02D11B904BCA6AC31AE721A43E3C4\
+910A24AF6F4D80C031C109FC0FE49F15274BCA92BDA04C3B4196C192F6CE489C\
+63A806ACFC895AB52CAD657C1783B528E12D0ED856E1F8FC91F2AAFDFA0A9249\
+8D68530772EE73B359FCF1418D1096C46B34DCF90E5B468BBB2970BECBD70089\
+CFB039D64CC50FFF5EEF26384D34F24515A6558B06A1FDD88F1050C5BD78CC6E\
+D83D4C2B0E882AEBCF84AFB0430D0BF09F2FB42B8B4589158093A7709AAE75A7\
+90910E211EE1333FFB6FD80778DA3BF73858978E9DD647978841B18001DBAAEA\
+43CA0C0A03DBB9BCF30CE76A6F4B2CF2A9B6531B3E4051E7E05090CD421BC66C\
+4731E7122AD129FC42DEDC83BB460E3F889992FBD3CA072686E56B72C720FBC9\
+8D723EF7F247286F77CCDDC728738E941B1A74D4F16671C21FDD5643A115DDBC\
+B88EE7EC67EA66FD2BCE718DF6E085D4B5FC71A72696636A8F7B3A68AFA51A89\
+6771FAAA7F1F827430AC5E8089DBC0D4175E1B22A057BC5F1724EADC1A41E78F\
+A3ACAA8B97E5F2E19EF9D59AE12B04E7F0E8A621E098A66910E2A5ED2102B824\
+CD3EA044A854F1CD0B33E61E7F737414B2953549F25DD34D19AA1981DE7CD564\
+9FF6C6364A4F25312EF62395A747AB88AAD722C05AEC40DEEA8EEE5E779EF458\
+A68840BC6BD5D29AD40F98B3AE010B6213372ABB7BB8B8:\
+75F9112253A5AB9767736CB5801763EEAFE5286EC12A7EE642E2683BD3F50BBC
+
+4FA3DF1DEA75AD4B9C379206A95FED930000482E5B683FD2B17DC8E7D5C4BC1B\
+73186CCC13C9FF2DD09FC1D4F68034D120E84CA73A00B71A3B46D1EFC6FF88CF\
+2EDA65810B098CC5E651D9CF064E87076D5A871849F3B405D3D58EF5B1F10520\
+A9FB4FC84A81A87B13DBFBF9D8674943E28C257E46D8AD7BE1785F1DC7C9B1BD\
+574AD1DDA48F0255C853D2490BD3D63DA22A8369CFD02594999A2EF443308FB8\
+298266A11EFA177102C75DC674E89FC9DCC1A0D3C863BC26141102175D2678EB\
+6E13D90BBD9A5EB89AE8C0CB47D7F340D3D32042A2762BC9BF2B40EB40E87FB4\
+2610FE7E357051F01494704FBFF73321B47301A0799B7EE3FE5E62200F397A61\
+ED4509A62F7106ED0EFB0ABD6AE9E4A1FE9B02C092DCDC75015CF602F3B9A898\
+8B609E6C0D1C5C3E219FF57875C2EF01615F89447EA602DFC94EEC17A398C014\
+BD346691FE209A002771DC8164422CD166AFB457A8B3071282178A3EBD201D9B\
+07B27E711E7EE7D33AA5210ED4E4E92486775D14A6CED092E34A7AC826709399\
+48FEC149F9C018FCAAD3FC597D315713F44FC5E1725F448ECAED40E8D841BD02\
+F1E81C019B08F99412E360C0BD378391C67D964B47F50C26F0A483ED66402361\
+6B0FC9AFE43620DBE9CCFE070EF295C049EAC754C2123130C6B2C0232F6403AA\
+7F0DC35A5999BF95D34AD612234C6289277ADB60E4F72EC2DF570F05395B3BE8\
+A0A3C78B732821AA08927C524E15D65F66A3DB8C1C96FB70BC0686AAC310051F\
+469FC5EF880C0F66947C1C328F97684EA24CBE63BAED8D114F40507C2901034E\
+6AB3893F366D53F1CFCA309309218CABCECA4722FA9CCBC7249B87C12FF8397F\
+40487EB00082E7F551D27E301C3BC7B5389F7042534BF7E692DFEA4DA24F7C34\
+B8D2FF145F54B517FC97134EC5AC2CB925C508D7A6BD01FE7B764648274972BF\
+08560D30802E0EB7EDCC57AF4797BBF92E8688268606B0F1BC901FCC22136281\
+665EC16393FA9601C4FBDB18CD1D1EE382BC07973903E91FFA87399D1141D49F\
+4F0C064ACF3AC9897891DF10BCA0116F2C3FEF180FE6A8E937C478F2EF293AE9\
+186DCB1F76B6E48101DF64E57EA7C64C5C0025E221C8F5CBA5CC92D9CEC62814\
+0996B26D17F439B780F59A999301122F82D0495F8AB5AE1EA5790F45E992DFE0\
+0D5F82A7FF1354AEFDCEFC0D2D1731D22FA2B75AFD4FDA25AB194055FA962838\
+1055247C8C7587D22E73C60136C4282452D47AE03AA035FEBC26FCCD42A1CB79\
+CF866DB6418A49FD8261E877DDBB839CC39514DDB87A8A40D795532626FEA4A4\
+C35D13E028F9ED1BC09B06BE999B8DDD2258AA0596BCBBF72AF67E10BEDD58D5\
+99B8D577A583D676BF5561F80CE5E9528729A92DF578FE75DBC70474B75747A8\
+D55DE70E57BDD62D4344DC2115ED4DD62F1FC98BFA1E7421FC0700025C46D0ED\
+1BEF35C3B778563211B9FA9E8BA4BBCBF01C2FB626AB7EF325CE9F468DF2CACD\
+B178D36557CD85D542C067C289E926C1EA2F20ABD329E984168BB6DEF1DDCCF2\
+14DCB6A53AFD462F0E7E7A19E8C88F049244125A6D7DD41E58BC9B2FF7FA2478\
+DF76AF73090CB1AB59E388BA20E2C297C967737A1AF61793B68ECD7439444C48\
+E28E2D09C48FADA5E0D1D15E5B340A52F8B3B854CCA479F0A598445E14F53B3B\
+A36891050C79673DF3E2B5825C955A29E5C9A22F3991D0AA785718CFEA1D2385\
+F8E47E4A75ACBC7988D0558D541D71C4E6C5F1CB15B60CEA0C34A67BBCE105D7\
+A896025E0254DE7D7AF724C9027D44B8642192A08AB8E1EF3046DDA6014DF7F4\
+C9E63C635E48AB2E70B640D480998EC9357E665F99D76FE5529EF23C1BDFE017\
+C3A66CD4EB2DDB42EF85EA0CD65534:\
+E78E29F038A4D0DBBBB28AEF1A99904F5E132660EC509BC1621987A9058FBFBD
+
+523DE8B1F4CBB65E81FF0B6CCD6EB8EF0A0F0A691ACAF4A77F25ACD2D66AD4B3\
+EFD25BE70308853C094412A518A32020E3020A9F6AB32F0CD60EC0D7A194917D\
+6C457B168A54A4B46F7B0D0C71BD61CD202F4C718776A701E0770B0EFA054187\
+70F98E4E79CD066366FB3300E8BE359A98B82B764BC2FBBF59C7E8F94A157B01\
+C6C7577B1428138CD422BC47330F8ED99F4C0AAB0D984287445539839389EE08\
+D6345108AF26ADED0EC1D7BE774CFB8C5205DFE07CF6CAF8C1AFE37C7A2E4FE6\
+013B93EB2463DE4E0971C7178D6A76B16A0E8960C984CE8BBE71B3B466EDF044\
+5B835F09414D01F14C7B6167FF78FF118127BBD5F812C27FACD57B3B120E2BCF\
+E87315C7A92B82EF5D50CA14A7174D1BEA7E056523E055A6AE42EA3765094E55\
+44E5ED003C989C2F98F38A17E3DDA74DBAF9C669A319638A2698B0E4A611480D\
+8AD3CF016792ECD1034925F42B9811A7214D623D047ABCA31997DDEB03275F80\
+DD21F40DDC80616E7AD3D481E8EBC0A1A6A398E16A78369215541ED10B75671A\
+DEB1AAE6E11142A1CF665FC1B7332DFBB0E10C21A2B48F78E57319AC9C58DFA8\
+B1C2548E2979EF1ACCFEB215AFCD6C2C1B46FE97DD491758378330EFFC728366\
+1D2CB84FA05281E9E517408508D24D042E7B9BCD34DB87CE972E4CBCDB98615F\
+B93093369DFEDC782F44BCD03E81CF93051318B2401FF29F753A264BDA65AF19\
+9E3FCBB8B5D39C838A67D6C7A3DB046DC56C323DDBB5340CBC229E47CFF8C9D2\
+9B7A49AC0EC8C1440AE498C7D150EF91C29BEA7DF3EFCC2871A13A1D72D139CB\
+4603D9FFFE85F6DDD544850EF63C3944FB35DBC00D4308CEAA6394B6E23F650D\
+323F8F7EF50DDB68F1486EABF989BF44451F620EC9485C0B52D1415D3C909A2C\
+FBE9D77DB19D069D33BAEE4D77292E63FCBF65C1EBA24BFFDDEFE95211EF0AAF\
+8ABFDA9F94445E582976F986F5382CB669506AF2B4A5A0C43000A3C72C5CA4AA\
+CDC9D3D39FC5C492A393B6C341B86DACBBF6BA8B465100CC683EDB2D9B9F83ED\
+F9C6A32645F51CC79ADC22A52A007BAACA618BE35E356D1FD1CFBDA73F1ED092\
+53039DEF609450FD2D5943B9CD49CBD52A318EE3510D7CF3FD8FB388AC6CB9C6\
+EEFEF3D3CAD8501B91CC04A888D33E16D6A4C9666F5F5F3B257193F2B46DEDDE\
+11842909D8C48ADE57775B0B272E2DC9CEF1A083EB2CE58F4D1F211922FD6ADE\
+D1B82FE6F5B11251CD396E5A3666ED9626036E4E356231C146BBA0A91AFD3648\
+EB7BFE0B9C14F15AF2F92309826F468945CAD0AC422DE3D6A773B76178422107\
+CE0270E7F580B5CCEBA82CA0184AAFA8341141E65E39859885768FBC5CE63B96\
+5A0604B659E71D9DA2C7A43646088D8071D76926163AAFC69E25355BB0A222B7\
+B2DA9F0A20C021ADC462E905A9C3BF31C16D87FBEC3F014F3957A720F1432E17\
+41553092052FB58A198640479ABCAA51B104CC93E2636E1460643EA812BD44E8\
+19C2166EB6B349BA5BDEBAD59078910B5C22A56F004B8D9E4B1224D8D204B48A\
+BE7355548A402736C5CB110F3A1476ED631FF168F4F3EFD89B38DE4751536548\
+647523D334FAD7CC2D142973F2DB3C1FE08FC5CF83F9F2BD2DAA524B37864816\
+AF29EE05951FA09D1C51D9D14EE4F72FD7BBF18B1A724FF5A0958A063947C430\
+142AD2356E4400AAECA442E163372A8F1CD36E2DB988E7781165E5D4E7074ACE\
+40858E8370E883694AF09977704347FB735C8717C42BC4EEEB2AAA50DFE637C6\
+40909CE379BFB9E2608F88751377038D1669F248178AD580A908D7A1B8DCC7E5\
+3E01801F1E485B5893F103F03E0F53B2B1440BE95644D85AA7F6EB7EDFBB4665\
+2196695EA23C08573397B111FF909025E20C5201293B4D223BF7AA01DE7CB28B\
+94714370434B9588097E2401B62C7A0DEF1FBF89809E810749FD3CE9EC3C07CE\
+4BF4C43DC966429B2BEB4D711FC6C448A12097B36F1E6817EAF4937A983F85D9\
+CF3E62CC1B2AC6AE1EC9EAA8CD8EE2C3322239CFE5DB3D4E8786282E630A7D25\
+9C2FEFECA03031C960A66A71E436A3ED6F2F3CFAB4BD77C660D14205ABF606FE\
+561A346F7D849B69475AC9F6822D80B9A2E56D5D495E4B309B0EA963C9FC5C7E\
+F94B217EE5337989AFBC7107D233A8B362AC27C4F69DF9E191CD65AE97D6EB9E\
+5484EB6F10349575E4CAE51452380151F902415AC9CF42C824EB23C9541D2DA1\
+C26DB85F53CDAFB06A12B8393CD580A8E494EDB6710C720DCAE30832967E33E6\
+303A92B1DF0841D7724284FFD2E00B95C6D623B168D21AC1BD3C675EDA33182A\
+2C22370998DE1E5EB905372CC6EF32D5B765F5C94870DF4842D011603BE4CDB1\
+C227E41EB2F2E8542CD325884FEDC9C5C7BB07A92D20D64B836215C59F162A3D\
+A8BB67D6FC13FEF97CAB6ECB8A29E431A6519A6261C4521CCB90E6E609869E6F\
+E398404AE047F64EC4263566DEFEE66329DD40AC985EB8A08D26529A544891B6\
+F57CC235C63C09057AB6B6ED720EF41A3C9AE65768B43F6DCF4962A103DD93C2\
+13171DC2C9194E43265C689B49331450281A3FEBC618D1AA4D65A135137051FD\
+46B568CE294C89:\
+73261257A08B911C326E016A5E8EDB23C23BA48EF26C6AA9E9013AB6B1688A50
+
+F5080D4C59E804BF8F34B334CABBCC7D32011BDE3677F4B9069416AC204114CD\
+9DA7A0ED0F4B4D8344416336EEC15553EF526B6DEC267B1242657DD0B508AF81\
+FECF9CFF9C82A6A7A9539814DD7E097615EF15373836B5D2F765CC8D5F82E904\
+49F13AA741D5EE2FE63898E55ACD85116846807606FE1E2E29F98F9940B067D0\
+D1DF01F080211B2EE4B0A30803782A7BC2EAFDC5EBDBA91EB05F7D7DC8E34BF6\
+D44FEC05824F53418F235FB64E899EE147BCB403C8855E94AF378D182D79C3EA\
+F977CB4E9D4A16D990A6C388CEB567B97785E6F2BC6745102B99AE765E960B6B\
+32BAF01E2379CD6ECB74D3E1A56552F5976DFE5C742BC92BE596CA742FFC3D0F\
+A032AC29F9F7C1A5C43BCCA62DF7D9DE35D0C7C179DB2E1AA255CEDCCA55064C\
+2049FEE1AF2CE5EF696ED4BC46B7C55BDD51F2D44C8713FB2475C0B85246AC01\
+03CC3863B7EB026AE076A600313F6FB40A4DF62A2AF81B7E917951EA870ECB31\
+B3401928B5046D9A1E62D14B30FDEBAF262868517318FE17EC3C0D52524F4412\
+0ED8ED3BA70C643300CD0BC70DA72C964A88F52C3A91EC20BFEB5CAEFCD4D9C7\
+685D8407476B5F34676C5EBD1E88A6CFF1C625322F8CD59B9ED60CEFB21F9491\
+B95E72791F7AC7EAA3C16159FE9DF7A989ADD6C2282C47585E11397EDA9F47DF\
+2B40166E03BCDD6186B46C6835118268DDBEF19A28BBADE1BDE0228FFD7E8B3C\
+3C598D89E24B8CDEE79C940254DE26CC6814BA2722E42F7571600B7325E1FF30\
+0251D52A895B8CCBD049B2953B8D231445F68F7C26EC25A4B8695C8AC116F736\
+BE939EDD762C9B4743E463C9B9B2F88E0BC0CE78781CDDC3BCA825ACD463C7CA\
+C2AA6C430BBE820EA94AF9A40B1B5C006E9641A2FFA6E427379E1AD49C81B983\
+20B3431FF0030DC683D61026438BC6A6D34B2C73704D9F62EAEB13ABB3E4B056\
+2B4E0482CD6B2D7AEBC0367EA29A88F4A76F3D76FA1197E1DCA92C8216C84C1A\
+F9B8C78C9E3A7799A4A79A783033B0F5547E8E75E69CF3615AB04EF989FE1A46\
+3B1672C571D50AB56972896E8A50C242F22C7F6E27CA4CA793F627E79608680F\
+5421B28BDD2589F05E65430DF774EE873FCD1234064F7A33CF5A1FA4E368137F\
+F9C1597F1FA0FA36493F20538077669EADFD3B06F788C912C715FB5D334DB6BE\
+D133A8FDC40F5496E66AD63881F0BA3727416715865253DC5290327B515BF68D\
+A188DD5B4B0EAC7CA712CAFA8FCAE0C5503FE58A219182F1C30DA6D0C19CFEE8\
+97B7D837C97996A35F4CA8CF0537A01D17E7DE0CC9C129E4DA0ADAF1FDA85030\
+DF9127BE628263B0624F372C47C3AC87EB945A57F5C732BEEE81A74030017989\
+92F3DC944114FF3D54C4666AC5AC8C98D0D5596CBDEB420665F5EDAAE747D54C\
+F7EDD37B162E372249D135938CF17D174D12D88279CB4C32BD6F018C766DA698\
+3D4EA51D6BD8FF0A9B34E9A93BBDA70CF1B4B867D60A74811FD98D52FAA559B5\
+2C755CB70A76C94BD19654CAE7017CCD70222BF08C5D7AD1F5E4E6344FDB3ABE\
+703452C29A696F39F9826ED8BC510A4A148E5BF8A5DBE6B82D7220164F08011C\
+05AC5159D52CE9D45D758B645BBB248C2D341DBEFA1F8602C5D458A64F38F3B0\
+4DB39089807B6A10E1BB52770B92CE72E2D3BB0C2241CDED35054B84558D1CC0\
+99EF7B2296951951D5B6A22F93BF962AC5EF8FB55EC6CC2B316428EDF12078ED\
+1B66D525D022819CBD489E1BEDB02FFBD507D55F9B5D4E22F6396EA233453754\
+688D20151A09C70044B8A5A9AC033C3C3B847AD833D5C05B33407666EE82F958\
+1DF9034EE15A9CA67D52F1D9B634B84C1B8BA9E515F1F060A5AC5CBAE2DE75F9\
+4E112F7198E239DF08D3103F065627438995026DF511C6E5BFDEEE5667D511D4\
+181850C7C5D179107C1B86D24D5532A88A4149A2810DCAE73731B0E1247281A6\
+FD31613DF6891B4C17B7A6A9AD9B77468254B93F85958AA0F01CEFC10B25169D\
+C46E035D3F24557B4BF0E7D60174219108D916FFDC55E25BFFD9809EFD058E12\
+C14F39C69D8FB73D3EC6458F47F2F8DB901BA76C86550B11B54D0641D4DB3EB0\
+00057DD00F2E511FB7A47E959A4402A3AC5462234B40B184020FCF7A0396C4D0\
+0A987C8741A4537BC17102A5C42AFEAB9F71EA66ED4CBC7B5EE682FF04F56F4B\
+A1EA0BB326C4089930F9E3F3FFA3E06637CCE32113881A06CC3A13837448145C\
+2BD01307A580FDBC385D8F46FB92FFEDBC8918D269DD1871164D4B3E2023441E\
+C8B99C82A5F09821CDDF6B38C9ACC3BF3A38D5628016159588C33EAA29D9463A\
+537C000A16AD8C177DC4CF716E625F46FC4CA8C19FBD8EF320F1D680639195C8\
+B195B0A02738E0665F4190D6287E589CD6DD45B9E8CC23B08E1681BFC6F66B88\
+DE6B091E825EA4BBFBD697E10BC407570AE4F2A3EBE569554639C2B8E051656C\
+C30C837F5A92260EAD1D552B45801B6D28134166796C87F900225CFDC3CC49D7\
+2DFBC18D8D95B1E160ED3CAFD5C3467D48AFF87402CBCB1E1420E3FCB588AA19\
+C8F42753B59DB6FB6A9FDBA127CA806DBA7DD97F2488FC2E438EEF57A4CC85B8\
+8DCFDE76AE1FF61225A1CA8BF4A14F729950322EA681B16D6492902506702DC8\
+F348E4D3AE7FB55FAC1231FDE82091B34F1791B6AE37587B10325F6FF5E23B85\
+5845B86EAE90785B9D10D90A16644D01BB626F343B908A9591F4069B21822CA4\
+ECF985C1E710475F33DF9AF4764CFB0FFE649063775338F15BEA7CFF29F16467\
+8160960A80ED148C9B7FAA58E9139911D3DD9536F69646F718F083DC9029D629\
+4FC4C607688AA75AF350AC2C0B001A157D023D73D86ED8133809FCB9592D1208\
+9CBD7A1BB6BBA882FE227C09A53FF088907CB4BC2FB4B7F62D41D3D397C4FE0A\
+D12BB3964370E21712951C679814D506E738C0201E42181D231136A435AE0397\
+B61CCBC5E8BBEBF8EA77C8BC48BD6211F29248F9D498D818E2B544D28A5E60BA\
+727F32EF4BA2707962230C900076FB764D0ED5CE078C9DB14DE894BBB836C6DE\
+9E83202AE89F9A8D8CB0341E1C81B5FA8B16731B8E231E969C0F1EF95336D4E7\
+3EAD6DA23DE3AD1EB608ACCE4D4D93996DD76EC1F5F2C576F6B3B76E07BD8A81\
+0FF5D88B00FFE48C42700B61CC499336E7FB57AD72FF44FC631C7222C9A3D1AB\
+F6E77B5ED7FE2F7228FED6C849BF7142C4103989A80F7C15642AE61650CDCA7E\
+854EB25E9E72F4C3E3768E6CCC8BFD556B56D3507EDDE9E5C331DDEA75568B07\
+813D20E8F4C9547838ED28448F2E67158ACF0C00B131473847816C5E2DC215:\
+7C39A01E12C91952FF656E415AFE80CDAAD576A87966B49F93F53FFA9AEFAD4D
+
+08944CB473B828B118A31986DB67FC757F238182E790553404B792AA4F0095A6\
+A83291E287CDD16521A3AE8C48F56FBC909DFCCFAA7BCC570C2159F26592DCD6\
+B15BC4DD55CC05595AC634B2C3DE15360B0F07A03B5957BC9333CC5097919399\
+DD9973ACE15E55940178C4C96BB5E0A0A10BAE175769548EBCE11E0D7D9DB296\
+47F197D4B87F7039F5D4E59E016531DBEBF55A797AC9A6835032CDF34240A7EE\
+7423E89C09124829CAFC5F89431C8AFC54FD979E50D48A82B47A53523C84B600\
+4DAA323EFB708203E5388A6A5110C6CE2E341048A65FDEADEB3837A03420F9FA\
+DDC3F02A544F1E46D96B07C90C7971A7040A179E8198E90AA019268E00367120\
+D5F3D98A5CCE82C885E77144B1AAD66EE682847776B04F01F501DCBEFE390308\
+0A8058B3B8F1D823D917ECF31FC2D5B0795BF95A55C7093ECA7C801DD0BD0DBD\
+BEDE7D56513128B29FC0B4D25A6240B24C99E017BDFF7ACAFC8F8DE9FAF5A294\
+4384AECE82BEA04DCCC6D51FC6E6F27AA38F131B7959B13681A09B311D242E62\
+22A1CE5687DE5C080508B1DB16B6F8290D33A3CC0D0138AC61FD9093825E9D37\
+52889E9F20DB9F80F92750EAC88B38AC81C0016D40371EAB4A87E845E91446B0\
+A07081B84F559CDB95340CB020AF22AEA1BFF2FDA12F7A42973FF163A1C6F33D\
+B8B8214AE27ABDF1C54F5B03E29310FA210125E1296E8AF93A2996DBAEFBADD4\
+C51C2C3B8A3E2BC9FE060C42BA32768F6992A99599206CD2291CCC5BBD50856F\
+7F8D2D0AE1EFB5892C15A799B77482DE4553736B162ABB06631F1688F6746E7D\
+7A37EE7EF24E6CC901175F04960C01990178F81E957E941DEAAC8846B3704E24\
+204F43DDB0765C433F3F7D4D201459CD65682B7DDF3D47E95CDB31B96A4CB229\
+07F08BA6E92A4A07703B2DCF150F922C4B7CF181380303FB72547847305999C3\
+C8F9AC877D05D9DC4159DEB8A13D36AD1D533A56950E20F906D29D51DDC45BD1\
+5C1773991707480E37B827044BDC6473181B760A9036E0D3FA491C2F08C55130\
+D8CDD5AC8E97D0813164AF3D28A585F0C2EC7004D498F95C6B62231A632A56C2\
+D0C48FC3A6992D4051957B9ED6D9A86DBCCD962A8883CF82CAF01DA2F51A203D\
+56B6089BC8FD0B1BD414C8063031ED469555E22EF872689C130B1C101034D572\
+FD8CD0EDDABEC9EF1503D7F728B0941EFE2B9512438C7DDB176BE2EC2D9FFCD5\
+6495A4511428DF02819CDDA18D1ED5D3B16C6F42AA0AC681A9FAB51E8A1A856C\
+15C51A3EC1031427142EA12543014DD4ACAC640B8A7729E63AB7DF1051112CDE\
+FD4B988A2258334FA9A7F5B3A87A02074B9F69DD81B83FC74089A91D76AA4041\
+259E80FA255F2084902AEB9E996AC2288AB464BDEC47AAB26A28A2A819498975\
+5D48FC9A5C9279285F2F1DBB8B8018F3E4E13115D78A879792E45A8F4F24ED4A\
+317440BA63E6929056EFC1D2529B75A709D6C0097DC2D97F646F334EBE6195EC\
+5630132FDE58E25DBC17DAD822D9FA0938A2A2C926B105D108403DC29CF371C3\
+504FF73BCE9C7ACF9A74C4954CE6A32DA96B21CF3211B3E49953DAB78C49C3E5\
+32A349003C59C62F7D40261CBA63A9EA21C89A38AA63CE431C43AE261C4D9999\
+B1CAF491FAB8E7BE6E8C3454F1BE8793B2D27141FC107DA599A4694C41353D77\
+85C05B5E31440458D17C6DB66FEB8A9C5C073FB946A67AC0312BB669D9B12FAB\
+AA5272CA6631379EF4ED420A4424A5CD08526384C047C33A84D5D7DC0C215366\
+3B54C73DD799A3568C01B818992CDF8143F1DADD6B50CAE6EAE13AC66F31FFA2\
+B362CC4D2880592B7FEE4B9E4CD6AA5E5DE27AAB9B5DAD9F7D39407AE927530C\
+AB2B61CD7394A21EF47BFB813B5EA6091458D239664923280ED0D5CCA8285BB2\
+281A2F9FB3FFECC8E9147E1E8FAC957D90C9E5F513738745A47C2AD0C31FD898\
+6EF3B6388C6E821F166513811D547AB4336B5E04643497FC9F8D6E380EF6478B\
+82B6E2F5F65DD98A63C68C32B94610E1D3B9538F13A7688FBB1EC3448BE9BD77\
+BB93A34546172AE8D614F85228988E7FEB18C9A0C9827699E8B3CBC69750BDFE\
+CDA8268F694F4C509BEFC1A1166F85C829725299D173F867A300987A2D36D1BB\
+BE37BE3208FB8EFE9152A41A5F0E931B6382FF7F9B18937958FB180E61F2A8C2\
+8F36C3C80C3722935AACB81C24AA17FB3E7A1026F7031A7449818ED62BA7705C\
+A27C2D3268F90B6322921683DFF800A306CFC186CF2A61B37F35837B217E3B2C\
+ECB0843D84EAC67431E3D689F01522D4A4C73618B7C2965C9DABB15C0BE637D1\
+0CEEF72271CF39A7B803B41767BC34433C3E6FF449A439AE13DA1EAFA038CB9F\
+2E1C84F1CE39C05DF56FE3D7B82386C4E628B6E27CBC5D575C66ADA3510C246B\
+D04DB48F4AFC2D7352966DA2266C2BC9831532F53655D8BE42B421AC0D70D8AD\
+1D3587257886DBF93668E907E861BA64F45999BADB0F766EADCE5238B5ED397F\
+265935194812C03C5769137BAC97140525303CF48D65F39004A3F59B1FAB0989\
+5CEE05335D15B9B12265892F4ABB92AB1DD2002ED00CF3562CB67DFE1055968E\
+4AB3306BB34BB87D0F64B26848812A2F7B50424A21FF94081A7F70F7B684AB0F\
+092B2B085DCF84CA38414CF7290F607BF79C37EA84253ABCA8D4184D2DBE2E90\
+0200B81479E1CE8B71DCF2BD6E3C557A8E431D627BA669C2EA03068E0F7EA62C\
+29777B22142D7A1D451BD541EF8EBDDBBA4E3BD8FFCD340E935BE7C66EFC14A1\
+3EA48134F655B0DE3180101F09D204C379743A357E6DF1268B55A9F7524398EC\
+F3A59849A27B142239059998083E8FA91785E91C4D220B2FB17E3389EBAA384A\
+49D89B5D78136DD2454F06CDE9837F096B744D53221127869904AC227CDF30BF\
+EA78CC5545583F999B9C42A1184E2FB9FF3EC095B9DA0D138205C4EAC4C8C480\
+C43153608849F63E161135C79D8B6C9CFE9B8DFD8AFAB559D8B595DDD4383503\
+3B4BBD391E028BB2A60832D9B697EE61408F149744DCE71AA11BB2B0436C1E26\
+26AC3A27CDA293366B90B9CDE2D927855130758D3946B867192DCF3FCE9A3B9A\
+5276E8C37B8CB136FC90A6DC22650F95E796A9886EFD3F424BE63A66DBB1041C\
+B3D4A06F4E7EEE89F0B6D15C36F9EA010C66B332011C8888E8E4AB2B3AB52231\
+91E1388613A0FD0F07C1B26D7CC7CDF1AC62A226454D6291B431CC3EF2DB2B24\
+42B37DEFB942117FA247096BEAE598611B8104F37BEBEDD8BB8B949A89B5BF8E\
+228ECA1D8F16BFEC75A02FFBB4EEE3A6D4A6087C43634D675311E72A9F3253BB\
+5DD364E07EB4B9C84F586BA267BAFFAEFEC79E03B83B18595FE06D7E063EE604\
+FF287004D141C1A43AF0CA7C5651D98F633FA875B4743353FB07BDE59B6567AE\
+25F7095F1D9EDF30570E2F7D7EC194216898D910F9E295A41DFEE072CB56F914\
+BB78CC9854129250F9874B63BB3EBE9A1CDC6EBCB0916E1C440354DED6AA818F\
+2811DA913912A21D3961AC94A39F0827D3A419616905DC45842C8E69A43004B8\
+AE922C8DE1E8CD0668674A7760153213835BC63FAE4F8D65614AFD74A34D42AB\
+AD5025B884B34639340B45D49CCED423771916E18AA077291923017CA50795F3\
+B7A3F349A3D29923833CE57801C631576E23B838A7767CA1BDA92B82AC502DB3\
+688FFC83C09A4E40CAC31D20D9D32FA6724A80BE7091CDE9C7A6560CFB326B46\
+7CADDB9E9B7A491EDA283EFB0B61B4A1116DD859D5C0897EAA2A3FB2CD82FFB3\
+3770BF9E08091363B6B81D23E61C2A647D2BE440C5C79EA89690656D9F10B1F0\
+7942834E1CB6E2D2DF106EB6D6A21FA23819E65028515E88BD279F9317BEAFFD\
+394EA51F8639371C3A89F11305A4CA35FB0711F5E2C7C3DD1659C79024581211\
+3204B4ED8AAE9FF09D43C6DDB13F5070D98831B2C7639FB6B9B01C288812DDFA\
+8861DB32DC8268C07D30CF969953042B3DAD530D9D744C06AABE7A886C0FE57B\
+09B7F42D193FB3E9C06329818251A2F7E6474462C95DED:\
+918EC37DC5D2FEC29E71E89A04AC10B3A4AFDA3045532E104BCAF15003A785D8
+
+1A3DEAFCE70AF6F3F55D66AD9CE78D5F4D5C5F2638A810AFCD07D67E9F9A1380\
+D6B34BE482EF030C22F1E978F544609CCE35A74C5109EE7038495B6210CDBCA8\
+DC82C6E9E7B0D593FAD9665382B3C401AB8941DF71307DD77EBAF140AA66A1F7\
+6316478850E58886A9610631E9C722F459FA00C0B53124FB4F12778BBBA37608\
+26D3DBA67CD030A96B654AF93F8E395F5F439549489F8161683F124BC980E693\
+9C83A6085E4B6CAAF8BCD89A0E01ED70DB487166CC29735D9235A9CDC57B80C9\
+C2E591DF6322F5BEDD32937073F781A30389552AE83FBE147D1B3D3461A3DF96\
+C15CD96900C56718EAAE838417057579115936862679F5F2A45DADF65D14108A\
+F1641DF987B57986384FA1433789F5DFBE87E90BD4E9D8D4D0741FCDA7348322\
+B967B566B18612DBB8FE64F151947C3F7E361EE868676BCCD0CB3A1AFE046BE7\
+0057A05ADD3E65AF31E3FF414A627C0183E8FF583B41B75B203650420216E6DF\
+CAB289665F054CFE3EA0943647528518573BBB1D0F27E1449E98739EAF0D0094\
+32DF0C1EDC1625264B94A71DB762659FF5A3A7A867F182D1F1FD34B341A4A181\
+221870DC4A494013091A7E3B2B07E0160C438F1EE1E8A2B989C4FFEC36B5083E\
+A427606767C29672F44779A8505B422B25A56907F565B27690D011426A62DF00\
+36D57D967CD1D14E915BBC2691E7AF818C769D9E1F9EDD40894BE88FA1D7A595\
+2AFD898E837716ACD73953BF2D1D448123FD1A0276D2C2EBDC760A4B787416CF\
+AE5E963FCBDC8B551CB70F91DA0ED4A8090FEF178E879F2C34F3A269DFFFF097\
+72D44A13D7A17468B5834C460957D5243C325F63F05F89D4ED98D361E7F0AB8A\
+83948A64D0CFF8514841AA21C7F337920A9983E59BE4A0F1339E1E462F92DC1F\
+C070126206012458A499A8111FAE078E00B0CA3BC1D6C7087CD318D5603C1C7E\
+0425E6F729CEECA5F35B82F8A42E0E9B950EFB0904C5FB5C06D91D239913665E\
+D1F1EE4B82185A01BA86CA2D3EA94E5A8842231A94C05280183B7ACA28998410\
+3F122203EC2FBA4A382E6F5236D6F68DA05E3BB0C558421F0EFAB91DCEEF6D1E\
+CDC60F9B88F8BEFE31CDC3C2F024A1AF2C7336AA5D151E8CDA814A5FE898BADE\
+B9DD680E337E682EBC22BFAE445417E37D2D89A338659A280AB1206DB74DD42C\
+6F25639C1803BFDF2156DF613B0F5924D209F7F9003CE8794F989F4F27B82121\
+210F4F65EC5A1F7723305CEE438C41F793EE04496BBE337BBD2FD3023830B1C8\
+889C6F4D0C1192E364EDBE1CD987BA5D66224EE9C9405E1DFCEC0EEFFC5C73D3\
+123F6731C6295D1E6B854B884FD22B6A3BBBE5395312585CD138BCA67532C6AB\
+71BEBC6657C50DA87D2AC6068FA3970202C5E15EB7B4B3D2676C0134BCF1EAC2\
+B26BA46930B5E660B16060894884C88BFACD6779276B86F685AB6F17C6D53F62\
+1275FAD66D021D26D1D480AFAB4B5EC75E0E763FFC45F599EA02504DA5D91EB5\
+EFC3E4AE196F219E45E7CB05594958C876FF474A020EF73C1F09B1F7F7457E81\
+6D3AF51D86663D4D461754CD5E907456691E02446D6CACFD33516206A3187054\
+3D574592087773653D4086C2BDCBAB3C9B65CA11AD0D4E58DDDA8B4403099898\
+57103929549B7300CED42651D4086661694092C42875CB62858E6D1BE5F7274B\
+4BCD83AA4DA05CACA186A30902830790F9FFA24418E1F9DB00FA40477E83B05C\
+2D11AD7D81DDDB1E31F94A9DD5E9E13391C22479B570976E3AFC1BE41086D3BE\
+6689D87CA4326A7CDE8E5B396A678D3CDB2C80FECFBA2BC799AE8B1528E96D88\
+0CD098DDE910D097EAAE660AD4D7EA51C18F18AA1B39614299A172512521DFD2\
+31B9840909839EB69C892EE23F1BCEEC1FADBA75786C7DED93BC9983F74CEAB3\
+97EB8BA84F7E4130B34258D628594A6F9E2348FD91BA2594E07B8057E8A2AE3A\
+DFEA0EF919555385977041C5B6DC4F3880569171F7217AAA9A85F2F5BBDFE3FF\
+DF79248F2A35FD4DEC34980C67290339B1C0A5A6AB8838157AE2F5140B4A2492\
+4A6688AE5CE72A48103EE9029CE8A0F15B1FBB19A12FAAB80A7CD9C0E389FC27\
+75833E3190F1CF735ECDFE7F6B6C326506AA82613CBEDA8DD3691B81F4C1E3B0\
+FC32D7E6719CBFC12F4A26E0FC29D6417953ABC9568DB4ED9A294B9FD5F2A666\
+DDA546ABA301B1C60985033953EFD6F4538333B5C7DD3148814A3FD7927C366F\
+40B3D7ABBDEB2332DDB586AF80959097663CFAB2FEECAD6D368AE10EFF9663D5\
+F8BAB95935D25F45776F7F04B46817D05165A9DD4770509ABB92F8B9E7373CA7\
+80703569981754A51D6D376D65C57F55CD70E2DF5FDF5A6B829AE30CE3BF9428\
+15C8B4BE858DB58151D02A68AAB9FD373E047EFA51BD1A0CD1B61744D9E97CEB\
+A3334B3BAAFEA3BC9E43AE097CF2C3D713EECC247FF43EC74D54907D8BF45E45\
+B2E0E11D82B126A8179D3F66C055E11F69EA67AACC5FEE8AF01FAA379E51998F\
+5070F9EE0FD30A2EB22A925586FB1B39024EB5EB1E127C76A149E7F02AF1B73C\
+16E9E5A5DBE378E08A9FADF1194C625132AB3FDEFE8FE9A89BB8E0035A1A3AC5\
+278F5D3D0ADE0E41C81C6853A41C4AC45BE3F68180FE23F27F18BE2E339DE1D5\
+59D75DE63ADF7A32BAE42B037AEAA3E123A5314891BCD35CA48D57DF4C17540E\
+97202A8EA1328DA25B1FD6BE2B56AEC1E5DEB209F3B7A13ADB1CBE53EB645956\
+E577A7621D74E42376D70BC5C4AACD239A852FBB7B3F62CF59FE10438C1DC8E1\
+E46566325DA0CA43AAA63FB7E0B450A2DB3E3A2204704D894DB24B72B3078106\
+E096CD543DCF027650CB4965E38AC36A8AD588C5962B4E26548AB88F0BC20E10\
+ACC1C3FC00EF415B3C32499264552B14E2C0E789A3B8A8BFF9620FD939D0B34E\
+806177EC696A4B3B1CA4B32BA979B2690CFB3A6B17BCEE6877FFCE757E4116DA\
+01099FFE82ADD5A0C593E73449A96DB9CC2B9E846D166B095174F2CAF8B35DD8\
+78C836D9BB6EEEAF8E1BC5D0E149C739828CC480D731DC16B35B80D4AD82ED7D\
+29BD05018239EFECF8DEAE180C6A459DBCBFE4AAB9A5E2C1E1BC31418CF2EEEB\
+31FDF8BA02C9A91525E9163F672BAE2EDEC38C1BDB84EA237B4EF86BF5C0F0FF\
+E178E3761E82D94F66E5EA40BA8170BF768409E1B4177AAFD9937BCE3FBFF590\
+320D7C445372463FBBFB34F57447F42C16E026F179CBF82F617C86D1E8D42F6C\
+908F9C6B77E38D25D51303DBD781FFAB569B4CF31FD0B947C45E1768A2E9DFE8\
+369F520DC38D77937B69B821DB4FFEA8F50EBC404F0587B5598189F54B5A5B98\
+966FD16801C87DE2C3C7813DD70DC600824D426D88C55E89D47214D59206A7A6\
+5A65DA7CA2E42FA62ED17E7AA5B3ED446BCC71F17FEC8593BE96D2037BD07F94\
+76D4D732B32BC5DF8C921316B45699004716FC89F8D45BAE402C26DBCDF1A340\
+847B932FF882DBEAFBEDD252E126C89A1E1FDD8908A1F67D15D8E432DAD8E08E\
+950A3BC46B96CB89CC5BDAC703B3FA3E986EF1C6E7E6606E6845BA1EB2FBDCFE\
+E744B5E45206F4A419E1CB103C8490EB293EE9AEC1F0A0D294F9D3847737413D\
+30873F3C94740E8FD072817815EBBCE3F09EDEC9D1211A9E99547D620B2EC56C\
+89E9CB8144AE9E46636324BD13C6CCA3AB9CD9FD8F7F937ABABC598232384427\
+A2D4CE0CBF9765F7225E208C3CE128602B0AD08A1BAAB77EDB3111F0C6CA7BA0\
+EAC9D89D5B4378EB82C17F6EA08308A79A53D150D3F85EFAB77294F02EE0E288\
+5EE2AB2793392B87DB11FA77992F5B4FD75EF2F1A822E87407A4878894215AB8\
+9B6CC4A120F5A78B3C31AB80FFCC9ACEF53FC6F7F85685EB9D56D30D87C21ABB\
+F1652EEF8F32C7C567BD1F08623B09C29F33561D42727A5649A3850071AA6C11\
+735AE63C4FD31559CE560B27A362786A83353FE460B37074664A9421D3B2F6A8\
+64D5ACA087187B27E2B82F31CB3DF5E985CEA271C609B94B4E58356D40C7D5C7\
+FF2E5990FB39588154843EA5FCA92F120075D4C4D006661A0FA1B0585454BEA7\
+25473EEF7D58117D5840C8348999003736C5EEB7858FFD273A1C3EB2812F5697\
+C59110275B08F6BEFBE84C92497D5F73B7B6F794A849713B23AC5F29D5C7112F\
+B2E7A6E89EB54DDFA3122E6C79624C1BF25EBFB9FE5CE6DAA779F3ECB2984DA4\
+2F8C6ADC77B21DD291E684FCA50E46070962A2D4F00813D8DE1B8ED33FED9715\
+180C7EA8E2BB74FA65D9C7F6E142F3C81CDC59172E1020F62F65CA5A12CF2BED\
+9DEA04A4D8CABC2948F7BE823A3E792625275B3925A6C8D8E2B428C75A5DB0F7\
+120278CD7D6CAB768755C7FE2FBF89FDED1FB38AC7F76A2F8798CA36ED42CB7C\
+07F006271205F546A4812C20077F050D4CDC79459FA686E97F0704B7A9FF7DE1\
+6318E862C53D361BC635A55A264BE15016545DBFCE3C6D6849576ADEFB6884ED\
+D768214E0B438B0231B4F2692C2C0B5C177674F8A0DE236EACD9E0CEC7C8647E\
+4E9A5861B957EC834A2F8572F01304C3FD6A06019E5F1499B62BAA8670B65246\
+7FA9A4F10F053263BFE9743CC7D933F86136AAE3A6FB56754D7D238397A0030C\
+EBEA87CB255AF36138C373DBBAC41DD4A697032E4796C552AD9C9B3FA713C3A4\
+E09E0EC5581E94BE7F31065157662F9E9C678B1EF1B8B8A847C51789C22B1841\
+BCFC855820AF3258AF9E08231090B45D10046A00178E89BD515616B8A44E77BF\
+57795DABAF40687B2CDA7A5014168F:\
+446D6A62F685746493DB900509FB28B14CE9D0005C0769A6193D43853F5B7593
+
+1633256AB03B20CE079196B708A1C02D1B6072219070712C8589EE21341D5075\
+2ACB6CFDA17E982D828BBD6CDF54BC7232FD418A323D64939928597B9B52F07C\
+F488250C5E42BFD3AB48012D709F8D747225839296386FCE5FC5AECC4BA7A107\
+6D089DEA8ECEFAA0CF66FCA8602395719C12A04F929321784D7AB8239FCE2FF3\
+BDAE046A266132B5C2AD9F7261F3014E87B389A6695978693D9371D0B1FF9C40\
+5F338C2FDE4687359603950A54CF4B9CDD9B24480B239ACC5405C14C886BBB03\
+78391CEF0662A38882BDD09E3866AB9A66CFBD28EB5EE4F8009BDEFC4AEB1670\
+0EBA7DC557B489190A71FDA75E85F7EF841697F70FFD4FEA185E7A67C81C5B8F\
+273BFB97B2CEF695C1C74446C4B425BE6B2E66DC0AAACB247E4467B7C7D84EC3\
+3B6B5AB8FA1979F503008BDCFF948CDBF1226B1B066CBCF34797298F3BA8C60F\
+A01E0AC8B803223C656112FB91435D75453BAE4707B63330467DD13E0A4B992E\
+6F7E46995899A2D95D23F4AC3D0802B2A6E7D024DEA19CA408C4BBE053F14C9C\
+E264F129724A18BCB18F385B1CA091A11434EA96D98C8D0602E98EDC8DFA1414\
+1AF93ED0BA66E885E9FA108591AE59E109AE34D6B9F5586E4B4D75E7DF7C3295\
+8A65E88A9BAF41082A0A3F11539DC4EA2CBD9E1C6C3C439B622F1DE574FA7547\
+0C8C939B51D2D1C2A7204B859881D43086BFD8FB90346218D099C5AB36846F3B\
+98A7C847318BDFA01E09717943FCD864C5A8A17B6CEB89D98E872D388F20ADC2\
+BE5E2006846904F41682FB1283214F3D20DBC9FC9E0FF571844A1282E88590D7\
+C085B2C568EC5ACC4462B389FEAA5757F7033187E2DE31955FCE55FEDC909255\
+048B327CCAB2E582BBC9D8054BF5CB45145C7D3A3AF9CD5CF6ECBA490C634ECF\
+00E646BF95E8642C43A4978EF08A574EF1F78F6CE57C3B34B5A123D123617FC8\
+EC9B2AC0F9B70A7F6062D38DD7B8E9FB4ECCEF13DED5C0477483ADDAE4F1CC0C\
+FCA274B1307ED0DE72FBCB819154CDA897D7575213042615F1741A8CB646A39F\
+8D134FDF9E60E000EB8220F65CC30F5FA52C431B9E3B6101B96E25B8D0440B96\
+E572A18A01747C02AFCD7513542F7AACE194632099D16274F31EBABB60DDD94F\
+E43DACCE900EC0902EB5E686D48ED8D09AE63DA0E15C736809903A0297A92DE8\
+4E0260F11F446E1FC448E0EBF59FAEA3C726F97925C57CBDF85B1F77078D3625\
+7C85D56CBBEDCE180FE12B687ADA2DC9912FAC60334166BD2CEF06B089ED5C95\
+63844D71D8FEAD2F3A93F3C07C52537336A8A70BF5B596B9007B9FDF2D082000\
+F20E6B70D2A7E6C7ED27C4146895A6D85A246F623C1B9258A2F891F823ADE4CE\
+FFD59D4FFAD077351E2F506E9A5BDD3900F0204B9E8969AFE72F5DCCB9CDF986\
+D197AE4C4DB53014041AE6221B750E5290E307AD292C8DE6B899235212EF8CE9\
+54785537DC9435AF11E0F3427A9C7B22EFA752EA0B7EADE5F6EB4093BACB7867\
+6E506698139E4F774423B8942166F9A7D22480D814FC0AE19CF4960FBF6E01FF\
+A65C8DA5BED4F1AE2B9ECEC5BE7B3C38DD4045B0C93EE6CC77A7E61E85D331B2\
+3C0D164B104518B3405497054445A353E9B48F2AC5E8E96298D6655614336CFF\
+E6D8C9C915E387391519AD2632366AA3BC935030FD12927EFCA17505ED74C946\
+50C778539004854DF6C24269AAB9C273A493D3E5B0B1D687C33C2FACE46B4BB3\
+742D6DF743D09164D2E0EE7F6BA128BD5FBA2E3B33C199AE80FA9DEE3AD811D0\
+2BAA3D42A6362B2AD47BBA8A2C5CD00B46CF22CFE367281488A4852EB8B7FACE\
+79F0CA6F8E78D32578DFEE01711C4DCF3C26D0BA13F3075478E708C5C5315AFD\
+C2E4C0062D16458213BEC506A9E991A61825FF78DA9BA1BAABBEFA56B4A8C9E2\
+E7B60EC4B7B541C8E0F79C86BB5F03F736761A37169B2AAB8884EC6EA217B02C\
+59035F5BB327243D126B78D4AAB430212439B5A75B80618DAFEB66AA3AFF866C\
+4DAEE47D374B512E74ADA933EF24A841BA271C6F02C870E8AB950FE06E93C91D\
+F0E99165DC01BCB190E411ECCD85358FD4A88127A22E4CF4266A90845124BF97\
+B25D7B1C46D3A0D68A684F84E2A638C692A52CB6E8C651A3AC492B0460004073\
+D5349E35552359CA37660F77B2770D6B2B3F7B1922424AC4A8598B4C61A6DB50\
+7608A72A6A7D573CC055206276E14005A28A0EC41F28D7E260611D40F089FFE5\
+E529375691412F4E9E12E62C3BE2C563C26D2444EA9C69E6C935FEB4DC4E802E\
+5FE3906F8ACEF4798D940C3CD574BB5E74506C3E0B70CB62454A25F589EADB6B\
+0709FE3B50417CD1D98F08E08B7CF68A04CCCF8D6588F9FC2F31E533CDA6159B\
+AA4297FA446450D71C16EA2324EC09773E7C8817ECF680ED12F64A04863EFE3D\
+9D8760F34DE5B0860B3991FF0EE5EDBA22C4D69120DE19D5429E4AAE91C9E7CF\
+05CC807159A58F13B480872AC1609D87E7009DEDB71C09CEAAB640A2B6135855\
+CEAE4AC2954933A0255B425D9FDCD9C246F82AEB7C3BB78C6E73E03DB7AEC424\
+5A28693FBD36EF4938D59CCE19EAFC00671A0851612406A075713C5D1154D8E1\
+3B59B7C5B0902239D4BACFA386AC817AC5EE02A181A9A47C622B3ECF287E1484\
+3D452AF347110498A620B34AB4E116308D976062C9EE9CD35DB6CB79805B93AC\
+9A15AFBCB52F1ED4309879D1924A4BA190B0B86E60A516E77D34B4E0A49D4EF2\
+CEF3CC2F410FD8EC901363FC9EBD75EB460D4D8910BDF27CE26A8B4AEB94F9F7\
+6242401DC35D0644842B99FB6C439B82D82ECFE1AF0D01F9BECB15BEC83F13B2\
+60F7F714AA381032923FDE8F8018F3518547451435C9A5207294D08A907C7369\
+6F6CB000745E072E25B73B3EE11595433D27A1F11468686F08094F1D31F5ADA8\
+1F11F0677A29D72EBB2E1C4792CCC607CB938647E1F153F9EEF03D982595C631\
+E49B6B7C1FA003A6EB8D59CB8892CD0888B05240F12701753F89007C859515A2\
+FEF944BC60B36003A26702AC6FE04D2E942978FC31A97EB29871D6752399D352\
+1720729007B6A7215A4282B2A4EFC2C56BD129E74C9B00847692B96FCC71CF7A\
+7F19F3FD6B45C519FD73B4860880A2DD74E5727B31A93F0A87F0078155344AE9\
+F7BDBF00D83393B634B5DCA88A398E42C320EB95C4A826ACEA90B65E4767B2EB\
+A748F97C247568393E2FD3A66075CC12935B6D7EB5C2FF5282185CB62C73972A\
+37B3CA508004B4F796BDF82B83B5BDF90D6BFD32B5089B0CA2683DC7FB2337DE\
+42E650ED911DBEE1EF98257F9BA5AF54B1A54B04C0087A5A64BA779D86461BA1\
+5337C2E7D4955FDD777A025DE226306A17C384F1C52CDB5946FB0B46DD5C13BD\
+7A55FE2E27E4C6D40D61D6FFC024468F8EDFC7C7992DF5DC5D05063FE7231992\
+24F53678E48F25250EA28BDF1089718EB8B730D1C06735C2F871164E2EB5E885\
+A8DFD2A083BE97EDC94159CE9BF75D2433F1D782762F771903CBF9A1C9D13F71\
+0BA0E151B079DC0A8262BCEB1DBCBBC0F35DF6EECF7BAA7105B9808745853C96\
+B4372E95E482035916B726DAC7BE95A72B19DAD48DB1B19E6EB2EDAB5AC1B301\
+3839E7806625ABC129F41813E6D71EE4AB2040D81E42E6ED73ABBA64FF2EB433\
+B910EA7D4F5ED3D8D27D39BB454EC019DF6114F544D7B155549D0C56D14551FA\
+F353994A80F30F3C97E863A4F2AF316468A568038EB4D799350A6FACAFF90ECD\
+44E0F44EFB6DC42EE4B0DC2C59EA9C1827326DF08C0A6E55CF4F9C3EA0E78CFF\
+3635F5D08E44F1400D20F638D56BA84B4832090454DE57EF04B6C8805A36F63E\
+5CCC6E830C87FFC164647CED20E4C486D09DE7A5F9E4B68D5456CDB22B0DDED2\
+B95B3BCAE529215C2D25D6823C7D66A4FAE0A1E9F022BA5663204F2314DFA51A\
+1F10E11D6D62A8BA6C28B6AE7DA1DEB5B57F2B65D7456059AD9F03DC5A524054\
+DA39DD100D74EB657DE219795E3C45A0E4C762BA22F9DA9D8159E425A1EE783B\
+4B22C250D8894CBEC706CE16D5CA393404FF478F141BE7CC69E45B077BA1955F\
+1F49EFBE4847C795347F703300F672334F490ABF8B644A34B56DA00EC45A3503\
+14B9ADF27CAF7C51CB7DBA0C5477E7D37662F4F23247BCB8F7DD5F3E9CB8BDA4\
+0FA97568832AF0ADC68F71422E412254A6BFC8943BB465B01FCC8DE0B957677C\
+78BC1F7566953E9D2446239F602C682A521C14F741FEA98C7E27AABEC339B6F5\
+B94C78287A894AFDAE971F8DA7C7E4A4C92C8DA47BE82DC2532EC2DA9BACEDD2\
+BE6DB2B2FB34DCCDCB34116507376578CBCA105E5E443BEC0F2EF23BE34CDF86\
+2EDAB34F0FF21335E3ACD92F59688B419F824EA61EEA82BC80E3463452192377\
+131BA51FB0795E089FC077D0ECA8012E58B0637AD7022206887FE9EC00EE5DF7\
+AD2E26FE819EE35C7A179C579098AA3DF645D9064CD557DA90BDD21F871CEB04\
+8CA56DF9653A10ED60F5E9F0ED7F8D89BCF5C22D1143CF44718FF2DFD8E10CEF\
+8AABB67D2305F18177C1426BD4CD03F2625E459CE905067826A214E08E56D8F9\
+455593E6B324E72DEDCC429D3BEFE2AE0599E360DF95E80D453A3A849E48389F\
+A745635BEDE30E7932DE6A3816E31A2217F98D5E40238963D0A36C159FD4EC32\
+D8A5CF59D433DEF3378634AF6887FDB3F3EDB96FC8840FE1B538C329674AE810\
+E8C8B2B46DB208716D38E9D1AEAB097068AD83ADD7DD2647839B3A7388B0615B\
+DE26F8692E9C07D8ADECC2A875203C3D3A9C6CB1D7D06307E9E1D9C3BC536DD8\
+EB271E9A2159C904E61E8C9357FE759F36366AEF5A3D14CEE82913CD2708AA60\
+69369CED763C8E830D70924E82E9015C2998E86EFC1DCE6AC2EBCB49455542A6\
+D7DAB265AD6D7381FFEEE1AA40F8FAC0659B6FB56BB03CD8CAFAACD48D13672F\
+7D524EB9684CFED4DBB7476E99149C28EC08F33BA6AFF839AA178F86B8EEAF17\
+39C829177BA78547AD394136AA3FAD451A11E9642506568B39668B2436610E06\
+EA45FA11D04D3759B033B5382645F15B3C39270B81B80487643913A24F2F1C1A\
+1ED57C85CCDDC8CD6D59B62FA67CC80572968C8FD01894F0153634C88792A7C4\
+A407A4A4CE46CEC5FE5D2569F95A27DE242444EA0C715B357518CAEA23E767E8\
+545983F0D3A4DF66111B4AA1D399CCAFD796D7A80E592D5A51D2B3F60B5B04F8\
+D9C009CA56CBD4DD84127A29B72ADB7645FB7279C9818B2B43963BD605F45B65\
+75A5E2E369E0B401F5EC10EC703F1179B0AB9D4A89D6F096573952E513827364\
+A84D38922734137E969D8167D6959B70F42F2BDA37E4C989ABAA8024C1A84ED6\
+BEB74780927F78B32EA736B9B2B4A795C355C0319811729D9CC399D235197303\
+38D62E16E5035FC52A817090703FE776D65EF9FEF5BA5F4FFEC3CC8E9EB2E312\
+C50A479BDD4E6AB0A56C18C2DF69ED408417BEE28BB41DD13F8366FF6EDA4B34\
+090FC9BC045271:\
+7758F5E55D885FC6B3A5A2996EF53A416080FF804A16D8B8459502A1236143ED
+
+[Skein-512(264)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+711008AEFD2E8E3F2AB52C038A28E213EBE8135A212840F3069BCF92F10F711C0E
+
+[Skein-512(384)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+C952AA1A43EC04F1FD9507DF7D6B5CE4550BFA40273A2B061C653E65CE41A2FA\
+3AE7AC3EE2120AB3DD3E3BE20DD26609
+
+:\
+2C3FE10673F4D6904F27585FC3DF455A678BC12D7D39D6BE4B37F47B80A43889\
+181103BC727A7DB4B4E2D2DEC1DED86A
+
+CC:\
+153100603EA72AC9379541D7D9E5D9D2A29B54CEDCD02BDB254C8A3A967CF18C\
+9F01149D1829A75E57BFCD7061741636
+
+41FB:\
+592F818C26B31F9713928C06BCB0A0AF37A8EAFDB1DB6E4CE3B898C9335FFC01\
+C2EA2BB5878C41FA1C1F880AF6B07E81
+
+1F877C:\
+E8A30D9AEBA2A2FD7D3F70D22467814743E49D0524F290D8ECBF9CE82093370D\
+D2533F7A3C4ED3004CB1A98513CE911A
+
+C1ECFDFC:\
+2F329BC31075B71C67766905F68F0EB69C93D72E01847E748D77E84CEF325C64\
+23C2EB321A97B5B5A44B4E37D18546A9
+
+21F134AC57:\
+E9C0109D2E5EEAD89750EB34678BB79A3FDE8DF016AB71CBF076EFDE0A97C4E5\
+6D83A3B085457A99A9CE8D04E313CAB9
+
+C6F50BB74E29:\
+8628572E137A7A28F8947B625B593E192EED783E751D2AB870B5D89B5CC4D60E\
+8852407345DF72C1434A13346F8BA85E
+
+119713CC83EEEF:\
+C80B465E10874FC36D0B9AF63FB8098D60012B29BCDDC850C310932D2DC4F535\
+E8E2E9782D31F4224ED9168B42E84A14
+
+4A4F202484512526:\
+8A18298A96C9BE26F9AB3A4F40A1666BB600CD1F8642844CCDE01F503894D808\
+C7A8B6161EE9C5F1786B0539B0A837F4
+
+1F66AB4185ED9B6375:\
+EC505856949FBB7D127E9A3A3E51AC5FAB3183F5604E44173F66716A2EAA9F64\
+4755701EA5157A2410AAB122BA76E28A
+
+EED7422227613B6F53C9:\
+9C91E8EBE46C9CC45F525B0FAE5C068BAC1B1C7369BB11B43C28625E1450EB04\
+0F3933E141D0B80A4FDF03163E2FEC2B
+
+EAEED5CDFFD89DECE455F1:\
+89933A7AC0C918294F3CE51B1804A474CE17531653A2A1AD821A898644368F79\
+3BD3F483B4BB5E3D9C904E299AB97F71
+
+5BE43C90F22902E4FE8ED2D3:\
+90BF8928E882EAA602DD001425866B7F8DC6C30F3BA9D015EF5A628916BADDAB\
+75CE2A77CAAA78A37524F16815349387
+
+A746273228122F381C3B46E4F1:\
+4E0EAA88A051E5B285D979839D1937AA86F32F5251A61A3D37937439E7A46167\
+D68C6D5AD043FB25D5D81FD9E5C0810C
+
+3C5871CD619C69A63B540EB5A625:\
+5A53537729CCF9F0C70C7922B2D12AD453093085412EDB25369DF3388DAF2DDB\
+2D9A22E5E87856161F0B743D0B745B2B
+
+FA22874BCC068879E8EF11A69F0722:\
+BF679781E632FC0129E1A006D618914AC66DA06797410BEE173FE1F88D4D9DDD\
+BD4C33C6F2A8541638D26746776B3ED0
+
+52A608AB21CCDD8A4457A57EDE782176:\
+D3B4BAD4D127D4D29F0965F115FC9733F8067DE731DA317B9ACA98F4AE94378B\
+73C0FC60E3871A0711332BF426E0D60D
+
+82E192E4043DDCD12ECF52969D0F807EED:\
+05365323208EE5ACFB02105C2D3CA3458202AE8DF6729B0741695499CA375A54\
+0AC0945EB270B3522A6DDA29F53A7C79
+
+75683DCB556140C522543BB6E9098B21A21E:\
+38F8A4070E589CAC8CCC2F2A419524E7F966F91B13B298B321130EB9FB712ADF\
+064929DC6873F4DDCDF56D409F8DCFF6
+
+06E4EFE45035E61FAAF4287B4D8D1F12CA97E5:\
+A3C489ECF7B545C25046EC2F65F13D79FBE12F5CE2AA10FA3A61E4DB32F3CAF1\
+855FC30E14457C26DD6F1ED4945BCD4F
+
+E26193989D06568FE688E75540AEA06747D9F851:\
+0A516C2C0FB8A498D15338A930A20FD86618358C53572255D09AC175F2B5751C\
+7BD49A01B4778429D51A3AB61AAC2061
+
+D8DC8FDEFBDCE9D44E4CBAFE78447BAE3B5436102A:\
+F1E8A00710E19E86249A80DE6FA50526E5FBE64438207231249D51B50DEC8883\
+E7FFDE09E8DEBB1CFCE539823B3362B9
+
+57085FD7E14216AB102D8317B0CB338A786D5FC32D8F:\
+7FA16BC2A56730815067F99E76E1CE9DB79F477067D85DDFF59D40E496D167F0\
+04A99C74928968022FC06E348EBCC8D5
+
+A05404DF5DBB57697E2C16FA29DEFAC8AB3560D6126FA0:\
+5F863EBB7A86F7FD6827CF599B8D85E3481F707A5ADFE75F25DF42E0CFB0C1A0\
+CDBA7620F8DC57F82868B46D02DF7DDC
+
+AECBB02759F7433D6FCB06963C74061CD83B5B3FFA6F13C6:\
+E5616D3DD0AC7F52B8E782A38CFE17EF08573A738A0AFF884F33C49427344EFB\
+FD0458213F3AA0C8553732AD11316350
+
+AAFDC9243D3D4A096558A360CC27C8D862F0BE73DB5E88AA55:\
+CCE64A8FAE669346FE91A12889EAB757217C2F0F8C8D78803D8A448A226123A8\
+9D41BF94A083E6EA68CAE3893D794CD8
+
+7BC84867F6F9E9FDC3E1046CAE3A52C77ED485860EE260E30B15:\
+F2A6C9D80252597C7BD0A6BB2242CFA97184E7D20C34C0DFAF72189875114F34\
+2E42A13F162B3E4C3BE9DE41AAFA1AC7
+
+FAC523575A99EC48279A7A459E98FF901918A475034327EFB55843:\
+23E007E2BB891712D875D2A93E33D20FF6B0EBE1F8264DB3CA738E33DE32EF9B\
+CD00888D0E07413211B534E4FCDA44AE
+
+0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E:\
+B9A975DF3113D4A3C53235CAF6D5579A0F4E7B1287AD1A7C37E7334131BFBCAC\
+89697353411FA22787254747C29F16AF
+
+A963C3E895FF5A0BE4824400518D81412F875FA50521E26E85EAC90C04:\
+4B62F5A40F3F919D055C2BCE2E9DC70515FDC3D609D76F6AD861C57B2D38DBE6\
+A57E46D28E33B45BF3CAE822A526CE76
+
+03A18688B10CC0EDF83ADF0A84808A9718383C4070C6C4F295098699AC2C:\
+99C520DA875D5EDD5BEA2842FC5C71FB4DA0F907E07641B232ABFF040EFF68AE\
+CE69708D8889CB00E33D17B0BB43C682
+
+84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29:\
+1A117392B66BF7EDAECB8B082F0E15B7B24F2BD51B3759129082D0E585749D11\
+37DFE717823CE2D82C072014B2669F36
+
+9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10:\
+4E0F3DFFE0E1E4FDB6DC714DBC5822348D9A664F8019F29DA980432AE8BD2833\
+476E4CD51315C665B982D9AE3EEC543B
+
+DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE0\
+46:\
+58D723501857B2C8655C25942CF33BFE39FDD970E2630BB59C13CD3BBA546917\
+EB7B70F551D2F7FAB63A4FE6A78B34C1
+
+62F154EC394D0BC757D045C798C8B87A00E0655D0481A7D2D9FB58D93AEDC676\
+B5A0:\
+4CBE1507D220DEF9571E3DD57BA781D8EE9B18B631A60BD93CDFEAF054EBEB46\
+DA2E1358422B2FBD46470810A861C30B
+
+B2DCFE9FF19E2B23CE7DA2A4207D3E5EC7C6112A8A22AEC9675A886378E14E5B\
+FBAD4E:\
+68917DDE9C73E2AF43BC5CF6CB221EDDF50EE53D3D964940F5CF701A4A738FA4\
+3AD9CAB9BEF59CCE32344DC9575B36EC
+
+47F5697AC8C31409C0868827347A613A3562041C633CF1F1F86865A576E02835\
+ED2C2492:\
+5D515A3F8DBA2F0C386EF2E5AB7178A6959ED1FDDE68068480A303D974DA9B20\
+6787305A9F9004557F51BD8BCD306C6B
+
+512A6D292E67ECB2FE486BFE92660953A75484FF4C4F2ECA2B0AF0EDCDD4339C\
+6B2EE4E542:\
+424282E6EDA3521DADF5822DE0BA07B9A729C9C68FF19AB4FCA207F35560B2B9\
+ACC5FEB9AD46896B1530369ED0161E24
+
+973CF2B4DCF0BFA872B41194CB05BB4E16760A1840D8343301802576197EC19E\
+2A1493D8F4FB:\
+32B9C298EB2DAF966CC0BD717A85FF5C9C38F7FDEB477D1EBE4CE3C4DBEB09B6\
+24DF2B882ED2E083F10E321D1996B718
+
+80BEEBCD2E3F8A9451D4499961C9731AE667CDC24EA020CE3B9AA4BBC0A7F79E\
+30A934467DA4B0:\
+9CB6A4A6A141DA9E807E8210671C089C1856F56CC45E5D386FD95D21F7403C0E\
+743048CF8A2E446AC430E251D99E25F1
+
+7ABAA12EC2A7347674E444140AE0FB659D08E1C66DECD8D6EAE925FA451D65F3\
+C0308E29446B8ED3:\
+0F7560C2316115A49278D58C670216F572FDD987B2514DADB1DE80425F0D4DD1\
+8E0F19B5E8AC9E16F69685ABFBBD3B2F
+
+C88DEE9927679B8AF422ABCBACF283B904FF31E1CAC58C7819809F65D5807D46\
+723B20F67BA610C2B7:\
+C0B9A77E8DAE031FB50DEE1DD298B354C9DF42734D2011D7F688E1C050593FFC\
+A0F9305A96F457E74C8F5CB6B3B52ABD
+
+01E43FE350FCEC450EC9B102053E6B5D56E09896E0DDD9074FE138E603821027\
+0C834CE6EADC2BB86BF6:\
+93B6BA62997D9C73B8287E062F9D81447584A86D324615643D7B69C2A1582772\
+DBF380AD015334C890204CAD1995A1B4
+
+337023370A48B62EE43546F17C4EF2BF8D7ECD1D49F90BAB604B839C2E6E5BD2\
+1540D29BA27AB8E309A4B7:\
+3B471D96B1A3ED28BE345DC04972C73C1409488BAF3628BB3CB0A1EA3F4851ED\
+292EE08922FE3D1E1E13A1BB5580F0C2
+
+6892540F964C8C74BD2DB02C0AD884510CB38AFD4438AF31FC912756F3EFEC6B\
+32B58EBC38FC2A6B913596A8:\
+BCFA350348267A8600ADE6550F6AA63ACEFD4700D7D4A7DEB7F7AC739B5E4614\
+BC67990FD04BA91F4BC76B706D2B0FAC
+
+F5961DFD2B1FFFFDA4FFBF30560C165BFEDAB8CE0BE525845DEB8DC61004B7DB\
+38467205F5DCFB34A2ACFE96C0:\
+1FCB346090BC993C83C070467E08156D13C916F98ABE75A16F885D83222B5703\
+0BF9123E54251AB8D40E53E4DAB20326
+
+CA061A2EB6CEED8881CE2057172D869D73A1951E63D57261384B80CEB5451E77\
+B06CF0F5A0EA15CA907EE1C27EBA:\
+74ACBC7D7CABF2E0935F695C383F1199D35A42145112B04F15BBB45A4B7C3CE2\
+9C74F5D9197C57CCE22C0D6D63335F6A
+
+1743A77251D69242750C4F1140532CD3C33F9B5CCDF7514E8584D4A5F9FBD730\
+BCF84D0D4726364B9BF95AB251D9BB:\
+5BDCA5F769B4F8C1BCE86E97B10FB34DC0397C7E1D3F9B89263A496467D9080B\
+8CFBA643C216D6169193C95F09763AE9
+
+D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7\
+C7F157298EABC4DCE7D89CE5162499F9:\
+7474D881894D358AD131EC542CA1A6627DE7B8C9DD420AA2EE182F1204741CEA\
+B223DFF7AED61007C2A35E043FD7B32E
+
+BE9684BE70340860373C9C482BA517E899FC81BAAA12E5C6D7727975D1D41BA8\
+BEF788CDB5CF4606C9C1C7F61AED59F97D:\
+E0ABA1C0CFF9A8FDB3170ED088E3ABFCA51B3151D18076589AE80DC14DED1CDF\
+E79C6EAAFA20248BB6B14BE958334657
+
+7E15D2B9EA74CA60F66C8DFAB377D9198B7B16DEB6A1BA0EA3C7EE2042F89D37\
+86E779CF053C77785AA9E692F821F14A7F51:\
+1A899A045F2DB571989A28902861F87949D2DB1314866ECBC0533FE7A960B235\
+3E65B03FD5475319900CF25450F82E56
+
+9A219BE43713BD578015E9FDA66C0F2D83CAC563B776AB9F38F3E4F7EF229CB4\
+43304FBA401EFB2BDBD7ECE939102298651C86:\
+F8F99EB34E023F45370C30E29A2BB360F8E68398C6E0257B487414C323A94589\
+C8F9EE7E5BD2DEC7BA256F731EB13D8A
+
+C8F2B693BD0D75EF99CAEBDC22ADF4088A95A3542F637203E283BBC3268780E7\
+87D68D28CC3897452F6A22AA8573CCEBF245972A:\
+9F5E92FC62BF8E9E223165F0EE330A025F2668ECBC55F4481B1F059A872D4768\
+F8B87E3A96A04789F82D95673AB3914B
+
+EC0F99711016C6A2A07AD80D16427506CE6F441059FD269442BAAA28C6CA037B\
+22EEAC49D5D894C0BF66219F2C08E9D0E8AB21DE52:\
+4BEA57BAF0210DF3F0EE7E78DFF504FBB64D874B3BEBCA181408C5A534FEC99B\
+1497FF12BFE32024483F8F2EE8945879
+
+0DC45181337CA32A8222FE7A3BF42FC9F89744259CFF653504D6051FE84B1A7F\
+FD20CB47D4696CE212A686BB9BE9A8AB1C697B6D6A33:\
+2B5A32DF064E646797C9DDEB3929DCFD5BAC33ADACE033E5705C7163A3182DF7\
+BC7F42BFC102899558E7394E03444186
+
+DE286BA4206E8B005714F80FB1CDFAEBDE91D29F84603E4A3EBC04686F99A46C\
+9E880B96C574825582E8812A26E5A857FFC6579F63742F:\
+20187DBC0D197F0348F7AB1D3C0CF63DB29168CAE06BB75E5808B6F5F10C599E\
+C91F7E1F0A676C06423E05B4B379733D
+
+EEBCC18057252CBF3F9C070F1A73213356D5D4BC19AC2A411EC8CDEEE7A571E2\
+E20EAF61FD0C33A0FFEB297DDB77A97F0A415347DB66BCAF:\
+0AFBB0A04C6461E979FEA1822BE6FCB3B625250B1803B1705A9950C8D8029169\
+9B9961EAF333DB94C1F108BDF6498FED
+
+416B5CDC9FE951BD361BD7ABFC120A5054758EBA88FDD68FD84E39D3B09AC254\
+97D36B43CBE7B85A6A3CEBDA8DB4E5549C3EE51BB6FCB6AC1E:\
+B697AA9B197114B0E0EFCBB842764EEC1CE0A7119445C97EC9540F018F5754C6\
+8E1C9DC3EDA22CBB948A124200B87BC4
+
+5C5FAF66F32E0F8311C32E8DA8284A4ED60891A5A7E50FB2956B3CBAA79FC66C\
+A376460E100415401FC2B8518C64502F187EA14BFC9503759705:\
+0F5ADBBE1EC5A2DC052010F955F0C23AB5BAC551EA8449C2743FE2DE28A54F6A\
+1947B06E45ED19418FA615F2AB8C409F
+
+7167E1E02BE1A7CA69D788666F823AE4EEF39271F3C26A5CF7CEE05BCA831610\
+66DC2E217B330DF821103799DF6D74810EED363ADC4AB99F36046A:\
+BEBF06EE6EC90FC36BAA543F28E576D4662D935F87CF763BDFFA1E0B01BBCCF9\
+5CF3E27C81597B165CF6F48D8B557D6D
+
+2FDA311DBBA27321C5329510FAE6948F03210B76D43E7448D1689A063877B6D1\
+4C4F6D0EAA96C150051371F7DD8A4119F7DA5C483CC3E6723C01FB7D:\
+9CFC8B95E54A43B2AE9443CC6468BB033AD4FFEC707D59DE21D454596FC00ACE\
+3DB59F83942D5A79BF99107A33F31A58
+
+95D1474A5AAB5D2422ACA6E481187833A6212BD2D0F91451A67DD786DFC91DFE\
+D51B35F47E1DEB8A8AB4B9CB67B70179CC26F553AE7B569969CE151B8D:\
+3FF0E46D9E71D354279A63A60B623FF3446192D783E385F5DDD33E5E794F6984\
+68FC2089ED46B34327C9690457A295B9
+
+C71BD7941F41DF044A2927A8FF55B4B467C33D089F0988AA253D294ADDBDB325\
+30C0D4208B10D9959823F0C0F0734684006DF79F7099870F6BF53211A88D:\
+7C6D14CB8F178882338D3B27CB91D37AF3A8980C739D492364CC24175C3D9291\
+89BA2355A044279A537ACB3A2C00E355
+
+F57C64006D9EA761892E145C99DF1B24640883DA79D9ED5262859DCDA8C3C32E\
+05B03D984F1AB4A230242AB6B78D368DC5AAA1E6D3498D53371E84B0C1D4BA:\
+4AAB89B4E37850B4C874C37BF24F457FDD49EF04A28F7E6AD5D3CB4A143D05F5\
+C29893CCB881B78082C40490AF0C5067
+
+E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\
+E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\
+6CE8169CBD2FADB7FEF003B8BE1E9744925FDBC1A26B0496D86128FABBE9FAD7\
+6C2272574EDC55B6D3B620273DBC0D6D
+
+16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652B\
+DF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC\
+00:\
+4A890EF5BDE2CD4FB34FC9DD5C264C66340DC47AA8F717630371BC2C9D1558A0\
+42AAD51955C2887FA81FFF50827937CC
+
+FC424EEB27C18A11C01F39C555D8B78A805B88DBA1DC2A42ED5E2C0EC737FF68\
+B2456D80EB85E11714FA3F8EABFB906D3C17964CB4F5E76B29C1765DB03D91BE\
+37FC:\
+DFF1E6EF7D24AC16E6F18D6421818CC9552500584BDD47C30EBC02FC95A4AF51\
+13D9A4F7FCF44457F335ACAAB8159732
+
+ABE3472B54E72734BDBA7D9158736464251C4F21B33FBBC92D7FAC9A35C4E332\
+2FF01D2380CBAA4EF8FB07D21A2128B7B9F5B6D9F34E13F39C7FFC2E72E47888\
+599BA5:\
+BF6DC926A7DBF0354E0F6F488D02B350F58E0F0E48241D6F5C3E49A363728929\
+5942D1156F0CAD515F27BC752299B853
+
+36F9F0A65F2CA498D739B944D6EFF3DA5EBBA57E7D9C41598A2B0E4380F3CF4B\
+479EC2348D015FFE6256273511154AFCF3B4B4BF09D6C4744FDD0F62D75079D4\
+40706B05:\
+672F3F8A1A35204DF532E93D3255E7F4C314649E04137007316776C302917C5C\
+22FE8332434A78E0966A15009F421FA5
+
+ABC87763CAE1CA98BD8C5B82CABA54AC83286F87E9610128AE4DE68AC95DF5E3\
+29C360717BD349F26B872528492CA7C94C2C1E1EF56B74DBB65C2AC351981FDB\
+31D06C77A4:\
+D9DA2B5081202D186B4B117431D716F0A9FF83A7513D918622A60B72AED07E8D\
+8F066F04557B0642FD991A2F303700D5
+
+94F7CA8E1A54234C6D53CC734BB3D3150C8BA8C5F880EAB8D25FED13793A9701\
+EBE320509286FD8E422E931D99C98DA4DF7E70AE447BAB8CFFD92382D8A77760\
+A259FC4FBD72:\
+D5648EACC0E8904FA86A182120DDD308A32AFBA4C1AC1EAF4D6EACCA4D619E71\
+0582C5FF067AAD49A2E6BB71F02686F9
+
+13BD2811F6ED2B6F04FF3895ACEED7BEF8DCD45EB121791BC194A0F806206BFF\
+C3B9281C2B308B1A729CE008119DD3066E9378ACDCC50A98A82E20738800B6CD\
+DBE5FE9694AD6D:\
+1A9B50918B7E47A0DEBBC572B69A0F8C748D493768FE69738D6EC18F72549997\
+19B6AD8B29AA42035DEC5A47F00CCD33
+
+1EED9CBA179A009EC2EC5508773DD305477CA117E6D569E66B5F64C6BC64801C\
+E25A8424CE4A26D575B8A6FB10EAD3FD1992EDDDEEC2EBE7150DC98F63ADC323\
+7EF57B91397AA8A7:\
+8F9F441D51B777EDE476F4C85548E0AB1F92389531B20661CFC993A77E03BE92\
+BCDE385487FC1E25BFFBFD3B37C8F419
+
+BA5B67B5EC3A3FFAE2C19DD8176A2EF75C0CD903725D45C9CB7009A900C0B0CA\
+7A2967A95AE68269A6DBF8466C7B6844A1D608AC661F7EFF00538E323DB5F2C6\
+44B78B2D48DE1A08AA:\
+6F2098082054F1B2232A4B85B20D1CF520A41EBBDC947C506A575CA2B47B8898\
+6E062583D15595893326E8AFAF3F6ECF
+
+0EFA26AC5673167DCACAB860932ED612F65FF49B80FA9AE65465E5542CB62075\
+DF1C5AE54FBA4DB807BE25B070033EFA223BDD5B1D3C94C6E1909C02B620D4B1\
+B3A6C9FED24D70749604:\
+4C0E90B28BC652F935D4F6C689B1555864DCF5D6B922F9C067F9D0810F1685EF\
+5892BA323C65BC83B2EA55869BE732AC
+
+BBFD933D1FD7BF594AC7F435277DC17D8D5A5B8E4D13D96D2F64E771ABBD51A5\
+A8AEA741BECCBDDB177BCEA05243EBD003CFDEAE877CCA4DA94605B67691919D\
+8B033F77D384CA01593C1B:\
+7E71FAF636E9AD3CE76DB7A358AC03064A99646CC704E0DFDDC3ED050DEA3788\
+1787326C7355C214D51874448FC74D35
+
+90078999FD3C35B8AFBF4066CBDE335891365F0FC75C1286CDD88FA51FAB94F9\
+B8DEF7C9AC582A5DBCD95817AFB7D1B48F63704E19C2BAA4DF347F48D4A6D603\
+013C23F1E9611D595EBAC37C:\
+F69DA6546BFE881D7D5C8990A7A012194C734A3089D4CFBA41937647AB7EEEDD\
+68604A0BC7B82E3F667BFB57C2F44F27
+
+64105ECA863515C20E7CFBAA0A0B8809046164F374D691CDBD6508AAABC1819F\
+9AC84B52BAFC1B0FE7CDDBC554B608C01C8904C669D8DB316A0953A4C68ECE32\
+4EC5A49FFDB59A1BD6A292AA0E:\
+3B40209B9BA0648359D4108ADD32012275A7935AA2F0D7D9603AA90006CCF69D\
+FEB999930684F10FD59B008F93CB1016
+
+D4654BE288B9F3B711C2D02015978A8CC57471D5680A092AA534F7372C71CEAA\
+B725A383C4FCF4D8DEAA57FCA3CE056F312961ECCF9B86F14981BA5BED6AB5B4\
+498E1F6C82C6CAE6FC14845B3C8A:\
+C6429C4D080056FAD6E95C81F91EC023FBDB65ADBE366053909018E0930BA47C\
+52066362C65088D159BABF0F76CB28C6
+
+12D9394888305AC96E65F2BF0E1B18C29C90FE9D714DD59F651F52B88B3008C5\
+88435548066EA2FC4C101118C91F32556224A540DE6EFDDBCA296EF1FB00341F\
+5B01FECFC146BDB251B3BDAD556CD2:\
+5552CE6258CB3EEA22A029E0C013760A14B009795322DAC05691C408A130F8C3\
+61B8D27C0C466D60D4D419725243E9F3
+
+871A0D7A5F36C3DA1DFCE57ACD8AB8487C274FAD336BC137EBD6FF4658B547C1\
+DCFAB65F037AA58F35EF16AFF4ABE77BA61F65826F7BE681B5B6D5A1EA8085E2\
+AE9CD5CF0991878A311B549A6D6AF230:\
+4CF2F34C8BB30FFCE607F52FBE54C8C72F4E6B109462A56D6DFAA35498A1F585\
+B964BDAD1C2D656FA09DAAA1591A488E
+
+E90B4FFEF4D457BC7711FF4AA72231CA25AF6B2E206F8BF859D8758B89A7CD36\
+105DB2538D06DA83BAD5F663BA11A5F6F61F236FD5F8D53C5E89F183A3CEC615\
+B50C7C681E773D109FF7491B5CC22296C5:\
+27B86E7B6008903ABC916199E511AF8AAADF8C3226CACDDF398D1C88F999EA48\
+94A0F0EF521CB3DF2F0866D5A00516E6
+
+E728DE62D75856500C4C77A428612CD804F30C3F10D36FB219C5CA0AA30726AB\
+190E5F3F279E0733D77E7267C17BE27D21650A9A4D1E32F649627638DBADA970\
+2C7CA303269ED14014B2F3CF8B894EAC8554:\
+A987C872E07801C8F0AF3E70EB25C370DB4001D731AE1CCA1365D82A33A7F2F3\
+7CBEF4CE88D0545228EB29175F787353
+
+6348F229E7B1DF3B770C77544E5166E081850FA1C6C88169DB74C76E42EB983F\
+ACB276AD6A0D1FA7B50D3E3B6FCD799EC97470920A7ABED47D288FF883E24CA2\
+1C7F8016B93BB9B9E078BDB9703D2B781B616E:\
+BAC5B9FDFD097BAF8AAEAE1D2695593D7B5258D224DEA79A1FD4A511C004351A\
+DBF000F37C28055FCD43FCF1CD2C0ABA
+
+4B127FDE5DE733A1680C2790363627E63AC8A3F1B4707D982CAEA258655D9BF1\
+8F89AFE54127482BA01E08845594B671306A025C9A5C5B6F93B0A39522DC8774\
+37BE5C2436CBF300CE7AB6747934FCFC30AEAAF6:\
+9F432BC09FBAF070F939DBAB12E6E148BE02B16B717D729BDB37CD667B4AD2D6\
+7921C0A598126FB715A7B0960076ED09
+
+08461F006CFF4CC64B752C957287E5A0FAABC05C9BFF89D23FD902D324C79903\
+B48FCB8F8F4B01F3E4DDB483593D25F000386698F5ADE7FAADE9615FDC50D327\
+85EA51D49894E45BAA3DC707E224688C6408B68B11:\
+7CF44B87EB23E3C92739CD6F0F6C5AC3FA1441ADFEADB3BAC87DAAA4C64BDAEC\
+9068AA7E68692E20168AAD5819ED2DC9
+
+68C8F8849B120E6E0C9969A5866AF591A829B92F33CD9A4A3196957A148C4913\
+8E1E2F5C7619A6D5EDEBE995ACD81EC8BB9C7B9CFCA678D081EA9E25A75D39DB\
+04E18D475920CE828B94E72241F24DB72546B352A0E4:\
+30887A16283EE8E45E7AA48B746A741B2F60522FC688B182573C1993562B2E71\
+9F526EBA3150406FA158DA61B68D99C8
+
+B8D56472954E31FB54E28FCA743F84D8DC34891CB564C64B08F7B71636DEBD64\
+CA1EDBDBA7FC5C3E40049CE982BBA8C7E0703034E331384695E9DE76B5104F2F\
+BC4535ECBEEBC33BC27F29F18F6F27E8023B0FBB6F563C:\
+732CFCC7A3680BAE5C3DF25F2B9AE98BABD31EDB0D7045B7550B9BADF66A1CB5\
+CD0EAC6919EE6B19B9A1E9DE61AB3EA4
+
+0D58AC665FA84342E60CEFEE31B1A4EACDB092F122DFC68309077AED1F3E528F\
+578859EE9E4CEFB4A728E946324927B675CD4F4AC84F64DB3DACFE850C1DD187\
+44C74CECCD9FE4DC214085108F404EAB6D8F452B5442A47D:\
+15C34B99050E8D0CD333D2EC6CD0A52DC76036AD7E000E01CC8F1812171D10BC\
+12E1D43DCC689CB5A38FA61484411104
+
+1755E2D2E5D1C1B0156456B539753FF416651D44698E87002DCF61DCFA2B4E72\
+F264D9AD591DF1FDEE7B41B2EB00283C5AEBB3411323B672EAA145C512518510\
+4F20F335804B02325B6DEA65603F349F4D5D8B782DD3469CCD:\
+D8CB85547D6C015433E608818BB58F0A5BC97997EC976BE33F9C2368D1245764\
+F4EEF9F5311CB5667224DA9F353A1A35
+
+B180DE1A611111EE7584BA2C4B020598CD574AC77E404E853D15A101C6F5A2E5\
+C801D7D85DC95286A1804C870BB9F00FD4DCB03AA8328275158819DCAD7253F3\
+E3D237AEAA7979268A5DB1C6CE08A9EC7C2579783C8AFC1F91A7:\
+35BCFC9BC9F138F76094099DE78BEBC0F1BB93FE5A4561493719716A2C33459E\
+AB4CF5175E3673782B09354FB191936D
+
+CF3583CBDFD4CBC17063B1E7D90B02F0E6E2EE05F99D77E24E560392535E47E0\
+5077157F96813544A17046914F9EFB64762A23CF7A49FE52A0A4C01C630CFE87\
+27B81FB99A89FF7CC11DCA5173057E0417B8FE7A9EFBA6D95C555F:\
+A2B4E92FC5D6978430B3ACB887FCC8B6EA23CCDB7494BD1025604843E7944CF1\
+14776D4E8C2B3C2AD517A7EE7AB0F788
+
+072FC02340EF99115BAD72F92C01E4C093B9599F6CFC45CB380EE686CB5EB019\
+E806AB9BD55E634AB10AA62A9510CC0672CD3EDDB589C7DF2B67FCD3329F61B1\
+A4441ECA87A33C8F55DA4FBBAD5CF2B2527B8E983BB31A2FADEC7523:\
+9F8E772C845766AA61B63C2873CD46C0F42769279B60E57122AE9D17508203C6\
+6F3F9833F7F6DC34C7ADAA5B5310D91B
+
+76EECF956A52649F877528146DE33DF249CD800E21830F65E90F0F25CA9D6540\
+FDE40603230ECA6760F1139C7F268DEBA2060631EEA92B1FFF05F93FD5572FBE\
+29579ECD48BC3A8D6C2EB4A6B26E38D6C5FBF2C08044AEEA470A8F2F26:\
+DA7A9EFFC5B684BAABF8CE6F10E72539D76FE2F97A4F77251739D310C7671742\
+4886252DB34BB4B467183BCF146E759D
+
+7ADC0B6693E61C269F278E6944A5A2D8300981E40022F839AC644387BFAC9086\
+650085C2CDC585FEA47B9D2E52D65A2B29A7DC370401EF5D60DD0D21F9E2B90F\
+AE919319B14B8C5565B0423CEFB827D5F1203302A9D01523498A4DB10374:\
+4B1CA37472CA2A810571CF8FDC364F1BE7B55ADEB3E4588BADDE5F3B477B0D77\
+DF143304FDED929E92242E5CB6C56940
+
+E1FFFA9826CCE8B86BCCEFB8794E48C46CDF372013F782ECED1E378269B7BE2B\
+7BF51374092261AE120E822BE685F2E7A83664BCFBE38FE8633F24E633FFE198\
+8E1BC5ACF59A587079A57A910BDA60060E85B5F5B6F776F0529639D9CCE4BD:\
+C7864270011C680DA45A8988FB499A6A14B869155118F74B48AC05FDACF407B0\
+B98789B3E6B805D3BCB8D87594D8EE77
+
+69F9ABBA65592EE01DB4DCE52DBAB90B08FC04193602792EE4DAA263033D5908\
+1587B09BBE49D0B49C9825D22840B2FF5D9C5155F975F8F2C2E7A90C75D2E4A8\
+040FE39F63BBAFB403D9E28CC3B86E04E394A9C9E8065BD3C85FA9F0C7891600:\
+871B7C9F9896A88979FF56138D51547CF21C5B2DBA048146FB28515572D474D6\
+DC9DF5CE71A09EA27518F31B1E95A14A
+
+38A10A352CA5AEDFA8E19C64787D8E9C3A75DBF3B8674BFAB29B5DBFC15A63D1\
+0FAE66CD1A6E6D2452D557967EAAD89A4C98449787B0B3164CA5B717A93F24EB\
+0B506CEB70CBBCB8D72B2A72993F909AAD92F044E0B5A2C9AC9CB16A0CA2F81F\
+49:\
+F00B722DE52D30F6741262A49081748F9C09ECF77F3505E5DBD033F3F5490466\
+8E2137B6F53146CD8DBB804375435452
+
+6D8C6E449BC13634F115749C248C17CD148B72157A2C37BF8969EA83B4D6BA8C\
+0EE2711C28EE11495F43049596520CE436004B026B6C1F7292B9C436B055CBB7\
+2D530D860D1276A1502A5140E3C3F54A93663E4D20EDEC32D284E25564F62495\
+5B52:\
+775816077887FC010E03C94E235BFB45CE7A2B0F491D3C1D5BDFBD1168210C94\
+FA286D7B8C04ACEE166F78DFC691CA5B
+
+6EFCBCAF451C129DBE00B9CEF0C3749D3EE9D41C7BD500ADE40CDC65DEDBBBAD\
+B885A5B14B32A0C0D087825201E303288A733842FA7E599C0C514E078F05C821\
+C7A4498B01C40032E9F1872A1C925FA17CE253E8935E4C3C71282242CB716B20\
+89CCC1:\
+F47D9E58D2F2CF8D8B0B62689B3BEA46D7329B095C3783C8B808C2047C6D2D32\
+849D906FB0378FB8F2413931A1C55847
+
+433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B982\
+14B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784444F\
+22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53E7E084\
+6DCBB4CE:\
+4B11FD3E56684E244573F53EFD5D9396591775D5A68EB82D4795396D14510106\
+122BCA43CEF98B5ADCF3ECD17DCD8F73
+
+A873E0C67CA639026B6683008F7AA6324D4979550E9BCE064CA1E1FB97A30B14\
+7A24F3F666C0A72D71348EDE701CF2D17E2253C34D1EC3B647DBCEF2F879F4EB\
+881C4830B791378C901EB725EA5C172316C6D606E0AF7DF4DF7F76E490CD30B2\
+BADF45685F:\
+CD165E9DC90F563CDB79E66EFE968CF19EF97ADF353803339968A4DD7B540411\
+5B430BC9D5AF24FFC6165487C3BE5FAE
+
+006917B64F9DCDF1D2D87C8A6173B64F6587168E80FAA80F82D84F60301E561E\
+312D9FBCE62F39A6FB476E01E925F26BCC91DE621449BE6504C504830AAE3940\
+96C8FC7694651051365D4EE9070101EC9B68086F2EA8F8AB7B811EA8AD934D5C\
+9B62C60A4771:\
+738D788FE5D49A3C33266D68AC4CE3F4D475B9209AAE2F0B7460891A2332F8AC\
+933340FC18192283D133D57A81C263AE
+
+F13C972C52CB3CC4A4DF28C97F2DF11CE089B815466BE88863243EB318C2ADB1\
+A417CB1041308598541720197B9B1CB5BA2318BD5574D1DF2174AF14884149BA\
+9B2F446D609DF240CE335599957B8EC80876D9A085AE084907BC5961B20BF5F6\
+CA58D5DAB38ADB:\
+8327353E70C85DC9B4CCFA0172E2E16439C3D8B65849DFA69CC1E7A92A506EE9\
+25BB483FD5239D8EA3CD89CABD6832F3
+
+E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486\
+F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D\
+B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A\
+21691E1069413848:\
+9962B874CF12130536B1EC61D5B6BF01008B271C60F37D25EDE7CA1E4D8A65AF\
+A90CE25553E99AD6104C1108471F018E
+
+64EC021C9585E01FFE6D31BB50D44C79B6993D72678163DB474947A053674619\
+D158016ADB243F5C8D50AA92F50AB36E579FF2DABB780A2B529370DAA299207C\
+FBCDD3A9A25006D19C4F1FE33E4B1EAEC315D8C6EE1E730623FD1941875B924E\
+B57D6D0C2EDC4E78D6:\
+B3A935122B532314B5CA59520C4E10D0761C15BA8E605556357A3E5C8F139B38\
+BE59BBEF4EB4D8F364863A5B04232873
+
+5954BAB512CF327D66B5D9F296180080402624AD7628506B555EEA8382562324\
+CF452FBA4A2130DE3E165D11831A270D9CB97CE8C2D32A96F50D71600BB4CA26\
+8CF98E90D6496B0A6619A5A8C63DB6D8A0634DFC6C7EC8EA9C006B6C456F1B20\
+CD19E781AF20454AC880:\
+FA2CCC83AB84357AE5850CC5A4862E7EFA72B74C99E904841895D39F69CB64CD\
+AB5ED766A5A43AB2BA8B21D3F8C9923B
+
+03D9F92B2C565709A568724A0AFF90F8F347F43B02338F94A03ED32E6F33666F\
+F5802DA4C81BDCE0D0E86C04AFD4EDC2FC8B4141C2975B6F07639B1994C973D9\
+A9AFCE3D9D365862003498513BFA166D2629E314D97441667B007414E739D7FE\
+BF0FE3C32C17AA188A8683:\
+E56CCFCAFCDF368296C596A70D2721D88ECEB513866052473B46EB768D39BB64\
+D7F119BBB17C177BD768D712E67CDE91
+
+F31E8B4F9E0621D531D22A380BE5D9ABD56FAEC53CBD39B1FAB230EA67184440\
+E5B1D15457BD25F56204FA917FA48E669016CB48C1FFC1E1E45274B3B47379E0\
+0A43843CF8601A5551411EC12503E5AAC43D8676A1B2297EC7A0800DBFEE0429\
+2E937F21C005F17411473041:\
+71096347A0EC565FC5303607BEAD5B2729EDBAC7C88D938FAD69A260710AA56D\
+F57BC0167A1EA324580F6BDBA134AF57
+
+758EA3FEA738973DB0B8BE7E599BBEF4519373D6E6DCD7195EA885FC991D8967\
+62992759C2A09002912FB08E0CB5B76F49162AEB8CF87B172CF3AD190253DF61\
+2F77B1F0C532E3B5FC99C2D31F8F65011695A087A35EE4EEE5E334C369D8EE5D\
+29F695815D866DA99DF3F79403:\
+10D64A7FF0FCFEC8267154BE73D61B31076B6BBF1BA5398ADA8476EBA472C60A\
+EF14F51AD8DF7DB6C3F457FFCC0DBDA6
+
+47C6E0C2B74948465921868804F0F7BD50DD323583DC784F998A93CD1CA4C6EF\
+84D41DC81C2C40F34B5BEE6A93867B3BDBA0052C5F59E6F3657918C382E771D3\
+3109122CC8BB0E1E53C4E3D13B43CE44970F5E0C079D2AD7D7A3549CD75760C2\
+1BB15B447589E86E8D76B1E9CED2:\
+582A6AF1176F547C4902DFF1F0CAE4E0A1A60C2653CCE9D0CE4904A1ECA58621\
+E1E4405A15AB7427CB43BF97C6C8E2FE
+
+F690A132AB46B28EDFA6479283D6444E371C6459108AFD9C35DBD235E0B6B6FF\
+4C4EA58E7554BD002460433B2164CA51E868F7947D7D7A0D792E4ABF0BE5F450\
+853CC40D85485B2B8857EA31B5EA6E4CCFA2F3A7EF3380066D7D8979FDAC618A\
+AD3D7E886DEA4F005AE4AD05E5065F:\
+41915C04CDAEE9CDC90DF4276EEF89EF1F1B11241397D352FA3AF261AF614F40\
+A76D72BCC7D193D5276908260DB0BA83
+
+58D6A99BC6458824B256916770A8417040721CCCFD4B79EACD8B65A3767CE5BA\
+7E74104C985AC56B8CC9AEBD16FEBD4CDA5ADB130B0FF2329CC8D611EB14DAC2\
+68A2F9E633C99DE33997FEA41C52A7C5E1317D5B5DAED35EBA7D5A60E45D1FA7\
+EAABC35F5C2B0A0F2379231953322C4E:\
+6A8339532F5314F35F4570CA151FD8D21E903B6995051A1C2FF8F9C0EA793D7D\
+500A0649C952C4656C6C85BB08FA1828
+
+BEFAB574396D7F8B6705E2D5B58B2C1C820BB24E3F4BAE3E8FBCD36DBF734EE1\
+4E5D6AB972AEDD3540235466E825850EE4C512EA9795ABFD33F330D9FD7F79E6\
+2BBB63A6EA85DE15BEAEEA6F8D204A28956059E2632D11861DFB0E65BC07AC8A\
+159388D5C3277E227286F65FF5E5B5AEC1:\
+6F906CA99970F6BD5344D4E8641ECF479F75E7EC56BEC6D88C82CF68F1E339AF\
+E61DF74D63023388346A93A1AC12968A
+
+8E58144FA9179D686478622CE450C748260C95D1BA43B8F9B59ABECA8D93488D\
+A73463EF40198B4D16FB0B0707201347E0506FF19D01BEA0F42B8AF9E71A1F1B\
+D168781069D4D338FDEF00BF419FBB003031DF671F4A37979564F69282DE9C65\
+407847DD0DA505AB1641C02DEA4F0D834986:\
+70DF5FD7B0B5E7E16F40978BAA958D1D64193886CC6BB09B8A253639A9C5DC6B\
+DEBF2F7D17B9E47E87DAF381508F851A
+
+B55C10EAE0EC684C16D13463F29291BF26C82E2FA0422A99C71DB4AF14DD9C7F\
+33EDA52FD73D017CC0F2DBE734D831F0D820D06D5F89DACC485739144F8CFD47\
+99223B1AFF9031A105CB6A029BA71E6E5867D85A554991C38DF3C9EF8C1E1E9A\
+7630BE61CAABCA69280C399C1FB7A12D12AEFC:\
+184BB5032F023B7162E981CE43BAD38A61291A0AC41FC30E18D5223AB9AE5978\
+BB3ACD8E883CB40BFF21EDB189E564F9
+
+2EEEA693F585F4ED6F6F8865BBAE47A6908AECD7C429E4BEC4F0DE1D0CA0183F\
+A201A0CB14A529B7D7AC0E6FF6607A3243EE9FB11BCF3E2304FE75FFCDDD6C5C\
+2E2A4CD45F63C962D010645058D36571404A6D2B4F44755434D76998E83409C3\
+205AA1615DB44057DB991231D2CB42624574F545:\
+6897C81DA325453DBAECFBA605E2B120F762BC6A14B3935EB8D1EAFFEABEE958\
+C7B15B9C10ED1143DBC5F2AEE2D559E3
+
+DAB11DC0B047DB0420A585F56C42D93175562852428499F66A0DB811FCDDDAB2\
+F7CDFFED1543E5FB72110B64686BC7B6887A538AD44C050F1E42631BC4EC8A9F\
+2A047163D822A38989EE4AAB01B4C1F161B062D873B1CFA388FD301514F62224\
+157B9BEF423C7783B7AAC8D30D65CD1BBA8D689C2D:\
+5468330C26A3C17BA1783A11F5198761AF24C2F9CB1F1F934B902201A7531B5F\
+5A2D110B9C783B69BF3EA2178DF91F29
+
+42E99A2F80AEE0E001279A2434F731E01D34A44B1A8101726921C0590C30F312\
+0EB83059F325E894A5AC959DCA71CE2214799916424E859D27D789437B9D2724\
+0BF8C35ADBAFCECC322B48AA205B293962D858652ABACBD588BCF6CBC388D099\
+3BD622F96ED54614C25B6A9AA527589EAAFFCF17DDF7:\
+2D21F6208A33C7919BDB33EC8F997F9FECD5D67E8E8EA6176E3BCF58497FFCEB\
+BAA723AF5C88A65760BE73AC447F32E6
+
+3C9B46450C0F2CAE8E3823F8BDB4277F31B744CE2EB17054BDDC6DFF36AF7F49\
+FB8A2320CC3BDF8E0A2EA29AD3A55DE1165D219ADEDDB5175253E2D1489E9B6F\
+DD02E2C3D3A4B54D60E3A47334C37913C5695378A669E9B72DEC32AF5434F93F\
+46176EBF044C4784467C700470D0C0B40C8A088C815816:\
+7C77507069871A5D8605EA4C9D7BEB6E1CC4521BDDB9B64F2614B9677DBD8C31\
+18AD375EA59CC3A6BD00B00E0A11CFD6
+
+D1E654B77CB155F5C77971A64DF9E5D34C26A3CAD6C7F6B300D39DEB19100946\
+91ADAA095BE4BA5D86690A976428635D5526F3E946F7DC3BD4DBC78999E65344\
+1187A81F9ADCD5A3C5F254BC8256B0158F54673DCC1232F6E918EBFC6C51CE67\
+EAEB042D9F57EEC4BFE910E169AF78B3DE48D137DF4F2840:\
+1C7941A5F120E32AC2DB8036F25C3311A7203170F8B10856DB49C297C319539D\
+509F1DE938CE94F7E1CBDA295FF8E4C8
+
+626F68C18A69A6590159A9C46BE03D5965698F2DAC3DE779B878B3D9C421E0F2\
+1B955A16C715C1EC1E22CE3EB645B8B4F263F60660EA3028981EEBD6C8C3A367\
+285B691C8EE56944A7CD1217997E1D9C21620B536BDBD5DE8925FF71DEC6FBC0\
+6624AB6B21E329813DE90D1E572DFB89A18120C3F606355D25:\
+15B14B1D44174D85B9AFC305D591B0CA50A9060CA1D78D8FD6D7BCC97DDC4BE8\
+3195B3EC6159C2891181BA2720E6D1BC
+
+651A6FB3C4B80C7C68C6011675E6094EB56ABF5FC3057324EBC6477825061F9F\
+27E7A94633ABD1FA598A746E4A577CAF524C52EC1788471F92B8C37F23795CA1\
+9D559D446CAB16CBCDCE90B79FA1026CEE77BF4AB1B503C5B94C2256AD75B3EA\
+C6FD5DCB96ACA4B03A834BFB4E9AF988CECBF2AE597CB9097940:\
+F5E3EF40266E244EDF40A2EEC07825A891A96CD1B852B5BC937073ADB68123F9\
+CCB85453D4FAE90877368DC4AE7EB718
+
+8AAF072FCE8A2D96BC10B3C91C809EE93072FB205CA7F10ABD82ECD82CF040B1\
+BC49EA13D1857815C0E99781DE3ADBB5443CE1C897E55188CEAF221AA9681638\
+DE05AE1B322938F46BCE51543B57ECDB4C266272259D1798DE13BE90E10EFEC2\
+D07484D9B21A3870E2AA9E06C21AA2D0C9CF420080A80A91DEE16F:\
+145DE80DC772DFE2DFD34294A8CA257DE4BEF9C882F20D922C8812992EE796D5\
+63C87C483333C492F2912F73229B8797
+
+53F918FD00B1701BD504F8CDEA803ACCA21AC18C564AB90C2A17DA592C7D6968\
+8F6580575395551E8CD33E0FEF08CA6ED4588D4D140B3E44C032355DF1C53156\
+4D7F4835753344345A6781E11CD5E095B73DF5F82C8AE3AD00877936896671E9\
+47CC52E2B29DCD463D90A0C9929128DA222B5A211450BBC0E02448E2:\
+617B3BC941708E0D3343925F531C6AAD9FC8B7076FCE8A64A13B4B196AF46616\
+80DFB7E884D1929900D76F9EDFF9FA3A
+
+A64599B8A61B5CCEC9E67AED69447459C8DA3D1EC6C7C7C82A7428B9B584FA67\
+E90F68E2C00FBBED4613666E5168DA4A16F395F7A3C3832B3B134BFC9CBAA95D\
+2A0FE252F44AC6681EB6D40AB91C1D0282FED6701C57463D3C5F2BB8C6A7301F\
+B4576AA3B5F15510DB8956FF77478C26A7C09BEA7B398CFC83503F538E:\
+5AEEE99287F9B81EA53D68B8831F6C0CF675A864F381F7ECF872B9CE18967AF9\
+EE70F941481FCBECE36DA6B40AD33782
+
+0E3AB0E054739B00CDB6A87BD12CAE024B54CB5E550E6C425360C2E87E59401F\
+5EC24EF0314855F0F56C47695D56A7FB1417693AF2A1ED5291F2FEE95F75EED5\
+4A1B1C2E81226FBFF6F63ADE584911C71967A8EB70933BC3F5D15BC91B5C2644\
+D9516D3C3A8C154EE48E118BD1442C043C7A0DBA5AC5B1D5360AAE5B9065:\
+FA4AC59E79C8BF68E27505766DBC0E7ED3CB2B8848148D324577A5CBD63AB603\
+D64F3C69054F22EC65D16BC86C867176
+
+A62FC595B4096E6336E53FCDFC8D1CC175D71DAC9D750A6133D23199EAAC2882\
+07944CEA6B16D27631915B4619F743DA2E30A0C00BBDB1BBB35AB852EF3B9AEC\
+6B0A8DCC6E9E1ABAA3AD62AC0A6C5DE765DE2C3711B769E3FDE44A74016FFF82\
+AC46FA8F1797D3B2A726B696E3DEA5530439ACEE3A45C2A51BC32DD055650B:\
+09376F02C5567AA313A9E828FABA108828D1729E244DE0F36DB8FF9A485FB393\
+846ED2627A31AD8DBB8FAA965ED89DA4
+
+2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\
+29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\
+E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\
+98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\
+D5E5E632BC24710887AFE34C784D8F65DBCEC105E0C642D5B67B960D629DEFD8\
+E6030EFA9B238EC567475D3401B8EFF8
+
+10DB509B2CDCABA6C062AE33BE48116A29EB18E390E1BBADA5CA0A2718AFBCD2\
+3431440106594893043CC7F2625281BF7DE2655880966A23705F0C5155C2F5CC\
+A9F2C2142E96D0A2E763B70686CD421B5DB812DACED0C6D65035FDE558E94F26\
+B3E6DDE5BD13980CC80292B723013BD033284584BFF27657871B0CF07A849F4A\
+E2:\
+14895343ED1DB9FA01DA79173C4CBEC323BC21352347DD9B82194A08E14AE418\
+7C35C6DC1B3715D1722689C7FF15669B
+
+9334DE60C997BDA6086101A6314F64E4458F5FF9450C509DF006E8C547983C65\
+1CA97879175AABA0C539E82D05C1E02C480975CBB30118121061B1EBAC4F8D9A\
+3781E2DB6B18042E01ECF9017A64A0E57447EC7FCBE6A7F82585F7403EE2223D\
+52D37B4BF426428613D6B4257980972A0ACAB508A7620C1CB28EB4E9D30FC413\
+61EC:\
+D5857D50A0BD78C9C72965F2D4B08AE3C7E2F24F9FBD3E3BB96E6964F8A78D9A\
+80E7A7603CBBEAFD80CC9CCD34EFA1A1
+
+E88AB086891693AA535CEB20E64C7AB97C7DD3548F3786339897A5F0C3903154\
+9CA870166E477743CCFBE016B4428D89738E426F5FFE81626137F17AECFF61B7\
+2DBEE2DC20961880CFE281DFAB5EE38B1921881450E16032DE5E4D55AD8D4FCA\
+609721B0692BAC79BE5A06E177FE8C80C0C83519FB3347DE9F43D5561CB8107B\
+9B5EDC:\
+EFE8F31B4080402A72D11E70E9F4C368CF7A51313915119FF00BFB105890121C\
+46E803A662DE2C694B843652CCACA22C
+
+FD19E01A83EB6EC810B94582CB8FBFA2FCB992B53684FB748D2264F020D3B960\
+CB1D6B8C348C2B54A9FCEA72330C2AAA9A24ECDB00C436ABC702361A82BB8828\
+B85369B8C72ECE0082FE06557163899C2A0EFA466C33C04343A839417057399A\
+63A3929BE1EE4805D6CE3E5D0D0967FE9004696A5663F4CAC9179006A2CEB755\
+42D75D68:\
+C9AE23B26501636E14225CB707A87C6228D273FD97C725FF31DF570343FCFA33\
+30FC592CAEBA8A26B2E598A66DF07B8D
+
+59AE20B6F7E0B3C7A989AFB28324A40FCA25D8651CF1F46AE383EF6D8441587A\
+A1C04C3E3BF88E8131CE6145CFB8973D961E8432B202FA5AF3E09D625FAAD825\
+BC19DA9B5C6C20D02ABDA2FCC58B5BD3FE507BF201263F30543819510C12BC23\
+E2DDB4F711D087A86EDB1B355313363A2DE996B891025E147036087401CCF3CA\
+7815BF3C49:\
+6F541A14D2016CAE80DA4CF80EC3B6B9D81180B860AFBC2FD2F412D44E460644\
+88962E68D515210C4C172EE39D79ADFC
+
+77EE804B9F3295AB2362798B72B0A1B2D3291DCEB8139896355830F34B3B3285\
+61531F8079B79A6E9980705150866402FDC176C05897E359A6CB1A7AB067383E\
+B497182A7E5AEF7038E4C96D133B2782917417E391535B5E1B51F47D8ED7E4D4\
+025FE98DC87B9C1622614BFF3D1029E68E372DE719803857CA52067CDDAAD958\
+951CB2068CC6:\
+141B750B7EEF0E4160AC1261CAA6A6E8F2FB344A23EC3F9483507E2E0CC19DE2\
+F3EBD5CC8F1F78CA8D5856343A2821B3
+
+B771D5CEF5D1A41A93D15643D7181D2A2EF0A8E84D91812F20ED21F147BEF732\
+BF3A60EF4067C3734B85BC8CD471780F10DC9E8291B58339A677B960218F71E7\
+93F2797AEA349406512829065D37BB55EA796FA4F56FD8896B49B2CD19B43215\
+AD967C712B24E5032D065232E02C127409D2ED4146B9D75D763D52DB98D949D3\
+B0FED6A8052FBB:\
+C9735F0A53D93622457E6C4AE4110B503B473FBED0066E27595E5D98D41F846D\
+500C875538B73FECE6CE70ED620FCB98
+
+B32D95B0B9AAD2A8816DE6D06D1F86008505BD8C14124F6E9A163B5A2ADE55F8\
+35D0EC3880EF50700D3B25E42CC0AF050CCD1BE5E555B23087E04D7BF9813622\
+780C7313A1954F8740B6EE2D3F71F768DD417F520482BD3A08D4F222B4EE9DBD\
+015447B33507DD50F3AB4247C5DE9A8ABD62A8DECEA01E3B87C8B927F5B08BEB\
+37674C6F8E380C04:\
+EECE82A3F4617FD13364D1F828582BB05F44BA3E466913EF6B8F8BE88739A37F\
+D57E0751B698E264D4B6929A28F97415
+
+04410E31082A47584B406F051398A6ABE74E4DA59BB6F85E6B49E8A1F7F2CA00\
+DFBA5462C2CD2BFDE8B64FB21D70C083F11318B56A52D03B81CAC5EEC29EB31B\
+D0078B6156786DA3D6D8C33098C5C47BB67AC64DB14165AF65B44544D806DDE5\
+F487D5373C7F9792C299E9686B7E5821E7C8E2458315B996B5677D926DAC57B3\
+F22DA873C601016A0D:\
+02EC97CD1BED4AC11BAF315CECB8E345EBA64A01808D6B472EB970D5CF11B7FE\
+1FCC1E8901F06FDFBFCD5F5A3C19F626
+
+8B81E9BADDE026F14D95C019977024C9E13DB7A5CD21F9E9FC491D716164BBAC\
+DC7060D882615D411438AEA056C340CDF977788F6E17D118DE55026855F93270\
+472D1FD18B9E7E812BAE107E0DFDE7063301B71F6CFE4E225CAB3B232905A56E\
+994F08EE2891BA922D49C3DAFEB75F7C69750CB67D822C96176C46BD8A29F170\
+1373FB09A1A6E3C7158F:\
+57272E80EA0D673EE8E8CCBE539300A182434CC5749E96C348AD3E86EF2E3564\
+32DE480E2FC73B5EDE3D023C9CB7EAC9
+
+FA6EED24DA6666A22208146B19A532C2EC9BA94F09F1DEF1E7FC13C399A48E41\
+ACC2A589D099276296348F396253B57CB0E40291BD282773656B6E0D8BEA1CDA\
+084A3738816A840485FCF3FB307F777FA5FEAC48695C2AF4769720258C77943F\
+B4556C362D9CBA8BF103AEB9034BAA8EA8BFB9C4F8E6742CE0D52C49EA8E974F\
+339612E830E9E7A9C29065:\
+7B049EC9A17EDCE74EA69A3E1FEB50A36456E41B3DA50F78A9BA8DDD02F93480\
+D9017E5FC1864EFA227060F936FB31E1
+
+9BB4AF1B4F09C071CE3CAFA92E4EB73CE8A6F5D82A85733440368DEE4EB1CBC7\
+B55AC150773B6FE47DBE036C45582ED67E23F4C74585DAB509DF1B8361056454\
+5642B2B1EC463E18048FC23477C6B2AA035594ECD33791AF6AF4CBC2A1166ABA\
+8D628C57E707F0B0E8707CAF91CD44BDB915E0296E0190D56D33D8DDE10B5B60\
+377838973C1D943C22ED335E:\
+307F1275FD1A18019290313C0C70C9F8503CA67482B95EA8F46CFE0DA6B8BF7D\
+61C84F498695C9B91410834014837A38
+
+2167F02118CC62043E9091A647CADBED95611A521FE0D64E8518F16C808AB297\
+725598AE296880A773607A798F7C3CFCE80D251EBEC6885015F9ABF7EAABAE46\
+798F82CB5926DE5C23F44A3F9F9534B3C6F405B5364C2F8A8BDC5CA49C749BED\
+8CE4BA48897062AE8424CA6DDE5F55C0E42A95D1E292CA54FB46A84FBC9CD87F\
+2D0C9E7448DE3043AE22FDD229:\
+ACE6DE32897220E66FEB86087215D33ED1440CD87452024294C711C15BD07AF8\
+6767DAA2E2421F2314A0557316F05AD5
+
+94B7FA0BC1C44E949B1D7617D31B4720CBE7CA57C6FA4F4094D4761567E389EC\
+C64F6968E4064DF70DF836A47D0C713336B5028B35930D29EB7A7F9A5AF9AD5C\
+F441745BAEC9BB014CEEFF5A41BA5C1CE085FEB980BAB9CF79F2158E03EF7E63\
+E29C38D7816A84D4F71E0F548B7FC316085AE38A060FF9B8DEC36F91AD9EBC0A\
+5B6C338CBB8F6659D342A24368CF:\
+ABB01DEF2545BF2F00F5D83B2B0EE6D67057996933821A4869EEE98CF2EBA6FA\
+D752E0F6F01F722F617614F79ABCD9B9
+
+EA40E83CB18B3A242C1ECC6CCD0B7853A439DAB2C569CFC6DC38A19F5C90ACBF\
+76AEF9EA3742FF3B54EF7D36EB7CE4FF1C9AB3BC119CFF6BE93C03E208783335\
+C0AB8137BE5B10CDC66FF3F89A1BDDC6A1EED74F504CBE7290690BB295A872B9\
+E3FE2CEE9E6C67C41DB8EFD7D863CF10F840FE618E7936DA3DCA5CA6DF933F24\
+F6954BA0801A1294CD8D7E66DFAFEC:\
+CAAF388B056F2AEA0A8F646B1EB9383FCB3B1EDA994D58FD6A41F8F04EEF8D0F\
+B61A41BB3CB573CC59689DFF25009DFF
+
+157D5B7E4507F66D9A267476D33831E7BB768D4D04CC3438DA12F9010263EA5F\
+CAFBDE2579DB2F6B58F911D593D5F79FB05FE3596E3FA80FF2F761D1B0E57080\
+055C118C53E53CDB63055261D7C9B2B39BD90ACC32520CBBDBDA2C4FD8856DBC\
+EE173132A2679198DAF83007A9B5C51511AE49766C792A29520388444EBEFE28\
+256FB33D4260439CBA73A9479EE00C63:\
+6397BEADC127E49ED51E14DC9C6C3336C45880A2987277A9A3BABD2ED4E89A00\
+C083E84466039D9D52C3962C7965D6D0
+
+836B34B515476F613FE447A4E0C3F3B8F20910AC89A3977055C960D2D5D2B72B\
+D8ACC715A9035321B86703A411DDE0466D58A59769672AA60AD587B8481DE4BB\
+A552A1645779789501EC53D540B904821F32B0BD1855B04E4848F9F8CFE9EBD8\
+911BE95781A759D7AD9724A7102DBE576776B7C632BC39B9B5E19057E226552A\
+5994C1DBB3B5C7871A11F5537011044C53:\
+41D07FEF7D6623A2171CE53AD77F00657A6C037929967B111ED8872E26EB95B2\
+0337FED74304391F38EEB5B9C93831DD
+
+CC7784A4912A7AB5AD3620AAB29BA87077CD3CB83636ADC9F3DC94F51EDF521B\
+2161EF108F21A0A298557981C0E53CE6CED45BDF782C1EF200D29BAB81DD6460\
+586964EDAB7CEBDBBEC75FD7925060F7DA2B853B2B089588FA0F8C16EC6498B1\
+4C55DCEE335CB3A91D698E4D393AB8E8EAC0825F8ADEBEEE196DF41205C01167\
+4E53426CAA453F8DE1CBB57932B0B741D4C6:\
+B2DCE2E4C0B39A2B544BB34BF35485547783EF59FB1EAB2111BF9B0CF7FBEC4D\
+12FC454BA49D3BD54CC073D31E65E7A8
+
+7639B461FFF270B2455AC1D1AFCE782944AEA5E9087EB4A39EB96BB5C3BAAF0E\
+868C8526D3404F9405E79E77BFAC5FFB89BF1957B523E17D341D7323C302EA70\
+83872DD5E8705694ACDDA36D5A1B895AAA16ECA6104C82688532C8BFE1790B5D\
+C9F4EC5FE95BAED37E1D287BE710431F1E5E8EE105BC42ED37D74B1E55984BF1\
+C09FE6A1FA13EF3B96FAEAED6A2A1950A12153:\
+E3E049A185E57B7B098B9E3F437200C61E60D272AE0FEDBF494D73519F3C0997\
+58BF0214C71F597277B10B31E92E5B02
+
+EB6513FC61B30CFBA58D4D7E80F94D14589090CF1D80B1DF2E68088DC6104959\
+BA0D583D585E9578AB0AEC0CF36C48435EB52ED9AB4BBCE7A5ABE679C97AE2DB\
+E35E8CC1D45B06DDA3CF418665C57CBEE4BBB47FA4CAF78F4EE656FEC237FE4E\
+EBBAFA206E1EF2BD0EE4AE71BD0E9B2F54F91DAADF1FEBFD7032381D636B733D\
+CB3BF76FB14E23AFF1F68ED3DBCF75C9B99C6F26:\
+7210A9FDD3CCD72B3A87E80B6ABE1D82D50D37773C23D61F74C62D06B47D0349\
+985032905B84C3B88059B4279775FAF2
+
+1594D74BF5DDE444265D4C04DAD9721FF3E34CBF622DAF341FE16B96431F6C4D\
+F1F760D34F296EB97D98D560AD5286FEC4DCE1724F20B54FD7DF51D4BF137ADD\
+656C80546FB1BF516D62EE82BAA992910EF4CC18B70F3F8698276FCFB44E0EC5\
+46C2C39CFD8EE91034FF9303058B4252462F86C823EB15BF481E6B79CC3A0221\
+8595B3658E8B37382BD5048EAED5FD02C37944E73B:\
+E7F5023F70475C3B6BB016B520893FF673DDD59285900C1A86E2728F435071E2\
+7CBDD203F756DCA5085639B41BC06F1F
+
+4CFA1278903026F66FEDD41374558BE1B585D03C5C55DAC94361DF286D4BD39C\
+7CB8037ED3B267B07C346626449D0CC5B0DD2CF221F7E4C3449A4BE99985D2D5\
+E67BFF2923357DDEAB5ABCB4619F3A3A57B2CF928A022EB27676C6CF80568900\
+4FCA4D41EA6C2D0A4789C7605F7BB838DD883B3AD3E6027E775BCF2628814280\
+99C7FFF95B14C095EA130E0B9938A5E22FC52650F591:\
+0AEFE328C2DB1214CE983BFC552EAD8FDAB85B9CE9A5C7BECA9ADC68A48FB027\
+1866F159919698233587721671D952A0
+
+D3E65CB92CFA79662F6AF493D696A07CCF32AAADCCEFF06E73E8D9F6F909209E\
+66715D6E978788C49EFB9087B170ECF3AA86D2D4D1A065AE0EFC8924F365D676\
+B3CB9E2BEC918FD96D0B43DEE83727C9A93BF56CA2B2E59ADBA85696546A8150\
+67FC7A78039629D4948D157E7B0D826D1BF8E81237BAB7321312FDAA4D521744\
+F988DB6FDF04549D0FDCA393D639C729AF716E9C8BBA48:\
+2A50545931886A36BD0311E1523CBEAEAEF3FD51D300AA45623533E88CC20FF0\
+A32F14FA5187B6F8EBFAF212F5888328
+
+842CC583504539622D7F71E7E31863A2B885C56A0BA62DB4C2A3F2FD12E79660\
+DC7205CA29A0DC0A87DB4DC62EE47A41DB36B9DDB3293B9AC4BAAE7DF5C6E720\
+1E17F717AB56E12CAD476BE49608AD2D50309E7D48D2D8DE4FA58AC3CFEAFEEE\
+48C0A9EEC88498E3EFC51F54D300D828DDDCCB9D0B06DD021A29CF5CB5B25069\
+15BEB8A11998B8B886E0F9B7A80E97D91A7D01270F9A7717:\
+933064A97F16887A93FED91A366BC2EBE104193999DD01BB96281C564DB97887\
+74CF2E29E6FA5AF5F6D064252E27D274
+
+6C4B0A0719573E57248661E98FEBE326571F9A1CA813D3638531AE28B4860F23\
+C3A3A8AC1C250034A660E2D71E16D3ACC4BF9CE215C6F15B1C0FC7E77D3D2715\
+7E66DA9CEEC9258F8F2BF9E02B4AC93793DD6E29E307EDE3695A0DF63CBDC0FC\
+66FB770813EB149CA2A916911BEE4902C47C7802E69E405FE3C04CEB5522792A\
+5503FA829F707272226621F7C488A7698C0D69AA561BE9F378:\
+3F099FA6A70BEB496A0F8B8BB52B4A1425E456CBDBECA503E40A8557226F8AB9\
+7FF4C1FC293F5FE882317370093BCD58
+
+51B7DBB7CE2FFEB427A91CCFE5218FD40F9E0B7E24756D4C47CD55606008BDC2\
+7D16400933906FD9F30EFFDD4880022D081155342AF3FB6CD53672AB7FB5B3A3\
+BCBE47BE1FD3A2278CAE8A5FD61C1433F7D350675DD21803746CADCA574130F0\
+1200024C6340AB0CC2CF74F2234669F34E9009EF2EB94823D62B31407F4BA46F\
+1A1EEC41641E84D77727B59E746B8A671BEF936F05BE820759FA:\
+479342BC69779327FAF1D39197ECB957E1AFC68F6BC6EB02C2EB0BAEEA35ED05\
+8994D8132A3F1CC2757EA700E0BA51A1
+
+83599D93F5561E821BD01A472386BC2FF4EFBD4AED60D5821E84AAE74D807102\
+9810F5E286F8F17651CD27DA07B1EB4382F754CD1C95268783AD09220F550284\
+0370D494BEB17124220F6AFCE91EC8A0F55231F9652433E5CE3489B727716CF4\
+AEBA7DCDA20CD29AA9A859201253F948DD94395ABA9E3852BD1D60DDA7AE5DC0\
+45B283DA006E1CBAD83CC13292A315DB5553305C628DD091146597:\
+625EBE3650496538E9FC2122C62952B40F7CB670E0D9BE8BE0485ACF43962AFA\
+0274C50E27EDD065B9A89F9E55B52DBB
+
+2BE9BF526C9D5A75D565DD11EF63B979D068659C7F026C08BEA4AF161D85A462\
+D80E45040E91F4165C074C43AC661380311A8CBED59CC8E4C4518E80CD2C78AB\
+1CABF66BFF83EAB3A80148550307310950D034A6286C93A1ECE8929E6385C5E3\
+BB6EA8A7C0FB6D6332E320E71CC4EB462A2A62E2BFE08F0CCAD93E61BEDB5DD0\
+B786A728AB666F07E0576D189C92BF9FB20DCA49AC2D3956D47385E2:\
+A3052636C2EDD4D48D8627E7CB24FC427A548EDF5659F454B1DD9D6550E19510\
+1418EAB0AEC1FE854F5F66383ADFD885
+
+CA76D3A12595A817682617006848675547D3E8F50C2210F9AF906C0E7CE50B44\
+60186FE70457A9E879E79FD4D1A688C70A347361C847BA0DD6AA52936EAF8E58\
+A1BE2F5C1C704E20146D366AEB3853BED9DE9BEFE9569AC8AAEA37A9FB7139A1\
+A1A7D5C748605A8DEFB297869EBEDD71D615A5DA23496D11E11ABBB126B206FA\
+0A7797EE7DE117986012D0362DCEF775C2FE145ADA6BDA1CCB326BF644:\
+B87D7F42CBD8F867956CD9806109F4103DEAFEE60B3190A16AFE6E8034C97996\
+6F1D61537376D95565E0806EB6802D29
+
+F76B85DC67421025D64E93096D1D712B7BAF7FB001716F02D33B2160C2C882C3\
+10EF13A576B1C2D30EF8F78EF8D2F465007109AAD93F74CB9E7D7BEF7C9590E8\
+AF3B267C89C15DB238138C45833C98CC4A471A7802723EF4C744A853CF80A0C2\
+568DD4ED58A2C9644806F42104CEE53628E5BDF7B63B0B338E931E31B87C24B1\
+46C6D040605567CEEF5960DF9E022CB469D4C787F4CBA3C544A1AC91F95F:\
+609206C8DAD2A95A64E8570831269DB0FB4D45112D6CFCBF4590C17934BDEEBC\
+3F5123282A393FDBC070E03277E361EC
+
+25B8C9C032EA6BCD733FFC8718FBB2A503A4EA8F71DEA1176189F694304F0FF6\
+8E862A8197B839957549EF243A5279FC2646BD4C009B6D1EDEBF24738197ABB4\
+C992F6B1DC9BA891F570879ACCD5A6B18691A93C7D0A8D38F95B639C1DAEB48C\
+4C2F15CCF5B9D508F8333C32DE78781B41850F261B855C4BEBCC125A380C54D5\
+01C5D3BD07E6B52102116088E53D76583B0161E2A58D0778F091206AABD5A1:\
+211943D97DD21032C126A8327FDF9FC6D26393C13FAC9B9DC6DC16CFC2C30B9D\
+44025D3C0753C10C2C0A97E6E8F93B32
+
+21CFDC2A7CCB7F331B3D2EEFFF37E48AD9FA9C788C3F3C200E0173D99963E1CB\
+CA93623B264E920394AE48BB4C3A5BB96FFBC8F0E53F30E22956ADABC2765F57\
+FB761E147ECBF8567533DB6E50C8A1F894310A94EDF806DD8CA6A0E141C0FA7C\
+9FAE6C6AE65F18C93A8529E6E5B553BF55F25BE2E80A9882BD37F145FECBEB3D\
+447A3C4E46C21524CC55CDD62F521AB92A8BA72B897996C49BB273198B7B1C9E:\
+F934F1642B8DDAEE31E46CA0B3FA178AFC48C73EE04B087B287102CA103F6B5C\
+2B1890FE398507C2CF0A2941D7ABBE57
+
+4E452BA42127DCC956EF4F8F35DD68CB225FB73B5BC7E1EC5A898BBA2931563E\
+74FAFF3B67314F241EC49F4A7061E3BD0213AE826BAB380F1F14FAAB8B0EFDDD\
+5FD1BB49373853A08F30553D5A55CCBBB8153DE4704F29CA2BDEEF0419468E05\
+DD51557CCC80C0A96190BBCC4D77ECFF21C66BDF486459D427F986410F883A80\
+A5BCC32C20F0478BB9A97A126FC5F95451E40F292A4614930D054C851ACD019C\
+CF:\
+84D5B3E3FF65D4E2197E71E2C7558467EF3480376F304B1F2B384D8E680D9AB8\
+E0AB4D6B7B541E875F3AD058C0C3CF39
+
+FA85671DF7DADF99A6FFEE97A3AB9991671F5629195049880497487867A6C446\
+B60087FAC9A0F2FCC8E3B24E97E42345B93B5F7D3691829D3F8CCD4BB36411B8\
+5FC2328EB0C51CB3151F70860AD3246CE0623A8DC8B3C49F958F8690F8E3860E\
+71EB2B1479A5CEA0B3F8BEFD87ACAF5362435EAECCB52F38617BC6C5C2C6E269\
+EAD1FBD69E941D4AD2012DA2C5B21BCFBF98E4A77AB2AF1F3FDA3233F046D38F\
+1DC8:\
+4B8794114634CF880CE5A8C0861BC2CCACB46B2E82208CF2B150B10C6291565B\
+0EAE2FF20A3293EE5B1965E15F3E40D0
+
+E90847AE6797FBC0B6B36D6E588C0A743D725788CA50B6D792352EA8294F5BA6\
+54A15366B8E1B288D84F5178240827975A763BC45C7B0430E8A559DF4488505E\
+009C63DA994F1403F407958203CEBB6E37D89C94A5EACF6039A327F6C4DBBC7A\
+2A307D976AA39E41AF6537243FC218DFA6AB4DD817B6A397DF5CA69107A91987\
+99ED248641B63B42CB4C29BFDD7975AC96EDFC274AC562D0474C60347A078CE4\
+C25E88:\
+EDFEC1B059C4645CE46D722C2A771C3F451A967BA60A35F6844A86A82A19F7AE\
+4BC940130BA2D61DC998FDD4F1EB7696
+
+F6D5C2B6C93954FC627602C00C4CA9A7D3ED12B27173F0B2C9B0E4A5939398A6\
+65E67E69D0B12FB7E4CEB253E8083D1CEB724AC07F009F094E42F2D6F2129489\
+E846EAFF0700A8D4453EF453A3EDDC18F408C77A83275617FABC4EA3A2833AA7\
+3406C0E966276079D38E8E38539A70E194CC5513AAA457C699383FD1900B1E72\
+BDFB835D1FD321B37BA80549B078A49EA08152869A918CA57F5B54ED71E4FD3A\
+C5C06729:\
+038E8E463D24674BAD250A7B63FFBB5FA83C0A2B702C9329982AFF5E0C9F4C67\
+4E4AF490E2FA00C4EC8666444635D180
+
+CF8562B1BED89892D67DDAAF3DEEB28246456E972326DBCDB5CF3FB289ACA01E\
+68DA5D59896E3A6165358B071B304D6AB3D018944BE5049D5E0E2BB819ACF67A\
+6006111089E6767132D72DD85BEDDCBB2D64496DB0CC92955AB4C6234F1EEA24\
+F2D51483F2E209E4589BF9519FAC51B4D061E801125E605F8093BB6997BC163D\
+551596FE4AB7CFAE8FB9A90F6980480CE0C229FD1675409BD788354DAF316240\
+CFE0AF93EB:\
+8F24904AA1CF56933E0EFEB6AE843BB3065C171C7A55E5544468CBDFA9CA06EA\
+6061541595AA0B3566CC1E0D63859249
+
+2ACE31ABB0A2E3267944D2F75E1559985DB7354C6E605F18DC8470423FCA30B7\
+331D9B33C4A4326783D1CAAE1B4F07060EFF978E4746BF0C7E30CD61040BD5EC\
+2746B29863EB7F103EBDA614C4291A805B6A4C8214230564A0557BC7102E0BD3\
+ED23719252F7435D64D210EE2AAFC585BE903FA41E1968C50FD5D5367926DF7A\
+05E3A42CF07E656FF92DE73B036CF8B19898C0CB34557C0C12C2D8B84E91181A\
+F467BC75A9D1:\
+5DB0E56A11B61E2639ABA1E46439D874E406F408A2899437EBF404011A195001\
+E9D4CDABD2B7178B8375A98910C30E2E
+
+0D8D09AED19F1013969CE5E7EB92F83A209AE76BE31C754844EA9116CEB39A22\
+EBB6003017BBCF26555FA6624185187DB8F0CB3564B8B1C06BF685D47F3286ED\
+A20B83358F599D2044BBF0583FAB8D78F854FE0A596183230C5EF8E54426750E\
+AF2CC4E29D3BDD037E734D863C2BD9789B4C243096138F7672C232314EFFDFC6\
+513427E2DA76916B5248933BE312EB5DDE4CF70804FB258AC5FB82D58D08177A\
+C6F4756017FFF5:\
+CE14E248C1615587F07A73470668FCC6FE760D8FBE361D7EE3CA73F187DBC922\
+19B5E58AB1ED9BD89CDD9BEACE219757
+
+C3236B73DEB7662BF3F3DAA58F137B358BA610560EF7455785A9BEFDB035A066\
+E90704F929BD9689CEF0CE3BDA5ACF4480BCEB8D09D10B098AD8500D9B6071DF\
+C3A14AF6C77511D81E3AA8844986C3BEA6F469F9E02194C92868CD5F51646256\
+798FF0424954C1434BDFED9FACB390B07D342E992936E0F88BFD0E884A0DDB67\
+9D0547CCDEC6384285A45429D115AC7D235A717242021D1DC35641F5F0A48E84\
+45DBA58E6CB2C8EA:\
+2573C84CF6A190AF5825B48985289BEB68379036D7247C2127BB891E0527FAE1\
+8C7E59A46B67DA938F1A5EA134EDBF37
+
+B39FEB8283EADC63E8184B51DF5AE3FD41AAC8A963BB0BE1CD08AA5867D8D910\
+C669221E73243360646F6553D1CA05A84E8DC0DE05B6419EC349CA994480193D\
+01C92525F3FB3DCEFB08AFC6D26947BDBBFD85193F53B50609C6140905C53A66\
+86B58E53A319A57B962331EDE98149AF3DE3118A819DA4D76706A0424B4E1D29\
+10B0ED26AF61D150EBCB46595D4266A0BD7F651BA47D0C7F179CA28545007D92\
+E8419D48FDFBD744CE:\
+6120D07BC9609EAA4235E0A7EBD649FD60DD6DE97ABD9B2513EA01F0EA8C9174\
+78B6A73C33DF39D99AEF3AE4718ADE5F
+
+A983D54F503803E8C7999F4EDBBE82E9084F422143A932DDDDC47A17B0B7564A\
+7F37A99D0786E99476428D29E29D3C197A72BFAB1342C12A0FC4787FD7017D7A\
+6174049EA43B5779169EF7472BDBBD941DCB82FC73AAC45A8A94C9F2BD3477F6\
+1FD3B796F02A1B8264A214C6FEA74B7051B226C722099EC7883A462B83B6AFDD\
+4009248B8A237F605FE5A08FE7D8B45321421EBBA67BD70A0B00DDBF94BAAB7F\
+359D5D1EEA105F28DCFB:\
+3005CF4DAF6F74C096E00BFE1DF106EB053F7E23181E1D235EBA57B921671633\
+E6FB0D2D9E2A89F599DE8404DF3EB966
+
+E4D1C1897A0A866CE564635B74222F9696BF2C7F640DD78D7E2ACA66E1B61C64\
+2BB03EA7536AAE597811E9BF4A7B453EDE31F97B46A5F0EF51A071A2B3918DF1\
+6B152519AE3776F9F1EDAB4C2A377C3292E96408359D3613844D5EB393000283\
+D5AD3401A318B12FD1474B8612F2BB50FB6A8B9E023A54D7DDE28C43D6D8854C\
+8D9D1155935C199811DBFC87E9E0072E90EB88681CC7529714F8FB8A2C9D8856\
+7ADFB974EE205A9BF7B848:\
+7D6924134B0FBEE6FBDF5604B51FEA18FFC0EC3D509A82834DD3C76CBAF112C9\
+C636E9AEBBDBE612510C293B10748EDC
+
+B10C59723E3DCADD6D75DF87D0A1580E73133A9B7D00CB95EC19F5547027323B\
+E75158B11F80B6E142C6A78531886D9047B08E551E75E6261E79785366D7024B\
+D7CD9CF322D9BE7D57FB661069F2481C7BB759CD71B4B36CA2BC2DF6D3A328FA\
+EBDB995A9794A8D72155ED551A1F87C80BF6059B43FC764900B18A1C2441F748\
+7743CF84E565F61F8DD2ECE6B6CCC9444049197AAAF53E926FBEE3BFCA8BE588\
+EC77F29D211BE89DE18B15F6:\
+F5E1A1035D378FAC64F31F773140DB91C61E659FC51533D85C9725A29F79DD5A\
+B2769BBB8FA60CC0D3E1742EAAC49721
+
+DB11F609BABA7B0CA634926B1DD539C8CBADA24967D7ADD4D9876F77C2D80C0F\
+4DCEFBD7121548373582705CCA2495BD2A43716FE64ED26D059CFB566B3364BD\
+49EE0717BDD9810DD14D8FAD80DBBDC4CAFB37CC60FB0FE2A80FB4541B8CA9D5\
+9DCE457738A9D3D8F641AF8C3FD6DA162DC16FC01AAC527A4A0255B4D231C0BE\
+50F44F0DB0B713AF03D968FE7F0F61ED0824C55C4B5265548FEBD6AAD5C5EEDF\
+63EFE793489C39B8FD29D104CE:\
+40BC9DD9D775D571AACCE6D17A49A931B53D598104CF79ABFF3A67F04EB8D31D\
+B6B2DD31A2C1AE7DF0C1CC0652F4F009
+
+BEBD4F1A84FC8B15E4452A54BD02D69E304B7F32616AADD90537937106AE4E28\
+DE9D8AAB02D19BC3E2FDE1D651559E296453E4DBA94370A14DBBB2D1D4E20223\
+02EE90E208321EFCD8528AD89E46DC839EA9DF618EA8394A6BFF308E7726BAE0\
+C19BCD4BE52DA6258E2EF4E96AA21244429F49EF5CB486D7FF35CAC1BACB7E95\
+711944BCCB2AB34700D42D1EB38B5D536B947348A458EDE3DC6BD6EC547B1B0C\
+AE5B257BE36A7124E1060C170FFA:\
+96B493E2E55320FE2DFBCAA14D1FBEEB8DDF4AEE018870F5434AFA4B23C6EFCC\
+90EB96DA5CAE98713DB93977AAC7D6F3
+
+5ACA56A03A13784BDC3289D9364F79E2A85C12276B49B92DB0ADAA4F206D5028\
+F213F678C3510E111F9DC4C1C1F8B6ACB17A6413AA227607C515C62A733817BA\
+5E762CC6748E7E0D6872C984D723C9BB3B117EB8963185300A80BFA65CDE495D\
+70A46C44858605FCCBED086C2B45CEF963D33294DBE9706B13AF22F1B7C4CD5A\
+001CFEC251FBA18E722C6E1C4B1166918B4F6F48A98B64B3C07FC86A6B17A6D0\
+480AB79D4E6415B520F1C484D675B1:\
+0E5521076983B02BEE8C9D2A91343D967C3570063DFC8E05DBEB3F2C2E2ED366\
+5E127A60E8C9A7CB35B0AD7D18C28239
+
+A5AAD0E4646A32C85CFCAC73F02FC5300F1982FABB2F2179E28303E447854094\
+CDFC854310E5C0F60993CEFF54D84D6B46323D930ADB07C17599B35B505F09E7\
+84BCA5985E0172257797FB53649E2E9723EFD16865C31B5C3D5113B58BB0BFC8\
+920FABDDA086D7537E66D709D050BD14D0C960873F156FAD5B3D3840CDFCDC9B\
+E6AF519DB262A27F40896AB25CC39F96984D650611C0D5A3080D5B3A1BF186AB\
+D42956588B3B58CD948970D298776060:\
+39B4012E95E7F74BD2C1C979CD0CB43208CB0FD6093C68CBCABFB8392E918BAF\
+7CF687FE1D6966C3E3A776F533C44FCE
+
+06CBBE67E94A978203EAD6C057A1A5B098478B4B4CBEF5A97E93C8E42F557271\
+3575FC2A884531D7622F8F879387A859A80F10EF02708CD8F7413AB385AFC357\
+678B9578C0EBF641EF076A1A30F1F75379E9DCB2A885BDD295905EE80C0168A6\
+2A9597D10CF12DD2D8CEE46645C7E5A141F6E0E23AA482ABE5661C16E69EF1E2\
+8371E2E236C359BA4E92C25626A7B7FF13F6EA4AE906E1CFE163E91719B1F750\
+A96CBDE5FBC953D9E576CD216AFC90323A:\
+10DD17C12F25CD5C4AB2475D4E2EE055A3A5184E3B1D1BBB192D62809670584D\
+C3DE5316005027F4685F191C0683C01E
+
+F1C528CF7739874707D4D8AD5B98F7C77169DE0B57188DF233B2DC8A5B31EDA5\
+DB4291DD9F68E6BAD37B8D7F6C9C0044B3BF74BBC3D7D1798E138709B0D75E7C\
+593D3CCCDC1B20C7174B4E692ADD820ACE262D45CCFAE2077E87879634716806\
+0A162ECCA8C38C1A88350BD63BB539134F700FD4ADDD5959E255337DAA06BC86\
+358FABCBEFDFB5BC889783D843C08AADC6C4F6C36F65F156E851C9A0F917E4A3\
+67B5AD93D874812A1DE6A7B93CD53AD97232:\
+CA4989360AD874C38A049FCE389028DCD5884FB1E93E4B60C5E06BE93EE99130\
+860FDAC3ADB902E47370A71ACB3FD689
+
+9D9F3A7ECD51B41F6572FD0D0881E30390DFB780991DAE7DB3B47619134718E6\
+F987810E542619DFAA7B505C76B7350C6432D8BF1CFEBDF1069B90A35F0D04CB\
+DF130B0DFC7875F4A4E62CDB8E525AADD7CE842520A482AC18F09442D78305FE\
+85A74E39E760A4837482ED2F437DD13B2EC1042AFCF9DECDC3E877E50FF4106A\
+D10A525230D11920324A81094DA31DEAB6476AA42F20C84843CFC1C58545EE80\
+352BDD3740DD6A16792AE2D86F11641BB717C2:\
+5552568147601C956ADC55344266AAAC8010F71D8B0241942F5E0D6242A3CF3F\
+03FB617C39193740BE27D1EE227CFBDF
+
+5179888724819FBAD3AFA927D3577796660E6A81C52D98E9303261D5A4A83232\
+F6F758934D50AA83FF9E20A5926DFEBAAC49529D006EB923C5AE5048ED544EC4\
+71ED7191EDF46363383824F915769B3E688094C682B02151E5EE01E510B431C8\
+865AFF8B6B6F2F59CB6D129DA79E97C6D2B8FA6C6DA3F603199D2D1BCAB54768\
+2A81CD6CF65F6551121391D78BCC23B5BD0E922EC6D8BF97C952E84DD28AEF90\
+9ABA31EDB903B28FBFC33B7703CD996215A11238:\
+1F226123B5840DC95C61C1B7042AEA3D044C807D0B1753283B6E5A32F63615C4\
+B2AA79DAC27074B6D50E171DAD094114
+
+576EF3520D30B7A4899B8C0D5E359E45C5189ADD100E43BE429A02FB3DE5FF4F\
+8FD0E79D9663ACCA72CD29C94582B19292A557C5B1315297D168FBB54E9E2ECD\
+13809C2B5FCE998EDC6570545E1499DBE7FB74D47CD7F35823B212B05BF3F5A7\
+9CAA34224FDD670D335FCB106F5D92C3946F44D3AFCBAE2E41AC554D8E6759F3\
+32B76BE89A0324AA12C5482D1EA3EE89DED4936F3E3C080436F539FA137E74C6\
+D3389BDF5A45074C47BC7B20B0948407A66D855E2F:\
+A0FB1050167EA0EE214338B4D240D4083E0EA4E8B2BFEBAD83177C02A8CFBFDC\
+67CD1BC9FE7D7C400ABC031BDA5787AE
+
+0DF2152FA4F4357C8741529DD77E783925D3D76E95BAFA2B542A2C33F3D1D117\
+D159CF473F82310356FEE4C90A9E505E70F8F24859656368BA09381FA245EB6C\
+3D763F3093F0C89B972E66B53D59406D9F01AEA07F8B3B615CAC4EE4D05F542E\
+7D0DAB45D67CCCCD3A606CCBEB31EA1FA7005BA07176E60DAB7D78F6810EF086\
+F42F08E595F0EC217372B98970CC6321576D92CE38F7C397A403BADA1548D205\
+C343AC09DECA86325373C3B76D9F32028FEA8EB32515:\
+3F137F81EFF0BBC83E89EEA41FFBAAF88EAEF2776BA9F01B49DEF393337E7608\
+E0D4BACA006B7380AFC40BAECCDC8BE6
+
+3E15350D87D6EBB5C8AD99D42515CFE17980933C7A8F6B8BBBF0A63728CEFAAD\
+2052623C0BD5931839112A48633FB3C2004E0749C87A41B26A8B48945539D1FF\
+41A4B269462FD199BFECD45374756F55A9116E92093AC99451AEFB2AF9FD32D6\
+D7F5FBC7F7A540D5097C096EBC3B3A721541DE073A1CC02F7FB0FB1B9327FB0B\
+1218CA49C9487AB5396622A13AE546C97ABDEF6B56380DDA7012A8384091B665\
+6D0AB272D363CEA78163FF765CDD13AB1738B940D16CAE:\
+58E4972774C28B8AF406700D5C4438C298B2F83E4256513210BE8847937456C6\
+522A32FFE69DD576892E1CAEEF5689D1
+
+C38D6B0B757CB552BE40940ECE0009EF3B0B59307C1451686F1A22702922800D\
+58BCE7A636C1727EE547C01B214779E898FC0E560F8AE7F61BEF4D75EAA696B9\
+21FD6B735D171535E9EDD267C192B99880C87997711002009095D8A7A437E258\
+104A41A505E5EF71E5613DDD2008195F0C574E6BA3FE40099CFA116E5F1A2FA8\
+A6DA04BADCB4E2D5D0DE31FDC4800891C45781A0AAC7C907B56D631FCA5CE8B2\
+CDE620D11D1777ED9FA603541DE794DDC5758FCD5FAD78C0:\
+F6674659BEF3CD14385A8F23E61E19DA5D597E1E7C8B9CE00012FC9B0CC38469\
+55F91B6A8897DA8A20B2A51C2E42582F
+
+8D2DE3F0B37A6385C90739805B170057F091CD0C7A0BC951540F26A5A75B3E69\
+4631BB64C7635EED316F51318E9D8DE13C70A2ABA04A14836855F35E480528B7\
+76D0A1E8A23B547C8B8D6A0D09B241D3BE9377160CCA4E6793D00A515DC2992C\
+B7FC741DACA171431DA99CCE6F7789F129E2AC5CF65B40D703035CD2185BB936\
+C82002DAF8CBC27A7A9E554B06196630446A6F0A14BA155ED26D95BD627B7205\
+C072D02B60DB0FD7E49EA058C2E0BA202DAFF0DE91E845CF79:\
+7254E5CCD2F682A9981CABE020DF1667B3CA3DC5590E1DE5799C1CD608AF6855\
+0B1C77AF8C7FC0B4F37ABD61EE12BB4A
+
+C464BBDAD275C50DCD983B65AD1019B9FF85A1E71C807F3204BB2C921DC31FBC\
+D8C5FC45868AE9EF85B6C9B83BBA2A5A822201ED68586EC5EC27FB2857A5D1A2\
+D09D09115F22DCC39FE61F5E1BA0FF6E8B4ACB4C6DA748BE7F3F0839739394FF\
+7FA8E39F7F7E84A33C3866875C01BCB1263C9405D91908E9E0B50E7459FABB63\
+D8C6BBB73D8E3483C099B55BC30FF092FF68B6ADEDFD477D63570C9F5515847F\
+36E24BA0B705557130CEC57EBAD1D0B31A378E91894EE26E3A04:\
+824E912E862C9923A98F9D416A5FA4B12BBBE5D165D38E2F1055271DF9DF24D4\
+B2F5F7904D49DDB22F83EA9ECBD17B11
+
+8B8D68BB8A75732FE272815A68A1C9C5AA31B41DEDC8493E76525D1D013D33CE\
+BD9E21A5BB95DB2616976A8C07FCF411F5F6BC6F7E0B57ACA78CC2790A6F9B89\
+8858AC9C79B165FF24E66677531E39F572BE5D81EB3264524181115F32780257\
+BFB9AEEC6AF12AF28E587CAC068A1A2953B59AD680F4C245B2E3EC36F59940D3\
+7E1D3DB38E13EDB29B5C0F404F6FF87F80FC8BE7A225FF22FBB9C8B6B1D7330C\
+57840D24BC75B06B80D30DAD6806544D510AF6C4785E823AC3E0B8:\
+69E3CC0325E159E33FC5B6CDB6686979A334FDF5E841EDA3E3AE32EC4A5B77FB\
+E9480444776DAF1D0E210C8CB75FC4FD
+
+6B018710446F368E7421F1BC0CCF562D9C1843846BC8D98D1C9BF7D9D6FCB48B\
+FC3BF83B36D44C4FA93430AF75CD190BDE36A7F92F867F58A803900DF8018150\
+384D85D82132F123006AC2AEBA58E02A037FE6AFBD65ECA7C44977DD3DC74F48\
+B6E7A1BFD5CC4DCF24E4D52E92BD4455848E4928B0EAC8B7476FE3CC03E862AA\
+4DFF4470DBFED6DE48E410F25096487ECFC32A27277F3F5023B2725ADE461B13\
+55889554A8836C9CF53BD767F5737D55184EEA1AB3F53EDD0976C485:\
+817DADD01589BEEB3A6A70003965C57755094BF3F731E2AD0AC339CB88A2120C\
+3B7CD70CFE95CB265952A1227DB5DCD5
+
+C9534A24714BD4BE37C88A3DA1082EDA7CABD154C309D7BD670DCCD95AA53559\
+4463058A29F79031D6ECAA9F675D1211E9359BE82669A79C855EA8D89DD38C2C\
+761DDD0EC0CE9E97597432E9A1BEAE062CDD71EDFDFD464119BE9E69D18A7A7F\
+D7CE0E2106F0C8B0ABF4715E2CA48EF9F454DC203C96656653B727083513F8EF\
+B86E49C513BB758B3B052FE21F1C05BB33C37129D6CC81F1AEF6ADC45B0E8827\
+A830FE545CF57D0955802C117D23CCB55EA28F95C0D8C2F9C5A242B33F:\
+71E243A14255B13BF3E4840BC649453759769BF4D6E6FB1DFB9EB835264233F6\
+9BCC1BDC70007E2E933D0CD3F6E4CF3B
+
+07906C87297B867ABF4576E9F3CC7F82F22B154AFCBF293B9319F1B0584DA6A4\
+0C27B32E0B1B7F412C4F1B82480E70A9235B12EC27090A5A33175A2BB28D8ADC\
+475CEFE33F7803F8CE27967217381F02E67A3B4F84A71F1C5228E0C2AD971373\
+F6F672624FCEA8D1A9F85170FAD30FA0BBD25035C3B41A6175D467998BD1215F\
+6F3866F53847F9CF68EF3E2FBB54BC994DE2302B829C5EEA68EC441FCBAFD7D1\
+6AE4FE9FFF98BF00E5BC2AD54DD91FF9FDA4DD77B6C754A91955D1FBAAD0:\
+A7A87BF389D420D04C930857034EA948C7099B5E7103D79874BE8FF069A97444\
+46DF2679E4CC066DE5912E030D1389B4
+
+588E94B9054ABC2189DF69B8BA34341B77CDD528E7860E5DEFCAA79B0C9A452A\
+D4B82AA306BE84536EB7CEDCBE058D7B84A6AEF826B028B8A0271B69AC3605A9\
+635EA9F5EA0AA700F3EB7835BC54611B922964300C953EFE7491E3677C2CEBE0\
+822E956CD16433B02C68C4A23252C3F9E151A416B4963257B783E038F6B4D5C9\
+F110F871652C7A649A7BCEDCBCCC6F2D0725BB903CC196BA76C76AA9F10A190B\
+1D1168993BAA9FFC96A1655216773458BEC72B0E39C9F2C121378FEAB4E76A:\
+043E849FF1B05A7447F34B1FDC4ACB7EAD94700B8B58089DB00D59E38AAD99F9\
+FF34E7F4AFA763C145A40CA819CDF969
+
+08959A7E4BAAE874928813364071194E2939772F20DB7C3157078987C557C2A6\
+D5ABE68D520EEF3DC491692E1E21BCD880ADEBF63BB4213B50897FA005256ED4\
+1B5690F78F52855C8D9168A4B666FCE2DA2B456D7A7E7C17AB5F2FB1EE90B79E\
+698712E963715983FD07641AE4B4E9DC73203FAC1AE11FA1F8C7941FCC82EAB2\
+47ADDB56E2638447E9D609E610B60CE086656AAEBF1DA3C8A231D7D94E2FD0AF\
+E46B391FF14A72EAEB3F44AD4DF85866DEF43D4781A0B3578BC996C87970B132:\
+6C67C129BC3B32A107F5E6F93108AE8EFEE971C4158A625EEB902D329CC635B4\
+620D55C22FA5D1F7F6BE0B0BBE019BCF
+
+CB2A234F45E2ECD5863895A451D389A369AAB99CFEF0D5C9FFCA1E6E63F763B5\
+C14FB9B478313C8E8C0EFEB3AC9500CF5FD93791B789E67EAC12FD038E2547CC\
+8E0FC9DB591F33A1E4907C64A922DDA23EC9827310B306098554A4A78F050262\
+DB5B545B159E1FF1DCA6EB734B872343B842C57EAFCFDA8405EEDBB48EF32E99\
+696D135979235C3A05364E371C2D76F1902F1D83146DF9495C0A6C57D7BF9EE7\
+7E80F9787AEE27BE1FE126CDC9EF893A4A7DCBBC367E40FE4E1EE90B42EA25AF\
+01:\
+D178543CA9E471C88BD4D69E65118BDFF29658598C4E1A6D57AFF008BDBD5E60\
+544BBE0EB69DF39AC2E62E0B62F4A900
+
+D16BEADF02AB1D4DC6F88B8C4554C51E866DF830B89C06E786A5F8757E890931\
+0AF51C840EFE8D20B35331F4355D80F73295974653DDD620CDDE4730FB6C8D0D\
+2DCB2B45D92D4FBDB567C0A3E86BD1A8A795AF26FBF29FC6C65941CDDB090FF7\
+CD230AC5268AB4606FCCBA9EDED0A2B5D014EE0C34F0B2881AC036E24E151BE8\
+9EEB6CD9A7A790AFCCFF234D7CB11B99EBF58CD0C589F20BDAC4F9F0E28F75E3\
+E04E5B3DEBCE607A496D848D67FA7B49132C71B878FD5557E082A18ECA1FBDA9\
+4D4B:\
+306F95DCD2A7E030507F30533166773C5FC7D2E353704A26AED7439922535109\
+1B7A66750F96A9225EDE9F8A38399F18
+
+8F65F6BC59A85705016E2BAE7FE57980DE3127E5AB275F573D334F73F8603106\
+EC3553016608EF2DD6E69B24BE0B7113BF6A760BA6E9CE1C48F9E186012CF96A\
+1D4849D75DF5BB8315387FD78E9E153E76F8BA7EC6C8849810F59FB4BB9B0043\
+18210B37F1299526866F44059E017E22E96CBE418699D014C6EA01C9F0038B10\
+299884DBEC3199BB05ADC94E955A1533219C1115FED0E5F21228B071F40DD57C\
+4240D98D37B73E412FE0FA4703120D7C0C67972ED233E5DEB300A22605472FA3\
+A3BA86:\
+0FB9B9016EA95BA4DBC8500F7758B0457A95437F2255472BB33FCB12FA5C10BB\
+1D346C3F36B4360E8A85B9C66C26A9F9
+
+84891E52E0D451813210C3FD635B39A03A6B7A7317B221A7ABC270DFA946C426\
+69AACBBBDF801E1584F330E28C729847EA14152BD637B3D0F2B38B4BD5BF9C79\
+1C58806281103A3EABBAEDE5E711E539E6A8B2CF297CF351C078B4FA8F7F35CF\
+61BEBF8814BF248A01D41E86C5715EA40C63F7375379A7EB1D78F27622FB468A\
+B784AAABA4E534A6DFD1DF6FA15511341E725ED2E87F98737CCB7B6A6DFAE416\
+477472B046BF1811187D151BFA9F7B2BF9ACDB23A3BE507CDF14CFDF517D2CB5\
+FB9E4AB6:\
+F84275FC683297C2D6D433B04022222DFFD2B47F29C9DC649CB146417D5665DB\
+A176B0A75B00925BEB8B1038D50CAE76
+
+FDD7A9433A3B4AFABD7A3A5E3457E56DEBF78E84B7A0B0CA0E8C6D53BD0C2DAE\
+31B2700C6128334F43981BE3B213B1D7A118D59C7E6B6493A86F866A1635C128\
+59CFB9AD17460A77B4522A5C1883C3D6ACC86E6162667EC414E9A104AA892053\
+A2B1D72165A855BACD8FAF8034A5DD9B716F47A0818C09BB6BAF22AA503C06B4\
+CA261F557761989D2AFBD88B6A678AD128AF68672107D0F1FC73C5CA74045929\
+7B3292B281E93BCEB761BDE7221C3A55708E5EC84472CDDCAA84ECF23723CC09\
+91355C6280:\
+9F1F27D8A76394B8FAD318A5A7A7071148501F4E95DCE20CA8C6CE12999BED33\
+8261399EA638D760C8648A8325023060
+
+70A40BFBEF92277A1AAD72F6B79D0177197C4EBD432668CFEC05D099ACCB6510\
+62B5DFF156C0B27336687A94B26679CFDD9DAF7AD204338DD9C4D14114033A5C\
+225BD11F217B5F4732DA167EE3F939262D4043FC9CBA92303B7B5E96AEA12ADD\
+A64859DF4B86E9EE0B58E39091E6B188B408AC94E1294A8911245EE361E60E60\
+1EFF58D1D37639F3753BEC80EBB4EFDE25817436076623FC65415FE51D1B0280\
+366D12C554D86743F3C3B6572E400361A60726131441BA493A83FBE9AFDA90F7\
+AF1AE717238D:\
+7954871B5B8B2D4451CBB267D7DCC176A23FAB8DD7C72F5735CCAD7E8016B4D2\
+B2B54668AD54C1CBCFBDD98DA1635DD4
+
+74356E449F4BF8644F77B14F4D67CB6BD9C1F5AE357621D5B8147E562B65C665\
+85CAF2E491B48529A01A34D226D436959153815380D5689E30B35357CDAC6E08\
+D3F2B0E88E200600D62BD9F5EAF488DF86A4470EA227006182E44809009868C4\
+C280C43D7D64A5268FA719074960087B3A6ABC837882F882C837834535929389\
+A12B2C78187E2EA07EF8B8EEF27DC85002C3AE35F1A50BEE6A1C48BA7E175F33\
+16670B27983472AA6A61EED0A683A39EE323080620EA44A9F74411AE5CE99030\
+528F9AB49C79F2:\
+B5E24CC7299D4B295B29A13ADEA87B58AFAC5731D9AC5DAC14D18C59D506A990\
+941C55182223F3FC44398B1FBBD9A18A
+
+8C3798E51BC68482D7337D3ABB75DC9FFE860714A9AD73551E120059860DDE24\
+AB87327222B64CF774415A70F724CDF270DE3FE47DDA07B61C9EF2A3551F45A5\
+584860248FABDE676E1CD75F6355AA3EAEABE3B51DC813D9FB2EAA4F0F1D9F83\
+4D7CAD9C7C695AE84B329385BC0BEF895B9F1EDF44A03D4B410CC23A79A6B62E\
+4F346A5E8DD851C2857995DDBF5B2D717AEB847310E1F6A46AC3D26A7F9B4498\
+5AF656D2B7C9406E8A9E8F47DCB4EF6B83CAACF9AEFB6118BFCFF7E44BEF6937\
+EBDDC89186839B77:\
+E1130E500E8E4C8804EC490C8669E20EC55A924F01AE17B8729E4FC2B92D55F1\
+159695B4DD5550C059100ADEE9443942
+
+FA56BF730C4F8395875189C10C4FB251605757A8FECC31F9737E3C2503B02608\
+E6731E85D7A38393C67DE516B85304824BFB135E33BF22B3A23B913BF6ACD2B7\
+AB85198B8187B2BCD454D5E3318CACB32FD6261C31AE7F6C54EF6A7A2A4C9F3E\
+CB81CE3555D4F0AD466DD4C108A90399D70041997C3B25345A9653F3C9A6711A\
+B1B91D6A9D2216442DA2C973CBD685EE7643BFD77327A2F7AE9CB283620A0871\
+6DFB462E5C1D65432CA9D56A90E811443CD1ECB8F0DE179C9CB48BA4F6FEC360\
+C66F252F6E64EDC96B:\
+7AE6290212713AD00E07B9AD18A118166D7C6E3537B1BD02C5FFA6E419A07AE0\
+3D81231DD9C872BD40CBECD92B359873
+
+B6134F9C3E91DD8000740D009DD806240811D51AB1546A974BCB18D344642BAA\
+5CD5903AF84D58EC5BA17301D5EC0F10CCD0509CBB3FD3FFF9172D193AF0F782\
+252FD1338C7244D40E0E42362275B22D01C4C3389F19DD69BDF958EBE28E31A4\
+FFE2B5F18A87831CFB7095F58A87C9FA21DB72BA269379B2DC2384B3DA953C79\
+25761FED324620ACEA435E52B424A7723F6A2357374157A34CD8252351C25A1B\
+232826CEFE1BD3E70FFC15A31E7C0598219D7F00436294D11891B82497BC78AA\
+5363892A2495DF8C1EEF:\
+B9D5A8571C99AAD244E931DF1C3249F7FE0CC4D2AAB0E26C075425470718B34D\
+15E20B30B2BBB1630397BA57520A7FF7
+
+C941CDB9C28AB0A791F2E5C8E8BB52850626AA89205BEC3A7E22682313D198B1\
+FA33FC7295381354858758AE6C8EC6FAC3245C6E454D16FA2F51C4166FAB51DF\
+272858F2D603770C40987F64442D487AF49CD5C3991CE858EA2A60DAB6A65A34\
+414965933973AC2457089E359160B7CDEDC42F29E10A91921785F6B7224EE0B3\
+49393CDCFF6151B50B377D609559923D0984CDA6000829B916AB6896693EF6A2\
+199B3C22F7DC5500A15B8258420E314C222BC000BC4E5413E6DD82C993F8330F\
+5C6D1BE4BC79F08A1A0A46:\
+8E2B057C5ABC03133B143FBA8FFD60B0A7ED58EDA82C26942C96199E7F656FF3\
+47E857BC25B17979AF6955E03F6C2EA0
+
+4499EFFFAC4BCEA52747EFD1E4F20B73E48758BE915C88A1FFE5299B0B005837\
+A46B2F20A9CB3C6E64A9E3C564A27C0F1C6AD1960373036EC5BFE1A8FC6A435C\
+2185ED0F114C50E8B3E4C7ED96B06A036819C9463E864A58D6286F785E32A804\
+443A56AF0B4DF6ABC57ED5C2B185DDEE8489EA080DEEEE66AA33C2E6DAB36251\
+C402682B6824821F998C32163164298E1FAFD31BABBCFFB594C91888C6219079\
+D907FDB438ED89529D6D96212FD55ABE20399DBEFD342248507436931CDEAD49\
+6EB6E4A80358ACC78647D043:\
+8385EBCA2713CF95F24EE18AFB651754DB093D06D28054BDD335206730FD88EF\
+D4FBF9BE7F3DDD1FB0670A1A3DC28CBF
+
+EECBB8FDFA4DA62170FD06727F697D81F83F601FF61E478105D3CB7502F2C89B\
+F3E8F56EDD469D049807A38882A7EEFBC85FC9A950952E9FA84B8AFEBD3CE782\
+D4DA598002827B1EB98882EA1F0A8F7AA9CE013A6E9BC462FB66C8D4A18DA214\
+01E1B93356EB12F3725B6DB1684F2300A98B9A119E5D27FF704AFFB618E12708\
+E77E6E5F34139A5A41131FD1D6336C272A8FC37080F041C71341BEE6AB550CB4\
+A20A6DDB6A8E0299F2B14BC730C54B8B1C1C487B494BDCCFD3A53535AB2F2315\
+90BF2C4062FD2AD58F906A2D0D:\
+7F045E33C10E4D5DB25B6B4B85D97055AF22D40E32C6C8409F8024F794CC3E12\
+403E8EA9575284294A9580201B6F7114
+
+E64F3E4ACE5C8418D65FEC2BC5D2A303DD458034736E3B0DF719098BE7A206DE\
+AF52D6BA82316CAF330EF852375188CDE2B39CC94AA449578A7E2A8E3F5A9D68\
+E816B8D16889FBC0EBF0939D04F63033AE9AE2BDAB73B88C26D6BD25EE460EE1\
+EF58FB0AFA92CC539F8C76D3D097E7A6A63EBB9B5887EDF3CF076028C5BBD5B9\
+DB3211371AD3FE121D4E9BF44229F4E1ECF5A0F9F0EBA4D5CEB72878AB22C3F0\
+EB5A625323AC66F7061F4A81FAC834471E0C59553F108475FE290D43E6A055AE\
+3EE46FB67422F814A68C4BE3E8C9:\
+3EE36F052B121B303E1243A5B116C1A036F4ECBCBCCB9AF64A51210EA554067F\
+6A398C7F269BF30B8C8CA32750E2294F
+
+D2CB2D733033F9E91395312808383CC4F0CA974E87EC68400D52E96B3FA6984A\
+C58D9AD0938DDE5A973008D818C49607D9DE2284E7618F1B8AED8372FBD52ED5\
+4557AF4220FAC09DFA8443011699B97D743F8F2B1AEF3537EBB45DCC9E13DFB4\
+38428EE190A4EFDB3CAEB7F3933117BF63ABDC7E57BEB4171C7E1AD260AB0587\
+806C4D137B6316B50ABC9CCE0DFF3ACADA47BBB86BE777E617BBE578FF451984\
+4DB360E0A96C6701290E76BB95D26F0F804C8A4F2717EAC4E7DE9F2CFF3BBC55\
+A17E776C0D02856032A6CD10AD2838:\
+0232C135B8F082CAC7C31EE81C10F423875004365C00E1E41FD1D6E91FF7074E\
+2265AAE87CFAA0153BC2FAFFEFAAADEE
+
+F2998955613DD414CC111DF5CE30A995BB792E260B0E37A5B1D942FE90171A4A\
+C2F66D4928D7AD377F4D0554CBF4C523D21F6E5F379D6F4B028CDCB9B1758D3B\
+39663242FF3CB6EDE6A36A6F05DB3BC41E0D861B384B6DEC58BB096D0A422FD5\
+42DF175E1BE1571FB52AE66F2D86A2F6824A8CFAACBAC4A7492AD0433EEB1545\
+4AF8F312B3B2A577750E3EFBD370E8A8CAC1582581971FBA3BA4BD0D76E718DA\
+CF8433D33A59D287F8CC92234E7A271041B526E389EFB0E40B6A18B3AAF658E8\
+2ED1C78631FD23B4C3EB27C3FAEC8685:\
+498741AC645D7C49BF3692D5A4430755B3AEABAD508818CAC453E92C07EABC8D\
+46706D457F98C73BCAC4673532F46A59
+
+447797E2899B72A356BA55BF4DF3ACCA6CDB1041EB477BD1834A9F9ACBC340A2\
+94D729F2F97DF3A610BE0FF15EDB9C6D5DB41644B9874360140FC64F52AA03F0\
+286C8A640670067A84E017926A70438DB1BB361DEFEE7317021425F8821DEF26\
+D1EFD77FC853B818545D055ADC9284796E583C76E6FE74C9AC2587AA46AA8F88\
+04F2FEB5836CC4B3ABABAB8429A5783E17D5999F32242EB59EF30CD7ADABC16D\
+72DBDB097623047C98989F88D14EAF02A7212BE16EC2D07981AAA99949DDF89E\
+CD90333A77BC4E1988A82ABF7C7CAF3291:\
+C970B0BD69D87EEA8AB00F8BD58CD0CC5E96C2ED43A667553308041A47C32BBB\
+1FB477CF8B53520D56A243E2F6BBA29A
+
+9F2C18ADE9B380C784E170FB763E9AA205F64303067EB1BCEA93DF5DAC4BF5A2\
+E00B78195F808DF24FC76E26CB7BE31DC35F0844CDED1567BBA29858CFFC97FB\
+29010331B01D6A3FB3159CC1B973D255DA9843E34A0A4061CABDB9ED37F241BF\
+ABB3C20D32743F4026B59A4CCC385A2301F83C0B0A190B0F2D01ACB8F0D41111\
+E10F2F4E149379275599A52DC089B35FDD5234B0CFB7B6D8AEBD563CA1FA653C\
+5C021DFD6F5920E6F18BFAFDBECBF0AB00281333ED50B9A999549C1C8F8C63D7\
+626C48322E9791D5FF72294049BDE91E73F8:\
+6679FD777C2E4DD03DA3EE5617CBF583710935D786828A8DAE1A4C8411DFD453\
+8059D6FEB97973BEEB621E2C7835D4F7
+
+AE159F3FA33619002AE6BCCE8CBBDD7D28E5ED9D61534595C4C9F43C402A9BB3\
+1F3B301CBFD4A43CE4C24CD5C9849CC6259ECA90E2A79E01FFBAC07BA0E147FA\
+42676A1D668570E0396387B5BCD599E8E66AAED1B8A191C5A47547F61373021F\
+A6DEADCB55363D233C24440F2C73DBB519F7C9FA5A8962EFD5F6252C0407F190\
+DFEFAD707F3C7007D69FF36B8489A5B6B7C557E79DD4F50C06511F599F56C896\
+B35C917B63BA35C6FF8092BAF7D1658E77FC95D8A6A43EEB4C01F33F03877F92\
+774BE89C1114DD531C011E53A34DC248A2F0E6:\
+9AD437DD093F9D3A6C2C763CF911658EEAE0AC9976914D353CED96A9F6714757\
+B41E6B2572CA34EBA5ACB0B1BE862C0E
+
+3B8E97C5FFC2D6A40FA7DE7FCEFC90F3B12C940E7AB415321E29EE692DFAC799\
+B009C99DCDDB708FCE5A178C5C35EE2B8617143EDC4C40B4D313661F49ABDD93\
+CEA79D117518805496FE6ACF292C4C2A1F76B403A97D7C399DAF85B46AD84E16\
+246C67D6836757BDE336C290D5D401E6C1386AB32797AF6BB251E9B2D8FE754C\
+47482B72E0B394EAB76916126FD68EA7D65EB93D59F5B4C5AC40F7C3B37E7F36\
+94F29424C24AF8C8F0EF59CD9DBF1D28E0E10F799A6F78CAD1D45B9DB3D7DEE4\
+A7059ABE99182714983B9C9D44D7F5643596D4F3:\
+5A0AABA2258361DA8D53BEBBE3C326C47CD08A681D5BED148909F7B691AE91F3\
+C53DFE1F364DDA82C9FB73EB2F632F15
+
+3434EC31B10FAFDBFEEC0DD6BD94E80F7BA9DCA19EF075F7EB017512AF66D6A4\
+BCF7D16BA0819A1892A6372F9B35BCC7CA8155EE19E8428BC22D214856ED5FA9\
+374C3C09BDE169602CC219679F65A1566FC7316F4CC3B631A18FB4449FA6AFA1\
+6A3DB2BC4212EFF539C67CF184680826535589C7111D73BFFCE431B4C40492E7\
+63D9279560AAA38EB2DC14A212D723F994A1FE656FF4DD14551CE4E7C621B2AA\
+5604A10001B2878A897A28A08095C325E10A26D2FB1A75BFD64C250309BB55A4\
+4F23BBAC0D5516A1C687D3B41EF2FBBF9CC56D4739:\
+444F16F77ED3EF011B24AF14453E20E72AF793AAE853A718FB2B3F6AD7FD6F5A\
+532F6B253C405D67621EAC61FDE7568C
+
+7C7953D81C8D208FD1C97681D48F49DD003456DE60475B84070EF4847C333B74\
+575B1FC8D2A186964485A3B8634FEAA3595AAA1A2F4595A7D6B6153563DEE31B\
+BAC443C8A33EED6D5D956A980A68366C2527B550EE950250DFB691EACBD5D56A\
+E14B970668BE174C89DF2FEA43AE52F13142639C884FD62A3683C0C3792F0F24\
+AB1318BCB27E21F4737FAB62C77EA38BC8FD1CF41F7DAB64C13FEBE7152BF5BB\
+7AB5A78F5346D43CC741CB6F72B7B8980F268B68BF62ABDFB1577A52438FE14B\
+591498CC95F071228460C7C5D5CEB4A7BDE588E7F21C:\
+71F2954EEEBF619C400341BF1BF3E108026655E0D79F83D55CACFA44812AA2FE\
+D065434CDCC533641C29F95ADE893B88
+
+7A6A4F4FDC59A1D223381AE5AF498D74B7252ECF59E389E49130C7EAEE626E7B\
+D9897EFFD92017F4CCDE66B0440462CDEDFD352D8153E6A4C8D7A0812F701CC7\
+37B5178C2556F07111200EB627DBC299CAA792DFA58F35935299FA3A3519E9B0\
+3166DFFA159103FFA35E8577F7C0A86C6B46FE13DB8E2CDD9DCFBA85BDDDCCE0\
+A7A8E155F81F712D8E9FE646153D3D22C811BD39F830433B2213DD46301941B5\
+9293FD0A33E2B63ADBD95239BC01315C46FDB678875B3C81E053A40F581CFBEC\
+24A1404B1671A1B88A6D06120229518FB13A74CA0AC5AE:\
+CF14A88F577F8B166ECE3945F93A83FDA5CD6BFFA9E599971F2928D921586813\
+ECEF65F2697DAE386B736CA7B30FEE35
+
+D9FAA14CEBE9B7DE551B6C0765409A33938562013B5E8E0E1E0A6418DF7399D0\
+A6A771FB81C3CA9BD3BB8E2951B0BC792525A294EBD1083688806FE5E7F1E17F\
+D4E3A41D00C89E8FCF4A363CAEDB1ACB558E3D562F1302B3D83BB886ED27B760\
+33798131DAB05B4217381EAAA7BA15EC820BB5C13B516DD640EAEC5A27D05FDF\
+CA0F35B3A5312146806B4C0275BCD0AAA3B2017F346975DB566F9B4D137F4EE1\
+0644C2A2DA66DEECA5342E236495C3C6280528BFD32E90AF4CD9BB908F34012B\
+52B4BC56D48CC8A6B59BAB014988EABD12E1A0A1C2E170E7:\
+ACD67AA725CFA1C23E1D0EAA4732CE67B15EDC2015B455ECFB6584708D07BC4C\
+286E820C256E130396338A4E2F561E6C
+
+2D8427433D0C61F2D96CFE80CF1E932265A191365C3B61AAA3D6DCC039F6BA2A\
+D52A6A8CC30FC10F705E6B7705105977FA496C1C708A277A124304F1FC40911E\
+7441D1B5E77B951AAD7B01FD5DB1B377D165B05BBF898042E39660CAF8B279FE\
+5229D1A8DB86C0999ED65E53D01CCBC4B43173CCF992B3A14586F6BA42F5FE30\
+AFA8AE40C5DF29966F9346DA5F8B35F16A1DE3AB6DE0F477D8D8660918060E88\
+B9B9E9CA6A4207033B87A812DBF5544D39E4882010F82B6CE005F8E8FF6FE3C3\
+806BC2B73C2B83AFB704345629304F9F86358712E9FAE3CA3E:\
+C8F92626C72916F9D9394391F00ABF203C2584889D49E78607F5C56F1A9AA3D7\
+D9B242329F4A208BB4CE6CDF75696681
+
+5E19D97887FCAAC0387E22C6F803C34A3DACD2604172433F7A8A7A526CA4A2A1\
+271ECFC5D5D7BE5AC0D85D921095350DFC65997D443C21C8094E0A3FEFD2961B\
+CB94AED03291AE310CCDA75D8ACE4BC7D89E7D3E5D1650BDA5D668B8B50BFC8E\
+608E184F4D3A9A2BADC4FF5F07E0C0BC8A9F2E0B2A26FD6D8C550008FAAAB75F\
+D71AF2A424BEC9A7CD9D83FAD4C8E9319115656A8717D3B523A68FF8004258B9\
+990ED362308461804BA3E3A7E92D8F2FFAE5C2FBA55BA5A3C27C0A2F71BD711D\
+2FE1799C2ADB31B200035481E9EE5C4ADF2AB9C0FA50B23975CF:\
+713FBC5CD55251312A505E4E4AC540AC439F71EE7545F89039DDCE1BAD4DEBD8\
+D42275EF803C65AF0E0055FED0C06ECB
+
+C8E976AB4638909387CE3B8D4E510C3230E5690E02C45093B1D297910ABC481E\
+56EEA0F296F98379DFC9080AF69E73B2399D1C143BEE80AE1328162CE1BA7F6A\
+8374679B20AACD380EB4E61382C99998704D62701AFA914F9A2705CDB065885F\
+50D086C3EB5753700C387118BB142F3E6DA1E988DFB31AC75D7368931E45D139\
+1A274B22F83CEB072F9BCABC0B216685BFD789F5023971024B1878A205442522\
+F9EA7D8797A4102A3DF41703768251FD5E017C85D1200A464118AA35654E7CA3\
+9F3C375B8EF8CBE7534DBC64BC20BEFB417CF60EC92F63D9EE7397:\
+40E904CF844BEBA5083EDCA65BE3874FA98AD7E15EAAA5DEF49E8F16DC67630A\
+A51C3876C3214A179CB8C4EE0B55840B
+
+7145FA124B7429A1FC2231237A949BA7201BCC1822D3272DE005B682398196C2\
+5F7E5CC2F289FBF44415F699CB7FE6757791B1443410234AE061EDF623359E2B\
+4E32C19BF88450432DD01CAA5EB16A1DC378F391CA5E3C4E5F356728BDDD4975\
+DB7C890DA8BBC84CC73FF244394D0D48954978765E4A00B593F70F2CA082673A\
+261ED88DBCEF1127728D8CD89BC2C597E9102CED6010F65FA75A14EBE467FA57\
+CE3BD4948B6867D74A9DF5C0EC6F530CBF2EE61CE6F06BC8F2864DFF5583776B\
+31DF8C7FFCB61428A56BF7BD37188B4A5123BBF338393AF46EDA85E6:\
+13CF8E684B995858EEE9C0D812DB851D29B927744457987AE97D57833B11D87B\
+ADE949C5EF5131C8541D613F40C7551D
+
+7FDFADCC9D29BAD23AE038C6C65CDA1AEF757221B8872ED3D75FF8DF7DA0627D\
+266E224E812C39F7983E4558BFD0A1F2BEF3FEB56BA09120EF762917B9C09386\
+7948547AEE98600D10D87B20106878A8D22C64378BF634F7F75900C03986B077\
+B0BF8B740A82447B61B99FEE5376C5EB6680EC9E3088F0BDD0C56883413D60C1\
+357D3C811950E5890E7600103C916341B80C743C6A852B7B4FB60C3BA21F3BC1\
+5B8382437A68454779CF3CD7F9F90CCC8EF28D0B706535B1E4108EB5627BB45D\
+719CB046839AEE311CA1ABDC8319E050D67972CB35A6B1601B25DBF487:\
+6490DEE37949D51317BD0F45F201ABC00106A671189D243C54B254CF1FFC5DEB\
+1D1E28C07E5F2226C2860CA05F257566
+
+988638219FD3095421F826F56E4F09E356296B628C3CE6930C9F2E758FD1A80C\
+8273F2F61E4DAAE65C4F110D3E7CA0965AC7D24E34C0DC4BA2D6FF0BF5BBE93B\
+3585F354D7543CB542A1AA54674D375077F2D360A8F4D42F3DB131C3B7AB7306\
+267BA107659864A90C8C909460A73621D1F5D9D3FD95BEB19B23DB1CB6C0D0FB\
+A91D36891529B8BD8263CAA1BAB56A4AFFAED44962DF096D8D5B1EB845EF3118\
+8B3E10F1AF811A13F156BEB7A288AAE593EBD1471B624AA1A7C6ADF01E2200B3\
+D72D88A3AED3100C88231E41EFC376906F0B580DC895F080FDA5741DB1CB:\
+5622C8B591C19D263DB8950A2BBC681C461B21967FB01D77B3F0CEE2C1FA2573\
+752E2945A351E54E690EBA7CC303E6B8
+
+5AAB62756D307A669D146ABA988D9074C5A159B3DE85151A819B117CA1FF6597\
+F6156E80FDD28C9C3176835164D37DA7DA11D94E09ADD770B68A6E081CD22CA0\
+C004BFE7CD283BF43A588DA91F509B27A6584C474A4A2F3EE0F1F56447379240\
+A5AB1FB77FDCA49B305F07BA86B62756FB9EFB4FC225C86845F026EA542076B9\
+1A0BC2CDD136E122C659BE259D98E5841DF4C2F60330D4D8CDEE7BF1A0A24452\
+4EECC68FF2AEF5BF0069C9E87A11C6E519DE1A4062A10C83837388F7EF58598A\
+3846F49D499682B683C4A062B421594FAFBC1383C943BA83BDEF515EFCF10D:\
+F3538F2AD8A797B94F5DE5A4B89945CFFE0C8DC5EE49B35FBEC2D66D39DD6F50\
+12389F25FA64EDA30AB938093D72B1B3
+
+47B8216AA0FBB5D67966F2E82C17C07AA2D6327E96FCD83E3DE7333689F3EE79\
+994A1BF45082C4D725ED8D41205CB5BCDF5C341F77FACB1DA46A5B9B2CBC49EA\
+DF786BCD881F371A95FA17DF73F606519AEA0FF79D5A11427B98EE7F13A5C006\
+37E2854134691059839121FEA9ABE2CD1BCBBBF27C74CAF3678E05BFB1C94989\
+7EA01F56FFA4DAFBE8644611685C617A3206C7A7036E4AC816799F693DAFE7F1\
+9F303CE4EBA09D21E03610201BFC665B72400A547A1E00FA9B7AD8D84F84B34A\
+EF118515E74DEF11B9188BD1E1F97D9A12C30132EC2806339BDADACDA2FD8B78:\
+44CF18335ED47D3858FD30559CB02ECD5BC57970DC9E17EC6D648DF8B104CB69\
+6B2008C2769A89BB4C0DE8B9C7CC2316
+
+8CFF1F67FE53C098896D9136389BD8881816CCAB34862BB67A656E3D98896F3C\
+E6FFD4DA73975809FCDF9666760D6E561C55238B205D8049C1CEDEEF374D1735\
+DAA533147BFA960B2CCE4A4F254176BB4D1BD1E89654432B8DBE1A135C42115B\
+394B024856A2A83DC85D6782BE4B444239567CCEC4B184D4548EAE3FF6A192F3\
+43292BA2E32A0F267F31CC26719EB85245D415FB897AC2DA433EE91A99424C9D\
+7F1766A44171D1651001C38FC79294ACCC68CEB5665D36218454D3BA169AE058\
+A831338C17743603F81EE173BFC0927464F9BD728DEE94C6AEAB7AAE6EE3A627\
+E8:\
+684F56F8E5F781F6E9429769733BBF32CB7CB91A7EB4E0880BCB6528B850DC82\
+BC5E00EDC7D0A1FD9680A96A0C88D741
+
+EACD07971CFF9B9939903F8C1D8CBB5D4DB1B548A85D04E037514A583604E787\
+F32992BF2111B97AC5E8A938233552731321522AB5E8583561260B7D13EBEEF7\
+85B23A41FD8576A6DA764A8ED6D822D4957A545D5244756C18AA80E1AAD4D1F9\
+C20D259DEE1711E2CC8FD013169FB7CC4CE38B362F8E0936AE9198B7E838DCEA\
+4F7A5B9429BB3F6BBCF2DC92565E3676C1C5E6EB3DD2A0F86AA23EDD3D0891F1\
+97447692794B3DFA269611AD97F72B795602B4FDB198F3FD3EB41B415064256E\
+345E8D8C51C555DC8A21904A9B0F1AD0EFFAB7786AAC2DA3B196507E9F33CA35\
+6427:\
+20541C2A62B48EB7CC3B51D867AA5589DE2A15262083002ADAE540038C444425\
+3B05B6A54D67987963C7C2DA91BB0CA3
+
+23AC4E9A42C6EF45C3336CE6DFC2FF7DE8884CD23DC912FEF0F7756C09D335C1\
+89F3AD3A23697ABDA851A81881A0C8CCAFC980AB2C702564C2BE15FE4C4B9F10\
+DFB2248D0D0CB2E2887FD4598A1D4ACDA897944A2FFC580FF92719C95CF2AA42\
+DC584674CB5A9BC5765B9D6DDF5789791D15F8DD925AA12BFFAFBCE60827B490\
+BB7DF3DDA6F2A143C8BF96ABC903D83D59A791E2D62814A89B8080A28060568C\
+F24A80AE61179FE84E0FFAD00388178CB6A617D37EFD54CC01970A4A41D1A8D3\
+DDCE46EDBBA4AB7C90AD565398D376F431189CE8C1C33E132FEAE6A8CD17A61C\
+630012:\
+B66EA21D2A4AD66E9AC2C935CEA581D6E798FE77E26C5A092A1565D280C563B9\
+55F0B9C5969409ADD68F23753B0E10F7
+
+0172DF732282C9D488669C358E3492260CBE91C95CFBC1E3FEA6C4B0EC129B45\
+F242ACE09F152FC6234E1BEE8AAB8CD56E8B486E1DCBA9C05407C2F95DA8D8F1\
+C0AF78EE2ED82A3A79EC0CB0709396EE62AADB84F8A4EE8A7CCCA3C1EE84E302\
+A09EA802204AFECF04097E67D0F8E8A9D2651126C0A598A37081E42D168B0AE8\
+A71951C524259E4E2054E535B779679BDADE566FE55700858618E626B4A0FAF8\
+95BCCE9011504A49E05FD56127EAE3D1F8917AFB548ECADABDA1020111FEC931\
+4C413498A360B08640549A22CB23C731ACE743252A8227A0D2689D4C60016066\
+78DFB921:\
+588433FC26C41E9854F2AEF43306043851BCCE4AFD782911599FF05EB01A5CEF\
+51BFF7A0F141948FCC989B56F5DC85B5
+
+3875B9240CF3E0A8B59C658540F26A701CF188496E2C2174788B126FD29402D6\
+A75453BA0635284D08835F40051A2A9683DC92AFB9383719191231170379BA6F\
+4ADC816FECBB0F9C446B785BF520796841E58878B73C58D3EBB097CE4761FDEA\
+BE15DE2F319DFBAF1742CDEB389559C788131A6793E193856661376C81CE9568\
+DA19AA6925B47FFD77A43C7A0E758C37D69254909FF0FBD415EF8EB937BCD49F\
+91468B49974C07DC819ABD67395DB0E05874FF83DDDAB895344ABD0E7111B2DF\
+9E58D76D85AD98106B36295826BE04D435615595605E4B4BB824B33C4AFEB5E7\
+BB0D19F909:\
+7AE8CC1E77BE9459E0F2449AC99EF9978F2A4587E877AEE8DF639E6655685957\
+A267E3766099612D2FDC8A83694276B9
+
+747CC1A59FEFBA94A9C75BA866C30DC5C1CB0C0F8E9361D98484956DD5D1A40F\
+6184AFBE3DAC9F76028D1CAECCFBF69199C6CE2B4C092A3F4D2A56FE5A33A007\
+57F4D7DEE5DFB0524311A97AE0668A47971B95766E2F6DD48C3F57841F91F04A\
+00AD5EA70F2D479A2620DC5CD78EAAB3A3B011719B7E78D19DDF70D9423798AF\
+77517EBC55392FCD01FC600D8D466B9E7A7A85BF33F9CC5419E9BD874DDFD609\
+81150DDAF8D7FEBAA4374F0872A5628D318000311E2F5655365AD4D407C20E5C\
+04DF17A222E7DEEC79C5AB1116D8572F91CD06E1CCC7CED53736FC867FD49ECE\
+BE6BF8082E8A:\
+A064A6AC91429EB63A0B2D97DFA3B3F07A273BCB87363FECF6831AB6534B5D60\
+2CEABA051B4CA62871E583406964E64B
+
+57AF971FCCAEC97435DC2EC9EF0429BCEDC6B647729EA168858A6E49AC1071E7\
+06F4A5A645CA14E8C7746D65511620682C906C8B86EC901F3DDED4167B3F00B0\
+6CBFAC6AEE3728051B3E5FF10B4F9ED8BD0B8DA94303C833755B3CA3AEDDF0B5\
+4BC8D6632138B5D25BAB03D17B3458A9D782108006F5BB7DE75B5C0BA854B423\
+D8BB801E701E99DC4FEAAD59BC1C7112453B04D33EA3635639FB802C73C2B71D\
+58A56BBD671B18FE34ED2E3DCA38827D63FDB1D4FB3285405004B2B3E26081A8\
+FF08CD6D2B08F8E7B7E90A2AB1ED7A41B1D0128522C2F8BFF56A7FE67969422C\
+E839A9D4608F03:\
+D72F778BA9B333AC61183BC8D84D6D4BFA51809519BF0E5081985276BA1A3F4E\
+9F4E191D208C7519771D348D4C3E29CA
+
+04E16DEDC1227902BAAF332D3D08923601BDD64F573FAA1BB7201918CFE16B1E\
+10151DAE875DA0C0D63C59C3DD050C4C6A874011B018421AFC4623AB0381831B\
+2DA2A8BA42C96E4F70864AC44E106F94311051E74C77C1291BF5DB9539E69567\
+BF6A11CF6932BBBAD33F8946BF5814C066D851633D1A513510039B349939BFD4\
+2B858C21827C8FF05F1D09B1B0765DC78A135B5CA4DFBA0801BCADDFA175623C\
+8B647EACFB4444B85A44F73890607D06D507A4F8393658788669F6EF4DEB58D0\
+8C50CA0756D5E2F49D1A7AD73E0F0B3D3B5F090ACF622B1878C59133E4A848E0\
+5153592EA81C6FBF:\
+A1C0E86F0093538477619E9DB75EF5881821FD9BCC00FD6590C815FB2DA59AAF\
+59C151F02DDE9B840841ADCAEEC72698
+
+7C815C384EEE0F288ECE27CCED52A01603127B079C007378BC5D1E6C5E9E6D1C\
+735723ACBBD5801AC49854B2B569D4472D33F40BBB8882956245C366DC3582D7\
+1696A97A4E19557E41E54DEE482A14229005F93AFD2C4A7D8614D10A97A9DFA0\
+7F7CD946FA45263063DDD29DB8F9E34DB60DAA32684F0072EA2A9426ECEBFA52\
+39FB67F29C18CBAA2AF6ED4BF4283936823AC1790164FEC5457A9CBA7C767CA5\
+9392D94CAB7448F50EB34E9A93A80027471CE59736F099C886DEA1AB4CBA4D89\
+F5FC7AE2F21CCD27F611ECA4626B2D08DC22382E92C1EFB2F6AFDC8FDC3D2172\
+604F5035C46B8197D3:\
+26A5D1D67AAE51F8A14A6DC2E42264FC62F63F73F6F6FF58AA02888D276D5C8F\
+F77862E8C4B59D4D53D516C208A85064
+
+E29D505158DBDD937D9E3D2145658EE6F5992A2FC790F4F608D9CDB44A091D5B\
+94B88E81FAC4FDF5C49442F13B911C55886469629551189EAFF62488F1A479B7\
+DB11A1560E198DDCCCCF50159093425FF7F1CB8D1D1246D0978764087D6BAC25\
+7026B090EFAE8CEC5F22B6F21C59ACE1AC7386F5B8837CA6A12B6FBF5534DD05\
+60EF05CA78104D3B943DDB220FEAEC89AA5E692A00F822A2AB9A2FE60350D75E\
+7BE16FF2526DC643872502D01F42F188ABED0A6E9A6F5FD0D1CE7D5755C9FFA6\
+6B0AF0B20BD806F08E06156690D81AC811778CA3DAC2C249B96002017FCE93E5\
+07E3B953ACF99964B847:\
+EE7B56D5135AC16823C49E65BDFABC83C8AB96778FB2FDBC9A32CE79CCB1AE7C\
+18CA39B48FFB8E9F0EBA584BD1CD1BA6
+
+D85588696F576E65ECA0155F395F0CFACD83F36A99111ED5768DF2D116D2121E\
+32357BA4F54EDE927F189F297D3A97FAD4E9A0F5B41D8D89DD7FE20156799C2B\
+7B6BF9C957BA0D6763F5C3BC5129747BBB53652B49290CFF1C87E2CDF2C4B95D\
+8AAEE09BC8FBFA6883E62D237885810491BFC101F1D8C636E3D0EDE838AD05C2\
+07A3DF4FAD76452979EB99F29AFAECEDD1C63B8D36CF378454A1BB67A741C77A\
+C6B6B3F95F4F02B64DABC15438613EA49750DF42EE90101F115AA9ABB9FF6432\
+4DDE9DABBB01054E1BD6B4BCDC7930A44C2300D87CA78C06924D0323AD7887E4\
+6C90E8C4D100ACD9EED21E:\
+94A3FEEE9C2554CF6732A7C87617FF6D067FF7851DC5148B6FC98F6E5EB1E65F\
+8917B14F7BA3295684869016383E7239
+
+3A12F8508B40C32C74492B66323375DCFE49184C78F73179F3314B79E63376B8\
+AC683F5A51F1534BD729B02B04D002F55CBD8E8FC9B5EC1EA6BBE6A0D0E74315\
+18E6BA45D124035F9D3DCE0A8BB7BF1430A9F657E0B4EA9F20EB20C786A58181\
+A1E20A96F1628F8728A13BDF7A4B4B32FC8AA7054CC4881AE7FA19AFA65C6C3E\
+E1B3ADE3192AF42054A8A911B8EC1826865D46D93F1E7C5E2B7813C92A506E53\
+886F3D4701BB93D2A681AD109C845904BB861AF8AF0646B6E399B38B614051D3\
+4F6842563A0F37EC00CB3D865FC5D746C4987DE2A65071100883A2A9C7A2BFE1\
+E2DD603D9EA24DC7C5FD06BE:\
+FD5707477DB367FB95AA0716703514CE3401637741D86CC0688CB879C82D59DE\
+4AE720B3E2F018A665D1F0FBD9562943
+
+1861EDCE46FA5AD17E1FF1DEAE084DEC580F97D0A67885DFE834B9DFAC1AE076\
+742CE9E267512CA51F6DF5A455AF0C5FD6ABF94ACEA103A3370C354485A7846F\
+B84F3AC7C2904B5B2FBF227002CE512133BB7E1C4E50057BFD1E44DB33C7CDB9\
+69A99E284B184F50A14B068A1FC5009D9B298DBE92239572A7627AAC02ABE8F3\
+E3B473417F36D4D2505D16B7577F4526C9D94A270A2DFE450D06DA8F6FA95687\
+9A0A55CFE99E742EA555EA477BA3E9B44CCD508C375423611AF92E55345DC215\
+779B2D5119EBA49C71D49B9FE3F1569FA24E5CA3E332D042422A8B8158D3EC66\
+A80012976F31FFDF305F0C9C5E:\
+94A27262B344E01233FBA98BEBDB822DA06BD22E0286ABF3ADA616AAD34049A0\
+8FF1A9D0FD4FAD9666C2AAD6F796CC97
+
+08D0FFDE3A6E4EF65608EA672E4830C12943D7187CCFF08F4941CFC13E545F3B\
+9C7AD5EEBBE2B01642B486CAF855C2C73F58C1E4E3391DA8E2D63D96E15FD849\
+53AE5C231911B00AD6050CD7AAFDAAC9B0F663AE6AAB45519D0F5391A541707D\
+479034E73A6AD805AE3598096AF078F1393301493D663DD71F83869CA27BA508\
+B7E91E81E128C1716DC3ACFE3084B2201E04CF8006617EECF1B640474A5D45CF\
+DE9F4D3EF92D6D055B909892194D8A8218DB6D8203A84261D200D71473D7488F\
+3427416B6896C137D455F231071CACBC86E0415AB88AEC841D96B7B8AF41E05B\
+B461A40645BF176601F1E760DE5F:\
+E3C7C87442779B40EC9ADAF74430144DE108515CABC232B70D3157BED0B17FA4\
+907E84F2C3FE23720A3031E7ECE5B187
+
+D782ABB72A5BE3392757BE02D3E45BE6E2099D6F000D042C8A543F50ED6EBC05\
+5A7F133B0DD8E9BC348536EDCAAE2E12EC18E8837DF7A1B3C87EC46D50C241DE\
+E820FD586197552DC20BEEA50F445A07A38F1768A39E2B2FF05DDDEDF751F1DE\
+F612D2E4D810DAA3A0CC904516F9A43AF660315385178A529E51F8AAE141808C\
+8BC5D7B60CAC26BB984AC1890D0436EF780426C547E94A7B08F01ACBFC4A3825\
+EAE04F520A9016F2FB8BF5165ED12736FC71E36A49A73614739EAA3EC834069B\
+1B40F1350C2B3AB885C02C640B9F7686ED5F99527E41CFCD796FE4C256C91731\
+86C226169FF257954EBDA81C0E5F99:\
+13183BC4EB545F24B5803F49BC278F64EFFE1F688E2DB09DBC01FA9B67DF38CF\
+15B9B5F7827D02F4B731F168CA413F7E
+
+5FCE8109A358570E40983E1184E541833BB9091E280F258CFB144387B05D190E\
+431CB19BAA67273BA0C58ABE91308E1844DCD0B3678BAA42F335F2FA05267A02\
+40B3C718A5942B3B3E3BFA98A55C25A1466E8D7A603722CB2BBF03AFA54CD769\
+A99F310735EE5A05DAE2C22D397BD95635F58C48A67F90E1B73AAFCD3F82117F\
+0166657838691005B18DA6F341D6E90FC1CDB352B30FAE45D348294E501B6325\
+2DE14740F2B85AE5299DDEC3172DE8B6D0BA219A20A23BB5E10FF434D39DB3F5\
+83305E9F5C039D98569E377B75A70AB837D1DF269B8A4B566F40BB91B577455F\
+D3C356C914FA06B9A7CE24C7317A172D:\
+FE98D2252804D32171AE2DBF85B70F7F4CC639CFC93F37167862A2AE493370F1\
+3333393E3FAAD85C0F371AC40BEC3E72
+
+6172F1971A6E1E4E6170AFBAD95D5FEC99BF69B24B674BC17DD78011615E502D\
+E6F56B86B1A71D3F4348087218AC7B7D09302993BE272E4A591968AEF18A1262\
+D665610D1070EE91CC8DA36E1F841A69A7A682C580E836941D21D909A3AFC1F0\
+B963E1CA5AB193E124A1A53DF1C587470E5881FB54DAE1B0D840F0C8F9D1B04C\
+645BA1041C7D8DBF22030A623AA15638B3D99A2C400FF76F3252079AF88D2B37\
+F35EE66C1AD7801A28D3D388AC450B97D5F0F79E4541755356B3B1A5696B023F\
+39AB7AB5F28DF4202936BC97393B93BC915CB159EA1BD7A0A414CB4B7A1AC3AF\
+68F50D79F0C9C7314E750F7D02FAA58BFA:\
+05E1DC86EE49D63E3F674B402A4280F682C73834BB2BF9759AC9466922B5D3BB\
+4275B04E090FD5194347B3F13268ED93
+
+5668ECD99DFBE215C4118398AC9C9EAF1A1433FAB4CCDD3968064752B625EA94\
+4731F75D48A27D047D67547F14DD0FFAA55FA5E29F7AF0D161D85EAFC4F2029B\
+717C918EAB9D304543290BDBA7158B68020C0BA4E079BC95B5BC0FC044A992B9\
+4B4CCD3BD66D0EABB5DBBAB904D62E00752C4E3B0091D773BCF4C14B4377DA3E\
+FFF824B1CB2FA01B32D1E46C909E626ED2DAE920F4C7DBEB635BC754FACBD8D4\
+9BEBA3F23C1C41CCBFCD0EE0C114E69737F5597C0BF1D859F0C767E18002AE8E\
+39C26261FFDE2920D3D0BAF0E906138696CFE5B7E32B600F45DF3AAA39932F3A\
+7DF95B60FA8712A2271FCAF3911CE7B511B1:\
+583C37FB2932A6FE22795CB74725B33EE2F13228CDF81ACDCE7DBAC4D2086805\
+6AA2F256C7A382A8D2300F34C73A2F44
+
+03D625488354DF30E3F875A68EDFCF340E8366A8E1AB67F9D5C5486A96829DFA\
+C0578289082B2A62117E1CF418B43B90E0ADC881FC6AE8105C888E9ECD21AEA1\
+C9AE1A4038DFD17378FED71D02AE492087D7CDCD98F746855227967CB1AB4714\
+261EE3BEAD3F4DB118329D3EBEF4BC48A875C19BA763966DA0EBEA800E01B2F5\
+0B00E9DD4CACA6DCB314D00184EF71EA2391D760C950710DB4A70F9212FFC548\
+61F9DC752CE18867B8AD0C48DF8466EF7231E7AC567F0EB55099E622EBB86CB2\
+37520190A61C66AD34F1F4E289CB3282AE3EAAC6152ED24D2C92BAE5A7658252\
+A53C49B7B02DFE54FDB2E90074B6CF310AC661:\
+3AC6EC41E7DB66408273C6AF2526099737A3F29E2D567BA37F7CF678F3E42978\
+D93CAAF8AFB06540591ABA9F767A1364
+
+2EDC282FFB90B97118DD03AAA03B145F363905E3CBD2D50ECD692B37BF000185\
+C651D3E9726C690D3773EC1E48510E42B17742B0B0377E7DE6B8F55E00A8A4DB\
+4740CEE6DB0830529DD19617501DC1E9359AA3BCF147E0A76B3AB70C4984C13E\
+339E6806BB35E683AF8527093670859F3D8A0FC7D493BCBA6BB12B5F65E71E70\
+5CA5D6C948D66ED3D730B26DB395B3447737C26FAD089AA0AD0E306CB28BF0AC\
+F106F89AF3745F0EC72D534968CCA543CD2CA50C94B1456743254E358C1317C0\
+7A07BF2B0ECA438A709367FAFC89A57239028FC5FECFD53B8EF958EF10EE0608\
+B7F5CB9923AD97058EC067700CC746C127A61EE3:\
+F96FF1F5D0FCB2A167141E91F18E04DD039E74822D65F7826E6CA3605CB9385C\
+DA5EA194866FBE7F91699ABF707CA11A
+
+90B28A6AA1FE533915BCB8E81ED6CACDC10962B7FF82474F845EEB86977600CF\
+70B07BA8E3796141EE340E3FCE842A38A50AFBE90301A3BDCC591F2E7D9DE53E\
+495525560B908C892439990A2CA2679C5539FFDF636777AD9C1CDEF809CDA9E8\
+DCDB451ABB9E9C17EFA4379ABD24B182BD981CAFC792640A183B61694301D04C\
+5B3EAAD694A6BD4CC06EF5DA8FA23B4FA2A64559C5A68397930079D250C51BCF\
+00E2B16A6C49171433B0AADFD80231276560B80458DD77089B7A1BBCC9E7E4B9\
+F881EACD6C92C4318348A13F4914EB27115A1CFC5D16D7FD94954C3532EFACA2\
+CAB025103B2D02C6FD71DA3A77F417D7932685888A:\
+A8C1CAE5BB4C53D9BC76EF0BF67B1A257A041F74CE59F9B0B5300F1FF185B2C1\
+C74FE82618BDE4143E43DD6F876C988B
+
+2969447D175490F2AA9BB055014DBEF2E6854C95F8D60950BFE8C0BE8DE254C2\
+6B2D31B9E4DE9C68C9ADF49E4EE9B1C2850967F29F5D08738483B417BB96B2A5\
+6F0C8ACA632B552059C59AAC3F61F7B45C966B75F1D9931FF4E596406378CEE9\
+1AAA726A3A84C33F37E9CDBE626B5745A0B06064A8A8D56E53AAF102D23DD9DF\
+0A3FDF7A638509A6761A33FA42FA8DDBD8E16159C93008B53765019C3F0E9F10\
+B144CE2AC57F5D7297F9C9949E4FF68B70D339F87501CE8550B772F32C6DA8AD\
+2CE2100A895D8B08FA1EEAD7C376B407709703C510B50F87E73E43F8E7348F87\
+C3832A547EF2BBE5799ABEDCF5E1F372EA809233F006:\
+519737FE0D3C60652F73CAD8222033ACE03BBCAB1BB96B1772658A92080ABD96\
+18F96B99AE3AE7932AD55C887B54BF91
+
+721645633A44A2C78B19024EAECF58575AB23C27190833C26875DC0F0D50B46A\
+EA9C343D82EA7D5B3E50EC700545C615DAEAEA64726A0F05607576DCD396D812\
+B03FB6551C641087856D050B10E6A4D5577B82A98AFB89CEE8594C9DC19E79FE\
+FF0382FCFD127F1B803A4B9946F4AC9A4378E1E6E041B1389A53E3450CD32D9D\
+2941B0CBABDB50DA8EA2513145164C3AB6BCBD251C448D2D4B087AC57A59C228\
+5D564F16DA4ED5E607ED979592146FFB0EF3F3DB308FB342DF5EB5924A48256F\
+C763141A278814C82D6D6348577545870AE3A83C7230AC02A1540FE1798F7EF0\
+9E335A865A2AE0949B21E4F748FB8A51F44750E213A8FB:\
+DF9E83758D502A5A3869697B415F411277BCE9A7638A99D912EAC710BEB3C86E\
+F90F7C41DB4D898A24E7E570745A145E
+
+6B860D39725A14B498BB714574B4D37CA787404768F64C648B1751B353AC92BA\
+C2C3A28EA909FDF0423336401A02E63EC24325300D823B6864BB701F9D7C7A1F\
+8EC9D0AE3584AA6DD62EA1997CD831B4BABD9A4DA50932D4EFDA745C61E41308\
+90E156AEE6113716DAF95764222A91187DB2EFFEA49D5D0596102D619BD26A61\
+6BBFDA8335505FBB0D90B4C180D1A2335B91538E1668F9F9642790B4E55F9CAB\
+0FE2BDD2935D001EE6419ABAB5457880D0DBFF20ED8758F4C20FE759EFB33141\
+CF0E892587FE8187E5FBC57786B7E8B089612C936DFC03D27EFBBE7C8673F160\
+6BD51D5FF386F4A7AB68EDF59F385EB1291F117BFE717399:\
+7E0A5E927B4D10A6430B368099C7B403E21F29BC66CD35F73E2013C8F24F1752\
+C88724E4A8970AE8050455E572FE0C82
+
+6A01830AF3889A25183244DECB508BD01253D5B508AB490D3124AFBF42626B2E\
+70894E9B562B288D0A2450CFACF14A0DDAE5C04716E5A0082C33981F6037D23D\
+5E045EE1EF2283FB8B6378A914C5D9441627A722C282FF452E25A7EA608D69CE\
+E4393A0725D17963D0342684F255496D8A18C2961145315130549311FC07F031\
+2FB78E6077334F87EAA873BEE8AA95698996EB21375EB2B4EF53C14401207DEB\
+4568398E5DD9A7CF97E8C9663E23334B46912F8344C19EFCF8C2BA6F04325F1A\
+27E062B62A58D0766FC6DB4D2C6A1928604B0175D872D16B7908EBC041761187\
+CC785526C2A3873FEAC3A642BB39F5351550AF9770C328AF7B:\
+C0826DB674835EB58C479DD02B95A1D14BD4C233B22E001AD5DFC10361EC2EA2\
+294F31DEC53DD08057B7F8D917C26821
+
+B3C5E74B69933C2533106C563B4CA20238F2B6E675E8681E34A389894785BDAD\
+E59652D4A73D80A5C85BD454FD1E9FFDAD1C3815F5038E9EF432AAC5C3C4FE84\
+0CC370CF86580A6011778BBEDAF511A51B56D1A2EB68394AA299E26DA9ADA6A2\
+F39B9FAFF7FBA457689B9C1A577B2A1E505FDF75C7A0A64B1DF81B3A356001BF\
+0DF4E02A1FC59F651C9D585EC6224BB279C6BEBA2966E8882D68376081B98746\
+8E7AED1EF90EBD090AE825795CDCA1B4F09A979C8DFC21A48D8A53CDBB26C4DB\
+547FC06EFE2F9850EDD2685A4661CB4911F165D4B63EF25B87D0A96D3DFF6AB0\
+758999AAD214D07BD4F133A6734FDE445FE474711B69A98F7E2B:\
+E36DB0361FF2713448930246EF3D9C325352B4F9211E428453038055E27C5A6F\
+3275546268A17B525BC6F661EE663F9A
+
+83AF34279CCB5430FEBEC07A81950D30F4B66F484826AFEE7456F0071A51E1BB\
+C55570B5CC7EC6F9309C17BF5BEFDD7C6BA6E968CF218A2B34BD5CF927AB846E\
+38A40BBD81759E9E33381016A755F699DF35D660007B5EADF292FEEFB735207E\
+BF70B5BD17834F7BFA0E16CB219AD4AF524AB1EA37334AA66435E5D397FC0A06\
+5C411EBBCE32C240B90476D307CE802EC82C1C49BC1BEC48C0675EC2A6C6F3ED\
+3E5B741D13437095707C565E10D8A20B8C20468FF9514FCF31B4249CD82DCEE5\
+8C0A2AF538B291A87E3390D737191A07484A5D3F3FB8C8F15CE056E5E5F8FEBE\
+5E1FB59D6740980AA06CA8A0C20F5712B4CDE5D032E92AB89F0AE1:\
+DA9526897C8B9B550AF90ABB2A8D57940E91254727C505F6E3551D988E6E1DA2\
+5A5C153AEBE3C6546DFBFBC5346A1205
+
+A7ED84749CCC56BB1DFBA57119D279D412B8A986886D810F067AF349E8749E9E\
+A746A60B03742636C464FC1EE233ACC52C1983914692B64309EDFDF29F1AB912\
+EC3E8DA074D3F1D231511F5756F0B6EEAD3E89A6A88FE330A10FACE267BFFBFC\
+3E3090C7FD9A850561F363AD75EA881E7244F80FF55802D5EF7A1A4E7B89FCFA\
+80F16DF54D1B056EE637E6964B9E0FFD15B6196BDD7DB270C56B47251485348E\
+49813B4EB9ED122A01B3EA45AD5E1A929DF61D5C0F3E77E1FDC356B63883A60E\
+9CBB9FC3E00C2F32DBD469659883F690C6772E335F617BC33F161D6F6984252E\
+E12E62B6000AC5231E0C9BC65BE223D8DFD94C5004A101AF9FD6C0FB:\
+5CD7038528211F12A21CBC69017C48E4AC4E361EB9B6CBC89A2907A86508E7FD\
+2A2B2CEC39A16AD412ADCE2AA4623755
+
+A6FE30DCFCDA1A329E82AB50E32B5F50EB25C873C5D2305860A835AECEE6264A\
+A36A47429922C4B8B3AFD00DA16035830EDB897831C4E7B00F2C23FC0B15FDC3\
+0D85FB70C30C431C638E1A25B51CAF1D7E8B050B7F89BFB30F59F0F20FECFF3D\
+639ABC4255B3868FC45DD81E47EB12AB40F2AAC735DF5D1DC1AD997CEFC4D836\
+B854CEE9AC02900036F3867FE0D84AFFF37BDE3308C2206C62C4743375094108\
+877C73B87B2546FE05EA137BEDFC06A2796274099A0D554DA8F7D7223A48CBF3\
+1B7DECAA1EBC8B145763E3673168C1B1B715C1CD99ECD3DDB238B06049885ECA\
+D9347C2436DFF32C771F34A38587A44A82C5D3D137A03CAA27E66C8FF6:\
+49DF9723D9FA56B7202AA9BD779D5AD33B7313015FEF57787AB34FEEC9D0033C\
+094009B585209A4B08F126285B5AB379
+
+83167FF53704C3AA19E9FB3303539759C46DD4091A52DDAE9AD86408B6933598\
+9E61414BC20AB4D01220E35241EFF5C9522B079FBA597674C8D716FE441E5661\
+10B6211531CECCF8FD06BC8E511D00785E57788ED9A1C5C73524F01830D2E114\
+8C92D0EDC97113E3B7B5CD3049627ABDB8B39DD4D6890E0EE91993F92B03354A\
+88F52251C546E64434D9C3D74544F23FB93E5A2D2F1FB15545B4E1367C97335B\
+0291944C8B730AD3D4789273FA44FB98D78A36C3C3764ABEEAC7C569C1E43A35\
+2E5B770C3504F87090DEE075A1C4C85C0C39CF421BDCC615F9EFF6CB4FE64680\
+04AECE5F30E1ECC6DB22AD9939BB2B0CCC96521DFBF4AE008B5B46BC006E:\
+F3F1F376CD2B43FE3B811792A6F4116225D04ACE10D480F7E42DDD5EB3B0884E\
+B670AA250215FCFBB5DFC87884C2B71F
+
+3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5\
+623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A\
+15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0\
+A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764\
+B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43\
+C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D\
+817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08\
+5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1:\
+CE7D90B1C0A54B5C1918CBD023FB90D130C54116F8292BC388E31C1218A48005\
+3A118DF97A07E6C3F4BFDCC45083A57B
+
+724627916C50338643E6996F07877EAFD96BDF01DA7E991D4155B9BE1295EA7D\
+21C9391F4C4A41C75F77E5D27389253393725F1427F57914B273AB862B9E31DA\
+BCE506E558720520D33352D119F699E784F9E548FF91BC35CA14704212870982\
+0D69A8287EA3257857615EB0321270E94B84F446942765CE882B191FAEE7E1C8\
+7E0F0BD4E0CD8A927703524B559B769CA4ECE1F6DBF313FDCF67C572EC4185C1\
+A88E86EC11B6454B371980020F19633B6B95BD280E4FBCB0161E1A82470320CE\
+C6ECFA25AC73D09F1536F286D3F9DACAFB2CD1D0CE72D64D197F5C7520B3CCB2\
+FD74EB72664BA93853EF41EABF52F015DD591500D018DD162815CC993595B195:\
+76AA811F8BEACBA315A805A3EE2782E44E9C950FAE78F502260641B7B7F267E9\
+7F0CCD0DFF353A48ED620D73845DE5DE
+
+3139840B8AD4BCD39092916FD9D01798FF5AA1E48F34702C72DFE74B12E98A11\
+4E318CDD2D47A9C320FFF908A8DBC2A5B1D87267C8E983829861A567558B37B2\
+92D4575E200DE9F1DE45755FAFF9EFAE34964E4336C259F1E66599A7C904EC02\
+539F1A8EAB8706E0B4F48F72FEC2794909EE4A7B092D6061C74481C9E21B9332\
+DC7C6E482D7F9CC3210B38A6F88F7918C2D8C55E64A428CE2B68FD07AB572A8B\
+0A2388664F99489F04EB54DF1376271810E0E7BCE396F52807710E0DEA94EB49\
+F4B367271260C3456B9818FC7A72234E6BF2205FF6A36546205015EBD7D8C252\
+7AA430F58E0E8AC97A7B6B793CD403D517D66295F37A34D0B7D2FA7BC345AC04\
+CA1E266480DEEC39F5C88641C9DC0BD1358158FDECDD96685BBBB5C1FE5EA89D\
+2CB4A9D5D12BB8C893281FF38E87D6B4841F0650092D447E013F20EA934E18:\
+4B24E0D8F401F94B7B3BC3B3CCA1843EB553AAD14F7997AC2F7ABDBC1D9FF96F\
+40E6B6E00C3376081DCED89AB4869A29
+
+023D91AC532601C7CA3942D62827566D9268BB4276FCAA1AE927693A69616526\
+76DBA09219A01B3D5ADFA12547A946E78F3C5C62DD880B02D2EEEB4B96636529\
+C6B01120B23EFC49CCFB36B8497CD19767B53710A636683BC5E0E5C9534CFC00\
+4691E87D1BEE39B86B953572927BD668620EAB87836D9F3F8F28ACE41150776C\
+0BC6657178EBF297FE1F7214EDD9F215FFB491B681B06AC2032D35E6FDF832A8\
+B06056DA70D77F1E9B4D26AE712D8523C86F79250718405F91B0A87C725F2D3F\
+52088965F887D8CF87206DFDE422386E58EDDA34DDE2783B3049B86917B46280\
+27A05D4D1F429D2B49C4B1C898DDDCB82F343E145596DE11A54182F39F4718EC\
+AE8F506BD9739F5CD5D5686D7FEFC834514CD1B2C91C33B381B45E2E5335D7A8\
+720A8F17AFC8C2CB2BD88B14AA2DCA099B00AA575D0A0CCF099CDEC4870FB710\
+D2680E60C48BFC291FF0CEF2EEBF9B36902E9FBA8C889BF6B4B9F5CE53A19B0D\
+9399CD19D61BD08C0C2EC25E099959848E6A550CA7137B63F43138D7B651:\
+9938232020EEA3BEDC550D9B85C1C6DD5D6AC043373BC1571AB5980F28287DF3\
+F48B2C8136E0A7A59B471F0B11A7414E
+
+20FF454369A5D05B81A78F3DB05819FEA9B08C2384F75CB0AB6AA115DD690DA3\
+131874A1CA8F708AD1519EA952C1E249CB540D196392C79E87755424FEE7C890\
+808C562722359EEA52E8A12FBBB969DD7961D2BA52037493755A5FA04F0D50A1\
+AA26C9B44148C0D3B94D1C4A59A31ACA15AE8BD44ACB7833D8E91C4B86FA3135\
+A423387B8151B4133ED23F6D7187B50EC2204AD901AD74D396E44274E0ECAFAA\
+E17B3B9085E22260B35CA53B15CC52ABBA758AF6798FBD04ECEECED648F3AF4F\
+DB3DED7557A9A5CFB7382612A8A8F3F45947D1A29CE29072928EC193CA25D510\
+71BD5E1984ECF402F306EA762F0F25282F5296D997658BE3F983696FFA6D095C\
+6369B4DAF79E9A5D3136229128F8EB63C12B9E9FA78AFF7A3E9E19A62022493C\
+D136DEFBB5BB7BA1B938F367FD2F63EB5CA76C0B0FF21B9E36C3F07230CF3C30\
+74E5DA587040A76975D7E39F4494ACE5486FCBF380AB7558C4FE89656335B82E\
+4DB8659509EAB46A19613126E594042732DD4C411F41AA8CDEAC71C0FB40A94E\
+6DA558C05E77B6182806F26D9AFDF3DA00C69419222C8186A6EFAD600B410E6C\
+E2F2A797E49DC1F135319801FA6F396B06F975E2A190A023E474B618E7:\
+099495B5804C6ADEABB69E59CAE70E81BC2CC7193EF74465DD9616F36FBBC07E\
+F1C5BD2A0F59796123EEEF22F31D2C25
+
+4FBDC596508D24A2A0010E140980B809FB9C6D55EC75125891DD985D37665BD8\
+0F9BEB6A50207588ABF3CEEE8C77CD8A5AD48A9E0AA074ED388738362496D2FB\
+2C87543BB3349EA64997CE3E7B424EA92D122F57DBB0855A803058437FE08AFB\
+0C8B5E7179B9044BBF4D81A7163B3139E30888B536B0F957EFF99A7162F4CA5A\
+A756A4A982DFADBF31EF255083C4B5C6C1B99A107D7D3AFFFDB89147C2CC4C9A\
+2643F478E5E2D393AEA37B4C7CB4B5E97DADCF16B6B50AAE0F3B549ECE47746D\
+B6CE6F67DD4406CD4E75595D5103D13F9DFA79372924D328F8DD1FCBEB5A8E2E\
+8BF4C76DE08E3FC46AA021F989C49329C7ACAC5A688556D7BCBCB2A5D4BE69D3\
+284E9C40EC4838EE8592120CE20A0B635ECADAA84FD5690509F54F77E35A417C\
+584648BC9839B974E07BFAB0038E90295D0B13902530A830D1C2BDD53F1F9C9F\
+AED43CA4EED0A8DD761BC7EDBDDA28A287C60CD42AF5F9C758E5C7250231C09A\
+582563689AFC65E2B79A7A2B68200667752E9101746F03184E2399E4ED8835CB\
+8E9AE90E296AF220AE234259FE0BD0BCC60F7A4A5FF3F70C5ED4DE9C8C519A10\
+E962F673C82C5E9351786A8A3BFD570031857BD4C87F4FCA31ED4D50E14F2107\
+DA02CB5058700B74EA241A8B41D78461658F1B2B90BFD84A4C2C9D6543861AB3\
+C56451757DCFB9BA60333488DBDD02D601B41AAE317CA7474EB6E6DD:\
+97C99D30F073E9FBF61954DD94DA41B19440F4B4678CD1566E8CE114EEF64587\
+047EE036EAB1E386373CC75114D3017C
+
+D1890B4704E169C28E44DDF62A1091450404910539FC2DAEB26E8ACF4533B024\
+E5215C2D02820DD8FB2CFC1743955CBACFF0F8F35DFBB5E3F942F36247F68211\
+D518F3F601AAE12A1CDC000BAB43D4C973F287E80741DD1FCF6C34F2E6B4B6C3\
+13D01C4FF3CBF9166F26946F18EF2D58271BA9233F09A6B77BFD4F48B36EB3D7\
+3D1133C4F842A7DC3907F680B0B773242C11E3DD973A44327EA7CEA9C0F8E07D\
+682B6651E506B587559FE01ED721000BAF570A16FBDD9EA29FA3DEF4BE912058\
+321A8B720C5C102E48A6E7ED6F8838D400DD57D06EEDBCD15323F86D855C94B2\
+1E41B14EC9E1BBC8019211FD88138C91F9ABBD9BB3914D26C1DDC21673D2D512\
+63B39D66E741D924CF2B192C5D2C1A140126A3D64A2C77BE6C2C6EBE8599978A\
+E90BD36CBB9AF64D078910C4094AB3BF399C34F2AB8EF843E9FE1BF88BF443BA\
+21E4377E5F49C07FD9653B526E14562237F02D11B904BCA6AC31AE721A43E3C4\
+910A24AF6F4D80C031C109FC0FE49F15274BCA92BDA04C3B4196C192F6CE489C\
+63A806ACFC895AB52CAD657C1783B528E12D0ED856E1F8FC91F2AAFDFA0A9249\
+8D68530772EE73B359FCF1418D1096C46B34DCF90E5B468BBB2970BECBD70089\
+CFB039D64CC50FFF5EEF26384D34F24515A6558B06A1FDD88F1050C5BD78CC6E\
+D83D4C2B0E882AEBCF84AFB0430D0BF09F2FB42B8B4589158093A7709AAE75A7\
+90910E211EE1333FFB6FD80778DA3BF73858978E9DD647978841B18001DBAAEA\
+43CA0C0A03DBB9BCF30CE76A6F4B2CF2A9B6531B3E4051E7E05090CD421BC66C\
+4731E7122AD129FC42DEDC83BB460E3F889992FBD3CA072686E56B72C720FBC9\
+8D723EF7F247286F77CCDDC728738E941B1A74D4F16671C21FDD5643A115DDBC\
+B88EE7EC67EA66FD2BCE718DF6E085D4B5FC71A72696636A8F7B3A68AFA51A89\
+6771FAAA7F1F827430AC5E8089DBC0D4175E1B22A057BC5F1724EADC1A41E78F\
+A3ACAA8B97E5F2E19EF9D59AE12B04E7F0E8A621E098A66910E2A5ED2102B824\
+CD3EA044A854F1CD0B33E61E7F737414B2953549F25DD34D19AA1981DE7CD564\
+9FF6C6364A4F25312EF62395A747AB88AAD722C05AEC40DEEA8EEE5E779EF458\
+A68840BC6BD5D29AD40F98B3AE010B6213372ABB7BB8B8:\
+47A44A3B08EB1AF1F5BCDE156207A71F1D123D2EAEFD2F554D1ADFACB41C7364\
+E8A7023D42DE0045CF3651FD9487584B
+
+4FA3DF1DEA75AD4B9C379206A95FED930000482E5B683FD2B17DC8E7D5C4BC1B\
+73186CCC13C9FF2DD09FC1D4F68034D120E84CA73A00B71A3B46D1EFC6FF88CF\
+2EDA65810B098CC5E651D9CF064E87076D5A871849F3B405D3D58EF5B1F10520\
+A9FB4FC84A81A87B13DBFBF9D8674943E28C257E46D8AD7BE1785F1DC7C9B1BD\
+574AD1DDA48F0255C853D2490BD3D63DA22A8369CFD02594999A2EF443308FB8\
+298266A11EFA177102C75DC674E89FC9DCC1A0D3C863BC26141102175D2678EB\
+6E13D90BBD9A5EB89AE8C0CB47D7F340D3D32042A2762BC9BF2B40EB40E87FB4\
+2610FE7E357051F01494704FBFF73321B47301A0799B7EE3FE5E62200F397A61\
+ED4509A62F7106ED0EFB0ABD6AE9E4A1FE9B02C092DCDC75015CF602F3B9A898\
+8B609E6C0D1C5C3E219FF57875C2EF01615F89447EA602DFC94EEC17A398C014\
+BD346691FE209A002771DC8164422CD166AFB457A8B3071282178A3EBD201D9B\
+07B27E711E7EE7D33AA5210ED4E4E92486775D14A6CED092E34A7AC826709399\
+48FEC149F9C018FCAAD3FC597D315713F44FC5E1725F448ECAED40E8D841BD02\
+F1E81C019B08F99412E360C0BD378391C67D964B47F50C26F0A483ED66402361\
+6B0FC9AFE43620DBE9CCFE070EF295C049EAC754C2123130C6B2C0232F6403AA\
+7F0DC35A5999BF95D34AD612234C6289277ADB60E4F72EC2DF570F05395B3BE8\
+A0A3C78B732821AA08927C524E15D65F66A3DB8C1C96FB70BC0686AAC310051F\
+469FC5EF880C0F66947C1C328F97684EA24CBE63BAED8D114F40507C2901034E\
+6AB3893F366D53F1CFCA309309218CABCECA4722FA9CCBC7249B87C12FF8397F\
+40487EB00082E7F551D27E301C3BC7B5389F7042534BF7E692DFEA4DA24F7C34\
+B8D2FF145F54B517FC97134EC5AC2CB925C508D7A6BD01FE7B764648274972BF\
+08560D30802E0EB7EDCC57AF4797BBF92E8688268606B0F1BC901FCC22136281\
+665EC16393FA9601C4FBDB18CD1D1EE382BC07973903E91FFA87399D1141D49F\
+4F0C064ACF3AC9897891DF10BCA0116F2C3FEF180FE6A8E937C478F2EF293AE9\
+186DCB1F76B6E48101DF64E57EA7C64C5C0025E221C8F5CBA5CC92D9CEC62814\
+0996B26D17F439B780F59A999301122F82D0495F8AB5AE1EA5790F45E992DFE0\
+0D5F82A7FF1354AEFDCEFC0D2D1731D22FA2B75AFD4FDA25AB194055FA962838\
+1055247C8C7587D22E73C60136C4282452D47AE03AA035FEBC26FCCD42A1CB79\
+CF866DB6418A49FD8261E877DDBB839CC39514DDB87A8A40D795532626FEA4A4\
+C35D13E028F9ED1BC09B06BE999B8DDD2258AA0596BCBBF72AF67E10BEDD58D5\
+99B8D577A583D676BF5561F80CE5E9528729A92DF578FE75DBC70474B75747A8\
+D55DE70E57BDD62D4344DC2115ED4DD62F1FC98BFA1E7421FC0700025C46D0ED\
+1BEF35C3B778563211B9FA9E8BA4BBCBF01C2FB626AB7EF325CE9F468DF2CACD\
+B178D36557CD85D542C067C289E926C1EA2F20ABD329E984168BB6DEF1DDCCF2\
+14DCB6A53AFD462F0E7E7A19E8C88F049244125A6D7DD41E58BC9B2FF7FA2478\
+DF76AF73090CB1AB59E388BA20E2C297C967737A1AF61793B68ECD7439444C48\
+E28E2D09C48FADA5E0D1D15E5B340A52F8B3B854CCA479F0A598445E14F53B3B\
+A36891050C79673DF3E2B5825C955A29E5C9A22F3991D0AA785718CFEA1D2385\
+F8E47E4A75ACBC7988D0558D541D71C4E6C5F1CB15B60CEA0C34A67BBCE105D7\
+A896025E0254DE7D7AF724C9027D44B8642192A08AB8E1EF3046DDA6014DF7F4\
+C9E63C635E48AB2E70B640D480998EC9357E665F99D76FE5529EF23C1BDFE017\
+C3A66CD4EB2DDB42EF85EA0CD65534:\
+3D30B8FD9922ACCE224F21324E9FDE7E9CDC3D961117DCCE95F9F1AEAEC23C10\
+85C14EF1C58FAE5F9FB56595491C9693
+
+523DE8B1F4CBB65E81FF0B6CCD6EB8EF0A0F0A691ACAF4A77F25ACD2D66AD4B3\
+EFD25BE70308853C094412A518A32020E3020A9F6AB32F0CD60EC0D7A194917D\
+6C457B168A54A4B46F7B0D0C71BD61CD202F4C718776A701E0770B0EFA054187\
+70F98E4E79CD066366FB3300E8BE359A98B82B764BC2FBBF59C7E8F94A157B01\
+C6C7577B1428138CD422BC47330F8ED99F4C0AAB0D984287445539839389EE08\
+D6345108AF26ADED0EC1D7BE774CFB8C5205DFE07CF6CAF8C1AFE37C7A2E4FE6\
+013B93EB2463DE4E0971C7178D6A76B16A0E8960C984CE8BBE71B3B466EDF044\
+5B835F09414D01F14C7B6167FF78FF118127BBD5F812C27FACD57B3B120E2BCF\
+E87315C7A92B82EF5D50CA14A7174D1BEA7E056523E055A6AE42EA3765094E55\
+44E5ED003C989C2F98F38A17E3DDA74DBAF9C669A319638A2698B0E4A611480D\
+8AD3CF016792ECD1034925F42B9811A7214D623D047ABCA31997DDEB03275F80\
+DD21F40DDC80616E7AD3D481E8EBC0A1A6A398E16A78369215541ED10B75671A\
+DEB1AAE6E11142A1CF665FC1B7332DFBB0E10C21A2B48F78E57319AC9C58DFA8\
+B1C2548E2979EF1ACCFEB215AFCD6C2C1B46FE97DD491758378330EFFC728366\
+1D2CB84FA05281E9E517408508D24D042E7B9BCD34DB87CE972E4CBCDB98615F\
+B93093369DFEDC782F44BCD03E81CF93051318B2401FF29F753A264BDA65AF19\
+9E3FCBB8B5D39C838A67D6C7A3DB046DC56C323DDBB5340CBC229E47CFF8C9D2\
+9B7A49AC0EC8C1440AE498C7D150EF91C29BEA7DF3EFCC2871A13A1D72D139CB\
+4603D9FFFE85F6DDD544850EF63C3944FB35DBC00D4308CEAA6394B6E23F650D\
+323F8F7EF50DDB68F1486EABF989BF44451F620EC9485C0B52D1415D3C909A2C\
+FBE9D77DB19D069D33BAEE4D77292E63FCBF65C1EBA24BFFDDEFE95211EF0AAF\
+8ABFDA9F94445E582976F986F5382CB669506AF2B4A5A0C43000A3C72C5CA4AA\
+CDC9D3D39FC5C492A393B6C341B86DACBBF6BA8B465100CC683EDB2D9B9F83ED\
+F9C6A32645F51CC79ADC22A52A007BAACA618BE35E356D1FD1CFBDA73F1ED092\
+53039DEF609450FD2D5943B9CD49CBD52A318EE3510D7CF3FD8FB388AC6CB9C6\
+EEFEF3D3CAD8501B91CC04A888D33E16D6A4C9666F5F5F3B257193F2B46DEDDE\
+11842909D8C48ADE57775B0B272E2DC9CEF1A083EB2CE58F4D1F211922FD6ADE\
+D1B82FE6F5B11251CD396E5A3666ED9626036E4E356231C146BBA0A91AFD3648\
+EB7BFE0B9C14F15AF2F92309826F468945CAD0AC422DE3D6A773B76178422107\
+CE0270E7F580B5CCEBA82CA0184AAFA8341141E65E39859885768FBC5CE63B96\
+5A0604B659E71D9DA2C7A43646088D8071D76926163AAFC69E25355BB0A222B7\
+B2DA9F0A20C021ADC462E905A9C3BF31C16D87FBEC3F014F3957A720F1432E17\
+41553092052FB58A198640479ABCAA51B104CC93E2636E1460643EA812BD44E8\
+19C2166EB6B349BA5BDEBAD59078910B5C22A56F004B8D9E4B1224D8D204B48A\
+BE7355548A402736C5CB110F3A1476ED631FF168F4F3EFD89B38DE4751536548\
+647523D334FAD7CC2D142973F2DB3C1FE08FC5CF83F9F2BD2DAA524B37864816\
+AF29EE05951FA09D1C51D9D14EE4F72FD7BBF18B1A724FF5A0958A063947C430\
+142AD2356E4400AAECA442E163372A8F1CD36E2DB988E7781165E5D4E7074ACE\
+40858E8370E883694AF09977704347FB735C8717C42BC4EEEB2AAA50DFE637C6\
+40909CE379BFB9E2608F88751377038D1669F248178AD580A908D7A1B8DCC7E5\
+3E01801F1E485B5893F103F03E0F53B2B1440BE95644D85AA7F6EB7EDFBB4665\
+2196695EA23C08573397B111FF909025E20C5201293B4D223BF7AA01DE7CB28B\
+94714370434B9588097E2401B62C7A0DEF1FBF89809E810749FD3CE9EC3C07CE\
+4BF4C43DC966429B2BEB4D711FC6C448A12097B36F1E6817EAF4937A983F85D9\
+CF3E62CC1B2AC6AE1EC9EAA8CD8EE2C3322239CFE5DB3D4E8786282E630A7D25\
+9C2FEFECA03031C960A66A71E436A3ED6F2F3CFAB4BD77C660D14205ABF606FE\
+561A346F7D849B69475AC9F6822D80B9A2E56D5D495E4B309B0EA963C9FC5C7E\
+F94B217EE5337989AFBC7107D233A8B362AC27C4F69DF9E191CD65AE97D6EB9E\
+5484EB6F10349575E4CAE51452380151F902415AC9CF42C824EB23C9541D2DA1\
+C26DB85F53CDAFB06A12B8393CD580A8E494EDB6710C720DCAE30832967E33E6\
+303A92B1DF0841D7724284FFD2E00B95C6D623B168D21AC1BD3C675EDA33182A\
+2C22370998DE1E5EB905372CC6EF32D5B765F5C94870DF4842D011603BE4CDB1\
+C227E41EB2F2E8542CD325884FEDC9C5C7BB07A92D20D64B836215C59F162A3D\
+A8BB67D6FC13FEF97CAB6ECB8A29E431A6519A6261C4521CCB90E6E609869E6F\
+E398404AE047F64EC4263566DEFEE66329DD40AC985EB8A08D26529A544891B6\
+F57CC235C63C09057AB6B6ED720EF41A3C9AE65768B43F6DCF4962A103DD93C2\
+13171DC2C9194E43265C689B49331450281A3FEBC618D1AA4D65A135137051FD\
+46B568CE294C89:\
+732977A1AC5D19808E9D7AB638F6463723AE3F16FC61CD2C035F253F0F7148F8\
+38C8CC41FB383A8C854B7A02B5116F54
+
+F5080D4C59E804BF8F34B334CABBCC7D32011BDE3677F4B9069416AC204114CD\
+9DA7A0ED0F4B4D8344416336EEC15553EF526B6DEC267B1242657DD0B508AF81\
+FECF9CFF9C82A6A7A9539814DD7E097615EF15373836B5D2F765CC8D5F82E904\
+49F13AA741D5EE2FE63898E55ACD85116846807606FE1E2E29F98F9940B067D0\
+D1DF01F080211B2EE4B0A30803782A7BC2EAFDC5EBDBA91EB05F7D7DC8E34BF6\
+D44FEC05824F53418F235FB64E899EE147BCB403C8855E94AF378D182D79C3EA\
+F977CB4E9D4A16D990A6C388CEB567B97785E6F2BC6745102B99AE765E960B6B\
+32BAF01E2379CD6ECB74D3E1A56552F5976DFE5C742BC92BE596CA742FFC3D0F\
+A032AC29F9F7C1A5C43BCCA62DF7D9DE35D0C7C179DB2E1AA255CEDCCA55064C\
+2049FEE1AF2CE5EF696ED4BC46B7C55BDD51F2D44C8713FB2475C0B85246AC01\
+03CC3863B7EB026AE076A600313F6FB40A4DF62A2AF81B7E917951EA870ECB31\
+B3401928B5046D9A1E62D14B30FDEBAF262868517318FE17EC3C0D52524F4412\
+0ED8ED3BA70C643300CD0BC70DA72C964A88F52C3A91EC20BFEB5CAEFCD4D9C7\
+685D8407476B5F34676C5EBD1E88A6CFF1C625322F8CD59B9ED60CEFB21F9491\
+B95E72791F7AC7EAA3C16159FE9DF7A989ADD6C2282C47585E11397EDA9F47DF\
+2B40166E03BCDD6186B46C6835118268DDBEF19A28BBADE1BDE0228FFD7E8B3C\
+3C598D89E24B8CDEE79C940254DE26CC6814BA2722E42F7571600B7325E1FF30\
+0251D52A895B8CCBD049B2953B8D231445F68F7C26EC25A4B8695C8AC116F736\
+BE939EDD762C9B4743E463C9B9B2F88E0BC0CE78781CDDC3BCA825ACD463C7CA\
+C2AA6C430BBE820EA94AF9A40B1B5C006E9641A2FFA6E427379E1AD49C81B983\
+20B3431FF0030DC683D61026438BC6A6D34B2C73704D9F62EAEB13ABB3E4B056\
+2B4E0482CD6B2D7AEBC0367EA29A88F4A76F3D76FA1197E1DCA92C8216C84C1A\
+F9B8C78C9E3A7799A4A79A783033B0F5547E8E75E69CF3615AB04EF989FE1A46\
+3B1672C571D50AB56972896E8A50C242F22C7F6E27CA4CA793F627E79608680F\
+5421B28BDD2589F05E65430DF774EE873FCD1234064F7A33CF5A1FA4E368137F\
+F9C1597F1FA0FA36493F20538077669EADFD3B06F788C912C715FB5D334DB6BE\
+D133A8FDC40F5496E66AD63881F0BA3727416715865253DC5290327B515BF68D\
+A188DD5B4B0EAC7CA712CAFA8FCAE0C5503FE58A219182F1C30DA6D0C19CFEE8\
+97B7D837C97996A35F4CA8CF0537A01D17E7DE0CC9C129E4DA0ADAF1FDA85030\
+DF9127BE628263B0624F372C47C3AC87EB945A57F5C732BEEE81A74030017989\
+92F3DC944114FF3D54C4666AC5AC8C98D0D5596CBDEB420665F5EDAAE747D54C\
+F7EDD37B162E372249D135938CF17D174D12D88279CB4C32BD6F018C766DA698\
+3D4EA51D6BD8FF0A9B34E9A93BBDA70CF1B4B867D60A74811FD98D52FAA559B5\
+2C755CB70A76C94BD19654CAE7017CCD70222BF08C5D7AD1F5E4E6344FDB3ABE\
+703452C29A696F39F9826ED8BC510A4A148E5BF8A5DBE6B82D7220164F08011C\
+05AC5159D52CE9D45D758B645BBB248C2D341DBEFA1F8602C5D458A64F38F3B0\
+4DB39089807B6A10E1BB52770B92CE72E2D3BB0C2241CDED35054B84558D1CC0\
+99EF7B2296951951D5B6A22F93BF962AC5EF8FB55EC6CC2B316428EDF12078ED\
+1B66D525D022819CBD489E1BEDB02FFBD507D55F9B5D4E22F6396EA233453754\
+688D20151A09C70044B8A5A9AC033C3C3B847AD833D5C05B33407666EE82F958\
+1DF9034EE15A9CA67D52F1D9B634B84C1B8BA9E515F1F060A5AC5CBAE2DE75F9\
+4E112F7198E239DF08D3103F065627438995026DF511C6E5BFDEEE5667D511D4\
+181850C7C5D179107C1B86D24D5532A88A4149A2810DCAE73731B0E1247281A6\
+FD31613DF6891B4C17B7A6A9AD9B77468254B93F85958AA0F01CEFC10B25169D\
+C46E035D3F24557B4BF0E7D60174219108D916FFDC55E25BFFD9809EFD058E12\
+C14F39C69D8FB73D3EC6458F47F2F8DB901BA76C86550B11B54D0641D4DB3EB0\
+00057DD00F2E511FB7A47E959A4402A3AC5462234B40B184020FCF7A0396C4D0\
+0A987C8741A4537BC17102A5C42AFEAB9F71EA66ED4CBC7B5EE682FF04F56F4B\
+A1EA0BB326C4089930F9E3F3FFA3E06637CCE32113881A06CC3A13837448145C\
+2BD01307A580FDBC385D8F46FB92FFEDBC8918D269DD1871164D4B3E2023441E\
+C8B99C82A5F09821CDDF6B38C9ACC3BF3A38D5628016159588C33EAA29D9463A\
+537C000A16AD8C177DC4CF716E625F46FC4CA8C19FBD8EF320F1D680639195C8\
+B195B0A02738E0665F4190D6287E589CD6DD45B9E8CC23B08E1681BFC6F66B88\
+DE6B091E825EA4BBFBD697E10BC407570AE4F2A3EBE569554639C2B8E051656C\
+C30C837F5A92260EAD1D552B45801B6D28134166796C87F900225CFDC3CC49D7\
+2DFBC18D8D95B1E160ED3CAFD5C3467D48AFF87402CBCB1E1420E3FCB588AA19\
+C8F42753B59DB6FB6A9FDBA127CA806DBA7DD97F2488FC2E438EEF57A4CC85B8\
+8DCFDE76AE1FF61225A1CA8BF4A14F729950322EA681B16D6492902506702DC8\
+F348E4D3AE7FB55FAC1231FDE82091B34F1791B6AE37587B10325F6FF5E23B85\
+5845B86EAE90785B9D10D90A16644D01BB626F343B908A9591F4069B21822CA4\
+ECF985C1E710475F33DF9AF4764CFB0FFE649063775338F15BEA7CFF29F16467\
+8160960A80ED148C9B7FAA58E9139911D3DD9536F69646F718F083DC9029D629\
+4FC4C607688AA75AF350AC2C0B001A157D023D73D86ED8133809FCB9592D1208\
+9CBD7A1BB6BBA882FE227C09A53FF088907CB4BC2FB4B7F62D41D3D397C4FE0A\
+D12BB3964370E21712951C679814D506E738C0201E42181D231136A435AE0397\
+B61CCBC5E8BBEBF8EA77C8BC48BD6211F29248F9D498D818E2B544D28A5E60BA\
+727F32EF4BA2707962230C900076FB764D0ED5CE078C9DB14DE894BBB836C6DE\
+9E83202AE89F9A8D8CB0341E1C81B5FA8B16731B8E231E969C0F1EF95336D4E7\
+3EAD6DA23DE3AD1EB608ACCE4D4D93996DD76EC1F5F2C576F6B3B76E07BD8A81\
+0FF5D88B00FFE48C42700B61CC499336E7FB57AD72FF44FC631C7222C9A3D1AB\
+F6E77B5ED7FE2F7228FED6C849BF7142C4103989A80F7C15642AE61650CDCA7E\
+854EB25E9E72F4C3E3768E6CCC8BFD556B56D3507EDDE9E5C331DDEA75568B07\
+813D20E8F4C9547838ED28448F2E67158ACF0C00B131473847816C5E2DC215:\
+6F9117B8DE97FAB71857BFF4BF5BA8C6FC83537017D225686C538D895DC5BDE8\
+BBCD4584201D1CBB47B60F6EC195B53B
+
+08944CB473B828B118A31986DB67FC757F238182E790553404B792AA4F0095A6\
+A83291E287CDD16521A3AE8C48F56FBC909DFCCFAA7BCC570C2159F26592DCD6\
+B15BC4DD55CC05595AC634B2C3DE15360B0F07A03B5957BC9333CC5097919399\
+DD9973ACE15E55940178C4C96BB5E0A0A10BAE175769548EBCE11E0D7D9DB296\
+47F197D4B87F7039F5D4E59E016531DBEBF55A797AC9A6835032CDF34240A7EE\
+7423E89C09124829CAFC5F89431C8AFC54FD979E50D48A82B47A53523C84B600\
+4DAA323EFB708203E5388A6A5110C6CE2E341048A65FDEADEB3837A03420F9FA\
+DDC3F02A544F1E46D96B07C90C7971A7040A179E8198E90AA019268E00367120\
+D5F3D98A5CCE82C885E77144B1AAD66EE682847776B04F01F501DCBEFE390308\
+0A8058B3B8F1D823D917ECF31FC2D5B0795BF95A55C7093ECA7C801DD0BD0DBD\
+BEDE7D56513128B29FC0B4D25A6240B24C99E017BDFF7ACAFC8F8DE9FAF5A294\
+4384AECE82BEA04DCCC6D51FC6E6F27AA38F131B7959B13681A09B311D242E62\
+22A1CE5687DE5C080508B1DB16B6F8290D33A3CC0D0138AC61FD9093825E9D37\
+52889E9F20DB9F80F92750EAC88B38AC81C0016D40371EAB4A87E845E91446B0\
+A07081B84F559CDB95340CB020AF22AEA1BFF2FDA12F7A42973FF163A1C6F33D\
+B8B8214AE27ABDF1C54F5B03E29310FA210125E1296E8AF93A2996DBAEFBADD4\
+C51C2C3B8A3E2BC9FE060C42BA32768F6992A99599206CD2291CCC5BBD50856F\
+7F8D2D0AE1EFB5892C15A799B77482DE4553736B162ABB06631F1688F6746E7D\
+7A37EE7EF24E6CC901175F04960C01990178F81E957E941DEAAC8846B3704E24\
+204F43DDB0765C433F3F7D4D201459CD65682B7DDF3D47E95CDB31B96A4CB229\
+07F08BA6E92A4A07703B2DCF150F922C4B7CF181380303FB72547847305999C3\
+C8F9AC877D05D9DC4159DEB8A13D36AD1D533A56950E20F906D29D51DDC45BD1\
+5C1773991707480E37B827044BDC6473181B760A9036E0D3FA491C2F08C55130\
+D8CDD5AC8E97D0813164AF3D28A585F0C2EC7004D498F95C6B62231A632A56C2\
+D0C48FC3A6992D4051957B9ED6D9A86DBCCD962A8883CF82CAF01DA2F51A203D\
+56B6089BC8FD0B1BD414C8063031ED469555E22EF872689C130B1C101034D572\
+FD8CD0EDDABEC9EF1503D7F728B0941EFE2B9512438C7DDB176BE2EC2D9FFCD5\
+6495A4511428DF02819CDDA18D1ED5D3B16C6F42AA0AC681A9FAB51E8A1A856C\
+15C51A3EC1031427142EA12543014DD4ACAC640B8A7729E63AB7DF1051112CDE\
+FD4B988A2258334FA9A7F5B3A87A02074B9F69DD81B83FC74089A91D76AA4041\
+259E80FA255F2084902AEB9E996AC2288AB464BDEC47AAB26A28A2A819498975\
+5D48FC9A5C9279285F2F1DBB8B8018F3E4E13115D78A879792E45A8F4F24ED4A\
+317440BA63E6929056EFC1D2529B75A709D6C0097DC2D97F646F334EBE6195EC\
+5630132FDE58E25DBC17DAD822D9FA0938A2A2C926B105D108403DC29CF371C3\
+504FF73BCE9C7ACF9A74C4954CE6A32DA96B21CF3211B3E49953DAB78C49C3E5\
+32A349003C59C62F7D40261CBA63A9EA21C89A38AA63CE431C43AE261C4D9999\
+B1CAF491FAB8E7BE6E8C3454F1BE8793B2D27141FC107DA599A4694C41353D77\
+85C05B5E31440458D17C6DB66FEB8A9C5C073FB946A67AC0312BB669D9B12FAB\
+AA5272CA6631379EF4ED420A4424A5CD08526384C047C33A84D5D7DC0C215366\
+3B54C73DD799A3568C01B818992CDF8143F1DADD6B50CAE6EAE13AC66F31FFA2\
+B362CC4D2880592B7FEE4B9E4CD6AA5E5DE27AAB9B5DAD9F7D39407AE927530C\
+AB2B61CD7394A21EF47BFB813B5EA6091458D239664923280ED0D5CCA8285BB2\
+281A2F9FB3FFECC8E9147E1E8FAC957D90C9E5F513738745A47C2AD0C31FD898\
+6EF3B6388C6E821F166513811D547AB4336B5E04643497FC9F8D6E380EF6478B\
+82B6E2F5F65DD98A63C68C32B94610E1D3B9538F13A7688FBB1EC3448BE9BD77\
+BB93A34546172AE8D614F85228988E7FEB18C9A0C9827699E8B3CBC69750BDFE\
+CDA8268F694F4C509BEFC1A1166F85C829725299D173F867A300987A2D36D1BB\
+BE37BE3208FB8EFE9152A41A5F0E931B6382FF7F9B18937958FB180E61F2A8C2\
+8F36C3C80C3722935AACB81C24AA17FB3E7A1026F7031A7449818ED62BA7705C\
+A27C2D3268F90B6322921683DFF800A306CFC186CF2A61B37F35837B217E3B2C\
+ECB0843D84EAC67431E3D689F01522D4A4C73618B7C2965C9DABB15C0BE637D1\
+0CEEF72271CF39A7B803B41767BC34433C3E6FF449A439AE13DA1EAFA038CB9F\
+2E1C84F1CE39C05DF56FE3D7B82386C4E628B6E27CBC5D575C66ADA3510C246B\
+D04DB48F4AFC2D7352966DA2266C2BC9831532F53655D8BE42B421AC0D70D8AD\
+1D3587257886DBF93668E907E861BA64F45999BADB0F766EADCE5238B5ED397F\
+265935194812C03C5769137BAC97140525303CF48D65F39004A3F59B1FAB0989\
+5CEE05335D15B9B12265892F4ABB92AB1DD2002ED00CF3562CB67DFE1055968E\
+4AB3306BB34BB87D0F64B26848812A2F7B50424A21FF94081A7F70F7B684AB0F\
+092B2B085DCF84CA38414CF7290F607BF79C37EA84253ABCA8D4184D2DBE2E90\
+0200B81479E1CE8B71DCF2BD6E3C557A8E431D627BA669C2EA03068E0F7EA62C\
+29777B22142D7A1D451BD541EF8EBDDBBA4E3BD8FFCD340E935BE7C66EFC14A1\
+3EA48134F655B0DE3180101F09D204C379743A357E6DF1268B55A9F7524398EC\
+F3A59849A27B142239059998083E8FA91785E91C4D220B2FB17E3389EBAA384A\
+49D89B5D78136DD2454F06CDE9837F096B744D53221127869904AC227CDF30BF\
+EA78CC5545583F999B9C42A1184E2FB9FF3EC095B9DA0D138205C4EAC4C8C480\
+C43153608849F63E161135C79D8B6C9CFE9B8DFD8AFAB559D8B595DDD4383503\
+3B4BBD391E028BB2A60832D9B697EE61408F149744DCE71AA11BB2B0436C1E26\
+26AC3A27CDA293366B90B9CDE2D927855130758D3946B867192DCF3FCE9A3B9A\
+5276E8C37B8CB136FC90A6DC22650F95E796A9886EFD3F424BE63A66DBB1041C\
+B3D4A06F4E7EEE89F0B6D15C36F9EA010C66B332011C8888E8E4AB2B3AB52231\
+91E1388613A0FD0F07C1B26D7CC7CDF1AC62A226454D6291B431CC3EF2DB2B24\
+42B37DEFB942117FA247096BEAE598611B8104F37BEBEDD8BB8B949A89B5BF8E\
+228ECA1D8F16BFEC75A02FFBB4EEE3A6D4A6087C43634D675311E72A9F3253BB\
+5DD364E07EB4B9C84F586BA267BAFFAEFEC79E03B83B18595FE06D7E063EE604\
+FF287004D141C1A43AF0CA7C5651D98F633FA875B4743353FB07BDE59B6567AE\
+25F7095F1D9EDF30570E2F7D7EC194216898D910F9E295A41DFEE072CB56F914\
+BB78CC9854129250F9874B63BB3EBE9A1CDC6EBCB0916E1C440354DED6AA818F\
+2811DA913912A21D3961AC94A39F0827D3A419616905DC45842C8E69A43004B8\
+AE922C8DE1E8CD0668674A7760153213835BC63FAE4F8D65614AFD74A34D42AB\
+AD5025B884B34639340B45D49CCED423771916E18AA077291923017CA50795F3\
+B7A3F349A3D29923833CE57801C631576E23B838A7767CA1BDA92B82AC502DB3\
+688FFC83C09A4E40CAC31D20D9D32FA6724A80BE7091CDE9C7A6560CFB326B46\
+7CADDB9E9B7A491EDA283EFB0B61B4A1116DD859D5C0897EAA2A3FB2CD82FFB3\
+3770BF9E08091363B6B81D23E61C2A647D2BE440C5C79EA89690656D9F10B1F0\
+7942834E1CB6E2D2DF106EB6D6A21FA23819E65028515E88BD279F9317BEAFFD\
+394EA51F8639371C3A89F11305A4CA35FB0711F5E2C7C3DD1659C79024581211\
+3204B4ED8AAE9FF09D43C6DDB13F5070D98831B2C7639FB6B9B01C288812DDFA\
+8861DB32DC8268C07D30CF969953042B3DAD530D9D744C06AABE7A886C0FE57B\
+09B7F42D193FB3E9C06329818251A2F7E6474462C95DED:\
+91E706E199A3601ADD699E05696623B6AE12B1E462E874177A79D1BE34C37348\
+359FBA3070281C78CF8813171760A6BA
+
+1A3DEAFCE70AF6F3F55D66AD9CE78D5F4D5C5F2638A810AFCD07D67E9F9A1380\
+D6B34BE482EF030C22F1E978F544609CCE35A74C5109EE7038495B6210CDBCA8\
+DC82C6E9E7B0D593FAD9665382B3C401AB8941DF71307DD77EBAF140AA66A1F7\
+6316478850E58886A9610631E9C722F459FA00C0B53124FB4F12778BBBA37608\
+26D3DBA67CD030A96B654AF93F8E395F5F439549489F8161683F124BC980E693\
+9C83A6085E4B6CAAF8BCD89A0E01ED70DB487166CC29735D9235A9CDC57B80C9\
+C2E591DF6322F5BEDD32937073F781A30389552AE83FBE147D1B3D3461A3DF96\
+C15CD96900C56718EAAE838417057579115936862679F5F2A45DADF65D14108A\
+F1641DF987B57986384FA1433789F5DFBE87E90BD4E9D8D4D0741FCDA7348322\
+B967B566B18612DBB8FE64F151947C3F7E361EE868676BCCD0CB3A1AFE046BE7\
+0057A05ADD3E65AF31E3FF414A627C0183E8FF583B41B75B203650420216E6DF\
+CAB289665F054CFE3EA0943647528518573BBB1D0F27E1449E98739EAF0D0094\
+32DF0C1EDC1625264B94A71DB762659FF5A3A7A867F182D1F1FD34B341A4A181\
+221870DC4A494013091A7E3B2B07E0160C438F1EE1E8A2B989C4FFEC36B5083E\
+A427606767C29672F44779A8505B422B25A56907F565B27690D011426A62DF00\
+36D57D967CD1D14E915BBC2691E7AF818C769D9E1F9EDD40894BE88FA1D7A595\
+2AFD898E837716ACD73953BF2D1D448123FD1A0276D2C2EBDC760A4B787416CF\
+AE5E963FCBDC8B551CB70F91DA0ED4A8090FEF178E879F2C34F3A269DFFFF097\
+72D44A13D7A17468B5834C460957D5243C325F63F05F89D4ED98D361E7F0AB8A\
+83948A64D0CFF8514841AA21C7F337920A9983E59BE4A0F1339E1E462F92DC1F\
+C070126206012458A499A8111FAE078E00B0CA3BC1D6C7087CD318D5603C1C7E\
+0425E6F729CEECA5F35B82F8A42E0E9B950EFB0904C5FB5C06D91D239913665E\
+D1F1EE4B82185A01BA86CA2D3EA94E5A8842231A94C05280183B7ACA28998410\
+3F122203EC2FBA4A382E6F5236D6F68DA05E3BB0C558421F0EFAB91DCEEF6D1E\
+CDC60F9B88F8BEFE31CDC3C2F024A1AF2C7336AA5D151E8CDA814A5FE898BADE\
+B9DD680E337E682EBC22BFAE445417E37D2D89A338659A280AB1206DB74DD42C\
+6F25639C1803BFDF2156DF613B0F5924D209F7F9003CE8794F989F4F27B82121\
+210F4F65EC5A1F7723305CEE438C41F793EE04496BBE337BBD2FD3023830B1C8\
+889C6F4D0C1192E364EDBE1CD987BA5D66224EE9C9405E1DFCEC0EEFFC5C73D3\
+123F6731C6295D1E6B854B884FD22B6A3BBBE5395312585CD138BCA67532C6AB\
+71BEBC6657C50DA87D2AC6068FA3970202C5E15EB7B4B3D2676C0134BCF1EAC2\
+B26BA46930B5E660B16060894884C88BFACD6779276B86F685AB6F17C6D53F62\
+1275FAD66D021D26D1D480AFAB4B5EC75E0E763FFC45F599EA02504DA5D91EB5\
+EFC3E4AE196F219E45E7CB05594958C876FF474A020EF73C1F09B1F7F7457E81\
+6D3AF51D86663D4D461754CD5E907456691E02446D6CACFD33516206A3187054\
+3D574592087773653D4086C2BDCBAB3C9B65CA11AD0D4E58DDDA8B4403099898\
+57103929549B7300CED42651D4086661694092C42875CB62858E6D1BE5F7274B\
+4BCD83AA4DA05CACA186A30902830790F9FFA24418E1F9DB00FA40477E83B05C\
+2D11AD7D81DDDB1E31F94A9DD5E9E13391C22479B570976E3AFC1BE41086D3BE\
+6689D87CA4326A7CDE8E5B396A678D3CDB2C80FECFBA2BC799AE8B1528E96D88\
+0CD098DDE910D097EAAE660AD4D7EA51C18F18AA1B39614299A172512521DFD2\
+31B9840909839EB69C892EE23F1BCEEC1FADBA75786C7DED93BC9983F74CEAB3\
+97EB8BA84F7E4130B34258D628594A6F9E2348FD91BA2594E07B8057E8A2AE3A\
+DFEA0EF919555385977041C5B6DC4F3880569171F7217AAA9A85F2F5BBDFE3FF\
+DF79248F2A35FD4DEC34980C67290339B1C0A5A6AB8838157AE2F5140B4A2492\
+4A6688AE5CE72A48103EE9029CE8A0F15B1FBB19A12FAAB80A7CD9C0E389FC27\
+75833E3190F1CF735ECDFE7F6B6C326506AA82613CBEDA8DD3691B81F4C1E3B0\
+FC32D7E6719CBFC12F4A26E0FC29D6417953ABC9568DB4ED9A294B9FD5F2A666\
+DDA546ABA301B1C60985033953EFD6F4538333B5C7DD3148814A3FD7927C366F\
+40B3D7ABBDEB2332DDB586AF80959097663CFAB2FEECAD6D368AE10EFF9663D5\
+F8BAB95935D25F45776F7F04B46817D05165A9DD4770509ABB92F8B9E7373CA7\
+80703569981754A51D6D376D65C57F55CD70E2DF5FDF5A6B829AE30CE3BF9428\
+15C8B4BE858DB58151D02A68AAB9FD373E047EFA51BD1A0CD1B61744D9E97CEB\
+A3334B3BAAFEA3BC9E43AE097CF2C3D713EECC247FF43EC74D54907D8BF45E45\
+B2E0E11D82B126A8179D3F66C055E11F69EA67AACC5FEE8AF01FAA379E51998F\
+5070F9EE0FD30A2EB22A925586FB1B39024EB5EB1E127C76A149E7F02AF1B73C\
+16E9E5A5DBE378E08A9FADF1194C625132AB3FDEFE8FE9A89BB8E0035A1A3AC5\
+278F5D3D0ADE0E41C81C6853A41C4AC45BE3F68180FE23F27F18BE2E339DE1D5\
+59D75DE63ADF7A32BAE42B037AEAA3E123A5314891BCD35CA48D57DF4C17540E\
+97202A8EA1328DA25B1FD6BE2B56AEC1E5DEB209F3B7A13ADB1CBE53EB645956\
+E577A7621D74E42376D70BC5C4AACD239A852FBB7B3F62CF59FE10438C1DC8E1\
+E46566325DA0CA43AAA63FB7E0B450A2DB3E3A2204704D894DB24B72B3078106\
+E096CD543DCF027650CB4965E38AC36A8AD588C5962B4E26548AB88F0BC20E10\
+ACC1C3FC00EF415B3C32499264552B14E2C0E789A3B8A8BFF9620FD939D0B34E\
+806177EC696A4B3B1CA4B32BA979B2690CFB3A6B17BCEE6877FFCE757E4116DA\
+01099FFE82ADD5A0C593E73449A96DB9CC2B9E846D166B095174F2CAF8B35DD8\
+78C836D9BB6EEEAF8E1BC5D0E149C739828CC480D731DC16B35B80D4AD82ED7D\
+29BD05018239EFECF8DEAE180C6A459DBCBFE4AAB9A5E2C1E1BC31418CF2EEEB\
+31FDF8BA02C9A91525E9163F672BAE2EDEC38C1BDB84EA237B4EF86BF5C0F0FF\
+E178E3761E82D94F66E5EA40BA8170BF768409E1B4177AAFD9937BCE3FBFF590\
+320D7C445372463FBBFB34F57447F42C16E026F179CBF82F617C86D1E8D42F6C\
+908F9C6B77E38D25D51303DBD781FFAB569B4CF31FD0B947C45E1768A2E9DFE8\
+369F520DC38D77937B69B821DB4FFEA8F50EBC404F0587B5598189F54B5A5B98\
+966FD16801C87DE2C3C7813DD70DC600824D426D88C55E89D47214D59206A7A6\
+5A65DA7CA2E42FA62ED17E7AA5B3ED446BCC71F17FEC8593BE96D2037BD07F94\
+76D4D732B32BC5DF8C921316B45699004716FC89F8D45BAE402C26DBCDF1A340\
+847B932FF882DBEAFBEDD252E126C89A1E1FDD8908A1F67D15D8E432DAD8E08E\
+950A3BC46B96CB89CC5BDAC703B3FA3E986EF1C6E7E6606E6845BA1EB2FBDCFE\
+E744B5E45206F4A419E1CB103C8490EB293EE9AEC1F0A0D294F9D3847737413D\
+30873F3C94740E8FD072817815EBBCE3F09EDEC9D1211A9E99547D620B2EC56C\
+89E9CB8144AE9E46636324BD13C6CCA3AB9CD9FD8F7F937ABABC598232384427\
+A2D4CE0CBF9765F7225E208C3CE128602B0AD08A1BAAB77EDB3111F0C6CA7BA0\
+EAC9D89D5B4378EB82C17F6EA08308A79A53D150D3F85EFAB77294F02EE0E288\
+5EE2AB2793392B87DB11FA77992F5B4FD75EF2F1A822E87407A4878894215AB8\
+9B6CC4A120F5A78B3C31AB80FFCC9ACEF53FC6F7F85685EB9D56D30D87C21ABB\
+F1652EEF8F32C7C567BD1F08623B09C29F33561D42727A5649A3850071AA6C11\
+735AE63C4FD31559CE560B27A362786A83353FE460B37074664A9421D3B2F6A8\
+64D5ACA087187B27E2B82F31CB3DF5E985CEA271C609B94B4E58356D40C7D5C7\
+FF2E5990FB39588154843EA5FCA92F120075D4C4D006661A0FA1B0585454BEA7\
+25473EEF7D58117D5840C8348999003736C5EEB7858FFD273A1C3EB2812F5697\
+C59110275B08F6BEFBE84C92497D5F73B7B6F794A849713B23AC5F29D5C7112F\
+B2E7A6E89EB54DDFA3122E6C79624C1BF25EBFB9FE5CE6DAA779F3ECB2984DA4\
+2F8C6ADC77B21DD291E684FCA50E46070962A2D4F00813D8DE1B8ED33FED9715\
+180C7EA8E2BB74FA65D9C7F6E142F3C81CDC59172E1020F62F65CA5A12CF2BED\
+9DEA04A4D8CABC2948F7BE823A3E792625275B3925A6C8D8E2B428C75A5DB0F7\
+120278CD7D6CAB768755C7FE2FBF89FDED1FB38AC7F76A2F8798CA36ED42CB7C\
+07F006271205F546A4812C20077F050D4CDC79459FA686E97F0704B7A9FF7DE1\
+6318E862C53D361BC635A55A264BE15016545DBFCE3C6D6849576ADEFB6884ED\
+D768214E0B438B0231B4F2692C2C0B5C177674F8A0DE236EACD9E0CEC7C8647E\
+4E9A5861B957EC834A2F8572F01304C3FD6A06019E5F1499B62BAA8670B65246\
+7FA9A4F10F053263BFE9743CC7D933F86136AAE3A6FB56754D7D238397A0030C\
+EBEA87CB255AF36138C373DBBAC41DD4A697032E4796C552AD9C9B3FA713C3A4\
+E09E0EC5581E94BE7F31065157662F9E9C678B1EF1B8B8A847C51789C22B1841\
+BCFC855820AF3258AF9E08231090B45D10046A00178E89BD515616B8A44E77BF\
+57795DABAF40687B2CDA7A5014168F:\
+CED226A8D39FDAF82FA3FB513B3D4DBCA48D586921B918F3CE45D1C5B294762A\
+AFAB4440F6732C6663D90E206C4C6552
+
+1633256AB03B20CE079196B708A1C02D1B6072219070712C8589EE21341D5075\
+2ACB6CFDA17E982D828BBD6CDF54BC7232FD418A323D64939928597B9B52F07C\
+F488250C5E42BFD3AB48012D709F8D747225839296386FCE5FC5AECC4BA7A107\
+6D089DEA8ECEFAA0CF66FCA8602395719C12A04F929321784D7AB8239FCE2FF3\
+BDAE046A266132B5C2AD9F7261F3014E87B389A6695978693D9371D0B1FF9C40\
+5F338C2FDE4687359603950A54CF4B9CDD9B24480B239ACC5405C14C886BBB03\
+78391CEF0662A38882BDD09E3866AB9A66CFBD28EB5EE4F8009BDEFC4AEB1670\
+0EBA7DC557B489190A71FDA75E85F7EF841697F70FFD4FEA185E7A67C81C5B8F\
+273BFB97B2CEF695C1C74446C4B425BE6B2E66DC0AAACB247E4467B7C7D84EC3\
+3B6B5AB8FA1979F503008BDCFF948CDBF1226B1B066CBCF34797298F3BA8C60F\
+A01E0AC8B803223C656112FB91435D75453BAE4707B63330467DD13E0A4B992E\
+6F7E46995899A2D95D23F4AC3D0802B2A6E7D024DEA19CA408C4BBE053F14C9C\
+E264F129724A18BCB18F385B1CA091A11434EA96D98C8D0602E98EDC8DFA1414\
+1AF93ED0BA66E885E9FA108591AE59E109AE34D6B9F5586E4B4D75E7DF7C3295\
+8A65E88A9BAF41082A0A3F11539DC4EA2CBD9E1C6C3C439B622F1DE574FA7547\
+0C8C939B51D2D1C2A7204B859881D43086BFD8FB90346218D099C5AB36846F3B\
+98A7C847318BDFA01E09717943FCD864C5A8A17B6CEB89D98E872D388F20ADC2\
+BE5E2006846904F41682FB1283214F3D20DBC9FC9E0FF571844A1282E88590D7\
+C085B2C568EC5ACC4462B389FEAA5757F7033187E2DE31955FCE55FEDC909255\
+048B327CCAB2E582BBC9D8054BF5CB45145C7D3A3AF9CD5CF6ECBA490C634ECF\
+00E646BF95E8642C43A4978EF08A574EF1F78F6CE57C3B34B5A123D123617FC8\
+EC9B2AC0F9B70A7F6062D38DD7B8E9FB4ECCEF13DED5C0477483ADDAE4F1CC0C\
+FCA274B1307ED0DE72FBCB819154CDA897D7575213042615F1741A8CB646A39F\
+8D134FDF9E60E000EB8220F65CC30F5FA52C431B9E3B6101B96E25B8D0440B96\
+E572A18A01747C02AFCD7513542F7AACE194632099D16274F31EBABB60DDD94F\
+E43DACCE900EC0902EB5E686D48ED8D09AE63DA0E15C736809903A0297A92DE8\
+4E0260F11F446E1FC448E0EBF59FAEA3C726F97925C57CBDF85B1F77078D3625\
+7C85D56CBBEDCE180FE12B687ADA2DC9912FAC60334166BD2CEF06B089ED5C95\
+63844D71D8FEAD2F3A93F3C07C52537336A8A70BF5B596B9007B9FDF2D082000\
+F20E6B70D2A7E6C7ED27C4146895A6D85A246F623C1B9258A2F891F823ADE4CE\
+FFD59D4FFAD077351E2F506E9A5BDD3900F0204B9E8969AFE72F5DCCB9CDF986\
+D197AE4C4DB53014041AE6221B750E5290E307AD292C8DE6B899235212EF8CE9\
+54785537DC9435AF11E0F3427A9C7B22EFA752EA0B7EADE5F6EB4093BACB7867\
+6E506698139E4F774423B8942166F9A7D22480D814FC0AE19CF4960FBF6E01FF\
+A65C8DA5BED4F1AE2B9ECEC5BE7B3C38DD4045B0C93EE6CC77A7E61E85D331B2\
+3C0D164B104518B3405497054445A353E9B48F2AC5E8E96298D6655614336CFF\
+E6D8C9C915E387391519AD2632366AA3BC935030FD12927EFCA17505ED74C946\
+50C778539004854DF6C24269AAB9C273A493D3E5B0B1D687C33C2FACE46B4BB3\
+742D6DF743D09164D2E0EE7F6BA128BD5FBA2E3B33C199AE80FA9DEE3AD811D0\
+2BAA3D42A6362B2AD47BBA8A2C5CD00B46CF22CFE367281488A4852EB8B7FACE\
+79F0CA6F8E78D32578DFEE01711C4DCF3C26D0BA13F3075478E708C5C5315AFD\
+C2E4C0062D16458213BEC506A9E991A61825FF78DA9BA1BAABBEFA56B4A8C9E2\
+E7B60EC4B7B541C8E0F79C86BB5F03F736761A37169B2AAB8884EC6EA217B02C\
+59035F5BB327243D126B78D4AAB430212439B5A75B80618DAFEB66AA3AFF866C\
+4DAEE47D374B512E74ADA933EF24A841BA271C6F02C870E8AB950FE06E93C91D\
+F0E99165DC01BCB190E411ECCD85358FD4A88127A22E4CF4266A90845124BF97\
+B25D7B1C46D3A0D68A684F84E2A638C692A52CB6E8C651A3AC492B0460004073\
+D5349E35552359CA37660F77B2770D6B2B3F7B1922424AC4A8598B4C61A6DB50\
+7608A72A6A7D573CC055206276E14005A28A0EC41F28D7E260611D40F089FFE5\
+E529375691412F4E9E12E62C3BE2C563C26D2444EA9C69E6C935FEB4DC4E802E\
+5FE3906F8ACEF4798D940C3CD574BB5E74506C3E0B70CB62454A25F589EADB6B\
+0709FE3B50417CD1D98F08E08B7CF68A04CCCF8D6588F9FC2F31E533CDA6159B\
+AA4297FA446450D71C16EA2324EC09773E7C8817ECF680ED12F64A04863EFE3D\
+9D8760F34DE5B0860B3991FF0EE5EDBA22C4D69120DE19D5429E4AAE91C9E7CF\
+05CC807159A58F13B480872AC1609D87E7009DEDB71C09CEAAB640A2B6135855\
+CEAE4AC2954933A0255B425D9FDCD9C246F82AEB7C3BB78C6E73E03DB7AEC424\
+5A28693FBD36EF4938D59CCE19EAFC00671A0851612406A075713C5D1154D8E1\
+3B59B7C5B0902239D4BACFA386AC817AC5EE02A181A9A47C622B3ECF287E1484\
+3D452AF347110498A620B34AB4E116308D976062C9EE9CD35DB6CB79805B93AC\
+9A15AFBCB52F1ED4309879D1924A4BA190B0B86E60A516E77D34B4E0A49D4EF2\
+CEF3CC2F410FD8EC901363FC9EBD75EB460D4D8910BDF27CE26A8B4AEB94F9F7\
+6242401DC35D0644842B99FB6C439B82D82ECFE1AF0D01F9BECB15BEC83F13B2\
+60F7F714AA381032923FDE8F8018F3518547451435C9A5207294D08A907C7369\
+6F6CB000745E072E25B73B3EE11595433D27A1F11468686F08094F1D31F5ADA8\
+1F11F0677A29D72EBB2E1C4792CCC607CB938647E1F153F9EEF03D982595C631\
+E49B6B7C1FA003A6EB8D59CB8892CD0888B05240F12701753F89007C859515A2\
+FEF944BC60B36003A26702AC6FE04D2E942978FC31A97EB29871D6752399D352\
+1720729007B6A7215A4282B2A4EFC2C56BD129E74C9B00847692B96FCC71CF7A\
+7F19F3FD6B45C519FD73B4860880A2DD74E5727B31A93F0A87F0078155344AE9\
+F7BDBF00D83393B634B5DCA88A398E42C320EB95C4A826ACEA90B65E4767B2EB\
+A748F97C247568393E2FD3A66075CC12935B6D7EB5C2FF5282185CB62C73972A\
+37B3CA508004B4F796BDF82B83B5BDF90D6BFD32B5089B0CA2683DC7FB2337DE\
+42E650ED911DBEE1EF98257F9BA5AF54B1A54B04C0087A5A64BA779D86461BA1\
+5337C2E7D4955FDD777A025DE226306A17C384F1C52CDB5946FB0B46DD5C13BD\
+7A55FE2E27E4C6D40D61D6FFC024468F8EDFC7C7992DF5DC5D05063FE7231992\
+24F53678E48F25250EA28BDF1089718EB8B730D1C06735C2F871164E2EB5E885\
+A8DFD2A083BE97EDC94159CE9BF75D2433F1D782762F771903CBF9A1C9D13F71\
+0BA0E151B079DC0A8262BCEB1DBCBBC0F35DF6EECF7BAA7105B9808745853C96\
+B4372E95E482035916B726DAC7BE95A72B19DAD48DB1B19E6EB2EDAB5AC1B301\
+3839E7806625ABC129F41813E6D71EE4AB2040D81E42E6ED73ABBA64FF2EB433\
+B910EA7D4F5ED3D8D27D39BB454EC019DF6114F544D7B155549D0C56D14551FA\
+F353994A80F30F3C97E863A4F2AF316468A568038EB4D799350A6FACAFF90ECD\
+44E0F44EFB6DC42EE4B0DC2C59EA9C1827326DF08C0A6E55CF4F9C3EA0E78CFF\
+3635F5D08E44F1400D20F638D56BA84B4832090454DE57EF04B6C8805A36F63E\
+5CCC6E830C87FFC164647CED20E4C486D09DE7A5F9E4B68D5456CDB22B0DDED2\
+B95B3BCAE529215C2D25D6823C7D66A4FAE0A1E9F022BA5663204F2314DFA51A\
+1F10E11D6D62A8BA6C28B6AE7DA1DEB5B57F2B65D7456059AD9F03DC5A524054\
+DA39DD100D74EB657DE219795E3C45A0E4C762BA22F9DA9D8159E425A1EE783B\
+4B22C250D8894CBEC706CE16D5CA393404FF478F141BE7CC69E45B077BA1955F\
+1F49EFBE4847C795347F703300F672334F490ABF8B644A34B56DA00EC45A3503\
+14B9ADF27CAF7C51CB7DBA0C5477E7D37662F4F23247BCB8F7DD5F3E9CB8BDA4\
+0FA97568832AF0ADC68F71422E412254A6BFC8943BB465B01FCC8DE0B957677C\
+78BC1F7566953E9D2446239F602C682A521C14F741FEA98C7E27AABEC339B6F5\
+B94C78287A894AFDAE971F8DA7C7E4A4C92C8DA47BE82DC2532EC2DA9BACEDD2\
+BE6DB2B2FB34DCCDCB34116507376578CBCA105E5E443BEC0F2EF23BE34CDF86\
+2EDAB34F0FF21335E3ACD92F59688B419F824EA61EEA82BC80E3463452192377\
+131BA51FB0795E089FC077D0ECA8012E58B0637AD7022206887FE9EC00EE5DF7\
+AD2E26FE819EE35C7A179C579098AA3DF645D9064CD557DA90BDD21F871CEB04\
+8CA56DF9653A10ED60F5E9F0ED7F8D89BCF5C22D1143CF44718FF2DFD8E10CEF\
+8AABB67D2305F18177C1426BD4CD03F2625E459CE905067826A214E08E56D8F9\
+455593E6B324E72DEDCC429D3BEFE2AE0599E360DF95E80D453A3A849E48389F\
+A745635BEDE30E7932DE6A3816E31A2217F98D5E40238963D0A36C159FD4EC32\
+D8A5CF59D433DEF3378634AF6887FDB3F3EDB96FC8840FE1B538C329674AE810\
+E8C8B2B46DB208716D38E9D1AEAB097068AD83ADD7DD2647839B3A7388B0615B\
+DE26F8692E9C07D8ADECC2A875203C3D3A9C6CB1D7D06307E9E1D9C3BC536DD8\
+EB271E9A2159C904E61E8C9357FE759F36366AEF5A3D14CEE82913CD2708AA60\
+69369CED763C8E830D70924E82E9015C2998E86EFC1DCE6AC2EBCB49455542A6\
+D7DAB265AD6D7381FFEEE1AA40F8FAC0659B6FB56BB03CD8CAFAACD48D13672F\
+7D524EB9684CFED4DBB7476E99149C28EC08F33BA6AFF839AA178F86B8EEAF17\
+39C829177BA78547AD394136AA3FAD451A11E9642506568B39668B2436610E06\
+EA45FA11D04D3759B033B5382645F15B3C39270B81B80487643913A24F2F1C1A\
+1ED57C85CCDDC8CD6D59B62FA67CC80572968C8FD01894F0153634C88792A7C4\
+A407A4A4CE46CEC5FE5D2569F95A27DE242444EA0C715B357518CAEA23E767E8\
+545983F0D3A4DF66111B4AA1D399CCAFD796D7A80E592D5A51D2B3F60B5B04F8\
+D9C009CA56CBD4DD84127A29B72ADB7645FB7279C9818B2B43963BD605F45B65\
+75A5E2E369E0B401F5EC10EC703F1179B0AB9D4A89D6F096573952E513827364\
+A84D38922734137E969D8167D6959B70F42F2BDA37E4C989ABAA8024C1A84ED6\
+BEB74780927F78B32EA736B9B2B4A795C355C0319811729D9CC399D235197303\
+38D62E16E5035FC52A817090703FE776D65EF9FEF5BA5F4FFEC3CC8E9EB2E312\
+C50A479BDD4E6AB0A56C18C2DF69ED408417BEE28BB41DD13F8366FF6EDA4B34\
+090FC9BC045271:\
+1CB96015F86E5DF62EBB416D772ED6CC74D056A83632EE18BACE73614AB0CED8\
+C3372EA72615CFE17F88C993FEE98415
+
+[Skein-512(512)]
+:\
+5AF68A4912E0A6187A004947A9D2A37D7A1F0873F0BDD9DC64838ECE60DA5535\
+C2A55D039BD58E178948996B7A8336486ED969C894BE658E47D595A5A9B86A8B
+
+CC:\
+D44B1D69E638D37908EE7C9EB212F4FBE465F2B383476C19BB5516E2A365BE1F\
+B33BD8E14B4E03539816B9E1430AEB6B16146E91D03BCE7968A35D7DAA4F9416
+
+41FB:\
+9FE78BD755A7B4E50E91033C250F65680D83D5288628FC848374496B849E0A21\
+31C538737FC48F017DA892D0F2A61C903790505313C4F22A207FC991E2BEEDC7
+
+1F877C:\
+14477998719358A65C531C8FD867A7830975FFB77FC8E7D997DC093B80C26FF0\
+02F691F74F7D4DCB2129354BBD04D5733B735D2A7548CAC5CDAC2D2A22D9D6F4
+
+C1ECFDFC:\
+7118835A893594C9829B6CBA912B03F90CAC2B5FCE8534181E90559237827381\
+A67D1D72422D3D896128A431DD36624DC9FC0423D66618945532C36485EBF492
+
+21F134AC57:\
+0B636B011E65FF9893C8B8665FAEB8438C1F2D67418B78E03372B835531EA6AF\
+B6AD6300BC7933A463AB675487E5BF4997B78DBA7453C35FD626657AE64B192E
+
+C6F50BB74E29:\
+162E21E3D5E818B47016E6E1C06889E418EFF6CABB735B1B1E6B5F19237F1DBA\
+CB74CDEDC6B764ED377B7BCD1EECBE7A83F4EE43AB075D8E6230DD6527645971
+
+119713CC83EEEF:\
+2A2909650F127D6E82E44E5E6A9808CF19C6755B8FDD57C8F2D14ECDBEF3D0CD\
+48CDC5E6D546A794B5B005A9A34C7F4D3B0C30DD9A45F73540431C46D5D75DA5
+
+4A4F202484512526:\
+67BFFE5E3E7AA93FF534949BE88A0BD280B74F65942904E925F361CC769E82EC\
+B3520E41A617788CE1F22A033B9476AD41AC890DF8AF61B3DCBC2C965AB8C539
+
+1F66AB4185ED9B6375:\
+BD27B8BAF70BD1A57F449B336FD441125070D317FF894EF5FFEC88F78EECCA9F\
+386B6502CC4340FA94F230A9A3FD39B94CD88D557F80CEB0B02DE7E482CE202F
+
+EED7422227613B6F53C9:\
+D62E7DD468F310B5BEC1FD2F8CE10EC55807D0F4D43CB34A1BA93BE818502898\
+8689E44D95CEEFBEF5BEACC63C95202C30858A8A788D83C60ECEB9327F89DD0C
+
+EAEED5CDFFD89DECE455F1:\
+38D4905C4233E15E0032CB3AFEC2016F7D4837BF9C3C50A5FB330E0F215132D8\
+98E516DA122A83FE995DFE80D0B9D16B959CCA1153FE74EE0B80AEED886FBF1B
+
+5BE43C90F22902E4FE8ED2D3:\
+55D8112842FDABB61FB26DA285C79025D3B22129F0B3A3A75BB32A30604BF7EE\
+42ED0A10B1F5307950739B1A3D10197F8DB5336AE81BEA27B5491F19F1D5A184
+
+A746273228122F381C3B46E4F1:\
+94CE960085179BDEDF655B1CE1E82C7F2F4B744B01ECE7F4F1E19D49AF88A7C9\
+5660CF77793A27C90C1060B22F6544169143708EA09F26416F81AB48278B504E
+
+3C5871CD619C69A63B540EB5A625:\
+A249D08ECB8D45E14B2ECFF34BB444A93F45FB687DA95FE2EDA2A645F0191869\
+43A0CA0635D5DC8DDD05007B21151CAB187B4BF0B831C70E48235D7FAB4D31F4
+
+FA22874BCC068879E8EF11A69F0722:\
+8004B6E57B50DDF61425194684FC6D2D548493C424BC380C5E20364D12939C30\
+333F04F170C02B8D39D0701AA9BD687DBCAE1856E4A358DC24086BAB50F8BF9B
+
+52A608AB21CCDD8A4457A57EDE782176:\
+83D4300128648D2C8A62970F3B228942A5708B525AF4F6CF52588686C65A1290\
+A3D1EA8BDEDF87D6FE81BE701FD237E7F80C5825E1BC02325B3869516D513C9C
+
+82E192E4043DDCD12ECF52969D0F807EED:\
+64D4BC8F76EACBBBAFFEF53E0A88C22369734541E709DA4C9E25E7FE796B6878\
+23474A38F8F9A0ED60FEDA6E052D415880AFE0A63A5B0EE1D9F3A97DBEEC6FFD
+
+75683DCB556140C522543BB6E9098B21A21E:\
+5F6CAAC2A8C20225ACCDF535169E01413DBD012BE8FC5B9D499D5E86A8D11728\
+235EF81FC7EEEB4AA55C4052065CE23D01E9FD9565500372890CB7B12CEA6E1B
+
+06E4EFE45035E61FAAF4287B4D8D1F12CA97E5:\
+7C298303F3C110FF7F0CFEA1BF0A5B03ECE9BE35707A2EF8A21EE7231986694B\
+681C246CBE0CD6B57746D02DDC2A08022D4F43DA48CDBB8608675A91F3EF6B6E
+
+E26193989D06568FE688E75540AEA06747D9F851:\
+F24A324C7D6002BEA95C2C58D76F7FB447EE8B8A44C79BC80A3561507B068E03\
+99E158EC21314EEEBD8C2BC3B2E754DE1A9CE6610873A9C6EF3E101E8DAFC377
+
+D8DC8FDEFBDCE9D44E4CBAFE78447BAE3B5436102A:\
+7CF59648210FE7128AD8100911DAC9315E5FB01691B14517B1A5CE2B87E09963\
+847623F230358284AB21D760CCB62A40CDB04B3F8F8F500FE71C7482B7AAB52B
+
+57085FD7E14216AB102D8317B0CB338A786D5FC32D8F:\
+6C7592D5EA214887F27BED37C73E5BB1F1F57A34D94B844729C99D136391F671\
+8313DE0E8171A9E72AF720DF8B8D79A644C156808E00E711434EBB1EF6A1A4D4
+
+A05404DF5DBB57697E2C16FA29DEFAC8AB3560D6126FA0:\
+A9B4107760E1A0CA06F58E6CCB8CDDCAC88FAB92A6AE78ADE7086D1D0F3F21B7\
+F3F61E750B98F2CCA926236381B00BE45C5B61398917090D1D97D86CE32CD4AE
+
+AECBB02759F7433D6FCB06963C74061CD83B5B3FFA6F13C6:\
+7F8863F906EF0605D3CA7C225D8EC78E793A53A2ED5EBCD06A6332B5F3CFE8A1\
+0FF722B087E8326C2D17EA38285509FDEE1337E75163AC3F24268D2CC3117755
+
+AAFDC9243D3D4A096558A360CC27C8D862F0BE73DB5E88AA55:\
+39F7739EA96268971A4D14F2DB217BB582EDE8891E5776EE1B7C9D380D7EBD62\
+A26AD9AC880E606950AB156ED0E58F05D7F1351FB69F91EF91F8D9BDB1A13B56
+
+7BC84867F6F9E9FDC3E1046CAE3A52C77ED485860EE260E30B15:\
+E12ABD9E3EF6CD2029BE5C3FE2BEB3909CD41EFEDD940D1CF7BEBE9921303115\
+F4FE78E3880821C8FB17C91D170C533072D260610510EDAF370655DFB4D142F7
+
+FAC523575A99EC48279A7A459E98FF901918A475034327EFB55843:\
+83CA72EBC5D7733F617BB3137551052DF789BCBF1ED9EA37E8132A3BB21B7AD6\
+31147FCEA0342D39E30C98F01B32CD804BE246CAE747CFDB9F9CCAA6A384D215
+
+0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E:\
+9B2B9905B6CBA3266ACD36AB4BFFD1038EF7D85E3CD4F6A538B2370771C4195A\
+0B057DF95B167D56BA14AA49F01D1D0E79547C8373B86807BB98C5B6D55E0240
+
+A963C3E895FF5A0BE4824400518D81412F875FA50521E26E85EAC90C04:\
+198CE7B1ABD54A06D27177CCFC875E557A3F88AAEA24FE27D42EB28F5DC3EDBB\
+7F94AB88E5536D1EFD79D68B9466419CAF146DDDB8707EBDF1E241FA8B4F43D7
+
+03A18688B10CC0EDF83ADF0A84808A9718383C4070C6C4F295098699AC2C:\
+3FF97EE9A9B02FCB9198C2B0674D039071AE38344EE45EADCAB21505B916DC71\
+8C9E31E31586D2D1DB03C3C4C32F65B44EDC00B8A02ABF0B6CE58303438989F8
+
+84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29:\
+D48BFE65490DD33DFBE4F218E786778EF6BA41507ABAFB0AE0566CDC95705FD4\
+F3C8D1C87D2FE3A6D1A770B5D2809552B3E7E4754A9EB8D300E7114A2D92163E
+
+9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10:\
+842443FAC2554CCFA9D8F23FB14AF18655D0E412B6EF6F156C4B2FCC2B6156AA\
+013D8D02FC04F4151899EDA22493A4F5D3C6402F1784A07BF4EAC6F83FE31D67
+
+DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE0\
+46:\
+A08A4E0CA9153E3B8D67FCC3607E22410E1F257243DCB0B02C4C1A3E7FF7B7C0\
+6C56F2A3EF6AF1F203F1AF353BCC654FA2788C397A584981DEEBB84B62CD784E
+
+62F154EC394D0BC757D045C798C8B87A00E0655D0481A7D2D9FB58D93AEDC676\
+B5A0:\
+94BC5CD05EC833E5ABA95E0AAD30704F53A759A03105A4EF0F66B05E4FB750DE\
+8D03171D45A8FAF53565C56D6CC1F254F97BFF437BD2AF271FCA14B6E10AFAE7
+
+B2DCFE9FF19E2B23CE7DA2A4207D3E5EC7C6112A8A22AEC9675A886378E14E5B\
+FBAD4E:\
+8C893818B1A4958593AAA3DFEC60A697301858F845060A97D630A7F60439911E\
+7498E4734779722459B8B038B58437499B9E04DC6AAC700753788904209862E3
+
+47F5697AC8C31409C0868827347A613A3562041C633CF1F1F86865A576E02835\
+ED2C2492:\
+604284B092DDFF75ABBE3C33DC49D602E32C925848A3CB6C5692A3BB41462EF4\
+9AB20964B92516A3D99D5CAA23F3C24BBE3F6BABCCF906EA337BD6389404E9D4
+
+512A6D292E67ECB2FE486BFE92660953A75484FF4C4F2ECA2B0AF0EDCDD4339C\
+6B2EE4E542:\
+8511F2B71FD7313E0F13DFA3334EE256FC696680C0588308DF978479990BC60C\
+757EE05CD869716164FC71A74C164F9EB8E013A3C26FC2B2DFFE3808E59BC6B0
+
+973CF2B4DCF0BFA872B41194CB05BB4E16760A1840D8343301802576197EC19E\
+2A1493D8F4FB:\
+AFED8C12189D55B3B7BC58767ECDED41CF3C990EB057BCAB0199341A9B548032\
+5679D87269EF95A03916BF29548FAF80092EA22D4BAE02500D26C5DD28C73AB6
+
+80BEEBCD2E3F8A9451D4499961C9731AE667CDC24EA020CE3B9AA4BBC0A7F79E\
+30A934467DA4B0:\
+F4A3305E83BFF9F4E724DED2621D186AB60C61E787207C60328FD2D998B6A16D\
+9B8C6527306ACC3E4307549C65B5013EBEE2827D9E2790D54B8906339FA6630A
+
+7ABAA12EC2A7347674E444140AE0FB659D08E1C66DECD8D6EAE925FA451D65F3\
+C0308E29446B8ED3:\
+B3E5DC61E4E8F42CF6FBEC1CB36B87A0EC15E3672BC31A74F4A4BB0C35A2F509\
+8166AAE37100326EC7E3C2D85E869AAD5FBF6C257AC8AF003AC2315138289219
+
+C88DEE9927679B8AF422ABCBACF283B904FF31E1CAC58C7819809F65D5807D46\
+723B20F67BA610C2B7:\
+CB8289DF6CA9F60F82D2ECBB27F6BB58C1E10588ADF3A875DD2154FC258CE8B9\
+77F68A03B8B91075B0930E9AB9E69EF6B55C005967D67BA1CE401B73D58D6FEF
+
+01E43FE350FCEC450EC9B102053E6B5D56E09896E0DDD9074FE138E603821027\
+0C834CE6EADC2BB86BF6:\
+A48EDB5A5466949DF0C13F0B31453D43B1E6072FFB46F1D271265F66D0712B9E\
+8C1FAB7BA33F7B598611B67E6C563577BFC6A5536A31B3FE77229752B3443163
+
+337023370A48B62EE43546F17C4EF2BF8D7ECD1D49F90BAB604B839C2E6E5BD2\
+1540D29BA27AB8E309A4B7:\
+D177AF21ED52695508442EE117EB2B958E992BE4E6EEC486D35164B34857AA9E\
+DA06ACFE8F2D83D65B6A3AA0EB16921995534BF5BA1E92340D65B86D1FD729D9
+
+6892540F964C8C74BD2DB02C0AD884510CB38AFD4438AF31FC912756F3EFEC6B\
+32B58EBC38FC2A6B913596A8:\
+473029BD56406552A0A73E42EE5C4E940BC0DF4615C3A6E90ADFD7ACCC642C87\
+2172E374C74065FA0E9CFD0D2FF837CB1FDCD28E337F8904962111983A446E9E
+
+F5961DFD2B1FFFFDA4FFBF30560C165BFEDAB8CE0BE525845DEB8DC61004B7DB\
+38467205F5DCFB34A2ACFE96C0:\
+95890A1D43E76A33C3CF4E3CAF9477310E240AD7ED33A1278A29B20D7CC0A7C2\
+D2AA3E2CDC64AE682BF8063449F972AEC5E7B5B29703E6B5D4C9746051E8C392
+
+CA061A2EB6CEED8881CE2057172D869D73A1951E63D57261384B80CEB5451E77\
+B06CF0F5A0EA15CA907EE1C27EBA:\
+80E68A5A7E83E11B5E872AB0EF2B4AE83BF0AE5F69C0C9877011D26E74DFBF01\
+02B3788BEABBE6B397E4930C37A9F9589D933A29D8F0817756A2DC760CC6260B
+
+1743A77251D69242750C4F1140532CD3C33F9B5CCDF7514E8584D4A5F9FBD730\
+BCF84D0D4726364B9BF95AB251D9BB:\
+1B7CED96075AC040E0DB5920DF335A5156E88E8CB4810CB678CB22022AA9B604\
+24761F576C20C8A1C34F3E2290E9035697E40DC6BD309652B3104AC16E930997
+
+D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7\
+C7F157298EABC4DCE7D89CE5162499F9:\
+3C0C4F502CAF055E9B145DAF4B45FCAB168C2CC7CF5BEEE2273F76D047AFAEB4\
+9A72A4D677DA23D0D7BD916C43E3B7D546E5A155F4DD2C877B08A880153D6409
+
+BE9684BE70340860373C9C482BA517E899FC81BAAA12E5C6D7727975D1D41BA8\
+BEF788CDB5CF4606C9C1C7F61AED59F97D:\
+EC59D0F7E4EBEDA8D53C8D562307CF2E040207C08EB90FF640E6C9D550851794\
+4757DACB0F00E3CB8548C2A363F8511034368A7BF200A62BEF363685F61250DE
+
+7E15D2B9EA74CA60F66C8DFAB377D9198B7B16DEB6A1BA0EA3C7EE2042F89D37\
+86E779CF053C77785AA9E692F821F14A7F51:\
+0D49FED2C3105D46DACFDEEAD9E029FBD5D80BC0D5931CA33105932E5442552E\
+357531BA36BE2F158AFE1E1983CCD5DD07C220DCD5956820A0A1A80BE7CAD201
+
+9A219BE43713BD578015E9FDA66C0F2D83CAC563B776AB9F38F3E4F7EF229CB4\
+43304FBA401EFB2BDBD7ECE939102298651C86:\
+C40708D0556997C243202DBEAADD5C18DD092BEA1988CED4E85B029C02912B81\
+192D262571B5578E8C50DD9DE8B30414D13AEA3CD134F19071B50524723ED9A7
+
+C8F2B693BD0D75EF99CAEBDC22ADF4088A95A3542F637203E283BBC3268780E7\
+87D68D28CC3897452F6A22AA8573CCEBF245972A:\
+C6333D0D55C12CFC2DCFF9661B81920FF38351382DB0D454D09512C2FDE2B109\
+F8C5D445DCDE08E18DBAB94DE6432AB88971AA57EC811FA6DC658F9DAD184DF1
+
+EC0F99711016C6A2A07AD80D16427506CE6F441059FD269442BAAA28C6CA037B\
+22EEAC49D5D894C0BF66219F2C08E9D0E8AB21DE52:\
+B7FD3B978E069F9A532E312D9B90AB8397D10DAA982184F76324D295A4D6DBAB\
+C3471B9817F1EE5881F611DE4F7A8CF66DA44C92284FE6DB7300CB98921F1EDF
+
+0DC45181337CA32A8222FE7A3BF42FC9F89744259CFF653504D6051FE84B1A7F\
+FD20CB47D4696CE212A686BB9BE9A8AB1C697B6D6A33:\
+C718B883F2CF362B3D85750A5C602D671A2A12542E305081A31B2EE20A6C4361\
+22CE67AF70D622B08412DE036AE7C4DF5AA67D3B74181309C139662733A9C4DD
+
+DE286BA4206E8B005714F80FB1CDFAEBDE91D29F84603E4A3EBC04686F99A46C\
+9E880B96C574825582E8812A26E5A857FFC6579F63742F:\
+AAC62EF9A43F0FFB93E89ACC421675E439F6C452851073877579EFF9D8CE126D\
+98A72DF829B066D12537FD5ADD3F5D584226A4885A52899E3FEDEC85F1D59176
+
+EEBCC18057252CBF3F9C070F1A73213356D5D4BC19AC2A411EC8CDEEE7A571E2\
+E20EAF61FD0C33A0FFEB297DDB77A97F0A415347DB66BCAF:\
+8FA10CD34DA4CF0E0FC2819F8C6843EA024AEF6786EAB7EB6C770C47D6B5F28B\
+32CDF3D1F6D23F4498FCB3D1135ACCB5AE9FB22519525E8A8A50A85FB7E72711
+
+416B5CDC9FE951BD361BD7ABFC120A5054758EBA88FDD68FD84E39D3B09AC254\
+97D36B43CBE7B85A6A3CEBDA8DB4E5549C3EE51BB6FCB6AC1E:\
+4FF9CB413E26122BF029A27014D932371CD3191622E062EAC7D13414FC9C52AC\
+F414B9E46353EC08F019403658F003F97A83B66CCE5D8127C5B64D7D937233C7
+
+5C5FAF66F32E0F8311C32E8DA8284A4ED60891A5A7E50FB2956B3CBAA79FC66C\
+A376460E100415401FC2B8518C64502F187EA14BFC9503759705:\
+31539AB8E30EB0DE0206ADBE95144482C42E6C9B7BDE8AEC94EE838215BFAA01\
+549212FC22058AE7A4B81CCAA36BFBBA05210C78346C9C687B2F24F47280A444
+
+7167E1E02BE1A7CA69D788666F823AE4EEF39271F3C26A5CF7CEE05BCA831610\
+66DC2E217B330DF821103799DF6D74810EED363ADC4AB99F36046A:\
+2CB150803ACEC71A771990A132FBEE6D841859E48C024D2757EAF2F6AEE737EF\
+0024A5F3BC423D4C8E5E3009E30A1EF7B137784221D602BEA3A83B81A8A2D5EC
+
+2FDA311DBBA27321C5329510FAE6948F03210B76D43E7448D1689A063877B6D1\
+4C4F6D0EAA96C150051371F7DD8A4119F7DA5C483CC3E6723C01FB7D:\
+93C64B20F4487EE75FDD266AA66228C31FB7F9C34A8C6BEE423A029AA0BBBEE7\
+50A597FC60C1180A1637455E8068E87AC52E6BC33DF55DFDD818B05920CB798F
+
+95D1474A5AAB5D2422ACA6E481187833A6212BD2D0F91451A67DD786DFC91DFE\
+D51B35F47E1DEB8A8AB4B9CB67B70179CC26F553AE7B569969CE151B8D:\
+77E947665E3674FBCD67139B98CAD5E0E05CBD04FE7978D489F0B3B0B8D26DE2\
+6A9C807F05B9D6EF30EC5FEF654EFA6B9F0366E155669F167F54EA2AF629C0B8
+
+C71BD7941F41DF044A2927A8FF55B4B467C33D089F0988AA253D294ADDBDB325\
+30C0D4208B10D9959823F0C0F0734684006DF79F7099870F6BF53211A88D:\
+6A020AABB7306680492575842E34A88A0329A43EA49D7EA6DC41FDAEA75BF0E8\
+0429D9378CF5DC6A05AFB4A2980C78BE223062126C7430CD95A5FAAFE82F2321
+
+F57C64006D9EA761892E145C99DF1B24640883DA79D9ED5262859DCDA8C3C32E\
+05B03D984F1AB4A230242AB6B78D368DC5AAA1E6D3498D53371E84B0C1D4BA:\
+F55C758ADD989972C679B26F399C204E4225CA29EC5AC8516DAFF82D90204BA0\
+8B3C4727B8E17100F9B9CFC04E7F39E5F6126C034CBCCF6FFA2DF3C0B081645E
+
+E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\
+E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\
+E33EDAF1D7A3553340DD919BF207E6852E5D5B3E09CC57C5CFEBAD2CB7D78600\
+2D7D568604CEDD09F9C24EA8377558F5E0A718BD47802DF75B8417F79743F4BD
+
+16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652B\
+DF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC\
+00:\
+B14AE0A5B22EFD7DD9CDD9493BC44F4DB00DE603F495FD7CC1C9D1A6526DC415\
+DEE5B7CC5906268C0005DA223A7D9F61347B12135EED23E971FFAF1A231BCB79
+
+FC424EEB27C18A11C01F39C555D8B78A805B88DBA1DC2A42ED5E2C0EC737FF68\
+B2456D80EB85E11714FA3F8EABFB906D3C17964CB4F5E76B29C1765DB03D91BE\
+37FC:\
+0771607C10C77F9C2CC381CC16265B51492E996B75D05A84088467FA33CD5644\
+20986C7FD32FF211FD4017C7CD3FCDDE9CB9869679511363F72CC121832847F0
+
+ABE3472B54E72734BDBA7D9158736464251C4F21B33FBBC92D7FAC9A35C4E332\
+2FF01D2380CBAA4EF8FB07D21A2128B7B9F5B6D9F34E13F39C7FFC2E72E47888\
+599BA5:\
+A1AA396E8689DEF39B8B81424525AB466FEF29EEC2E0B418E6FB4819A1D5E916\
+3A342E9FF9B013E49091FC1AF06879FFCA3C9FB40D0A5BB885CA7AC6495E2EEC
+
+36F9F0A65F2CA498D739B944D6EFF3DA5EBBA57E7D9C41598A2B0E4380F3CF4B\
+479EC2348D015FFE6256273511154AFCF3B4B4BF09D6C4744FDD0F62D75079D4\
+40706B05:\
+713FE585737CA3817C711A5A747AC2C9B83E30EE9A83D5E6639EE4EB3A0F039F\
+F2342E25868D63BDB0FDA1030C26E2CB12997320A1103325ECD37E3FE06B95E5
+
+ABC87763CAE1CA98BD8C5B82CABA54AC83286F87E9610128AE4DE68AC95DF5E3\
+29C360717BD349F26B872528492CA7C94C2C1E1EF56B74DBB65C2AC351981FDB\
+31D06C77A4:\
+8C54B270780181E9AFFB354A46967D2E15EB627A33B9B51FFCD470B6D6CD5EDA\
+728F52244DCB6CC601A377F1912E3C081DEBE1309D52CC8A24AE932346B532AA
+
+94F7CA8E1A54234C6D53CC734BB3D3150C8BA8C5F880EAB8D25FED13793A9701\
+EBE320509286FD8E422E931D99C98DA4DF7E70AE447BAB8CFFD92382D8A77760\
+A259FC4FBD72:\
+37F6454A0790CF4228DB57AAA21361F4C9445F5D43769B0667E8DD4651C9FAA5\
+D82AB2232E1F76E0B43AE3B231E980197E93A89DD17FAA87F8C1974DD4691D2B
+
+13BD2811F6ED2B6F04FF3895ACEED7BEF8DCD45EB121791BC194A0F806206BFF\
+C3B9281C2B308B1A729CE008119DD3066E9378ACDCC50A98A82E20738800B6CD\
+DBE5FE9694AD6D:\
+066876DEA299473304E95FDE464BC8DE5EF690F7ABD175FBF645627B2510696A\
+CBA360B3AC18738EF8BA68E9061A1AF8ADEDC0CDBD6BAB3BB191E90FFCC275D0
+
+1EED9CBA179A009EC2EC5508773DD305477CA117E6D569E66B5F64C6BC64801C\
+E25A8424CE4A26D575B8A6FB10EAD3FD1992EDDDEEC2EBE7150DC98F63ADC323\
+7EF57B91397AA8A7:\
+F08F0A71CF5691E602FABC24F466C737CC796AC4F467F42EA0751466426026C0\
+DD26211286D8783810CA8E3989891A6A4ABB54FF214391172DFDFA4F38214E54
+
+BA5B67B5EC3A3FFAE2C19DD8176A2EF75C0CD903725D45C9CB7009A900C0B0CA\
+7A2967A95AE68269A6DBF8466C7B6844A1D608AC661F7EFF00538E323DB5F2C6\
+44B78B2D48DE1A08AA:\
+3D59497B54622B33A4A8238653792A99E89E3DCCB8925149954E7DE6027D89D1\
+5D24D7B8E43D35C8C4B2DE8AF22138DC0515C4B20FB9A5EC065CAEF7E422C47A
+
+0EFA26AC5673167DCACAB860932ED612F65FF49B80FA9AE65465E5542CB62075\
+DF1C5AE54FBA4DB807BE25B070033EFA223BDD5B1D3C94C6E1909C02B620D4B1\
+B3A6C9FED24D70749604:\
+3BEC4E0682BEF95AB5495A5949B11F570B3DA7801C7383F2A01EA87302BF40C1\
+61EA827828EB1763DA0D401DF4010FAD5329E3B1CA4A9925D2ACC325D5C9A906
+
+BBFD933D1FD7BF594AC7F435277DC17D8D5A5B8E4D13D96D2F64E771ABBD51A5\
+A8AEA741BECCBDDB177BCEA05243EBD003CFDEAE877CCA4DA94605B67691919D\
+8B033F77D384CA01593C1B:\
+B04D52AB7728CB43949ABF54274AC6842CF5B6BF1B7AC38FC352735322B9A655\
+7738E65580A0D110EED81E484BB2EE7FE8FFD257A9F9DCEC28A29B837D064F8E
+
+90078999FD3C35B8AFBF4066CBDE335891365F0FC75C1286CDD88FA51FAB94F9\
+B8DEF7C9AC582A5DBCD95817AFB7D1B48F63704E19C2BAA4DF347F48D4A6D603\
+013C23F1E9611D595EBAC37C:\
+F33AED5F4B135D56A1387823FFC3E0B743C2D80E7EC32B7D8F339ABE83047790\
+8BB12F90F7BF18DD01C899CF6249AF4E77AE862B9BD80DC68CE05CD316A94E24
+
+64105ECA863515C20E7CFBAA0A0B8809046164F374D691CDBD6508AAABC1819F\
+9AC84B52BAFC1B0FE7CDDBC554B608C01C8904C669D8DB316A0953A4C68ECE32\
+4EC5A49FFDB59A1BD6A292AA0E:\
+C235A9378EE1138DDEBF7BA475C0E298AD07673C03C3EC7FD6C67C957C80C56B\
+1ED079EEA09E84A7EEED20F3A10679A621205871E908D41589B4CAFB158A9BED
+
+D4654BE288B9F3B711C2D02015978A8CC57471D5680A092AA534F7372C71CEAA\
+B725A383C4FCF4D8DEAA57FCA3CE056F312961ECCF9B86F14981BA5BED6AB5B4\
+498E1F6C82C6CAE6FC14845B3C8A:\
+0F15A5BEA0B3FD775796B8AF4C37C6293258CAA7137AD1EA1C42E85223C4F790\
+A1622B9A0EAB00AEFFC2F6C5D5F410A366C401BF30711F42A5CCB053B988452C
+
+12D9394888305AC96E65F2BF0E1B18C29C90FE9D714DD59F651F52B88B3008C5\
+88435548066EA2FC4C101118C91F32556224A540DE6EFDDBCA296EF1FB00341F\
+5B01FECFC146BDB251B3BDAD556CD2:\
+8A9C9EA4910C8E0013387EE14D2158AB77A6E8E8D9BDDAD46012C0E8492EEDB3\
+6B6633C77B611C54438E33835C0AEB10EA2DB72D3A876C463DE848BDB75368E3
+
+871A0D7A5F36C3DA1DFCE57ACD8AB8487C274FAD336BC137EBD6FF4658B547C1\
+DCFAB65F037AA58F35EF16AFF4ABE77BA61F65826F7BE681B5B6D5A1EA8085E2\
+AE9CD5CF0991878A311B549A6D6AF230:\
+9845D5E82E4811D34FAAAD0B0AFFB22058B3F3BA23A2F2D2C96118510B51DD8E\
+8B58F6BE4997D60130FAE637BFB6172CE15A220F194AE2A706119A0681469C7C
+
+E90B4FFEF4D457BC7711FF4AA72231CA25AF6B2E206F8BF859D8758B89A7CD36\
+105DB2538D06DA83BAD5F663BA11A5F6F61F236FD5F8D53C5E89F183A3CEC615\
+B50C7C681E773D109FF7491B5CC22296C5:\
+668BC32E633DF1C83D2E1E16E74A4EB292B5E9A92500213DC02A68AA98A783A9\
+21E73C78224A77DCD480551D7A07505C586DACB13E76C6C9C882B0F34848FA1F
+
+E728DE62D75856500C4C77A428612CD804F30C3F10D36FB219C5CA0AA30726AB\
+190E5F3F279E0733D77E7267C17BE27D21650A9A4D1E32F649627638DBADA970\
+2C7CA303269ED14014B2F3CF8B894EAC8554:\
+8232E343C42568FB76CD4AFA7C554CC10F1188DB5CC22779C3614F03216A8783\
+7B8F331A02EB586C9764920D5CF62CA733DEEC217997E4D617671D35AA045217
+
+6348F229E7B1DF3B770C77544E5166E081850FA1C6C88169DB74C76E42EB983F\
+ACB276AD6A0D1FA7B50D3E3B6FCD799EC97470920A7ABED47D288FF883E24CA2\
+1C7F8016B93BB9B9E078BDB9703D2B781B616E:\
+4FC121F7F12E84CA4CCBD936B65A072FF73D80D8F5CC3AE73D0B6108A2C21238\
+56FAEE60C54F578042E26398B4E2EE19595B8775FF30672A489CDCCB8689B6AE
+
+4B127FDE5DE733A1680C2790363627E63AC8A3F1B4707D982CAEA258655D9BF1\
+8F89AFE54127482BA01E08845594B671306A025C9A5C5B6F93B0A39522DC8774\
+37BE5C2436CBF300CE7AB6747934FCFC30AEAAF6:\
+DFF6BC6E2CF7BC1FB5B31B3779B58D5E6747BD83C4D0330C01D509059AFBC821\
+9B0F007580F6819C374C7892EDD6D5D2998D77EFF37F6412F44DADFBDF190206
+
+08461F006CFF4CC64B752C957287E5A0FAABC05C9BFF89D23FD902D324C79903\
+B48FCB8F8F4B01F3E4DDB483593D25F000386698F5ADE7FAADE9615FDC50D327\
+85EA51D49894E45BAA3DC707E224688C6408B68B11:\
+A00BE2BC62617F78B7A40771B0884304DBDCC4D9A18CDB6C090AA60A8A9B4E5F\
+337A08BFDBAF8BECE5758B68D5F9A4615B797677ADFE076D701AAE7D177707BC
+
+68C8F8849B120E6E0C9969A5866AF591A829B92F33CD9A4A3196957A148C4913\
+8E1E2F5C7619A6D5EDEBE995ACD81EC8BB9C7B9CFCA678D081EA9E25A75D39DB\
+04E18D475920CE828B94E72241F24DB72546B352A0E4:\
+FBADA5CC80D297537DDE932D45BB3CB2F08EA9859AAE830ECA90454D757CA11F\
+A719F260E613F5621D1AE1A9DAE2EDF8C81B4595008610E3957FC965CA6E021D
+
+B8D56472954E31FB54E28FCA743F84D8DC34891CB564C64B08F7B71636DEBD64\
+CA1EDBDBA7FC5C3E40049CE982BBA8C7E0703034E331384695E9DE76B5104F2F\
+BC4535ECBEEBC33BC27F29F18F6F27E8023B0FBB6F563C:\
+38992902898AF4199CB7AF17E9890D2CFF7C772C65CC6A89CB524D07A4927290\
+D7DEC357C99253A14098B9169E83B970C65ADE55D66DFD64FBB6FE3421661FE1
+
+0D58AC665FA84342E60CEFEE31B1A4EACDB092F122DFC68309077AED1F3E528F\
+578859EE9E4CEFB4A728E946324927B675CD4F4AC84F64DB3DACFE850C1DD187\
+44C74CECCD9FE4DC214085108F404EAB6D8F452B5442A47D:\
+6A790982AA5FDFD646AA1CE1F7026BD70CD8F4B16D5A98F78F9853C9F454EC1E\
+653D8E81B074B83964E083D42A87371FF627F316C73E1CAACDF22B359C64D1FC
+
+1755E2D2E5D1C1B0156456B539753FF416651D44698E87002DCF61DCFA2B4E72\
+F264D9AD591DF1FDEE7B41B2EB00283C5AEBB3411323B672EAA145C512518510\
+4F20F335804B02325B6DEA65603F349F4D5D8B782DD3469CCD:\
+F7F195061FE0F6B3CE2BB0A1AE6F62040EA4BCD7F76750B7254D39F29FAABBFE\
+95810714F24FD2C2AEB25F037BF81FFAA14700D2F6EBFF5E341FFE7DE471DE82
+
+B180DE1A611111EE7584BA2C4B020598CD574AC77E404E853D15A101C6F5A2E5\
+C801D7D85DC95286A1804C870BB9F00FD4DCB03AA8328275158819DCAD7253F3\
+E3D237AEAA7979268A5DB1C6CE08A9EC7C2579783C8AFC1F91A7:\
+4F25B9AE73EB2ABF53BA6D8864981AE382332279A57D6008C000709AB7BA1FC1\
+87074C9DE58BA55C88B532481C1110EFED65F9F89F55AA5C307A099066D9EAD3
+
+CF3583CBDFD4CBC17063B1E7D90B02F0E6E2EE05F99D77E24E560392535E47E0\
+5077157F96813544A17046914F9EFB64762A23CF7A49FE52A0A4C01C630CFE87\
+27B81FB99A89FF7CC11DCA5173057E0417B8FE7A9EFBA6D95C555F:\
+909287F22D5619789410D2148F99D8997E6C42741A784A2C289D936FBA3A11E7\
+10E6F4A3918181BE5F3DBF8E867478D6F6F5189480A0FF327A479480932189D5
+
+072FC02340EF99115BAD72F92C01E4C093B9599F6CFC45CB380EE686CB5EB019\
+E806AB9BD55E634AB10AA62A9510CC0672CD3EDDB589C7DF2B67FCD3329F61B1\
+A4441ECA87A33C8F55DA4FBBAD5CF2B2527B8E983BB31A2FADEC7523:\
+F9419515E368F174C98E6CBDBD0C4A608D49ADC8C0D0AFF45D2045385D8C8656\
+0A1F107E16AC294A22E2E29382CE39D2D63ECE51FCC8D02371605A5AE647E710
+
+76EECF956A52649F877528146DE33DF249CD800E21830F65E90F0F25CA9D6540\
+FDE40603230ECA6760F1139C7F268DEBA2060631EEA92B1FFF05F93FD5572FBE\
+29579ECD48BC3A8D6C2EB4A6B26E38D6C5FBF2C08044AEEA470A8F2F26:\
+28F4D11F5F7811CD0DBC382F9DB2C8F309CCF510EDC13C7577EF73AC04FD9C89\
+75576DCD0A75D725C216BE2FC016D84128BC30C29BD838A8E5D23C7EC0D2279F
+
+7ADC0B6693E61C269F278E6944A5A2D8300981E40022F839AC644387BFAC9086\
+650085C2CDC585FEA47B9D2E52D65A2B29A7DC370401EF5D60DD0D21F9E2B90F\
+AE919319B14B8C5565B0423CEFB827D5F1203302A9D01523498A4DB10374:\
+E11ACE7F6D80AA0D2A6F80F74BAB9FB6CED1082B0BAEC48FFF2CD00B4A04A67C\
+58EEED8A617A48704AF36CAF8B3D38766DB1D88C0B4CE404DF15E703EB5C60A2
+
+E1FFFA9826CCE8B86BCCEFB8794E48C46CDF372013F782ECED1E378269B7BE2B\
+7BF51374092261AE120E822BE685F2E7A83664BCFBE38FE8633F24E633FFE198\
+8E1BC5ACF59A587079A57A910BDA60060E85B5F5B6F776F0529639D9CCE4BD:\
+C34CD1BBB4BA5A3F35A2050B4BC01FB45DCC12929D250195B681CA17299F41A2\
+D466629B28BA0DDB5A8E7117836D09DC3654449A6225E245DED5E47F5116233A
+
+69F9ABBA65592EE01DB4DCE52DBAB90B08FC04193602792EE4DAA263033D5908\
+1587B09BBE49D0B49C9825D22840B2FF5D9C5155F975F8F2C2E7A90C75D2E4A8\
+040FE39F63BBAFB403D9E28CC3B86E04E394A9C9E8065BD3C85FA9F0C7891600:\
+625A5D81169F344C5502E0F37A8373FEA67DD046A9F529DC2FD8AF63C930F4DE\
+D077145CDBCFDDD26BFF74B4B6855D12923906FEAF767BC3FA5F650D35FBE93B
+
+38A10A352CA5AEDFA8E19C64787D8E9C3A75DBF3B8674BFAB29B5DBFC15A63D1\
+0FAE66CD1A6E6D2452D557967EAAD89A4C98449787B0B3164CA5B717A93F24EB\
+0B506CEB70CBBCB8D72B2A72993F909AAD92F044E0B5A2C9AC9CB16A0CA2F81F\
+49:\
+8E4E564509D498AF8730C1F624B5B3ED039CDF1F9D0FDF7E6662BFD2F21D6350\
+37E9D724E646777AAD6AC17B1E10B516528658FDB923D4AD14EAD28018AC0BB0
+
+6D8C6E449BC13634F115749C248C17CD148B72157A2C37BF8969EA83B4D6BA8C\
+0EE2711C28EE11495F43049596520CE436004B026B6C1F7292B9C436B055CBB7\
+2D530D860D1276A1502A5140E3C3F54A93663E4D20EDEC32D284E25564F62495\
+5B52:\
+1CF572260B273D588B8F69C79C95E799441AC2BDD53E755BAFBE650E066794B6\
+6584FF66BFEAD0D6439CF8559F4AE723A7C8E5AA9968C3A3F413CE112CCB3F9F
+
+6EFCBCAF451C129DBE00B9CEF0C3749D3EE9D41C7BD500ADE40CDC65DEDBBBAD\
+B885A5B14B32A0C0D087825201E303288A733842FA7E599C0C514E078F05C821\
+C7A4498B01C40032E9F1872A1C925FA17CE253E8935E4C3C71282242CB716B20\
+89CCC1:\
+96DDFEF31B9C589ADF4DD7AFDEA6F4D3F053C96518C51E9A6B1B56083B4D4371\
+72AB6AF42E3E4504E8186CF5A20FA1384A9DD56431181786562A7765F3BB5734
+
+433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B982\
+14B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784444F\
+22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53E7E084\
+6DCBB4CE:\
+C482F674B5C5CA87BC3417A07053F160C6ED905B6D7A7BBAD4288AEE2854B54C\
+1B7350F6D23BEEDB5C687721FCD1B5E46C19D1625B3AB20EB2C22249C95672C6
+
+A873E0C67CA639026B6683008F7AA6324D4979550E9BCE064CA1E1FB97A30B14\
+7A24F3F666C0A72D71348EDE701CF2D17E2253C34D1EC3B647DBCEF2F879F4EB\
+881C4830B791378C901EB725EA5C172316C6D606E0AF7DF4DF7F76E490CD30B2\
+BADF45685F:\
+C721ABCA24C7A496275D7B4171CE962144A7AAAFC9984CBFB7A6CBF69BDC6A36\
+39D363386171FE08E13609A2EAB4D78CEF842D95BBEE248CD662B7ACE72D7A8A
+
+006917B64F9DCDF1D2D87C8A6173B64F6587168E80FAA80F82D84F60301E561E\
+312D9FBCE62F39A6FB476E01E925F26BCC91DE621449BE6504C504830AAE3940\
+96C8FC7694651051365D4EE9070101EC9B68086F2EA8F8AB7B811EA8AD934D5C\
+9B62C60A4771:\
+473AD9315718739279E96A01F10E6D58B1272F6BB3496F2BA915D6E5B702FE96\
+2F1384CCC7C96E7EB71E54FEDA2F58016092BFD0DBCF70A4EA353A72F83A3FC4
+
+F13C972C52CB3CC4A4DF28C97F2DF11CE089B815466BE88863243EB318C2ADB1\
+A417CB1041308598541720197B9B1CB5BA2318BD5574D1DF2174AF14884149BA\
+9B2F446D609DF240CE335599957B8EC80876D9A085AE084907BC5961B20BF5F6\
+CA58D5DAB38ADB:\
+3D673DA2CF25C00F21B51F30A41675B97FB59F828815B858F62F3E70AFBEE61E\
+AB72652213323FBAAB554C72A593FFCA648A03DD34806302984D8F91540B7196
+
+E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486\
+F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D\
+B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A\
+21691E1069413848:\
+E90BEDF3CC53985910E405E6FD3357E9E34D642B8492341AC63E4B97DC097D5B\
+0E1617A4DCA0E8AA142595A7D52F2353189FF419328F60DCC9DAD5B5240D8C88
+
+64EC021C9585E01FFE6D31BB50D44C79B6993D72678163DB474947A053674619\
+D158016ADB243F5C8D50AA92F50AB36E579FF2DABB780A2B529370DAA299207C\
+FBCDD3A9A25006D19C4F1FE33E4B1EAEC315D8C6EE1E730623FD1941875B924E\
+B57D6D0C2EDC4E78D6:\
+D3D783CFC9AE13C2CD463A2FBD776497435C5F31376C7DEB25F8F075ACD1640F\
+0FD244F2B8F80B1A8247D12BEFFC85994235A7357DEA2AF3952D8AFF69D2DD66
+
+5954BAB512CF327D66B5D9F296180080402624AD7628506B555EEA8382562324\
+CF452FBA4A2130DE3E165D11831A270D9CB97CE8C2D32A96F50D71600BB4CA26\
+8CF98E90D6496B0A6619A5A8C63DB6D8A0634DFC6C7EC8EA9C006B6C456F1B20\
+CD19E781AF20454AC880:\
+EFB0510BE69988D8AC86EC6EC8955E81970BBB6419967E9886C479AEEB3C2B35\
+C210E388B3FD84F7CCCF7C8FCEEF27A760342446418274784319D1BFB6E31D7E
+
+03D9F92B2C565709A568724A0AFF90F8F347F43B02338F94A03ED32E6F33666F\
+F5802DA4C81BDCE0D0E86C04AFD4EDC2FC8B4141C2975B6F07639B1994C973D9\
+A9AFCE3D9D365862003498513BFA166D2629E314D97441667B007414E739D7FE\
+BF0FE3C32C17AA188A8683:\
+78EBBABA1E277949D3227086A8FE5C8AACEE40E78D16DF9CFEB80C0F5AA2160D\
+F19FE72BA4F2B2BBF5C6142E370F6FB70660551C96E02FE84AC3910D7FAA8655
+
+F31E8B4F9E0621D531D22A380BE5D9ABD56FAEC53CBD39B1FAB230EA67184440\
+E5B1D15457BD25F56204FA917FA48E669016CB48C1FFC1E1E45274B3B47379E0\
+0A43843CF8601A5551411EC12503E5AAC43D8676A1B2297EC7A0800DBFEE0429\
+2E937F21C005F17411473041:\
+0EFF04A9DCF46B12BE7FC8E1EB96B6C77FD7C8B548F90F7B4BEF8181AEE70BD6\
+F7538B508290C796D4656AB64C13BF965EA30A40A79BB084BB23A0DC3C962F5F
+
+758EA3FEA738973DB0B8BE7E599BBEF4519373D6E6DCD7195EA885FC991D8967\
+62992759C2A09002912FB08E0CB5B76F49162AEB8CF87B172CF3AD190253DF61\
+2F77B1F0C532E3B5FC99C2D31F8F65011695A087A35EE4EEE5E334C369D8EE5D\
+29F695815D866DA99DF3F79403:\
+811DCEC2A8020F66974EC685546BD97854C72597332B860DD687FA977CC82159\
+B69D61F106AC4A70833BDC78471632D96FD1BA82BBCBFA9415FDCA12F868A813
+
+47C6E0C2B74948465921868804F0F7BD50DD323583DC784F998A93CD1CA4C6EF\
+84D41DC81C2C40F34B5BEE6A93867B3BDBA0052C5F59E6F3657918C382E771D3\
+3109122CC8BB0E1E53C4E3D13B43CE44970F5E0C079D2AD7D7A3549CD75760C2\
+1BB15B447589E86E8D76B1E9CED2:\
+4A1027E1D074DD6E1C480995DC551A857C6A61791DEC5B4B38908DAB68804D35\
+4B7F6055B395C0CDF158EFCDBD8170302439037C0DFF49F087D08DC5FF141FF3
+
+F690A132AB46B28EDFA6479283D6444E371C6459108AFD9C35DBD235E0B6B6FF\
+4C4EA58E7554BD002460433B2164CA51E868F7947D7D7A0D792E4ABF0BE5F450\
+853CC40D85485B2B8857EA31B5EA6E4CCFA2F3A7EF3380066D7D8979FDAC618A\
+AD3D7E886DEA4F005AE4AD05E5065F:\
+C669C31277926472D262E3967578F82E1756EF387B94EA9A778A2D60C1C8CF48\
+ED193D520BFEE4F7E13F820735996232D93960A237AF8D4EEFD70129A1C2AC8B
+
+58D6A99BC6458824B256916770A8417040721CCCFD4B79EACD8B65A3767CE5BA\
+7E74104C985AC56B8CC9AEBD16FEBD4CDA5ADB130B0FF2329CC8D611EB14DAC2\
+68A2F9E633C99DE33997FEA41C52A7C5E1317D5B5DAED35EBA7D5A60E45D1FA7\
+EAABC35F5C2B0A0F2379231953322C4E:\
+6694CB192D378B19E30D2C61CF323F95361008B63BEEAADC2CC1156FC5C3A3EE\
+8DC3D057E74B5AC68A2D6BE30CDDCC3D066F8F753B2F0EBD648B9D11C1B244A5
+
+BEFAB574396D7F8B6705E2D5B58B2C1C820BB24E3F4BAE3E8FBCD36DBF734EE1\
+4E5D6AB972AEDD3540235466E825850EE4C512EA9795ABFD33F330D9FD7F79E6\
+2BBB63A6EA85DE15BEAEEA6F8D204A28956059E2632D11861DFB0E65BC07AC8A\
+159388D5C3277E227286F65FF5E5B5AEC1:\
+293711F929B2D7069A7551737639FEC7F0B84F8859486E3CDFD9C49553C0A719\
+06B87D5344234F098ABB4DE86F463155BD243A71B72D59B82B84230CFC6B38B1
+
+8E58144FA9179D686478622CE450C748260C95D1BA43B8F9B59ABECA8D93488D\
+A73463EF40198B4D16FB0B0707201347E0506FF19D01BEA0F42B8AF9E71A1F1B\
+D168781069D4D338FDEF00BF419FBB003031DF671F4A37979564F69282DE9C65\
+407847DD0DA505AB1641C02DEA4F0D834986:\
+1B13A33069397F84B575283BF01F9B6859C39B19FD0539E979738CDE220BFA32\
+E194047E0EE944E51E4E5F2961AFD359534013D6C01D64E1EFE05CB089BDADA4
+
+B55C10EAE0EC684C16D13463F29291BF26C82E2FA0422A99C71DB4AF14DD9C7F\
+33EDA52FD73D017CC0F2DBE734D831F0D820D06D5F89DACC485739144F8CFD47\
+99223B1AFF9031A105CB6A029BA71E6E5867D85A554991C38DF3C9EF8C1E1E9A\
+7630BE61CAABCA69280C399C1FB7A12D12AEFC:\
+3B9DB555CE766F19E08AA227DF42574A312353510713E5F9DF5F3704A851907A\
+465471F686D24DE3FEFA23C6A010FAD0D2CEE2B970AC8629E69E75325FE72ABA
+
+2EEEA693F585F4ED6F6F8865BBAE47A6908AECD7C429E4BEC4F0DE1D0CA0183F\
+A201A0CB14A529B7D7AC0E6FF6607A3243EE9FB11BCF3E2304FE75FFCDDD6C5C\
+2E2A4CD45F63C962D010645058D36571404A6D2B4F44755434D76998E83409C3\
+205AA1615DB44057DB991231D2CB42624574F545:\
+5B16C423C1AD8FAAC4539E02E2F728B7AD951AB608D2FA607ADEAAA0E2A8C2E4\
+33DE19048F9122D4A5819D62EC76581C1E12DD619AD7CF48E93980A9B87CBA39
+
+DAB11DC0B047DB0420A585F56C42D93175562852428499F66A0DB811FCDDDAB2\
+F7CDFFED1543E5FB72110B64686BC7B6887A538AD44C050F1E42631BC4EC8A9F\
+2A047163D822A38989EE4AAB01B4C1F161B062D873B1CFA388FD301514F62224\
+157B9BEF423C7783B7AAC8D30D65CD1BBA8D689C2D:\
+FA2C6CE535A66502E36B2D0B6861ECAB0F2018A730175D2A150A614E04AA11D2\
+48F327F8CF1C16C5B33F53879394BD243E2F2E56C96556958C51BB036F3CFA3C
+
+42E99A2F80AEE0E001279A2434F731E01D34A44B1A8101726921C0590C30F312\
+0EB83059F325E894A5AC959DCA71CE2214799916424E859D27D789437B9D2724\
+0BF8C35ADBAFCECC322B48AA205B293962D858652ABACBD588BCF6CBC388D099\
+3BD622F96ED54614C25B6A9AA527589EAAFFCF17DDF7:\
+41761A253EA4A37EBB9D68B022F30ABBEF1B0038B043D72092ECC2A51F810282\
+DA06143156EBC3A632F5E0D8561CB4B1C9EBF5F89AADC6B7B62FDC33A6955B44
+
+3C9B46450C0F2CAE8E3823F8BDB4277F31B744CE2EB17054BDDC6DFF36AF7F49\
+FB8A2320CC3BDF8E0A2EA29AD3A55DE1165D219ADEDDB5175253E2D1489E9B6F\
+DD02E2C3D3A4B54D60E3A47334C37913C5695378A669E9B72DEC32AF5434F93F\
+46176EBF044C4784467C700470D0C0B40C8A088C815816:\
+DE0665A8B41255B24D6FB3C32A64884CAA7D185D8AC72A829A3903B8D6D6CE7D\
+2C572C2DF4AA108557874E730A524B100D57B4A6C6E7DB27B00B3B602603037F
+
+D1E654B77CB155F5C77971A64DF9E5D34C26A3CAD6C7F6B300D39DEB19100946\
+91ADAA095BE4BA5D86690A976428635D5526F3E946F7DC3BD4DBC78999E65344\
+1187A81F9ADCD5A3C5F254BC8256B0158F54673DCC1232F6E918EBFC6C51CE67\
+EAEB042D9F57EEC4BFE910E169AF78B3DE48D137DF4F2840:\
+A8200C1AA6009807FD50B0B4B9704F2B5B7E14983A0A40DB431EAFDF2DAC012A\
+E7695E85DD11E50A028C4EF1C3B4DDF5BAED8336FDD5C0D1380E3B5EF28A27A2
+
+626F68C18A69A6590159A9C46BE03D5965698F2DAC3DE779B878B3D9C421E0F2\
+1B955A16C715C1EC1E22CE3EB645B8B4F263F60660EA3028981EEBD6C8C3A367\
+285B691C8EE56944A7CD1217997E1D9C21620B536BDBD5DE8925FF71DEC6FBC0\
+6624AB6B21E329813DE90D1E572DFB89A18120C3F606355D25:\
+D9A0278086A77DEB208298197FC8D1806235163959EEB26CD36C523F2A77F6E2\
+6FBEA52D4F3637C3792F93E889C4F8640C882C2DCF811B728DB4316CCC1804F2
+
+651A6FB3C4B80C7C68C6011675E6094EB56ABF5FC3057324EBC6477825061F9F\
+27E7A94633ABD1FA598A746E4A577CAF524C52EC1788471F92B8C37F23795CA1\
+9D559D446CAB16CBCDCE90B79FA1026CEE77BF4AB1B503C5B94C2256AD75B3EA\
+C6FD5DCB96ACA4B03A834BFB4E9AF988CECBF2AE597CB9097940:\
+9611A7BA803A72823BBC3B9811D9BCF83C2B434EA1625758F3DE912E3B2CC6B2\
+6AFD733C942E95F6BEB68BB4F81A3AD919A1F4001902ED2D3041B7AEBDFB33C6
+
+8AAF072FCE8A2D96BC10B3C91C809EE93072FB205CA7F10ABD82ECD82CF040B1\
+BC49EA13D1857815C0E99781DE3ADBB5443CE1C897E55188CEAF221AA9681638\
+DE05AE1B322938F46BCE51543B57ECDB4C266272259D1798DE13BE90E10EFEC2\
+D07484D9B21A3870E2AA9E06C21AA2D0C9CF420080A80A91DEE16F:\
+E220AA5855680EB8B4B35E61173B48B8A5B1D77C181439EFDB3BF642757256DC\
+A2B132EEE6D6F15652912C1F12EB875BAA25FE690787A35DD06444E661763999
+
+53F918FD00B1701BD504F8CDEA803ACCA21AC18C564AB90C2A17DA592C7D6968\
+8F6580575395551E8CD33E0FEF08CA6ED4588D4D140B3E44C032355DF1C53156\
+4D7F4835753344345A6781E11CD5E095B73DF5F82C8AE3AD00877936896671E9\
+47CC52E2B29DCD463D90A0C9929128DA222B5A211450BBC0E02448E2:\
+E0027961679B6CD1CF4B496DEF4466EC6692B435D2AB3DF739A6D82E0C5B71B0\
+E666714E1EE58B78AEF5986FC63BACE53C658517306628E059B310A718605BDA
+
+A64599B8A61B5CCEC9E67AED69447459C8DA3D1EC6C7C7C82A7428B9B584FA67\
+E90F68E2C00FBBED4613666E5168DA4A16F395F7A3C3832B3B134BFC9CBAA95D\
+2A0FE252F44AC6681EB6D40AB91C1D0282FED6701C57463D3C5F2BB8C6A7301F\
+B4576AA3B5F15510DB8956FF77478C26A7C09BEA7B398CFC83503F538E:\
+BA3291627ADBCF8D6447E46FE2DC88544D38304353DEF25C4C1DE27D3B3CD90E\
+1B8629334DD1CC155D576925DDEC7F89C933BBFB761FC029221BD163D731052C
+
+0E3AB0E054739B00CDB6A87BD12CAE024B54CB5E550E6C425360C2E87E59401F\
+5EC24EF0314855F0F56C47695D56A7FB1417693AF2A1ED5291F2FEE95F75EED5\
+4A1B1C2E81226FBFF6F63ADE584911C71967A8EB70933BC3F5D15BC91B5C2644\
+D9516D3C3A8C154EE48E118BD1442C043C7A0DBA5AC5B1D5360AAE5B9065:\
+D49A8BC7CDF5194F5B1278F765091616F54ED1F7144F72CBAB23A4FE0F89DEBF\
+9CCD47C38349A0F35681628E70C401BD859CBB3048A4089B8153A124629521C3
+
+A62FC595B4096E6336E53FCDFC8D1CC175D71DAC9D750A6133D23199EAAC2882\
+07944CEA6B16D27631915B4619F743DA2E30A0C00BBDB1BBB35AB852EF3B9AEC\
+6B0A8DCC6E9E1ABAA3AD62AC0A6C5DE765DE2C3711B769E3FDE44A74016FFF82\
+AC46FA8F1797D3B2A726B696E3DEA5530439ACEE3A45C2A51BC32DD055650B:\
+FF9FBA36F65BB0F4E5A201E7F5FD9E32B68A7E7ECFF5874B4CC8239C8F7AFE5F\
+E8A548C77E120E2417704DA858791207BE072958ABB80A1818A9D2A9E48DAC71
+
+2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\
+29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\
+E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\
+98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\
+492DB0C6B669BE4D9EC22A45F4C9D8F706FF580B90A6D5C8B83A22B2CEB6D919\
+35B549F3E5D4CE0010B57ACB0A6F99FF2DBBF51305ED934904C5F3A1AC7DBBC7
+
+10DB509B2CDCABA6C062AE33BE48116A29EB18E390E1BBADA5CA0A2718AFBCD2\
+3431440106594893043CC7F2625281BF7DE2655880966A23705F0C5155C2F5CC\
+A9F2C2142E96D0A2E763B70686CD421B5DB812DACED0C6D65035FDE558E94F26\
+B3E6DDE5BD13980CC80292B723013BD033284584BFF27657871B0CF07A849F4A\
+E2:\
+8F49E749AB90B158C061B32E8BC4E375EE02712A39DD4A414F037001ECCC97BB\
+3D9AA3D05BD5674E40266B0D7D402A0396EBC3D880FD0C6BCDD19FAB1C2D8AB7
+
+9334DE60C997BDA6086101A6314F64E4458F5FF9450C509DF006E8C547983C65\
+1CA97879175AABA0C539E82D05C1E02C480975CBB30118121061B1EBAC4F8D9A\
+3781E2DB6B18042E01ECF9017A64A0E57447EC7FCBE6A7F82585F7403EE2223D\
+52D37B4BF426428613D6B4257980972A0ACAB508A7620C1CB28EB4E9D30FC413\
+61EC:\
+036F6083AC46A67292E7685C835AA334FC1E58013A11EC8DD8A02D79512C265B\
+1009846F46F292C26767BED00372719541BFBDC8056CF5010EE2A61A87826131
+
+E88AB086891693AA535CEB20E64C7AB97C7DD3548F3786339897A5F0C3903154\
+9CA870166E477743CCFBE016B4428D89738E426F5FFE81626137F17AECFF61B7\
+2DBEE2DC20961880CFE281DFAB5EE38B1921881450E16032DE5E4D55AD8D4FCA\
+609721B0692BAC79BE5A06E177FE8C80C0C83519FB3347DE9F43D5561CB8107B\
+9B5EDC:\
+9F84EFA2D01B7CE2DC1879B54D9CA330438933219EB0AB63EAE03EC40D44F9D0\
+9468ACC223DC9F67537B4A4177529A65491C682F21CC316F24B64DD05930595A
+
+FD19E01A83EB6EC810B94582CB8FBFA2FCB992B53684FB748D2264F020D3B960\
+CB1D6B8C348C2B54A9FCEA72330C2AAA9A24ECDB00C436ABC702361A82BB8828\
+B85369B8C72ECE0082FE06557163899C2A0EFA466C33C04343A839417057399A\
+63A3929BE1EE4805D6CE3E5D0D0967FE9004696A5663F4CAC9179006A2CEB755\
+42D75D68:\
+9C7BB21B3A034216AD6BB42A157D4018911671BCAC9165DEA00045FFD9928A7B\
+E25EC695D82EFA328D924C5B18A709A092B1D1FAE9B30ACEF72BAA142A22332A
+
+59AE20B6F7E0B3C7A989AFB28324A40FCA25D8651CF1F46AE383EF6D8441587A\
+A1C04C3E3BF88E8131CE6145CFB8973D961E8432B202FA5AF3E09D625FAAD825\
+BC19DA9B5C6C20D02ABDA2FCC58B5BD3FE507BF201263F30543819510C12BC23\
+E2DDB4F711D087A86EDB1B355313363A2DE996B891025E147036087401CCF3CA\
+7815BF3C49:\
+6DEDF9B477A2081879C289A3105272E431E226D794E52DCFFE50960D1C18FBB5\
+65CD7891233B1FDD26D26D0E7D19284191E0705F6EFB4B93CDE1482FC54B475A
+
+77EE804B9F3295AB2362798B72B0A1B2D3291DCEB8139896355830F34B3B3285\
+61531F8079B79A6E9980705150866402FDC176C05897E359A6CB1A7AB067383E\
+B497182A7E5AEF7038E4C96D133B2782917417E391535B5E1B51F47D8ED7E4D4\
+025FE98DC87B9C1622614BFF3D1029E68E372DE719803857CA52067CDDAAD958\
+951CB2068CC6:\
+6441C583EF5862DA39F1DAE9E5AB301C2E5297A226F54968B98C6121E57C34AF\
+76D5D1B4DEA90D1CA30B7F088C2FBB4044F1E120E59450BC2274E7D16F4FA7CC
+
+B771D5CEF5D1A41A93D15643D7181D2A2EF0A8E84D91812F20ED21F147BEF732\
+BF3A60EF4067C3734B85BC8CD471780F10DC9E8291B58339A677B960218F71E7\
+93F2797AEA349406512829065D37BB55EA796FA4F56FD8896B49B2CD19B43215\
+AD967C712B24E5032D065232E02C127409D2ED4146B9D75D763D52DB98D949D3\
+B0FED6A8052FBB:\
+E252EBC46763D1C46B4B6F5BD7B7A68C0EBA6CB5ACE8E31DE2BC67B60553AB5B\
+CD5AF42E0BCA79EFA038B46D456778E9769E8C3805899FD69EBF6417F3A4DB0A
+
+B32D95B0B9AAD2A8816DE6D06D1F86008505BD8C14124F6E9A163B5A2ADE55F8\
+35D0EC3880EF50700D3B25E42CC0AF050CCD1BE5E555B23087E04D7BF9813622\
+780C7313A1954F8740B6EE2D3F71F768DD417F520482BD3A08D4F222B4EE9DBD\
+015447B33507DD50F3AB4247C5DE9A8ABD62A8DECEA01E3B87C8B927F5B08BEB\
+37674C6F8E380C04:\
+1DC90E1A98EDE43835371AED47CD1BAEF83229FB1FB148160F48AC0B080B5CF9\
+EB76F60C6728988AB4A5FE43D1A67B5A80098808369A0D0AE09FB7C8BD1A6A4D
+
+04410E31082A47584B406F051398A6ABE74E4DA59BB6F85E6B49E8A1F7F2CA00\
+DFBA5462C2CD2BFDE8B64FB21D70C083F11318B56A52D03B81CAC5EEC29EB31B\
+D0078B6156786DA3D6D8C33098C5C47BB67AC64DB14165AF65B44544D806DDE5\
+F487D5373C7F9792C299E9686B7E5821E7C8E2458315B996B5677D926DAC57B3\
+F22DA873C601016A0D:\
+083E6B3D4683464BBD9039BC446E75D751A7DDE74DF0C6FDFBF53524F7E8879A\
+9F0FD7C58979FCD9700DE0B59A71CDF5CB019CA196D497B8CF03C2B596103102
+
+8B81E9BADDE026F14D95C019977024C9E13DB7A5CD21F9E9FC491D716164BBAC\
+DC7060D882615D411438AEA056C340CDF977788F6E17D118DE55026855F93270\
+472D1FD18B9E7E812BAE107E0DFDE7063301B71F6CFE4E225CAB3B232905A56E\
+994F08EE2891BA922D49C3DAFEB75F7C69750CB67D822C96176C46BD8A29F170\
+1373FB09A1A6E3C7158F:\
+AD978D3A72E307F396DEAFAF87EEE2E8E4BDFE12AC5B32954EE2CE61CC562F41\
+5C6DDF4C656F88C3863DC3A8EBCD7B007977BCB1ACB41F8D35F2EAB0F6401C8D
+
+FA6EED24DA6666A22208146B19A532C2EC9BA94F09F1DEF1E7FC13C399A48E41\
+ACC2A589D099276296348F396253B57CB0E40291BD282773656B6E0D8BEA1CDA\
+084A3738816A840485FCF3FB307F777FA5FEAC48695C2AF4769720258C77943F\
+B4556C362D9CBA8BF103AEB9034BAA8EA8BFB9C4F8E6742CE0D52C49EA8E974F\
+339612E830E9E7A9C29065:\
+F2E9D8402E4FE43618FE1570DB0F2D8E004CC15BE3B70534E9BB77B52DAAFCF8\
+6DEF6E28C40AB31745C0F5E6A2678B508065C90EC5AC61EB461A3990EACECAD4
+
+9BB4AF1B4F09C071CE3CAFA92E4EB73CE8A6F5D82A85733440368DEE4EB1CBC7\
+B55AC150773B6FE47DBE036C45582ED67E23F4C74585DAB509DF1B8361056454\
+5642B2B1EC463E18048FC23477C6B2AA035594ECD33791AF6AF4CBC2A1166ABA\
+8D628C57E707F0B0E8707CAF91CD44BDB915E0296E0190D56D33D8DDE10B5B60\
+377838973C1D943C22ED335E:\
+B38D0AEF283D33B490C1A7289AE1B954AB2F649C3194F6C3C55FE34030F91B25\
+1259F3725950C4F0DBF15B6A29881393D3FC7582A0223711ED3ABBAE54C2EC55
+
+2167F02118CC62043E9091A647CADBED95611A521FE0D64E8518F16C808AB297\
+725598AE296880A773607A798F7C3CFCE80D251EBEC6885015F9ABF7EAABAE46\
+798F82CB5926DE5C23F44A3F9F9534B3C6F405B5364C2F8A8BDC5CA49C749BED\
+8CE4BA48897062AE8424CA6DDE5F55C0E42A95D1E292CA54FB46A84FBC9CD87F\
+2D0C9E7448DE3043AE22FDD229:\
+BFFA1584243F431DED719972832AE363D17EFCC27BECE05A46A5E8C68C421EF4\
+524F9C7B5FB3C09686B16295A7F3CC16D2D6802EA7031F2A4587C230794BDBC2
+
+94B7FA0BC1C44E949B1D7617D31B4720CBE7CA57C6FA4F4094D4761567E389EC\
+C64F6968E4064DF70DF836A47D0C713336B5028B35930D29EB7A7F9A5AF9AD5C\
+F441745BAEC9BB014CEEFF5A41BA5C1CE085FEB980BAB9CF79F2158E03EF7E63\
+E29C38D7816A84D4F71E0F548B7FC316085AE38A060FF9B8DEC36F91AD9EBC0A\
+5B6C338CBB8F6659D342A24368CF:\
+4BAE05893FE99B63E6EFA831D6B0ADF6B857A25814C1983AE209C01B45D14070\
+0CC99EB18903FB8849FAC4E32B822D63968446A9DADF42F81EFF3B11BA0F882D
+
+EA40E83CB18B3A242C1ECC6CCD0B7853A439DAB2C569CFC6DC38A19F5C90ACBF\
+76AEF9EA3742FF3B54EF7D36EB7CE4FF1C9AB3BC119CFF6BE93C03E208783335\
+C0AB8137BE5B10CDC66FF3F89A1BDDC6A1EED74F504CBE7290690BB295A872B9\
+E3FE2CEE9E6C67C41DB8EFD7D863CF10F840FE618E7936DA3DCA5CA6DF933F24\
+F6954BA0801A1294CD8D7E66DFAFEC:\
+C64D9689EF653BAF2EACB6417049DC1B9CCD1B47EFCB77DA039C0B31AC91652B\
+022E4A9BA1B2A8F67AEC6BF3B475CF61D1599D481774FB99D6CE4394939DAA89
+
+157D5B7E4507F66D9A267476D33831E7BB768D4D04CC3438DA12F9010263EA5F\
+CAFBDE2579DB2F6B58F911D593D5F79FB05FE3596E3FA80FF2F761D1B0E57080\
+055C118C53E53CDB63055261D7C9B2B39BD90ACC32520CBBDBDA2C4FD8856DBC\
+EE173132A2679198DAF83007A9B5C51511AE49766C792A29520388444EBEFE28\
+256FB33D4260439CBA73A9479EE00C63:\
+89659D854DCFF397CC19CA47656D165CC98541C87C2B208BE0F4137D1F4BACD3\
+2604CA886AAE9907DC383155C381C78659FEBA11F63380D837EE4FF6AA6C6DE8
+
+836B34B515476F613FE447A4E0C3F3B8F20910AC89A3977055C960D2D5D2B72B\
+D8ACC715A9035321B86703A411DDE0466D58A59769672AA60AD587B8481DE4BB\
+A552A1645779789501EC53D540B904821F32B0BD1855B04E4848F9F8CFE9EBD8\
+911BE95781A759D7AD9724A7102DBE576776B7C632BC39B9B5E19057E226552A\
+5994C1DBB3B5C7871A11F5537011044C53:\
+53763EA36E27ABF066F6CB232DE00DB5483EE2A0B08CDB3AA8BCB164186DB4B9\
+43598484BD1B5D4F616774B63A0F318B781F9AF9EFFE9CA3AF824C07D611B492
+
+CC7784A4912A7AB5AD3620AAB29BA87077CD3CB83636ADC9F3DC94F51EDF521B\
+2161EF108F21A0A298557981C0E53CE6CED45BDF782C1EF200D29BAB81DD6460\
+586964EDAB7CEBDBBEC75FD7925060F7DA2B853B2B089588FA0F8C16EC6498B1\
+4C55DCEE335CB3A91D698E4D393AB8E8EAC0825F8ADEBEEE196DF41205C01167\
+4E53426CAA453F8DE1CBB57932B0B741D4C6:\
+F378B13998EED4FF3D9F064C80BF99DA7663DACAFE504F757D5281B30225FF27\
+5C43ABE91897F152FF5B90048485532926D446684BC0BB744C0F825BAC4519EC
+
+7639B461FFF270B2455AC1D1AFCE782944AEA5E9087EB4A39EB96BB5C3BAAF0E\
+868C8526D3404F9405E79E77BFAC5FFB89BF1957B523E17D341D7323C302EA70\
+83872DD5E8705694ACDDA36D5A1B895AAA16ECA6104C82688532C8BFE1790B5D\
+C9F4EC5FE95BAED37E1D287BE710431F1E5E8EE105BC42ED37D74B1E55984BF1\
+C09FE6A1FA13EF3B96FAEAED6A2A1950A12153:\
+6000F31F370B82E83ED8D5ACAEFC074F627C065E97494E3AA591507FD31EBD86\
+E52C9CA0F565E868CDC84A2A62CA03AF7893D5F4ACF0817E506FFF9CFF095006
+
+EB6513FC61B30CFBA58D4D7E80F94D14589090CF1D80B1DF2E68088DC6104959\
+BA0D583D585E9578AB0AEC0CF36C48435EB52ED9AB4BBCE7A5ABE679C97AE2DB\
+E35E8CC1D45B06DDA3CF418665C57CBEE4BBB47FA4CAF78F4EE656FEC237FE4E\
+EBBAFA206E1EF2BD0EE4AE71BD0E9B2F54F91DAADF1FEBFD7032381D636B733D\
+CB3BF76FB14E23AFF1F68ED3DBCF75C9B99C6F26:\
+BBD4EBE27C353D6B9680D4C6AAAAA912573445200C601FD67EBF96117A1CF543\
+D6BBA6C8EEF734AE34429BF555DD79B691027900931652B0B9DF0F9E9FD9C050
+
+1594D74BF5DDE444265D4C04DAD9721FF3E34CBF622DAF341FE16B96431F6C4D\
+F1F760D34F296EB97D98D560AD5286FEC4DCE1724F20B54FD7DF51D4BF137ADD\
+656C80546FB1BF516D62EE82BAA992910EF4CC18B70F3F8698276FCFB44E0EC5\
+46C2C39CFD8EE91034FF9303058B4252462F86C823EB15BF481E6B79CC3A0221\
+8595B3658E8B37382BD5048EAED5FD02C37944E73B:\
+A6D3D6AE760CAFA9C97215D412B294947AEF38D0E3F174F41D99C87AF9EA8A72\
+B799CED0489006EB3078147E36FFF8A4429DA581214D70D38567776DEB4EBEF6
+
+4CFA1278903026F66FEDD41374558BE1B585D03C5C55DAC94361DF286D4BD39C\
+7CB8037ED3B267B07C346626449D0CC5B0DD2CF221F7E4C3449A4BE99985D2D5\
+E67BFF2923357DDEAB5ABCB4619F3A3A57B2CF928A022EB27676C6CF80568900\
+4FCA4D41EA6C2D0A4789C7605F7BB838DD883B3AD3E6027E775BCF2628814280\
+99C7FFF95B14C095EA130E0B9938A5E22FC52650F591:\
+9AA3ACA7AB03CFA7E59403169343C34A0D3E8B256DE91C5BD62FB465E2D1CAD1\
+E1AC5949CDED1F86B76B64DC23BC4C5195EDB42AF04ECA3E22B8C11A9304DC92
+
+D3E65CB92CFA79662F6AF493D696A07CCF32AAADCCEFF06E73E8D9F6F909209E\
+66715D6E978788C49EFB9087B170ECF3AA86D2D4D1A065AE0EFC8924F365D676\
+B3CB9E2BEC918FD96D0B43DEE83727C9A93BF56CA2B2E59ADBA85696546A8150\
+67FC7A78039629D4948D157E7B0D826D1BF8E81237BAB7321312FDAA4D521744\
+F988DB6FDF04549D0FDCA393D639C729AF716E9C8BBA48:\
+981C7896E9930313752E5BA36A1871598034987482B30403C763D7B458E73B1C\
+0D2F9007ACE336A4659877D5C746A18A3B67876385335DBB31FD3987CC701169
+
+842CC583504539622D7F71E7E31863A2B885C56A0BA62DB4C2A3F2FD12E79660\
+DC7205CA29A0DC0A87DB4DC62EE47A41DB36B9DDB3293B9AC4BAAE7DF5C6E720\
+1E17F717AB56E12CAD476BE49608AD2D50309E7D48D2D8DE4FA58AC3CFEAFEEE\
+48C0A9EEC88498E3EFC51F54D300D828DDDCCB9D0B06DD021A29CF5CB5B25069\
+15BEB8A11998B8B886E0F9B7A80E97D91A7D01270F9A7717:\
+A95F37C2E906C7CC23FE7C9834A6660DA363827C512919FE19B79676782051E6\
+F8009C34E3C70B7B51E365096B895C6BCEFD1B3F9A42BCF35DC458FFE9430CFB
+
+6C4B0A0719573E57248661E98FEBE326571F9A1CA813D3638531AE28B4860F23\
+C3A3A8AC1C250034A660E2D71E16D3ACC4BF9CE215C6F15B1C0FC7E77D3D2715\
+7E66DA9CEEC9258F8F2BF9E02B4AC93793DD6E29E307EDE3695A0DF63CBDC0FC\
+66FB770813EB149CA2A916911BEE4902C47C7802E69E405FE3C04CEB5522792A\
+5503FA829F707272226621F7C488A7698C0D69AA561BE9F378:\
+4D5C55BFD9A5B840AF2D0E087E27503E2955B8DB30CCFBFF36A51BF529013AB0\
+A6F7F9D3A19C8B735F5E756ED7D24CA36FF46B75D746099546274BDA493771F4
+
+51B7DBB7CE2FFEB427A91CCFE5218FD40F9E0B7E24756D4C47CD55606008BDC2\
+7D16400933906FD9F30EFFDD4880022D081155342AF3FB6CD53672AB7FB5B3A3\
+BCBE47BE1FD3A2278CAE8A5FD61C1433F7D350675DD21803746CADCA574130F0\
+1200024C6340AB0CC2CF74F2234669F34E9009EF2EB94823D62B31407F4BA46F\
+1A1EEC41641E84D77727B59E746B8A671BEF936F05BE820759FA:\
+95EF299ED55C75630EDB3BA526A0172D80DC9A0D98389D3E8FF1D8A317C2CBFE\
+F509C2D2736B81F4E4324F7BA036548E94344723DFCBC368808370040B93FF72
+
+83599D93F5561E821BD01A472386BC2FF4EFBD4AED60D5821E84AAE74D807102\
+9810F5E286F8F17651CD27DA07B1EB4382F754CD1C95268783AD09220F550284\
+0370D494BEB17124220F6AFCE91EC8A0F55231F9652433E5CE3489B727716CF4\
+AEBA7DCDA20CD29AA9A859201253F948DD94395ABA9E3852BD1D60DDA7AE5DC0\
+45B283DA006E1CBAD83CC13292A315DB5553305C628DD091146597:\
+8C30FC0EDD2C4AD0CD674A9421BDB0ACD23941B0672ACDAD34348F126BF8457C\
+49C00AED645831B4766B039B42AED42D7E2C5523D0C2CCCD4FE2A99267751246
+
+2BE9BF526C9D5A75D565DD11EF63B979D068659C7F026C08BEA4AF161D85A462\
+D80E45040E91F4165C074C43AC661380311A8CBED59CC8E4C4518E80CD2C78AB\
+1CABF66BFF83EAB3A80148550307310950D034A6286C93A1ECE8929E6385C5E3\
+BB6EA8A7C0FB6D6332E320E71CC4EB462A2A62E2BFE08F0CCAD93E61BEDB5DD0\
+B786A728AB666F07E0576D189C92BF9FB20DCA49AC2D3956D47385E2:\
+0572CD419E48997F008008F29EAA066C92245A319A8CD5F3F1E17B6A9ECC8AF8\
+F6AD0BCCA8B5E36BFE250F162CBC43FE87C4F76F1EC395581E892FC370FC2640
+
+CA76D3A12595A817682617006848675547D3E8F50C2210F9AF906C0E7CE50B44\
+60186FE70457A9E879E79FD4D1A688C70A347361C847BA0DD6AA52936EAF8E58\
+A1BE2F5C1C704E20146D366AEB3853BED9DE9BEFE9569AC8AAEA37A9FB7139A1\
+A1A7D5C748605A8DEFB297869EBEDD71D615A5DA23496D11E11ABBB126B206FA\
+0A7797EE7DE117986012D0362DCEF775C2FE145ADA6BDA1CCB326BF644:\
+E16A1FF187CE047B79A9D33CCB40E2A665857430C985A074B22DF228716337D7\
+C02CF1E800BB28A927F58532EA989D2B0A08143A26B016237FBE0E7A4EBD4066
+
+F76B85DC67421025D64E93096D1D712B7BAF7FB001716F02D33B2160C2C882C3\
+10EF13A576B1C2D30EF8F78EF8D2F465007109AAD93F74CB9E7D7BEF7C9590E8\
+AF3B267C89C15DB238138C45833C98CC4A471A7802723EF4C744A853CF80A0C2\
+568DD4ED58A2C9644806F42104CEE53628E5BDF7B63B0B338E931E31B87C24B1\
+46C6D040605567CEEF5960DF9E022CB469D4C787F4CBA3C544A1AC91F95F:\
+1E7A250410C53BE0F9E7BD12CBDBA9157330018BAFAD317510A8C08D8BA74037\
+C96B2DCC3C2835517314541C1CC33F7A4A98C657789754C1E5CEE24D8AB79B7B
+
+25B8C9C032EA6BCD733FFC8718FBB2A503A4EA8F71DEA1176189F694304F0FF6\
+8E862A8197B839957549EF243A5279FC2646BD4C009B6D1EDEBF24738197ABB4\
+C992F6B1DC9BA891F570879ACCD5A6B18691A93C7D0A8D38F95B639C1DAEB48C\
+4C2F15CCF5B9D508F8333C32DE78781B41850F261B855C4BEBCC125A380C54D5\
+01C5D3BD07E6B52102116088E53D76583B0161E2A58D0778F091206AABD5A1:\
+042B7FC81C0A1A2635648D60C90B80144DCD51BF83497F45696DF6091EF1C70B\
+54E8798AE309304AE088256F6DE815B0F758BAAB24F4787BDD9DEC35027582FD
+
+21CFDC2A7CCB7F331B3D2EEFFF37E48AD9FA9C788C3F3C200E0173D99963E1CB\
+CA93623B264E920394AE48BB4C3A5BB96FFBC8F0E53F30E22956ADABC2765F57\
+FB761E147ECBF8567533DB6E50C8A1F894310A94EDF806DD8CA6A0E141C0FA7C\
+9FAE6C6AE65F18C93A8529E6E5B553BF55F25BE2E80A9882BD37F145FECBEB3D\
+447A3C4E46C21524CC55CDD62F521AB92A8BA72B897996C49BB273198B7B1C9E:\
+F1531F74713213E6A5E29ACF8AEDBDC08FE56D3AEEF76E53CC63C553D8EDDACC\
+0757096590F9AA8C059671AEE73BA2CFC5B9C8BE731AAC103A200227AF4E6BD7
+
+4E452BA42127DCC956EF4F8F35DD68CB225FB73B5BC7E1EC5A898BBA2931563E\
+74FAFF3B67314F241EC49F4A7061E3BD0213AE826BAB380F1F14FAAB8B0EFDDD\
+5FD1BB49373853A08F30553D5A55CCBBB8153DE4704F29CA2BDEEF0419468E05\
+DD51557CCC80C0A96190BBCC4D77ECFF21C66BDF486459D427F986410F883A80\
+A5BCC32C20F0478BB9A97A126FC5F95451E40F292A4614930D054C851ACD019C\
+CF:\
+690A922814B1F0C905C0BE2B1F1B84176C86E11F9508F94D32324F633ABC0D51\
+DFB9866EEC06AB1545088BF46F17CF9EADA5AAD3D46016363E1567AB33F14AAD
+
+FA85671DF7DADF99A6FFEE97A3AB9991671F5629195049880497487867A6C446\
+B60087FAC9A0F2FCC8E3B24E97E42345B93B5F7D3691829D3F8CCD4BB36411B8\
+5FC2328EB0C51CB3151F70860AD3246CE0623A8DC8B3C49F958F8690F8E3860E\
+71EB2B1479A5CEA0B3F8BEFD87ACAF5362435EAECCB52F38617BC6C5C2C6E269\
+EAD1FBD69E941D4AD2012DA2C5B21BCFBF98E4A77AB2AF1F3FDA3233F046D38F\
+1DC8:\
+44CE8A1D5CFCBDC5573F562D96116137254313F0D12692006F3EE319FE2FC36F\
+3FA9EBCCF630C88AF2A2283B60124F82CDF0E0F51577B3E3E11FD4B93CD556FF
+
+E90847AE6797FBC0B6B36D6E588C0A743D725788CA50B6D792352EA8294F5BA6\
+54A15366B8E1B288D84F5178240827975A763BC45C7B0430E8A559DF4488505E\
+009C63DA994F1403F407958203CEBB6E37D89C94A5EACF6039A327F6C4DBBC7A\
+2A307D976AA39E41AF6537243FC218DFA6AB4DD817B6A397DF5CA69107A91987\
+99ED248641B63B42CB4C29BFDD7975AC96EDFC274AC562D0474C60347A078CE4\
+C25E88:\
+C36AA59A5F385CF0093337872E819EE1D21AA653781D3C433969C416FC6435D8\
+D5827B9DC2FD2EFC5298A23D4771E1E7FE368A6860DE3DB8BFF5E96C902DCACD
+
+F6D5C2B6C93954FC627602C00C4CA9A7D3ED12B27173F0B2C9B0E4A5939398A6\
+65E67E69D0B12FB7E4CEB253E8083D1CEB724AC07F009F094E42F2D6F2129489\
+E846EAFF0700A8D4453EF453A3EDDC18F408C77A83275617FABC4EA3A2833AA7\
+3406C0E966276079D38E8E38539A70E194CC5513AAA457C699383FD1900B1E72\
+BDFB835D1FD321B37BA80549B078A49EA08152869A918CA57F5B54ED71E4FD3A\
+C5C06729:\
+76EE20581200E8C2744BEEE0868F6AB4E4700F14B7E6BC119CA15ABF5B7D7650\
+42D745A1DB59411E199491F412B7D2DE4E6602C0C517AD46A11599EB1B41FE04
+
+CF8562B1BED89892D67DDAAF3DEEB28246456E972326DBCDB5CF3FB289ACA01E\
+68DA5D59896E3A6165358B071B304D6AB3D018944BE5049D5E0E2BB819ACF67A\
+6006111089E6767132D72DD85BEDDCBB2D64496DB0CC92955AB4C6234F1EEA24\
+F2D51483F2E209E4589BF9519FAC51B4D061E801125E605F8093BB6997BC163D\
+551596FE4AB7CFAE8FB9A90F6980480CE0C229FD1675409BD788354DAF316240\
+CFE0AF93EB:\
+D1D3D9705FA1E6F850730F7CAA2109041DBFB5B2D9A07D8ADDBE79DD7643C528\
+233E1A7BD43A5B5A249CFBDFC75C77B93E535A51CA1670B2E6676F9D978A0F80
+
+2ACE31ABB0A2E3267944D2F75E1559985DB7354C6E605F18DC8470423FCA30B7\
+331D9B33C4A4326783D1CAAE1B4F07060EFF978E4746BF0C7E30CD61040BD5EC\
+2746B29863EB7F103EBDA614C4291A805B6A4C8214230564A0557BC7102E0BD3\
+ED23719252F7435D64D210EE2AAFC585BE903FA41E1968C50FD5D5367926DF7A\
+05E3A42CF07E656FF92DE73B036CF8B19898C0CB34557C0C12C2D8B84E91181A\
+F467BC75A9D1:\
+41FA9C9DDCBA93F6CFF44DC85D251384686F42313BAFB1581FD44AA3F471E12E\
+88626410A1BBD7D6C029C8836292443BC776B47611BF440BAF31AEE416088E70
+
+0D8D09AED19F1013969CE5E7EB92F83A209AE76BE31C754844EA9116CEB39A22\
+EBB6003017BBCF26555FA6624185187DB8F0CB3564B8B1C06BF685D47F3286ED\
+A20B83358F599D2044BBF0583FAB8D78F854FE0A596183230C5EF8E54426750E\
+AF2CC4E29D3BDD037E734D863C2BD9789B4C243096138F7672C232314EFFDFC6\
+513427E2DA76916B5248933BE312EB5DDE4CF70804FB258AC5FB82D58D08177A\
+C6F4756017FFF5:\
+4B301E55D2186F1AE749FEACC15BF7957DADEF69E0C6B22BD1EB07B8CA5F37B7\
+26B642E6FE2D5C87427742712FF842DC3D1D68EEBBA1E7E6A27DB195ED526258
+
+C3236B73DEB7662BF3F3DAA58F137B358BA610560EF7455785A9BEFDB035A066\
+E90704F929BD9689CEF0CE3BDA5ACF4480BCEB8D09D10B098AD8500D9B6071DF\
+C3A14AF6C77511D81E3AA8844986C3BEA6F469F9E02194C92868CD5F51646256\
+798FF0424954C1434BDFED9FACB390B07D342E992936E0F88BFD0E884A0DDB67\
+9D0547CCDEC6384285A45429D115AC7D235A717242021D1DC35641F5F0A48E84\
+45DBA58E6CB2C8EA:\
+21B32E64D26CC9F9F589E74850A08203B70D3E5CB7E0CFD01FCCFA95F9DD05F7\
+7B1299DC92387860A6E3EA676E0859F0B11E6FA029D4F3BBFEF472D6F096FF94
+
+B39FEB8283EADC63E8184B51DF5AE3FD41AAC8A963BB0BE1CD08AA5867D8D910\
+C669221E73243360646F6553D1CA05A84E8DC0DE05B6419EC349CA994480193D\
+01C92525F3FB3DCEFB08AFC6D26947BDBBFD85193F53B50609C6140905C53A66\
+86B58E53A319A57B962331EDE98149AF3DE3118A819DA4D76706A0424B4E1D29\
+10B0ED26AF61D150EBCB46595D4266A0BD7F651BA47D0C7F179CA28545007D92\
+E8419D48FDFBD744CE:\
+62ABB23B1C72C7E00F65007D0CBE5D96B93CB318E1495326D366AEAA618B2FFE\
+42AD7CE18D5A65FF877ADB42A35CE6227FB8F5748E653482824426AFA92DB6B2
+
+A983D54F503803E8C7999F4EDBBE82E9084F422143A932DDDDC47A17B0B7564A\
+7F37A99D0786E99476428D29E29D3C197A72BFAB1342C12A0FC4787FD7017D7A\
+6174049EA43B5779169EF7472BDBBD941DCB82FC73AAC45A8A94C9F2BD3477F6\
+1FD3B796F02A1B8264A214C6FEA74B7051B226C722099EC7883A462B83B6AFDD\
+4009248B8A237F605FE5A08FE7D8B45321421EBBA67BD70A0B00DDBF94BAAB7F\
+359D5D1EEA105F28DCFB:\
+2FED42B65B3F785E89C25AE005DE353BF6819459E071292CE81E1458D4FB1B80\
+A805FB568889D8A05EF68740F472E05D7001A6FCC28B28C339D1F790848F49DA
+
+E4D1C1897A0A866CE564635B74222F9696BF2C7F640DD78D7E2ACA66E1B61C64\
+2BB03EA7536AAE597811E9BF4A7B453EDE31F97B46A5F0EF51A071A2B3918DF1\
+6B152519AE3776F9F1EDAB4C2A377C3292E96408359D3613844D5EB393000283\
+D5AD3401A318B12FD1474B8612F2BB50FB6A8B9E023A54D7DDE28C43D6D8854C\
+8D9D1155935C199811DBFC87E9E0072E90EB88681CC7529714F8FB8A2C9D8856\
+7ADFB974EE205A9BF7B848:\
+BE28BE9E3B17384A3724CD601E32AD86A8E7FFE97E655A17148EE9F7BB49BAC6\
+9D248CECC5AA18FBFABF2A9005B862E8935F310A7C0DB04F9286F83AFE3C5B43
+
+B10C59723E3DCADD6D75DF87D0A1580E73133A9B7D00CB95EC19F5547027323B\
+E75158B11F80B6E142C6A78531886D9047B08E551E75E6261E79785366D7024B\
+D7CD9CF322D9BE7D57FB661069F2481C7BB759CD71B4B36CA2BC2DF6D3A328FA\
+EBDB995A9794A8D72155ED551A1F87C80BF6059B43FC764900B18A1C2441F748\
+7743CF84E565F61F8DD2ECE6B6CCC9444049197AAAF53E926FBEE3BFCA8BE588\
+EC77F29D211BE89DE18B15F6:\
+001F8A09BC7D7321E3E6191D10DB354606FE1F80E06EA598E164C9ED5A9BA8D8\
+B3E3CB0D4E243DDBA700BC9D0F1B2B1F0AD5635B63DCEF6741336ECB19C87C2E
+
+DB11F609BABA7B0CA634926B1DD539C8CBADA24967D7ADD4D9876F77C2D80C0F\
+4DCEFBD7121548373582705CCA2495BD2A43716FE64ED26D059CFB566B3364BD\
+49EE0717BDD9810DD14D8FAD80DBBDC4CAFB37CC60FB0FE2A80FB4541B8CA9D5\
+9DCE457738A9D3D8F641AF8C3FD6DA162DC16FC01AAC527A4A0255B4D231C0BE\
+50F44F0DB0B713AF03D968FE7F0F61ED0824C55C4B5265548FEBD6AAD5C5EEDF\
+63EFE793489C39B8FD29D104CE:\
+E635747BEDC669D071D16D70DAD0C66B82A87BAB3891992BD891ED0D0B6C2809\
+919E507571D35A35D80F772FE11E61E94675BC5138138AB24722BF1D56BC7449
+
+BEBD4F1A84FC8B15E4452A54BD02D69E304B7F32616AADD90537937106AE4E28\
+DE9D8AAB02D19BC3E2FDE1D651559E296453E4DBA94370A14DBBB2D1D4E20223\
+02EE90E208321EFCD8528AD89E46DC839EA9DF618EA8394A6BFF308E7726BAE0\
+C19BCD4BE52DA6258E2EF4E96AA21244429F49EF5CB486D7FF35CAC1BACB7E95\
+711944BCCB2AB34700D42D1EB38B5D536B947348A458EDE3DC6BD6EC547B1B0C\
+AE5B257BE36A7124E1060C170FFA:\
+25EDD7E6E3496256343928AD4F59A00AD38866AF358E120D1B53F7B3A975AD3D\
+0F9C960AB8D17E7D29B331EB3C37AC779D36352F33B238F1992626FF5B134E10
+
+5ACA56A03A13784BDC3289D9364F79E2A85C12276B49B92DB0ADAA4F206D5028\
+F213F678C3510E111F9DC4C1C1F8B6ACB17A6413AA227607C515C62A733817BA\
+5E762CC6748E7E0D6872C984D723C9BB3B117EB8963185300A80BFA65CDE495D\
+70A46C44858605FCCBED086C2B45CEF963D33294DBE9706B13AF22F1B7C4CD5A\
+001CFEC251FBA18E722C6E1C4B1166918B4F6F48A98B64B3C07FC86A6B17A6D0\
+480AB79D4E6415B520F1C484D675B1:\
+CBEC8E314138BECE0FD4A4A266AE09D5776FF0C19E3CEB2AB287E7DAB909A8F8\
+82718CF90489E8772D151E50DFAAB87D7FABD5873D060FCC3936A84D253857FB
+
+A5AAD0E4646A32C85CFCAC73F02FC5300F1982FABB2F2179E28303E447854094\
+CDFC854310E5C0F60993CEFF54D84D6B46323D930ADB07C17599B35B505F09E7\
+84BCA5985E0172257797FB53649E2E9723EFD16865C31B5C3D5113B58BB0BFC8\
+920FABDDA086D7537E66D709D050BD14D0C960873F156FAD5B3D3840CDFCDC9B\
+E6AF519DB262A27F40896AB25CC39F96984D650611C0D5A3080D5B3A1BF186AB\
+D42956588B3B58CD948970D298776060:\
+BC11B07AC39497094FDEEEE0AB6A1AF7AA3A2E9E496EE7607D64058A0896430C\
+74FB967EC7F742D788E2F448B588D61F4DE56FF2EA392AA3EE516302DBAE9E52
+
+06CBBE67E94A978203EAD6C057A1A5B098478B4B4CBEF5A97E93C8E42F557271\
+3575FC2A884531D7622F8F879387A859A80F10EF02708CD8F7413AB385AFC357\
+678B9578C0EBF641EF076A1A30F1F75379E9DCB2A885BDD295905EE80C0168A6\
+2A9597D10CF12DD2D8CEE46645C7E5A141F6E0E23AA482ABE5661C16E69EF1E2\
+8371E2E236C359BA4E92C25626A7B7FF13F6EA4AE906E1CFE163E91719B1F750\
+A96CBDE5FBC953D9E576CD216AFC90323A:\
+9306E8982942FE6310626C66863546D3CB1354D568A4477B8C226023F5B10330\
+2B2D2B04540EDD45381E3262593E7FFED53850053ED782FAD7A8684660417122
+
+F1C528CF7739874707D4D8AD5B98F7C77169DE0B57188DF233B2DC8A5B31EDA5\
+DB4291DD9F68E6BAD37B8D7F6C9C0044B3BF74BBC3D7D1798E138709B0D75E7C\
+593D3CCCDC1B20C7174B4E692ADD820ACE262D45CCFAE2077E87879634716806\
+0A162ECCA8C38C1A88350BD63BB539134F700FD4ADDD5959E255337DAA06BC86\
+358FABCBEFDFB5BC889783D843C08AADC6C4F6C36F65F156E851C9A0F917E4A3\
+67B5AD93D874812A1DE6A7B93CD53AD97232:\
+D0344AFA80AC97DA86D1AF70D61808273399EA7E970099A83D1B05572C0D257F\
+8E72F99313F52EF801113E37D60036E6333F1A8563D7360A56AE007090B3E256
+
+9D9F3A7ECD51B41F6572FD0D0881E30390DFB780991DAE7DB3B47619134718E6\
+F987810E542619DFAA7B505C76B7350C6432D8BF1CFEBDF1069B90A35F0D04CB\
+DF130B0DFC7875F4A4E62CDB8E525AADD7CE842520A482AC18F09442D78305FE\
+85A74E39E760A4837482ED2F437DD13B2EC1042AFCF9DECDC3E877E50FF4106A\
+D10A525230D11920324A81094DA31DEAB6476AA42F20C84843CFC1C58545EE80\
+352BDD3740DD6A16792AE2D86F11641BB717C2:\
+97976B7A6D374CEDA51D3D63353AA7362E2CEC852BA67FD7F00E08F5A82FE062\
+31A93F860ECFC42566983C8160609A7B77A2AF1BBDCA447219CC392866BC102F
+
+5179888724819FBAD3AFA927D3577796660E6A81C52D98E9303261D5A4A83232\
+F6F758934D50AA83FF9E20A5926DFEBAAC49529D006EB923C5AE5048ED544EC4\
+71ED7191EDF46363383824F915769B3E688094C682B02151E5EE01E510B431C8\
+865AFF8B6B6F2F59CB6D129DA79E97C6D2B8FA6C6DA3F603199D2D1BCAB54768\
+2A81CD6CF65F6551121391D78BCC23B5BD0E922EC6D8BF97C952E84DD28AEF90\
+9ABA31EDB903B28FBFC33B7703CD996215A11238:\
+CA4F055CE09A20AC58ADEE120EB0B6CF3DAEA0734A41ED162DF863A71B946581\
+5DF6F75B872B9AA45360ABDD8FC2A7320D620050679C300D0A9AF2EB240AC5F6
+
+576EF3520D30B7A4899B8C0D5E359E45C5189ADD100E43BE429A02FB3DE5FF4F\
+8FD0E79D9663ACCA72CD29C94582B19292A557C5B1315297D168FBB54E9E2ECD\
+13809C2B5FCE998EDC6570545E1499DBE7FB74D47CD7F35823B212B05BF3F5A7\
+9CAA34224FDD670D335FCB106F5D92C3946F44D3AFCBAE2E41AC554D8E6759F3\
+32B76BE89A0324AA12C5482D1EA3EE89DED4936F3E3C080436F539FA137E74C6\
+D3389BDF5A45074C47BC7B20B0948407A66D855E2F:\
+651BBB9A3478CF0186A9F94EF8DD33D76A29966D8F747586D73EA963DC966F27\
+7A7361E84A88BC99E2ECE134FFB807FB86B8AC92474C99AD7B730BB6C1ADBA6F
+
+0DF2152FA4F4357C8741529DD77E783925D3D76E95BAFA2B542A2C33F3D1D117\
+D159CF473F82310356FEE4C90A9E505E70F8F24859656368BA09381FA245EB6C\
+3D763F3093F0C89B972E66B53D59406D9F01AEA07F8B3B615CAC4EE4D05F542E\
+7D0DAB45D67CCCCD3A606CCBEB31EA1FA7005BA07176E60DAB7D78F6810EF086\
+F42F08E595F0EC217372B98970CC6321576D92CE38F7C397A403BADA1548D205\
+C343AC09DECA86325373C3B76D9F32028FEA8EB32515:\
+66AA665B49601F044B334769E9D745BBBA240F7E8732BB28DFE4E6D337A9BE5E\
+50747B63CCC2FD88E1A963A3CD62D2BFAFDDF0E5E803006C3CD25C743EC21A04
+
+3E15350D87D6EBB5C8AD99D42515CFE17980933C7A8F6B8BBBF0A63728CEFAAD\
+2052623C0BD5931839112A48633FB3C2004E0749C87A41B26A8B48945539D1FF\
+41A4B269462FD199BFECD45374756F55A9116E92093AC99451AEFB2AF9FD32D6\
+D7F5FBC7F7A540D5097C096EBC3B3A721541DE073A1CC02F7FB0FB1B9327FB0B\
+1218CA49C9487AB5396622A13AE546C97ABDEF6B56380DDA7012A8384091B665\
+6D0AB272D363CEA78163FF765CDD13AB1738B940D16CAE:\
+3162916999F016C87E0775D7DFD2666003092247EF1FDF031BDB803EACF33CE1\
+5C47F7E9C8AC08976DC8A67CC35B4AD69E72D30E90EE7A849E4281944737A1ED
+
+C38D6B0B757CB552BE40940ECE0009EF3B0B59307C1451686F1A22702922800D\
+58BCE7A636C1727EE547C01B214779E898FC0E560F8AE7F61BEF4D75EAA696B9\
+21FD6B735D171535E9EDD267C192B99880C87997711002009095D8A7A437E258\
+104A41A505E5EF71E5613DDD2008195F0C574E6BA3FE40099CFA116E5F1A2FA8\
+A6DA04BADCB4E2D5D0DE31FDC4800891C45781A0AAC7C907B56D631FCA5CE8B2\
+CDE620D11D1777ED9FA603541DE794DDC5758FCD5FAD78C0:\
+F032D67B156D1873B4DD9268856435737DA3203E9614DC74E8DCA4A9A84D65D9\
+0CE1EF255FC1B0427D2D95417472889F0C49D9014E27E51779EC2AE71BCF1C7A
+
+8D2DE3F0B37A6385C90739805B170057F091CD0C7A0BC951540F26A5A75B3E69\
+4631BB64C7635EED316F51318E9D8DE13C70A2ABA04A14836855F35E480528B7\
+76D0A1E8A23B547C8B8D6A0D09B241D3BE9377160CCA4E6793D00A515DC2992C\
+B7FC741DACA171431DA99CCE6F7789F129E2AC5CF65B40D703035CD2185BB936\
+C82002DAF8CBC27A7A9E554B06196630446A6F0A14BA155ED26D95BD627B7205\
+C072D02B60DB0FD7E49EA058C2E0BA202DAFF0DE91E845CF79:\
+ED9B31E1BD0CE1BA0BB66EE03EB9D648385E7CE6AFC2EC777F1EB943E6ACF12B\
+4510B0F37804632540A9BAA03624E9501C285698104E5EDAF471F638DDA13485
+
+C464BBDAD275C50DCD983B65AD1019B9FF85A1E71C807F3204BB2C921DC31FBC\
+D8C5FC45868AE9EF85B6C9B83BBA2A5A822201ED68586EC5EC27FB2857A5D1A2\
+D09D09115F22DCC39FE61F5E1BA0FF6E8B4ACB4C6DA748BE7F3F0839739394FF\
+7FA8E39F7F7E84A33C3866875C01BCB1263C9405D91908E9E0B50E7459FABB63\
+D8C6BBB73D8E3483C099B55BC30FF092FF68B6ADEDFD477D63570C9F5515847F\
+36E24BA0B705557130CEC57EBAD1D0B31A378E91894EE26E3A04:\
+DEE7D084B9C53A0AC64338554D7144A325FC7287F6014CE675B32FA194B99E0F\
+208100B85A0071AABC52D6BCE17E9DBF4CF3ECD55DB87F135A7D88D49DB8D0E7
+
+8B8D68BB8A75732FE272815A68A1C9C5AA31B41DEDC8493E76525D1D013D33CE\
+BD9E21A5BB95DB2616976A8C07FCF411F5F6BC6F7E0B57ACA78CC2790A6F9B89\
+8858AC9C79B165FF24E66677531E39F572BE5D81EB3264524181115F32780257\
+BFB9AEEC6AF12AF28E587CAC068A1A2953B59AD680F4C245B2E3EC36F59940D3\
+7E1D3DB38E13EDB29B5C0F404F6FF87F80FC8BE7A225FF22FBB9C8B6B1D7330C\
+57840D24BC75B06B80D30DAD6806544D510AF6C4785E823AC3E0B8:\
+C983E9577544FF394FCC034FEBA8942A1DE7875ED82EE4E5AA394AAD4F2EC87E\
+0BAF454DA957ABEEB527582DD14896CDECE6048278569C3F6576D76E46E0545E
+
+6B018710446F368E7421F1BC0CCF562D9C1843846BC8D98D1C9BF7D9D6FCB48B\
+FC3BF83B36D44C4FA93430AF75CD190BDE36A7F92F867F58A803900DF8018150\
+384D85D82132F123006AC2AEBA58E02A037FE6AFBD65ECA7C44977DD3DC74F48\
+B6E7A1BFD5CC4DCF24E4D52E92BD4455848E4928B0EAC8B7476FE3CC03E862AA\
+4DFF4470DBFED6DE48E410F25096487ECFC32A27277F3F5023B2725ADE461B13\
+55889554A8836C9CF53BD767F5737D55184EEA1AB3F53EDD0976C485:\
+8E22CB4065DB12F2742FB77FD70E195A4E06CA507DEF9948F5DDCF06245CACF8\
+C37FCE88980759177105F164106DBF43183E0BF32F311B39908F5481A526A86A
+
+C9534A24714BD4BE37C88A3DA1082EDA7CABD154C309D7BD670DCCD95AA53559\
+4463058A29F79031D6ECAA9F675D1211E9359BE82669A79C855EA8D89DD38C2C\
+761DDD0EC0CE9E97597432E9A1BEAE062CDD71EDFDFD464119BE9E69D18A7A7F\
+D7CE0E2106F0C8B0ABF4715E2CA48EF9F454DC203C96656653B727083513F8EF\
+B86E49C513BB758B3B052FE21F1C05BB33C37129D6CC81F1AEF6ADC45B0E8827\
+A830FE545CF57D0955802C117D23CCB55EA28F95C0D8C2F9C5A242B33F:\
+9126DCD87166196A0A3C6F27C728DD9B6652854478BD97B1118C6FC4581109F6\
+CF548CCE0C817A45E8E154A7B7CABDA0AD87E04B93B1498DE97CDFD36527D6EA
+
+07906C87297B867ABF4576E9F3CC7F82F22B154AFCBF293B9319F1B0584DA6A4\
+0C27B32E0B1B7F412C4F1B82480E70A9235B12EC27090A5A33175A2BB28D8ADC\
+475CEFE33F7803F8CE27967217381F02E67A3B4F84A71F1C5228E0C2AD971373\
+F6F672624FCEA8D1A9F85170FAD30FA0BBD25035C3B41A6175D467998BD1215F\
+6F3866F53847F9CF68EF3E2FBB54BC994DE2302B829C5EEA68EC441FCBAFD7D1\
+6AE4FE9FFF98BF00E5BC2AD54DD91FF9FDA4DD77B6C754A91955D1FBAAD0:\
+6B37FB9120740BADAA1839965179B5C2E30AD8C07F5818C228CE490A6EE661C7\
+395F1A66928F7C32DE82183B6CCAD07217B189CD3C95DAA1A42F567FBA7C8019
+
+588E94B9054ABC2189DF69B8BA34341B77CDD528E7860E5DEFCAA79B0C9A452A\
+D4B82AA306BE84536EB7CEDCBE058D7B84A6AEF826B028B8A0271B69AC3605A9\
+635EA9F5EA0AA700F3EB7835BC54611B922964300C953EFE7491E3677C2CEBE0\
+822E956CD16433B02C68C4A23252C3F9E151A416B4963257B783E038F6B4D5C9\
+F110F871652C7A649A7BCEDCBCCC6F2D0725BB903CC196BA76C76AA9F10A190B\
+1D1168993BAA9FFC96A1655216773458BEC72B0E39C9F2C121378FEAB4E76A:\
+95ED53B3D0EA630000AD37035B86502FB98CD2825D8AD2734116AF09C0FF0058\
+95E0CBF84FA843C09DAF43FDCE8C4DACA2F9432480942710C6E4AA640B9BD403
+
+08959A7E4BAAE874928813364071194E2939772F20DB7C3157078987C557C2A6\
+D5ABE68D520EEF3DC491692E1E21BCD880ADEBF63BB4213B50897FA005256ED4\
+1B5690F78F52855C8D9168A4B666FCE2DA2B456D7A7E7C17AB5F2FB1EE90B79E\
+698712E963715983FD07641AE4B4E9DC73203FAC1AE11FA1F8C7941FCC82EAB2\
+47ADDB56E2638447E9D609E610B60CE086656AAEBF1DA3C8A231D7D94E2FD0AF\
+E46B391FF14A72EAEB3F44AD4DF85866DEF43D4781A0B3578BC996C87970B132:\
+41EBE47652EBD797A1DA07936C97FDC63E658B718548167B2908D08EEFFB6C7F\
+00838BD79A7B2F25D582A93B144C101ABBB5C9975C5FA404638F68E6F146F782
+
+CB2A234F45E2ECD5863895A451D389A369AAB99CFEF0D5C9FFCA1E6E63F763B5\
+C14FB9B478313C8E8C0EFEB3AC9500CF5FD93791B789E67EAC12FD038E2547CC\
+8E0FC9DB591F33A1E4907C64A922DDA23EC9827310B306098554A4A78F050262\
+DB5B545B159E1FF1DCA6EB734B872343B842C57EAFCFDA8405EEDBB48EF32E99\
+696D135979235C3A05364E371C2D76F1902F1D83146DF9495C0A6C57D7BF9EE7\
+7E80F9787AEE27BE1FE126CDC9EF893A4A7DCBBC367E40FE4E1EE90B42EA25AF\
+01:\
+3659331E32D9CF89CF0D4F2A484DA0626C50DD2604739D62F1260EEF67EDEB5D\
+77ECB02147428697684DD135067D7CEEF9BD6DFD1109EB348086D494F954FECC
+
+D16BEADF02AB1D4DC6F88B8C4554C51E866DF830B89C06E786A5F8757E890931\
+0AF51C840EFE8D20B35331F4355D80F73295974653DDD620CDDE4730FB6C8D0D\
+2DCB2B45D92D4FBDB567C0A3E86BD1A8A795AF26FBF29FC6C65941CDDB090FF7\
+CD230AC5268AB4606FCCBA9EDED0A2B5D014EE0C34F0B2881AC036E24E151BE8\
+9EEB6CD9A7A790AFCCFF234D7CB11B99EBF58CD0C589F20BDAC4F9F0E28F75E3\
+E04E5B3DEBCE607A496D848D67FA7B49132C71B878FD5557E082A18ECA1FBDA9\
+4D4B:\
+38D34FB7D56C15C2216D5B8409C5D2EF229B89E546BCBDC7172E3E0B1F6FD6DA\
+36E87A2BC794EAD5FB748EE6C1E9E4DFF29C950F2129CEFF290F3A7D6BB68EE1
+
+8F65F6BC59A85705016E2BAE7FE57980DE3127E5AB275F573D334F73F8603106\
+EC3553016608EF2DD6E69B24BE0B7113BF6A760BA6E9CE1C48F9E186012CF96A\
+1D4849D75DF5BB8315387FD78E9E153E76F8BA7EC6C8849810F59FB4BB9B0043\
+18210B37F1299526866F44059E017E22E96CBE418699D014C6EA01C9F0038B10\
+299884DBEC3199BB05ADC94E955A1533219C1115FED0E5F21228B071F40DD57C\
+4240D98D37B73E412FE0FA4703120D7C0C67972ED233E5DEB300A22605472FA3\
+A3BA86:\
+64EFC4356C27F19824C324932938A7FC3941FB0410A3BBCCE5C93D2794825348\
+78D9DD77BAF5505EAA668EA5441F05F53F7D5AF00B0FDA0367037720EBF1E5CC
+
+84891E52E0D451813210C3FD635B39A03A6B7A7317B221A7ABC270DFA946C426\
+69AACBBBDF801E1584F330E28C729847EA14152BD637B3D0F2B38B4BD5BF9C79\
+1C58806281103A3EABBAEDE5E711E539E6A8B2CF297CF351C078B4FA8F7F35CF\
+61BEBF8814BF248A01D41E86C5715EA40C63F7375379A7EB1D78F27622FB468A\
+B784AAABA4E534A6DFD1DF6FA15511341E725ED2E87F98737CCB7B6A6DFAE416\
+477472B046BF1811187D151BFA9F7B2BF9ACDB23A3BE507CDF14CFDF517D2CB5\
+FB9E4AB6:\
+00C2AB70B3D6C51A5FE5D0F0081EDE0C215BDCD342C720231D0BCC0D85BB4B5D\
+7F082ECBA986E2CE2B8B65E67ED186D03319007FB29C286F7F53CFF5864C385F
+
+FDD7A9433A3B4AFABD7A3A5E3457E56DEBF78E84B7A0B0CA0E8C6D53BD0C2DAE\
+31B2700C6128334F43981BE3B213B1D7A118D59C7E6B6493A86F866A1635C128\
+59CFB9AD17460A77B4522A5C1883C3D6ACC86E6162667EC414E9A104AA892053\
+A2B1D72165A855BACD8FAF8034A5DD9B716F47A0818C09BB6BAF22AA503C06B4\
+CA261F557761989D2AFBD88B6A678AD128AF68672107D0F1FC73C5CA74045929\
+7B3292B281E93BCEB761BDE7221C3A55708E5EC84472CDDCAA84ECF23723CC09\
+91355C6280:\
+E4D7B11C693EBE332A054100DBB84B860B485E9F2DDD2C3105A399C5D882F5E1\
+9504EB09874D6CD08BC29E8898AD118B7B52A1E3D111266671663B23FA8130C3
+
+70A40BFBEF92277A1AAD72F6B79D0177197C4EBD432668CFEC05D099ACCB6510\
+62B5DFF156C0B27336687A94B26679CFDD9DAF7AD204338DD9C4D14114033A5C\
+225BD11F217B5F4732DA167EE3F939262D4043FC9CBA92303B7B5E96AEA12ADD\
+A64859DF4B86E9EE0B58E39091E6B188B408AC94E1294A8911245EE361E60E60\
+1EFF58D1D37639F3753BEC80EBB4EFDE25817436076623FC65415FE51D1B0280\
+366D12C554D86743F3C3B6572E400361A60726131441BA493A83FBE9AFDA90F7\
+AF1AE717238D:\
+CBA293EDC18DC23BC4D3519C8E395A1152408CD30C769F907F832528211F3D9A\
+40516C5FF35B0089166F7343B61ED1DBF7E690403695A5C1BA6759B63C512D3E
+
+74356E449F4BF8644F77B14F4D67CB6BD9C1F5AE357621D5B8147E562B65C665\
+85CAF2E491B48529A01A34D226D436959153815380D5689E30B35357CDAC6E08\
+D3F2B0E88E200600D62BD9F5EAF488DF86A4470EA227006182E44809009868C4\
+C280C43D7D64A5268FA719074960087B3A6ABC837882F882C837834535929389\
+A12B2C78187E2EA07EF8B8EEF27DC85002C3AE35F1A50BEE6A1C48BA7E175F33\
+16670B27983472AA6A61EED0A683A39EE323080620EA44A9F74411AE5CE99030\
+528F9AB49C79F2:\
+B76B535F4284DAE534942D4550BB44ACC68F0CCDD4C37E41657D49F969311E81\
+DC03D4CF6EE6F0EC02DE4203D52B9C54364C1EDCEABB97963468B68CD88CCACB
+
+8C3798E51BC68482D7337D3ABB75DC9FFE860714A9AD73551E120059860DDE24\
+AB87327222B64CF774415A70F724CDF270DE3FE47DDA07B61C9EF2A3551F45A5\
+584860248FABDE676E1CD75F6355AA3EAEABE3B51DC813D9FB2EAA4F0F1D9F83\
+4D7CAD9C7C695AE84B329385BC0BEF895B9F1EDF44A03D4B410CC23A79A6B62E\
+4F346A5E8DD851C2857995DDBF5B2D717AEB847310E1F6A46AC3D26A7F9B4498\
+5AF656D2B7C9406E8A9E8F47DCB4EF6B83CAACF9AEFB6118BFCFF7E44BEF6937\
+EBDDC89186839B77:\
+E6431FFEB780377D04EA873C6F407A55BF9696E96FEBD19217E5B6303EA45873\
+4FCEE2BF895D7095BAFDE147FC1D24A57BC48450B494515192F2D5BFA09A2D2E
+
+FA56BF730C4F8395875189C10C4FB251605757A8FECC31F9737E3C2503B02608\
+E6731E85D7A38393C67DE516B85304824BFB135E33BF22B3A23B913BF6ACD2B7\
+AB85198B8187B2BCD454D5E3318CACB32FD6261C31AE7F6C54EF6A7A2A4C9F3E\
+CB81CE3555D4F0AD466DD4C108A90399D70041997C3B25345A9653F3C9A6711A\
+B1B91D6A9D2216442DA2C973CBD685EE7643BFD77327A2F7AE9CB283620A0871\
+6DFB462E5C1D65432CA9D56A90E811443CD1ECB8F0DE179C9CB48BA4F6FEC360\
+C66F252F6E64EDC96B:\
+9F1D730DF3670BF72EDED050572F9338F5A651709818558849CA3AF8DBFC591E\
+81606753F742B67DCED42785FB6E019BE776EBAAB5AA20219052C03093FF9156
+
+B6134F9C3E91DD8000740D009DD806240811D51AB1546A974BCB18D344642BAA\
+5CD5903AF84D58EC5BA17301D5EC0F10CCD0509CBB3FD3FFF9172D193AF0F782\
+252FD1338C7244D40E0E42362275B22D01C4C3389F19DD69BDF958EBE28E31A4\
+FFE2B5F18A87831CFB7095F58A87C9FA21DB72BA269379B2DC2384B3DA953C79\
+25761FED324620ACEA435E52B424A7723F6A2357374157A34CD8252351C25A1B\
+232826CEFE1BD3E70FFC15A31E7C0598219D7F00436294D11891B82497BC78AA\
+5363892A2495DF8C1EEF:\
+63E1C2300AB80C173489D84A4E3F3E589C616F792475BE05A1C85EC319364B96\
+FF1AFAC04127F59C4AD4BCDF7A8ECB2C3EC2EA41BF2119F8F3E0CF396213C9EB
+
+C941CDB9C28AB0A791F2E5C8E8BB52850626AA89205BEC3A7E22682313D198B1\
+FA33FC7295381354858758AE6C8EC6FAC3245C6E454D16FA2F51C4166FAB51DF\
+272858F2D603770C40987F64442D487AF49CD5C3991CE858EA2A60DAB6A65A34\
+414965933973AC2457089E359160B7CDEDC42F29E10A91921785F6B7224EE0B3\
+49393CDCFF6151B50B377D609559923D0984CDA6000829B916AB6896693EF6A2\
+199B3C22F7DC5500A15B8258420E314C222BC000BC4E5413E6DD82C993F8330F\
+5C6D1BE4BC79F08A1A0A46:\
+37D4442868321073AB61D481468EDB24CE60CE3C0C2A92B6E20BC144CEA5B749\
+D2AD93A23D1A2312675EE50F069F77D43D36FA3571322D5DB07A97E5F735AD3F
+
+4499EFFFAC4BCEA52747EFD1E4F20B73E48758BE915C88A1FFE5299B0B005837\
+A46B2F20A9CB3C6E64A9E3C564A27C0F1C6AD1960373036EC5BFE1A8FC6A435C\
+2185ED0F114C50E8B3E4C7ED96B06A036819C9463E864A58D6286F785E32A804\
+443A56AF0B4DF6ABC57ED5C2B185DDEE8489EA080DEEEE66AA33C2E6DAB36251\
+C402682B6824821F998C32163164298E1FAFD31BABBCFFB594C91888C6219079\
+D907FDB438ED89529D6D96212FD55ABE20399DBEFD342248507436931CDEAD49\
+6EB6E4A80358ACC78647D043:\
+92B29DC4A8B4378E8C8D8759563E1145F0255A9B0EF8351947AE0C132E008FC4\
+0508C0124B9AF0E7D4116E3C3280D9BC69D92DFFA39E0DC99AB3D90D5FD00220
+
+EECBB8FDFA4DA62170FD06727F697D81F83F601FF61E478105D3CB7502F2C89B\
+F3E8F56EDD469D049807A38882A7EEFBC85FC9A950952E9FA84B8AFEBD3CE782\
+D4DA598002827B1EB98882EA1F0A8F7AA9CE013A6E9BC462FB66C8D4A18DA214\
+01E1B93356EB12F3725B6DB1684F2300A98B9A119E5D27FF704AFFB618E12708\
+E77E6E5F34139A5A41131FD1D6336C272A8FC37080F041C71341BEE6AB550CB4\
+A20A6DDB6A8E0299F2B14BC730C54B8B1C1C487B494BDCCFD3A53535AB2F2315\
+90BF2C4062FD2AD58F906A2D0D:\
+423857FF8C9A0F5536566FBE09CF5BA527442F4EBE3ADA7C28951A89999A613D\
+C9EF13E52A389B3880B8C911F6629AD6ACD4AC4BE1E39CFEBDF74F7AFB42ADC4
+
+E64F3E4ACE5C8418D65FEC2BC5D2A303DD458034736E3B0DF719098BE7A206DE\
+AF52D6BA82316CAF330EF852375188CDE2B39CC94AA449578A7E2A8E3F5A9D68\
+E816B8D16889FBC0EBF0939D04F63033AE9AE2BDAB73B88C26D6BD25EE460EE1\
+EF58FB0AFA92CC539F8C76D3D097E7A6A63EBB9B5887EDF3CF076028C5BBD5B9\
+DB3211371AD3FE121D4E9BF44229F4E1ECF5A0F9F0EBA4D5CEB72878AB22C3F0\
+EB5A625323AC66F7061F4A81FAC834471E0C59553F108475FE290D43E6A055AE\
+3EE46FB67422F814A68C4BE3E8C9:\
+BE84D55224938B7B69F0CE8A2C45BEC38D1DE818FB80F492690D5CB75E473163\
+87656EF483AC978066D8B4F05017460EC28AA349F888BD213F3499EEAB7A6D11
+
+D2CB2D733033F9E91395312808383CC4F0CA974E87EC68400D52E96B3FA6984A\
+C58D9AD0938DDE5A973008D818C49607D9DE2284E7618F1B8AED8372FBD52ED5\
+4557AF4220FAC09DFA8443011699B97D743F8F2B1AEF3537EBB45DCC9E13DFB4\
+38428EE190A4EFDB3CAEB7F3933117BF63ABDC7E57BEB4171C7E1AD260AB0587\
+806C4D137B6316B50ABC9CCE0DFF3ACADA47BBB86BE777E617BBE578FF451984\
+4DB360E0A96C6701290E76BB95D26F0F804C8A4F2717EAC4E7DE9F2CFF3BBC55\
+A17E776C0D02856032A6CD10AD2838:\
+E1FC5A6C209F8A4E2F1701CFC43EE843807E3994A2943DACCF0347D30B6243E4\
+AEC2D8700AC713CE5ED76EC9688E78922EDB2CA0D578634ADF60763C025EB424
+
+F2998955613DD414CC111DF5CE30A995BB792E260B0E37A5B1D942FE90171A4A\
+C2F66D4928D7AD377F4D0554CBF4C523D21F6E5F379D6F4B028CDCB9B1758D3B\
+39663242FF3CB6EDE6A36A6F05DB3BC41E0D861B384B6DEC58BB096D0A422FD5\
+42DF175E1BE1571FB52AE66F2D86A2F6824A8CFAACBAC4A7492AD0433EEB1545\
+4AF8F312B3B2A577750E3EFBD370E8A8CAC1582581971FBA3BA4BD0D76E718DA\
+CF8433D33A59D287F8CC92234E7A271041B526E389EFB0E40B6A18B3AAF658E8\
+2ED1C78631FD23B4C3EB27C3FAEC8685:\
+F77ED1B03275C3BA51501DBD076B36C8EAFAD9FBBDFC0CE80A2FE105CB4D9EE7\
+C7AEDCA5F6FEA9065CF507D8F61DD7BA0B9355ED2A753A4F9F084CC758BF9ADA
+
+447797E2899B72A356BA55BF4DF3ACCA6CDB1041EB477BD1834A9F9ACBC340A2\
+94D729F2F97DF3A610BE0FF15EDB9C6D5DB41644B9874360140FC64F52AA03F0\
+286C8A640670067A84E017926A70438DB1BB361DEFEE7317021425F8821DEF26\
+D1EFD77FC853B818545D055ADC9284796E583C76E6FE74C9AC2587AA46AA8F88\
+04F2FEB5836CC4B3ABABAB8429A5783E17D5999F32242EB59EF30CD7ADABC16D\
+72DBDB097623047C98989F88D14EAF02A7212BE16EC2D07981AAA99949DDF89E\
+CD90333A77BC4E1988A82ABF7C7CAF3291:\
+9408FE45CB615EAE7CCC92E33051C3CA8382A1BAB834AD8201B901B897175C35\
+509296066FE4ABAA2347BF25D798F7B51B6231BE37DC363818B55AE3D93C7861
+
+9F2C18ADE9B380C784E170FB763E9AA205F64303067EB1BCEA93DF5DAC4BF5A2\
+E00B78195F808DF24FC76E26CB7BE31DC35F0844CDED1567BBA29858CFFC97FB\
+29010331B01D6A3FB3159CC1B973D255DA9843E34A0A4061CABDB9ED37F241BF\
+ABB3C20D32743F4026B59A4CCC385A2301F83C0B0A190B0F2D01ACB8F0D41111\
+E10F2F4E149379275599A52DC089B35FDD5234B0CFB7B6D8AEBD563CA1FA653C\
+5C021DFD6F5920E6F18BFAFDBECBF0AB00281333ED50B9A999549C1C8F8C63D7\
+626C48322E9791D5FF72294049BDE91E73F8:\
+B8EDB924C295E8740A0C4BA2F55C2E3A9D0F193F81402BCD95DCBC3481ED6F2F\
+E60BB871CBB52347C1B871E5F9195CAB3ED4C54B61F199ABC15FE5BB1CCBE920
+
+AE159F3FA33619002AE6BCCE8CBBDD7D28E5ED9D61534595C4C9F43C402A9BB3\
+1F3B301CBFD4A43CE4C24CD5C9849CC6259ECA90E2A79E01FFBAC07BA0E147FA\
+42676A1D668570E0396387B5BCD599E8E66AAED1B8A191C5A47547F61373021F\
+A6DEADCB55363D233C24440F2C73DBB519F7C9FA5A8962EFD5F6252C0407F190\
+DFEFAD707F3C7007D69FF36B8489A5B6B7C557E79DD4F50C06511F599F56C896\
+B35C917B63BA35C6FF8092BAF7D1658E77FC95D8A6A43EEB4C01F33F03877F92\
+774BE89C1114DD531C011E53A34DC248A2F0E6:\
+4BEAFE927E01FEA9EC5A1EC24F6B58B56468C3064C43AE91354EA2770FCD0B39\
+6702F6750C7B91A3625AB6D38DEA3D49C2FD32872D7CF842BD8BCDFF3787705B
+
+3B8E97C5FFC2D6A40FA7DE7FCEFC90F3B12C940E7AB415321E29EE692DFAC799\
+B009C99DCDDB708FCE5A178C5C35EE2B8617143EDC4C40B4D313661F49ABDD93\
+CEA79D117518805496FE6ACF292C4C2A1F76B403A97D7C399DAF85B46AD84E16\
+246C67D6836757BDE336C290D5D401E6C1386AB32797AF6BB251E9B2D8FE754C\
+47482B72E0B394EAB76916126FD68EA7D65EB93D59F5B4C5AC40F7C3B37E7F36\
+94F29424C24AF8C8F0EF59CD9DBF1D28E0E10F799A6F78CAD1D45B9DB3D7DEE4\
+A7059ABE99182714983B9C9D44D7F5643596D4F3:\
+151D4002FE1C85CA59D8F759938CED3236CC5D00471C300D3CAC63BC180214A4\
+49795E35C39A8C6DFDD74D2DD340A71C284678B99929B9DFFF0852462E0ED10D
+
+3434EC31B10FAFDBFEEC0DD6BD94E80F7BA9DCA19EF075F7EB017512AF66D6A4\
+BCF7D16BA0819A1892A6372F9B35BCC7CA8155EE19E8428BC22D214856ED5FA9\
+374C3C09BDE169602CC219679F65A1566FC7316F4CC3B631A18FB4449FA6AFA1\
+6A3DB2BC4212EFF539C67CF184680826535589C7111D73BFFCE431B4C40492E7\
+63D9279560AAA38EB2DC14A212D723F994A1FE656FF4DD14551CE4E7C621B2AA\
+5604A10001B2878A897A28A08095C325E10A26D2FB1A75BFD64C250309BB55A4\
+4F23BBAC0D5516A1C687D3B41EF2FBBF9CC56D4739:\
+9CA3A802AA51F1AFA3D50A6E369C22DE9D68809ED5A0CD443F46C3B3118B0F34\
+8E0FA230F6E0BE784396957F52E100413FA26832CE0B88FBCCD47A1AB1C667C8
+
+7C7953D81C8D208FD1C97681D48F49DD003456DE60475B84070EF4847C333B74\
+575B1FC8D2A186964485A3B8634FEAA3595AAA1A2F4595A7D6B6153563DEE31B\
+BAC443C8A33EED6D5D956A980A68366C2527B550EE950250DFB691EACBD5D56A\
+E14B970668BE174C89DF2FEA43AE52F13142639C884FD62A3683C0C3792F0F24\
+AB1318BCB27E21F4737FAB62C77EA38BC8FD1CF41F7DAB64C13FEBE7152BF5BB\
+7AB5A78F5346D43CC741CB6F72B7B8980F268B68BF62ABDFB1577A52438FE14B\
+591498CC95F071228460C7C5D5CEB4A7BDE588E7F21C:\
+09D304C2BE91424FABE8CA3C91E331B92C4A0A11928BBD59BDB1454D22D0B689\
+A25A0BE04CC1605C158AFA2E504D08B13DA4F04C10C07D94088F664163EEDB78
+
+7A6A4F4FDC59A1D223381AE5AF498D74B7252ECF59E389E49130C7EAEE626E7B\
+D9897EFFD92017F4CCDE66B0440462CDEDFD352D8153E6A4C8D7A0812F701CC7\
+37B5178C2556F07111200EB627DBC299CAA792DFA58F35935299FA3A3519E9B0\
+3166DFFA159103FFA35E8577F7C0A86C6B46FE13DB8E2CDD9DCFBA85BDDDCCE0\
+A7A8E155F81F712D8E9FE646153D3D22C811BD39F830433B2213DD46301941B5\
+9293FD0A33E2B63ADBD95239BC01315C46FDB678875B3C81E053A40F581CFBEC\
+24A1404B1671A1B88A6D06120229518FB13A74CA0AC5AE:\
+0045581DC66F42F4020CF88E67D1810A234BD5A99715B3E6B06EF649E6071A3B\
+3BB2B1628C711528621DC94810F0063F2656CF83C4093CB637B233431F76625A
+
+D9FAA14CEBE9B7DE551B6C0765409A33938562013B5E8E0E1E0A6418DF7399D0\
+A6A771FB81C3CA9BD3BB8E2951B0BC792525A294EBD1083688806FE5E7F1E17F\
+D4E3A41D00C89E8FCF4A363CAEDB1ACB558E3D562F1302B3D83BB886ED27B760\
+33798131DAB05B4217381EAAA7BA15EC820BB5C13B516DD640EAEC5A27D05FDF\
+CA0F35B3A5312146806B4C0275BCD0AAA3B2017F346975DB566F9B4D137F4EE1\
+0644C2A2DA66DEECA5342E236495C3C6280528BFD32E90AF4CD9BB908F34012B\
+52B4BC56D48CC8A6B59BAB014988EABD12E1A0A1C2E170E7:\
+415F5ED9FC4E825DDAC3A283BB79339CEE6D67880A9B8A79A1EB6597BB25C8D8\
+E4716712FE0D3F12A45699FB55E857E76609593DE2516EDF0F5E99D59946A806
+
+2D8427433D0C61F2D96CFE80CF1E932265A191365C3B61AAA3D6DCC039F6BA2A\
+D52A6A8CC30FC10F705E6B7705105977FA496C1C708A277A124304F1FC40911E\
+7441D1B5E77B951AAD7B01FD5DB1B377D165B05BBF898042E39660CAF8B279FE\
+5229D1A8DB86C0999ED65E53D01CCBC4B43173CCF992B3A14586F6BA42F5FE30\
+AFA8AE40C5DF29966F9346DA5F8B35F16A1DE3AB6DE0F477D8D8660918060E88\
+B9B9E9CA6A4207033B87A812DBF5544D39E4882010F82B6CE005F8E8FF6FE3C3\
+806BC2B73C2B83AFB704345629304F9F86358712E9FAE3CA3E:\
+BF4A6DFD55489A2B9787960E6A787BE9DBCA875B17A8CF2F111C313B01C8994C\
+E01B2ADA486AF7676AF04BAA88E07A0214BCA00008004150CE4DF598B44CD814
+
+5E19D97887FCAAC0387E22C6F803C34A3DACD2604172433F7A8A7A526CA4A2A1\
+271ECFC5D5D7BE5AC0D85D921095350DFC65997D443C21C8094E0A3FEFD2961B\
+CB94AED03291AE310CCDA75D8ACE4BC7D89E7D3E5D1650BDA5D668B8B50BFC8E\
+608E184F4D3A9A2BADC4FF5F07E0C0BC8A9F2E0B2A26FD6D8C550008FAAAB75F\
+D71AF2A424BEC9A7CD9D83FAD4C8E9319115656A8717D3B523A68FF8004258B9\
+990ED362308461804BA3E3A7E92D8F2FFAE5C2FBA55BA5A3C27C0A2F71BD711D\
+2FE1799C2ADB31B200035481E9EE5C4ADF2AB9C0FA50B23975CF:\
+72F3EC4F8D3A31E42C4B8C3C4C1CE51340677D17A7FE8AE04F9DB6B6B7C13CF5\
+613FBCB7396E5F1B3FAB086558996B2079FF64C7AEA34AA7830084D40E416F29
+
+C8E976AB4638909387CE3B8D4E510C3230E5690E02C45093B1D297910ABC481E\
+56EEA0F296F98379DFC9080AF69E73B2399D1C143BEE80AE1328162CE1BA7F6A\
+8374679B20AACD380EB4E61382C99998704D62701AFA914F9A2705CDB065885F\
+50D086C3EB5753700C387118BB142F3E6DA1E988DFB31AC75D7368931E45D139\
+1A274B22F83CEB072F9BCABC0B216685BFD789F5023971024B1878A205442522\
+F9EA7D8797A4102A3DF41703768251FD5E017C85D1200A464118AA35654E7CA3\
+9F3C375B8EF8CBE7534DBC64BC20BEFB417CF60EC92F63D9EE7397:\
+7B26CC15637AE7137BFEB543208A7BB5C41F2F8E1AA8C7336EB656F2A7D350AE\
+EA77734091E49D8C026F67CC712A54BE8AC2C2879661CC83BE51554D9D141FD0
+
+7145FA124B7429A1FC2231237A949BA7201BCC1822D3272DE005B682398196C2\
+5F7E5CC2F289FBF44415F699CB7FE6757791B1443410234AE061EDF623359E2B\
+4E32C19BF88450432DD01CAA5EB16A1DC378F391CA5E3C4E5F356728BDDD4975\
+DB7C890DA8BBC84CC73FF244394D0D48954978765E4A00B593F70F2CA082673A\
+261ED88DBCEF1127728D8CD89BC2C597E9102CED6010F65FA75A14EBE467FA57\
+CE3BD4948B6867D74A9DF5C0EC6F530CBF2EE61CE6F06BC8F2864DFF5583776B\
+31DF8C7FFCB61428A56BF7BD37188B4A5123BBF338393AF46EDA85E6:\
+6A8A4AF537B7B652EB1C1B4F55E442F8D20FB7D477A22AA4A3AF7DF5AF140F17\
+1BCFE65603255414F7D5E87C2DB91DCA223026D9E26BF3BDCA251E8325327977
+
+7FDFADCC9D29BAD23AE038C6C65CDA1AEF757221B8872ED3D75FF8DF7DA0627D\
+266E224E812C39F7983E4558BFD0A1F2BEF3FEB56BA09120EF762917B9C09386\
+7948547AEE98600D10D87B20106878A8D22C64378BF634F7F75900C03986B077\
+B0BF8B740A82447B61B99FEE5376C5EB6680EC9E3088F0BDD0C56883413D60C1\
+357D3C811950E5890E7600103C916341B80C743C6A852B7B4FB60C3BA21F3BC1\
+5B8382437A68454779CF3CD7F9F90CCC8EF28D0B706535B1E4108EB5627BB45D\
+719CB046839AEE311CA1ABDC8319E050D67972CB35A6B1601B25DBF487:\
+AFE7EF29D0CF870483B17FBCAD1B425F59C542D9CD777AB48F29060665ACCCAC\
+1409DC5A191E3D91B34B3D6DB907F2F575911B797A91C981F13FA5A83E2A81BF
+
+988638219FD3095421F826F56E4F09E356296B628C3CE6930C9F2E758FD1A80C\
+8273F2F61E4DAAE65C4F110D3E7CA0965AC7D24E34C0DC4BA2D6FF0BF5BBE93B\
+3585F354D7543CB542A1AA54674D375077F2D360A8F4D42F3DB131C3B7AB7306\
+267BA107659864A90C8C909460A73621D1F5D9D3FD95BEB19B23DB1CB6C0D0FB\
+A91D36891529B8BD8263CAA1BAB56A4AFFAED44962DF096D8D5B1EB845EF3118\
+8B3E10F1AF811A13F156BEB7A288AAE593EBD1471B624AA1A7C6ADF01E2200B3\
+D72D88A3AED3100C88231E41EFC376906F0B580DC895F080FDA5741DB1CB:\
+D61BFC84CEDB8148652A409AF58EADD8E85D920DF69C70AB5929587FC1D14662\
+DE3A4D8E238F9269095E972A698C29E391852E9BF3C7AC052148AA6D2F54B974
+
+5AAB62756D307A669D146ABA988D9074C5A159B3DE85151A819B117CA1FF6597\
+F6156E80FDD28C9C3176835164D37DA7DA11D94E09ADD770B68A6E081CD22CA0\
+C004BFE7CD283BF43A588DA91F509B27A6584C474A4A2F3EE0F1F56447379240\
+A5AB1FB77FDCA49B305F07BA86B62756FB9EFB4FC225C86845F026EA542076B9\
+1A0BC2CDD136E122C659BE259D98E5841DF4C2F60330D4D8CDEE7BF1A0A24452\
+4EECC68FF2AEF5BF0069C9E87A11C6E519DE1A4062A10C83837388F7EF58598A\
+3846F49D499682B683C4A062B421594FAFBC1383C943BA83BDEF515EFCF10D:\
+5D33D32A4401B95BB332238FC13F4A905A4E07157006370CF6B47ABE33495598\
+E0A6144D2201ACF4BD60594EC431F66AC7308C7916B17A03122934499ED4EE39
+
+47B8216AA0FBB5D67966F2E82C17C07AA2D6327E96FCD83E3DE7333689F3EE79\
+994A1BF45082C4D725ED8D41205CB5BCDF5C341F77FACB1DA46A5B9B2CBC49EA\
+DF786BCD881F371A95FA17DF73F606519AEA0FF79D5A11427B98EE7F13A5C006\
+37E2854134691059839121FEA9ABE2CD1BCBBBF27C74CAF3678E05BFB1C94989\
+7EA01F56FFA4DAFBE8644611685C617A3206C7A7036E4AC816799F693DAFE7F1\
+9F303CE4EBA09D21E03610201BFC665B72400A547A1E00FA9B7AD8D84F84B34A\
+EF118515E74DEF11B9188BD1E1F97D9A12C30132EC2806339BDADACDA2FD8B78:\
+E50E6C9BF5DFC7698DAB40159D2BD7E0C22E845ED8F2A817421845C522B85458\
+6415923768B4FA29431EC3ED7202CE9D512954DA4BA96C5B28657E9A50B9AECF
+
+8CFF1F67FE53C098896D9136389BD8881816CCAB34862BB67A656E3D98896F3C\
+E6FFD4DA73975809FCDF9666760D6E561C55238B205D8049C1CEDEEF374D1735\
+DAA533147BFA960B2CCE4A4F254176BB4D1BD1E89654432B8DBE1A135C42115B\
+394B024856A2A83DC85D6782BE4B444239567CCEC4B184D4548EAE3FF6A192F3\
+43292BA2E32A0F267F31CC26719EB85245D415FB897AC2DA433EE91A99424C9D\
+7F1766A44171D1651001C38FC79294ACCC68CEB5665D36218454D3BA169AE058\
+A831338C17743603F81EE173BFC0927464F9BD728DEE94C6AEAB7AAE6EE3A627\
+E8:\
+8ED1362986F4A6D24534EA826AF9BD746044657B35FA48EDA6EFFA9417D1218A\
+4CA84E8847243B22C508D74489747FA53E7CF96EC52ED7C485BEA3CCD5AB1E32
+
+EACD07971CFF9B9939903F8C1D8CBB5D4DB1B548A85D04E037514A583604E787\
+F32992BF2111B97AC5E8A938233552731321522AB5E8583561260B7D13EBEEF7\
+85B23A41FD8576A6DA764A8ED6D822D4957A545D5244756C18AA80E1AAD4D1F9\
+C20D259DEE1711E2CC8FD013169FB7CC4CE38B362F8E0936AE9198B7E838DCEA\
+4F7A5B9429BB3F6BBCF2DC92565E3676C1C5E6EB3DD2A0F86AA23EDD3D0891F1\
+97447692794B3DFA269611AD97F72B795602B4FDB198F3FD3EB41B415064256E\
+345E8D8C51C555DC8A21904A9B0F1AD0EFFAB7786AAC2DA3B196507E9F33CA35\
+6427:\
+F757E258A9F249FEDD4D3D8F43A0862B46951700902AE90B7782D01D0869ED72\
+0DC57F2E4E89E329E8F81FEE91D5A0DD72888C08535F2987BB6A020CC9A3A13A
+
+23AC4E9A42C6EF45C3336CE6DFC2FF7DE8884CD23DC912FEF0F7756C09D335C1\
+89F3AD3A23697ABDA851A81881A0C8CCAFC980AB2C702564C2BE15FE4C4B9F10\
+DFB2248D0D0CB2E2887FD4598A1D4ACDA897944A2FFC580FF92719C95CF2AA42\
+DC584674CB5A9BC5765B9D6DDF5789791D15F8DD925AA12BFFAFBCE60827B490\
+BB7DF3DDA6F2A143C8BF96ABC903D83D59A791E2D62814A89B8080A28060568C\
+F24A80AE61179FE84E0FFAD00388178CB6A617D37EFD54CC01970A4A41D1A8D3\
+DDCE46EDBBA4AB7C90AD565398D376F431189CE8C1C33E132FEAE6A8CD17A61C\
+630012:\
+995958EBB5F16F360A7C035B081BD3324F85E3A84047362EE22957B5D8C8BE78\
+65A09FE1B50E37ADA0812C370593730752D963FE83DFFA00C3F5D9EFC23A28C7
+
+0172DF732282C9D488669C358E3492260CBE91C95CFBC1E3FEA6C4B0EC129B45\
+F242ACE09F152FC6234E1BEE8AAB8CD56E8B486E1DCBA9C05407C2F95DA8D8F1\
+C0AF78EE2ED82A3A79EC0CB0709396EE62AADB84F8A4EE8A7CCCA3C1EE84E302\
+A09EA802204AFECF04097E67D0F8E8A9D2651126C0A598A37081E42D168B0AE8\
+A71951C524259E4E2054E535B779679BDADE566FE55700858618E626B4A0FAF8\
+95BCCE9011504A49E05FD56127EAE3D1F8917AFB548ECADABDA1020111FEC931\
+4C413498A360B08640549A22CB23C731ACE743252A8227A0D2689D4C60016066\
+78DFB921:\
+8E1F3C32D6994A9F28FF810DAEBEC0DCDA92F963E1F464915CB9B2F05B081E9B\
+7D968E73A2FCDEC720F67DAADEE186B3A3E7BDBFD68D015AE4084081407978EC
+
+3875B9240CF3E0A8B59C658540F26A701CF188496E2C2174788B126FD29402D6\
+A75453BA0635284D08835F40051A2A9683DC92AFB9383719191231170379BA6F\
+4ADC816FECBB0F9C446B785BF520796841E58878B73C58D3EBB097CE4761FDEA\
+BE15DE2F319DFBAF1742CDEB389559C788131A6793E193856661376C81CE9568\
+DA19AA6925B47FFD77A43C7A0E758C37D69254909FF0FBD415EF8EB937BCD49F\
+91468B49974C07DC819ABD67395DB0E05874FF83DDDAB895344ABD0E7111B2DF\
+9E58D76D85AD98106B36295826BE04D435615595605E4B4BB824B33C4AFEB5E7\
+BB0D19F909:\
+64F2AB3327F730A3FEB81AF8122EE111F64D6C31A2ED23F9BA22F67946D5811F\
+03DB1CF002E57E2CEDB18C29C0C73EF2255D8AAA6A851F2ABA50D1B0CBFF6F16
+
+747CC1A59FEFBA94A9C75BA866C30DC5C1CB0C0F8E9361D98484956DD5D1A40F\
+6184AFBE3DAC9F76028D1CAECCFBF69199C6CE2B4C092A3F4D2A56FE5A33A007\
+57F4D7DEE5DFB0524311A97AE0668A47971B95766E2F6DD48C3F57841F91F04A\
+00AD5EA70F2D479A2620DC5CD78EAAB3A3B011719B7E78D19DDF70D9423798AF\
+77517EBC55392FCD01FC600D8D466B9E7A7A85BF33F9CC5419E9BD874DDFD609\
+81150DDAF8D7FEBAA4374F0872A5628D318000311E2F5655365AD4D407C20E5C\
+04DF17A222E7DEEC79C5AB1116D8572F91CD06E1CCC7CED53736FC867FD49ECE\
+BE6BF8082E8A:\
+9B833B7C6B5F97E75FBCEAE20AA2487DF07692DCA64375295C09A68B4A93EADF\
+12A7137283C215DF590F1E1304FC2A5E95528AD95EDC08085647526A69FF57F8
+
+57AF971FCCAEC97435DC2EC9EF0429BCEDC6B647729EA168858A6E49AC1071E7\
+06F4A5A645CA14E8C7746D65511620682C906C8B86EC901F3DDED4167B3F00B0\
+6CBFAC6AEE3728051B3E5FF10B4F9ED8BD0B8DA94303C833755B3CA3AEDDF0B5\
+4BC8D6632138B5D25BAB03D17B3458A9D782108006F5BB7DE75B5C0BA854B423\
+D8BB801E701E99DC4FEAAD59BC1C7112453B04D33EA3635639FB802C73C2B71D\
+58A56BBD671B18FE34ED2E3DCA38827D63FDB1D4FB3285405004B2B3E26081A8\
+FF08CD6D2B08F8E7B7E90A2AB1ED7A41B1D0128522C2F8BFF56A7FE67969422C\
+E839A9D4608F03:\
+624CD5B6F0F1259512D6E0B6E65174CA7FBF6CD324149F0F592F386BAF5DE550\
+D44AA471CB97E9EEF6C03D262714BE00F6581D902A9326A337CD6DC2A1CC5CBA
+
+04E16DEDC1227902BAAF332D3D08923601BDD64F573FAA1BB7201918CFE16B1E\
+10151DAE875DA0C0D63C59C3DD050C4C6A874011B018421AFC4623AB0381831B\
+2DA2A8BA42C96E4F70864AC44E106F94311051E74C77C1291BF5DB9539E69567\
+BF6A11CF6932BBBAD33F8946BF5814C066D851633D1A513510039B349939BFD4\
+2B858C21827C8FF05F1D09B1B0765DC78A135B5CA4DFBA0801BCADDFA175623C\
+8B647EACFB4444B85A44F73890607D06D507A4F8393658788669F6EF4DEB58D0\
+8C50CA0756D5E2F49D1A7AD73E0F0B3D3B5F090ACF622B1878C59133E4A848E0\
+5153592EA81C6FBF:\
+0FA1E0A7FFA3CAB76299251FF7A910A2076BBC6A0BC36025B1B0AA290FEA8E30\
+AE1D5B512778E0DB8CCD5C325CBD711BE4C7BF6F5465380878A2FC6285D3D630
+
+7C815C384EEE0F288ECE27CCED52A01603127B079C007378BC5D1E6C5E9E6D1C\
+735723ACBBD5801AC49854B2B569D4472D33F40BBB8882956245C366DC3582D7\
+1696A97A4E19557E41E54DEE482A14229005F93AFD2C4A7D8614D10A97A9DFA0\
+7F7CD946FA45263063DDD29DB8F9E34DB60DAA32684F0072EA2A9426ECEBFA52\
+39FB67F29C18CBAA2AF6ED4BF4283936823AC1790164FEC5457A9CBA7C767CA5\
+9392D94CAB7448F50EB34E9A93A80027471CE59736F099C886DEA1AB4CBA4D89\
+F5FC7AE2F21CCD27F611ECA4626B2D08DC22382E92C1EFB2F6AFDC8FDC3D2172\
+604F5035C46B8197D3:\
+02FE69A2CA198E76405BEBA6088EA173F581DEFD8F7312F5B810E60E5EBE4336\
+690154E0B3E05C4DE06BD4B9AA274BBA2E362B247219C9475587A706C50B8EFF
+
+E29D505158DBDD937D9E3D2145658EE6F5992A2FC790F4F608D9CDB44A091D5B\
+94B88E81FAC4FDF5C49442F13B911C55886469629551189EAFF62488F1A479B7\
+DB11A1560E198DDCCCCF50159093425FF7F1CB8D1D1246D0978764087D6BAC25\
+7026B090EFAE8CEC5F22B6F21C59ACE1AC7386F5B8837CA6A12B6FBF5534DD05\
+60EF05CA78104D3B943DDB220FEAEC89AA5E692A00F822A2AB9A2FE60350D75E\
+7BE16FF2526DC643872502D01F42F188ABED0A6E9A6F5FD0D1CE7D5755C9FFA6\
+6B0AF0B20BD806F08E06156690D81AC811778CA3DAC2C249B96002017FCE93E5\
+07E3B953ACF99964B847:\
+9A478AF3A0C60C5A3C2A84FE8144BB0917C3F309A867ADA82E736092006D3CE3\
+BA923310689850708CD5B4C28C022AEC70858B9E2962D7EFA507DA763D33ED4B
+
+D85588696F576E65ECA0155F395F0CFACD83F36A99111ED5768DF2D116D2121E\
+32357BA4F54EDE927F189F297D3A97FAD4E9A0F5B41D8D89DD7FE20156799C2B\
+7B6BF9C957BA0D6763F5C3BC5129747BBB53652B49290CFF1C87E2CDF2C4B95D\
+8AAEE09BC8FBFA6883E62D237885810491BFC101F1D8C636E3D0EDE838AD05C2\
+07A3DF4FAD76452979EB99F29AFAECEDD1C63B8D36CF378454A1BB67A741C77A\
+C6B6B3F95F4F02B64DABC15438613EA49750DF42EE90101F115AA9ABB9FF6432\
+4DDE9DABBB01054E1BD6B4BCDC7930A44C2300D87CA78C06924D0323AD7887E4\
+6C90E8C4D100ACD9EED21E:\
+F4B4D0CCD7C89E6E9C076F50353684BA262A00B7ED4C09DEA918F2D55607632E\
+4698771B85B76C257F067D2178AA496B39CBABBC1BDA24498011547D20557728
+
+3A12F8508B40C32C74492B66323375DCFE49184C78F73179F3314B79E63376B8\
+AC683F5A51F1534BD729B02B04D002F55CBD8E8FC9B5EC1EA6BBE6A0D0E74315\
+18E6BA45D124035F9D3DCE0A8BB7BF1430A9F657E0B4EA9F20EB20C786A58181\
+A1E20A96F1628F8728A13BDF7A4B4B32FC8AA7054CC4881AE7FA19AFA65C6C3E\
+E1B3ADE3192AF42054A8A911B8EC1826865D46D93F1E7C5E2B7813C92A506E53\
+886F3D4701BB93D2A681AD109C845904BB861AF8AF0646B6E399B38B614051D3\
+4F6842563A0F37EC00CB3D865FC5D746C4987DE2A65071100883A2A9C7A2BFE1\
+E2DD603D9EA24DC7C5FD06BE:\
+AF743FC4D4A38E1DF12031C88650E2FEB8DD44E5E4F7EB6A4CF7510D9F8ECE46\
+C65EFAD09CE058CC79857FB0BD8E36880BBDA85974CF8E23A900E6BC2C08EE34
+
+1861EDCE46FA5AD17E1FF1DEAE084DEC580F97D0A67885DFE834B9DFAC1AE076\
+742CE9E267512CA51F6DF5A455AF0C5FD6ABF94ACEA103A3370C354485A7846F\
+B84F3AC7C2904B5B2FBF227002CE512133BB7E1C4E50057BFD1E44DB33C7CDB9\
+69A99E284B184F50A14B068A1FC5009D9B298DBE92239572A7627AAC02ABE8F3\
+E3B473417F36D4D2505D16B7577F4526C9D94A270A2DFE450D06DA8F6FA95687\
+9A0A55CFE99E742EA555EA477BA3E9B44CCD508C375423611AF92E55345DC215\
+779B2D5119EBA49C71D49B9FE3F1569FA24E5CA3E332D042422A8B8158D3EC66\
+A80012976F31FFDF305F0C9C5E:\
+24708162B81727BFB94FABE72B10A3B4C199F56C6A802B61567902E4CBFB5F63\
+968CF1C96BD95F89C9713CDCC0C0A8DE917E74D84B2053F5A6CF89AB2EE246D8
+
+08D0FFDE3A6E4EF65608EA672E4830C12943D7187CCFF08F4941CFC13E545F3B\
+9C7AD5EEBBE2B01642B486CAF855C2C73F58C1E4E3391DA8E2D63D96E15FD849\
+53AE5C231911B00AD6050CD7AAFDAAC9B0F663AE6AAB45519D0F5391A541707D\
+479034E73A6AD805AE3598096AF078F1393301493D663DD71F83869CA27BA508\
+B7E91E81E128C1716DC3ACFE3084B2201E04CF8006617EECF1B640474A5D45CF\
+DE9F4D3EF92D6D055B909892194D8A8218DB6D8203A84261D200D71473D7488F\
+3427416B6896C137D455F231071CACBC86E0415AB88AEC841D96B7B8AF41E05B\
+B461A40645BF176601F1E760DE5F:\
+355646AB4447D03309BEC48B9F42BA621A36782A6E4838A77CD2E683CFD601C2\
+02DE97FDB26340C8EB0C8DC71A2C6400ED3B95FE7987410307E8CEEA78BA77E5
+
+D782ABB72A5BE3392757BE02D3E45BE6E2099D6F000D042C8A543F50ED6EBC05\
+5A7F133B0DD8E9BC348536EDCAAE2E12EC18E8837DF7A1B3C87EC46D50C241DE\
+E820FD586197552DC20BEEA50F445A07A38F1768A39E2B2FF05DDDEDF751F1DE\
+F612D2E4D810DAA3A0CC904516F9A43AF660315385178A529E51F8AAE141808C\
+8BC5D7B60CAC26BB984AC1890D0436EF780426C547E94A7B08F01ACBFC4A3825\
+EAE04F520A9016F2FB8BF5165ED12736FC71E36A49A73614739EAA3EC834069B\
+1B40F1350C2B3AB885C02C640B9F7686ED5F99527E41CFCD796FE4C256C91731\
+86C226169FF257954EBDA81C0E5F99:\
+DBB1DFCB8D644373EF832EE88DA144A118F85FB2265D0CF970A9007E310D0499\
+99281C8F817C80D2F893563DEDFA8F82366F19131A04BCC951588B98B224A739
+
+5FCE8109A358570E40983E1184E541833BB9091E280F258CFB144387B05D190E\
+431CB19BAA67273BA0C58ABE91308E1844DCD0B3678BAA42F335F2FA05267A02\
+40B3C718A5942B3B3E3BFA98A55C25A1466E8D7A603722CB2BBF03AFA54CD769\
+A99F310735EE5A05DAE2C22D397BD95635F58C48A67F90E1B73AAFCD3F82117F\
+0166657838691005B18DA6F341D6E90FC1CDB352B30FAE45D348294E501B6325\
+2DE14740F2B85AE5299DDEC3172DE8B6D0BA219A20A23BB5E10FF434D39DB3F5\
+83305E9F5C039D98569E377B75A70AB837D1DF269B8A4B566F40BB91B577455F\
+D3C356C914FA06B9A7CE24C7317A172D:\
+2907154FF72177BEE84B4C0F36EE1816B4018527CDA1D8342C3F9E658E89D8BB\
+3D0C630C6C15FD7CCB923693A9A8BE055CD763C07680CF1E514B59E37E9050BE
+
+6172F1971A6E1E4E6170AFBAD95D5FEC99BF69B24B674BC17DD78011615E502D\
+E6F56B86B1A71D3F4348087218AC7B7D09302993BE272E4A591968AEF18A1262\
+D665610D1070EE91CC8DA36E1F841A69A7A682C580E836941D21D909A3AFC1F0\
+B963E1CA5AB193E124A1A53DF1C587470E5881FB54DAE1B0D840F0C8F9D1B04C\
+645BA1041C7D8DBF22030A623AA15638B3D99A2C400FF76F3252079AF88D2B37\
+F35EE66C1AD7801A28D3D388AC450B97D5F0F79E4541755356B3B1A5696B023F\
+39AB7AB5F28DF4202936BC97393B93BC915CB159EA1BD7A0A414CB4B7A1AC3AF\
+68F50D79F0C9C7314E750F7D02FAA58BFA:\
+73D5B2280174B827D23F50A181D5B14BAA98BACA01ED41C1F6340592EF728351\
+73A384F016A9F3653906725EFF77A1C3DF7151737879955EA00BD9BDE094386D
+
+5668ECD99DFBE215C4118398AC9C9EAF1A1433FAB4CCDD3968064752B625EA94\
+4731F75D48A27D047D67547F14DD0FFAA55FA5E29F7AF0D161D85EAFC4F2029B\
+717C918EAB9D304543290BDBA7158B68020C0BA4E079BC95B5BC0FC044A992B9\
+4B4CCD3BD66D0EABB5DBBAB904D62E00752C4E3B0091D773BCF4C14B4377DA3E\
+FFF824B1CB2FA01B32D1E46C909E626ED2DAE920F4C7DBEB635BC754FACBD8D4\
+9BEBA3F23C1C41CCBFCD0EE0C114E69737F5597C0BF1D859F0C767E18002AE8E\
+39C26261FFDE2920D3D0BAF0E906138696CFE5B7E32B600F45DF3AAA39932F3A\
+7DF95B60FA8712A2271FCAF3911CE7B511B1:\
+CE44C5ED4AF7B36F5081768EA8C25BA1A71890A0FB7991C04140DF521C923B22\
+2B5358ED05AD7DCDB4D2EA752DE791A90003A1F8C55556B5A7C47BF91FCFE755
+
+03D625488354DF30E3F875A68EDFCF340E8366A8E1AB67F9D5C5486A96829DFA\
+C0578289082B2A62117E1CF418B43B90E0ADC881FC6AE8105C888E9ECD21AEA1\
+C9AE1A4038DFD17378FED71D02AE492087D7CDCD98F746855227967CB1AB4714\
+261EE3BEAD3F4DB118329D3EBEF4BC48A875C19BA763966DA0EBEA800E01B2F5\
+0B00E9DD4CACA6DCB314D00184EF71EA2391D760C950710DB4A70F9212FFC548\
+61F9DC752CE18867B8AD0C48DF8466EF7231E7AC567F0EB55099E622EBB86CB2\
+37520190A61C66AD34F1F4E289CB3282AE3EAAC6152ED24D2C92BAE5A7658252\
+A53C49B7B02DFE54FDB2E90074B6CF310AC661:\
+C5DCE72A89807E54BD4A8EF240DCA679955333A27E166483001D250E1FDDCA12\
+BAF513B0832058F1E7B91929226DA79910AAD20B6C4262C4D087AC69EE593161
+
+2EDC282FFB90B97118DD03AAA03B145F363905E3CBD2D50ECD692B37BF000185\
+C651D3E9726C690D3773EC1E48510E42B17742B0B0377E7DE6B8F55E00A8A4DB\
+4740CEE6DB0830529DD19617501DC1E9359AA3BCF147E0A76B3AB70C4984C13E\
+339E6806BB35E683AF8527093670859F3D8A0FC7D493BCBA6BB12B5F65E71E70\
+5CA5D6C948D66ED3D730B26DB395B3447737C26FAD089AA0AD0E306CB28BF0AC\
+F106F89AF3745F0EC72D534968CCA543CD2CA50C94B1456743254E358C1317C0\
+7A07BF2B0ECA438A709367FAFC89A57239028FC5FECFD53B8EF958EF10EE0608\
+B7F5CB9923AD97058EC067700CC746C127A61EE3:\
+42BC28AFD406DC56568834C0B61AE363EEF99CA53F4A26104FC84E57D06DBE73\
+93AEA9A567AACFDBF8FB5AE3D5EEBA953FDA4CDAF09C6DF9B14826BEFA241FB4
+
+90B28A6AA1FE533915BCB8E81ED6CACDC10962B7FF82474F845EEB86977600CF\
+70B07BA8E3796141EE340E3FCE842A38A50AFBE90301A3BDCC591F2E7D9DE53E\
+495525560B908C892439990A2CA2679C5539FFDF636777AD9C1CDEF809CDA9E8\
+DCDB451ABB9E9C17EFA4379ABD24B182BD981CAFC792640A183B61694301D04C\
+5B3EAAD694A6BD4CC06EF5DA8FA23B4FA2A64559C5A68397930079D250C51BCF\
+00E2B16A6C49171433B0AADFD80231276560B80458DD77089B7A1BBCC9E7E4B9\
+F881EACD6C92C4318348A13F4914EB27115A1CFC5D16D7FD94954C3532EFACA2\
+CAB025103B2D02C6FD71DA3A77F417D7932685888A:\
+08075B4359FD064EB852CA1A9135B5ADCE9823B26C70B5A7BB3DFE6150C935C3\
+AA541D127B7502692DE31F640C86C0E5CB45633A37A0415AB837FEB1D1DDE2C2
+
+2969447D175490F2AA9BB055014DBEF2E6854C95F8D60950BFE8C0BE8DE254C2\
+6B2D31B9E4DE9C68C9ADF49E4EE9B1C2850967F29F5D08738483B417BB96B2A5\
+6F0C8ACA632B552059C59AAC3F61F7B45C966B75F1D9931FF4E596406378CEE9\
+1AAA726A3A84C33F37E9CDBE626B5745A0B06064A8A8D56E53AAF102D23DD9DF\
+0A3FDF7A638509A6761A33FA42FA8DDBD8E16159C93008B53765019C3F0E9F10\
+B144CE2AC57F5D7297F9C9949E4FF68B70D339F87501CE8550B772F32C6DA8AD\
+2CE2100A895D8B08FA1EEAD7C376B407709703C510B50F87E73E43F8E7348F87\
+C3832A547EF2BBE5799ABEDCF5E1F372EA809233F006:\
+FC2D6DF44B9AA29D442D630161A94B2CC3B48F26F147C65928C46A6724AF3F20\
+6EC2C6FB5DBF868BD73E9A1900DF7D1099D5F7C8715F1F0D3194C6B44BAFE92F
+
+721645633A44A2C78B19024EAECF58575AB23C27190833C26875DC0F0D50B46A\
+EA9C343D82EA7D5B3E50EC700545C615DAEAEA64726A0F05607576DCD396D812\
+B03FB6551C641087856D050B10E6A4D5577B82A98AFB89CEE8594C9DC19E79FE\
+FF0382FCFD127F1B803A4B9946F4AC9A4378E1E6E041B1389A53E3450CD32D9D\
+2941B0CBABDB50DA8EA2513145164C3AB6BCBD251C448D2D4B087AC57A59C228\
+5D564F16DA4ED5E607ED979592146FFB0EF3F3DB308FB342DF5EB5924A48256F\
+C763141A278814C82D6D6348577545870AE3A83C7230AC02A1540FE1798F7EF0\
+9E335A865A2AE0949B21E4F748FB8A51F44750E213A8FB:\
+0ED14BB066ABBAB817EF207CAD4C414AC9C6539570FA3FFB49E2D9F4139AC7AD\
+03A00B668AD7E82836F60BA75E71CDE45E1C161CD635B5AE4D4B2F605D4D88D3
+
+6B860D39725A14B498BB714574B4D37CA787404768F64C648B1751B353AC92BA\
+C2C3A28EA909FDF0423336401A02E63EC24325300D823B6864BB701F9D7C7A1F\
+8EC9D0AE3584AA6DD62EA1997CD831B4BABD9A4DA50932D4EFDA745C61E41308\
+90E156AEE6113716DAF95764222A91187DB2EFFEA49D5D0596102D619BD26A61\
+6BBFDA8335505FBB0D90B4C180D1A2335B91538E1668F9F9642790B4E55F9CAB\
+0FE2BDD2935D001EE6419ABAB5457880D0DBFF20ED8758F4C20FE759EFB33141\
+CF0E892587FE8187E5FBC57786B7E8B089612C936DFC03D27EFBBE7C8673F160\
+6BD51D5FF386F4A7AB68EDF59F385EB1291F117BFE717399:\
+16DED5B846E2F478C9B55428982616FA711FF0F1565030D597F562BFE4E32C76\
+52222261DE787C554F3D54897C7781575F8972871A8E05DA9425F18A2CF107AD
+
+6A01830AF3889A25183244DECB508BD01253D5B508AB490D3124AFBF42626B2E\
+70894E9B562B288D0A2450CFACF14A0DDAE5C04716E5A0082C33981F6037D23D\
+5E045EE1EF2283FB8B6378A914C5D9441627A722C282FF452E25A7EA608D69CE\
+E4393A0725D17963D0342684F255496D8A18C2961145315130549311FC07F031\
+2FB78E6077334F87EAA873BEE8AA95698996EB21375EB2B4EF53C14401207DEB\
+4568398E5DD9A7CF97E8C9663E23334B46912F8344C19EFCF8C2BA6F04325F1A\
+27E062B62A58D0766FC6DB4D2C6A1928604B0175D872D16B7908EBC041761187\
+CC785526C2A3873FEAC3A642BB39F5351550AF9770C328AF7B:\
+54B8E349B7DFDF7EF6BDF29662BFAD5B9393354E344786895E87D59EE8F7564A\
+336E70B1ACB5AE7C4B18F4488A87217D8F27EE2102BB7C15CCA532B229E2C22A
+
+B3C5E74B69933C2533106C563B4CA20238F2B6E675E8681E34A389894785BDAD\
+E59652D4A73D80A5C85BD454FD1E9FFDAD1C3815F5038E9EF432AAC5C3C4FE84\
+0CC370CF86580A6011778BBEDAF511A51B56D1A2EB68394AA299E26DA9ADA6A2\
+F39B9FAFF7FBA457689B9C1A577B2A1E505FDF75C7A0A64B1DF81B3A356001BF\
+0DF4E02A1FC59F651C9D585EC6224BB279C6BEBA2966E8882D68376081B98746\
+8E7AED1EF90EBD090AE825795CDCA1B4F09A979C8DFC21A48D8A53CDBB26C4DB\
+547FC06EFE2F9850EDD2685A4661CB4911F165D4B63EF25B87D0A96D3DFF6AB0\
+758999AAD214D07BD4F133A6734FDE445FE474711B69A98F7E2B:\
+55A9BD64C942E46F7BFE916BFBEA173433E17CD9FA58EE3F615B7747944E0ADE\
+18E432D605CB1B2D0D3F168F3A1B792B97062834C33AB8260D63D06CCF6DE843
+
+83AF34279CCB5430FEBEC07A81950D30F4B66F484826AFEE7456F0071A51E1BB\
+C55570B5CC7EC6F9309C17BF5BEFDD7C6BA6E968CF218A2B34BD5CF927AB846E\
+38A40BBD81759E9E33381016A755F699DF35D660007B5EADF292FEEFB735207E\
+BF70B5BD17834F7BFA0E16CB219AD4AF524AB1EA37334AA66435E5D397FC0A06\
+5C411EBBCE32C240B90476D307CE802EC82C1C49BC1BEC48C0675EC2A6C6F3ED\
+3E5B741D13437095707C565E10D8A20B8C20468FF9514FCF31B4249CD82DCEE5\
+8C0A2AF538B291A87E3390D737191A07484A5D3F3FB8C8F15CE056E5E5F8FEBE\
+5E1FB59D6740980AA06CA8A0C20F5712B4CDE5D032E92AB89F0AE1:\
+FDE40A74217B586CCDA78C27C1F6920D69B755557942CABF37E7C409E27A29D9\
+1A41D9B5E8D99F6E908BE4517F799CEDF344B195077125D7C85B71429370055E
+
+A7ED84749CCC56BB1DFBA57119D279D412B8A986886D810F067AF349E8749E9E\
+A746A60B03742636C464FC1EE233ACC52C1983914692B64309EDFDF29F1AB912\
+EC3E8DA074D3F1D231511F5756F0B6EEAD3E89A6A88FE330A10FACE267BFFBFC\
+3E3090C7FD9A850561F363AD75EA881E7244F80FF55802D5EF7A1A4E7B89FCFA\
+80F16DF54D1B056EE637E6964B9E0FFD15B6196BDD7DB270C56B47251485348E\
+49813B4EB9ED122A01B3EA45AD5E1A929DF61D5C0F3E77E1FDC356B63883A60E\
+9CBB9FC3E00C2F32DBD469659883F690C6772E335F617BC33F161D6F6984252E\
+E12E62B6000AC5231E0C9BC65BE223D8DFD94C5004A101AF9FD6C0FB:\
+A4EB74B9A9075E138375E20643E5143CD1D43E5D90F4794341514BA4FEE442DB\
+4204DB5E07F431FE27B863899F584AA61B6AC132FC03964E57B725408E70B7BA
+
+A6FE30DCFCDA1A329E82AB50E32B5F50EB25C873C5D2305860A835AECEE6264A\
+A36A47429922C4B8B3AFD00DA16035830EDB897831C4E7B00F2C23FC0B15FDC3\
+0D85FB70C30C431C638E1A25B51CAF1D7E8B050B7F89BFB30F59F0F20FECFF3D\
+639ABC4255B3868FC45DD81E47EB12AB40F2AAC735DF5D1DC1AD997CEFC4D836\
+B854CEE9AC02900036F3867FE0D84AFFF37BDE3308C2206C62C4743375094108\
+877C73B87B2546FE05EA137BEDFC06A2796274099A0D554DA8F7D7223A48CBF3\
+1B7DECAA1EBC8B145763E3673168C1B1B715C1CD99ECD3DDB238B06049885ECA\
+D9347C2436DFF32C771F34A38587A44A82C5D3D137A03CAA27E66C8FF6:\
+C1B250A1AD9CF163C56A59847A1742694FDD4258FA4BF534BA8E1DA108166937\
+ACC7E6FB7D4ADB0B70F3293CA678B5F56C18B4653545C2F283801567AF73304E
+
+83167FF53704C3AA19E9FB3303539759C46DD4091A52DDAE9AD86408B6933598\
+9E61414BC20AB4D01220E35241EFF5C9522B079FBA597674C8D716FE441E5661\
+10B6211531CECCF8FD06BC8E511D00785E57788ED9A1C5C73524F01830D2E114\
+8C92D0EDC97113E3B7B5CD3049627ABDB8B39DD4D6890E0EE91993F92B03354A\
+88F52251C546E64434D9C3D74544F23FB93E5A2D2F1FB15545B4E1367C97335B\
+0291944C8B730AD3D4789273FA44FB98D78A36C3C3764ABEEAC7C569C1E43A35\
+2E5B770C3504F87090DEE075A1C4C85C0C39CF421BDCC615F9EFF6CB4FE64680\
+04AECE5F30E1ECC6DB22AD9939BB2B0CCC96521DFBF4AE008B5B46BC006E:\
+B592380AA42A1BB56301CE763D3664B9356F1EB900241E0A23E5AC9AD474A7A1\
+B367926BC3E5F4CF8E3C5D85BDADFCEAB0FB6EA8D05EDEB50C869FD271737571
+
+3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5\
+623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A\
+15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0\
+A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764\
+B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43\
+C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D\
+817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08\
+5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1:\
+2200D5458E4948BCA7A818CEB2CEDD3C3ACBEA67DAD5F61C134724F884F140E0\
+B68898E8E779ED454E3C8151218B46E22E96472199E87999FBDAC380E1FBCA2A
+
+724627916C50338643E6996F07877EAFD96BDF01DA7E991D4155B9BE1295EA7D\
+21C9391F4C4A41C75F77E5D27389253393725F1427F57914B273AB862B9E31DA\
+BCE506E558720520D33352D119F699E784F9E548FF91BC35CA14704212870982\
+0D69A8287EA3257857615EB0321270E94B84F446942765CE882B191FAEE7E1C8\
+7E0F0BD4E0CD8A927703524B559B769CA4ECE1F6DBF313FDCF67C572EC4185C1\
+A88E86EC11B6454B371980020F19633B6B95BD280E4FBCB0161E1A82470320CE\
+C6ECFA25AC73D09F1536F286D3F9DACAFB2CD1D0CE72D64D197F5C7520B3CCB2\
+FD74EB72664BA93853EF41EABF52F015DD591500D018DD162815CC993595B195:\
+5D44716E5D773B289E6F77E7A0C87D11467D2EAD2C06E3FD6242FF051F4590EB\
+E3712D83176861D93FFAA14378C17AAB0758C04CEBF054C6CFB7BA973BCFC3D7
+
+3139840B8AD4BCD39092916FD9D01798FF5AA1E48F34702C72DFE74B12E98A11\
+4E318CDD2D47A9C320FFF908A8DBC2A5B1D87267C8E983829861A567558B37B2\
+92D4575E200DE9F1DE45755FAFF9EFAE34964E4336C259F1E66599A7C904EC02\
+539F1A8EAB8706E0B4F48F72FEC2794909EE4A7B092D6061C74481C9E21B9332\
+DC7C6E482D7F9CC3210B38A6F88F7918C2D8C55E64A428CE2B68FD07AB572A8B\
+0A2388664F99489F04EB54DF1376271810E0E7BCE396F52807710E0DEA94EB49\
+F4B367271260C3456B9818FC7A72234E6BF2205FF6A36546205015EBD7D8C252\
+7AA430F58E0E8AC97A7B6B793CD403D517D66295F37A34D0B7D2FA7BC345AC04\
+CA1E266480DEEC39F5C88641C9DC0BD1358158FDECDD96685BBBB5C1FE5EA89D\
+2CB4A9D5D12BB8C893281FF38E87D6B4841F0650092D447E013F20EA934E18:\
+1E4D41591C38DAAFDF29E7E2D653D7CB304537A98DCCB7CBAB24F315C85B5031\
+F4DD511F06526E645F73CDD21BEF8060731A76D0AA1971C368BEDB8C8A71C379
+
+023D91AC532601C7CA3942D62827566D9268BB4276FCAA1AE927693A69616526\
+76DBA09219A01B3D5ADFA12547A946E78F3C5C62DD880B02D2EEEB4B96636529\
+C6B01120B23EFC49CCFB36B8497CD19767B53710A636683BC5E0E5C9534CFC00\
+4691E87D1BEE39B86B953572927BD668620EAB87836D9F3F8F28ACE41150776C\
+0BC6657178EBF297FE1F7214EDD9F215FFB491B681B06AC2032D35E6FDF832A8\
+B06056DA70D77F1E9B4D26AE712D8523C86F79250718405F91B0A87C725F2D3F\
+52088965F887D8CF87206DFDE422386E58EDDA34DDE2783B3049B86917B46280\
+27A05D4D1F429D2B49C4B1C898DDDCB82F343E145596DE11A54182F39F4718EC\
+AE8F506BD9739F5CD5D5686D7FEFC834514CD1B2C91C33B381B45E2E5335D7A8\
+720A8F17AFC8C2CB2BD88B14AA2DCA099B00AA575D0A0CCF099CDEC4870FB710\
+D2680E60C48BFC291FF0CEF2EEBF9B36902E9FBA8C889BF6B4B9F5CE53A19B0D\
+9399CD19D61BD08C0C2EC25E099959848E6A550CA7137B63F43138D7B651:\
+14DAB99E5924FBF164A08C31EEBBCAFDF1550DDF51A9E617DC920158360AAD59\
+4F894CAA950CA95130946C1DA6281B467EEE0C7E41FAED8A062A19662DB3945C
+
+20FF454369A5D05B81A78F3DB05819FEA9B08C2384F75CB0AB6AA115DD690DA3\
+131874A1CA8F708AD1519EA952C1E249CB540D196392C79E87755424FEE7C890\
+808C562722359EEA52E8A12FBBB969DD7961D2BA52037493755A5FA04F0D50A1\
+AA26C9B44148C0D3B94D1C4A59A31ACA15AE8BD44ACB7833D8E91C4B86FA3135\
+A423387B8151B4133ED23F6D7187B50EC2204AD901AD74D396E44274E0ECAFAA\
+E17B3B9085E22260B35CA53B15CC52ABBA758AF6798FBD04ECEECED648F3AF4F\
+DB3DED7557A9A5CFB7382612A8A8F3F45947D1A29CE29072928EC193CA25D510\
+71BD5E1984ECF402F306EA762F0F25282F5296D997658BE3F983696FFA6D095C\
+6369B4DAF79E9A5D3136229128F8EB63C12B9E9FA78AFF7A3E9E19A62022493C\
+D136DEFBB5BB7BA1B938F367FD2F63EB5CA76C0B0FF21B9E36C3F07230CF3C30\
+74E5DA587040A76975D7E39F4494ACE5486FCBF380AB7558C4FE89656335B82E\
+4DB8659509EAB46A19613126E594042732DD4C411F41AA8CDEAC71C0FB40A94E\
+6DA558C05E77B6182806F26D9AFDF3DA00C69419222C8186A6EFAD600B410E6C\
+E2F2A797E49DC1F135319801FA6F396B06F975E2A190A023E474B618E7:\
+09A1766C860771A5ADEA9E01F811DEC3C45B58915EDF1CFF452A6B67A01C67D4\
+F2C51BF1FBCB7D0B54018E7DA3873093F35448CFB666A18428A964638853FB5B
+
+4FBDC596508D24A2A0010E140980B809FB9C6D55EC75125891DD985D37665BD8\
+0F9BEB6A50207588ABF3CEEE8C77CD8A5AD48A9E0AA074ED388738362496D2FB\
+2C87543BB3349EA64997CE3E7B424EA92D122F57DBB0855A803058437FE08AFB\
+0C8B5E7179B9044BBF4D81A7163B3139E30888B536B0F957EFF99A7162F4CA5A\
+A756A4A982DFADBF31EF255083C4B5C6C1B99A107D7D3AFFFDB89147C2CC4C9A\
+2643F478E5E2D393AEA37B4C7CB4B5E97DADCF16B6B50AAE0F3B549ECE47746D\
+B6CE6F67DD4406CD4E75595D5103D13F9DFA79372924D328F8DD1FCBEB5A8E2E\
+8BF4C76DE08E3FC46AA021F989C49329C7ACAC5A688556D7BCBCB2A5D4BE69D3\
+284E9C40EC4838EE8592120CE20A0B635ECADAA84FD5690509F54F77E35A417C\
+584648BC9839B974E07BFAB0038E90295D0B13902530A830D1C2BDD53F1F9C9F\
+AED43CA4EED0A8DD761BC7EDBDDA28A287C60CD42AF5F9C758E5C7250231C09A\
+582563689AFC65E2B79A7A2B68200667752E9101746F03184E2399E4ED8835CB\
+8E9AE90E296AF220AE234259FE0BD0BCC60F7A4A5FF3F70C5ED4DE9C8C519A10\
+E962F673C82C5E9351786A8A3BFD570031857BD4C87F4FCA31ED4D50E14F2107\
+DA02CB5058700B74EA241A8B41D78461658F1B2B90BFD84A4C2C9D6543861AB3\
+C56451757DCFB9BA60333488DBDD02D601B41AAE317CA7474EB6E6DD:\
+CD50496D8998A0F2F2B1AEE49DCCB7423994912F1DE493302D94A11CADAC731F\
+3EB855C20FC645E711E181FB1BCB7252CB6F8EE3D7119EBD56EC219BEA011FF0
+
+D1890B4704E169C28E44DDF62A1091450404910539FC2DAEB26E8ACF4533B024\
+E5215C2D02820DD8FB2CFC1743955CBACFF0F8F35DFBB5E3F942F36247F68211\
+D518F3F601AAE12A1CDC000BAB43D4C973F287E80741DD1FCF6C34F2E6B4B6C3\
+13D01C4FF3CBF9166F26946F18EF2D58271BA9233F09A6B77BFD4F48B36EB3D7\
+3D1133C4F842A7DC3907F680B0B773242C11E3DD973A44327EA7CEA9C0F8E07D\
+682B6651E506B587559FE01ED721000BAF570A16FBDD9EA29FA3DEF4BE912058\
+321A8B720C5C102E48A6E7ED6F8838D400DD57D06EEDBCD15323F86D855C94B2\
+1E41B14EC9E1BBC8019211FD88138C91F9ABBD9BB3914D26C1DDC21673D2D512\
+63B39D66E741D924CF2B192C5D2C1A140126A3D64A2C77BE6C2C6EBE8599978A\
+E90BD36CBB9AF64D078910C4094AB3BF399C34F2AB8EF843E9FE1BF88BF443BA\
+21E4377E5F49C07FD9653B526E14562237F02D11B904BCA6AC31AE721A43E3C4\
+910A24AF6F4D80C031C109FC0FE49F15274BCA92BDA04C3B4196C192F6CE489C\
+63A806ACFC895AB52CAD657C1783B528E12D0ED856E1F8FC91F2AAFDFA0A9249\
+8D68530772EE73B359FCF1418D1096C46B34DCF90E5B468BBB2970BECBD70089\
+CFB039D64CC50FFF5EEF26384D34F24515A6558B06A1FDD88F1050C5BD78CC6E\
+D83D4C2B0E882AEBCF84AFB0430D0BF09F2FB42B8B4589158093A7709AAE75A7\
+90910E211EE1333FFB6FD80778DA3BF73858978E9DD647978841B18001DBAAEA\
+43CA0C0A03DBB9BCF30CE76A6F4B2CF2A9B6531B3E4051E7E05090CD421BC66C\
+4731E7122AD129FC42DEDC83BB460E3F889992FBD3CA072686E56B72C720FBC9\
+8D723EF7F247286F77CCDDC728738E941B1A74D4F16671C21FDD5643A115DDBC\
+B88EE7EC67EA66FD2BCE718DF6E085D4B5FC71A72696636A8F7B3A68AFA51A89\
+6771FAAA7F1F827430AC5E8089DBC0D4175E1B22A057BC5F1724EADC1A41E78F\
+A3ACAA8B97E5F2E19EF9D59AE12B04E7F0E8A621E098A66910E2A5ED2102B824\
+CD3EA044A854F1CD0B33E61E7F737414B2953549F25DD34D19AA1981DE7CD564\
+9FF6C6364A4F25312EF62395A747AB88AAD722C05AEC40DEEA8EEE5E779EF458\
+A68840BC6BD5D29AD40F98B3AE010B6213372ABB7BB8B8:\
+A36AEE15B7942102CA6ADE2796C36CCD8EE2B76BDF1437B9A4C885391F680B91\
+7A95CA7DBA79CE46CE75C675572A92A047909521EEB3AA994FF8AC81C524DF25
+
+4FA3DF1DEA75AD4B9C379206A95FED930000482E5B683FD2B17DC8E7D5C4BC1B\
+73186CCC13C9FF2DD09FC1D4F68034D120E84CA73A00B71A3B46D1EFC6FF88CF\
+2EDA65810B098CC5E651D9CF064E87076D5A871849F3B405D3D58EF5B1F10520\
+A9FB4FC84A81A87B13DBFBF9D8674943E28C257E46D8AD7BE1785F1DC7C9B1BD\
+574AD1DDA48F0255C853D2490BD3D63DA22A8369CFD02594999A2EF443308FB8\
+298266A11EFA177102C75DC674E89FC9DCC1A0D3C863BC26141102175D2678EB\
+6E13D90BBD9A5EB89AE8C0CB47D7F340D3D32042A2762BC9BF2B40EB40E87FB4\
+2610FE7E357051F01494704FBFF73321B47301A0799B7EE3FE5E62200F397A61\
+ED4509A62F7106ED0EFB0ABD6AE9E4A1FE9B02C092DCDC75015CF602F3B9A898\
+8B609E6C0D1C5C3E219FF57875C2EF01615F89447EA602DFC94EEC17A398C014\
+BD346691FE209A002771DC8164422CD166AFB457A8B3071282178A3EBD201D9B\
+07B27E711E7EE7D33AA5210ED4E4E92486775D14A6CED092E34A7AC826709399\
+48FEC149F9C018FCAAD3FC597D315713F44FC5E1725F448ECAED40E8D841BD02\
+F1E81C019B08F99412E360C0BD378391C67D964B47F50C26F0A483ED66402361\
+6B0FC9AFE43620DBE9CCFE070EF295C049EAC754C2123130C6B2C0232F6403AA\
+7F0DC35A5999BF95D34AD612234C6289277ADB60E4F72EC2DF570F05395B3BE8\
+A0A3C78B732821AA08927C524E15D65F66A3DB8C1C96FB70BC0686AAC310051F\
+469FC5EF880C0F66947C1C328F97684EA24CBE63BAED8D114F40507C2901034E\
+6AB3893F366D53F1CFCA309309218CABCECA4722FA9CCBC7249B87C12FF8397F\
+40487EB00082E7F551D27E301C3BC7B5389F7042534BF7E692DFEA4DA24F7C34\
+B8D2FF145F54B517FC97134EC5AC2CB925C508D7A6BD01FE7B764648274972BF\
+08560D30802E0EB7EDCC57AF4797BBF92E8688268606B0F1BC901FCC22136281\
+665EC16393FA9601C4FBDB18CD1D1EE382BC07973903E91FFA87399D1141D49F\
+4F0C064ACF3AC9897891DF10BCA0116F2C3FEF180FE6A8E937C478F2EF293AE9\
+186DCB1F76B6E48101DF64E57EA7C64C5C0025E221C8F5CBA5CC92D9CEC62814\
+0996B26D17F439B780F59A999301122F82D0495F8AB5AE1EA5790F45E992DFE0\
+0D5F82A7FF1354AEFDCEFC0D2D1731D22FA2B75AFD4FDA25AB194055FA962838\
+1055247C8C7587D22E73C60136C4282452D47AE03AA035FEBC26FCCD42A1CB79\
+CF866DB6418A49FD8261E877DDBB839CC39514DDB87A8A40D795532626FEA4A4\
+C35D13E028F9ED1BC09B06BE999B8DDD2258AA0596BCBBF72AF67E10BEDD58D5\
+99B8D577A583D676BF5561F80CE5E9528729A92DF578FE75DBC70474B75747A8\
+D55DE70E57BDD62D4344DC2115ED4DD62F1FC98BFA1E7421FC0700025C46D0ED\
+1BEF35C3B778563211B9FA9E8BA4BBCBF01C2FB626AB7EF325CE9F468DF2CACD\
+B178D36557CD85D542C067C289E926C1EA2F20ABD329E984168BB6DEF1DDCCF2\
+14DCB6A53AFD462F0E7E7A19E8C88F049244125A6D7DD41E58BC9B2FF7FA2478\
+DF76AF73090CB1AB59E388BA20E2C297C967737A1AF61793B68ECD7439444C48\
+E28E2D09C48FADA5E0D1D15E5B340A52F8B3B854CCA479F0A598445E14F53B3B\
+A36891050C79673DF3E2B5825C955A29E5C9A22F3991D0AA785718CFEA1D2385\
+F8E47E4A75ACBC7988D0558D541D71C4E6C5F1CB15B60CEA0C34A67BBCE105D7\
+A896025E0254DE7D7AF724C9027D44B8642192A08AB8E1EF3046DDA6014DF7F4\
+C9E63C635E48AB2E70B640D480998EC9357E665F99D76FE5529EF23C1BDFE017\
+C3A66CD4EB2DDB42EF85EA0CD65534:\
+C0676C3390631D76AA6E5779716E3CFA579B52C27F31BEE78127803C08152EB7\
+60FB7D7301154C2A52C5CE39D8E237C0E38947A9554689E72D0C20AC6EA8762D
+
+523DE8B1F4CBB65E81FF0B6CCD6EB8EF0A0F0A691ACAF4A77F25ACD2D66AD4B3\
+EFD25BE70308853C094412A518A32020E3020A9F6AB32F0CD60EC0D7A194917D\
+6C457B168A54A4B46F7B0D0C71BD61CD202F4C718776A701E0770B0EFA054187\
+70F98E4E79CD066366FB3300E8BE359A98B82B764BC2FBBF59C7E8F94A157B01\
+C6C7577B1428138CD422BC47330F8ED99F4C0AAB0D984287445539839389EE08\
+D6345108AF26ADED0EC1D7BE774CFB8C5205DFE07CF6CAF8C1AFE37C7A2E4FE6\
+013B93EB2463DE4E0971C7178D6A76B16A0E8960C984CE8BBE71B3B466EDF044\
+5B835F09414D01F14C7B6167FF78FF118127BBD5F812C27FACD57B3B120E2BCF\
+E87315C7A92B82EF5D50CA14A7174D1BEA7E056523E055A6AE42EA3765094E55\
+44E5ED003C989C2F98F38A17E3DDA74DBAF9C669A319638A2698B0E4A611480D\
+8AD3CF016792ECD1034925F42B9811A7214D623D047ABCA31997DDEB03275F80\
+DD21F40DDC80616E7AD3D481E8EBC0A1A6A398E16A78369215541ED10B75671A\
+DEB1AAE6E11142A1CF665FC1B7332DFBB0E10C21A2B48F78E57319AC9C58DFA8\
+B1C2548E2979EF1ACCFEB215AFCD6C2C1B46FE97DD491758378330EFFC728366\
+1D2CB84FA05281E9E517408508D24D042E7B9BCD34DB87CE972E4CBCDB98615F\
+B93093369DFEDC782F44BCD03E81CF93051318B2401FF29F753A264BDA65AF19\
+9E3FCBB8B5D39C838A67D6C7A3DB046DC56C323DDBB5340CBC229E47CFF8C9D2\
+9B7A49AC0EC8C1440AE498C7D150EF91C29BEA7DF3EFCC2871A13A1D72D139CB\
+4603D9FFFE85F6DDD544850EF63C3944FB35DBC00D4308CEAA6394B6E23F650D\
+323F8F7EF50DDB68F1486EABF989BF44451F620EC9485C0B52D1415D3C909A2C\
+FBE9D77DB19D069D33BAEE4D77292E63FCBF65C1EBA24BFFDDEFE95211EF0AAF\
+8ABFDA9F94445E582976F986F5382CB669506AF2B4A5A0C43000A3C72C5CA4AA\
+CDC9D3D39FC5C492A393B6C341B86DACBBF6BA8B465100CC683EDB2D9B9F83ED\
+F9C6A32645F51CC79ADC22A52A007BAACA618BE35E356D1FD1CFBDA73F1ED092\
+53039DEF609450FD2D5943B9CD49CBD52A318EE3510D7CF3FD8FB388AC6CB9C6\
+EEFEF3D3CAD8501B91CC04A888D33E16D6A4C9666F5F5F3B257193F2B46DEDDE\
+11842909D8C48ADE57775B0B272E2DC9CEF1A083EB2CE58F4D1F211922FD6ADE\
+D1B82FE6F5B11251CD396E5A3666ED9626036E4E356231C146BBA0A91AFD3648\
+EB7BFE0B9C14F15AF2F92309826F468945CAD0AC422DE3D6A773B76178422107\
+CE0270E7F580B5CCEBA82CA0184AAFA8341141E65E39859885768FBC5CE63B96\
+5A0604B659E71D9DA2C7A43646088D8071D76926163AAFC69E25355BB0A222B7\
+B2DA9F0A20C021ADC462E905A9C3BF31C16D87FBEC3F014F3957A720F1432E17\
+41553092052FB58A198640479ABCAA51B104CC93E2636E1460643EA812BD44E8\
+19C2166EB6B349BA5BDEBAD59078910B5C22A56F004B8D9E4B1224D8D204B48A\
+BE7355548A402736C5CB110F3A1476ED631FF168F4F3EFD89B38DE4751536548\
+647523D334FAD7CC2D142973F2DB3C1FE08FC5CF83F9F2BD2DAA524B37864816\
+AF29EE05951FA09D1C51D9D14EE4F72FD7BBF18B1A724FF5A0958A063947C430\
+142AD2356E4400AAECA442E163372A8F1CD36E2DB988E7781165E5D4E7074ACE\
+40858E8370E883694AF09977704347FB735C8717C42BC4EEEB2AAA50DFE637C6\
+40909CE379BFB9E2608F88751377038D1669F248178AD580A908D7A1B8DCC7E5\
+3E01801F1E485B5893F103F03E0F53B2B1440BE95644D85AA7F6EB7EDFBB4665\
+2196695EA23C08573397B111FF909025E20C5201293B4D223BF7AA01DE7CB28B\
+94714370434B9588097E2401B62C7A0DEF1FBF89809E810749FD3CE9EC3C07CE\
+4BF4C43DC966429B2BEB4D711FC6C448A12097B36F1E6817EAF4937A983F85D9\
+CF3E62CC1B2AC6AE1EC9EAA8CD8EE2C3322239CFE5DB3D4E8786282E630A7D25\
+9C2FEFECA03031C960A66A71E436A3ED6F2F3CFAB4BD77C660D14205ABF606FE\
+561A346F7D849B69475AC9F6822D80B9A2E56D5D495E4B309B0EA963C9FC5C7E\
+F94B217EE5337989AFBC7107D233A8B362AC27C4F69DF9E191CD65AE97D6EB9E\
+5484EB6F10349575E4CAE51452380151F902415AC9CF42C824EB23C9541D2DA1\
+C26DB85F53CDAFB06A12B8393CD580A8E494EDB6710C720DCAE30832967E33E6\
+303A92B1DF0841D7724284FFD2E00B95C6D623B168D21AC1BD3C675EDA33182A\
+2C22370998DE1E5EB905372CC6EF32D5B765F5C94870DF4842D011603BE4CDB1\
+C227E41EB2F2E8542CD325884FEDC9C5C7BB07A92D20D64B836215C59F162A3D\
+A8BB67D6FC13FEF97CAB6ECB8A29E431A6519A6261C4521CCB90E6E609869E6F\
+E398404AE047F64EC4263566DEFEE66329DD40AC985EB8A08D26529A544891B6\
+F57CC235C63C09057AB6B6ED720EF41A3C9AE65768B43F6DCF4962A103DD93C2\
+13171DC2C9194E43265C689B49331450281A3FEBC618D1AA4D65A135137051FD\
+46B568CE294C89:\
+99F6BBABC6C82A5E093DAC4A81360C22982A105A4F9F16FB5F4D3557C571DC3A\
+1178CDB18287E8A8BAC028F9D9F246E046B646C079A4442217BC6F748959E7E2
+
+F5080D4C59E804BF8F34B334CABBCC7D32011BDE3677F4B9069416AC204114CD\
+9DA7A0ED0F4B4D8344416336EEC15553EF526B6DEC267B1242657DD0B508AF81\
+FECF9CFF9C82A6A7A9539814DD7E097615EF15373836B5D2F765CC8D5F82E904\
+49F13AA741D5EE2FE63898E55ACD85116846807606FE1E2E29F98F9940B067D0\
+D1DF01F080211B2EE4B0A30803782A7BC2EAFDC5EBDBA91EB05F7D7DC8E34BF6\
+D44FEC05824F53418F235FB64E899EE147BCB403C8855E94AF378D182D79C3EA\
+F977CB4E9D4A16D990A6C388CEB567B97785E6F2BC6745102B99AE765E960B6B\
+32BAF01E2379CD6ECB74D3E1A56552F5976DFE5C742BC92BE596CA742FFC3D0F\
+A032AC29F9F7C1A5C43BCCA62DF7D9DE35D0C7C179DB2E1AA255CEDCCA55064C\
+2049FEE1AF2CE5EF696ED4BC46B7C55BDD51F2D44C8713FB2475C0B85246AC01\
+03CC3863B7EB026AE076A600313F6FB40A4DF62A2AF81B7E917951EA870ECB31\
+B3401928B5046D9A1E62D14B30FDEBAF262868517318FE17EC3C0D52524F4412\
+0ED8ED3BA70C643300CD0BC70DA72C964A88F52C3A91EC20BFEB5CAEFCD4D9C7\
+685D8407476B5F34676C5EBD1E88A6CFF1C625322F8CD59B9ED60CEFB21F9491\
+B95E72791F7AC7EAA3C16159FE9DF7A989ADD6C2282C47585E11397EDA9F47DF\
+2B40166E03BCDD6186B46C6835118268DDBEF19A28BBADE1BDE0228FFD7E8B3C\
+3C598D89E24B8CDEE79C940254DE26CC6814BA2722E42F7571600B7325E1FF30\
+0251D52A895B8CCBD049B2953B8D231445F68F7C26EC25A4B8695C8AC116F736\
+BE939EDD762C9B4743E463C9B9B2F88E0BC0CE78781CDDC3BCA825ACD463C7CA\
+C2AA6C430BBE820EA94AF9A40B1B5C006E9641A2FFA6E427379E1AD49C81B983\
+20B3431FF0030DC683D61026438BC6A6D34B2C73704D9F62EAEB13ABB3E4B056\
+2B4E0482CD6B2D7AEBC0367EA29A88F4A76F3D76FA1197E1DCA92C8216C84C1A\
+F9B8C78C9E3A7799A4A79A783033B0F5547E8E75E69CF3615AB04EF989FE1A46\
+3B1672C571D50AB56972896E8A50C242F22C7F6E27CA4CA793F627E79608680F\
+5421B28BDD2589F05E65430DF774EE873FCD1234064F7A33CF5A1FA4E368137F\
+F9C1597F1FA0FA36493F20538077669EADFD3B06F788C912C715FB5D334DB6BE\
+D133A8FDC40F5496E66AD63881F0BA3727416715865253DC5290327B515BF68D\
+A188DD5B4B0EAC7CA712CAFA8FCAE0C5503FE58A219182F1C30DA6D0C19CFEE8\
+97B7D837C97996A35F4CA8CF0537A01D17E7DE0CC9C129E4DA0ADAF1FDA85030\
+DF9127BE628263B0624F372C47C3AC87EB945A57F5C732BEEE81A74030017989\
+92F3DC944114FF3D54C4666AC5AC8C98D0D5596CBDEB420665F5EDAAE747D54C\
+F7EDD37B162E372249D135938CF17D174D12D88279CB4C32BD6F018C766DA698\
+3D4EA51D6BD8FF0A9B34E9A93BBDA70CF1B4B867D60A74811FD98D52FAA559B5\
+2C755CB70A76C94BD19654CAE7017CCD70222BF08C5D7AD1F5E4E6344FDB3ABE\
+703452C29A696F39F9826ED8BC510A4A148E5BF8A5DBE6B82D7220164F08011C\
+05AC5159D52CE9D45D758B645BBB248C2D341DBEFA1F8602C5D458A64F38F3B0\
+4DB39089807B6A10E1BB52770B92CE72E2D3BB0C2241CDED35054B84558D1CC0\
+99EF7B2296951951D5B6A22F93BF962AC5EF8FB55EC6CC2B316428EDF12078ED\
+1B66D525D022819CBD489E1BEDB02FFBD507D55F9B5D4E22F6396EA233453754\
+688D20151A09C70044B8A5A9AC033C3C3B847AD833D5C05B33407666EE82F958\
+1DF9034EE15A9CA67D52F1D9B634B84C1B8BA9E515F1F060A5AC5CBAE2DE75F9\
+4E112F7198E239DF08D3103F065627438995026DF511C6E5BFDEEE5667D511D4\
+181850C7C5D179107C1B86D24D5532A88A4149A2810DCAE73731B0E1247281A6\
+FD31613DF6891B4C17B7A6A9AD9B77468254B93F85958AA0F01CEFC10B25169D\
+C46E035D3F24557B4BF0E7D60174219108D916FFDC55E25BFFD9809EFD058E12\
+C14F39C69D8FB73D3EC6458F47F2F8DB901BA76C86550B11B54D0641D4DB3EB0\
+00057DD00F2E511FB7A47E959A4402A3AC5462234B40B184020FCF7A0396C4D0\
+0A987C8741A4537BC17102A5C42AFEAB9F71EA66ED4CBC7B5EE682FF04F56F4B\
+A1EA0BB326C4089930F9E3F3FFA3E06637CCE32113881A06CC3A13837448145C\
+2BD01307A580FDBC385D8F46FB92FFEDBC8918D269DD1871164D4B3E2023441E\
+C8B99C82A5F09821CDDF6B38C9ACC3BF3A38D5628016159588C33EAA29D9463A\
+537C000A16AD8C177DC4CF716E625F46FC4CA8C19FBD8EF320F1D680639195C8\
+B195B0A02738E0665F4190D6287E589CD6DD45B9E8CC23B08E1681BFC6F66B88\
+DE6B091E825EA4BBFBD697E10BC407570AE4F2A3EBE569554639C2B8E051656C\
+C30C837F5A92260EAD1D552B45801B6D28134166796C87F900225CFDC3CC49D7\
+2DFBC18D8D95B1E160ED3CAFD5C3467D48AFF87402CBCB1E1420E3FCB588AA19\
+C8F42753B59DB6FB6A9FDBA127CA806DBA7DD97F2488FC2E438EEF57A4CC85B8\
+8DCFDE76AE1FF61225A1CA8BF4A14F729950322EA681B16D6492902506702DC8\
+F348E4D3AE7FB55FAC1231FDE82091B34F1791B6AE37587B10325F6FF5E23B85\
+5845B86EAE90785B9D10D90A16644D01BB626F343B908A9591F4069B21822CA4\
+ECF985C1E710475F33DF9AF4764CFB0FFE649063775338F15BEA7CFF29F16467\
+8160960A80ED148C9B7FAA58E9139911D3DD9536F69646F718F083DC9029D629\
+4FC4C607688AA75AF350AC2C0B001A157D023D73D86ED8133809FCB9592D1208\
+9CBD7A1BB6BBA882FE227C09A53FF088907CB4BC2FB4B7F62D41D3D397C4FE0A\
+D12BB3964370E21712951C679814D506E738C0201E42181D231136A435AE0397\
+B61CCBC5E8BBEBF8EA77C8BC48BD6211F29248F9D498D818E2B544D28A5E60BA\
+727F32EF4BA2707962230C900076FB764D0ED5CE078C9DB14DE894BBB836C6DE\
+9E83202AE89F9A8D8CB0341E1C81B5FA8B16731B8E231E969C0F1EF95336D4E7\
+3EAD6DA23DE3AD1EB608ACCE4D4D93996DD76EC1F5F2C576F6B3B76E07BD8A81\
+0FF5D88B00FFE48C42700B61CC499336E7FB57AD72FF44FC631C7222C9A3D1AB\
+F6E77B5ED7FE2F7228FED6C849BF7142C4103989A80F7C15642AE61650CDCA7E\
+854EB25E9E72F4C3E3768E6CCC8BFD556B56D3507EDDE9E5C331DDEA75568B07\
+813D20E8F4C9547838ED28448F2E67158ACF0C00B131473847816C5E2DC215:\
+5F3B32AFE1FEDF7258ABC6C34F89CE73A1668A97E170CC4905CA8B15C5919AA6\
+F45654A3C74FC9E13CE088EC8C5C76D06FF94D64691C7477A65EBF058D1A6FAA
+
+08944CB473B828B118A31986DB67FC757F238182E790553404B792AA4F0095A6\
+A83291E287CDD16521A3AE8C48F56FBC909DFCCFAA7BCC570C2159F26592DCD6\
+B15BC4DD55CC05595AC634B2C3DE15360B0F07A03B5957BC9333CC5097919399\
+DD9973ACE15E55940178C4C96BB5E0A0A10BAE175769548EBCE11E0D7D9DB296\
+47F197D4B87F7039F5D4E59E016531DBEBF55A797AC9A6835032CDF34240A7EE\
+7423E89C09124829CAFC5F89431C8AFC54FD979E50D48A82B47A53523C84B600\
+4DAA323EFB708203E5388A6A5110C6CE2E341048A65FDEADEB3837A03420F9FA\
+DDC3F02A544F1E46D96B07C90C7971A7040A179E8198E90AA019268E00367120\
+D5F3D98A5CCE82C885E77144B1AAD66EE682847776B04F01F501DCBEFE390308\
+0A8058B3B8F1D823D917ECF31FC2D5B0795BF95A55C7093ECA7C801DD0BD0DBD\
+BEDE7D56513128B29FC0B4D25A6240B24C99E017BDFF7ACAFC8F8DE9FAF5A294\
+4384AECE82BEA04DCCC6D51FC6E6F27AA38F131B7959B13681A09B311D242E62\
+22A1CE5687DE5C080508B1DB16B6F8290D33A3CC0D0138AC61FD9093825E9D37\
+52889E9F20DB9F80F92750EAC88B38AC81C0016D40371EAB4A87E845E91446B0\
+A07081B84F559CDB95340CB020AF22AEA1BFF2FDA12F7A42973FF163A1C6F33D\
+B8B8214AE27ABDF1C54F5B03E29310FA210125E1296E8AF93A2996DBAEFBADD4\
+C51C2C3B8A3E2BC9FE060C42BA32768F6992A99599206CD2291CCC5BBD50856F\
+7F8D2D0AE1EFB5892C15A799B77482DE4553736B162ABB06631F1688F6746E7D\
+7A37EE7EF24E6CC901175F04960C01990178F81E957E941DEAAC8846B3704E24\
+204F43DDB0765C433F3F7D4D201459CD65682B7DDF3D47E95CDB31B96A4CB229\
+07F08BA6E92A4A07703B2DCF150F922C4B7CF181380303FB72547847305999C3\
+C8F9AC877D05D9DC4159DEB8A13D36AD1D533A56950E20F906D29D51DDC45BD1\
+5C1773991707480E37B827044BDC6473181B760A9036E0D3FA491C2F08C55130\
+D8CDD5AC8E97D0813164AF3D28A585F0C2EC7004D498F95C6B62231A632A56C2\
+D0C48FC3A6992D4051957B9ED6D9A86DBCCD962A8883CF82CAF01DA2F51A203D\
+56B6089BC8FD0B1BD414C8063031ED469555E22EF872689C130B1C101034D572\
+FD8CD0EDDABEC9EF1503D7F728B0941EFE2B9512438C7DDB176BE2EC2D9FFCD5\
+6495A4511428DF02819CDDA18D1ED5D3B16C6F42AA0AC681A9FAB51E8A1A856C\
+15C51A3EC1031427142EA12543014DD4ACAC640B8A7729E63AB7DF1051112CDE\
+FD4B988A2258334FA9A7F5B3A87A02074B9F69DD81B83FC74089A91D76AA4041\
+259E80FA255F2084902AEB9E996AC2288AB464BDEC47AAB26A28A2A819498975\
+5D48FC9A5C9279285F2F1DBB8B8018F3E4E13115D78A879792E45A8F4F24ED4A\
+317440BA63E6929056EFC1D2529B75A709D6C0097DC2D97F646F334EBE6195EC\
+5630132FDE58E25DBC17DAD822D9FA0938A2A2C926B105D108403DC29CF371C3\
+504FF73BCE9C7ACF9A74C4954CE6A32DA96B21CF3211B3E49953DAB78C49C3E5\
+32A349003C59C62F7D40261CBA63A9EA21C89A38AA63CE431C43AE261C4D9999\
+B1CAF491FAB8E7BE6E8C3454F1BE8793B2D27141FC107DA599A4694C41353D77\
+85C05B5E31440458D17C6DB66FEB8A9C5C073FB946A67AC0312BB669D9B12FAB\
+AA5272CA6631379EF4ED420A4424A5CD08526384C047C33A84D5D7DC0C215366\
+3B54C73DD799A3568C01B818992CDF8143F1DADD6B50CAE6EAE13AC66F31FFA2\
+B362CC4D2880592B7FEE4B9E4CD6AA5E5DE27AAB9B5DAD9F7D39407AE927530C\
+AB2B61CD7394A21EF47BFB813B5EA6091458D239664923280ED0D5CCA8285BB2\
+281A2F9FB3FFECC8E9147E1E8FAC957D90C9E5F513738745A47C2AD0C31FD898\
+6EF3B6388C6E821F166513811D547AB4336B5E04643497FC9F8D6E380EF6478B\
+82B6E2F5F65DD98A63C68C32B94610E1D3B9538F13A7688FBB1EC3448BE9BD77\
+BB93A34546172AE8D614F85228988E7FEB18C9A0C9827699E8B3CBC69750BDFE\
+CDA8268F694F4C509BEFC1A1166F85C829725299D173F867A300987A2D36D1BB\
+BE37BE3208FB8EFE9152A41A5F0E931B6382FF7F9B18937958FB180E61F2A8C2\
+8F36C3C80C3722935AACB81C24AA17FB3E7A1026F7031A7449818ED62BA7705C\
+A27C2D3268F90B6322921683DFF800A306CFC186CF2A61B37F35837B217E3B2C\
+ECB0843D84EAC67431E3D689F01522D4A4C73618B7C2965C9DABB15C0BE637D1\
+0CEEF72271CF39A7B803B41767BC34433C3E6FF449A439AE13DA1EAFA038CB9F\
+2E1C84F1CE39C05DF56FE3D7B82386C4E628B6E27CBC5D575C66ADA3510C246B\
+D04DB48F4AFC2D7352966DA2266C2BC9831532F53655D8BE42B421AC0D70D8AD\
+1D3587257886DBF93668E907E861BA64F45999BADB0F766EADCE5238B5ED397F\
+265935194812C03C5769137BAC97140525303CF48D65F39004A3F59B1FAB0989\
+5CEE05335D15B9B12265892F4ABB92AB1DD2002ED00CF3562CB67DFE1055968E\
+4AB3306BB34BB87D0F64B26848812A2F7B50424A21FF94081A7F70F7B684AB0F\
+092B2B085DCF84CA38414CF7290F607BF79C37EA84253ABCA8D4184D2DBE2E90\
+0200B81479E1CE8B71DCF2BD6E3C557A8E431D627BA669C2EA03068E0F7EA62C\
+29777B22142D7A1D451BD541EF8EBDDBBA4E3BD8FFCD340E935BE7C66EFC14A1\
+3EA48134F655B0DE3180101F09D204C379743A357E6DF1268B55A9F7524398EC\
+F3A59849A27B142239059998083E8FA91785E91C4D220B2FB17E3389EBAA384A\
+49D89B5D78136DD2454F06CDE9837F096B744D53221127869904AC227CDF30BF\
+EA78CC5545583F999B9C42A1184E2FB9FF3EC095B9DA0D138205C4EAC4C8C480\
+C43153608849F63E161135C79D8B6C9CFE9B8DFD8AFAB559D8B595DDD4383503\
+3B4BBD391E028BB2A60832D9B697EE61408F149744DCE71AA11BB2B0436C1E26\
+26AC3A27CDA293366B90B9CDE2D927855130758D3946B867192DCF3FCE9A3B9A\
+5276E8C37B8CB136FC90A6DC22650F95E796A9886EFD3F424BE63A66DBB1041C\
+B3D4A06F4E7EEE89F0B6D15C36F9EA010C66B332011C8888E8E4AB2B3AB52231\
+91E1388613A0FD0F07C1B26D7CC7CDF1AC62A226454D6291B431CC3EF2DB2B24\
+42B37DEFB942117FA247096BEAE598611B8104F37BEBEDD8BB8B949A89B5BF8E\
+228ECA1D8F16BFEC75A02FFBB4EEE3A6D4A6087C43634D675311E72A9F3253BB\
+5DD364E07EB4B9C84F586BA267BAFFAEFEC79E03B83B18595FE06D7E063EE604\
+FF287004D141C1A43AF0CA7C5651D98F633FA875B4743353FB07BDE59B6567AE\
+25F7095F1D9EDF30570E2F7D7EC194216898D910F9E295A41DFEE072CB56F914\
+BB78CC9854129250F9874B63BB3EBE9A1CDC6EBCB0916E1C440354DED6AA818F\
+2811DA913912A21D3961AC94A39F0827D3A419616905DC45842C8E69A43004B8\
+AE922C8DE1E8CD0668674A7760153213835BC63FAE4F8D65614AFD74A34D42AB\
+AD5025B884B34639340B45D49CCED423771916E18AA077291923017CA50795F3\
+B7A3F349A3D29923833CE57801C631576E23B838A7767CA1BDA92B82AC502DB3\
+688FFC83C09A4E40CAC31D20D9D32FA6724A80BE7091CDE9C7A6560CFB326B46\
+7CADDB9E9B7A491EDA283EFB0B61B4A1116DD859D5C0897EAA2A3FB2CD82FFB3\
+3770BF9E08091363B6B81D23E61C2A647D2BE440C5C79EA89690656D9F10B1F0\
+7942834E1CB6E2D2DF106EB6D6A21FA23819E65028515E88BD279F9317BEAFFD\
+394EA51F8639371C3A89F11305A4CA35FB0711F5E2C7C3DD1659C79024581211\
+3204B4ED8AAE9FF09D43C6DDB13F5070D98831B2C7639FB6B9B01C288812DDFA\
+8861DB32DC8268C07D30CF969953042B3DAD530D9D744C06AABE7A886C0FE57B\
+09B7F42D193FB3E9C06329818251A2F7E6474462C95DED:\
+010ACCEAC8A085540933A8B2872DFA7014AE88B08468AE73AF1DECF232A627FB\
+F5191743F1782E554DBAE76C8A40CB190730C3C533E5E00D07D12FA88D39D40C
+
+1A3DEAFCE70AF6F3F55D66AD9CE78D5F4D5C5F2638A810AFCD07D67E9F9A1380\
+D6B34BE482EF030C22F1E978F544609CCE35A74C5109EE7038495B6210CDBCA8\
+DC82C6E9E7B0D593FAD9665382B3C401AB8941DF71307DD77EBAF140AA66A1F7\
+6316478850E58886A9610631E9C722F459FA00C0B53124FB4F12778BBBA37608\
+26D3DBA67CD030A96B654AF93F8E395F5F439549489F8161683F124BC980E693\
+9C83A6085E4B6CAAF8BCD89A0E01ED70DB487166CC29735D9235A9CDC57B80C9\
+C2E591DF6322F5BEDD32937073F781A30389552AE83FBE147D1B3D3461A3DF96\
+C15CD96900C56718EAAE838417057579115936862679F5F2A45DADF65D14108A\
+F1641DF987B57986384FA1433789F5DFBE87E90BD4E9D8D4D0741FCDA7348322\
+B967B566B18612DBB8FE64F151947C3F7E361EE868676BCCD0CB3A1AFE046BE7\
+0057A05ADD3E65AF31E3FF414A627C0183E8FF583B41B75B203650420216E6DF\
+CAB289665F054CFE3EA0943647528518573BBB1D0F27E1449E98739EAF0D0094\
+32DF0C1EDC1625264B94A71DB762659FF5A3A7A867F182D1F1FD34B341A4A181\
+221870DC4A494013091A7E3B2B07E0160C438F1EE1E8A2B989C4FFEC36B5083E\
+A427606767C29672F44779A8505B422B25A56907F565B27690D011426A62DF00\
+36D57D967CD1D14E915BBC2691E7AF818C769D9E1F9EDD40894BE88FA1D7A595\
+2AFD898E837716ACD73953BF2D1D448123FD1A0276D2C2EBDC760A4B787416CF\
+AE5E963FCBDC8B551CB70F91DA0ED4A8090FEF178E879F2C34F3A269DFFFF097\
+72D44A13D7A17468B5834C460957D5243C325F63F05F89D4ED98D361E7F0AB8A\
+83948A64D0CFF8514841AA21C7F337920A9983E59BE4A0F1339E1E462F92DC1F\
+C070126206012458A499A8111FAE078E00B0CA3BC1D6C7087CD318D5603C1C7E\
+0425E6F729CEECA5F35B82F8A42E0E9B950EFB0904C5FB5C06D91D239913665E\
+D1F1EE4B82185A01BA86CA2D3EA94E5A8842231A94C05280183B7ACA28998410\
+3F122203EC2FBA4A382E6F5236D6F68DA05E3BB0C558421F0EFAB91DCEEF6D1E\
+CDC60F9B88F8BEFE31CDC3C2F024A1AF2C7336AA5D151E8CDA814A5FE898BADE\
+B9DD680E337E682EBC22BFAE445417E37D2D89A338659A280AB1206DB74DD42C\
+6F25639C1803BFDF2156DF613B0F5924D209F7F9003CE8794F989F4F27B82121\
+210F4F65EC5A1F7723305CEE438C41F793EE04496BBE337BBD2FD3023830B1C8\
+889C6F4D0C1192E364EDBE1CD987BA5D66224EE9C9405E1DFCEC0EEFFC5C73D3\
+123F6731C6295D1E6B854B884FD22B6A3BBBE5395312585CD138BCA67532C6AB\
+71BEBC6657C50DA87D2AC6068FA3970202C5E15EB7B4B3D2676C0134BCF1EAC2\
+B26BA46930B5E660B16060894884C88BFACD6779276B86F685AB6F17C6D53F62\
+1275FAD66D021D26D1D480AFAB4B5EC75E0E763FFC45F599EA02504DA5D91EB5\
+EFC3E4AE196F219E45E7CB05594958C876FF474A020EF73C1F09B1F7F7457E81\
+6D3AF51D86663D4D461754CD5E907456691E02446D6CACFD33516206A3187054\
+3D574592087773653D4086C2BDCBAB3C9B65CA11AD0D4E58DDDA8B4403099898\
+57103929549B7300CED42651D4086661694092C42875CB62858E6D1BE5F7274B\
+4BCD83AA4DA05CACA186A30902830790F9FFA24418E1F9DB00FA40477E83B05C\
+2D11AD7D81DDDB1E31F94A9DD5E9E13391C22479B570976E3AFC1BE41086D3BE\
+6689D87CA4326A7CDE8E5B396A678D3CDB2C80FECFBA2BC799AE8B1528E96D88\
+0CD098DDE910D097EAAE660AD4D7EA51C18F18AA1B39614299A172512521DFD2\
+31B9840909839EB69C892EE23F1BCEEC1FADBA75786C7DED93BC9983F74CEAB3\
+97EB8BA84F7E4130B34258D628594A6F9E2348FD91BA2594E07B8057E8A2AE3A\
+DFEA0EF919555385977041C5B6DC4F3880569171F7217AAA9A85F2F5BBDFE3FF\
+DF79248F2A35FD4DEC34980C67290339B1C0A5A6AB8838157AE2F5140B4A2492\
+4A6688AE5CE72A48103EE9029CE8A0F15B1FBB19A12FAAB80A7CD9C0E389FC27\
+75833E3190F1CF735ECDFE7F6B6C326506AA82613CBEDA8DD3691B81F4C1E3B0\
+FC32D7E6719CBFC12F4A26E0FC29D6417953ABC9568DB4ED9A294B9FD5F2A666\
+DDA546ABA301B1C60985033953EFD6F4538333B5C7DD3148814A3FD7927C366F\
+40B3D7ABBDEB2332DDB586AF80959097663CFAB2FEECAD6D368AE10EFF9663D5\
+F8BAB95935D25F45776F7F04B46817D05165A9DD4770509ABB92F8B9E7373CA7\
+80703569981754A51D6D376D65C57F55CD70E2DF5FDF5A6B829AE30CE3BF9428\
+15C8B4BE858DB58151D02A68AAB9FD373E047EFA51BD1A0CD1B61744D9E97CEB\
+A3334B3BAAFEA3BC9E43AE097CF2C3D713EECC247FF43EC74D54907D8BF45E45\
+B2E0E11D82B126A8179D3F66C055E11F69EA67AACC5FEE8AF01FAA379E51998F\
+5070F9EE0FD30A2EB22A925586FB1B39024EB5EB1E127C76A149E7F02AF1B73C\
+16E9E5A5DBE378E08A9FADF1194C625132AB3FDEFE8FE9A89BB8E0035A1A3AC5\
+278F5D3D0ADE0E41C81C6853A41C4AC45BE3F68180FE23F27F18BE2E339DE1D5\
+59D75DE63ADF7A32BAE42B037AEAA3E123A5314891BCD35CA48D57DF4C17540E\
+97202A8EA1328DA25B1FD6BE2B56AEC1E5DEB209F3B7A13ADB1CBE53EB645956\
+E577A7621D74E42376D70BC5C4AACD239A852FBB7B3F62CF59FE10438C1DC8E1\
+E46566325DA0CA43AAA63FB7E0B450A2DB3E3A2204704D894DB24B72B3078106\
+E096CD543DCF027650CB4965E38AC36A8AD588C5962B4E26548AB88F0BC20E10\
+ACC1C3FC00EF415B3C32499264552B14E2C0E789A3B8A8BFF9620FD939D0B34E\
+806177EC696A4B3B1CA4B32BA979B2690CFB3A6B17BCEE6877FFCE757E4116DA\
+01099FFE82ADD5A0C593E73449A96DB9CC2B9E846D166B095174F2CAF8B35DD8\
+78C836D9BB6EEEAF8E1BC5D0E149C739828CC480D731DC16B35B80D4AD82ED7D\
+29BD05018239EFECF8DEAE180C6A459DBCBFE4AAB9A5E2C1E1BC31418CF2EEEB\
+31FDF8BA02C9A91525E9163F672BAE2EDEC38C1BDB84EA237B4EF86BF5C0F0FF\
+E178E3761E82D94F66E5EA40BA8170BF768409E1B4177AAFD9937BCE3FBFF590\
+320D7C445372463FBBFB34F57447F42C16E026F179CBF82F617C86D1E8D42F6C\
+908F9C6B77E38D25D51303DBD781FFAB569B4CF31FD0B947C45E1768A2E9DFE8\
+369F520DC38D77937B69B821DB4FFEA8F50EBC404F0587B5598189F54B5A5B98\
+966FD16801C87DE2C3C7813DD70DC600824D426D88C55E89D47214D59206A7A6\
+5A65DA7CA2E42FA62ED17E7AA5B3ED446BCC71F17FEC8593BE96D2037BD07F94\
+76D4D732B32BC5DF8C921316B45699004716FC89F8D45BAE402C26DBCDF1A340\
+847B932FF882DBEAFBEDD252E126C89A1E1FDD8908A1F67D15D8E432DAD8E08E\
+950A3BC46B96CB89CC5BDAC703B3FA3E986EF1C6E7E6606E6845BA1EB2FBDCFE\
+E744B5E45206F4A419E1CB103C8490EB293EE9AEC1F0A0D294F9D3847737413D\
+30873F3C94740E8FD072817815EBBCE3F09EDEC9D1211A9E99547D620B2EC56C\
+89E9CB8144AE9E46636324BD13C6CCA3AB9CD9FD8F7F937ABABC598232384427\
+A2D4CE0CBF9765F7225E208C3CE128602B0AD08A1BAAB77EDB3111F0C6CA7BA0\
+EAC9D89D5B4378EB82C17F6EA08308A79A53D150D3F85EFAB77294F02EE0E288\
+5EE2AB2793392B87DB11FA77992F5B4FD75EF2F1A822E87407A4878894215AB8\
+9B6CC4A120F5A78B3C31AB80FFCC9ACEF53FC6F7F85685EB9D56D30D87C21ABB\
+F1652EEF8F32C7C567BD1F08623B09C29F33561D42727A5649A3850071AA6C11\
+735AE63C4FD31559CE560B27A362786A83353FE460B37074664A9421D3B2F6A8\
+64D5ACA087187B27E2B82F31CB3DF5E985CEA271C609B94B4E58356D40C7D5C7\
+FF2E5990FB39588154843EA5FCA92F120075D4C4D006661A0FA1B0585454BEA7\
+25473EEF7D58117D5840C8348999003736C5EEB7858FFD273A1C3EB2812F5697\
+C59110275B08F6BEFBE84C92497D5F73B7B6F794A849713B23AC5F29D5C7112F\
+B2E7A6E89EB54DDFA3122E6C79624C1BF25EBFB9FE5CE6DAA779F3ECB2984DA4\
+2F8C6ADC77B21DD291E684FCA50E46070962A2D4F00813D8DE1B8ED33FED9715\
+180C7EA8E2BB74FA65D9C7F6E142F3C81CDC59172E1020F62F65CA5A12CF2BED\
+9DEA04A4D8CABC2948F7BE823A3E792625275B3925A6C8D8E2B428C75A5DB0F7\
+120278CD7D6CAB768755C7FE2FBF89FDED1FB38AC7F76A2F8798CA36ED42CB7C\
+07F006271205F546A4812C20077F050D4CDC79459FA686E97F0704B7A9FF7DE1\
+6318E862C53D361BC635A55A264BE15016545DBFCE3C6D6849576ADEFB6884ED\
+D768214E0B438B0231B4F2692C2C0B5C177674F8A0DE236EACD9E0CEC7C8647E\
+4E9A5861B957EC834A2F8572F01304C3FD6A06019E5F1499B62BAA8670B65246\
+7FA9A4F10F053263BFE9743CC7D933F86136AAE3A6FB56754D7D238397A0030C\
+EBEA87CB255AF36138C373DBBAC41DD4A697032E4796C552AD9C9B3FA713C3A4\
+E09E0EC5581E94BE7F31065157662F9E9C678B1EF1B8B8A847C51789C22B1841\
+BCFC855820AF3258AF9E08231090B45D10046A00178E89BD515616B8A44E77BF\
+57795DABAF40687B2CDA7A5014168F:\
+FD963B660F075A55C055E41FE5535B79923F0D20787AC05AF2BB15829FEAB38E\
+9AC653383550056344FF769CBCF4FAB9BB1A50E44A02BC12533C3538D8906A63
+
+1633256AB03B20CE079196B708A1C02D1B6072219070712C8589EE21341D5075\
+2ACB6CFDA17E982D828BBD6CDF54BC7232FD418A323D64939928597B9B52F07C\
+F488250C5E42BFD3AB48012D709F8D747225839296386FCE5FC5AECC4BA7A107\
+6D089DEA8ECEFAA0CF66FCA8602395719C12A04F929321784D7AB8239FCE2FF3\
+BDAE046A266132B5C2AD9F7261F3014E87B389A6695978693D9371D0B1FF9C40\
+5F338C2FDE4687359603950A54CF4B9CDD9B24480B239ACC5405C14C886BBB03\
+78391CEF0662A38882BDD09E3866AB9A66CFBD28EB5EE4F8009BDEFC4AEB1670\
+0EBA7DC557B489190A71FDA75E85F7EF841697F70FFD4FEA185E7A67C81C5B8F\
+273BFB97B2CEF695C1C74446C4B425BE6B2E66DC0AAACB247E4467B7C7D84EC3\
+3B6B5AB8FA1979F503008BDCFF948CDBF1226B1B066CBCF34797298F3BA8C60F\
+A01E0AC8B803223C656112FB91435D75453BAE4707B63330467DD13E0A4B992E\
+6F7E46995899A2D95D23F4AC3D0802B2A6E7D024DEA19CA408C4BBE053F14C9C\
+E264F129724A18BCB18F385B1CA091A11434EA96D98C8D0602E98EDC8DFA1414\
+1AF93ED0BA66E885E9FA108591AE59E109AE34D6B9F5586E4B4D75E7DF7C3295\
+8A65E88A9BAF41082A0A3F11539DC4EA2CBD9E1C6C3C439B622F1DE574FA7547\
+0C8C939B51D2D1C2A7204B859881D43086BFD8FB90346218D099C5AB36846F3B\
+98A7C847318BDFA01E09717943FCD864C5A8A17B6CEB89D98E872D388F20ADC2\
+BE5E2006846904F41682FB1283214F3D20DBC9FC9E0FF571844A1282E88590D7\
+C085B2C568EC5ACC4462B389FEAA5757F7033187E2DE31955FCE55FEDC909255\
+048B327CCAB2E582BBC9D8054BF5CB45145C7D3A3AF9CD5CF6ECBA490C634ECF\
+00E646BF95E8642C43A4978EF08A574EF1F78F6CE57C3B34B5A123D123617FC8\
+EC9B2AC0F9B70A7F6062D38DD7B8E9FB4ECCEF13DED5C0477483ADDAE4F1CC0C\
+FCA274B1307ED0DE72FBCB819154CDA897D7575213042615F1741A8CB646A39F\
+8D134FDF9E60E000EB8220F65CC30F5FA52C431B9E3B6101B96E25B8D0440B96\
+E572A18A01747C02AFCD7513542F7AACE194632099D16274F31EBABB60DDD94F\
+E43DACCE900EC0902EB5E686D48ED8D09AE63DA0E15C736809903A0297A92DE8\
+4E0260F11F446E1FC448E0EBF59FAEA3C726F97925C57CBDF85B1F77078D3625\
+7C85D56CBBEDCE180FE12B687ADA2DC9912FAC60334166BD2CEF06B089ED5C95\
+63844D71D8FEAD2F3A93F3C07C52537336A8A70BF5B596B9007B9FDF2D082000\
+F20E6B70D2A7E6C7ED27C4146895A6D85A246F623C1B9258A2F891F823ADE4CE\
+FFD59D4FFAD077351E2F506E9A5BDD3900F0204B9E8969AFE72F5DCCB9CDF986\
+D197AE4C4DB53014041AE6221B750E5290E307AD292C8DE6B899235212EF8CE9\
+54785537DC9435AF11E0F3427A9C7B22EFA752EA0B7EADE5F6EB4093BACB7867\
+6E506698139E4F774423B8942166F9A7D22480D814FC0AE19CF4960FBF6E01FF\
+A65C8DA5BED4F1AE2B9ECEC5BE7B3C38DD4045B0C93EE6CC77A7E61E85D331B2\
+3C0D164B104518B3405497054445A353E9B48F2AC5E8E96298D6655614336CFF\
+E6D8C9C915E387391519AD2632366AA3BC935030FD12927EFCA17505ED74C946\
+50C778539004854DF6C24269AAB9C273A493D3E5B0B1D687C33C2FACE46B4BB3\
+742D6DF743D09164D2E0EE7F6BA128BD5FBA2E3B33C199AE80FA9DEE3AD811D0\
+2BAA3D42A6362B2AD47BBA8A2C5CD00B46CF22CFE367281488A4852EB8B7FACE\
+79F0CA6F8E78D32578DFEE01711C4DCF3C26D0BA13F3075478E708C5C5315AFD\
+C2E4C0062D16458213BEC506A9E991A61825FF78DA9BA1BAABBEFA56B4A8C9E2\
+E7B60EC4B7B541C8E0F79C86BB5F03F736761A37169B2AAB8884EC6EA217B02C\
+59035F5BB327243D126B78D4AAB430212439B5A75B80618DAFEB66AA3AFF866C\
+4DAEE47D374B512E74ADA933EF24A841BA271C6F02C870E8AB950FE06E93C91D\
+F0E99165DC01BCB190E411ECCD85358FD4A88127A22E4CF4266A90845124BF97\
+B25D7B1C46D3A0D68A684F84E2A638C692A52CB6E8C651A3AC492B0460004073\
+D5349E35552359CA37660F77B2770D6B2B3F7B1922424AC4A8598B4C61A6DB50\
+7608A72A6A7D573CC055206276E14005A28A0EC41F28D7E260611D40F089FFE5\
+E529375691412F4E9E12E62C3BE2C563C26D2444EA9C69E6C935FEB4DC4E802E\
+5FE3906F8ACEF4798D940C3CD574BB5E74506C3E0B70CB62454A25F589EADB6B\
+0709FE3B50417CD1D98F08E08B7CF68A04CCCF8D6588F9FC2F31E533CDA6159B\
+AA4297FA446450D71C16EA2324EC09773E7C8817ECF680ED12F64A04863EFE3D\
+9D8760F34DE5B0860B3991FF0EE5EDBA22C4D69120DE19D5429E4AAE91C9E7CF\
+05CC807159A58F13B480872AC1609D87E7009DEDB71C09CEAAB640A2B6135855\
+CEAE4AC2954933A0255B425D9FDCD9C246F82AEB7C3BB78C6E73E03DB7AEC424\
+5A28693FBD36EF4938D59CCE19EAFC00671A0851612406A075713C5D1154D8E1\
+3B59B7C5B0902239D4BACFA386AC817AC5EE02A181A9A47C622B3ECF287E1484\
+3D452AF347110498A620B34AB4E116308D976062C9EE9CD35DB6CB79805B93AC\
+9A15AFBCB52F1ED4309879D1924A4BA190B0B86E60A516E77D34B4E0A49D4EF2\
+CEF3CC2F410FD8EC901363FC9EBD75EB460D4D8910BDF27CE26A8B4AEB94F9F7\
+6242401DC35D0644842B99FB6C439B82D82ECFE1AF0D01F9BECB15BEC83F13B2\
+60F7F714AA381032923FDE8F8018F3518547451435C9A5207294D08A907C7369\
+6F6CB000745E072E25B73B3EE11595433D27A1F11468686F08094F1D31F5ADA8\
+1F11F0677A29D72EBB2E1C4792CCC607CB938647E1F153F9EEF03D982595C631\
+E49B6B7C1FA003A6EB8D59CB8892CD0888B05240F12701753F89007C859515A2\
+FEF944BC60B36003A26702AC6FE04D2E942978FC31A97EB29871D6752399D352\
+1720729007B6A7215A4282B2A4EFC2C56BD129E74C9B00847692B96FCC71CF7A\
+7F19F3FD6B45C519FD73B4860880A2DD74E5727B31A93F0A87F0078155344AE9\
+F7BDBF00D83393B634B5DCA88A398E42C320EB95C4A826ACEA90B65E4767B2EB\
+A748F97C247568393E2FD3A66075CC12935B6D7EB5C2FF5282185CB62C73972A\
+37B3CA508004B4F796BDF82B83B5BDF90D6BFD32B5089B0CA2683DC7FB2337DE\
+42E650ED911DBEE1EF98257F9BA5AF54B1A54B04C0087A5A64BA779D86461BA1\
+5337C2E7D4955FDD777A025DE226306A17C384F1C52CDB5946FB0B46DD5C13BD\
+7A55FE2E27E4C6D40D61D6FFC024468F8EDFC7C7992DF5DC5D05063FE7231992\
+24F53678E48F25250EA28BDF1089718EB8B730D1C06735C2F871164E2EB5E885\
+A8DFD2A083BE97EDC94159CE9BF75D2433F1D782762F771903CBF9A1C9D13F71\
+0BA0E151B079DC0A8262BCEB1DBCBBC0F35DF6EECF7BAA7105B9808745853C96\
+B4372E95E482035916B726DAC7BE95A72B19DAD48DB1B19E6EB2EDAB5AC1B301\
+3839E7806625ABC129F41813E6D71EE4AB2040D81E42E6ED73ABBA64FF2EB433\
+B910EA7D4F5ED3D8D27D39BB454EC019DF6114F544D7B155549D0C56D14551FA\
+F353994A80F30F3C97E863A4F2AF316468A568038EB4D799350A6FACAFF90ECD\
+44E0F44EFB6DC42EE4B0DC2C59EA9C1827326DF08C0A6E55CF4F9C3EA0E78CFF\
+3635F5D08E44F1400D20F638D56BA84B4832090454DE57EF04B6C8805A36F63E\
+5CCC6E830C87FFC164647CED20E4C486D09DE7A5F9E4B68D5456CDB22B0DDED2\
+B95B3BCAE529215C2D25D6823C7D66A4FAE0A1E9F022BA5663204F2314DFA51A\
+1F10E11D6D62A8BA6C28B6AE7DA1DEB5B57F2B65D7456059AD9F03DC5A524054\
+DA39DD100D74EB657DE219795E3C45A0E4C762BA22F9DA9D8159E425A1EE783B\
+4B22C250D8894CBEC706CE16D5CA393404FF478F141BE7CC69E45B077BA1955F\
+1F49EFBE4847C795347F703300F672334F490ABF8B644A34B56DA00EC45A3503\
+14B9ADF27CAF7C51CB7DBA0C5477E7D37662F4F23247BCB8F7DD5F3E9CB8BDA4\
+0FA97568832AF0ADC68F71422E412254A6BFC8943BB465B01FCC8DE0B957677C\
+78BC1F7566953E9D2446239F602C682A521C14F741FEA98C7E27AABEC339B6F5\
+B94C78287A894AFDAE971F8DA7C7E4A4C92C8DA47BE82DC2532EC2DA9BACEDD2\
+BE6DB2B2FB34DCCDCB34116507376578CBCA105E5E443BEC0F2EF23BE34CDF86\
+2EDAB34F0FF21335E3ACD92F59688B419F824EA61EEA82BC80E3463452192377\
+131BA51FB0795E089FC077D0ECA8012E58B0637AD7022206887FE9EC00EE5DF7\
+AD2E26FE819EE35C7A179C579098AA3DF645D9064CD557DA90BDD21F871CEB04\
+8CA56DF9653A10ED60F5E9F0ED7F8D89BCF5C22D1143CF44718FF2DFD8E10CEF\
+8AABB67D2305F18177C1426BD4CD03F2625E459CE905067826A214E08E56D8F9\
+455593E6B324E72DEDCC429D3BEFE2AE0599E360DF95E80D453A3A849E48389F\
+A745635BEDE30E7932DE6A3816E31A2217F98D5E40238963D0A36C159FD4EC32\
+D8A5CF59D433DEF3378634AF6887FDB3F3EDB96FC8840FE1B538C329674AE810\
+E8C8B2B46DB208716D38E9D1AEAB097068AD83ADD7DD2647839B3A7388B0615B\
+DE26F8692E9C07D8ADECC2A875203C3D3A9C6CB1D7D06307E9E1D9C3BC536DD8\
+EB271E9A2159C904E61E8C9357FE759F36366AEF5A3D14CEE82913CD2708AA60\
+69369CED763C8E830D70924E82E9015C2998E86EFC1DCE6AC2EBCB49455542A6\
+D7DAB265AD6D7381FFEEE1AA40F8FAC0659B6FB56BB03CD8CAFAACD48D13672F\
+7D524EB9684CFED4DBB7476E99149C28EC08F33BA6AFF839AA178F86B8EEAF17\
+39C829177BA78547AD394136AA3FAD451A11E9642506568B39668B2436610E06\
+EA45FA11D04D3759B033B5382645F15B3C39270B81B80487643913A24F2F1C1A\
+1ED57C85CCDDC8CD6D59B62FA67CC80572968C8FD01894F0153634C88792A7C4\
+A407A4A4CE46CEC5FE5D2569F95A27DE242444EA0C715B357518CAEA23E767E8\
+545983F0D3A4DF66111B4AA1D399CCAFD796D7A80E592D5A51D2B3F60B5B04F8\
+D9C009CA56CBD4DD84127A29B72ADB7645FB7279C9818B2B43963BD605F45B65\
+75A5E2E369E0B401F5EC10EC703F1179B0AB9D4A89D6F096573952E513827364\
+A84D38922734137E969D8167D6959B70F42F2BDA37E4C989ABAA8024C1A84ED6\
+BEB74780927F78B32EA736B9B2B4A795C355C0319811729D9CC399D235197303\
+38D62E16E5035FC52A817090703FE776D65EF9FEF5BA5F4FFEC3CC8E9EB2E312\
+C50A479BDD4E6AB0A56C18C2DF69ED408417BEE28BB41DD13F8366FF6EDA4B34\
+090FC9BC045271:\
+8B64094ABC1CB0FF0BF0E156173297F07680FEC15F32187AAC32E7CBF9D667DE\
+92999C2DD7B40E7F326D174E493DD15F6699D2C2824F4209FE2E9124F8A46148
+
+[Skein-512(512,20090606 lloyd@randombit.net BOTAN/test)]
+:\
+433FDF4356B59774F971B24569CFB7214EAB19640AF3E3B23993040FA3392910\
+32495D163CB696EC8F1B8F1E85CEAF47CAED303279FC6608C27E070B04B48B59
+
+52A608AB21CCDD8A4457A57EDE782176:\
+7796202A3FC08282B85E9EE677884DCF4E4AFFBC398C93993F90AFE2A430BD6F\
+9CAA96EC3AC7F23CF4EFDA5D9EABA5622766101D6751882BD5ED1B03D02E31D8
+
+E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\
+E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\
+E3587F76DA804A12CB639A2ECADBDA67A6748A3022F96DDA6E17E55D3A89570F\
+6D81480C906F18A7BF08E0C0D02EEB953C675353EB22D3B6144CDD7108B309D9
+
+2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\
+29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\
+E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\
+98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\
+499B8752B2E0BD0B28B55BD516F468A1E6DDE1D82626376296C88F0083C7D151\
+A148C5767D6E5D7B2BDA65D6209BC02F291096EBC14DFDE6A0F8E9252D2A1E8B
+
+[Skein-512(1032)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+24971DF13AB62266AB7D3E4EA8234CB3D74AF3264692BE46F6FE51FA2B77CB18\
+7675A25DABDB6F8390CD389CBD5C21FF6B4AA230DF6734616DD7CF2F3BC1D443\
+114984C4425D4A89009CAA9FDAD1A4A854E4420424738C3F892FCBB738DD380B\
+AB4BAD90A50C6BE5E3184B9824B75E1213CD87AAE9E5ACA5969B014C6D9B775202
+
+[Skein-512(2056)]
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000\
+0000000000000000000000000000000000000000000000000000000000000000:\
+ADDCD709FD7BDD504C173A7A80091E00B26EBD035302C43B74C23A2721492AE8\
+1C083FE13CDAD62FCF30CEA277A157975EE9D92ACF9B8CCA78AC2D0B7BD2B3C1\
+F8B52D43175470F6A2BC3B5B7C2B94BBEC210C8513204B3DC4970EC7943BAD20\
+AE8E56AF8A319CC834097932E94D329DB216C3F9CCD673D01993A7E8AF128313\
+D988CE60222F674894349F1B4B89C13C6248468CE9B088CC62A52AE3A8A80D5A\
+757410CD23E9F89CA5C242916CB2BE7BCDFF8C8C35BF41088CEB75361D38DA36\
+6D0D2DF38B76D91736AD8B2F910D543FE1F0CF5537D1D85FD3AE08CF84C5D46C\
+0BC83D0B63C0D8159CE118E636182BC02CEB0312F627D543A136BD2116AD3E02D1
+
+[Tiger(16)]
+:3293AC630C13F0245F92BBB1766E1616
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A3D6162636465\
+666768696A6B6C6D6E6F707172737475767778797A2B30313233343536373839:\
+48CEEB6308B87D46E95D656112CDF18D
+
+[Tiger(20,3)]
+:3293AC630C13F0245F92BBB1766E16167A4E5849
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A3D6162636465\
+666768696A6B6C6D6E6F707172737475767778797A2B30313233343536373839:\
+48CEEB6308B87D46E95D656112CDF18D97915F97
+
+# Tiger is Tiger(24,3)
+[Tiger]
+:3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
+
+616263:2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A3D6162636465\
+666768696A6B6C6D6E6F707172737475767778797A2B30313233343536373839:\
+48CEEB6308B87D46E95D656112CDF18D97915F9765658957
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6\
+C6D6E6F707172737475767778797A303132333435363738392B2D4142434445464748494A4B\
+4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737475767\
+778797A303132333435363738392B2D:\
+C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25
+
+5469676572202D20412046617374204E657720486173682046756E6374696F6E\
+2C20627920526F737320416E646572736F6E20616E6420456C6920426968616D:\
+8A866829040A410C729AD23F5ADA711603B3CDD357E4C15E
+
+[Whirlpool]
+:19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A7\
+3E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3
+
+61:8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42\
+D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A
+
+616263:4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C\
+7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5
+
+6D65737361676520646967657374:\
+378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B\
+8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E
+
+6162636465666768696A6B6C6D6E6F707172737475767778797A:\
+F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B\
+08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B
+
+4142434445464748494A4B4C4D4E4F505152535455565758595A616263646566\
+6768696A6B6C6D6E6F707172737475767778797A30313233343536373839:\
+DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E\
+08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467
+
+313233343536373839303132333435363738393031323334353637383930\
+313233343536373839303132333435363738393031323334353637383930\
+3132333435363738393031323334353637383930:\
+466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB601429\
+4D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B
+
+6162636462636465636465666465666765666768666768696768696A68696A6B:\
+2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C69\
+16BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD
+
+[Parallel(Tiger(24))]
+:3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
+
+[Parallel(MD5,SHA-1)]
+:D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+
+[Parallel(SHA-160,Tiger(24,3))]
+:DA39A3EE5E6B4B0D3255BFEF95601890AFD807093293AC630\
+C13F0245F92BBB1766E16167A4E58492DDE73F3
+
+[Parallel(SHA-1,RIPEMD-128,Tiger)]
+:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709CDF26213A150DC3ECB610F18F6B38B46\
+3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
+
+# This is mostly just a tricky test for the lookup code, it's equivalent to
+# "Parallel(SHA-1,RIPEMD-128,Tiger,MD5,MD4)"
+[Parallel(SHA-1,Parallel(RIPEMD-128,Parallel(Tiger,MD5),MD4))]
+:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709CDF26213A150DC3ECB610F18F6B38B463293\
+AC630C13F0245F92BBB1766E16167A4E58492DDE73F3D41D8CD98F00B204E9800998ECF8427E\
+31D6CFE0D16AE931B73C59D7E0C089C0
+
+[Parallel(MD5,SHA-1)]
+:D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+
+# Lookup test: TLS.Digest.0 is an alias for Parallel(MD5,SHA-1)
+[TLS.Digest.0]
+:D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+
+# A tricky one
+[Parallel(TLS.Digest.0,MD5)]
+:D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709\
+D41D8CD98F00B204E9800998ECF8427E
+
+# MARKER: MACs
+
+# MAC format is input:mac:key
+
+[CBC-MAC(DES)]
+37363534333231204E6F77206973207468652074696D6520666F7220:\
+F1D30F6849312CA4:0123456789ABCDEF
+
+:0000000000000000:67C6697351FF4AEC
+
+29:616FE88F809D55FE:CDBAABF2FBE3467C
+
+C254:AED0202A4D19E0E1:F81BE8E78D765A2E
+
+63339F:69E2BBE362FFA373:C99A66320DB73158
+
+A35A255D:99AF085AE0872883:051758E95ED4ABB2
+
+CDC69BB454:346750C009F85AE7:110E827441213DDC
+
+8770E93EA141:457FA6D39A704CDB:E1FC673E017E97EA
+
+DC6B968F385C2A:725FFF0F41477E42:ECB03BFB32AF3C54
+
+EC18DB5C021AFE43:1D119FAEB0BB44C3:FBFAAA3AFB29D1E6
+
+053C7C9475D8BE6189:E4DD5474534FE9DA:F95CBBA8990F95B1
+
+EBF1B305EFF700E9A13A:BEE63E65CAEFA450:E5CA0BCBD0484764
+
+BD1F231EA81C7B64C51473:495FF947F6665F45:5AC55E4B79633B70
+
+6424119E09DCAAD4ACF21B10:53C806C8B69CF03C:AF3B33CDE3504847
+
+155CBB6F2219BA9B7DF50BE11A:2CFD97F2BD38C7A0:1C7F23F829F8A41B
+
+13B5CA4EE8983238E0794D3D34BC:A83C88744DF51267:5F4E77FACB6C05AC
+
+86212BAA1A55A2BE70B5733B045CD3:112C46B74BD7D1EC:3694B3AFE2F0E49E
+
+4F321549FD824EA90870D4B28A295448:F12831C24A551F5C:9A0ABCD50E18A844
+
+AC5BF38E4CD72D9B0942E506C433AFCDA3:0AB4EC81A81F5C6C:847F2DADD47647DE
+
+321CEC4AC430F62023856CFBB20704F4EC0B:B2D3297BE75E9505:B920BA86C33E05F1
+
+ECD96733B79950A3E314D3D934F75EA0F210A8:0AA5F1B82E138AB3:F6059401BEB4BC44
+
+78FA4969E623D01ADA696A7E4C7E5125B3488453:7143592230891CC9:3A94FB3199903257
+
+44EE9BBCE9E525CF08F5E9E25E5360AAD2B2D085FA:90E6F543EDA1AC82:54D835E8D4668264
+
+98D9A8877565705A8A3F62802944DE7CA5894E5759D3:491310A9E2B8B18C:51ADAC869580EC17
+
+E485F18C0C66F17CC07CBB22FCE466DA610B63AF62BC83:\
+302E436ABB2B6193:B4692F3AFFAF2716
+
+93AC071FB86D11342D8DEF4F89D4B66335C1C7E4248367D8:\
+1ED636A10A187609:ED9612EC453902D8
+
+E50AF89D7709D1A596C1F41F95AA82CA6C49AE90CD1668BAAC:\
+2A02740B45449296:7AA6F2B4A8CA99B2
+
+C2372ACB08CF61C9C3805E6E0328DA4CD76A19EDD2D3994C798B:\
+CEA8016EAE33A92B:0022569AD418D1FE
+
+E4D9CD45A391C601FFC92AD91501432FEE150287617C13629E69FC:\
+E584507E7606DD42:7281CD7165A63EAB
+
+49CF714BCE3A75A74F76EA7E64FF81EB61FDFEC39B67BF0DE98C7E4E:\
+5A09D5EF7B21251E:32BDF97C8C6AC75B
+
+A43C02F4B2ED7216ECF3014DF000108B67CF99505B179F8ED4980A6103:\
+3AA4E5750CA579D9:D1BCA70DBE9BBFAB
+
+0ED59801D6E5F2D6F67D3EC5168E212E2DAF02C6B963C98A1F7097DE0C56:\
+FAC262455D9691C6:891A2B211B01070D
+
+D8FD8B16C2A1A4E3CFD292D2984B3561D555D16C33DDC2BCF7EDDE13EFE520:\
+32127540A949B873:C7E2ABDDA44D8188
+
+[CBC-MAC(AES-128)]
+
+# A test vector from InSiTo (taken from Bouncy Castle)
+00000000000000000000000000000000:\
+66E94BD4EF8A2C3B884CFA59CA342B2E:\
+00000000000000000000000000000000:
+
+# Randomly generated
+:00000000000000000000000000000000:67C6697351FF4AEC29CDBAABF2FBE346
+
+7C:A2F5C113EBEE0F124B649287C7F7986F:C254F81BE8E78D765A2E63339FC99A66
+
+320D:5C787D4CDAF3B4D106A7AA09F41BCFCA:B73158A35A255D051758E95ED4ABB2CD
+
+C69BB4:B32F25C34E061A972C49E4B0A0678AA5:54110E827441213DDC8770E93EA141E1
+
+FC673E01:B5D6A0E8F3202BFF37796DB5EB920B7E:7E97EADC6B968F385C2AECB03BFB32AF
+
+3C54EC18DB:F3896484B179F90BE3B62DCE3F748C52:5C021AFE43FBFAAA3AFB29D1E6053C7C
+
+9475D8BE6189:100D2CDA97B85428D785D9EECC8D51E2:F95CBBA8990F95B1EBF1B305EFF700E9
+
+A13AE5CA0BCBD0:\
+92A7A024C4F6D8C82C53030545C23C10:484764BD1F231EA81C7B64C514735AC5
+
+5E4B79633B706424:\
+E235CFD4C307E2B3D44199E83E5D83C6:119E09DCAAD4ACF21B10AF3B33CDE350
+
+4847155CBB6F2219BA:\
+2379D24A48EF60E46807E92C1A602AA6:9B7DF50BE11A1C7F23F829F8A41B13B5
+
+CA4EE8983238E0794D3D:\
+D6DA42CAE5C664F3C4D597CF6CE1DDD7:34BC5F4E77FACB6C05AC86212BAA1A55
+
+A2BE70B5733B045CD33694:\
+93990491923BF761B3220C1E45ACD359:B3AFE2F0E49E4F321549FD824EA90870
+
+D4B28A2954489A0ABCD50E18:\
+9B14531370EE1EFFCF5A3BBC2161D25C:A844AC5BF38E4CD72D9B0942E506C433
+
+AFCDA3847F2DADD47647DE321C:\
+EB597AD53F1B208B4FEB5C20D78545AB:EC4AC430F62023856CFBB20704F4EC0B
+
+B920BA86C33E05F1ECD96733B799:\
+91C3626B64EA3B16E15C2F9B32189C68:50A3E314D3D934F75EA0F210A8F60594
+
+01BEB4BC4478FA4969E623D01ADA69:\
+F6251F1A89FE388121DED78B8CA9FD7C:6A7E4C7E5125B34884533A94FB319990
+
+325744EE9BBCE9E525CF08F5E9E25E53:\
+E55A004723589CAA843140BA5AC52119:60AAD2B2D085FA54D835E8D466826498
+
+D9A8877565705A8A3F62802944DE7CA589:\
+53A217151AA961BBF0C7AD4AFDCB9B5F:4E5759D351ADAC869580EC17E485F18C
+
+0C66F17CC07CBB22FCE466DA610B63AF62BC:\
+CE21D27F4D455511CD327D205853EE85:83B4692F3AFFAF271693AC071FB86D11
+
+342D8DEF4F89D4B66335C1C7E4248367D8ED96:\
+4DC9B5ED541B7382F0FCC7CFAB5AAFE0:12EC453902D8E50AF89D7709D1A596C1
+
+F41F95AA82CA6C49AE90CD1668BAAC7AA6F2B4A8:\
+2FB0B595042C8D7AD592583D7E6C76F7:CA99B2C2372ACB08CF61C9C3805E6E03
+
+28DA4CD76A19EDD2D3994C798B0022569AD418D1FE:\
+AC464531064DA66A2F8591AFAB2931D0:E4D9CD45A391C601FFC92AD91501432F
+
+D4A628D05B1663A1BABEA82646DE1005197A63C1EB5C:\
+A16EADA7B6D32D01FE75759FB6DE2E1D:F466C626BC51E907F0BDAE188D092EF1
+
+ABE8AF530FF6311FFB4B995F0C84BB00EA8226A7D30FAE:\
+7D980A5E6DA633CE4FED22E815A1C5AD:C3CC5CDB5A660A4B11F2FA6401F09621
+
+ECE1BA4BED3F06ED298813D05B237F1EEFDBFA4941049452:\
+425497C221479FC5696D3078D062E725:F68FB7F87F4D196B2ED3B61B12BD083C
+
+451B0CA13E8BBF2E67B977A8BD0CFBB49BB2AC1AFFC5862D98:\
+90029A6EE195A0665D02997A844BE499:3C48ABF950E73F6BF3E0AA7F9FD8E659
+
+4F8E165B89CAF63B76113A3B9767D4D3AF7FCDFF660C6B59EC15:\
+BCA39FFF3C95AB00DACF2B2A9A37C7FE:D88BEDBEE43C4DFB98D6C58E123C9F4C
+
+7736B44B0A63CAD76330E3CE8ACFE3625AD0213F0C6E3AA444FF33:\
+D55DC707BA4568B0642E3D70116308D1:563BD2A3B30957FE13BAC9EA1DF9CDEB
+
+839CCEE6F69E0735AB756F4FB96F8210AA55B35D5E0A5C71C4255BE2:\
+295F3F2DC91B300874147AADBF2132FE:1E28CDA2C49C88BA3A8FF0E5045F35BD
+
+CEB7CD790C80D66A8A32DB4F573631765EFE18229AA0DDD52FCDBA332C:\
+049AE1796CE825B2ABB88AA1EBE8D7D2:EFF0FBA7BE74B33E4A1EC97DF918D430
+
+494A8E4762B1E2028EB7315B7164876155820813F6BB5141D91ABED33292:\
+AD921BBF28C028B76D9E1B4F92D36DCC:037BDD91C33F42A542D05C732BCDD8B3
+
+2E2D3536402CF2916DCBAC2B9EDEBDA15A9A331DDA75C21C461E8F71EB6724:\
+952D487FE1B8A1F63B26B2027217AC14:1A945A50D4864266F30E121EACF0DB4E
+
+4A76816750F6296C3C47FBAE3363D24DF72C9DCCB2E032A5EE44C39A349FE87F:\
+ED1B41F593FF135A1E6DC7C85A2F1A2B:1569E6656010D19C57CC4A8A2F1DD727
+
+4975F3FC5525A1436965DD9D04C61C192F037E8F134F2C6A1B76F54B93CC72DD41:\
+29326E91479F46720D9D1B067B10E617:65D9968A7AD9F3DFB790E37DADFCACB0
+
+7A3CC3C9682DE5DE223072EFA24F300728C791A2A08482571465D4C1628171DCBD34:\
+440A055C9D93DE336B725E0FAE8BCB3D:A625628B0384BB75735DC4A464EC6BF5
+
+8F0B7911638D76374FD8B8C0B575F55B9A57E69EDBA1134FFED8F362C45E575369D064:\
+345B392931218A9395F08BD1A45A9B43:CC5DDB04ACB3BC6D683262C3CCB9A96A
+
+944A7EE34856D6AA1A34016E9ED1D26A2FAD6EDB612B48C95DAA8D29633694F88112DBC9:\
+2D49E335B07A2519287CDA50D482FC48:68B27482E675F08447C3EF76705D51D1
+
+889A9BE544280FA85EA3A0DFB57BA91D2D1D9F14929098D953874FC3E5A1956D3B30537F58:\
+900A6FB8FD5661FF12B7F391279DB085:6227B605C796BA433FD7705C7684EE06
+
+1DC859A4171D89B8B2F7F3E24A733AAC9AF0B162866BA5C5421521B89A10BFB7D8185BEF35E5:\
+096DCD92F3919145B298201BC3820612:A8E7DC9BC9260E03D2A9F4830B7AEEB0
+
+4030C561E85F71A71649C07239F557E1DD337CA6\
+598BAA2B349EAE3F189CEF58CCB4BAB4142B5C:\
+2E8B2AF6CFF3FD6AF55898BC1374609D:2A751C9CAE11F38FEE260B957F963FAA
+
+CADD5809F5F4F84EC0AD0875C133D1EBA8ED8856\
+FE7BE5EDA2F1822187C1CC529E245B931954E1D9:\
+351E0741D63B5CCED0131A483C3B89F0:01E94EC21D1FADC50C351C0BB101F853
+
+F27A747A3B40CCD965276C7E7B4E577C37A63E54\
+C5EC1AD22136DDD237D5252A4F9AA48ADA70633F97:\
+5F144222C4B8C33CA82A85CCC177A0AF:CFBD131D158F55BBCEA980BAC352DBF9
+
+2FAE3104D35B536DFFDD486F4087061045192D5A\
+A98215772C9531EFE80CE917BA1A1C8E756FFB744D43:\
+5FD061418DDE0BB0A8A3E6A4FD5BD2A8:E38DCBE99D1003CB6AAC4D7F23791454
+
+69FC6052141B6C30A9E19FA455ECE8387AB32117\
+C324E22DD030ACF3A9C04712BDA864D1C3D0016CB1A010:\
+73E376B5D0B9466453438B5CEFB27EEF:068DF83E07AB601E6E84019B55314748
+
+DA0890EDC5385196FB229767D33777DAC47018CB\
+1B78EA8AFDEB25521C6D9AF6752AE33A6235D05D5767C42A:\
+03F54C4F6B9E5E214BE93289CB2F2D4B:9E3C0463AC1D2EC7951851920377E41F
+
+E47F1659A9F9930C2E636985CA2EB0686AB4CB16\
+D1FADD67122FF916A6DE358A5D4BE30645761273D97CF9A3AA:\
+9FA99D925751C9613D3A8D42E3B604B0:A90B145DD72A2FD10796E3368FF9DC6D
+
+2F66CA7A49D1BFBFE333985F2C3B09D5471D321E\
+4761EF4FF7D28587CC62F4FBC8BF75129035D173686AD394A5DC:\
+BF0557B787C01A589BBD6EBB83F3A330:69ECFA9B0A41FDF990F4CC167B987870
+
+[CMAC(AES)]
+# First twelve vectors come from a paper, they were generated by Eisuke Kuroda
+# and Yuki Ohira at Ibaraki University. The rest were generated by me for the
+# EAX specification.
+:BB1D6929E95937287FA37D129B756746:2B7E151628AED2A6ABF7158809CF4F3C
+
+6BC1BEE22E409F96E93D7E117393172A:070A16B46B4D4144F79BDD9DD04A287C:\
+2B7E151628AED2A6ABF7158809CF4F3C
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411:\
+DFA66747DE9AE63030CA32611497C827:2B7E151628AED2A6ABF7158809CF4F3C
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+51F0BEBF7E3B9D92FC49741779363CFE:2B7E151628AED2A6ABF7158809CF4F3C
+
+:D17DDF46ADAACDE531CAC483DE7A9367:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+
+6BC1BEE22E409F96E93D7E117393172A:9E99A7BF31E710900662F65E617C5184:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411:8A1DE5BE2EB31AAD089A82E6EE908B0E:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+A1D5DF0EED790F794D77589659F39A11:\
+8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+
+:028962F61B7BF89EFC6B551F4667D983:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+
+6BC1BEE22E409F96E93D7E117393172A:28A7023F452E8F82BD4BF28D8C37C35C:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411:AAF3D8F1DE5640C232F5B169B9C911E6:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+
+6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
+30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
+E1992190549F6ED5696A2C056C315410:\
+603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+
+# The rest were generated by me and are non-official
+:146843CEFEF83BB230862DEE5288012C:FBFC57D01402E2527D11C008C041D51F
+
+4C:3FD7EC49061ABD552D6FA2685FF77388:556813A5E6DC9A926FB235991CA1A014
+
+258B:80BC1B9501710D77C01451732517F272:6195FB30EABDBEEF1C5CE5E2CD533893
+
+D1EF53:B708B2BDDEAB33BF33AAE5B47C8ED59B:7BB3D07953D5D76252B2C73642F1C829
+
+84878883:D8E24AF6410BE6D26FE65E05DB95C1A0:18D366221A8BDAD5DD6483A388163EF5
+
+721CFD4147:8F8ECB42EFE42F708D0EF849B4180627:2E0C3C02080D6B4C6A01FABC78FCC2D2
+
+991225136F00:2B73C3006233572AD1AF399539723018:A157A82608FD6228D0F08D785B1AAB24
+
+350183544EB437:D25C063089641481A482D02BAE21DEB0:\
+DA042063FE9E16CBA7EA06345E479DB5
+
+424ADA19952F4588:2625B8C34C00C1F1BB066BBCCBFF9BCA:\
+8DC221212A006704B5DB69FDFE17FCF9
+
+8596E11E94EA19CC3A:86A9ACE5C41B661924C8D4CB02335E0F:\
+B7F6065E06187815BCEA2B8260C4968A
+
+7C82BF2335D8A2E21C7A:836A7DC8C531AB6CFA8022132D88B4FD:\
+43929194A29B904776D80925BCDDA258
+
+70202B9787517E4E1135C3:2C05A0B0ED6D8425347C07AC28CCE816:\
+F587DAD7CEB57FD9D205B1FBA1C7CD48
+
+AFB34746EDC8281368ADB521:01454B9D291553F7B2832A88F0D4F4A9:\
+19B140930E41923A1381B76133A28067
+
+C35C54CA3855817DC78E9E3187:A0FA07F0E142234072A12F0512197ECD:\
+C9D0F494B96DE372B33D8507EA2AA2B3
+
+A601BF53B49B3CBED0CFC259C96D:0BA5CC599A16EC3965A5E2FC53AE2016:\
+2767C4F69FF145F1226863771AC86B90
+
+3581A17D977891E5EBA90C547397A1:6A8EB76EFA42243E15A7CE5913298331:\
+4D1F72F544CE74099E135956FAF88FF8
+
+1E28DBAA317AFA919A0F97FE25B3C8A1:1DB868DE86D1E6ED593060147B78E08E:\
+C97C0A1C1E2F7327331FBF3337846251
+
+01702E80410F607CE8A85041E0419FE88A:666315D7F0A1D25BD69E7C11E0220258:\
+5E0848CEB6E1469C33B9C397C6212608
+
+DFC8914D867E651B30F5910397E6DEB9F140:137C3A9C80A9FBAE82B1B53586EED7DC:\
+DB210A614E72085F8681A82936893EE6
+
+1C8EF80E2D646CE28406C4312000F18E95D82A:B964FEC670CD39AAF35D2DC10D3071EE:\
+BF6E95E79CFF45B78B60B523682A67F8
+
+3DC82D1710367C124696CAA6760F1C01B626E065:7F6E14CF8020207D74CB786FCE9F10C0:\
+768AA70ADFAF6738DC8FF2A85C34B6AE
+
+91D45A498BB9A093F6F678C495A7EF12C881A782E0:0BCFCBF5C1011EED7453CAEBEFEDDFC3:\
+2B7D219195BA5F620E18C9628F3611EC
+
+91B47BA5E78F1D059BE584C388D76CB7F55079BAC1EC:36790C9BA09C76E402F22D4FE9127C9C:\
+A92F1EE4C1C4717339FA7A4305851B5D
+
+3B2E8F8C7838FDE9610CE6FCC10F854AEAAE3A2184832A:\
+6B642B7D118A78A160B7EA0E11789A99:8989DA29F037D54809D39E0F21BAD66B
+
+9951105BBA18783C1AF2DC8F88A9B98C9E9C5502A1CEE559:\
+7C05D6851E344F0F725CE228A5E91F40:2903F5E3C9630579E3B7F9E97E141494
+
+94D6C4C8EF018F83115A27B01218A7CE29A715FE32C90AAB84:\
+1C10A73B946DBFABCCBB21C93990AE5A:F7BC110047D58BB40C79BB46697AF357
+
+DB170C579267ECDD54DFE24695B56459160530EB62EC7A9489A3:\
+C27600E6310E45A698C5F5F8BEDFB6DF:1EC461A0D7D45DBB8F329D28FD1120BF
+
+52ADDFA309053D90A9C807EBB9B85D28C8BD6F6463247B20726170:\
+03E0A715698908157EC2CF38A818092C:726F0F60469CA5B517BD4EE64FEC2198
+
+B47B761A8FBA35F68E25B097A17191F2A9DB4D34162E1242BFEAED88:\
+97442B172B28A4C98BD1CB2A4D1634F3:FA51384A5B8B3BE1DD2C91D8ABC9E262
+
+264D32E2A14653254743926ADB7CBB4DDF1C55DD0F24429DBC4BCF718E:\
+A6945844614FB76BDC75BD488637E34D:5171636008FDF3CF658D980932B44394
+
+BF685A96FE74FC30B14285B1479A1591D92CDAE6BBBE678A193D3AB7B360:\
+022D9710FC7641F76728136323870565:644A3F16490C8FE381CF5BD6B09E7525
+
+415D0574EAAE71B878EC707F50A850A196CE448AB4274701CF27CD0EF5A2CC:\
+C9CF027DBAF268A9B7304AA8E3F5BAF3:D151ED7EA3F4E6E3BD4DA7E0CC3FCED5
+
+A39FA8261CD507B473C53E7B6BC2A859AF5A1E7E38F3938230A23470E7DAD48A:\
+79171CA85E8F2821B0889A259491CFDB:2DEEEDB2C4CEDED515493D0EB23F45A6
+
+F688810E10DCFE4A64:61364AD45A2E15C8EE119CA8C36FBFA9:\
+D5505FEB66C306AFB167E1B240682C1A
+
+C280CBC1:76EA6672EEE06EE1050365F4CB404D66:D1CB929113E995A13D9E0B5FF068CF2C
+
+F610:5AFE8C966695BE3B4FCEA22F5C27B059:A7A252D3AB457702263B837F48814AE4
+
+3D5E:41246CF56814027408D33634109C9C9D:7B3ED445B003A4839266B017B7F8226D
+
+741D:BB170239A6A86DC4906F8FA56222F883:25F10513DAC4792CBC0A76A1603E3CFE
+
+2D225860EF0FF7FFFA2040C60077560E5AB737B9F9AA689C11B35480AEABBCDB\
+CD143CBD2433BC1E54FDE454743B63CEF29A87EB44EF8756A2DBD651:\
+D36509415886167C44D9208EF5DB4C5A:900EE360285E4273AFA3674BB76FFB57
+
+DDE273DA5EE3F41B370A7C10B706FE82AB82E7813BA44162EA99514218C3A4F5\
+A517CF03FBC41E32CE9A4385A141074CC3EECDFE930E607DA8B1C0C07464B61A\
+7C851D77493CA918D6EC9D772DA5C3F19391EF269F50A44701640876C8BE9044\
+43AD:DE5E5B64B403E3772CCB13E175C734FE:\
+EDCBA48465D6B8BDBF274658EF587F72
+
+F4FF3C7E2F56F4:E1D41EC244EBC98373457A95685D0EFB:\
+76BF48A88F0F5531C4D1A14846742CE39B8D8827F863ABDA
+
+B664B2C219D625DC472EC765605E6D5822681C5E9FFD10645B:\
+3FC310BAF6F1A39FA25AE7DEA104EDA9:\
+19449A56180CB52462C37109EA1D329708F7C4FBC43B37E1B2C55E38F5551C0E
+
+6540E334A0024EFCEB621E91B94AB6E5A6D4D085D986410B113A5B6E319B9D96\
+DC80CA7C8319786E7B96FF34E0B6:\
+DA97AE2997EB3E74B35C6A6FD5471F8C:\
+F0D16D00B5CF601F1A5BE91422A5562C252C5C1DEBDF05B5BC328BF8505DF740
+
+4DD7C1974501D1E454D23C509FE2265BC375CA:\
+CB1C20084C5DACB3270F118633DB4F33:\
+420D2C372E496D403A9F520158FCCDA6D6BCE14E6EAD2B90918B919E5E8621A0
+
+E2C0FFB463EF4B6EC114322FAFB8:D25D89E8CE9685D975C645FB2A19E50D:\
+970BD2C9C46E9B85E13949E13D39B466A8070F40570D1070
+
+85380139C424704AC24497634E9CBFCEE21E0F99CF3AC8F9C6AE2D6FDD091363\
+41149C05380C4FFA50E65D9E831D6C653B7BFE0BB5C6047C7431EB513AFEB47B\
+1250804B5DD045ADB6A34C39C0B89EFB349C06E9620A65D63C5028764EDCF261\
+2D72AC8A42F137F9948332543CD150706D5659D061BFA69D0FCE135EAB05BFD8\
+786B62BA5C99B3F11DE64559B795C924EC22F44DE19BEAF169FD4F14030EEC7B\
+794E35D5E8E9C6:\
+3015A6D16CDDF7E1E8C28521F4064A28:FB565C5DB38C2237869ED34CA10A055C
+
+7B326530160FE8CFFB68704022DE43BBB54FCD83BF4C554774BAC625441C1DBF\
+4F82F06591D8348C40A4CD6282101D3860EBBB1F371166ABCB2DD00F49EDCF98\
+6FBFFD0197328DD7D65A39596B5791CB424CEA795D5024287DF438C7E1075F50\
+C65D515D8FDF3465396DBEA4C44F6F069C597FF9AAA32227:\
+39F2933F156616549749CCAEBF682322:\
+0398D70C12CE6F7ED28828647FB18A56
+
+# SSL3-MAC vectors were posted by Thomas Pornin to sci.crypt
+[SSL3-MAC(MD5)]
+00:A856430AF077AE2C328D9FFE4E56813A:0123456789ABCDEF0123456789ABCDEF
+
+01:96279D16E7812EDDA2EC64DAC996348F:0123456789ABCDEF0123456789ABCDEF
+
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF:475006C7DC7A3F371352D948B4BE950E:\
+0123456789ABCDEF0123456789ABCDEF
+
+[SSL3-MAC(SHA-1)]
+00:DD2BA1F4A721F22C8A9BA7350B5CD6838B225827:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
+01:CD6289A1FEC0BB104C271BE488343BA92328B073:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\
+0123456789ABCDEF0123456789ABCDEF:98E523EADE38B3BF4EBF51D7EE814316C9EB3159:\
+0123456789ABCDEF0123456789ABCDEF01234567
+
+# From draft-ietf-tls-seedhas-00.txt
+[HMAC(HAS-160)]
+4869205468657265:\
+F5B44115A53F716B6F488DE1098EE7C251418623:\
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+
+7768617420646F2079612077616E7420666F72206E6F7468696E673F:\
+A74547C1EF0AA147C7428AB7E71664549BE2A412:\
+4A656665
+
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD:\
+E4C91BC71782FA44A56BE1A34AAE167E8FFC9734:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD\
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD:\
+14D1055DA875222053BF1180BBEF8892EBA3AC30:\
+0102030405060708090A0B0C0D0E0F10111213141516171819
+
+# The RFC has this one wrong
+546573742057697468205472756E636174696F6E:\
+124131A293F1FDF3D6B11E2B7F7A1F5B12E42D58:\
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+
+# The key is HAS-160(AA x 80): prehashed because Botan's HMAC accepts
+# a key of at most 512 bits
+54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A\
+65204B6579202D2048617368204B6579204669727374:\
+63750D67AF40E3FDE33526545D300972A1527053:\
+A766901C8630F7DB3A3FC2A9747A6E2593452BE7
+
+[HMAC(MD2)]
+50752120507521205075212050752120507521205075212050752120\
+50752120507521205075212050752120507521205075212050752120:\
+3CC6A661CC76DC9A617C967EA7E1CDC7:\
+FFFB66FFC4F304CBF3B2A3E293D856FC3B30A9DF82DF3D17DDC300215A89CF23
+
+43617264436170746F722053616B75726120346576657221205E5F5E:\
+93B02F8CA34C52F33A9BDCD75D3558E7:\
+93837AF03A1378796B2234EF3CA009AFEE599FE446EF7B3043BA273A5A4DD9
+
+53616B757261204B696E6F6D6F746F:3F0EFFE820B7F02939656A3092F9E657:\
+17DB32EAA8FF99C81EC3C063915A122A51FD32D70C76DB07D788
+
+[HMAC(MD5)]
+4869205468657265:\
+9294727A3638BB1C13F48EF8158BFC9D:0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+546573742057697468205472756E636174696F6E:\
+56461EF2342EDC00F9BAB995690EFD4C:0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+54657374205573696E67204C6172676572205468616E20426C6F63\
+6B2D53697A65204B6579202D2048617368204B6579204669727374:\
+6B1AB7FE4BD7BF8F0B62E6CE61B9D0CD:8FB6AB01840023EC453ECDEC73DC1B66
+54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B657\
+920616E64204C6172676572205468616E204F6E6520426C6F636B2D53697A652044617461:\
+6F630FAD67CDA0EE1FB1F562DB3AA53E:8FB6AB01840023EC453ECDEC73DC1B66
+
+[HMAC(SHA-1)]
+4869205468657265:B617318655057264E28BC0B6FB378C8EF146BE00:\
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+546573742057697468205472756E636174696F6E:\
+4C1A03424B55E07FE7F27BE1D58BB9324A9A5A04:\
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+54657374205573696E67204C6172676572205468616E20426C6F63\
+6B2D53697A65204B6579202D2048617368204B6579204669727374:\
+AA4AE5E15272D00E95705637CE8A3B55ED402112:\
+4CA0EF38F1794B28A8F8EE110EE79D48CE13BE25
+54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B657\
+920616E64204C6172676572205468616E204F6E6520426C6F636B2D53697A652044617461:\
+E8E99D0F45237D786D6BBAA7965C7808BBFF1A91:\
+4CA0EF38F1794B28A8F8EE110EE79D48CE13BE25
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD\
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD:\
+4C9007F4026250C6BC8414F9BF50C86C2D7235DA:\
+0102030405060708090A0B0C0D0E0F10111213141516171819
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD:\
+125D7342B9AC11CD91A39AF48AA17B4F63F175D3:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+[HMAC(RIPEMD-128)]
+4869205468657265:\
+FBF61F9492AA4BBF81C172E84E0734DB:0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD\
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD:\
+BDBBD7CF03E44B5AA60AF815BE4D2294:\
+0102030405060708090A0B0C0D0E0F10111213141516171819
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD:\
+09F0B2846D2F543DA363CBEC8D62A38D:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+546573742057697468205472756E636174696F6E:\
+E79808F24B25FD031C155F0D551D9A3A:0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+
+[HMAC(RIPEMD-160)]
+4869205468657265:24CB4BD67D20FC1A5D2ED7732DCC39377F0A5668:\
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\
+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD:\
+B0B105360DE759960AB4F35298E116E295D8E7C1:\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD\
+CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD:\
+D5CA862F4D21D5E610E18B4CF1BEB97A4365ECF4:\
+0102030405060708090A0B0C0D0E0F10111213141516171819
+546573742057697468205472756E636174696F6E:\
+7619693978F91D90539AE786500FF3D8E0518E39:\
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+
+# From draft-ietf-ipsec-ciph-sha-256-01.txt
+[HMAC(SHA-256)]
+616263:\
+A21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181:\
+0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
+
+7768617420646F2079612077616E7420666F72206E6F7468696E673F:\
+5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC3843:\
+4A656665
+
+6162636462636465636465666465666765666768666768696768696A68696A6B\
+696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716162636462636465\
+636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D\
+6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\
+470305FC7E40FE34D3EEB3E773D95AAB73ACF0FD060447A5EB4595BF33A9D1A3:\
+0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
+
+4869205468657265:\
+198A607EB44BFBC69903A0F1CF2BBDC5BA0AA3F3D9AE3C1C7A3B1696A0B68CF7:\
+0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
+
+546573742057697468205472756E636174696F6E:\
+7546AF01841FC09B1AB9C3749A5F1C17D4F589668A587B2700A9C97C1193CF42:\
+0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C
+
+[X9.19-MAC]
+# The first three test vectors are from ANSI X9.19-1996, Annex I
+31311C3931383237333634351C1C35383134333237361C1C3B31323334353637\
+3839303132333435363D3939313231303030303F1C30303031323530301C3937\
+38363533343132343837363932331C:C156F1B8CDBFB451:0123456789ABCDEF
+
+35383134333237361C3B313233343536373839303132333435363D1C30303031\
+323530301C393738363533343132343837363932331C:\
+AB4884061A159618:0123456789ABCDEF
+
+31311C3931383237333634351C1C35383134333237361C1C3B31323334353637\
+3839303132333435363D3939313231303030303F1C30303031323530301C3937\
+38363533343132343837363932331C:C209CCB78EE1B606:\
+0123456789ABCDEFFEDCBA9876543210
+
+# The following were sent by Darren Starsmore (he has access to a commercial
+# implementation of the X9.19 MAC)
+3330303030323031393543555354303120202020552020202020202020202020\
+202020202020202054303253454154504152594742324C54535435534F414131\
+3939353032323731333339343430303030202020202020202020202020203330\
+30303031304139354558413030303030333144:\
+DBE9EB0FA03838D2:4061610D85685DB0F4D9F1C8FE15A123
+
+E7EF0EC901CCC8E5E44579A25AAE7FB82FA475ACD95F2DE313C5C2B7BCA63BA3\
+95496C9615347CFA7AF59CD4A31C8DD3C0027F9961AD7C75723E2C2EE467D279\
+B13E10C6738CC0ED815DC125794EF8395177D2B2244E27978D53C571BB97EB6C\
+D6FB324987F3360850F72DC9462502979DD449C1227158AFC41E217FB50CEB8B\
+071ED48E110A966102C42A48E92CDF860028482299A0D25EBEF3DD74FFC9FF06\
+E7D494F8DE2A59E0EE8328D8AF075EAF30A6D1C947A3270596057995CE799BB5\
+4D2FAD2B5A060C48893420383C7FE76C25B8356C5C5D72F262EB88306423E5B1\
+5392DDAD98E9F521:83C4B075AF24AB7C:BB296726F91480CDC432AB3067536EAB
+
+12916051C77047C9EFD1E3A43D0086D9899AA28818BCCC5D8B5A0A848682F898\
+1359E9DAC931A4B902875D3F87E318107DBB98967765F302BFFD8645807FDE93\
+D8C76EA1F8125AFB99B83A209B5331190EC9AF852EA287EEA00D33208C11B364\
+D92106D13360CCCC1807EDB45A1ECD68E77CED161E7404BE8137DE0E49927222\
+B378F3E7D9C0B3F1C7A0A521BE7289A6EE76BC0DEAC0CB6BF7AA79403CEC62EF\
+6456D63D168A2FDD2AD4FEE947878F35FD4B42E70B0E5202B8CC43F4B8A5E31C\
+FBBA5A114489EE6E5DEC57A473E6DA70311C573C2AAA3FE2:\
+31174049F029EB36:214B48AB97E144F1005831C8C97B8EF0
+
+# MARKER: KDF Algorithms
+
+# Format: secret:output:salt:out_size
+
+[KDF1(SHA-1)]
+61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A73\
+6F6964676A736F6964676A736F696A:\
+A0D760447F105CE64DB99FF2FC92F961F24E7D9C::0
+
+61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A73:\
+A0D760447F105CE64DB99FF2FC92F961F24E7D9C:\
+6F6964676A736F6964676A736F696A:0
+
+61736F67696A6F7367696A736F69676A736F6964676A6F696A6F736467696A:\
+A0D760447F105CE64DB99FF2FC92F961F24E7D9C:\
+736F6964676A736F6964676A736F696A:0
+
+617361736F67696A6F7367696A736F69676A736F6964676A6F696A6F73646769\
+6A736F6964676A736F6964676A736F696A0A:\
+DBFEFA0EA12D352C4AE5B0AF17D061E0E2C469A8::0
+
+617361736F67696A6F7367696A736F69676A736F6964676A6F696A6F73646769:\
+DBFEFA0EA12D352C4AE5B0AF17D061E0E2C469A8:\
+6A736F6964676A736F6964676A736F696A0A:0
+
+[KDF2(SHA-1)]
+FD7A43EA8A443C580C0DE618ECC013704505EFF8B5A4A9:79:BF0B2ECD1724A348211D8C0CA7:1
+
+701F3480DFE95F57941F804B1B2413EF:FBEC:55A4E9DD5F4CA2EF82:2
+
+BEEA23BF806E106D0C91F8E87095AB402C433C581088E1236FD20564A8F1AF67DCD2265C40:\
+78F8E7:36C94DC7C2353757E0778323B3DB333BBD57AA8F5C:3
+
+5A6999A96594B0989B89CA72B5C0803043D4DE78709B490EB98610:\
+84C92008:5F0F820B69ECA512:4
+
+C6E227F3F9BB5227BE37D6CE7433022D5F0DFFE18C5777EBAF396F1E40C4:\
+F518EEE6F2:CC06A6F3F9A0AF4CC76D839D:5
+
+CD6356CA771E3FCC4BB548B4E6EE4E3715EB7A4A806E4967B1:\
+E72EC27D6A81:221DA543:6
+
+B7FA7917A833B0C0364FAC414D92DA:8E54D1C86DA8A9:\
+DC32AA175531CF88C8D55A51DA5CAFB314A92C2B52:7
+
+8A14:A2FC623645F9AD29:65A907357B5CBADC5C5EFF7065AD:8
+
+135FF7296DC87F5775B64F8CFF46D366C10A8A98712345CE58CD5839E9:\
+73036FBD1941C7955E:A439FC03312570F9A4C76E5B17FA:9
+
+AD499722078DF83AEC1EC23A507B190740B0A6821F8C:\
+A461A98B6BBBB0FDB0BD:3772601ACF052CD530D91EC7:10
+
+CF99B7A985C223BE83F999D7:735BFCF26A4357F5642964:\
+055396C3E0EE8190DBE10212AE099FF0BC0A8D:11
+
+B640D21A1FECF5E61D79E1E09C2393915D5790EF8080E7F6CC18:\
+6DB9BAE99803B2EB725FA8B3:5AE5506D6306:12
+
+F69885268F3DF8488490419F49CD39A54D0D8C9A3861D375A8BE:\
+2A1EB238B7CB39422DE263E4FD:C1:13
+
+DCF4DF1F6B5D71DF98ECFFE8A4B7C5E7234AFC10CC0C941D853BFC32487A:\
+FCF8D9D4E43318EFC0056EBCD271:\
+7F246E5F44DABCB5B954A1B83D456F022C924D29A21935:14
+
+BD2EDB4CCCB0ED3D01BA03D1A816425E40ACBC7F214126A6775AFE28B0B2646DE040B9ACF0:\
+C669ECC95557FE8E49457576BDABD3:\
+A7E9F261EDC30903056744B123C3D364E979:15
+
+3185AFBCFC621B6F9FFCBB75C7E71A4161A0AA39278676:\
+687481BEF8354C8D48D8F5A5F3D9ED3D:80834249A9A4CFFCD655AB92:16
+
+15723A13E56CA0FF5EE43D8A4BA8284B4A946D861F:\
+439082061EBAE065C434932D981603AE1B::17
+
+92167440112E:3A5DC9AA1C872B4744515AC2702D6396FC2A:\
+45A9BEDED69163123D0348F5185F61ABFB1BF18D6AEA454F:18
+
+208AA86616B4133903946BA8:A267CC65619C84EF5FE1744EC3A92A06B99399:\
+CF08208B76D97F:19
+
+04879F0DB43E33435D53F0DDDC72BEB957F04F2CA5E8FB38DC4F78:\
+F46E2675B807CC42FC1DD4C84A5BEA3AC175B093:2B688B3F6C12:20
+
+AAF175079CB9CD462EB2D4D62440EF18B22AEF1552CE5F04EF0158C177572D21:\
+5A3796C9045712759E6DE769E5049E5829408615DC:\
+48A228E55BF52B89A8FF5FCC3F4EE4F178D406CBA265CF9166:21
+
+901BBA708DAE7365ADCCB7AE056729B5DD610226966B084A02D1E8:\
+8A397BBA8EA862DCD004897304B901784513754E9FF6:\
+3FCD4A2A5D65E4CDF29241573F:22
+
+D20CD658:5C893F99FE81F1E955F2A7CFEC4F50B7CCC890BEAE4768:\
+17D7E5C9E3DB69B28EC9:23
+
+B669EDEC3D9A78:1A4DD8282E8B4D7A739030FF60CD88C4D3C0E5C3A0DEB127:\
+D072D0:24
+
+349AD0D9BEA0D29C:678051858CED59674C06B60EE21D18ACD55C10B049B22F5CFF:\
+D4C8D8DB185F7EBBEC046ADC49A26DAA172F81E3:25
+
+B809759B369EF9B2F34A0254AAE645:\
+1C2C3C95529E4C8E5677F714E122A2E348810379B09689FA4B30:\
+D3EF4B914359E78F253FFC8B9B6D711E257B94:26
+
+20216E8DCC3AA461F9FEFA4BE06F3C63BB:\
+A24D44F5194B4257B92CF85C8493B5BDA52515E18337280C45F005:\
+AD13544336F28B8F1B2615BB9658:27
+
+40923A6409592A370301A859F1E797:\
+4C8919843B73BAA06853E1C8D9D4B18518CD857A624BE3EBBD507BCF:\
+C3D9FCE8C68AFD0F97D21AAE826ADC1EAB6F580F78B139B0B43B58:28
+
+26541874BEBDA8DB76CCD60DE28E65E91CC5F128B9C56F6609185F108337A4A98B:\
+B16B3FAD79618B39D2FB0983BDE7D3E8C17E2DBF2C2853CE8D92191696:\
+BD1D497AC525F091FBFD7389635DA5284ECE:29
+
+5D17A9CFD9994A1CC1F0AAC3C48F60C7DB:\
+1233A118E3B025AF2240F2AB14A61777A1347AE58033B2FFA313946631B3:\
+FC56:30
+
+32048974CBE67FE8B4E6C0D4E21035B2A657E7C5E3592A61A2:\
+5301147F08E1D473F82558F815498F7421D8C501056402F77A186779A6C5C8:\
+D6ABF65542:31
+
+F4E8338789D14BCD31EAE46199DB1A86AC76B8611809DF4D77279F53CB0F6DBF:\
+90C528975E02E3B5A9970B0074C02A691401A7BCAA94A8B731648A1732806D6D:\
+F7A146807292:32
+
+0DE2DADDC876B4B0322B3B995B43B580B4D5DF529F4E29606F825AFA72:\
+41163C646606A0B96EE1FA2783AAD072260670283870BB8A510A693D01F9C0A5D6:\
+BECB7FA1A65C69:33
+
+CF00B2A31485DCC4D6F9296D219F4831CE80A0043CA937F9712DCD1C0AF02BD9F0DD7C:\
+EFEAF89E578CFC169570F08452C42157EFB9905D33DCD97DF29A4CD626F9DF539E3E:\
+046259C93952F2:34
+
+EE67BFB3A6F4CD:\
+1D02C4CE8D6AF08F2A4E8660718EBF8031C640B7502BE5F1F2EE91CB35241952D63BB4:\
+A85EEB10A12C6B8DE05642:35
+
+BC02C1:\
+6D3B84710944B5A4448455C22D5CF21852123816A33269ECB29DBCB10616978FD5200FB6:\
+E2E57EB395:36
+
+85B2DFCEC6D020E7DD45933451363AF111346D52E1BA4B168D47BE178F:\
+E43AC0F5353A0ED3C35C1EC0BEA6190C49A9F8925E510DB762441BBAF8B798686C1BE6D84C:\
+CA79147C58E3422803290548BD3999F3738A04A8:37
+
+6E757BDFE044D00A96AB79F3CEB27F96:\
+0A18BD32469D8FCA917A80C173C2E01B2C9E2AF978CDE34E5EFF933B563F3B26842778BAD326:\
+:38
+
+26E7CF534DAF8F9243C5CE3297D807D1C6B4F0CAB16AB5CED3C737:4A:8AD8F6:1
+
+166C66F4B39A17A2:8AEC:81:2
+
+8533C513D7D26ECD416DD3DC:030CAC:52474087F2:3
+
+E876D64472865C8F4B7F:A83C863B:BA88B207:4
+
+15AC949219878463A7B1A6599ED9:AA28AD4916:E79A373588F3:5
+
+D288A4BBC027594788F81964C74F:5777F5478B70:06:6
+
+84D3564BA0AA5A0DAC7AD62F88D9373B9DB280D026AF0AE5BCA633AE36C24ABA95A005:\
+934CEDC65FDE09:364A60:7
+
+5977D030DF4051B9FB03167331C6B6366A0F8CEC71B69FFB1FDC9469B5:\
+F09FE23B9C34EFC1:E734:8
+
+26A51955CBF815122460E803F1B399F617A4AE1CEE:\
+17A5BFF10B516A752E:0E33D563:9
+
+EFB7C556790493E3C15B513CCD250FEF4BA7878585B8E50E1009C56BB146B5A0:\
+EC92ACB1367E34CF1361:FD7B:10
+
+F2EAABA8E42ADCC55CD36A2C78DD0325E55C1B4E9C6BE9F77966BFBD623CD454267FFC0BA9:\
+E0DC1C8E9071A644ADEE46:D8D005AB3A3123:11
+
+01A8F53F2BBDFB05D41E9FCCDD85CFBD4BC0502C:\
+1C9D86C49E9F3DBFF9674A11:6E3EAC35BA:12
+
+02414433D5734F:EDB45D5FA17F17147645DD8DC2:70:13
+
+13EC731CB6C29FC4350FE0DE63FCBB5A6F3568E05250099715795D51C5AC10D89883F44E46:\
+AA07990CEAAB482272FCB3A3AB46:93127BA3F25906:14
+
+2BCB12D2E40A5BB81BE4297F9306:3F450384BEB9C9A478F46F051FF152:67:15
+
+4DBF180733:0FDFEE8AF8D926763E28AB284C7B8040:54C4:16
+
+BD3E9044AD45F1E710529172837597E7BCBC2C27505187:\
+0E4FD5D562490C5FFD0A37588344D86347::17
+
+822816:21E8AEDC72151B03D2F9A3E7CD9CA6805FEE:C1:18
+
+7FE688:6701CD19F736B12C067D58FBF0D024E695C18B:C9:19
+
+1EC869F1476B8C7C537E8B1AC4411A10332A7DD06645C835EBBB3CEFD570A9:\
+F04DCD7617D96283E463511A1A9313006EB6BD4E:F338:20
+
+6C78966EAF4DB43ADC3865962F292CDC81:\
+9093D86736C445B12843AD189410984F8B912281A5:D4:21
+
+D85C07E05DDA286A4A1B9191A929FBE1D19D:\
+DCB8FF108AAE1B16901CABF9BAF0AFC4ED1B20A72312:\
+138399:22
+
+597406:AE58662CFE38E861B289EF9E3146A37393C798BB7ABEE0:D5A5EEBC47:23
+
+33460E:6A85B3C6A5A6D0E1734004B788FE84C744BBDDBE42C32ABC:F8A648C9B6E9:24
+
+74BF53754034B0DC:BDCADDFCCA599DBB24A2789DEAD088EEA633E8A15A03B65291:89:25
+
+F6B3A879AEE95C1604EF005F90D35EC4621F6BE5D52F65F1BF192FAD2D22C223D66B9C8454:\
+9FA401DABDDEFE3B64702DB7395950A357CA32A501E43CF6DFFE:F89A58E89B:26
+
+5C90E327068324D80B780A10646E01F1C57D4F67E2BF9322:\
+F95C1618F2F62B9EB4516E0AE68D38658183D30BF3B97B63BBAEB6:C13297:27
+
+F88AEB2006224184F1231BF42D63D2BA69C88ACD47C27996232EB2FCF04647E8D03308D6:\
+A7666ACE2515FBF42334F21F48510174CD8944A7397EE0F0BF38262C:\
+55495A:28
+
+B98B0026B2D40DD0827B58090D2698140A9CBB3B13F5:\
+ECE9B1E55CCF257F2C7BA2B39BA852DB81FE9B32DD08130CB6041CB349:\
+C1AA:29
+
+F8BEF20480916E2762A77D00:\
+1102796B06234073DC6913318D65010A4F4C9E95358DACB3CE0D08857B28:\
+1CE36F6EC8FE:30
+
+80C9D5FD0C7BC1278F74975303D1F94600877754FCE3B8:\
+CFE56E573F2933E1728B3367F4EDAA797BE7C843B89250B98C4EB3BAF2E4D7:\
+EA8332DE20:31
+
+2EDB67D2CC64BF4B62:\
+52E44DB4B04F9792243508B969FF730779CB2A1EDF764324D11C14235B055D30:\
+38D7ED2715EC6F:32
+
+86D77225DB6E5EA176F5DAF433E4C2C804B24FB22F2747FC5D8978189842981F19:\
+02BF3A2F5009054AF526E277EF6AB436BD8B7A53A3E4C2671F1E34556239F97453::33
+
+C73E664D445C0C60C59CEF54F10ACEAA456E6BFB:\
+4E984339A1FB20BD73894494B36CE8C1182BCB0D289BBAB3BBBD366B1DD061BB9E16:\
+F8C579F9:34
+
+0651E961BA3374DE7248CE52EFC948809C20B8:\
+36AEC134DF567B1FBF448D0C56C6B62E40A375BDC74A2D44E415BCD105B48317145D95:\
+43:35
+
+BF5BB2:\
+6F7533ABD09546770D6E71769A645B0D3BFA6D578B7B9B182D25CF8F8B4394C2BBDCECAE:\
+159B4039D67403:36
+
+64353C0E4D64C60C3F2FEBE1C6466E57FB28:\
+7B80CD69345CBA9E46186372DD6602F2CB55496364CEEA96823110E28CAA68BB200F56F37F:\
+EF4AAB69:37
+
+6FD4C3C0F38E5C7A6F83E99CD9BD:\
+02AEB40A3D4B66FBA540F9D4B20006F2046E0F3A029DEAB201FC692B79EB27CEF7E16069046A:\
+DBB986:38
+
+[SSL3-PRF]
+6E60:D626B75AB8BD4F5B9458BDDA8589FD39:17FEBCA565786528F84A:16
+
+66BEEC6EDE7FCDF50B76EBCD5C0FE0A472F2EA8B1E2BE2971E49CA:\
+EB:5C461D77ACDB631ABAE2E7AFED5E9ABBBAA99B:1
+
+1171D78F812512DEFBA258574E41F2832BB9B359EB0CA79E7669:\
+2C8B:73D677854D88F62417774A2A5645CCAE9C1AEF8E9D1B48:2
+
+6162DEC990B2132C30C153F2B200:1B9430:2666F0B22E8E48DB1640:3
+
+D3C0DD69C18F17D35C5296FE45F0:C7C19FCD:320C9EEC122C19AFB8E90F72:4
+
+EE6A733EC671DA7477AE18916895A133CC92E23DBACEE2634846CAEF0B08:\
+C264D9D0C9:B7F9722B37389C11:5
+
+97D7F3D2AFB3198862F6FAC8B17CCEFB26:C1CB767626AC:\
+D3583CD13AC119CAFBD44CAEA5AB:6
+
+E87A9BBC656884A13295B8D4DD4645905846C249D2470ACD2BE5:\
+3DC5B6402F451C:542D044668EDC104A9266C2EC79EC37F72A0C6B7301EFDF267CF39:7
+
+7463F0B9F822E17311E47680DC5B505811E9:FE4B1DA4EDA36820:02AB98439528C994:8
+
+EE8999703E5D9C628AA404235F3C94C3A890B1:EF317D3E81DAEF0F89:161DEB5AB705BD15:9
+
+AE531918E679D2D7B32C61BA31415484E9725B2905095819:18D5272345C1695BE38C:\
+A162AC0F0AB41CB80735D1EDAEA3C562CF261C0067:10
+
+8FE402D6ED0BD018A532FC063E7D81D97CDEA7:D61088CA1CE8944B17CD3E:\
+BF7F091B6E0DDB90897B6BF80A4F:11
+
+4279DB52505E7B505BBC26CE0FBF2F4353086C1363:4A84A8E829528393FF890129:\
+8710A8A12B2D18A27A50E5F32C37448A:12
+
+B80B58DAB89B1C4D1335C48E479220E253B8EACFD64319544A:1450E50B7D86B76015930BA420:\
+E9158BA5F6E25D013A37B9D65406E989CB77D05D97B2B04F9C7F26DF987A:13
+
+965F1BC656F01C1C7F977419A5F99FB54FA34548C332EA79B5B0EE:\
+CEE11A3A9A406FE9DA77FE6FB007:\
+3F6FF94F05596ACBAF5AE7CBD97E3FF3233992D988361E:14
+
+657B5F618710AF88BF4F0328E7071D022D02EA5E:8EA957C330D55CC208326CEA06D25A:\
+BD0A575481E823931F68BE84E31DE56B2D95F3ECE4F614CBFD31CE:15
+
+33CE7917528009F2A1011CFCD494B80D4BBFD901:2FB1FDD16FCE41C9C563226A564D1647:\
+81851CC61D3E910E04D5EC38A465:16
+
+40ED568CFC6C0A17866C67B7660C96BF9DA54C:321118AA031C5C9EFF145542B4426C3C71:\
+A3502B96214854E5AF5720E8970D3F240AAB2E21319A88E901:17
+
+12695F5B19541C8B0092418A72A7ED8482F35FCC4A82D4E1C5AE:\
+22BC94F745F6E247054DDA2C772E5D2D3EC4:\
+2CE5F4676C06D0CB61E91F7D751F0F:18
+
+F36E535A1C2C6F6771:6004BBD20BB68E2F1FFC65977807EE25A3FBFE:\
+290BE26068D887AA6E86500E85C606:19
+
+7C7EE43D46AE85D23F0D5264DBD410:0E1FE69316D67CF65D62196C25CC4F517664BD43:\
+FC4A7F986331A012CBDAD765288C2CEC08AAD045:20
+
+C580B05EC577F45434C13640AAB31B:937E22F90D1493317B0B068A44859036905540AF67:\
+6C9F5929EA435A86E117BD586B34F7E4F97794573C0B4C90:21
+
+E275AEB758A949CBB11256E74412E1DA3743899F9007DD5D80A7:\
+69C2640797F38E87F1C870891164F0B31F1A3A02627A:\
+585B267A9E08EF4DBF48F6:22
+
+DCF06E7AC257DA73CC6FC0A086B4:30CCF63491F642A55E45136E42FDD0355DB272502EA1B0:\
+16F0355230F105EB316F558512EC3B51871741:23
+
+C4C38EC6A1EA975D0ECA535B0CC4D6D0:\
+3B50F91EDFDD96CBA8B6329616D4F5964CD8C961CB1D9332:\
+E84EE4D9DC701DE04E250768F2DFB9B6A2:24
+
+7B557AC16D60B74ECAA87641887E6467BAC107:\
+CA148D27F3DC362B0F43C68312058C1CD9B92ECAC2CFDD601F:\
+D7B9EB91BCDE1F6C144A0799:25
+
+B23EFA7FAA11D0E597F00867992CB3B9DA93D607FAC0:\
+510297144BA4E0FB5C94749576F756AA36F51289CA463419DC06:\
+DA5E3A17C6DDE81CC69A5AC11904D2E9E969D9F2D1731E842C:26
+
+1A5063B374A5F7769AD59432CFFA6B:\
+3437D8B56E573E724B72DD08A5D144E86E646BD24EA0795BA2C3BD:\
+FE0314911D4C07803C48A9EA86:27
+
+870515C65F0AF7AAB10C365AF8AC535E1AA8997D139645A21F71FD23ABBB:\
+1895554BD0A1DE7F48FA8776D314EAE2B9E8D7E3CF2A418D17659DC1:\
+AA33C0BFF91FC9F1C97BFD00D5F5AC2953C6D1EC43E5838887A2F984C5A53F:28
+
+1BAE220F6AFEB0A2F51D44721A7A9B9C:\
+13720151D256DEBAAA668359A876A9A9788D540F509E90372952A91757:\
+11555530CBAECFF82C76147416A50831532A40BD29F15F1E0EA49129:29
+
+BC55F2BAC14370BB5832575A233F1FCE32322E5B4CE1955153CAF3C84493DF:\
+972B190F7EC73DA7C5B8B38E9B6DCEE452AB0BC2220F37BEA3FAC596B2F6:\
+00E8D1BAA9142A646C5DBCC680FB:30
+
+834CD382FBF84FF54CC8D3BCB778ACD7DDE8FE32ABA212ABB1:\
+6151C82D7384ED41264424827766B6A7279593C86DCBAC9A4D711009E30EC3:\
+EE768F1AAF889EFB5B20F7536FECA037BF:31
+
+E0BDEBC1D1EEDB393368D489:\
+F3D8ED6D46280C3694F33D2D4A210248D657277DD78ACD3B34063D085657A58E:\
+5D2B46C7BB5258ABC13514995E518FD4D77BECB738D77909:32
+
+[TLS-PRF]
+6C81AF87ABD86BE83C37CE981F6BFE11BD53A8:A8:\
+A6D455CB1B2929E43D63CCE55CE89D66F252549729C19C1511:1
+
+6BB61D34AF2BCCF45A850850BCDE35E55A92BA:5E75:\
+510194C9C9F90D98452FB914F636D5E5297C:2
+
+3CC54F5F3EF82C93CE60EB62DC9DF005280DD1:706F52:\
+7FC24D382379A9CD54D53458947CB28E298A1DCC5EB2556F71ACAC1B:3
+
+BD3462DC587DFA992AE48BD7643B62A9971928:841D7339:\
+9F6FAFED1F241A1E40ADEAF2AD80:4
+
+1235A061FA3867B8E51511D1E672CE141E2FA6:D856787D41:\
+1026B9224FC59706BEADAE58EBD161FD2EAC:5
+
+63A22C3C7C5651103648F5CFC9764A7BDE821F:F13096FEED6E:\
+512FBF47D9DA2915:6
+
+AA15082F10F25EC4F96DFFE9DC3D80BBA6361B:B637FCADE57896:\
+519B87DB85FBE92FB4070F3BEF6E3D97DF69B66061EB83B4A334E8EEDC0F8E:7
+
+775B727CE679B8696171C7BE60FC2E3F4DE516:3431016193616501:\
+453C2549058B063C83E8B85E5CEF3570DF51B7D79B486F4F33:8
+
+AB299AD69DC581F13D86562AE2BE8B08015FF8:A624CC363499B1EA64:5569FC:9
+
+AE4947624D877916E5B01EDDAB8E4CDC817630:5B908EB5B2A7F115CF57:\
+7FDE51EFB4044017C95E3608F8FB6F:10
+
+4F13EB6FBE1FA2FCD7B5B21C9F20980D1986A4:EE73EEE90E35AF2BC3575D:\
+514DBCE520AB34:11
+
+41BC094049008CBAE99CAC0BA901D0B2DD15DF:BD859DAE2729A348774146B5:\
+CB6C0544FF8CF74C71E910F2220D54C509DC442CB3:12
+
+95751B37945DD9DE515B45927A229AAB40F7D0:FE310AF0913149D53718AC53E5:\
+75318F49A11F42A24AF48267411FDD0831:13
+
+FC250F36E5C1365C3EAD122E63F90612DBBDA7:C0107D144E53227EDE5E677A35BE:\
+8A4B5AEA3AC0B2FF777D77B5EFB6E7D8AF:14
+
+F6A8A67ACA60F25080100F3F5C928038936E57:A1FCD686295E3DE32C438A8FFD63CE:\
+F8B663768421BA77861F1EBEBF4C8341DC01ED1F7D4B054B7C:15
+
+77BF131D53997B1FB2ACE2137E26992B36BF3E:60D0A09FCFDE24AB73F62A7C9F594766:\
+859D1EE9A694865ECC1830C361D24485AC1026:16
+
+39CF412177DD47B8E97A4D92D104138CD4E41C:F7D49D2C112F3EE64411F50B264AE15BB4:\
+9CD35F26E8A89C25410B3394A957B781BBD0D190DA:17
+
+5C40AF252D0A4F445E638D954993BCB0673281:\
+FDA100D44E2F839C21199A56ACAF57454C21:\
+2DFB810DC9ED5B291754144937E6052666D476D1F5F94C:18
+
+2A8B07B082F2A4C95611B20685A4410E90B8D2:\
+A5CCE186AFDB9C0EB664C719DD1A69C1BA6059:\
+320ADFA586F7EBF346646DE9:19
+
+BCBD1EFDA490B9D541BA9DF50FE9A451DD0313:\
+2291E19459725562F106F63FE2F81E73BA23F04A:\
+255230A341E671BC31B1:20
+
+B361B123993602D0BA62567BF9B81992DB108EAE:\
+A71CB3E9C58E83414D69775CF7127E9C95AF10B7E2:\
+20878A3A703785DE37846086C097619E9823F7FCD2B7B3A9466FA6:21
+
+8E7CC0EED8BFF691B370C08FE0DB32D06700B088:\
+25DA6B3027CBBCA4352EFB85D3FCB9060285BC39ECB8:\
+02F3B9155F5CFF08B9F47A2FDC701BA3F08BCDDF21292911D06FC0A5A99B:22
+
+041CC7ED27C01A701A0F15269DA6CA6D806B10C3:\
+E3B7F0D721C05663166B43A75F2997F9F029886FC069D0:\
+8E5F4FADE80AF92D495AF5A50C8E:23
+
+A7421C0D96D2455E57408C2BF02E86DCEE71B060:\
+46948B1DD4C7977AA7241ABD74A88E7838E575DD34AA9B75:\
+BD2623716653B538C885FA2ED4B0A2:24
+
+56DAD2D1AF95F938E073D10A1A779F80BB0F76FE:\
+53B1169FA52AABC427D1C41501B612DF6D726F55DAD9D246E9:\
+D1DA1DEF7BD5C327894B7A992AA7A694664470F642:25
+
+4F2E4F77820A686894B90A0AFD0ABA772D0CC6B0:\
+30ED285AE596143BE7998901C2F35530D81CA4DD14E03D17DF2C:\
+062577E22854BAF0E68A51A27644FFB0:26
+
+86173BD0F3C5E7052482B53BD8604E197112F3D8:\
+BB3BD1CBFA7889441E930C4B5E8EC7AB00D9612E9D762D42427AD9:\
+12B4E5F24ADC8A:27
+
+2B9CE8B0AB3041D6A1803BDD342E6537E40BE305:\
+88F8AFCB8109C7B359B18CCED73A1B09404CC9EABB23695BF353ED9E:\
+517D3D00850F48912B713E653CB4F38703B6A6:28
+
+819CB722AA4475D8301A8E24DCD9D82DF2B081F4:\
+83FD6F33AD11819019E086F0683E26D59D57C9E5AF26C81738E44D47A3:\
+56872A31A10E8C:29
+
+80F1F9B0D05F41C448E5306E41833918B9E688ED:\
+0C00B5F50565FDD5345C63773D5FCC8B3C8E412DFFF23B95490EFB4E53FA:\
+6175CDE230DF6691F4E8A36B265C53CAD736AD6F34F895D5C6633D66B5:30
+
+0AE876A7BB96C24CEFA6ED53CEE7B0A41B8FF7B3:\
+881B99C3E43B1A42F096CF556D3143D5C5DBC4E984D26C5F3075BCB08B73DA::31
+
+2212169D33FADC6FF94A3E5E0020587953CF1964:\
+1E1C646C2BFBDC62FA4C81F1D0781F5F269D3F45E5C33CAC8A2640226C8C5D16:\
+FCD5C9637A21E43F3CFF6ECF65B6E2F97933779F101AD6:32
+
+# From RFC 2631
+
+[X9.42-PRF(KeyWrap.TripleDES)]
+000102030405060708090A0B0C0D0E0F10111213:\
+A09661392376F7044D9052A397883246B67F5F1EF63EB5FB::24
+
+# Same as above, just numeric OID instead of name
+[X9.42-PRF(1.2.840.113549.1.9.16.3.6)]
+000102030405060708090A0B0C0D0E0F10111213:\
+A09661392376F7044D9052A397883246B67F5F1EF63EB5FB::24
+
+[X9.42-PRF(KeyWrap.RC2)]
+000102030405060708090A0B0C0D0E0F10111213:48950C46E0530075403CCE72889604E0:\
+0123456789ABCDEFFEDCBA98765432010123456789ABCDEFFEDCBA9876543201\
+0123456789ABCDEFFEDCBA98765432010123456789ABCDEFFEDCBA9876543201:16
+
+# MARKER: S2K Algorithms
+
+# S2K format: passphrase:output:salt:out_len:iterations
+
+[OpenPGP-S2K(SHA-1)]
+666F6F:0BEEC7B5EA3F0FDBC95D0DD47F3C5BC275DA8A335A8CAA4039FDBC02C01A649C::32:0
+616263:A9993E364706816ABA3E25717850C26C9CD0D89DDD3742EC1A4D2A5B563A2B62::32:0
+
+666F6F:DFFE49EEC99E3530FF75A794773E1F8429A46835925DAED4A27FA2957BBD29B5:\
+698619A932D101BE:32:0
+
+666F6F:8051BB97BB42199330C9D52383D1B56532FF9BDFB180BD2BD61F24A25265639F:\
+EFB0A8DDE02BAB42:32:65536
+
+696C696B65706965:A32F874A4CF95DFAD8359302B395455C:2AE6E5831A717917:16:65536
+
+666F6F626172:9B1D52CC0DA89C9D85B91EC84B6780FB:AD8FC3C853BBB225:16:65536
+
+717765727479:67CACC2B4B6F1B76E620748C1E777070:3891D354B8C86161:16:0
+
+4141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141414141414141414141:080316AFB4E11D98120B29D1070CE749::16:0
+
+696C6F766573616B757261:109D161363DF1E97322112F82169911A::16:0
+
+[OpenPGP-S2K(MD5)]
+666F6F626172:\
+3858F62230AC3C915F300C664312C63F26E4AEBF38BF1BB6AD49BA54BCACD9DB::32:0
+
+616263646566:99C8FD9A0516337E7C0F71563D937B09B14F7E7B6CB53FB56B5B8137E189DA20:\
+B89343B95A46FECE:32:65536
+
+666F6F:CC364F2BC41FACAD36E0D45E581D61F707BA925C982BEF7E:\
+760566702FEE54C8:24:65536
+
+[PBKDF1(MD2)]
+71616C7A73656774:7C1991F3F38A09D70CF3B1ACADB70BC6:\
+40CF117C3865E0CF:16:1000
+
+766E68617A6A66736978626F6D787175:677500EDA9F0C5E96E0A11F90FB9:\
+3A2484CE5D3E1B4D:14:1
+
+66686565746E657162646D7171716E797977696F716A666C6F6976636371756A:\
+91A5B689156B441BF27DD2BDD276:\
+5D838B0F4FA22BFA2157F9083D87F8752E0495BB2113012761EF11B66E87C3CB:14:15
+
+736E6279696E6A7075696B7176787867726C6B66:\
+49516935CC9F438BAFA30FF038FB:\
+F22D341361B47E3390107BD973FDC0D3E0BC02A3:14:2
+
+[PBKDF1(SHA-1)]
+66746C6B6662786474626A62766C6C7662776977:\
+768B277DC970F912DBDD3EDAD48AD2F065D25D:\
+40AC5837560251C275AF5E30A6A3074E57CED38E:19:6
+
+786E736F736D6B766867677A7370636E63706F63:\
+4D90E846A4B6AAA02AC548014A00E97E506B2AFB:\
+7008A9DC1B9A81470A2360275C19DAB77F716824:20:6
+
+6F74696C71776C756B717473:\
+71ED1A995E693EFCD33155935E800037DA74EA28:\
+CCFC44C09339040E55D3F7F76CA6EF838FDE928717241DEB9AC1A4EF45A27711:20:2001
+
+6B7A6E657166666C6274767374686E6663746166:F345FB8FBD880206B650266661F6:\
+8108883FC04A01FEB10661651516425DAD1C93E0:14:10000
+
+716B78686C7170656D7868796B6D7975636A626F:\
+2D54DFED0C7EF7D20B0945BA414A:\
+BC8BC53D4604977C3ADB1D19C15E87B77A84C2F6:14:10000
+
+[PBKDF2(SHA-1)]
+6A79756571677872736367676C707864796B6366:\
+DF6D9D72872404BF73E708CF3B7D:\
+9B56E55328A4C97A250738F8DBA1B992E8A1B508:14:10000
+
+61717271737A6E7A76767A67746B73616D6D676F:\
+FA13F40AF1ADE2A30F2FFFD66FC8A659EF95E6388C1682FC0FE4D15A70109517\
+A32942E39C371440:57487813CDD2220DFC485D932A2979EE8769EA8B:40:101
+
+6C7465786D666579796C6D6C62727379696B6177:\
+027AFADD48F4BE8DCC4F:ED1F39A0A7F3889AAF7E60743B3BC1CC2C738E60:10:1000
+
+6378676E7972636772766C6C796C6F6C736A706F:\
+7C0D009FC91B48CB6D19BAFBFCCFF3E2CCABFE725EAA234E56BDE1D551C132F2:\
+94AC88200743FB0F6AC51BE62166CBEF08D94C15:32:1
+
+7871796668727865686965646C6865776E76626A:\
+4661301D3517CA4443A6A607B32B2A63F69996299DF75DB75F1E0B98DD0EB7D8:\
+24A1A50B17D63EE8394B69FC70887F4F94883D68:32:5
+
+616E6461716B706A7761627663666E706E6A6B6C:\
+82FB44A521448D5AAC94B5158EAD1E4DCD7363081A747B9F7626752BDA2D:\
+9316C80801623CC2734AF74BEC42CF4DBAA3F6D5:30:100
+
+687361767679766F636C6F79757A746C736E6975:\
+F8EC2B0AC817896AC8189D787C6424ED24A6D881436687A4629802C0ECCE:\
+612CC61DF3CF2BDB36E10C4D8C9D73192BDDEE05:30:100
+
+6561696D72627A70636F706275736171746B6D77:\
+C9A0B2622F13916036E29E7462E206E8BA5B50CE9212752EB8EA2A4AA7B40A4CC1BF:\
+45248F9D0CEBCB86A18243E76C972A1F3B36772A:34:100
+
+67777278707178756D7364736D626D6866686D666463766C63766E677A6B6967:\
+4C9DB7BA24955225D5B845F65EF24EF1B0C6E86F2E39C8DDAA4B8ABD26082D1F\
+350381FADEAEB560DC447AFC68A6B47E6EA1E7412F6CF7B2D82342FCCD11D3B4:\
+A39B76C6EEC8374A11493AD08C246A3E40DFAE5064F4EE3489C273646178:64:1000
+
+# MARKER: Encoders/Decoders
+
+# Format is input:output
+
+# Kinda silly to hex encode base64 encoded ASCII, but... <shrug>
+[Base64_Encode]
+31:4D513D3D
+235C91:49317952
+4142634452313236:51554A6A524649784D6A593D
+241BB300A3989A620659:4A42757A414B4F596D6D494757513D3D
+
+31323537374343666671333435337836:\
+4D5449314E7A644451325A6D63544D304E544E344E673D3D
+
+60E8E5EBB1A5EAC95A01EC7F8796B2DCE471:\
+594F6A6C3637476C36736C614165782F68356179334F5278
+
+31346D354F33313333372C31274D754E7354307050346231333A29:\
+4D5452744E55387A4D544D7A4E7977784A303131546E4E554D4842514E4749784D7A6F70
+
+[Base64_Decode]
+4D513D3D:31
+49317952:235C91
+51554A6A524649784D6A593D:4142634452313236
+4A42757A414B4F596D6D494757513D3D:241BB300A3989A620659
+
+4D5449314E7A644451325A6D63544D304E544E344E673D3D:\
+31323537374343666671333435337836
+
+594F6A6C3637476C36736C614165782F68356179334F5278:\
+60E8E5EBB1A5EAC95A01EC7F8796B2DCE471
+4D5452744E55387A4D544D7A4E7977784A303131546E4E554D4842514E4749784D7A6F70:\
+31346D354F33313333372C31274D754E7354307050346231333A29
+
+# These are actually fairly dangerous, because bzip2 could change the
+# compression format somehow and still be compatible with old versions, but not
+# output this exact bitstring...
+[Bzip_Compression <EXTENSION>]
+:425A683917724538509000000000
+
+54484953204953204120425A49503220544553540A:\
+425A6839314159265359FDAED210000009DE0000104000100032604C1020\
+0021A4D1EA0FD2840D03401E19B4D4B254EE89F177245385090FDAED2100
+
+# These are much safer
+[Bzip_Decompression <EXTENSION>]
+425A683917724538509000000000:
+
+425A6839314159265359FDAED210000009DE0000104000100032604C1020\
+0021A4D1EA0FD2840D03401E19B4D4B254EE89F177245385090FDAED2100:\
+54484953204953204120425A49503220544553540A
+
+# The stream was flushed every 10 bytes
+425A68393141592653598BB9F5F700000A7FFFC021D1CE7DF41018B66921CD80\
+681D23A08C880C91110BE808084F8353AA822820007439900068001A00000000\
+03201A6D2064D82870000D3201A34C469E9000001A6269A7A8623200D1A63D70\
+DF4E435801FAA9C3CE54096593D38853A1E5A8DDD43585C763E592CF011C0D5A\
+956B48C7EC1D405F5B90DF441E168AA02C6D25E179EC44D02A2691295F38ACE1\
+201DE855B2B543D8944F805514C8D6971908389F4520A130AA848329C6BEDC53\
+3F8BB9229C284845DCFAFB80:\
+2328B92CB5578B4B87D7E07F7457E0DE93268B5FD5720F484558D057A600E9E6\
+3B9B5B5669179FCB2CA6415EDDD709223F201CF527E55C421BF916689C207E48\
+18BB3AE0AA29D3C31D12268FB51044A673816B218F49EF1B51AED3231CED7DE7\
+5FF5B532EB8B1BFB8CA2242AF9E9E226D4D629796B76749BD4EFB6B80E4EB7B3
+
+# Two concatenated streams (same stream, doubled)
+425A68393141592653592ED49B3D000011FF00001000204004100032604C1030\
+44200021A6A06431014D323131310BD3A516096617117C90B42C26B1292F659F\
+254753C2DF1772453850902ED49B3D425A68393141592653592ED49B3D000011\
+FF00001000204004100032604C103044200021A6A06431014D323131310BD3A5\
+16096617117C90B42C26B1292F659F254753C2DF1772453850902ED49B3D:\
+54484953204953204120425A49503220544553540A0A41414141414141414141\
+414141414141414141414141414141414141410A0A0A426C61682C20626C6168\
+2C20626C61680A0A54484953204953204120425A49503220544553540A0A4141\
+4141414141414141414141414141414141414141414141414141410A0A0A426C\
+61682C20626C61682C20626C61680A0A
+
+# Two concatenated streams (different streams)
+425A683931415926535980A46FE20000FB5F800010507FFFF07FFFDDE03FFFFF\
+E040031CCC62B5D74143534134C9A9EA683D53D1A4F53269E8CA7A4F51A66A03\
+4343404553FF51A4D31354F328C286418464C020C8D007A9A19E9A9EA8F48034\
+1E89A64C8C43401A1A6834C234C25348200202646D29EA0D0001A3D460D4D016\
+EAB324536379286DA9D72DCE3E1DACF47749AF69757E5E7F6589071D076F7FDE\
+9E3227D8EEAC7D2ADB6C98D82F0FE534F76F9B1D2A498B440E921B0B47D66809\
+2E6AB8DCA972C499399C923849148B4343D2AF95D2FEA63C00953DB38E47A94F\
+993CAC4B48E5459448C69A906B75779D00B5D25D02ECF3E955F77AF7D31CCACE\
+A6D766C9BD447AA85AD393BAB5343CF7BED96AE2F1A72DF6FC512430CBD13371\
+1D442490439C3BDA77C95341F5EEB3269B62608CFAEDEB16968AE0E1C7753E1A\
+4B6DC7ACF5670E4B362858963DA8888EB483B82630B6442AE6C2460FBB95549B\
+CCDAF8408C74F1BE7984FD643E90E35FBE0EDEC19C38B32699CEEC4AF1BB21D2\
+B2E42DEB44718B63CACBA7C9520882C457A828469A102444386BD54E724C3AAB\
+6BF6DCF24C969154AC2D704AB4D123280D1C2646726A2F69EF8C10CB5412918C\
+80EF05771E58BE5827CFB59C95A9068FD0F6021BE2418A8977A09CD734FD5871\
+2F672E76F06F6C612C1C85C4E4E8F432886D8B46075B92428A02519CCDD2C0A0\
+CBC1C1B28A3FAD08281080BA8981FD84B2C5138C44987953B3357F39E35DFAA2\
+D0B582B90F136B2C6DBCC1E7C227C744A85B1672F818E332EFA32AA24B158F24\
+204A1D310B264CE35D24021852F03A6D6B24024046744FB7BCDA68835129EFCB\
+40A4350B66487BB3212310E5AE7330F85643470D99C0D04F9F2A922FA5028621\
+F220B87E422B866CD7A13042D2B564316000ED9504B71D21329B02DB17839B94\
+70D6A6C45EDA5A96A26EC4EE0CED46CCBA3C532CCE19AD2F131AF59A74F56E28\
+41912A2AE079CC91BF7D3ADB3F3C8F733692EC3407388C79E31DD81C239356AE\
+1C673CC6768D429E376781B711EB2CF2D6E488D6419C145B574736BBE8578E25\
+B2125659973504559442A7A2D7C37C244C7E6AA709631308D78C3FD285B08595\
+D32154402DA6254F31403C4B32444507CA1C32A7FBAA86204E29D1DADC046970\
+87253D38C21131CF44661B046A59A1563495044FF8BB9229C2848405237F10\
+425A68393141592653598E46405D00011CDF8008D060EFF71CBFEFDFB0BFFFFF\
+F05004A5AF5C689D74340EB4786A653654F530D4DA991EAA7A9FA8C6A9E126D3\
+534F2469EA6D320C5004553FD3234464D32A7A9B29B536A1900001A06800D01A\
+A7869094F49E840DA80D0000000680007302626830993264C8C2609A69918980\
+218069A1009A9A9E22609A9B530A7A8F53D4CD400D1A347A81EA4DD64CF7FBEE\
+A25B21C0CDA99F572545B2436738C98D46F76CD222194C4E3130CCA4C121330D\
+1BCBD8E1C17D5124E37CC31EC74364E6E0A7CBB3CDC38FBDB2CE3E54E744C337\
+86924DA1B840AC53FAC8D9A4AF92C2671A2FB4C097C22ABF7119FA4D758D60D3\
+5186FEE4CE23643BD62FE490BC123E9561F1D092729E9330CD7C8B612C4381A8\
+CF061D2786C5D544421539BDCA41949E820E7E6B22B757534F25B5B56186B66A\
+C0BE8CAD5C796BBB5624C4B7952CE7AD678D5B5D42CC8360AAD4812E371DCD9A\
+285A51A520F04181EAC5474D793B1CC9C908C25298E50E3456D8C155D94D8C0A\
+2951723DB9DE8F70FB65DBE79EA0FADD0B2BD0DB70935D6E603F1881803B808C\
+659C50F6B5E1292C6323799426F06C759AE61A00B375DFE43EA298E9AACE4F1A\
+48B3EECCD57EFF4BABDA432BCB9F7EB68B4925E7CF8A0EC53D60FA1485ED0BE7\
+F1F4F927BEF419AC8593230DEEC1C823637C078F45E82C407A56CEC38FA30EF4\
+308D37020852624B3A29072212825D954810915F2508CA6515A03269515F46E9\
+D1BEE330901B3BCB6A39B888AA21DDFD5640B417C1502CE17E8BFB683B5DE8D3\
+C78A4A483203260399BB70136F9C127C0A8403EA9A0407E6F4BEB40BCCE0E379\
+1EF0407F4F9292C4F6D78BBD23B360E39447DCA5E52316108A05F81934A26509\
+0D155B7B3081560A412C1772603B649511C31986AC033342E5DC2CBB254E8D85\
+4D08D2550C0E62110F282C21C60B1D9D0A23515259DACAFA59BF5A9EF8DA354E\
+129B880F76A9C542BA8EA2F91A858645E969E0CCAF090083286CC714CE4234D5\
+1758A2301076C932813905A18856FE5D311C8D00D226931EEECBB5CD863A81EB\
+BAD43476102E47614D8822503F274AF08D038BAF65B1E671E73A989FBFAE4106\
+F2F0451EC29C8A1218189603C03E207370B0239861B99F6354F2E4B095C25C84\
+7DBBB98D08EA3A8C923515F541F30F07B4927DAA8313DF01D00DAEBE6228BB48\
+F6851D2898F0B4040AD354213349D096B8AADB92B887533A32174C5BA7A3CB46\
+F5A2FAC580C26A987508D9C4AE2EF2D5D04AD8F72A52A9DE470554B41F0D0030\
+48C1C3C962ED158409287B9560E8CA5CB3396DC43977DAE8A0025193798220B5\
+AA8CF250B26463F59E40085714F16E29D2C35E027974D6834D12F82500C45977\
+51FAEF7B883482EE04A9F2194B6CA60391A6099E6899E0821E6BC2795B7D5808\
+E043A30D9613F39BC26AAA3E81D3598248DBC3049389D7AB4C5A974502AAA402\
+47459D9C90CB9FF33C25051ABBD9C4D8754F70902C942E49BA94389C6C1A8E66\
+D7519D75DFF9A3B11CFD6F8A365F0B87A9EEDB5262DC155922CC580855531CEC\
+C80C8B46418C46520A44C8125A4484DCD26AB2A8862AB81672293CFA3186666A\
+E52801C200D1E0BE39F11E5315409520A10A568AD8459029191AE9EDC5A93A88\
+BA2E16A2EBF15847D58535A266376BBE082891ED6413F54D62093D71CB10F01F\
+932886265650E6066A7D9EAD0238EA014DC86BE01A6F9C07879BD33FC36F7000\
+CCC5DC914E14242391901740:\
+4F70656E434C2C20612043727970746F6772617068696320436C617373204C69\
+627261727920696E20432B2B0A56657273696F6E20302E372E333A204A756E65\
+20382C20323030310A0A2A4E4F54452A3A204F70656E434C2069732063757272\
+656E746C7920696E206561726C7920626574612E20546875732C20796F757220\
+636F6D6D656E74732061626F7574204F70656E434C0A286D6F73742065737065\
+6369616C6C7920746865206170706C69636174696F6E20696E74657266616365\
+2920617265206E65656465642C20616E6420796F757220636F6D6D656E747320\
+63616E0A6861766520612064697265637420656666656374206F6E20686F7720\
+4F70656E434C206368616E67657320696E20746865206675747572652E0A0A4F\
+70656E434C2061696D7320746F206265206120706F727461626C652C20656173\
+7920746F20757365206C69627261727920666F7220706572666F726D696E6720\
+636F6D6D6F6E0A63727970746F67726170686963207461736B732E204F70656E\
+434C2063757272656E746C7920696E636C756465733A0A0A426C6F636B204369\
+70686572733A20426C6F77666973682C20434153543235362C2043415354352C\
+2043532D4369706865722C204445532C20444553582C20547269706C65444553\
+2C20474F53542C0A202020494445412C204C7562792D5261636B6F66662C204D\
+49535459312C205243322C205243352C205243362C2052696A6E6461656C2C20\
+53414645522D534B3132382C2053657270656E742C0A202020534841524B2C20\
+536B69706A61636B2C205371756172652C205445412C2054687265655761792C\
+2054776F666973682C20585445410A436970686572204D6F6465733A20434243\
+20772F2050616464696E672C204346422C204F46422C20616E6420436F756E74\
+65720A53747265616D20436970686572733A2049534141432C20415243342C20\
+5345414C0A486173682046756E6374696F6E733A20484156414C2C204D44322C\
+204D44342C204D44352C20524950452D4D443132382C20524950452D4D443136\
+302C205348412D312C20534841322D3235362C0A202020534841322D3531322C\
+2054696765720A4D4143733A20454D41432C20484D41432C204D44354D41430A\
+4D6973633A2041646C657233322C2043524332342C2043524333322C2052616E\
+64706F6F6C2C2058392E313720524E470A0A466F7220696E666F726D6174696F\
+6E206F6E206275696C64696E67204F70656E434C2C2072656164207468652073\
+656374696F6E20224275696C64696E6720746865204C6962726172792220696E\
+0A646F632F6F70656E636C2E70732E205265616420646F632F72656C6E6F7465\
+732E74787420666F72206E6F7465732072656C6174656420746F206973737565\
+7320737065636966696320746F0A746869732072656C656173652E2054686520\
+6C6963656E736520697320696E20646F632F6C6963656E73652E7478742E0A0A\
+436865636B20687474703A2F2F6F70656E636C2E736F75726365666F7267652E\
+6E657420666F72207570646174657320616E64206E65772076657273696F6E73\
+20286F722069662C20686F72726F720A6F6620686F72726F72732C20796F7520\
+66696E64206120627567292E20496620796F75206861766520616E7920717565\
+7374696F6E732C20636F6D6D656E74732C206F722072657175657374732C0A73\
+656E6420656D61696C2E0A0A4A61636B204C6C6F796420286C6C6F7964406163\
+6D2E6A68752E656475290A0A4D5553540A2D2D2D2D2D2D2D2D2D2D2D0A492074\
+68696E6B2074686520667470206C696E6B20696E206F70656E636C2E74657820\
+69732077726F6E670A0A427A6970325F4465636F6D7072657373207365676661\
+756C7473206F6E2062616420696E707574202D2069732074686174207573206F\
+7220746865206C6962726172793F0A0A53484F554C440A2D2D2D2D2D2D2D2D2D\
+2D2D0A546865207370656366696C652073686F756C6420666967757265206F75\
+74207768617420657874656E73696F6E73206172650A617661696C61626C6520\
+286261736564206F6E204F532920616E6420636F6D70696C65207468656D2069\
+6E2E0A0A73656371756575652E682073686F756C642070726F6261626C79206E\
+6F7420626520696E7374616C6C65642061732069742069732061207072697661\
+7465206865616465720A0A41646420612067656F6D65746963206D65616E2074\
+6F207468652062656E63686D61726B20636F64652C20666F7220636F6D706172\
+696E67206265747765656E0A646966666572656E742073797374656D7320286D\
+61796265206A75737420616E206F766572616C6C20617665726167653F292E0A\
+0A4D616B6520612073637269707420746F2068616E646C6520616C6C20746865\
+2072656C656173652073747566660A20286D616B652054475A2F54425A202872\
+6F6F74206F776E6572292C206D616B65206261645F6C69622E6469662C207369\
+676E20616C6C2C206D616B65205352504D2C0A2020207369676E20746861742C\
+20706F737369626C7920736F6D657468696E6720746F206D616B652052504D73\
+206F6E2061206C6F740A2020206F6620626F78656E20696E20706172656C6C65\
+6C2C20746F6F292E0A0A54657374206F6E2043796777696E20616E642042654F\
+53350A0A54727920746F2067657420612056432B2B2F4E4D414B4520706F7274\
+20676F696E670A0A4D6F7265206578616D706C657320286120676F6F64206372\
+7970746F206F6E6520657370656369616C6C792C206572726F7220636865636B\
+696E672C206D6163732C20616E64207468650A77686F6C65207363686D657265\
+292E20577269746520757020736F6D657468696E672073696D696C6961722069\
+6E204F70656E53534C2C20616E6420676574207468656D20746F20776F726B0A\
+746F6765746865722E0A0A7A6C69622F627A6970323A204D756C7469706C6520\
+73747265616D732E205741495421212120446F657320697420616C7265616479\
+3F3F213F213F0A627A6970323A2053686F756C6420737570706F727420666C75\
+7368696E672E0A0A5A6C69622F477A69702066696C74657273206E6F74206576\
+656E20696D706C656D656E7465640A0A416C6C6F6361746520616E64206D6C6F\
+636B206120706F6F6C206F66206D656D6F727920616E64207265706561647465\
+646C792070617373206974206F75742E20486F77206C617267653F0A616E6420\
+484F573F0A0A576861742063616E20626520646F6E6520626574746572207769\
+7468204F532F43505520646570656E64616E7420636F64653F0A20202074696D\
+6572732C20656E74726F707920736F757263652C206D6C6F636B2C2066696C65\
+68616E646C6520737570706F727420696E20506970652F657463200A0A444553\
+2049502F46500A0A506970652073686F756C6420737570706F72742027726561\
+6C2720616C7465726E617465206F75747075742073747566662C206E6F74206A\
+757374207468650A6861636B207573656420666F72204269744275636B657420\
+2D206D617962652E204973207468657265206120646563656E74207761792074\
+6F206A7573740A706C756720697420696E2C20696E73746561643F0A0A446F63\
+756D656E742074686520757365722D76697369626C65206D6F64756C65730A0A\
+52657772697465207468652070617273657220696E2076616C69646174652E63\
+707020286D6F726520666C65786962696C697479290A0A436F6E73747563746F\
+72732073686F756C64206F7074696F6E616C6C792074616B65206B6579732028\
+3F290A0A4D6F726520636865636B7320666F723A0A2020427A69703220286E6F\
+6E652121290A202043532D43697068657220284E4553534945290A2020534541\
+4C202849424D3F290A0A53686F756C6420757365207265706C6163652028666F\
+722048544D4C2062656E636861726B20616E6420696E0A76616C696461746529\
+2E205361646C7920697427732062726F6B656E20696E204B41490A0A4E657720\
+53796D20416C676F726974686D730A2D2D2D2D2D2D2D0A4D415243340A50616E\
+616D61203C2D2043616E2075736520696E2052616E64706F6F6C0A0A4D415942\
+452053484F554C440A2D2D2D2D2D2D2D2D2D2D2D2D0A46697820495341414320\
+6B6579207363686564756C653F20556E74696C20492073656520736F6D657468\
+696E672066696E616C20746865726520646F65736E2774207365656D206D7563\
+680A706F696E742E0A0A466978206F766572666C6F7720697373756573207769\
+74682075706461746520696E207468652068617368696E6720636F64652E2050\
+726574747920756E6C696B656C7920746F20657665720A61637475616C6C7920\
+68617070656E2074686F7567682E2E2E2075706461746528782C31293B207570\
+6461746528792C30784646464646464629200A446F6573206D616B65696E6720\
+706F736974696F6E207536346269742073746F7020746869733F0A0A
+
+[Zlib_Compression <EXTENSION>]
+416263416263414141626262436341626343666F6F6261720A0A666F6F206261\
+722062617A20717575780A0A48656C6C6F20576F726C64210A0A416972277320\
+224D6F6F6E20536166617269222069732061207265616C6C7920677265617420\
+43442E0A:\
+78DA15863B0E83400C057B9FE241932E77B0968226550A6A9B9F56B2B0628214\
+387D8C34A319D6911366552DF796C55D2588B2C8492F7C8EE347D4CF668EC1C3\
+A686886B3C76B42FF70D6F59246A8BBA4310B3989D58B35F94EE497F70C02021
+
+4141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141410A:\
+78DA73742416700100F0260AB5
+
+[Zlib_Decompression <EXTENSION>]
+78DA8DCAB10A83301405D0FD7DC5C5C5C90E82D08E199D5B704EF49604352979\
+B1FAF9825FE0998F317789989FE781CF1E62ADA8DE5C38164E30AB0B8C0543CA\
+B3E2D935AFB642504991485F144F386AC1F5738A61845DDCB62AFAFA4F78DA3C\
+3D444ECBD82A0278DA4BCBCF57484A2C02E22A85C2D2D20A85B4FC7C103FAD14\
+425628240171597E4E49517E1E17008A0710D3:\
+4141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141410A0A4170686578205477696E2773202253656C656374\
+656420416D6269656E7420576F726B732038352D3932222069730A6F6E65206F\
+6620746865206265737420656C656374726F6E696320616C62756D7320492776\
+652068656172642E0A0A666F6F206261722062617A207175757820666F6F6261\
+72206675626172206675782062757820766F6C74726F6E0A
+
+78DA734C4A76042247C7A4A4246710D3392D3F3F29B1880B006C380868:\
+416263416263414141626262436341626343666F6F6261720A
+
+78DA0180007FFFDA2EE53C61F3EF2147C60D6F20A1B470782B538BF848E85E8C\
+CDD05AAF9BB1A895B96FC5144435AAE4D7E7428FEFACADF543EDFFCCE1083414\
+8B043F0FD65ED45B19CCBDDA923C60A6492C98921798B4711F6A3EB4651157B5\
+213DEFF8ED8292154B6B8490C8B536F1D6925B3BCEF1C4334F10C0FE607D9DEB\
+5F0967F5AC1D07FF634251:\
+DA2EE53C61F3EF2147C60D6F20A1B470782B538BF848E85E8CCDD05AAF9BB1A8\
+95B96FC5144435AAE4D7E7428FEFACADF543EDFFCCE10834148B043F0FD65ED4\
+5B19CCBDDA923C60A6492C98921798B4711F6A3EB4651157B5213DEFF8ED8292\
+154B6B8490C8B536F1D6925B3BCEF1C4334F10C0FE607D9DEB5F0967F5AC1D07
+
+78DA73742416700100F0260AB5:\
+4141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141410A
+
+# Same as the last one, doubled up
+78DA73742416700100F0260AB578DA73742416700100F0260AB5:\
+4141414141414141414141414141414141414141414141414141414141414141\
+414141414141414141410A414141414141414141414141414141414141414141\
+4141414141414141414141414141414141414141410A
+
+789C15863B0E83400C057B9FE241932E77B0968226550A6A9B9F56B2B0628214\
+387D8C34A319D6911366552DF796C55D2588B2C8492F7C8EE347D4CF668EC1C3\
+A686886B3C76B42FF70D6F59246A8BBA4310B3989D58B35F94EE497F70C02021:\
+416263416263414141626262436341626343666F6F6261720A0A666F6F206261\
+722062617A20717575780A0A48656C6C6F20576F726C64210A0A416972277320\
+224D6F6F6E20536166617269222069732061207265616C6C7920677265617420\
+43442E0A
+
+# The stream was flushed every 1 byte
+78DA0A06000000FFFFBA02000000FFFFE206000000FFFFDA00000000FFFF1202\
+000000FFFFFA01000000FFFF9200000000FFFF8A03000000FFFFF205000000FF\
+FFAA03000000FFFF3A0E000000FFFF0A02000000FFFF6A02000000FFFF3A0D00\
+0000FFFF9A09000000FFFF5A09000000FFFF9203000000FFFFE202000000FFFF\
+5A04000000FFFF3A07000000FFFFE202000000FFFF3A06000000FFFFAA010000\
+00FFFFD205000000FFFFCA05000000FFFF3A0C000000FFFF3A0E000000FFFF2A\
+07000000FFFF7A07000000FFFF6A05000000FFFF3A0F000000FFFF7A0D000000\
+FFFF5A09000000FFFF7207000000FFFF0A07000000FFFF7206000000FFFF5201\
+000000FFFF5204000000FFFFFA0F000000FFFFBA05000000FFFFE202000000FF\
+FF5A0D000000FFFFDA02000000FFFF1206000000FFFF7205000000FFFF920000\
+0000FFFF1206000000FFFFAA04000000FFFFDA08000000FFFFEA04000000FFFF\
+FA0D000000FFFF1206000000FFFFEA04000000FFFF6A02000000FFFF32070000\
+00FFFF2A02000000FFFFAA04000000FFFFFA06000000FFFFCA05000000FFFF7A\
+0F000000FFFF9A06000000FFFF5A03000000FFFF3A0F000000FFFF9A08000000\
+FFFF7A09000000FFFF3201000000FFFF6A06000000FFFFFA01000000FFFFF202\
+000000FFFF9A09000000FFFFEA06000000FFFF9A07000000FFFFAA04000000FF\
+FF4A00000000FFFF0A01000000FFFF3A07000000FFFFD204000000FFFF3A0700\
+0000FFFF3203000000FFFF3A08000000FFFFDA02000000FFFFDA05000000FFFF\
+FA0C000000FFFF5A0C000000FFFF5200000000FFFF3A0F000000FFFFEA010000\
+00FFFF3207000000FFFF3201000000FFFF6203000000FFFF7201000000FFFFE2\
+04000000FFFFF204000000FFFFB205000000FFFF5A01000000FFFF6A00000000\
+FFFFD201000000FFFF9200000000FFFFAA04000000FFFF8A03000000FFFFDA08\
+000000FFFF8A01000000FFFFDA0E000000FFFFE206000000FFFF6205000000FF\
+FF9A0F000000FFFF4A05000000FFFF6A07000000FFFF5A0C000000FFFFB20000\
+0000FFFF0A04000000FFFFCA07000000FFFFDA0C000000FFFF1207000000FFFF\
+9A05000000FFFFDA0E000000FFFF9A0D000000FFFF7A01000000FFFFD2000000\
+00FFFFB202000000FFFFFA06000000FFFF5A00000000FFFFFA04000000FFFFD2\
+02000000FFFF3A0C000000FFFF6A01000000FFFF0A02000000FFFF7A0A000000\
+FFFF0300D0883EB5:\
+53D40BB012F8185E4D7EC75282CB99A91E0AA2CE0AC67C2D6DC3C777EE85CFEB\
+A94757432421FFDA0AABB41345181379B189FB138982377279F66DEF96ACCF91\
+E93483F84A998B9E796054CE29CE36C1B4BAF3A320CF8C3734064409493DA880\
+2C18795EB15CB70B059F6587A338516FB3179AB79BE8283AF6A0F22AC38452E5
+
+# The stream was flushed every 10 bytes
+78DA0ABEC2BD41E887449C6F1D000000FFFF3A1ED4747AE64A39AE45E7000000\
+00FFFFE23A56A39B7BF878F9BB5600000000FFFF3AFF7AA57BB8B38AE2FF5B00\
+000000FFFFE25ABD45D85542B8726327000000FFFFFA2DDCD9645E54F92DF73D\
+000000FFFF9AB6E6FCC49726CD3FBC6602000000FFFFEA9E579910724EF39CD9\
+4100000000FFFFDAB2EBF36285F33DE6266C00000000FFFF72E1F4B45DD1A023\
+511907000000FFFFDA18B39D9B757E6AFB620B00000000FFFF0ACCDF2C3E6BFB\
+EC171A5600000000FFFFFAB6E093D6E196A0A700000000FFFF0300D0883EB5:\
+53D40BB012F8185E4D7EC75282CB99A91E0AA2CE0AC67C2D6DC3C777EE85CFEB\
+A94757432421FFDA0AABB41345181379B189FB138982377279F66DEF96ACCF91\
+E93483F84A998B9E796054CE29CE36C1B4BAF3A320CF8C3734064409493DA880\
+2C18795EB15CB70B059F6587A338516FB3179AB79BE8283AF6A0F22AC38452E5
+
+# The stream was flushed every 100 bytes
+78DA0064009BFF53D40BB012F8185E4D7EC75282CB99A91E0AA2CE0AC67C2D6D\
+C3C777EE85CFEBA94757432421FFDA0AABB41345181379B189FB138982377279\
+F66DEF96ACCF91E93483F84A998B9E796054CE29CE36C1B4BAF3A320CF8C3734\
+064409493DA8802C18795E000000FFFFDA18B39D9B757E6AFB628BC0FCCDE2B3\
+B6CF7EA161F56DC127ADC32D414F01000000FFFF0300D0883EB5:\
+53D40BB012F8185E4D7EC75282CB99A91E0AA2CE0AC67C2D6DC3C777EE85CFEB\
+A94757432421FFDA0AABB41345181379B189FB138982377279F66DEF96ACCF91\
+E93483F84A998B9E796054CE29CE36C1B4BAF3A320CF8C3734064409493DA880\
+2C18795EB15CB70B059F6587A338516FB3179AB79BE8283AF6A0F22AC38452E5
+
+# MARKER: Random Number Generators
+
+[X9.31-RNG(AES-128)]
+00000000000000000000000000000000:CF08AD39D7DA4FCDBE158347EE3752A3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+80000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BA
+
+00000000000000000000000000000000:07BDFB5F94D0CB20F668161CE7E25E36:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+C0000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BB
+
+00000000000000000000000000000000:81A997CAAA8EE7403D03A8F0AA6A588C:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+E0000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BC
+
+00000000000000000000000000000000:B00B42011B37494912AA2DE456FE6284:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+F0000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BD
+
+00000000000000000000000000000000:D42AA72455C3AE5AD634A5A4B3D577D2:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+F8000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BE
+
+00000000000000000000000000000000:0D06CB87B99641C38A5411EC3D273E70:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FC000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642BF
+
+00000000000000000000000000000000:459E5E2D6976A5B34FD18926EE1E0BB7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FE000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C0
+
+00000000000000000000000000000000:53F2D091AD47E858555371AC9BE9F3DA:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FF000000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C1
+
+00000000000000000000000000000000:1A72444D745503F63B340E0F294726DC:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FF800000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C2
+
+00000000000000000000000000000000:6FA57C78F09768AEA09ABB7DC5EA2944:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFC00000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C3
+
+00000000000000000000000000000000:6E549FCCD3BE7B6B70B317BC04B5AB01:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFE00000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C4
+
+00000000000000000000000000000000:7FF7C3F80E9A7C323B822FA436D6AA2F:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFF00000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C5
+
+00000000000000000000000000000000:52FF54A163E97610EAF318E7EE7CEC7E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFF80000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C6
+
+00000000000000000000000000000000:4FF5C162147653F594105D480D9F24F7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFC0000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C7
+
+00000000000000000000000000000000:1F863D1EA9EA0E1D741D195249B6AF21:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFE0000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C8
+
+00000000000000000000000000000000:A87313E2771F16B842DB27D3E55AB0B0:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFF0000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642C9
+
+00000000000000000000000000000000:A45BBF6E2ED76655119273112AFE1C6A:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFF8000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CA
+
+00000000000000000000000000000000:E135FBD5BE6CB13B0A5A76696BCF46F6:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFC000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CB
+
+00000000000000000000000000000000:5A0601F625C622CC97D6CAE9BA0AB6BB:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFE000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CC
+
+00000000000000000000000000000000:A9662449F9AC50293766DEC60334B8F0:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFF000000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CD
+
+00000000000000000000000000000000:F80A41023F9E350E1D2F86DB10CBB329:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFF800000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CE
+
+00000000000000000000000000000000:334EB3E404DE9F452C647C05EE09E3E6:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFC00000000000000000000000000EB8DE39CF261EE2C7389B748F8B642CF
+
+00000000000000000000000000000000:5B2C202C018A5E482D5035B18905BF46:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFE00000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D0
+
+00000000000000000000000000000000:9E9E63D29CFB4757FDDEC2B35147D830:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFF00000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D1
+
+00000000000000000000000000000000:EAAC43B87260BC73BFFDFABF5BCF94A9:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFF80000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D2
+
+00000000000000000000000000000000:4B378D2FF53B5FF913AA2064D04285D5:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFC0000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D3
+
+00000000000000000000000000000000:DBC25FE1203EA0E64F1D5C2E2F056F87:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFE0000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D4
+
+00000000000000000000000000000000:D3C96C9C5905DC56A292A7A98AAC9234:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFF0000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D5
+
+00000000000000000000000000000000:0A9223570A1288EB47595D6D18994353:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFF8000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D6
+
+00000000000000000000000000000000:E43B8F94C2B557259920C10A51A38543:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFC000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D7
+
+00000000000000000000000000000000:9B86C73D371FDAD1432065F9EB6BB6D2:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFE000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D8
+
+00000000000000000000000000000000:13F949FF373A58947D8C6543FEB81F93:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFF000000000000000000000000EB8DE39CF261EE2C7389B748F8B642D9
+
+00000000000000000000000000000000:2F7D996CB269EDC9B7902FF6D061C302:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFF800000000000000000000000EB8DE39CF261EE2C7389B748F8B642DA
+
+00000000000000000000000000000000:801AF9A32F49A1F3A43DBB22DB281DFC:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFC00000000000000000000000EB8DE39CF261EE2C7389B748F8B642DB
+
+00000000000000000000000000000000:8914E2CE1F46B13624AB93FDE9104214:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFE00000000000000000000000EB8DE39CF261EE2C7389B748F8B642DC
+
+00000000000000000000000000000000:C1D223A2A1785EF3CE6128333DD95347:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFF00000000000000000000000EB8DE39CF261EE2C7389B748F8B642DD
+
+00000000000000000000000000000000:538FEEC081411A95767AA722BCFB8C0E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFF80000000000000000000000EB8DE39CF261EE2C7389B748F8B642DE
+
+00000000000000000000000000000000:0CCDCCA45FF772D0D02F53D823BB4C9E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFC0000000000000000000000EB8DE39CF261EE2C7389B748F8B642DF
+
+00000000000000000000000000000000:550B87DA4C940750ABB829E43522F4D7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFE0000000000000000000000EB8DE39CF261EE2C7389B748F8B642E0
+
+00000000000000000000000000000000:3E17DE96FFF84D276E8156ADC9E35007:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFF0000000000000000000000EB8DE39CF261EE2C7389B748F8B642E1
+
+00000000000000000000000000000000:06F0855A2F6CE7DFF53F59A6994017AE:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFF8000000000000000000000EB8DE39CF261EE2C7389B748F8B642E2
+
+00000000000000000000000000000000:741FA68C1FEF02AF6DFCE803379AF7B8:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFC000000000000000000000EB8DE39CF261EE2C7389B748F8B642E3
+
+00000000000000000000000000000000:A7F64667398AECDEC34481265FE59235:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFE000000000000000000000EB8DE39CF261EE2C7389B748F8B642E4
+
+00000000000000000000000000000000:F19F46D46822951708F4E194F4960A56:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFF000000000000000000000EB8DE39CF261EE2C7389B748F8B642E5
+
+00000000000000000000000000000000:6E7AF2F730E9CF4CCA2E69D5067DDC76:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFF800000000000000000000EB8DE39CF261EE2C7389B748F8B642E6
+
+00000000000000000000000000000000:CA15A95DFB686938D97D804298D094AA:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFC00000000000000000000EB8DE39CF261EE2C7389B748F8B642E7
+
+00000000000000000000000000000000:F76DAEB0ED23167614294AC2F8E9EE9A:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFE00000000000000000000EB8DE39CF261EE2C7389B748F8B642E8
+
+00000000000000000000000000000000:C66A4B38050953805598F4EAF203CDE4:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFF00000000000000000000EB8DE39CF261EE2C7389B748F8B642E9
+
+00000000000000000000000000000000:76A726ED76276D5E7119AF0CCAED854A:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFF80000000000000000000EB8DE39CF261EE2C7389B748F8B642EA
+
+00000000000000000000000000000000:EB8FE9FF9A053DD2F132B11F17F53D78:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFC0000000000000000000EB8DE39CF261EE2C7389B748F8B642EB
+
+00000000000000000000000000000000:A6C5E4E13C36E80E1BBB046E6377D290:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFE0000000000000000000EB8DE39CF261EE2C7389B748F8B642EC
+
+00000000000000000000000000000000:75B476973CF532F655B8BF80CB6AC2A3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFF0000000000000000000EB8DE39CF261EE2C7389B748F8B642ED
+
+00000000000000000000000000000000:3AC698CFC1EF3ED72C26CAF5347DF997:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFF8000000000000000000EB8DE39CF261EE2C7389B748F8B642EE
+
+00000000000000000000000000000000:167ECAE8C6F793FEB00A69E3A9FAF332:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFC000000000000000000EB8DE39CF261EE2C7389B748F8B642EF
+
+00000000000000000000000000000000:8F2906AF93A28FFFBFD83D5D7E6D7F72:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFE000000000000000000EB8DE39CF261EE2C7389B748F8B642F0
+
+00000000000000000000000000000000:5BBA7C625C23F69354A61CCF2289A1B3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFF000000000000000000EB8DE39CF261EE2C7389B748F8B642F1
+
+00000000000000000000000000000000:0083A3EC21348F22B0039759AE762A2F:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFF800000000000000000EB8DE39CF261EE2C7389B748F8B642F2
+
+00000000000000000000000000000000:5E2864DD971DB13227F06535D52C24AE:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFC00000000000000000EB8DE39CF261EE2C7389B748F8B642F3
+
+00000000000000000000000000000000:D5792243D3B9BD5C7299151685192BBA:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFE00000000000000000EB8DE39CF261EE2C7389B748F8B642F4
+
+00000000000000000000000000000000:7B26CD6C3468209850FDF7F67448FAB7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFF00000000000000000EB8DE39CF261EE2C7389B748F8B642F5
+
+00000000000000000000000000000000:717586F8B816B273A691D3379005301E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFF80000000000000000EB8DE39CF261EE2C7389B748F8B642F6
+
+00000000000000000000000000000000:33D8F8DDF2A5E97E9CB1C032735BEF21:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFC0000000000000000EB8DE39CF261EE2C7389B748F8B642F7
+
+00000000000000000000000000000000:B277E4BA071293C54D84A29637273B04:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFE0000000000000000EB8DE39CF261EE2C7389B748F8B642F8
+
+00000000000000000000000000000000:FBD6F5662D222FC9C55332A60F747879:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFF0000000000000000EB8DE39CF261EE2C7389B748F8B642F9
+
+00000000000000000000000000000000:88FF65F58F6F4BF35DB846BB2132DEC6:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFF8000000000000000EB8DE39CF261EE2C7389B748F8B642FA
+
+00000000000000000000000000000000:BE12ADEDECB8DCFF2723E1D5F0D9C753:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFC000000000000000EB8DE39CF261EE2C7389B748F8B642FB
+
+00000000000000000000000000000000:5A368FCCC787680145BBFBDA64BE16C6:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFE000000000000000EB8DE39CF261EE2C7389B748F8B642FC
+
+00000000000000000000000000000000:A804DC10C6223194AE4310D7C628DBAF:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFF000000000000000EB8DE39CF261EE2C7389B748F8B642FD
+
+00000000000000000000000000000000:1DE5494C7B609ABD1406FB318B572DE7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFF800000000000000EB8DE39CF261EE2C7389B748F8B642FE
+
+00000000000000000000000000000000:78566AA937E9C90D764DFB1D5723140B:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFC00000000000000EB8DE39CF261EE2C7389B748F8B642FF
+
+00000000000000000000000000000000:9F42A9F1512DA372008DF3D469B4AD04:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFE00000000000000EB8DE39CF261EE2C7389B748F8B64300
+
+00000000000000000000000000000000:C80993A52AE00A74A64FAD42EC586FF5:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFF00000000000000EB8DE39CF261EE2C7389B748F8B64301
+
+00000000000000000000000000000000:3AFC74E774FE9B27202B8596C5B1396E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFF80000000000000EB8DE39CF261EE2C7389B748F8B64302
+
+00000000000000000000000000000000:64829EB2B232687C9CE32F8A91274497:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFC0000000000000EB8DE39CF261EE2C7389B748F8B64303
+
+00000000000000000000000000000000:E9795D38B5A1AAD7901C7765CF4F23B2:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFE0000000000000EB8DE39CF261EE2C7389B748F8B64304
+
+00000000000000000000000000000000:28989B6F2458E95A32485C7050DB4155:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFF0000000000000EB8DE39CF261EE2C7389B748F8B64305
+
+00000000000000000000000000000000:3DFFB7C3CDBB9C3B27A5CCCFDAFA9AAE:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFF8000000000000EB8DE39CF261EE2C7389B748F8B64306
+
+00000000000000000000000000000000:4B42865DA59E224D8CD7587D8C4AD73E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFC000000000000EB8DE39CF261EE2C7389B748F8B64307
+
+00000000000000000000000000000000:19316BB7F4041A621BD659FBD34397D6:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFE000000000000EB8DE39CF261EE2C7389B748F8B64308
+
+00000000000000000000000000000000:963835BE55A1E143D1F2F56BCA837BBE:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFF000000000000EB8DE39CF261EE2C7389B748F8B64309
+
+00000000000000000000000000000000:2C614F8E813AF275902D7139B08C0998:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFF800000000000EB8DE39CF261EE2C7389B748F8B6430A
+
+00000000000000000000000000000000:6B0F6D50554C31C8439ECEAC28B2C256:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFC00000000000EB8DE39CF261EE2C7389B748F8B6430B
+
+00000000000000000000000000000000:B6D80EEEC39FBB091ADC6BB3BB5D5A67:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFE00000000000EB8DE39CF261EE2C7389B748F8B6430C
+
+00000000000000000000000000000000:6C8D5E16792215E76E73FD4650A407DB:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFF00000000000EB8DE39CF261EE2C7389B748F8B6430D
+
+00000000000000000000000000000000:AA6E5BE4C0C26EEC0161D364F0FF7DE3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFF80000000000EB8DE39CF261EE2C7389B748F8B6430E
+
+00000000000000000000000000000000:1CC202A40F8ED80D5559BB2B29E96A65:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFC0000000000EB8DE39CF261EE2C7389B748F8B6430F
+
+00000000000000000000000000000000:0B4B9B6139443912D9492EE91A1769CB:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFE0000000000EB8DE39CF261EE2C7389B748F8B64310
+
+00000000000000000000000000000000:C10EBF773A13A852500F2025AB965540:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFF0000000000EB8DE39CF261EE2C7389B748F8B64311
+
+00000000000000000000000000000000:5221FDCFA12F36E4E893E902A54999E8:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFF8000000000EB8DE39CF261EE2C7389B748F8B64312
+
+00000000000000000000000000000000:E9090364194100265EF53E91299865FB:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFC000000000EB8DE39CF261EE2C7389B748F8B64313
+
+00000000000000000000000000000000:8CD5E4284B02C8B711DE7B234F6484F7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFE000000000EB8DE39CF261EE2C7389B748F8B64314
+
+00000000000000000000000000000000:76F5D704C6B17CF7397C58D3021C2FBC:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFF000000000EB8DE39CF261EE2C7389B748F8B64315
+
+00000000000000000000000000000000:F157BFB5FBF1011BD22292D947D12986:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFF800000000EB8DE39CF261EE2C7389B748F8B64316
+
+00000000000000000000000000000000:2D2BD62F2AD0EE7854072B7F6860FFCA:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFC00000000EB8DE39CF261EE2C7389B748F8B64317
+
+00000000000000000000000000000000:3D96768C1F0796A39077BE1C70301FD4:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFE00000000EB8DE39CF261EE2C7389B748F8B64318
+
+00000000000000000000000000000000:D5073B8CF890C43AEE43AE333D57D642:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFF00000000EB8DE39CF261EE2C7389B748F8B64319
+
+00000000000000000000000000000000:D38ADEA6FE821453B9EB88D9CADAD3F4:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFF80000000EB8DE39CF261EE2C7389B748F8B6431A
+
+00000000000000000000000000000000:F4F66618DBFED3C4B90AD93FAC1083F8:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFC0000000EB8DE39CF261EE2C7389B748F8B6431B
+
+00000000000000000000000000000000:930AD1D86D3ECA7A0692766CD1E40490:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFE0000000EB8DE39CF261EE2C7389B748F8B6431C
+
+00000000000000000000000000000000:63D8247A053BBE984B9840CFB7D90DD2:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFF0000000EB8DE39CF261EE2C7389B748F8B6431D
+
+00000000000000000000000000000000:827D954277E357D0453BBC537C9AB221:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFF8000000EB8DE39CF261EE2C7389B748F8B6431E
+
+00000000000000000000000000000000:9E2BDF167485A3AE004F0643E775CF42:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFC000000EB8DE39CF261EE2C7389B748F8B6431F
+
+00000000000000000000000000000000:445A3F86B2FC284BB933CBC68649E4CC:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFE000000EB8DE39CF261EE2C7389B748F8B64320
+
+00000000000000000000000000000000:F6AEADC9A5A8DF7A1664B4CD055E42B4:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000EB8DE39CF261EE2C7389B748F8B64321
+
+00000000000000000000000000000000:1B43269E05CD108EE91AAA0ECC1CA831:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFF800000EB8DE39CF261EE2C7389B748F8B64322
+
+00000000000000000000000000000000:857EEB71AB8F12AE4051B825F6B7B686:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFC00000EB8DE39CF261EE2C7389B748F8B64323
+
+00000000000000000000000000000000:C92EF523170FDEBA77CFA50D84742D68:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFE00000EB8DE39CF261EE2C7389B748F8B64324
+
+00000000000000000000000000000000:DC8C52D3698E8356F9D0F77361D8F26E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF00000EB8DE39CF261EE2C7389B748F8B64325
+
+00000000000000000000000000000000:86A95BA023CBE3E5A5911D5CA22C504E:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF80000EB8DE39CF261EE2C7389B748F8B64326
+
+00000000000000000000000000000000:6E9CACEB9D51D7D05E1FD06B1BE031C7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFC0000EB8DE39CF261EE2C7389B748F8B64327
+
+00000000000000000000000000000000:556ECC72A98D46912ADDD08FDE7BA0A3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFE0000EB8DE39CF261EE2C7389B748F8B64328
+
+00000000000000000000000000000000:3A404D891C30FBBA2EED516E81B82391:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000EB8DE39CF261EE2C7389B748F8B64329
+
+00000000000000000000000000000000:7BC825F8C9CB40A71E6B714171A77436:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF8000EB8DE39CF261EE2C7389B748F8B6432A
+
+00000000000000000000000000000000:EC8430466E19133B11D9B99DA3C614B8:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFC000EB8DE39CF261EE2C7389B748F8B6432B
+
+00000000000000000000000000000000:DCB6690389626F5392FD37E486490649:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFE000EB8DE39CF261EE2C7389B748F8B6432C
+
+00000000000000000000000000000000:73A591DF83E5F8E819BC63702471DD4A:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000EB8DE39CF261EE2C7389B748F8B6432D
+
+00000000000000000000000000000000:76B3B1D6EB12BBD6C3F17E73E9E2EB30:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF800EB8DE39CF261EE2C7389B748F8B6432E
+
+00000000000000000000000000000000:FEC46BE2B11B2FA1C7D7A5CC3012F5DC:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00EB8DE39CF261EE2C7389B748F8B6432F
+
+00000000000000000000000000000000:393389AC2C7FBA821920F6DC2193A4E0:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00EB8DE39CF261EE2C7389B748F8B64330
+
+00000000000000000000000000000000:43D7D429B793F150173FCFEC35D9A4E8:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00EB8DE39CF261EE2C7389B748F8B64331
+
+00000000000000000000000000000000:8EAE659DF12B19C428CFC37E3432683D:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80EB8DE39CF261EE2C7389B748F8B64332
+
+00000000000000000000000000000000:5080B7459858EA77FFC5AEAD88DEE1B5:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0EB8DE39CF261EE2C7389B748F8B64333
+
+00000000000000000000000000000000:ACBEEAFC7D2C5DCE6AC63452E07D6A95:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0EB8DE39CF261EE2C7389B748F8B64334
+
+00000000000000000000000000000000:95407BD82770032D496FD3F54478A589:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0EB8DE39CF261EE2C7389B748F8B64335
+
+00000000000000000000000000000000:F3B8D4093A4D2845A2C411C8EA1E9F12:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8EB8DE39CF261EE2C7389B748F8B64336
+
+00000000000000000000000000000000:6B232AD852E9D6EB2CA54E8C9B5163C3:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCEB8DE39CF261EE2C7389B748F8B64337
+
+00000000000000000000000000000000:C3CB4B5855323C13C8973982E9EA33E7:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEEB8DE39CF261EE2C7389B748F8B64338
+
+00000000000000000000000000000000:504D101AC84F9B4542C1B0264B947410:\
+C592BF6A04D72BB1CBEAF590B7CCA6BC\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB8DE39CF261EE2C7389B748F8B64339
+
+[X9.31-RNG(AES-192)]
+00000000000000000000000000000000:765F8B450404187233E6F7C30A9C3033:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+800000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C82
+
+00000000000000000000000000000000:3636889C7E3720C3E0DCF399104597A4:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+C00000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C83
+
+00000000000000000000000000000000:2845D5BCACD8C65B5B4B5A168E778DF7:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+E00000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C84
+
+00000000000000000000000000000000:41CDAA700F6E179354AD61B7CBD5E272:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+F00000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C85
+
+00000000000000000000000000000000:E08638EAEC7EA84B43AC7EB48296B94C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+F80000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C86
+
+00000000000000000000000000000000:A7AFADA8824F5B94EB20E31B30519A91:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FC0000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C87
+
+00000000000000000000000000000000:F5CAB3443DA2C48B0C309FC64FB903C6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FE0000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C88
+
+00000000000000000000000000000000:6CCEBF22A49BB4921E4E30D0663F90DC:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FF0000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C89
+
+00000000000000000000000000000000:D8CCE94DE9CFE74E3392418BCC843B14:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FF8000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8A
+
+00000000000000000000000000000000:D56EEA4E0B3963E370E6145352F170F0:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFC000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8B
+
+00000000000000000000000000000000:43894E0870AD99C2CF7116FF3F076AA3:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFE000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8C
+
+00000000000000000000000000000000:0181C2495F3DDB5BBA9F52634A3CA1A1:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFF000000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8D
+
+00000000000000000000000000000000:AE97729D2D864B54619DCCA39F7C1E3E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFF800000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8E
+
+00000000000000000000000000000000:E7F674C418E2CF20CE7152BFD184428D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFC00000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C8F
+
+00000000000000000000000000000000:DA0CCB4303614FE6F975AAC0A6B79C0C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFE00000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C90
+
+00000000000000000000000000000000:02AAAFF23E2D38885670604C1356CAFA:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFF00000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C91
+
+00000000000000000000000000000000:649A70DFBEEBAFE24F102BB45302CA90:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFF80000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C92
+
+00000000000000000000000000000000:2E2CE97AD3E20C8F5E676D453FC0573A:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFC0000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C93
+
+00000000000000000000000000000000:147AA9D83747429EB9E642190331E140:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFE0000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C94
+
+00000000000000000000000000000000:CA64870FDF1A3DFD3206EC3C39E37831:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFF0000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C95
+
+00000000000000000000000000000000:9D91BBFA64EC181C0FEA5B620338C93F:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFF8000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C96
+
+00000000000000000000000000000000:DBF7E2FFD26CC3DE9E58F06EA4AA108B:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFC000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C97
+
+00000000000000000000000000000000:172248D875492388F40E465884809BEC:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFE000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C98
+
+00000000000000000000000000000000:9CDDA74369BCE1E0545AC7BB33ED56C6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFF000000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C99
+
+00000000000000000000000000000000:58F86FD5A8CE9F2DE1D7B036646C3CF0:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFF800000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9A
+
+00000000000000000000000000000000:22B087E72247F42628C4EED66DAC2857:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFC00000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9B
+
+00000000000000000000000000000000:2C5A29C655986B70CF4D824DA14CCC51:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFE00000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9C
+
+00000000000000000000000000000000:166EA4679813A0BC390389EC305336FB:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFF00000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9D
+
+00000000000000000000000000000000:BF11A059C4081554C66DA4BD62B20954:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFF80000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9E
+
+00000000000000000000000000000000:566904C94E52FC620F980EDF352428CA:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFC0000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0C9F
+
+00000000000000000000000000000000:DC3EFF7EAC7A8EBD840DF5F621A3449A:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFE0000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA0
+
+00000000000000000000000000000000:EADDA03E98C5B8A6A28C92B7EBC7AC97:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFF0000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA1
+
+00000000000000000000000000000000:99F41647A63D58E862E3AC10FC5AEE92:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFF8000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA2
+
+00000000000000000000000000000000:B5D386B2184EDFD9726DA021B0F34142:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFC000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA3
+
+00000000000000000000000000000000:FAAE880D0C2DADC2015C66BE8AD6BC1E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFE000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA4
+
+00000000000000000000000000000000:250DCFF45916E9F8FA2219F62A422B00:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFF000000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA5
+
+00000000000000000000000000000000:853BAB572DCE44B910DDE9D74D6EC4A9:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFF800000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA6
+
+00000000000000000000000000000000:EBFC3DFD08EE68B825F47F63F47FFC2D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFC00000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA7
+
+00000000000000000000000000000000:6D25021AE6865BC70971485E1888CB35:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFE00000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA8
+
+00000000000000000000000000000000:A1D2584BBE712619CABD295ADE48D132:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFF00000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CA9
+
+00000000000000000000000000000000:8EA62AAFD310009DE585FCA2542128C6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFF80000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAA
+
+00000000000000000000000000000000:5DBEEB2438CDC2E4B0727F537EB6BCEE:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFC0000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAB
+
+00000000000000000000000000000000:81A884DD17A78D57BB00FC23B372A003:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFE0000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAC
+
+00000000000000000000000000000000:22ECAAC6F2884CC9F2977C63A7F429AF:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFF0000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAD
+
+00000000000000000000000000000000:35A2E0D7BE633C0E24C09E6F7EB681A5:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFF8000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAE
+
+00000000000000000000000000000000:FAA2B324614E430AF7168D3BE22AB8F5:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFC000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CAF
+
+00000000000000000000000000000000:FEEB51786DA2CAD7C17EB084F16ED95C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFE000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB0
+
+00000000000000000000000000000000:60C5CC3D4FA90CAE8F800FE0EBC3BD7D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFF000000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB1
+
+00000000000000000000000000000000:F4F4B400DE91585909EC6C772A616331:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFF800000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB2
+
+00000000000000000000000000000000:10A1126BFCF62DE266240BEBC70345D4:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFC00000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB3
+
+00000000000000000000000000000000:7E54A01950089CECD54EF526C2CA4D32:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFE00000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB4
+
+00000000000000000000000000000000:878880E754C0835B28EE7ABBAC5483BE:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFF00000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB5
+
+00000000000000000000000000000000:5818CF8CCCF36E2FD381F40E8E6B6C22:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFF80000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB6
+
+00000000000000000000000000000000:5342E61C5CE89EFC82790297315BC6BE:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFC0000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB7
+
+00000000000000000000000000000000:C1A6F265700B4B032B82A8DDECE58FA8:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFE0000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB8
+
+00000000000000000000000000000000:4206F2CBF9FBBC6CF774642B552754A6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFF0000000000000000008159E43DB66ECF3EABE5A44E0D4C0CB9
+
+00000000000000000000000000000000:0839EF91752B19D1B4D853BF27945C98:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFF8000000000000000008159E43DB66ECF3EABE5A44E0D4C0CBA
+
+00000000000000000000000000000000:3AA99E43E643F56D51EAE0DD94D53FAD:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFC000000000000000008159E43DB66ECF3EABE5A44E0D4C0CBB
+
+00000000000000000000000000000000:8A17C2B4992E26A7A0E709F05C3B81EC:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFE000000000000000008159E43DB66ECF3EABE5A44E0D4C0CBC
+
+00000000000000000000000000000000:9D14DA0A5F6D0E5F7B9FC38BBD598196:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFF000000000000000008159E43DB66ECF3EABE5A44E0D4C0CBD
+
+00000000000000000000000000000000:709CAED6B876ECE41FF7AE78C3892CAC:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFF800000000000000008159E43DB66ECF3EABE5A44E0D4C0CBE
+
+00000000000000000000000000000000:5AD091FF7C2677F8E3DFB98F8E85E54A:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFC00000000000000008159E43DB66ECF3EABE5A44E0D4C0CBF
+
+00000000000000000000000000000000:989D89F341AB464BE89E17B06467A8FD:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFE00000000000000008159E43DB66ECF3EABE5A44E0D4C0CC0
+
+00000000000000000000000000000000:3257273E13063BCFB64C7A0B090B0A2D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFF00000000000000008159E43DB66ECF3EABE5A44E0D4C0CC1
+
+00000000000000000000000000000000:431D551090D4E840432CD0D8E7170666:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFF80000000000000008159E43DB66ECF3EABE5A44E0D4C0CC2
+
+00000000000000000000000000000000:F3EBF6C275C41C7015BFEE14DE87F372:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFC0000000000000008159E43DB66ECF3EABE5A44E0D4C0CC3
+
+00000000000000000000000000000000:13EE442069EC7B852034397B1F09EB3D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFE0000000000000008159E43DB66ECF3EABE5A44E0D4C0CC4
+
+00000000000000000000000000000000:ACFAA2C816C9ECAD0A19BA783BCAB411:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFF0000000000000008159E43DB66ECF3EABE5A44E0D4C0CC5
+
+00000000000000000000000000000000:2AAEB898354B9E1358CA6DF57369C361:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFF8000000000000008159E43DB66ECF3EABE5A44E0D4C0CC6
+
+00000000000000000000000000000000:52C35276866C0DA1277FC4952B732EEA:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFC000000000000008159E43DB66ECF3EABE5A44E0D4C0CC7
+
+00000000000000000000000000000000:BAEEB093F380B5D887DC48B7DE672D33:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFE000000000000008159E43DB66ECF3EABE5A44E0D4C0CC8
+
+00000000000000000000000000000000:D524C38205AD436D54199E0F8E04D8D9:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFF000000000000008159E43DB66ECF3EABE5A44E0D4C0CC9
+
+00000000000000000000000000000000:A0D1315745F15F0DDC468DBDD9E56714:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFF800000000000008159E43DB66ECF3EABE5A44E0D4C0CCA
+
+00000000000000000000000000000000:2776D4FFDFFB344EC55FC22FFE450A3C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFC00000000000008159E43DB66ECF3EABE5A44E0D4C0CCB
+
+00000000000000000000000000000000:BC0716E00000562CC8A9E2470F3D8B63:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFE00000000000008159E43DB66ECF3EABE5A44E0D4C0CCC
+
+00000000000000000000000000000000:E29DD29D73D883CD8DAF74838BBEFC7C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFF00000000000008159E43DB66ECF3EABE5A44E0D4C0CCD
+
+00000000000000000000000000000000:84CBCBB352E2D3CB77E04C954280694E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFF80000000000008159E43DB66ECF3EABE5A44E0D4C0CCE
+
+00000000000000000000000000000000:558744FEBFFE7A0AE424D45921B87309:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFC0000000000008159E43DB66ECF3EABE5A44E0D4C0CCF
+
+00000000000000000000000000000000:7FF9325EA7576D41B4A1B557533432FB:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFE0000000000008159E43DB66ECF3EABE5A44E0D4C0CD0
+
+00000000000000000000000000000000:01CC9B4887AD0B270EC55F6527AB90A6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFF0000000000008159E43DB66ECF3EABE5A44E0D4C0CD1
+
+00000000000000000000000000000000:044176DA3370910AE0BCBDCF1D895CC0:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFF8000000000008159E43DB66ECF3EABE5A44E0D4C0CD2
+
+00000000000000000000000000000000:BCA18B1630EAEC7CBDDF5C513A53D456:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFC000000000008159E43DB66ECF3EABE5A44E0D4C0CD3
+
+00000000000000000000000000000000:19D1D3DA04BDAD8D710DD14A611F8F17:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFE000000000008159E43DB66ECF3EABE5A44E0D4C0CD4
+
+00000000000000000000000000000000:615BC0AF497F862399EF275E649746F0:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFF000000000008159E43DB66ECF3EABE5A44E0D4C0CD5
+
+00000000000000000000000000000000:58F46ACF8BB0D1B56EF0AD46D90DA340:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFF800000000008159E43DB66ECF3EABE5A44E0D4C0CD6
+
+00000000000000000000000000000000:2F2DBE7F2123A2E66CD8DD478688A07E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFC00000000008159E43DB66ECF3EABE5A44E0D4C0CD7
+
+00000000000000000000000000000000:AA80B113C8E106723409B3F31969965A:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFE00000000008159E43DB66ECF3EABE5A44E0D4C0CD8
+
+00000000000000000000000000000000:DFC761136BCB3B2E1E13E0291BA85972:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFF00000000008159E43DB66ECF3EABE5A44E0D4C0CD9
+
+00000000000000000000000000000000:E0944C42C6EE12FAA28286B0ED4F5DC7:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFF80000000008159E43DB66ECF3EABE5A44E0D4C0CDA
+
+00000000000000000000000000000000:DAF99970E52C6639188262C5DAD13123:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFC0000000008159E43DB66ECF3EABE5A44E0D4C0CDB
+
+00000000000000000000000000000000:0E07202C26F31E74004015F6BC7E2100:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFE0000000008159E43DB66ECF3EABE5A44E0D4C0CDC
+
+00000000000000000000000000000000:93DCAC92FB0DA5976DF8A75DBDC61C9B:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFF0000000008159E43DB66ECF3EABE5A44E0D4C0CDD
+
+00000000000000000000000000000000:9370C5EC398DE376E319370A4C5F26E2:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFF8000000008159E43DB66ECF3EABE5A44E0D4C0CDE
+
+00000000000000000000000000000000:83C03F2B1B64E72ED21D0A5F59FA7F8C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFC000000008159E43DB66ECF3EABE5A44E0D4C0CDF
+
+00000000000000000000000000000000:AA1159B23592ADECC168B2268952A92B:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFE000000008159E43DB66ECF3EABE5A44E0D4C0CE0
+
+00000000000000000000000000000000:14EEE0E44CA217E45440EC84011D89A5:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFF000000008159E43DB66ECF3EABE5A44E0D4C0CE1
+
+00000000000000000000000000000000:B2C88BBA8B055BA74622297E8BC8D95D:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFF800000008159E43DB66ECF3EABE5A44E0D4C0CE2
+
+00000000000000000000000000000000:FADFBA23CC801A926A119F78B37A9307:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFC00000008159E43DB66ECF3EABE5A44E0D4C0CE3
+
+00000000000000000000000000000000:4CB2D5484366D91C9243C4797DA983DD:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFE00000008159E43DB66ECF3EABE5A44E0D4C0CE4
+
+00000000000000000000000000000000:367EF2BDC4163545C4C9011AE53755DE:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFF00000008159E43DB66ECF3EABE5A44E0D4C0CE5
+
+00000000000000000000000000000000:51888B85AD78889BACEA726798C30C95:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFF80000008159E43DB66ECF3EABE5A44E0D4C0CE6
+
+00000000000000000000000000000000:1D3CEC46E078E44BF11603DB2726D8F2:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFC0000008159E43DB66ECF3EABE5A44E0D4C0CE7
+
+00000000000000000000000000000000:A369189A3667F44FFA8DA2E5E9425D6F:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFE0000008159E43DB66ECF3EABE5A44E0D4C0CE8
+
+00000000000000000000000000000000:ED8C0F37154A57D27A9A11CAE3F3131E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFF0000008159E43DB66ECF3EABE5A44E0D4C0CE9
+
+00000000000000000000000000000000:8B04BF18036328006D9A7FC4C1BCF818:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFF8000008159E43DB66ECF3EABE5A44E0D4C0CEA
+
+00000000000000000000000000000000:0E1E3F517E7502E4CC98A3A312692666:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFC000008159E43DB66ECF3EABE5A44E0D4C0CEB
+
+00000000000000000000000000000000:306CA0902C2B572BB5E2CE0848D6280E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFE000008159E43DB66ECF3EABE5A44E0D4C0CEC
+
+00000000000000000000000000000000:8F8479252EF0C104D27B38C52F4F40EB:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF000008159E43DB66ECF3EABE5A44E0D4C0CED
+
+00000000000000000000000000000000:D5C6F739A2B316B8CAFBC39999C731CB:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF800008159E43DB66ECF3EABE5A44E0D4C0CEE
+
+00000000000000000000000000000000:5C153EA9F8580BE16B093EE1CF83529B:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFC00008159E43DB66ECF3EABE5A44E0D4C0CEF
+
+00000000000000000000000000000000:13A3DF5F58736008E8101087B5B49563:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFE00008159E43DB66ECF3EABE5A44E0D4C0CF0
+
+00000000000000000000000000000000:2CB0DC2125C33149703A9A86CB0FB7D2:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF00008159E43DB66ECF3EABE5A44E0D4C0CF1
+
+00000000000000000000000000000000:5453577F4F95E85D729DCFD84B297381:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF80008159E43DB66ECF3EABE5A44E0D4C0CF2
+
+00000000000000000000000000000000:588702C309F54A76467B8F587FE17096:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFC0008159E43DB66ECF3EABE5A44E0D4C0CF3
+
+00000000000000000000000000000000:7779A89AD48BB3FD8BBFDC5BD8C9101E:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFE0008159E43DB66ECF3EABE5A44E0D4C0CF4
+
+00000000000000000000000000000000:9EDB48F7416AE0BD9802172515AA3D80:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF0008159E43DB66ECF3EABE5A44E0D4C0CF5
+
+00000000000000000000000000000000:84AEA377BDDC54012F710254A435E1D1:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF8008159E43DB66ECF3EABE5A44E0D4C0CF6
+
+00000000000000000000000000000000:4BEE75DC775926F27373A958BF64A168:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC008159E43DB66ECF3EABE5A44E0D4C0CF7
+
+00000000000000000000000000000000:76B563BA44BFF0D9CB460CD5E8D55C32:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE008159E43DB66ECF3EABE5A44E0D4C0CF8
+
+00000000000000000000000000000000:0682EA4560113BE4D3F3E92256D2BAAC:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF008159E43DB66ECF3EABE5A44E0D4C0CF9
+
+00000000000000000000000000000000:65D98A2BC1A84569FC553ED36C28FF45:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF808159E43DB66ECF3EABE5A44E0D4C0CFA
+
+00000000000000000000000000000000:0AABEB6CE77559F813C8257E57938C2C:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC08159E43DB66ECF3EABE5A44E0D4C0CFB
+
+00000000000000000000000000000000:5ED815849F9F2480202FDAE7C05CC83B:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE08159E43DB66ECF3EABE5A44E0D4C0CFC
+
+00000000000000000000000000000000:5F453DBC5FED77520B0AFB71DAE3C083:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08159E43DB66ECF3EABE5A44E0D4C0CFD
+
+00000000000000000000000000000000:14CAA4D84D923CCDAD2CD1CCD0377833:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88159E43DB66ECF3EABE5A44E0D4C0CFE
+
+00000000000000000000000000000000:573691CD8E310DC33A645582BA51DE9A:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8159E43DB66ECF3EABE5A44E0D4C0CFF
+
+00000000000000000000000000000000:8B77DFB1C9BD1FBF4B379B159230A7A6:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8159E43DB66ECF3EABE5A44E0D4C0D00
+
+00000000000000000000000000000000:CCAE97D6E56FBDA46C9B0DF5B6AF71C3:\
+E8BF7880FD391D95F3F83B700422E91B22ACDEC4D2D9E163\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8159E43DB66ECF3EABE5A44E0D4C0D01
+
+[X9.31-RNG(AES-256)]
+00000000000000000000000000000000:6C5EE8D10201D608874E6AE8C8A2BA79:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+8000000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C2
+
+00000000000000000000000000000000:3790A9D44DE68EF0800837B32E2ED032:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+C000000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C3
+
+00000000000000000000000000000000:72A1742C79E8B1D4F62E0669657F744D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+E000000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C4
+
+00000000000000000000000000000000:9E5708E79B379B9D393C766CFD802C98:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+F000000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C5
+
+00000000000000000000000000000000:AF7A0A13DE0B16512986538D5FECDC7D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+F800000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C6
+
+00000000000000000000000000000000:D885CBF7B4E38B9FAC1C8EB625DDABCA:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FC00000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C7
+
+00000000000000000000000000000000:7AEF038A328D1827D52DA4A36567C7BA:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FE00000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C8
+
+00000000000000000000000000000000:14169D5DE6E79DEA20E261DA55DBA593:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FF00000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666C9
+
+00000000000000000000000000000000:DFE31312A96369CF41CAED493D4DFF4B:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FF80000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CA
+
+00000000000000000000000000000000:BAFFD64502B19D26DCA93D09E43D8036:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFC0000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CB
+
+00000000000000000000000000000000:8BDEF0F95AB8F3B5A591A78364B723C7:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFE0000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CC
+
+00000000000000000000000000000000:38145A8F807E13CB05B2810E752BABDE:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFF0000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CD
+
+00000000000000000000000000000000:98EA671222B7332AEA395F37A355B1CC:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFF8000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CE
+
+00000000000000000000000000000000:20C8AB02049C9987A7B00B4498B2C6E3:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFC000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666CF
+
+00000000000000000000000000000000:67B8ACDE366BD5D064CB53C09EB0A95A:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFE000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D0
+
+00000000000000000000000000000000:137721E4A673550141E2E3CF652A0819:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFF000000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D1
+
+00000000000000000000000000000000:29C0369E50A4B5494166E60E7E394149:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFF800000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D2
+
+00000000000000000000000000000000:09FAA6F94FE3DAFE3E10A38D8B9ABDE4:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFC00000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D3
+
+00000000000000000000000000000000:5F976E965ABC8C93D1C175AA750C16DC:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFE00000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D4
+
+00000000000000000000000000000000:25C386A980D1E75632566AD290FE3333:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFF00000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D5
+
+00000000000000000000000000000000:D0CB44688ADA0966204B3D53FA89D534:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFF80000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D6
+
+00000000000000000000000000000000:D2D11DD6ABE3B30BAECAADE50A2E9642:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFC0000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D7
+
+00000000000000000000000000000000:068451BECF49C9AD8BF47F176B154092:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFE0000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D8
+
+00000000000000000000000000000000:A8B505B0B75D061A1111FF97EE70CB2D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFF0000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666D9
+
+00000000000000000000000000000000:0479DBD05E14286F769AD495AE114D56:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFF8000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DA
+
+00000000000000000000000000000000:9C62B0A336593C307F2144658DA20BA2:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFC000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DB
+
+00000000000000000000000000000000:D68EFECC5CA3C1109769F14288202779:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFE000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DC
+
+00000000000000000000000000000000:DE6A7F99826A4F60BD70A2839B269A39:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFF000000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DD
+
+00000000000000000000000000000000:F03D08EDF438E946E056B6D085C27B28:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFF800000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DE
+
+00000000000000000000000000000000:4DB84EFD6F81DC4B70CAB3E365C70B21:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFC00000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666DF
+
+00000000000000000000000000000000:2D78FEC4CA1917B5070D4B5246D5CD11:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFE00000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E0
+
+00000000000000000000000000000000:CE9228E22BD9E7A39FF05E194805F730:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFF00000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E1
+
+00000000000000000000000000000000:D8912B41584C29C70874CBB947833B38:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFF80000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E2
+
+00000000000000000000000000000000:83644C0D80557650F719DF1B28A0CB3F:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFC0000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E3
+
+00000000000000000000000000000000:032A88989BB02C57501CC05D4D72E8A1:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFE0000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E4
+
+00000000000000000000000000000000:7C3607B5F5193A51DF18A19CF4577795:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFF0000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E5
+
+00000000000000000000000000000000:76B055658ADF07D15422895951F692E0:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFF8000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E6
+
+00000000000000000000000000000000:7F87F363569F479DA806ABF988002705:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFC000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E7
+
+00000000000000000000000000000000:9A830D8126A8D39BA023B4F545670618:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFE000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E8
+
+00000000000000000000000000000000:7C0907F8FEBC6DCF1A4D83D420E5DC85:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFF000000000000000000000097B45F0EE0FB64AC3B8A1B9B750666E9
+
+00000000000000000000000000000000:F84F6500F554CAF20FF785C28E70AA69:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFF800000000000000000000097B45F0EE0FB64AC3B8A1B9B750666EA
+
+00000000000000000000000000000000:876052A291745E5479FD0ADB65AB3CFD:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFC00000000000000000000097B45F0EE0FB64AC3B8A1B9B750666EB
+
+00000000000000000000000000000000:69F6A409470573A5DEB23744A9FE8C26:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFE00000000000000000000097B45F0EE0FB64AC3B8A1B9B750666EC
+
+00000000000000000000000000000000:455FF206B8BA6D99DDA0B0E645DD03A0:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFF00000000000000000000097B45F0EE0FB64AC3B8A1B9B750666ED
+
+00000000000000000000000000000000:A82E4437632E216EA6E5F75AEB6DC148:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFF80000000000000000000097B45F0EE0FB64AC3B8A1B9B750666EE
+
+00000000000000000000000000000000:A7B1E69A85CC0E01CD2F59E7AFAF790F:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFC0000000000000000000097B45F0EE0FB64AC3B8A1B9B750666EF
+
+00000000000000000000000000000000:68FFCB667FCD6113A1B3E6F20ADBADFE:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFE0000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F0
+
+00000000000000000000000000000000:CEE4E4C331CE6AF61D07617079420E4E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFF0000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F1
+
+00000000000000000000000000000000:E7CFD60A04AE3875F6E460FE73FC151E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFF8000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F2
+
+00000000000000000000000000000000:301E3DA5BD96188B3154AAC685EB8B6F:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFC000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F3
+
+00000000000000000000000000000000:12588D677D871E4B042F16E98693167F:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFE000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F4
+
+00000000000000000000000000000000:938DF998D725B8EF5363C99A82D447F8:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFF000000000000000000097B45F0EE0FB64AC3B8A1B9B750666F5
+
+00000000000000000000000000000000:6588A7E9B2D3F82BEACB086A24F05730:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFF800000000000000000097B45F0EE0FB64AC3B8A1B9B750666F6
+
+00000000000000000000000000000000:CA0BBDDD004301639B1644A8CB9360B2:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFC00000000000000000097B45F0EE0FB64AC3B8A1B9B750666F7
+
+00000000000000000000000000000000:35B609CE89EE33F267A4E875FA4128F3:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFE00000000000000000097B45F0EE0FB64AC3B8A1B9B750666F8
+
+00000000000000000000000000000000:BAC817B7C3E5B617FFC977F23BBF755B:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFF00000000000000000097B45F0EE0FB64AC3B8A1B9B750666F9
+
+00000000000000000000000000000000:46487C6F7B5EEDCDAB5BB08234EE4C76:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFF80000000000000000097B45F0EE0FB64AC3B8A1B9B750666FA
+
+00000000000000000000000000000000:752D69F5FFAAB3D22A07B5E8CC02C7DA:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFC0000000000000000097B45F0EE0FB64AC3B8A1B9B750666FB
+
+00000000000000000000000000000000:46688ED5C008A8431D25FECADCAC511E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFE0000000000000000097B45F0EE0FB64AC3B8A1B9B750666FC
+
+00000000000000000000000000000000:2A5BCBE76FE95C1274F4B9315D4286CE:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFF0000000000000000097B45F0EE0FB64AC3B8A1B9B750666FD
+
+00000000000000000000000000000000:C9BD29164997EB53E05D41B4A5654AE8:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFF8000000000000000097B45F0EE0FB64AC3B8A1B9B750666FE
+
+00000000000000000000000000000000:EB5C8D67F1B7A2183A0B196E8450B873:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFC000000000000000097B45F0EE0FB64AC3B8A1B9B750666FF
+
+00000000000000000000000000000000:CD9231AF1BB1CA82226F5C5852BA17C2:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFE000000000000000097B45F0EE0FB64AC3B8A1B9B75066700
+
+00000000000000000000000000000000:5C0DA74392E5BE679DBD40FC95EE03D4:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFF000000000000000097B45F0EE0FB64AC3B8A1B9B75066701
+
+00000000000000000000000000000000:786D6BA1C0BA6FC1AF0F11EC5875A1F5:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFF800000000000000097B45F0EE0FB64AC3B8A1B9B75066702
+
+00000000000000000000000000000000:1F251DD8210AAEDCB79D4152369CD76B:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFC00000000000000097B45F0EE0FB64AC3B8A1B9B75066703
+
+00000000000000000000000000000000:1B291C0DBDB2075E9B9C709A15016ED7:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFE00000000000000097B45F0EE0FB64AC3B8A1B9B75066704
+
+00000000000000000000000000000000:8465C72B7319CD4D0E35A05D49C5508D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFF00000000000000097B45F0EE0FB64AC3B8A1B9B75066705
+
+00000000000000000000000000000000:07F04A0749B6DE3B5C668729B28AFB54:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFF80000000000000097B45F0EE0FB64AC3B8A1B9B75066706
+
+00000000000000000000000000000000:6C97CB048F5B4E7C32196C14E678A0E1:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFC0000000000000097B45F0EE0FB64AC3B8A1B9B75066707
+
+00000000000000000000000000000000:BE029441D7AF7EE8CE7310F6F5006809:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFE0000000000000097B45F0EE0FB64AC3B8A1B9B75066708
+
+00000000000000000000000000000000:31074BC8D063E87E2FF1F9E0EAA404D9:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFF0000000000000097B45F0EE0FB64AC3B8A1B9B75066709
+
+00000000000000000000000000000000:37A677D029773FE867F07020F65F0246:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFF8000000000000097B45F0EE0FB64AC3B8A1B9B7506670A
+
+00000000000000000000000000000000:89DF0BD0FA7D852EAC6B564AB8E6F3F3:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFC000000000000097B45F0EE0FB64AC3B8A1B9B7506670B
+
+00000000000000000000000000000000:CA7747BEFE61CFA622F7A821116E43C2:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFE000000000000097B45F0EE0FB64AC3B8A1B9B7506670C
+
+00000000000000000000000000000000:82D1BA96DF72AC93CD57E9234509FB08:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFF000000000000097B45F0EE0FB64AC3B8A1B9B7506670D
+
+00000000000000000000000000000000:299ECF7AAFADB0F2B21812B8B2977470:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFF800000000000097B45F0EE0FB64AC3B8A1B9B7506670E
+
+00000000000000000000000000000000:7A7A2015F797F943F75F70994F43E523:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFC00000000000097B45F0EE0FB64AC3B8A1B9B7506670F
+
+00000000000000000000000000000000:88F208943716B38D25EC02E164357DBF:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFE00000000000097B45F0EE0FB64AC3B8A1B9B75066710
+
+00000000000000000000000000000000:2420712BC5A2187E71436DF0C7D9E5D7:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFF00000000000097B45F0EE0FB64AC3B8A1B9B75066711
+
+00000000000000000000000000000000:A95EC3F73418436AD057F861BBC1811C:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFF80000000000097B45F0EE0FB64AC3B8A1B9B75066712
+
+00000000000000000000000000000000:713E1A0B1C56DD8D219921C8FEB462EF:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFC0000000000097B45F0EE0FB64AC3B8A1B9B75066713
+
+00000000000000000000000000000000:B5AA2282CC8D2F0003A6492CDE8BD888:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFE0000000000097B45F0EE0FB64AC3B8A1B9B75066714
+
+00000000000000000000000000000000:BD38241AF3C4E5CC844CED745CF65B7D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFF0000000000097B45F0EE0FB64AC3B8A1B9B75066715
+
+00000000000000000000000000000000:D6DF902987B9C3D5826BA71F1A5FA271:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFF8000000000097B45F0EE0FB64AC3B8A1B9B75066716
+
+00000000000000000000000000000000:DCD0CA7E3C0422E4723AE53641DF1E47:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFC000000000097B45F0EE0FB64AC3B8A1B9B75066717
+
+00000000000000000000000000000000:757E483E335672145C0C0C2097DACDA5:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFE000000000097B45F0EE0FB64AC3B8A1B9B75066718
+
+00000000000000000000000000000000:3BAE296E2434A5331383085CC7704988:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFF000000000097B45F0EE0FB64AC3B8A1B9B75066719
+
+00000000000000000000000000000000:F2CE3B5AA3DCCAF64722D1AE10DE005E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFF800000000097B45F0EE0FB64AC3B8A1B9B7506671A
+
+00000000000000000000000000000000:58DEC1DEF6FD5E09D814AE6F8641A219:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFC00000000097B45F0EE0FB64AC3B8A1B9B7506671B
+
+00000000000000000000000000000000:2F28B31722EE508F8679234F458BDA26:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFE00000000097B45F0EE0FB64AC3B8A1B9B7506671C
+
+00000000000000000000000000000000:B89DE1B9E3937F115EEE36CE1C1BDD74:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFF00000000097B45F0EE0FB64AC3B8A1B9B7506671D
+
+00000000000000000000000000000000:B6B987E6C49B5BC452F97991838DDCEB:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFF80000000097B45F0EE0FB64AC3B8A1B9B7506671E
+
+00000000000000000000000000000000:E363D02F055C097BF19CD491654FF798:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFC0000000097B45F0EE0FB64AC3B8A1B9B7506671F
+
+00000000000000000000000000000000:654A5415175E6343672AE4C63D6643A2:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFE0000000097B45F0EE0FB64AC3B8A1B9B75066720
+
+00000000000000000000000000000000:ED2313EFC077667BD26DB08F581F3C74:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFF0000000097B45F0EE0FB64AC3B8A1B9B75066721
+
+00000000000000000000000000000000:FC6348FC174F45C96F5A3C78C13B220B:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFF8000000097B45F0EE0FB64AC3B8A1B9B75066722
+
+00000000000000000000000000000000:65AEDCD56236E056217C94642BFEF8BC:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFC000000097B45F0EE0FB64AC3B8A1B9B75066723
+
+00000000000000000000000000000000:920A3A154BD41CB775BA25C2EB3A6885:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFE000000097B45F0EE0FB64AC3B8A1B9B75066724
+
+00000000000000000000000000000000:07953BBE0BE803D75E3B8A0EDBEF1D36:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFF000000097B45F0EE0FB64AC3B8A1B9B75066725
+
+00000000000000000000000000000000:A0BCB7A68C7C29E13306E5BD11AD6746:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFF800000097B45F0EE0FB64AC3B8A1B9B75066726
+
+00000000000000000000000000000000:6DEB2CEA2F4AC6AADB7D3A22A3DA0B65:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFC00000097B45F0EE0FB64AC3B8A1B9B75066727
+
+00000000000000000000000000000000:9D70BC79E81D6279EDCBEFD2C0EF1C5D:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFE00000097B45F0EE0FB64AC3B8A1B9B75066728
+
+00000000000000000000000000000000:AEF03890D852369F48651CF873E30710:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFF00000097B45F0EE0FB64AC3B8A1B9B75066729
+
+00000000000000000000000000000000:F189987D9AA73395765EF29A72B8B058:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFF80000097B45F0EE0FB64AC3B8A1B9B7506672A
+
+00000000000000000000000000000000:87F833C8D5200898FF3B6BDD0B869F94:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFC0000097B45F0EE0FB64AC3B8A1B9B7506672B
+
+00000000000000000000000000000000:5A7B8BB4F19D6DAC3AB19C2F9E2C65DA:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFE0000097B45F0EE0FB64AC3B8A1B9B7506672C
+
+00000000000000000000000000000000:CBDBA79302A31040BEB82623B832DF92:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF0000097B45F0EE0FB64AC3B8A1B9B7506672D
+
+00000000000000000000000000000000:38E92CC8333025DC803CE15A2628E34A:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFF8000097B45F0EE0FB64AC3B8A1B9B7506672E
+
+00000000000000000000000000000000:FB033A85B5CD43564D80C0280D70B92F:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFC000097B45F0EE0FB64AC3B8A1B9B7506672F
+
+00000000000000000000000000000000:21EC2A86B6A717DB2A3FC7F1DFF2ECEB:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFE000097B45F0EE0FB64AC3B8A1B9B75066730
+
+00000000000000000000000000000000:7DDECD08BA8101F3CD61C42C33B987A7:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000097B45F0EE0FB64AC3B8A1B9B75066731
+
+00000000000000000000000000000000:784E688C7D87FC3C9D31B2B45885DB6E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF800097B45F0EE0FB64AC3B8A1B9B75066732
+
+00000000000000000000000000000000:08610008A6FF151C4DD5DE24D578A284:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFC00097B45F0EE0FB64AC3B8A1B9B75066733
+
+00000000000000000000000000000000:91F83EC50CE5A5885659D15A3A50FF3E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFE00097B45F0EE0FB64AC3B8A1B9B75066734
+
+00000000000000000000000000000000:B4CE519B707EA0791AF63F4344207CB4:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF00097B45F0EE0FB64AC3B8A1B9B75066735
+
+00000000000000000000000000000000:94D92918083BF232F8D6580E6A0DEF10:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFF80097B45F0EE0FB64AC3B8A1B9B75066736
+
+00000000000000000000000000000000:F62EE1B2DB6D84D57BEFC1C99C7F4B60:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0097B45F0EE0FB64AC3B8A1B9B75066737
+
+00000000000000000000000000000000:5E4B8514D4CDFDD77796B3ED0E310AFE:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0097B45F0EE0FB64AC3B8A1B9B75066738
+
+00000000000000000000000000000000:3175BBBFE5ED208D189E6B25ADEEB78B:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0097B45F0EE0FB64AC3B8A1B9B75066739
+
+00000000000000000000000000000000:5AC67D25AA2BEFA746FCD6B3FF5BE1DA:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8097B45F0EE0FB64AC3B8A1B9B7506673A
+
+00000000000000000000000000000000:6842AA6307CC06A719828A0039FFC800:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC097B45F0EE0FB64AC3B8A1B9B7506673B
+
+00000000000000000000000000000000:664C66BDE4DEA06C4A79E2EC36DBA148:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE097B45F0EE0FB64AC3B8A1B9B7506673C
+
+00000000000000000000000000000000:F14CE6B410049F5601E8426C4DBAB6F8:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF097B45F0EE0FB64AC3B8A1B9B7506673D
+
+00000000000000000000000000000000:262051DCA403EFBABE2B6BD45C9952D5:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF897B45F0EE0FB64AC3B8A1B9B7506673E
+
+00000000000000000000000000000000:4B4D035F1419C491D8FB486510EA97D8:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC97B45F0EE0FB64AC3B8A1B9B7506673F
+
+00000000000000000000000000000000:152AF024DA001782BFEB875224F2622E:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE97B45F0EE0FB64AC3B8A1B9B75066740
+
+00000000000000000000000000000000:8D7040135B3F89F28277A2527111CF36:\
+A53E052EA80A62133EB26B3372A71EA2CCDDF10E1A7CB80B6FD9C8A86DA45D46\
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97B45F0EE0FB64AC3B8A1B9B75066741
+
+[X9.31-RNG(TripleDES)]
+
+# Two-key TDES
+0000000000000000:667BC708CC798ABE:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+8000000000000000F03E2147D5D7BC7F
+
+0000000000000000:E721EE3C0A2D3886:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+C000000000000000F03E2147D5D7BC80
+
+0000000000000000:CB0FA40E1752F8B4:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+E000000000000000F03E2147D5D7BC81
+
+0000000000000000:DF0351A5B44144A8:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+F000000000000000F03E2147D5D7BC82
+
+0000000000000000:2110E29B7345A88D:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+F800000000000000F03E2147D5D7BC83
+
+0000000000000000:78B751774AF554FB:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FC00000000000000F03E2147D5D7BC84
+
+0000000000000000:E6BC50D6F128D30B:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FE00000000000000F03E2147D5D7BC85
+
+0000000000000000:6B7A3116248AE121:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FF00000000000000F03E2147D5D7BC86
+
+0000000000000000:B9B973F5CFA262BD:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FF80000000000000F03E2147D5D7BC87
+
+0000000000000000:CF0A02808E4416F5:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFC0000000000000F03E2147D5D7BC88
+
+0000000000000000:57AAA1031665A0F6:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFE0000000000000F03E2147D5D7BC89
+
+0000000000000000:C5DA694741C400B8:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFF0000000000000F03E2147D5D7BC8A
+
+0000000000000000:827985C4BEED13AD:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFF8000000000000F03E2147D5D7BC8B
+
+0000000000000000:4C959F98D557367B:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFC000000000000F03E2147D5D7BC8C
+
+0000000000000000:FEB783CEC07F19E0:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFE000000000000F03E2147D5D7BC8D
+
+0000000000000000:B2729B4BC2D30E9A:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFF000000000000F03E2147D5D7BC8E
+
+0000000000000000:09F52DED6D12850F:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFF800000000000F03E2147D5D7BC8F
+
+0000000000000000:84255B4BEA0AD20E:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFC00000000000F03E2147D5D7BC90
+
+0000000000000000:D85EC40C40BCA823:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFE00000000000F03E2147D5D7BC91
+
+0000000000000000:66E000E798487EDB:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFF00000000000F03E2147D5D7BC92
+
+0000000000000000:DA51E314770DC073:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFF80000000000F03E2147D5D7BC93
+
+0000000000000000:3C9876ABFCD744E1:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFC0000000000F03E2147D5D7BC94
+
+0000000000000000:35C48069FB403A05:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFE0000000000F03E2147D5D7BC95
+
+0000000000000000:167E7A420F8CE115:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFF0000000000F03E2147D5D7BC96
+
+0000000000000000:3F5F4A0BA480A18B:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFF8000000000F03E2147D5D7BC97
+
+0000000000000000:F8A5AB2EFFBE6588:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFC000000000F03E2147D5D7BC98
+
+0000000000000000:49D255DCA42D2980:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFE000000000F03E2147D5D7BC99
+
+0000000000000000:01FD7EA6AC37D847:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFF000000000F03E2147D5D7BC9A
+
+0000000000000000:94A77C76071734A9:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFF800000000F03E2147D5D7BC9B
+
+0000000000000000:BF7E82A8F9ACEE71:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFC00000000F03E2147D5D7BC9C
+
+0000000000000000:F7CD2DB61C062B70:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFE00000000F03E2147D5D7BC9D
+
+0000000000000000:5D5FC3205EA443CB:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFF00000000F03E2147D5D7BC9E
+
+0000000000000000:177BA1ABE977A3BC:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFF80000000F03E2147D5D7BC9F
+
+0000000000000000:A216FB8EBB474E43:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFC0000000F03E2147D5D7BCA0
+
+0000000000000000:EC01B37568C1C8E6:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFE0000000F03E2147D5D7BCA1
+
+0000000000000000:5C99E5EC34992209:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFF0000000F03E2147D5D7BCA2
+
+0000000000000000:7CA695FA30B7274C:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFF8000000F03E2147D5D7BCA3
+
+0000000000000000:C4FEE5C7491D331A:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFC000000F03E2147D5D7BCA4
+
+0000000000000000:E478C7F21574449D:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFE000000F03E2147D5D7BCA5
+
+0000000000000000:A11D4FBD732DFD01:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFF000000F03E2147D5D7BCA6
+
+0000000000000000:2C44DD477C786C0D:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFF800000F03E2147D5D7BCA7
+
+0000000000000000:850D5D9DA85BC0FF:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFC00000F03E2147D5D7BCA8
+
+0000000000000000:A3A6DDB46772D1B1:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFE00000F03E2147D5D7BCA9
+
+0000000000000000:97FF98957CF38B00:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFF00000F03E2147D5D7BCAA
+
+0000000000000000:BC9E368D91CD2271:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFF80000F03E2147D5D7BCAB
+
+0000000000000000:6B47A38A2BBDD3C8:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFC0000F03E2147D5D7BCAC
+
+0000000000000000:123A41498F2F64E0:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFE0000F03E2147D5D7BCAD
+
+0000000000000000:7362426810CB6EAF:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFF0000F03E2147D5D7BCAE
+
+0000000000000000:42FB3B0EC5DBC02C:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFF8000F03E2147D5D7BCAF
+
+0000000000000000:B7524AB40D565D49:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFC000F03E2147D5D7BCB0
+
+0000000000000000:811C84CD8E223FB5:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFE000F03E2147D5D7BCB1
+
+0000000000000000:16DDAFC9DBA1194D:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFF000F03E2147D5D7BCB2
+
+0000000000000000:390B6AB9069DC5B4:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFF800F03E2147D5D7BCB3
+
+0000000000000000:009F167DC8664555:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFC00F03E2147D5D7BCB4
+
+0000000000000000:47645D90B39B319F:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFE00F03E2147D5D7BCB5
+
+0000000000000000:D75CEC7FBA2064DF:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFF00F03E2147D5D7BCB6
+
+0000000000000000:F59DDE3C02AD7C11:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFF80F03E2147D5D7BCB7
+
+0000000000000000:35AC2155446CCE9F:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFC0F03E2147D5D7BCB8
+
+0000000000000000:1DFEBF13320F7758:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFE0F03E2147D5D7BCB9
+
+0000000000000000:017CA3327FC53831:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFF0F03E2147D5D7BCBA
+
+0000000000000000:999A450B6E2040B9:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFF8F03E2147D5D7BCBB
+
+0000000000000000:49C1CAAC8C229EDE:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFFCF03E2147D5D7BCBC
+
+0000000000000000:2C9D8D0F5D014F7B:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFFEF03E2147D5D7BCBD
+
+0000000000000000:16D7C77223C2FAED:\
+E92C8F13F897BF76193DF2DAAB98DF49E92C8F13F897BF76\
+FFFFFFFFFFFFFFFFF03E2147D5D7BCBE
+
+# Three-key TDES
+0000000000000000:4AACAD89C236FA2B:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+80000000000000000167E25F4EBC7336
+
+0000000000000000:A255A79AAB2211BA:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+C0000000000000000167E25F4EBC7337
+
+0000000000000000:061EFE779DAB818D:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+E0000000000000000167E25F4EBC7338
+
+0000000000000000:23214F0B19BF16B4:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+F0000000000000000167E25F4EBC7339
+
+0000000000000000:52D38F9D53B530AF:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+F8000000000000000167E25F4EBC733A
+
+0000000000000000:B9F4BA694FE9BC3E:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FC000000000000000167E25F4EBC733B
+
+0000000000000000:2384398BBFBD3010:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FE000000000000000167E25F4EBC733C
+
+0000000000000000:D33ECF451E367919:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FF000000000000000167E25F4EBC733D
+
+0000000000000000:FAA94CA00765794C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FF800000000000000167E25F4EBC733E
+
+0000000000000000:14C1303AAEE1B314:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFC00000000000000167E25F4EBC733F
+
+0000000000000000:DC3A4F07DC68AC93:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFE00000000000000167E25F4EBC7340
+
+0000000000000000:A4872C92A093B379:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFF00000000000000167E25F4EBC7341
+
+0000000000000000:3EE74CDFFBEED032:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFF80000000000000167E25F4EBC7342
+
+0000000000000000:328FD9C77EDC78BA:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFC0000000000000167E25F4EBC7343
+
+0000000000000000:A5D36BD81D93CB71:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFE0000000000000167E25F4EBC7344
+
+0000000000000000:D0765A50A9CAE3ED:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFF0000000000000167E25F4EBC7345
+
+0000000000000000:15F3441B4AC4F802:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFF8000000000000167E25F4EBC7346
+
+0000000000000000:01463E8F161851C2:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFC000000000000167E25F4EBC7347
+
+0000000000000000:312E7CB57F08CBC2:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFE000000000000167E25F4EBC7348
+
+0000000000000000:D9688FEF358FE5DF:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFF000000000000167E25F4EBC7349
+
+0000000000000000:30B34034C46E22B5:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFF800000000000167E25F4EBC734A
+
+0000000000000000:A7CA7218CA7D5F9D:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFC00000000000167E25F4EBC734B
+
+0000000000000000:CE41C7659B6BFDA3:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFE00000000000167E25F4EBC734C
+
+0000000000000000:B8EED0C6DFB8B76B:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFF00000000000167E25F4EBC734D
+
+0000000000000000:A0C514277C70278A:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFF80000000000167E25F4EBC734E
+
+0000000000000000:7A8F57670E11D5D8:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFC0000000000167E25F4EBC734F
+
+0000000000000000:35AF5134EC18E0FC:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFE0000000000167E25F4EBC7350
+
+0000000000000000:3034436B0E8B1B4D:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFF0000000000167E25F4EBC7351
+
+0000000000000000:B1DC17DE141AD9EC:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFF8000000000167E25F4EBC7352
+
+0000000000000000:40D2868DCF3BDA80:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFC000000000167E25F4EBC7353
+
+0000000000000000:D3F365825B585FF6:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFE000000000167E25F4EBC7354
+
+0000000000000000:952046F8E93A268A:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFF000000000167E25F4EBC7355
+
+0000000000000000:97D96E48A9216264:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFF800000000167E25F4EBC7356
+
+0000000000000000:DBEE3AD97B87915C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFC00000000167E25F4EBC7357
+
+0000000000000000:94093248683E084F:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFE00000000167E25F4EBC7358
+
+0000000000000000:3133C57CE22A28AB:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFF00000000167E25F4EBC7359
+
+0000000000000000:B32CC354449589E1:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFF80000000167E25F4EBC735A
+
+0000000000000000:979F03CF867FDA3C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFC0000000167E25F4EBC735B
+
+0000000000000000:6BFECB79437E62F4:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFE0000000167E25F4EBC735C
+
+0000000000000000:BAFB5D5B9BE92EEC:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFF0000000167E25F4EBC735D
+
+0000000000000000:D4FB2CAF0F114F42:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFF8000000167E25F4EBC735E
+
+0000000000000000:3F910FDBC4C74698:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFC000000167E25F4EBC735F
+
+0000000000000000:516D7E7739908FED:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFE000000167E25F4EBC7360
+
+0000000000000000:50DE403CB1FB1733:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFF000000167E25F4EBC7361
+
+0000000000000000:1A91443B2892FE8C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFF800000167E25F4EBC7362
+
+0000000000000000:F3A490F9FE853450:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFC00000167E25F4EBC7363
+
+0000000000000000:B7F8398C9D32149C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFE00000167E25F4EBC7364
+
+0000000000000000:179C6729EBDE6A46:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFF00000167E25F4EBC7365
+
+0000000000000000:34520C49E68D307B:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFF80000167E25F4EBC7366
+
+0000000000000000:B6C2F4E4763DF833:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFC0000167E25F4EBC7367
+
+0000000000000000:F911A2AB5E1F0E49:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFE0000167E25F4EBC7368
+
+0000000000000000:307C3C11DF3EE8EA:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFF0000167E25F4EBC7369
+
+0000000000000000:C26A5A02596BFE8D:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFF8000167E25F4EBC736A
+
+0000000000000000:B44B68C5BE17352C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFC000167E25F4EBC736B
+
+0000000000000000:3779CEB11398375F:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFE000167E25F4EBC736C
+
+0000000000000000:7A9EF507F43BD31C:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFF000167E25F4EBC736D
+
+0000000000000000:85CD4D72D2664C70:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFF800167E25F4EBC736E
+
+0000000000000000:9EB57EACAB2B38C8:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFC00167E25F4EBC736F
+
+0000000000000000:E521B274CC7EC06F:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFE00167E25F4EBC7370
+
+0000000000000000:50148A63F3D39097:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFF00167E25F4EBC7371
+
+0000000000000000:6DCE0D8E770CF809:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFF80167E25F4EBC7372
+
+0000000000000000:CAF9334B5A606C31:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFFC0167E25F4EBC7373
+
+0000000000000000:1088488A43D9ACAD:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFFE0167E25F4EBC7374
+
+0000000000000000:F922C4B2357E9034:\
+5E5B890B133B345494AB15F75EB30757972667C862C4BF5E\
+FFFFFFFFFFFFFFFF0167E25F4EBC7375
+
diff --git a/botan/checks/validate.h b/botan/checks/validate.h
new file mode 100644
index 0000000..f7cc4bd
--- /dev/null
+++ b/botan/checks/validate.h
@@ -0,0 +1,34 @@
+
+#ifndef BOTAN_TEST_VALIDATE_H__
+#define BOTAN_TEST_VALIDATE_H__
+
+#include <botan/types.h>
+#include <botan/rng.h>
+#include <string>
+
+using Botan::RandomNumberGenerator;
+
+using Botan::u32bit;
+
+u32bit do_validation_tests(const std::string&,
+ RandomNumberGenerator& rng,
+ bool = true);
+
+u32bit do_bigint_tests(const std::string&,
+ RandomNumberGenerator& rng);
+
+u32bit do_gfpmath_tests(RandomNumberGenerator& rng);
+
+
+u32bit do_pk_validation_tests(const std::string&,
+ RandomNumberGenerator&);
+
+void do_ec_tests(RandomNumberGenerator& rng);
+
+u32bit do_ecdsa_tests(RandomNumberGenerator& rng);
+u32bit do_eckaeg_tests(RandomNumberGenerator& rng);
+u32bit do_cvc_tests(RandomNumberGenerator& rng);
+
+void do_x509_tests(RandomNumberGenerator&);
+
+#endif
diff --git a/botan/checks/x509.cpp b/botan/checks/x509.cpp
new file mode 100644
index 0000000..6f19128
--- /dev/null
+++ b/botan/checks/x509.cpp
@@ -0,0 +1,224 @@
+
+#include <botan/filters.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#ifdef BOTAN_HAS_X509
+ #include <botan/x509self.h>
+ #include <botan/x509stor.h>
+ #include <botan/x509_ca.h>
+ #include <botan/pkcs10.h>
+#endif
+
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+#include "validate.h"
+#include "common.h"
+
+#if defined(BOTAN_HAS_X509) && defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_DSA)
+
+namespace {
+
+u64bit key_id(const Public_Key* key)
+ {
+ std::auto_ptr<X509_Encoder> encoder(key->x509_encoder());
+ if(!encoder.get())
+ throw Internal_Error("Public_Key:key_id: No encoder found");
+
+ Pipe pipe(new Hash_Filter("SHA-1", 8));
+ pipe.start_msg();
+ pipe.write(key->algo_name());
+ pipe.write(encoder->alg_id().parameters);
+ pipe.write(encoder->key_bits());
+ pipe.end_msg();
+
+ SecureVector<byte> output = pipe.read_all();
+
+ if(output.size() != 8)
+ throw Internal_Error("Public_Key::key_id: Incorrect output size");
+
+ u64bit id = 0;
+ for(u32bit j = 0; j != 8; ++j)
+ id = (id << 8) | output[j];
+ return id;
+ }
+
+
+/* Return some option sets */
+X509_Cert_Options ca_opts()
+ {
+ X509_Cert_Options opts("Test CA/US/Botan Project/Testing");
+
+ opts.uri = "http://botan.randombit.net";
+ opts.dns = "botan.randombit.net";
+ opts.email = "testing@randombit.net";
+
+ opts.CA_key(1);
+
+ return opts;
+ }
+
+X509_Cert_Options req_opts1()
+ {
+ X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
+
+ opts.uri = "http://botan.randombit.net";
+ opts.dns = "botan.randombit.net";
+ opts.email = "testing@randombit.net";
+
+ return opts;
+ }
+
+X509_Cert_Options req_opts2()
+ {
+ X509_Cert_Options opts("Test User 2/US/Botan Project/Testing");
+
+ opts.uri = "http://botan.randombit.net";
+ opts.dns = "botan.randombit.net";
+ opts.email = "testing@randombit.net";
+
+ opts.add_ex_constraint("PKIX.EmailProtection");
+
+ return opts;
+ }
+
+u32bit check_against_copy(const Private_Key& orig,
+ RandomNumberGenerator& rng)
+ {
+ Private_Key* copy_priv = PKCS8::copy_key(orig, rng);
+ Public_Key* copy_pub = X509::copy_key(orig);
+
+ const std::string passphrase= "I need work! -Mr. T";
+ DataSource_Memory enc_source(PKCS8::PEM_encode(orig, rng, passphrase));
+ Private_Key* copy_priv_enc = PKCS8::load_key(enc_source, rng,
+ passphrase);
+
+ u64bit orig_id = key_id(&orig);
+ u64bit pub_id = key_id(copy_pub);
+ u64bit priv_id = key_id(copy_priv);
+ u64bit priv_enc_id = key_id(copy_priv_enc);
+
+ delete copy_pub;
+ delete copy_priv;
+ delete copy_priv_enc;
+
+ if(orig_id != pub_id || orig_id != priv_id || orig_id != priv_enc_id)
+ {
+ std::cout << "Failed copy check\n";
+ return 1;
+ }
+ return 0;
+ }
+
+}
+
+void do_x509_tests(RandomNumberGenerator& rng)
+ {
+ std::cout << "Testing X.509 CA/CRL/cert/cert request: " << std::flush;
+
+ /* Create the CA's key and self-signed cert */
+ std::cout << '.' << std::flush;
+ RSA_PrivateKey ca_key(rng, 1024);
+
+ std::cout << '.' << std::flush;
+ X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(),
+ ca_key,
+ rng);
+ std::cout << '.' << std::flush;
+
+ /* Create user #1's key and cert request */
+ std::cout << '.' << std::flush;
+ DSA_PrivateKey user1_key(rng, DL_Group("dsa/jce/1024"));
+
+ std::cout << '.' << std::flush;
+ PKCS10_Request user1_req = X509::create_cert_req(req_opts1(),
+ user1_key,
+ rng);
+
+ /* Create user #2's key and cert request */
+ std::cout << '.' << std::flush;
+#if defined(BOTAN_HAS_ECDSA)
+ ECDSA_PrivateKey user2_key(rng, get_EC_Dom_Pars_by_oid("1.3.132.0.8"));
+#else
+ RSA_PrivateKey user2_key(rng, 1024);
+#endif
+
+ std::cout << '.' << std::flush;
+ PKCS10_Request user2_req = X509::create_cert_req(req_opts2(),
+ user2_key,
+ rng);
+
+ /* Create the CA object */
+ std::cout << '.' << std::flush;
+ X509_CA ca(ca_cert, ca_key);
+ std::cout << '.' << std::flush;
+
+ /* Sign the requests to create the certs */
+ std::cout << '.' << std::flush;
+ X509_Certificate user1_cert =
+ ca.sign_request(user1_req, rng,
+ X509_Time("2008-01-01"), X509_Time("2100-01-01"));
+
+ std::cout << '.' << std::flush;
+ X509_Certificate user2_cert = ca.sign_request(user2_req, rng,
+ X509_Time("2008-01-01"),
+ X509_Time("2100-01-01"));
+ std::cout << '.' << std::flush;
+
+ X509_CRL crl1 = ca.new_crl(rng);
+
+ /* Verify the certs */
+ X509_Store store;
+
+ store.add_cert(ca_cert, true); // second arg == true: trusted CA cert
+
+ std::cout << '.' << std::flush;
+ if(store.validate_cert(user1_cert) != VERIFIED)
+ std::cout << "\nFAILED: User cert #1 did not validate" << std::endl;
+
+ if(store.validate_cert(user2_cert) != VERIFIED)
+ std::cout << "\nFAILED: User cert #2 did not validate" << std::endl;
+
+ if(store.add_crl(crl1) != VERIFIED)
+ std::cout << "\nFAILED: CRL #1 did not validate" << std::endl;
+
+ std::vector<CRL_Entry> revoked;
+ revoked.push_back(user2_cert);
+
+ X509_CRL crl2 = ca.update_crl(crl1, revoked, rng);
+
+ if(store.add_crl(crl2) != VERIFIED)
+ std::cout << "\nFAILED: CRL #2 did not validate" << std::endl;
+
+ if(store.validate_cert(user2_cert) != CERT_IS_REVOKED)
+ std::cout << "\nFAILED: User cert #2 was not revoked" << std::endl;
+
+ check_against_copy(ca_key, rng);
+ check_against_copy(user1_key, rng);
+ check_against_copy(user2_key, rng);
+
+ std::cout << std::endl;
+ }
+
+#else
+
+void do_x509_tests(RandomNumberGenerator&)
+ {
+ std::cout << "Skipping Botan X.509 tests (disabled in build)\n";
+ }
+
+#endif
+
diff --git a/botan/configure.pl b/botan/configure.pl
new file mode 100644
index 0000000..1ce01e2
--- /dev/null
+++ b/botan/configure.pl
@@ -0,0 +1,2340 @@
+#!/usr/bin/perl -w
+
+require 5.006;
+
+use strict;
+
+use Config;
+use Getopt::Long;
+use File::Spec;
+use File::Copy;
+use File::Find;
+use Sys::Hostname;
+
+my $MAJOR_VERSION = 1;
+my $MINOR_VERSION = 8;
+my $PATCH_VERSION = 8;
+
+my $VERSION_SUFFIX = '';
+
+my $SO_PATCH_VERSION = 2;
+
+my $VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION$VERSION_SUFFIX";
+my $SO_VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$SO_PATCH_VERSION$VERSION_SUFFIX";
+
+##################################################
+# Data #
+##################################################
+my (%CPU, %OPERATING_SYSTEM, %COMPILER, %MODULES);
+
+my @DOCS = (
+ 'api.pdf', 'tutorial.pdf', 'fips140.pdf',
+ 'api.tex', 'tutorial.tex', 'fips140.tex',
+ 'credits.txt', 'license.txt', 'log.txt',
+ 'thanks.txt', 'todo.txt', 'pgpkeys.asc');
+
+my $TRACING = 0;
+
+##################################################
+# Run main() and Quit #
+##################################################
+my $config = {};
+
+main();
+exit;
+
+sub exec_uname {
+ # Only exec it if we think it might actually work
+ if(-f '/bin/uname' || -f '/usr/bin/uname' || -f '/bin/sh') {
+ my $uname = `uname -a`;
+ if($uname) {
+ chomp $uname;
+ return $uname;
+ }
+ }
+
+ return '';
+}
+
+sub deprecation_warning {
+ warning("$0 is deprecated; migration to ./configure.py strongly recommended");
+}
+
+##################################################
+# Main Driver #
+##################################################
+sub main {
+ my $base_dir = where_am_i();
+
+ deprecation_warning();
+
+ $$config{'uname'} = exec_uname();
+
+ $$config{'base-dir'} = $base_dir;
+ $$config{'src-dir'} = File::Spec->catdir($base_dir, 'src');
+ $$config{'checks-dir'} = File::Spec->catdir($base_dir, 'checks');
+ $$config{'doc_src_dir'} = File::Spec->catdir($base_dir, 'doc');
+
+ $$config{'config-dir'} =
+ File::Spec->catdir($$config{'src-dir'}, 'build-data');
+
+ $$config{'command_line'} = $0 . ' ' . join(' ', @ARGV);
+ $$config{'timestamp'} = gmtime;
+ $$config{'user'} = getlogin || getpwuid($<) || '';
+ $$config{'hostname'} = hostname;
+
+ %CPU = read_info_files($config, 'arch', \&get_arch_info);
+ %OPERATING_SYSTEM = read_info_files($config, 'os', \&get_os_info);
+ %COMPILER = read_info_files($config, 'cc', \&get_cc_info);
+ %MODULES = read_module_files($config);
+
+ add_to($config, {
+ 'version_major' => $MAJOR_VERSION,
+ 'version_minor' => $MINOR_VERSION,
+ 'version_patch' => $PATCH_VERSION,
+ 'version' => $VERSION_STRING,
+ 'so_version' => $SO_VERSION_STRING,
+ });
+
+ get_options($config);
+
+ my $default_value_is = sub {
+ my ($var, $val) = @_;
+ $$config{$var} = $val if not defined($$config{$var});
+ };
+
+ &$default_value_is('gcc_bug', 0);
+ &$default_value_is('autoconfig', 1);
+ &$default_value_is('debug', 0);
+ &$default_value_is('shared', 'yes');
+ &$default_value_is('local_config', '');
+
+ # Goes into build-specific dirs (maybe)
+
+ $$config{'build_dir'} = 'build';
+ $$config{'botan_config'} = File::Spec->catfile(
+ $$config{'build_dir'}, 'botan-config');
+
+ $$config{'botan_pkgconfig'} = File::Spec->catfile(
+ $$config{'build_dir'},
+ 'botan-' . $MAJOR_VERSION . '.' . $MINOR_VERSION . '.pc');
+
+ $$config{'makefile'} = 'Makefile';
+ $$config{'check_prefix'} = '';
+ $$config{'lib_prefix'} = '';
+
+ if(defined($$config{'with_build_dir'})) {
+ for my $var ('build_dir',
+ 'botan_config',
+ 'botan_pkgconfig',
+ 'makefile',
+ 'check_prefix',
+ 'lib_prefix')
+ {
+ $$config{$var} = File::Spec->catfile($$config{'with_build_dir'},
+ $$config{$var});
+ }
+ }
+ else {
+ }
+
+ choose_target($config);
+
+ my $os = $$config{'os'};
+ my $cc = $$config{'compiler'};
+
+ &$default_value_is('prefix', os_info_for($os, 'install_root'));
+ &$default_value_is('libdir', os_info_for($os, 'lib_dir'));
+ &$default_value_is('docdir', os_info_for($os, 'doc_dir'));
+ &$default_value_is('make_style', $COMPILER{$cc}{'makefile_style'});
+
+ scan_modules($config);
+
+ print_enabled_modules($config);
+
+ add_to($config, {
+ 'includedir' => os_info_for($os, 'header_dir'),
+
+ 'build_lib' => File::Spec->catdir($$config{'build_dir'}, 'lib'),
+ 'build_check' => File::Spec->catdir($$config{'build_dir'}, 'checks'),
+ 'build_include' =>
+ File::Spec->catdir($$config{'build_dir'}, 'include'),
+ 'build_include_botan' =>
+ File::Spec->catdir($$config{'build_dir'}, 'include', 'botan'),
+
+ 'mp_bits' => find_mp_bits($config),
+ 'mod_libs' => [ using_libs($config) ],
+
+ 'sources' => { },
+ 'includes' => { },
+
+ 'check_src' => {
+ map_to($$config{'checks-dir'},
+ grep { $_ ne 'keys' and !m@\.(dat|h)$@ }
+ dir_list($$config{'checks-dir'}))
+ }
+ });
+
+ load_modules($config);
+
+ my @dirs = mkdirs($$config{'build_dir'},
+ $$config{'build_include'},
+ $$config{'build_include_botan'},
+ $$config{'build_lib'},
+ $$config{'build_check'});
+
+ #autoconfig('Created ' . join(' ', @dirs)) if @dirs;
+
+ write_pkg_config($config);
+
+ determine_config($config);
+
+ process_template(File::Spec->catfile($$config{'config-dir'}, 'buildh.in'),
+ File::Spec->catfile($$config{'build_dir'}, 'build.h'),
+ $config);
+
+ process_template(File::Spec->catfile(
+ $$config{'config-dir'}, 'botan.doxy.in'),
+ File::Spec->catfile($$config{'doc_src_dir'}, 'botan.doxy'),
+ $config);
+
+ $$config{'includes'}{'build.h'} = $$config{'build_dir'};
+
+ generate_makefile($config);
+
+ copy_include_files($config);
+
+ deprecation_warning();
+}
+
+sub where_am_i {
+ my ($volume,$dir,$file) = File::Spec->splitpath($0);
+ my $src_dir = File::Spec->catpath($volume, $dir, '');
+ return $src_dir if $src_dir;
+ return File::Spec->curdir();
+}
+
+##################################################
+# Diagnostics #
+##################################################
+sub with_diagnostic {
+ my ($type, @args) = @_;
+
+ my $args = join('', @args);
+ my $str = "($type): ";
+ while(length($str) < 14) { $str = ' ' . $str; }
+
+ $str .= $args . "\n";
+ return $str;
+}
+
+sub croak {
+ die with_diagnostic('error', @_);
+}
+
+sub warning {
+ warn with_diagnostic('warning', @_);
+}
+
+sub autoconfig {
+ print with_diagnostic('autoconfig', @_);
+}
+
+sub emit_help {
+ print join('', @_);
+ exit;
+}
+
+sub trace {
+ return unless $TRACING;
+
+ my (undef, undef, $line) = caller(0);
+ my (undef, undef, undef, $func) = caller(1);
+
+ $func =~ s/main:://;
+
+ print with_diagnostic('trace', "at $func:$line - ", @_);
+}
+
+##################################################
+# Display Help and Quit #
+##################################################
+sub display_help {
+ sub module_sets {
+ my %modsets;
+ for my $name (sort keys %MODULES) {
+ my %info = %{$MODULES{$name}};
+ next unless (defined($info{'modset'}));
+
+ for my $s (split(/,/, $info{'modset'})) {
+ $modsets{$s} = undef;
+ }
+ }
+
+ return sort keys %modsets;
+ }
+
+ my $sets = join(' ', module_sets());
+
+ my $listing = sub {
+ my (@list) = @_;
+
+ return '' if (@list == 0);
+
+ my ($output, $len) = ('', 0);
+
+ my $append = sub {
+ my ($to_append) = @_;
+ $output .= $to_append;
+ $len += length $to_append;
+ };
+
+ foreach my $name (sort @list) {
+ next if $name eq 'defaults';
+ if($len > 58) {
+ $output .= "\n ";
+ $len = 8;
+ }
+ &$append($name . ' ');
+ }
+ chop $output;
+ return $output;
+ };
+
+ #my $modules = &$listing(keys %MODULES);
+ my $compilers = &$listing(keys %COMPILER);
+ my $oses = &$listing(keys %OPERATING_SYSTEM);
+ my $cpus = &$listing(keys %CPU);
+
+ my $helptxt = <<ENDOFHELP;
+This is $0 from Botan $VERSION_STRING
+
+To select the compiler, use
+
+ --cc=[$compilers]
+
+To select the OS and processor to target, use these options. By
+default, autodetection will be attempted.
+
+ --os=[generic $oses]
+ --cpu=[generic $cpus]
+
+ --with-endian=[little big none]
+ --with-unaligned-mem=[yes no]
+
+To change build options:
+
+ --with-tr1={none,system,boost} enable (or disable) using a TR1 implementation
+ --with-build-dir=DIR setup the build in DIR
+ --with-local-config=FILE include the contents of FILE into build.h
+
+ --disable-debug don't worry about debugging
+ --enable-debug set compiler flags for debugging
+
+ --enable-shared enable shared libraries
+ --disable-shared don't build shared libararies
+
+To change where the library is installed:
+
+ --prefix=PATH set the base installation directory
+ --libdir=PATH install library files in \${prefix}/\${libdir}
+ --docdir=PATH install documentation in \${prefix}/\${docdir}
+
+To change what modules to use:
+
+ --enable-modules=[module,[module[,...]]]
+ --disable-modules=[module,[module[,...]]]
+
+To get diagnostic and debug output:
+
+ --module-info display more information about modules
+
+ --show-arch-info=CPU show more information about a particular CPU
+ [$cpus]
+
+ --help display this help
+ --version display the version of Botan
+ --quiet display only warnings and errors
+ --trace enable runtime tracing of this program
+
+See doc/building.pdf for more information about this program.
+
+ENDOFHELP
+
+ emit_help($helptxt);
+}
+
+##################################################
+# Display Further Information about Modules #
+##################################################
+sub module_info {
+
+ my $info = '';
+ foreach my $mod (sort keys %MODULES) {
+ my $modinfo = $MODULES{$mod};
+ my $fullname = $$modinfo{'realname'};
+
+ while(length($mod) < 10) { $mod .= ' '; }
+ $info .= "$mod - $fullname\n";
+ }
+
+ return $info;
+}
+
+##################################################
+#
+##################################################
+sub choose_target {
+ my ($config) = @_;
+
+ my $cc = $$config{'compiler'};
+ my $os = $$config{'os'};
+ my $cpu = $$config{'cpu'};
+
+ autoconfig("Setting up build for Botan $VERSION_STRING");
+
+ $cpu = guess_cpu() if not defined($cpu);
+ $cc = guess_compiler() if not defined($cc);
+ $os = guess_os() if not defined($os);
+
+ display_help()
+ unless(defined($cc) and defined($os) and defined($cpu));
+
+ croak("Compiler $cc isn't known (try --help)")
+ unless defined($COMPILER{$cc});
+
+ my %ccinfo = %{$COMPILER{$cc}};
+
+ if(defined($ccinfo{'compiler_has_tr1'})) {
+ unless(defined($$config{'tr1'})) {
+ autoconfig('Assuming compiler ', $cc, ' has TR1 headers. ',
+ 'Use --with-tr1=none to disable');
+ $$config{'tr1'} = 'system';
+ }
+ }
+
+ $os = os_alias($os);
+ croak("OS $os isn't known (try --help)") unless
+ ($os eq 'generic' or defined($OPERATING_SYSTEM{$os}));
+
+ my ($arch, $submodel) = figure_out_arch($cpu);
+
+ # hacks
+ if($cc eq 'gcc') {
+ $ccinfo{'binary_name'} = 'c++' if($os eq 'darwin');
+
+ if($$config{'gcc_bug'} != 1) {
+ my $binary = $ccinfo{'binary_name'};
+
+ my $gcc_version = `$binary -v 2>&1`;
+
+ $gcc_version = '' if not defined $gcc_version;
+
+ my $has_ll_bug = 0;
+ $has_ll_bug = 1 if($gcc_version =~ /4\.[01234]/);
+ $has_ll_bug = 1 if($gcc_version =~ /3\.[34]/);
+ $has_ll_bug = 1 if($gcc_version =~ /2\.95\.[0-4]/);
+ $has_ll_bug = 1 if($gcc_version eq '');
+
+ $has_ll_bug = 0 if($arch eq 'alpha' or $arch =~ /.*64$/);
+
+ if($has_ll_bug)
+ {
+ warning('Enabling -fpermissive to work around ',
+ 'possible GCC bug');
+
+ $$config{'gcc_bug'} = 1;
+ }
+
+ warning('GCC 2.95.x issues many spurious warnings')
+ if($gcc_version =~ /2\.95\.[0-4]/);
+ }
+ }
+
+ trace("using $cc $os $arch $submodel");
+
+ add_to($config, {
+ 'compiler' => $cc,
+ 'os' => $os,
+ 'arch' => $arch,
+ 'submodel' => $submodel,
+ });
+}
+
+sub module_runs_on {
+ my ($config, $modinfo, $mod, $noisy) = @_;
+
+ my $cc = $$config{'compiler'};
+ my $os = $$config{'os'};
+ my $submodel = $$config{'submodel'};
+ my $arch = $$config{'arch'};
+
+ my %modinfo = %{$modinfo};
+
+ my $realname = $modinfo{'realname'};
+
+ my @arch_list = @{ $modinfo{'arch'} };
+ if(scalar @arch_list > 0 && !in_array($arch, \@arch_list) &&
+ !in_array($submodel, \@arch_list))
+ {
+ autoconfig("$mod ($realname): skipping, " .
+ "not compatible with " . realname($arch) .
+ "/" . $submodel) if $noisy;
+ return 0;
+ }
+
+ my @os_list = @{ $modinfo{'os'} };
+ if(scalar @os_list > 0 && !in_array($os, \@os_list))
+ {
+ autoconfig("$mod ($realname): " .
+ "skipping, not compatible with " . realname($os)) if $noisy;
+ return 0;
+ }
+
+ my @cc_list = @{ $modinfo{'cc'} };
+ if(scalar @cc_list > 0 && !in_array($cc, \@cc_list)) {
+ autoconfig("$mod ($realname): " .
+ "skipping, not compatible with " . realname($cc)) if $noisy;
+ return 0;
+ }
+
+
+ if($modinfo{'uses_tr1'} eq 'yes') {
+ return 0 unless defined($$config{'tr1'});
+
+ my $tr1 = $$config{'tr1'};
+ return 0 unless($tr1 eq 'system' or $tr1 eq 'boost');
+ }
+
+ return 1;
+}
+
+sub scan_modules {
+ my ($config) = @_;
+
+ foreach my $mod (sort keys %MODULES) {
+ my %modinfo = %{ $MODULES{$mod} };
+
+ next if(defined($$config{'modules'}{$mod}) && $$config{'modules'}{$mod} < 0);
+
+ next unless(module_runs_on($config, \%modinfo, $mod, 0));
+
+ if($modinfo{'load_on'} eq 'auto' or
+ $modinfo{'load_on'} eq 'always' or
+ ($modinfo{'load_on'} eq 'asm_ok' and $$config{'asm_ok'})) {
+
+ my %maybe_load = ();
+ my $all_deps_found = 1;
+
+ LINE: foreach (@{$modinfo{'requires'}}) {
+ for my $req_mod (split(/\|/, $_)) {
+ next unless defined $MODULES{$req_mod};
+
+ next if(defined($$config{'modules'}{$req_mod}) && $$config{'modules'}{$req_mod} < 0);
+ next unless(module_runs_on($config, $MODULES{$req_mod}, $req_mod, 0));
+
+ $maybe_load{$req_mod} = 1;
+ next LINE;
+ }
+ $all_deps_found = 0;
+ }
+
+ if($all_deps_found) {
+ foreach my $depmod (keys %maybe_load)
+ { $$config{'modules'}{$depmod} = 1; }
+ $$config{'modules'}{$mod} = 1;
+ }
+ }
+ }
+}
+
+sub print_enabled_modules {
+ my ($config) = @_;
+
+ return unless($$config{'verbose'});
+
+ my %by_type;
+
+ foreach my $mod (sort keys %MODULES) {
+ my $type = $MODULES{$mod}{'type'};
+
+ my $n = 0;
+ $n = 1 if($$config{'modules'}{$mod} && $$config{'modules'}{$mod} > 0);
+
+ $by_type{$type}{$mod} = $n;
+ }
+
+ for my $type (sort keys %by_type) {
+ my %mods = %{$by_type{$type}};
+
+ my @load_lines;
+
+ if(keys %mods == 1) {
+ my $on = $mods{$type};
+
+ if($on > 0) {
+ print with_diagnostic('loading', $type);
+ }
+ else {
+ print with_diagnostic('loading', '[', $type , ']');
+ }
+ }
+ else {
+ my $s = $type . ': ';
+
+ for my $mod (sort keys %mods) {
+ my $on = $mods{$mod};
+
+ if($s eq '') {
+ $s = ' ' x (length($type) + 16);
+ }
+
+ if($on > 0) {
+ $s .= $mod . ' ';
+ }
+ else {
+ $s .= '[' . $mod . '] ';
+ }
+
+ if(length($s) > 60) {
+ push @load_lines, $s;
+ $s = '';
+ }
+ }
+
+ #print "Last1 '$s'\n";
+
+ $s =~ s/\s*$//m; # strip trailing whitespace
+
+ push @load_lines, $s if($s ne '');
+
+
+ print with_diagnostic('loading', join("\n", @load_lines));
+ }
+ }
+}
+
+sub get_options {
+ my ($config) = @_;
+
+ my $save_option = sub {
+ my ($opt, $val) = @_;
+ $opt =~ s/-/_/g;
+ $$config{$opt} = $val;
+ };
+
+ $$config{'verbose'} = 1;
+ $$config{'asm_ok'} = 1;
+ $$config{'tr1'} = undef; # not enabled by default
+ $$config{'modules'} = {};
+
+ sub arch_info {
+ my $arg = $_[0];
+
+ my $arch = find_arch($arg);
+
+ unless(defined($arch) and defined($CPU{$arch})) {
+ warning("Unknown arch '$arg' passed to --arch-info (try --help)");
+ return '';
+ }
+
+ my %info = %{ $CPU{$arch} };
+
+ my $out = "Information for $arg ($arch)\n--------\n";
+
+ if(@{$info{'aliases'}}) {
+ $out .= 'Aliases: ' . join(' ', @{$info{'aliases'}}) . "\n";
+ }
+
+ if(@{$info{'submodels'}}) {
+ $out .= 'Submodels: ' . join(' ', @{$info{'submodels'}}) . "\n";
+ }
+
+ foreach my $k (keys %{$info{'submodel_aliases'}}) {
+ $out .= "Alias '$k' -> '" . $info{'submodel_aliases'}{$k} . "'\n";
+ }
+
+ if(defined($info{'endian'})) {
+ $out .= 'Default endian: ' . $info{'endian'} . "\n";
+ }
+
+ if(defined($info{'unaligned'})) {
+ $out .= 'Unaligned memory access: ' . $info{'unaligned'} . "\n";
+ }
+
+ return $out;
+ }
+
+ sub add_modules {
+ my ($config,$mods) = @_;
+
+ foreach my $mod (split(/,/, $mods)) {
+ # -1 means disabled by user, do not load
+ $$config{'modules'}{$mod} = 1 unless(
+ defined($$config{'modules'}{$mod}) &&
+ $$config{'modules'}{$mod} == -1);
+ }
+ }
+
+ sub disable_modules {
+ my ($config,$mods) = @_;
+
+ foreach my $mod (split(/,/, $mods)) {
+ # -1 means disabled by user, do not load
+ $$config{'modules'}{$mod} = -1;
+ }
+ }
+
+ sub add_module_sets {
+ my ($config,$sets) = @_;
+
+ foreach my $set (split(/,/, $sets)) {
+ for my $mod (sort keys %MODULES) {
+ my %info = %{$MODULES{$mod}};
+
+ next unless (defined($info{'modset'}));
+
+ for my $s (split(/,/, $info{'modset'})) {
+ if($s eq $set) {
+ $$config{'modules'}{$mod} = 1
+ unless($$config{'modules'}{$mod} == -1);
+ }
+ }
+ }
+ }
+ }
+
+ exit 1 unless GetOptions(
+ 'prefix=s' => sub { &$save_option(@_); },
+ 'exec-prefix=s' => sub { &$save_option(@_); },
+
+ 'bindir=s' => sub { &$save_option(@_); },
+ 'datadir' => sub { &$save_option(@_); },
+ 'datarootdir' => sub { &$save_option(@_); },
+ 'docdir=s' => sub { &$save_option(@_); },
+ 'dvidir' => sub { &$save_option(@_); },
+ 'htmldir' => sub { &$save_option(@_); },
+ 'includedir' => sub { &$save_option(@_); },
+ 'infodir' => sub { &$save_option(@_); },
+ 'libdir=s' => sub { &$save_option(@_); },
+ 'libexecdir' => sub { &$save_option(@_); },
+ 'localedir' => sub { &$save_option(@_); },
+ 'localstatedir' => sub { &$save_option(@_); },
+ 'mandir' => sub { &$save_option(@_); },
+ 'oldincludedir' => sub { &$save_option(@_); },
+ 'pdfdir' => sub { &$save_option(@_); },
+ 'psdir' => sub { &$save_option(@_); },
+ 'sbindir=s' => sub { &$save_option(@_); },
+ 'sharedstatedir' => sub { &$save_option(@_); },
+ 'sysconfdir' => sub { &$save_option(@_); },
+
+ 'cc=s' => sub { &$save_option('compiler', $_[1]) },
+ 'os=s' => sub { &$save_option(@_) },
+ 'cpu=s' => sub { &$save_option(@_) },
+
+ 'help' => sub { display_help(); },
+ 'module-info' => sub { emit_help(module_info()); },
+ 'version' => sub { emit_help("$VERSION_STRING\n") },
+ 'so-version' => sub { emit_help("$SO_VERSION_STRING\n") },
+
+ 'with-tr1-implementation=s' => sub { $$config{'tr1'} = $_[1]; },
+
+ 'quiet' => sub { $$config{'verbose'} = 0; },
+ 'trace' => sub { $TRACING = 1; },
+
+ 'enable-asm' => sub { $$config{'asm_ok'} = 1; },
+ 'disable-asm' => sub { $$config{'asm_ok'} = 0; },
+
+ 'enable-autoconfig' => sub { $$config{'autoconfig'} = 1; },
+ 'disable-autoconfig' => sub { $$config{'autoconfig'} = 0; },
+
+ 'enable-shared' => sub { $$config{'shared'} = 'yes'; },
+ 'disable-shared' => sub { $$config{'shared'} = 'no'; },
+
+ 'enable-debug' => sub { &$save_option('debug', 1); },
+ 'disable-debug' => sub { &$save_option('debug', 0); },
+
+ 'enable-modules:s' => sub { add_modules($config, $_[1]); },
+ 'disable-modules:s' => sub { disable_modules($config, $_[1]); },
+
+ 'with-openssl' => sub { add_modules($config, 'openssl'); },
+ 'without-openssl' => sub { disable_modules($config, 'openssl'); },
+ 'with-gnump' => sub { add_modules($config, 'gnump'); },
+ 'without-gnump' => sub { disable_modules($config, 'gnump'); },
+ 'with-bzip2' => sub { add_modules($config, 'bzip2'); },
+ 'without-bzip2' => sub { disable_modules($config, 'bzip2'); },
+ 'with-zlib' => sub { add_modules($config, 'zlib'); },
+ 'without-zlib' => sub { disable_modules($config, 'zlib'); },
+
+ 'use-module-set=s' => sub { add_module_sets($config, $_[1]); },
+
+ 'with-build-dir=s' => sub { &$save_option(@_); },
+ 'with-endian=s' => sub { &$save_option(@_); },
+ 'with-unaligned-mem=s' => sub { &$save_option(@_); },
+ 'with-local-config=s' =>
+ sub { &$save_option('local_config', slurp_file($_[1])); },
+
+ 'modules=s' => sub { add_modules($config, $_[1]); },
+ 'show-arch-info=s' => sub { emit_help(arch_info($_[1])); },
+ 'make-style=s' => sub { &$save_option(@_); },
+ 'dumb-gcc|gcc295x' => sub { $$config{'gcc_bug'} = 1; }
+ );
+
+ # All arguments should now be consumed
+ croak("Unknown option $ARGV[0] (try --help)") unless($#ARGV == -1);
+}
+
+##################################################
+# Functions to search the info tables #
+##################################################
+sub find_arch {
+ my $name = $_[0];
+
+ foreach my $arch (keys %CPU) {
+ my %info = %{$CPU{$arch}};
+
+ return $arch if($name eq $arch);
+
+ foreach my $alias (@{$info{'aliases'}}) {
+ return $arch if($name eq $alias);
+ }
+
+ foreach my $submodel (@{$info{'submodels'}}) {
+ return $arch if($name eq $submodel);
+ }
+
+ foreach my $submodel (keys %{$info{'submodel_aliases'}}) {
+ return $arch if($name eq $submodel);
+ }
+ }
+ return undef;
+};
+
+sub figure_out_arch {
+ my ($name) = @_;
+
+ return ('generic', 'generic') if($name eq 'generic');
+
+ my $submodel_alias = sub {
+ my ($name,$info) = @_;
+
+ my %info = %{$info};
+
+ foreach my $submodel (@{$info{'submodels'}}) {
+ return $submodel if($name eq $submodel);
+ }
+
+ return '' unless defined $info{'submodel_aliases'};
+ my %sm_aliases = %{$info{'submodel_aliases'}};
+
+ foreach my $alias (keys %sm_aliases) {
+ my $official = $sm_aliases{$alias};
+ return $official if($alias eq $name);
+ }
+ return '';
+ };
+
+ my $arch = find_arch($name);
+ croak("Arch type $name isn't known (try --help)") unless defined $arch;
+ trace("mapped name '$name' to arch '$arch'");
+
+ my %archinfo = %{ $CPU{$arch} };
+
+ my $submodel = &$submodel_alias($name, \%archinfo);
+
+ if($submodel eq '') {
+ $submodel = $archinfo{'default_submodel'};
+
+ autoconfig("Using $submodel as default type for family ",
+ realname($arch)) if($submodel ne $arch);
+ }
+
+ trace("mapped name '$name' to submodel '$submodel'");
+
+ croak("Couldn't figure out arch type of $name")
+ unless defined($arch) and defined($submodel);
+
+ return ($arch,$submodel);
+}
+
+sub os_alias {
+ my $name = $_[0];
+
+ foreach my $os (keys %OPERATING_SYSTEM) {
+ foreach my $alias (@{$OPERATING_SYSTEM{$os}{'aliases'}}) {
+ if($alias eq $name) {
+ trace("os_alias($name) -> $os");
+ return $os;
+ }
+ }
+ }
+
+ return $name;
+}
+
+sub os_info_for {
+ my ($os,$what) = @_;
+
+ die unless defined($os);
+
+ croak('os_info_for called with an os of defaults (internal problem)')
+ if($os eq 'defaults');
+
+ my $result = '';
+
+ if(defined($OPERATING_SYSTEM{$os})) {
+ my %osinfo = %{$OPERATING_SYSTEM{$os}};
+ $result = $osinfo{$what};
+ }
+
+ if(!defined($result) or $result eq '') {
+ $result = $OPERATING_SYSTEM{'defaults'}{$what};
+ }
+
+ croak("os_info_for: No info for $what on $os") unless defined $result;
+
+ return $result;
+}
+
+sub my_compiler {
+ my ($config) = @_;
+ my $cc = $$config{'compiler'};
+
+ croak('my_compiler called, but no compiler set in config')
+ unless defined $cc and $cc ne '';
+
+ croak("unknown compiler $cc") unless defined $COMPILER{$cc};
+
+ return %{$COMPILER{$cc}};
+}
+
+sub mach_opt {
+ my ($config) = @_;
+
+ my %ccinfo = my_compiler($config);
+
+ # Nothing we can do in that case
+ return '' unless $ccinfo{'mach_opt_flags'};
+
+ my $submodel = $$config{'submodel'};
+ my $arch = $$config{'arch'};
+ if(defined($ccinfo{'mach_opt_flags'}{$submodel}))
+ {
+ return $ccinfo{'mach_opt_flags'}{$submodel};
+ }
+ elsif(defined($ccinfo{'mach_opt_flags'}{$arch})) {
+ my $mach_opt_flags = $ccinfo{'mach_opt_flags'}{$arch};
+ my $processed_modelname = $submodel;
+
+ my $remove = '';
+ if(defined($ccinfo{'mach_opt_re'}) and
+ defined($ccinfo{'mach_opt_re'}{$arch})) {
+ $remove = $ccinfo{'mach_opt_re'}{$arch};
+ }
+
+ $processed_modelname =~ s/$remove//;
+ $mach_opt_flags =~ s/SUBMODEL/$processed_modelname/g;
+ return $mach_opt_flags;
+ }
+ return '';
+}
+
+##################################################
+# #
+##################################################
+sub using_libs {
+ my ($config) = @_;
+
+ my $os = $$config{'os'};
+ my %libs;
+
+ foreach my $mod (sort keys %{$$config{'modules'}}) {
+ next if ${$$config{'modules'}}{$mod} < 0;
+
+ my %MOD_LIBS = %{ $MODULES{$mod}{'libs'} };
+
+ foreach my $mod_os (keys %MOD_LIBS)
+ {
+ next if($mod_os =~ /^all!$os$/);
+ next if($mod_os =~ /^all!$os,/);
+ #next if($mod_os =~ /^all!.*,${os}$/);
+ next if($mod_os =~ /^all!.*,$os,.*/);
+ next unless($mod_os eq $os or ($mod_os =~ /^all.*/));
+ my @liblist = split(/,/, $MOD_LIBS{$mod_os});
+ foreach my $lib (@liblist) { $libs{$lib} = 1; }
+ }
+ }
+
+ return sort keys %libs;
+}
+
+sub libs {
+ my ($prefix,$suffix,@libs) = @_;
+ my $output = '';
+ foreach my $lib (@libs) {
+ $output .= ' ' if($output ne '');
+ $output .= $prefix . $lib . $suffix;
+ }
+ return $output;
+}
+
+##################################################
+# Path and file manipulation utilities #
+##################################################
+sub portable_symlink {
+ my ($from, $to_dir, $to_fname) = @_;
+
+ #trace("portable_symlink($from, $to_dir, $to_fname)");
+
+ my $can_symlink = 0;
+ my $can_link = 0;
+
+ unless($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'cygwin') {
+ $can_symlink = eval { symlink("",""); 1 };
+ $can_link = eval { link("",""); 1 };
+ }
+
+ chdir $to_dir or croak("Can't chdir to $to_dir ($!)");
+
+ if($can_symlink) {
+ symlink $from, $to_fname or
+ croak("Can't symlink $from to $to_fname ($!)");
+ }
+ elsif($can_link) {
+ link $from, $to_fname or
+ croak("Can't link $from to $to_fname ($!)");
+ }
+ else {
+ copy ($from, $to_fname) or
+ croak("Can't copy $from to $to_fname ($!)");
+ }
+
+ my $go_up = File::Spec->splitdir($to_dir);
+ for(my $j = 0; $j != $go_up; $j++) # return to where we were
+ {
+ chdir File::Spec->updir();
+ }
+}
+
+sub copy_include_files {
+ my ($config) = @_;
+
+ my $include_dir = $$config{'build_include_botan'};
+
+ trace('Copying to ', $include_dir);
+
+ foreach my $file (dir_list($include_dir)) {
+ my $path = File::Spec->catfile($include_dir, $file);
+ unlink $path or croak("Could not unlink $path ($!)");
+ }
+
+ my $link_up = sub {
+ my ($dir, $file) = @_;
+ my $updir = File::Spec->updir();
+ portable_symlink(File::Spec->catfile($updir, $updir, $updir,
+ $dir, $file),
+ $include_dir, $file);
+ };
+
+ my $files = $$config{'includes'};
+
+ foreach my $file (keys %$files) {
+ &$link_up($$files{$file}, $file);
+ }
+}
+
+sub dir_list {
+ my ($dir) = @_;
+ opendir(DIR, $dir) or croak("Couldn't read directory '$dir' ($!)");
+
+ my @listing = grep { !/#/ and -f File::Spec->catfile($dir, $_) and
+ $_ ne File::Spec->curdir() and
+ $_ ne File::Spec->updir() } readdir DIR;
+
+ closedir DIR;
+ return @listing;
+}
+
+sub mkdirs {
+ my (@dirs) = @_;
+
+ my @created;
+ foreach my $dir (@dirs) {
+ next if( -e $dir and -d $dir ); # skip it if it's already there
+ mkdir($dir, 0777) or
+ croak("Could not create directory $dir ($!)");
+ push @created, $dir;
+ }
+ return @created;
+}
+
+sub slurp_file {
+ my $file = $_[0];
+
+ return '' if(!defined($file) or $file eq '');
+
+ croak("'$file': No such file") unless(-e $file);
+ croak("'$file': Not a regular file") unless(-f $file);
+
+ open FILE, "<$file" or croak("Couldn't read $file ($!)");
+
+ my $output = '';
+ while(<FILE>) { $output .= $_; }
+ close FILE;
+
+ return $output;
+}
+
+sub which
+{
+ my $file = $_[0];
+ my @paths = split(/:/, $ENV{PATH});
+ foreach my $path (@paths)
+ {
+ my $file_path = File::Spec->catfile($path, $file);
+ return $file_path if(-e $file_path and -r $file_path);
+ }
+ return '';
+}
+
+# Return a hash mapping every var in a list to a constant value
+sub map_to {
+ my $var = shift;
+ return map { $_ => $var } @_;
+}
+
+sub in_array {
+ my($target, $array) = @_;
+ return 0 unless defined($array);
+ foreach (@$array) { return 1 if($_ eq $target); }
+ return 0;
+}
+
+sub add_to {
+ my ($to,$from) = @_;
+
+ foreach my $key (keys %$from) {
+ $$to{$key} = $$from{$key};
+ }
+}
+
+##################################################
+# #
+##################################################
+sub find_mp_bits {
+ my(@modules_list) = @_;
+ my $mp_bits = 32; # default, good for most systems
+
+ my $seen_mp_module = undef;
+
+ foreach my $modname (sort keys %{$$config{'modules'}}) {
+ croak("Unknown module $modname") unless defined $MODULES{$modname};
+
+ next if $$config{'modules'}{$modname} < 0;
+
+ my %modinfo = %{ $MODULES{$modname} };
+ if($modinfo{'mp_bits'}) {
+ if(defined($seen_mp_module) and $modinfo{'mp_bits'} != $mp_bits) {
+ croak('Inconsistent mp_bits requests from modules ',
+ $seen_mp_module, ' and ', $modname);
+ }
+
+ $seen_mp_module = $modname;
+ $mp_bits = $modinfo{'mp_bits'};
+ }
+ }
+ return $mp_bits;
+}
+
+##################################################
+# #
+##################################################
+sub realname {
+ my $arg = $_[0];
+
+ return $COMPILER{$arg}{'realname'}
+ if defined $COMPILER{$arg};
+
+ return $OPERATING_SYSTEM{$arg}{'realname'}
+ if defined $OPERATING_SYSTEM{$arg};
+
+ return $CPU{$arg}{'realname'}
+ if defined $CPU{$arg};
+
+ return $arg;
+}
+
+##################################################
+# #
+##################################################
+
+sub load_module {
+ my ($config, $modname) = @_;
+
+ #trace("load_module($modname)");
+
+ croak("Unknown module $modname") unless defined($MODULES{$modname});
+
+ my %module = %{$MODULES{$modname}};
+
+ my $works_on = sub {
+ my ($what, $lst_ref) = @_;
+ my @lst = @{$lst_ref};
+ return 1 if not @lst; # empty list -> no restrictions
+ return 1 if $what eq 'generic'; # trust the user
+ return in_array($what, \@lst);
+ };
+
+ # Check to see if everything is OK WRT system requirements
+ my $os = $$config{'os'};
+
+ croak("Module '$modname' does not run on $os")
+ unless(&$works_on($os, $module{'os'}));
+
+ my $arch = $$config{'arch'};
+ my $sub = $$config{'submodel'};
+
+ croak("Module '$modname' does not run on $arch/$sub")
+ unless(&$works_on($arch, $module{'arch'}) or
+ &$works_on($sub, $module{'arch'}));
+
+ my $cc = $$config{'compiler'};
+
+ croak("Module '$modname' does not work with $cc")
+ unless(&$works_on($cc, $module{'cc'}));
+
+ my $handle_files = sub {
+ my($lst, $func) = @_;
+ return unless defined($lst);
+
+ foreach (sort @$lst) {
+ &$func($module{'moddirs'}, $config, $_);
+ }
+ };
+
+ &$handle_files($module{'ignore'}, \&ignore_file);
+ &$handle_files($module{'add'}, \&add_file);
+ &$handle_files($module{'replace'},
+ sub { ignore_file(@_); add_file(@_); });
+
+ warning($modname, ': ', $module{'note'})
+ if(defined($module{'note'}));
+}
+
+sub load_modules {
+ my ($config) = @_;
+
+ my @mod_names;
+
+ foreach my $mod (sort keys %{$$config{'modules'}}) {
+ next unless($$config{'modules'}{$mod} > 0);
+
+ load_module($config, $mod);
+
+ push @mod_names, $mod;
+ }
+
+ $$config{'mod_list'} = join("\n", @mod_names);
+
+ my $unaligned_ok = 0;
+
+ my $target_os_defines = sub {
+ my @macro_list;
+
+ my $os = $$config{'os'};
+ if($os ne 'generic') {
+ push @macro_list, '#define BOTAN_TARGET_OS_IS_' . uc $os;
+
+ my @features = @{$OPERATING_SYSTEM{$os}{'target_features'}};
+
+ for my $feature (@features) {
+ push @macro_list, '#define BOTAN_TARGET_OS_HAS_' . uc $feature;
+ }
+
+ }
+ return join("\n", @macro_list);
+ };
+
+ $$config{'target_os_defines'} = &$target_os_defines();
+
+ my $target_cpu_defines = sub {
+ my @macro_list;
+
+ my $arch = $$config{'arch'};
+ if($arch ne 'generic') {
+ my %cpu_info = %{$CPU{$arch}};
+ my $endian = $cpu_info{'endian'};
+
+ if(defined($$config{'with_endian'})) {
+ $endian = $$config{'with_endian'};
+ $endian = undef unless($endian eq 'little' ||
+ $endian eq 'big');
+ }
+ elsif(defined($endian)) {
+ autoconfig("Since arch is $arch, assuming $endian endian mode");
+ }
+
+ push @macro_list, "#define BOTAN_TARGET_ARCH_IS_" . (uc $arch);
+
+ my $submodel = $$config{'submodel'};
+ if($arch ne $submodel) {
+ $submodel = uc $submodel;
+ $submodel =~ tr/-/_/;
+ $submodel =~ tr/.//;
+
+ push @macro_list, "#define BOTAN_TARGET_CPU_IS_$submodel";
+ }
+
+ if(defined($endian)) {
+ $endian = uc $endian;
+ push @macro_list,
+ "#define BOTAN_TARGET_CPU_IS_${endian}_ENDIAN";
+
+ # See if the user set --with-unaligned-mem
+ if(defined($$config{'with_unaligned_mem'})) {
+ my $spec = $$config{'with_unaligned_mem'};
+
+ if($spec eq 'yes') {
+ $unaligned_ok = 1;
+ }
+ elsif($spec eq 'no') {
+ $unaligned_ok = 0;
+ }
+ else {
+ warning('Unknown arg to --with-unaligned-mem (' .
+ $spec . ') will ignore');
+ $unaligned_ok = 0;
+ }
+ }
+ # Otherwise, see if the CPU has a default setting
+ elsif(defined($cpu_info{'unaligned'}) and
+ $cpu_info{'unaligned'} eq 'ok')
+ {
+ autoconfig("Since arch is $arch, " .
+ 'assuming unaligned memory access is OK');
+ $unaligned_ok = 1;
+ }
+ }
+ }
+
+ # variable is always set (one or zero)
+ push @macro_list,
+ "#define BOTAN_TARGET_UNALIGNED_LOADSTOR_OK $unaligned_ok";
+ return join("\n", @macro_list);
+ };
+
+ $$config{'target_cpu_defines'} = &$target_cpu_defines();
+
+ my $target_compiler_defines = sub {
+ my @macro_list;
+
+ if(defined($$config{'tr1'})) {
+ my $tr1 = $$config{'tr1'};
+
+ if($tr1 eq 'system') {
+ push @macro_list, '#define BOTAN_USE_STD_TR1';
+ }
+ elsif($tr1 eq 'boost') {
+ push @macro_list, '#define BOTAN_USE_BOOST_TR1';
+ }
+ elsif($tr1 ne 'none') {
+ croak("Unknown --with-tr1= option value '$tr1' (try --help)");
+ }
+ }
+
+ return join("\n", @macro_list);
+ };
+
+ $$config{'target_compiler_defines'} = &$target_compiler_defines();
+
+ my $gen_defines = sub {
+ my @macro_list;
+
+ my %defines;
+
+ foreach my $mod (sort keys %{$$config{'modules'}}) {
+ next unless $$config{'modules'}{$mod} > 0;
+
+ my $defs = $MODULES{$mod}{'define'};
+ next unless $defs;
+
+ push @{$defines{$MODULES{$mod}{'type'}}}, split(/,/, $defs);
+ }
+
+ foreach my $type (sort keys %defines) {
+ push @macro_list, "\n/* $type */";
+
+ for my $macro (@{$defines{$type}}) {
+ die unless(defined $macro and $macro ne '');
+ push @macro_list, "#define BOTAN_HAS_$macro";
+ }
+ }
+
+ return join("\n", @macro_list);
+ };
+
+ $$config{'module_defines'} = &$gen_defines();
+}
+
+##################################################
+# #
+##################################################
+sub file_type {
+ my ($file) = @_;
+
+ return 'sources'
+ if($file =~ /\.cpp$/ or $file =~ /\.c$/ or $file =~ /\.S$/);
+ return 'includes' if($file =~ /\.h$/);
+
+ croak('file_type() - don\'t know what sort of file ', $file, ' is');
+}
+
+sub add_file {
+ my ($mod_dir, $config, $file) = @_;
+
+ check_for_file($config, $file, $mod_dir, $mod_dir);
+
+ my $do_add_file = sub {
+ my ($type) = @_;
+
+ croak("File $file already added from ", $$config{$type}{$file})
+ if(defined($$config{$type}{$file}));
+
+ if($file =~ /(.*):(.*)/) {
+ my @dirs = File::Spec->splitdir($mod_dir);
+
+ $dirs[$#dirs-1] = $1;
+
+ $$config{$type}{$2} = File::Spec->catdir(@dirs);
+ }
+ else {
+ $$config{$type}{$file} = $mod_dir;
+ }
+ };
+
+ &$do_add_file(file_type($file));
+}
+
+sub ignore_file {
+ my ($mod_dir, $config, $file) = @_;
+ check_for_file($config, $file, undef, $mod_dir);
+
+ my $do_ignore_file = sub {
+ my ($type, $ok_if_from) = @_;
+
+ if(defined ($$config{$type}{$file})) {
+
+ croak("$mod_dir - File $file modified from ",
+ $$config{$type}{$file})
+ if($$config{$type}{$file} ne $ok_if_from);
+
+ delete $$config{$type}{$file};
+ }
+ };
+
+ &$do_ignore_file(file_type($file));
+}
+
+sub check_for_file {
+ my ($config, $file, $added_from, $mod_dir) = @_;
+
+ #trace("check_for_file($file, $added_from, $mod_dir)");
+
+ my $full_path = sub {
+ my ($file,$mod_dir) = @_;
+
+ if($file =~ /(.*):(.*)/) {
+ return File::Spec->catfile($mod_dir, '..', $1, $2);
+ } else {
+ return File::Spec->catfile($mod_dir, $file) if(defined($mod_dir));
+
+ my @typeinfo = file_type($config, $file);
+ return File::Spec->catfile($typeinfo[1], $file);
+ }
+ };
+
+ $file = &$full_path($file, $added_from);
+
+ croak("Module $mod_dir requires that file $file exist. This error\n ",
+ 'should never occur; please contact the maintainers with details.')
+ unless(-e $file);
+}
+
+##################################################
+# #
+##################################################
+sub process_template {
+ my ($in, $out, $config) = @_;
+
+ trace("process_template: $in -> $out");
+
+ my $contents = slurp_file($in);
+
+ foreach my $name (keys %$config) {
+ my $val = $$config{$name};
+
+ unless(defined $val) {
+ trace("Undefined variable $name in $in");
+ next;
+ }
+
+ $contents =~ s/\%\{$name\}/$val/g;
+ }
+
+ if($contents =~ /\%\{([a-z_]*)\}/) {
+
+ sub summarize {
+ my ($n, $s) = @_;
+
+ $s =~ s/\n/\\n/; # escape newlines
+
+ return $s if(length($s) <= $n);
+
+ return substr($s, 0, 57) . '...';
+ }
+
+ foreach my $key (sort keys %$config) {
+ print with_diagnostic("debug",
+ "In %config:", $key, " -> ",
+ summarize(60, $$config{$key}));
+ }
+
+ croak("Unbound variable '$1' in $in");
+ }
+
+ open OUT, ">$out" or croak("Couldn't write $out ($!)");
+ print OUT $contents;
+ close OUT;
+}
+
+##################################################
+# #
+##################################################
+sub read_list {
+ my ($line, $reader, $marker, $func) = @_;
+
+ if($line =~ m@^<$marker>$@) {
+ while(1) {
+ $line = &$reader();
+
+ die "EOF while searching for $marker" unless $line;
+ last if($line =~ m@^</$marker>$@);
+ &$func($line);
+ }
+ }
+}
+
+sub list_push {
+ my ($listref) = @_;
+ return sub { push @$listref, $_[0]; }
+}
+
+sub match_any_of {
+ my ($line, $hash, $quoted, @any_of) = @_;
+
+ $quoted = ($quoted eq 'quoted') ? 1 : 0;
+
+ foreach my $what (@any_of) {
+ $$hash{$what} = $1 if(not $quoted and $line =~ /^$what (.*)/);
+ $$hash{$what} = $1 if($quoted and $line =~ /^$what \"(.*)\"/);
+ }
+}
+
+##################################################
+# #
+##################################################
+sub make_reader {
+ my $filename = $_[0];
+
+ croak("make_reader(): Arg was undef") if not defined $filename;
+
+ open FILE, "<$filename" or
+ croak("Couldn't read $filename ($!)");
+
+ return sub {
+ my $line = '';
+ while(1) {
+ my $line = <FILE>;
+ last unless defined($line);
+
+ chomp($line);
+ $line =~ s/#.*//;
+ $line =~ s/^\s*//;
+ $line =~ s/\s*$//;
+ $line =~ s/\s\s*/ /;
+ $line =~ s/\t/ /;
+ return $line if $line ne '';
+ }
+ close FILE;
+ return undef;
+ }
+}
+
+##################################################
+# #
+##################################################
+sub read_info_files {
+ my ($config, $dir, $func) = @_;
+
+ $dir = File::Spec->catdir($$config{'config-dir'}, $dir);
+
+ my %allinfo;
+ foreach my $file (dir_list($dir)) {
+ my $fullpath = File::Spec->catfile($dir, $file);
+
+ $file =~ s/.txt//;
+
+ trace("reading $fullpath");
+ %{$allinfo{$file}} = &$func($file, $fullpath);
+ }
+
+ return %allinfo;
+}
+
+sub read_module_files {
+ my ($config) = @_;
+
+ my %allinfo;
+
+ my @modinfos;
+
+ File::Find::find(
+ { wanted => sub
+ { if(-f $_ && /^info\.txt\z/s) {
+ my $name = $File::Find::name;
+ push @modinfos, $name;
+ }
+ }
+ },
+ $$config{'src-dir'});
+
+ foreach my $modfile (@modinfos) {
+ trace("reading $modfile");
+
+ my ($volume,$dirs,$file) = File::Spec->splitpath($modfile);
+
+ my @dirs = File::Spec->splitdir($dirs);
+ my $moddir = $dirs[$#dirs-1];
+
+ trace("module $moddir in $dirs $modfile");
+
+ %{$allinfo{$moddir}} = get_module_info($dirs, $moddir, $modfile);
+ }
+
+ return %allinfo;
+}
+
+##################################################
+# #
+##################################################
+
+sub get_module_info {
+ my ($dirs, $name, $modfile) = @_;
+ my $reader = make_reader($modfile);
+
+ my %info;
+
+ $info{'name'} = $name;
+ $info{'modinfo'} = $modfile;
+ $info{'moddirs'} = $dirs;
+
+ # Default module settings
+ $info{'load_on'} = 'request'; # default unless specified
+ $info{'uses_tr1'} = 'no';
+ $info{'libs'} = {};
+ $info{'use'} = 'no';
+
+ my @dir_arr = File::Spec->splitdir($dirs);
+ $info{'type'} = $dir_arr[$#dir_arr-2]; # cipher, hash, ...
+ if($info{'type'} eq 'src') { $info{'type'} = $dir_arr[$#dir_arr-1]; }
+
+ while($_ = &$reader()) {
+ match_any_of($_, \%info, 'quoted', 'realname', 'note', 'type');
+ match_any_of($_, \%info, 'unquoted', 'define', 'mp_bits',
+ 'modset', 'load_on', 'uses_tr1');
+
+ read_list($_, $reader, 'arch', list_push(\@{$info{'arch'}}));
+ read_list($_, $reader, 'cc', list_push(\@{$info{'cc'}}));
+ read_list($_, $reader, 'os', list_push(\@{$info{'os'}}));
+ read_list($_, $reader, 'add', list_push(\@{$info{'add'}}));
+ read_list($_, $reader, 'replace', list_push(\@{$info{'replace'}}));
+ read_list($_, $reader, 'ignore', list_push(\@{$info{'ignore'}}));
+ read_list($_, $reader, 'requires', list_push(\@{$info{'requires'}}));
+
+ read_list($_, $reader, 'libs',
+ sub {
+ my $line = $_[0];
+ $line =~ m/^([\w!,]*) -> ([\w.,-]*)$/;
+ $info{'libs'}{$1} = $2;
+ });
+
+ if(/^require_version /) {
+ if(/^require_version (\d+)\.(\d+)\.(\d+)$/) {
+ my $version = "$1.$2.$3";
+ my $needed_version = 100*$1 + 10*$2 + $3;
+
+ my $have_version =
+ 100*$MAJOR_VERSION + 10*$MINOR_VERSION + $PATCH_VERSION;
+
+ if($needed_version > $have_version) {
+ warning("Module $name needs v$version; disabling");
+ return ();
+ }
+ }
+ else {
+ croak("In module $name, bad version requirement '$_'");
+ }
+ }
+ }
+
+ return %info;
+}
+
+##################################################
+# #
+##################################################
+sub get_arch_info {
+ my ($name,$file) = @_;
+ my $reader = make_reader($file);
+
+ my %info;
+ $info{'name'} = $name;
+
+ while($_ = &$reader()) {
+ match_any_of($_, \%info, 'quoted', 'realname');
+ match_any_of($_, \%info, 'unquoted',
+ 'default_submodel', 'endian', 'unaligned');
+
+ read_list($_, $reader, 'aliases', list_push(\@{$info{'aliases'}}));
+ read_list($_, $reader, 'submodels', list_push(\@{$info{'submodels'}}));
+
+ read_list($_, $reader, 'submodel_aliases',
+ sub {
+ my $line = $_[0];
+ $line =~ m/^(\S*) -> (\S*)$/;
+ $info{'submodel_aliases'}{$1} = $2;
+ });
+ }
+ return %info;
+}
+
+##################################################
+# #
+##################################################
+sub get_os_info {
+ my ($name,$file) = @_;
+ my $reader = make_reader($file);
+
+ my %info;
+ $info{'name'} = $name;
+
+ while($_ = &$reader()) {
+ match_any_of($_, \%info,
+ 'quoted', 'realname', 'ar_command',
+ 'install_cmd_data', 'install_cmd_exec');
+
+ match_any_of($_, \%info, 'unquoted',
+ 'os_type',
+ 'obj_suffix',
+ 'so_suffix',
+ 'static_suffix',
+ 'install_root',
+ 'header_dir',
+ 'lib_dir', 'doc_dir',
+ 'ar_needs_ranlib');
+
+ read_list($_, $reader, 'aliases', list_push(\@{$info{'aliases'}}));
+
+ read_list($_, $reader, 'target_features',
+ list_push(\@{$info{'target_features'}}));
+
+ read_list($_, $reader, 'supports_shared',
+ list_push(\@{$info{'supports_shared'}}));
+ }
+ return %info;
+}
+
+##################################################
+# Read a file from misc/config/cc and set the values from
+# there into a hash for later reference
+##################################################
+sub get_cc_info {
+ my ($name,$file) = @_;
+ my $reader = make_reader($file);
+
+ my %info;
+ $info{'name'} = $name;
+
+ while($_ = &$reader()) {
+ match_any_of($_, \%info, 'quoted',
+ 'realname',
+ 'binary_name',
+ 'compile_option',
+ 'output_to_option',
+ 'add_include_dir_option',
+ 'add_lib_dir_option',
+ 'add_lib_option',
+ 'lib_opt_flags',
+ 'check_opt_flags',
+ 'dll_import_flags',
+ 'dll_export_flags',
+ 'lang_flags',
+ 'warning_flags',
+ 'shared_flags',
+ 'ar_command',
+ 'debug_flags',
+ 'no_debug_flags');
+
+ match_any_of($_, \%info, 'unquoted',
+ 'makefile_style',
+ 'compiler_has_tr1');
+
+ sub quoted_mapping {
+ my $hashref = $_[0];
+ return sub {
+ my $line = $_[0];
+ $line =~ m/^(\S*) -> \"(.*)\"$/;
+ $$hashref{$1} = $2;
+ }
+ }
+
+ read_list($_, $reader, 'mach_abi_linking',
+ quoted_mapping(\%{$info{'mach_abi_linking'}}));
+ read_list($_, $reader, 'so_link_flags',
+ quoted_mapping(\%{$info{'so_link_flags'}}));
+
+ read_list($_, $reader, 'mach_opt',
+ sub {
+ my $line = $_[0];
+ $line =~ m/^(\S*) -> \"(.*)\" ?(.*)?$/;
+ $info{'mach_opt_flags'}{$1} = $2;
+ $info{'mach_opt_re'}{$1} = $3;
+ });
+
+ }
+ return %info;
+}
+
+##################################################
+# #
+##################################################
+sub write_pkg_config {
+ my ($config) = @_;
+
+ return if($$config{'os'} eq 'generic' or
+ $$config{'os'} eq 'windows');
+
+ $$config{'link_to'} = libs('-l', '', 'm', @{$$config{'mod_libs'}});
+
+ my $botan_config = $$config{'botan_config'};
+
+ process_template(
+ File::Spec->catfile($$config{'config-dir'}, 'botan-config.in'),
+ $botan_config, $config);
+ chmod 0755, $botan_config;
+
+ process_template(
+ File::Spec->catfile($$config{'config-dir'}, 'botan.pc.in'),
+ $$config{'botan_pkgconfig'}, $config);
+
+ delete $$config{'link_to'};
+}
+
+##################################################
+# #
+##################################################
+sub file_list {
+ my ($put_in, $from, $to, %files) = @_;
+
+ my $list = '';
+
+ my $spaces = 16;
+
+ foreach (sort keys %files) {
+ my $file = $_;
+
+ $file =~ s/$from/$to/ if(defined($from) and defined($to));
+
+ my $dir = $files{$_};
+ $dir = $put_in if defined $put_in;
+
+ if(defined($dir)) {
+ $list .= File::Spec->catfile ($dir, $file);
+ }
+ else {
+ $list .= $file;
+ }
+
+ $list .= " \\\n ";
+ }
+
+ $list =~ s/\\\n +$//; # remove trailing escape
+
+ return $list;
+}
+
+sub build_cmds {
+ my ($config, $dir, $flags, $files) = @_;
+
+ my $obj_suffix = $$config{'obj_suffix'};
+
+ my %ccinfo = my_compiler($config);
+
+ my $inc = $ccinfo{'add_include_dir_option'};
+ my $from = $ccinfo{'compile_option'};
+ my $to = $ccinfo{'output_to_option'};
+
+ my $inc_dir = $$config{'build_include'};
+
+ # Probably replace by defaults to -I -c -o
+ croak('undef value found in build_cmds')
+ unless defined($inc) and defined($from) and defined($to);
+
+ my $bld_line = "\t\$(CXX) $inc$inc_dir $flags $from\$? $to\$@";
+
+ my @output_lines;
+
+ foreach (sort keys %$files) {
+ my $src_file = File::Spec->catfile($$files{$_}, $_);
+ my $obj_file = File::Spec->catfile($dir, $_);
+
+ $obj_file =~ s/\.cpp$/.$obj_suffix/;
+ $obj_file =~ s/\.c$/.$obj_suffix/;
+ $obj_file =~ s/\.S$/.$obj_suffix/;
+
+ push @output_lines, "$obj_file: $src_file\n$bld_line";
+ }
+
+ return join("\n\n", @output_lines);
+}
+
+sub determine_config {
+ my ($config) = @_;
+
+ sub os_ar_command {
+ return os_info_for(shift, 'ar_command');
+ }
+
+ sub append_if {
+ my($var,$addme,$cond) = @_;
+
+ croak('append_if: reference was undef') unless defined $var;
+
+ if($cond and $addme ne '') {
+ $$var .= ' ' unless($$var eq '' or $$var =~ / $/);
+ $$var .= $addme;
+ }
+ }
+
+ sub append_ifdef {
+ my($var,$addme) = @_;
+ append_if($var, $addme, defined($addme));
+ }
+
+ my $empty_if_nil = sub {
+ my $val = $_[0];
+ return $val if defined($val);
+ return '';
+ };
+
+ my %ccinfo = my_compiler($config);
+
+ my $lang_flags = '';
+ append_ifdef(\$lang_flags, $ccinfo{'lang_flags'});
+ append_if(\$lang_flags, "-fpermissive", $$config{'gcc_bug'});
+
+ my $debug = $$config{'debug'};
+
+ my $lib_opt_flags = '';
+ append_ifdef(\$lib_opt_flags, $ccinfo{'lib_opt_flags'});
+ append_ifdef(\$lib_opt_flags, $ccinfo{'debug_flags'}) if($debug);
+ append_ifdef(\$lib_opt_flags, $ccinfo{'no_debug_flags'}) if(!$debug);
+
+ # This is a default that works on most Unix and Unix-like systems
+ my $ar_command = 'ar crs';
+ my $ranlib_command = 'true'; # almost no systems need it anymore
+
+ # See if there are any over-riding methods. We presume if CC is creating
+ # the static libs, it knows how to create the index itself.
+
+ my $os = $$config{'os'};
+
+ if($ccinfo{'ar_command'}) {
+ $ar_command = $ccinfo{'ar_command'};
+ }
+ elsif(os_ar_command($os))
+ {
+ $ar_command = os_ar_command($os);
+ $ranlib_command = 'ranlib'
+ if(os_info_for($os, 'ar_needs_ranlib') eq 'yes');
+ }
+
+ my $arch = $$config{'arch'};
+
+ my $abi_opts = '';
+ append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{$arch});
+ append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{$os});
+ append_ifdef(\$abi_opts, $ccinfo{'mach_abi_linking'}{'all'});
+ $abi_opts = ' ' . $abi_opts if($abi_opts ne '');
+
+ if($$config{'shared'} eq 'yes' and
+ (in_array('all', $OPERATING_SYSTEM{$os}{'supports_shared'}) or
+ in_array($$config{'compiler'},
+ $OPERATING_SYSTEM{$os}{'supports_shared'}))) {
+
+ $$config{'shared_flags'} = &$empty_if_nil($ccinfo{'shared_flags'});
+ $$config{'so_link'} = &$empty_if_nil($ccinfo{'so_link_flags'}{$os});
+
+ if($$config{'so_link'} eq '') {
+ $$config{'so_link'} =
+ &$empty_if_nil($ccinfo{'so_link_flags'}{'default'})
+ }
+
+ if($$config{'shared_flags'} eq '' and $$config{'so_link'} eq '') {
+ $$config{'shared'} = 'no';
+
+ warning($$config{'compiler'}, ' has no shared object flags set ',
+ "for $os; disabling shared");
+ }
+ }
+ else {
+ autoconfig("No shared library generated with " .
+ $$config{'compiler'} . " on " . $$config{'os'});
+
+ $$config{'shared'} = 'no';
+ $$config{'shared_flags'} = '';
+ $$config{'so_link'} = '';
+ }
+
+ add_to($config, {
+ 'cc' => $ccinfo{'binary_name'} . $abi_opts,
+ 'lib_opt' => $lib_opt_flags,
+ 'check_opt' => &$empty_if_nil($ccinfo{'check_opt_flags'}),
+ 'mach_opt' => mach_opt($config),
+ 'lang_flags' => $lang_flags,
+ 'warn_flags' => &$empty_if_nil($ccinfo{'warning_flags'}),
+
+ 'ar_command' => $ar_command,
+ 'ranlib_command' => $ranlib_command,
+ 'static_suffix' => os_info_for($os, 'static_suffix'),
+ 'so_suffix' => os_info_for($os, 'so_suffix'),
+ 'obj_suffix' => os_info_for($os, 'obj_suffix'),
+
+ 'dll_export_flags' => $ccinfo{'dll_export_flags'},
+ 'dll_import_flags' => $ccinfo{'dll_import_flags'},
+
+ 'install_cmd_exec' => os_info_for($os, 'install_cmd_exec'),
+ 'install_cmd_data' => os_info_for($os, 'install_cmd_data'),
+ });
+}
+
+sub generate_makefile {
+ my ($config) = @_;
+
+ my $is_in_doc_dir =
+ sub { -e File::Spec->catfile($$config{'doc_src_dir'}, $_[0]) };
+
+ my $docs = file_list(undef, undef, undef,
+ map_to($$config{'doc_src_dir'},
+ grep { &$is_in_doc_dir($_); } @DOCS));
+
+ $docs .= File::Spec->catfile($$config{'base-dir'}, 'readme.txt');
+
+ my $includes = file_list(undef, undef, undef,
+ map_to($$config{'build_include_botan'},
+ keys %{$$config{'includes'}}));
+
+ my $lib_objs = file_list($$config{'build_lib'}, '(\.cpp$|\.c$|\.S$)',
+ '.' . $$config{'obj_suffix'},
+ %{$$config{'sources'}});
+
+ my $check_objs = file_list($$config{'build_check'}, '.cpp',
+ '.' . $$config{'obj_suffix'},
+ %{$$config{'check_src'}}),
+
+ my $lib_build_cmds = build_cmds($config, $$config{'build_lib'},
+ '$(LIB_FLAGS)', $$config{'sources'});
+
+ my $check_build_cmds = build_cmds($config, $$config{'build_check'},
+ '$(CHECK_FLAGS)', $$config{'check_src'});
+
+ add_to($config, {
+ 'lib_objs' => $lib_objs,
+ 'check_objs' => $check_objs,
+ 'lib_build_cmds' => $lib_build_cmds,
+ 'check_build_cmds' => $check_build_cmds,
+
+ 'doc_files' => $docs,
+ 'include_files' => $includes
+ });
+
+ my $template_dir = File::Spec->catdir($$config{'config-dir'}, 'makefile');
+ my $template = undef;
+
+ my $make_style = $$config{'make_style'};
+
+ if($make_style eq 'unix') {
+ $template = File::Spec->catfile($template_dir, 'unix.in');
+
+ $template = File::Spec->catfile($template_dir, 'unix_shr.in')
+ if($$config{'shared'} eq 'yes');
+
+ add_to($config, {
+ 'link_to' => libs('-l', '', 'm', @{$$config{'mod_libs'}}),
+ });
+ }
+ elsif($make_style eq 'nmake') {
+ $template = File::Spec->catfile($template_dir, 'nmake.in');
+
+ add_to($config, {
+ 'shared' => 'no',
+ 'link_to' => libs('', '', '', @{$$config{'mod_libs'}}),
+ });
+ }
+
+ croak("Don't know about makefile format '$make_style'")
+ unless defined $template;
+
+ trace("'$make_style' -> '$template'");
+
+ process_template($template, $$config{'makefile'}, $config);
+
+ autoconfig("Wrote ${make_style}-style makefile in $$config{'makefile'}");
+}
+
+##################################################
+# Configuration Guessing #
+##################################################
+sub guess_cpu_from_this
+{
+ my $cpuinfo = lc $_[0];
+
+ $cpuinfo =~ s/\(r\)//g;
+ $cpuinfo =~ s/\(tm\)//g;
+ $cpuinfo =~ s/ //g;
+
+ trace("guess_cpu_from_this($cpuinfo)");
+
+ # The 32-bit SPARC stuff is impossible to match to arch type easily, and
+ # anyway the uname stuff will pick up that it's a SPARC so it doesn't
+ # matter. If it's an Ultra, assume a 32-bit userspace, no 64-bit code
+ # possible; that's the most common setup right now anyway
+ return 'sparc32-v9' if($cpuinfo =~ /ultrasparc/);
+
+ # Should probably do this once and cache it
+ my @names;
+ my %all_alias;
+
+ foreach my $arch (keys %CPU) {
+ my %info = %{$CPU{$arch}};
+
+ foreach my $submodel (@{$info{'submodels'}}) {
+ push @names, $submodel;
+ }
+
+ if(defined($info{'submodel_aliases'})) {
+ my %submodel_aliases = %{$info{'submodel_aliases'}};
+ foreach my $sm_alias (keys %submodel_aliases) {
+ push @names, $sm_alias;
+ $all_alias{$sm_alias} = $submodel_aliases{$sm_alias};
+ }
+ }
+ }
+
+ @names = sort { length($b) <=> length($a) } @names;
+
+ foreach my $name (@names) {
+ if($cpuinfo =~ $name) {
+ trace("Matched '$cpuinfo' against '$name'");
+
+ return $all_alias{$name} if defined($all_alias{$name});
+
+ return $name;
+ }
+ }
+
+ trace("Couldn't match $cpuinfo against any submodels");
+
+ # No match? Try arch names. Reset @names
+ @names = ();
+
+ foreach my $arch (keys %CPU) {
+ my %info = %{$CPU{$arch}};
+
+ push @names, $info{'name'};
+
+ foreach my $alias (@{$info{'aliases'}}) {
+ push @names, $alias;
+ }
+ }
+
+ @names = sort { length($b) <=> length($a) } @names;
+
+ foreach my $name (@names) {
+ if($cpuinfo =~ $name) {
+ trace("Matched '$cpuinfo' against '$name'");
+ return $name;
+ }
+ }
+
+ return '';
+}
+
+# Do some WAGing and see if we can figure out what system we are. Think about
+# this as a really moronic config.guess
+sub guess_compiler
+{
+ my @CCS = ('gcc', 'msvc', 'icc', 'compaq', 'kai');
+
+ # First try the CC enviornmental variable, if it's set
+ if(defined($ENV{CC}))
+ {
+ my @new_CCS = ($ENV{CC});
+ foreach my $cc (@CCS) { push @new_CCS, $cc; }
+ @CCS = @new_CCS;
+ }
+
+ foreach (@CCS)
+ {
+ my $bin_name = $COMPILER{$_}{'binary_name'};
+ if(which($bin_name) ne '') {
+ autoconfig("Guessing to use $_ as the compiler " .
+ "(use --cc to set)");
+ return $_;
+ }
+ }
+
+ croak(
+ "Can't find a usable C++ compiler, is PATH right?\n" .
+ "You might need to run with the --cc option (try $0 --help)\n");
+}
+
+sub guess_os
+{
+ sub recognize_os
+ {
+ my $os = os_alias($_[0]);
+ if(defined($OPERATING_SYSTEM{$os})) {
+ autoconfig("Guessing operating system is $os (use --os to set)");
+ return $os;
+ }
+ return undef;
+ }
+
+ my $guess = recognize_os($^O);
+ return $guess if $guess;
+
+ trace("Can't guess os from $^O");
+
+ my $uname = $$config{'uname'};
+
+ if($uname ne '') {
+ $guess = recognize_os($uname);
+ return $guess if $guess;
+ trace("Can't guess os from $uname");
+ }
+
+ warning("Unknown OS ('$^O', '$uname'), falling back to generic code");
+ return 'generic';
+}
+
+sub guess_cpu
+{
+ # If we have /proc/cpuinfo, try to get nice specific information about
+ # what kind of CPU we're running on.
+ my $cpuinfo = '/proc/cpuinfo';
+
+ if(defined($ENV{'CPUINFO'})) {
+ my $cpuinfo_env = $ENV{'CPUINFO'};
+
+ if(-e $cpuinfo_env and -r $cpuinfo_env) {
+ autoconfig("Will use $cpuinfo_env as /proc/cpuinfo");
+ $cpuinfo = $cpuinfo_env;
+ } else {
+ warn("Could not read from ENV /proc/cpuinfo ($cpuinfo_env)");
+ }
+ }
+
+ if(-e $cpuinfo and -r $cpuinfo)
+ {
+ open CPUINFO, $cpuinfo or die "Could not read $cpuinfo\n";
+
+ while(<CPUINFO>) {
+
+ chomp;
+ $_ =~ s/\t/ /g;
+ $_ =~ s/ +/ /g;
+
+ if($_ =~ /^cpu +: (.*)/ or
+ $_ =~ /^model name +: (.*)/)
+ {
+ my $cpu = guess_cpu_from_this($1);
+ if($cpu ne '') {
+ autoconfig("Guessing CPU using $cpuinfo line '$_'");
+ autoconfig("Guessing CPU is a $cpu (use --cpu to set)");
+ return $cpu;
+ }
+ }
+ }
+
+ autoconfig("*** Could not figure out CPU based on $cpuinfo");
+ autoconfig("*** Please mail contents to lloyd\@randombit.net");
+ }
+
+ sub known_arch {
+ my ($name) = @_;
+
+ foreach my $arch (keys %CPU) {
+ my %info = %{$CPU{$arch}};
+
+ return 1 if $name eq $info{'name'};
+ foreach my $submodel (@{$info{'submodels'}}) {
+ return 1 if $name eq $submodel;
+ }
+
+ foreach my $alias (@{$info{'aliases'}}) {
+ return 1 if $name eq $alias;
+ }
+
+ if(defined($info{'submodel_aliases'})) {
+ my %submodel_aliases = %{$info{'submodel_aliases'}};
+ foreach my $sm_alias (keys %submodel_aliases) {
+ return 1 if $name eq $sm_alias;
+ }
+ }
+ }
+
+ my $guess = guess_cpu_from_this($name);
+
+ return 0 if($guess eq $name or $guess eq '');
+
+ return known_arch($guess);
+ }
+
+ my $uname = $$config{'uname'};
+ if($uname ne '') {
+ my $cpu = guess_cpu_from_this($uname);
+
+ if($cpu ne '')
+ {
+ autoconfig("Guessing CPU using uname output '$uname'");
+ autoconfig("Guessing CPU is a $cpu (use --cpu to set)");
+
+ return $cpu if known_arch($cpu);
+ }
+ }
+
+ my $config_archname = $Config{'archname'};
+ my $cpu = guess_cpu_from_this($config_archname);
+
+ if($cpu ne '')
+ {
+ autoconfig("Guessing CPU using Config{archname} '$config_archname'");
+ autoconfig("Guessing CPU is a $cpu (use --cpu to set)");
+
+ return $cpu if known_arch($cpu);
+ }
+
+ warning("Could not determine CPU type (try --cpu option)");
+ return 'generic';
+}
diff --git a/botan/configure.py b/botan/configure.py
new file mode 100644
index 0000000..7f597a8
--- /dev/null
+++ b/botan/configure.py
@@ -0,0 +1,1122 @@
+#!/usr/bin/env python
+
+"""
+Configuration program for botan (http://botan.randombit.net/)
+ (C) 2009 Jack Lloyd
+ Distributed under the terms of the Botan license
+
+Tested with
+ CPython 2.4, 2.5, 2.6 - OK
+ Jython 2.5 - Target detection does not work (use --os and --cpu)
+
+ CPython 2.3 and earlier are not supported
+
+ Has not been tested with IronPython or PyPy
+"""
+
+import sys
+import os
+import os.path
+import platform
+import re
+import shlex
+import shutil
+import string
+import subprocess
+import logging
+import getpass
+import time
+
+from optparse import (OptionParser, OptionGroup,
+ IndentedHelpFormatter, SUPPRESS_HELP)
+
+class BuildConfigurationInformation(object):
+
+ """
+ Version information
+ """
+ version_major = 1
+ version_minor = 8
+ version_patch = 8
+ version_so_patch = 2
+ version_suffix = ''
+
+ version_string = '%d.%d.%d%s' % (
+ version_major, version_minor, version_patch, version_suffix)
+ soversion_string = '%d.%d.%d%s' % (
+ version_major, version_minor, version_so_patch, version_suffix)
+
+ """
+ Constructor
+ """
+ def __init__(self, options, modules):
+ self.build_dir = os.path.join(options.with_build_dir, 'build')
+
+ self.checkobj_dir = os.path.join(self.build_dir, 'checks')
+ self.libobj_dir = os.path.join(self.build_dir, 'lib')
+
+ self.include_dir = os.path.join(self.build_dir, 'include')
+ self.full_include_dir = os.path.join(self.include_dir, 'botan')
+
+ all_files = sum([mod.add for mod in modules], [])
+
+ self.headers = sorted(
+ [file for file in all_files if file.endswith('.h')])
+
+ self.sources = sorted(set(all_files) - set(self.headers))
+
+ checks_dir = os.path.join(options.base_dir, 'checks')
+
+ self.check_sources = sorted(
+ [os.path.join(checks_dir, file) for file in os.listdir(checks_dir)
+ if file.endswith('.cpp')])
+
+ def doc_files(self):
+ docs = ['readme.txt']
+
+ for docfile in ['api.pdf', 'tutorial.pdf', 'fips140.pdf',
+ 'api.tex', 'tutorial.tex', 'fips140.tex',
+ 'credits.txt', 'license.txt', 'log.txt',
+ 'thanks.txt', 'todo.txt', 'pgpkeys.asc']:
+ filename = os.path.join('doc', docfile)
+ if os.access(filename, os.R_OK):
+ docs.append(filename)
+ return docs
+
+ def pkg_config_file(self):
+ return 'botan-%d.%d.pc' % (self.version_major,
+ self.version_minor)
+
+ def username(self):
+ return getpass.getuser()
+
+ def hostname(self):
+ return platform.node()
+
+ def timestamp(self):
+ return time.ctime()
+
+"""
+Handle command line options
+"""
+def process_command_line(args):
+ parser = OptionParser(
+ formatter = IndentedHelpFormatter(max_help_position = 50),
+ version = BuildConfigurationInformation.version_string)
+
+ target_group = OptionGroup(parser, 'Target options')
+
+ target_group.add_option('--cc', dest='compiler',
+ help='set the desired build compiler')
+ target_group.add_option('--os', default=platform.system().lower(),
+ help='set the target operating system [%default]')
+ target_group.add_option('--cpu',
+ help='set the target processor type/model')
+ target_group.add_option('--with-endian', metavar='ORDER', default=None,
+ help='override guess of CPU byte order')
+
+ build_group = OptionGroup(parser, 'Build options')
+
+ build_group.add_option('--enable-shared', dest='build_shared_lib',
+ action='store_true', default=True,
+ help=SUPPRESS_HELP)
+ build_group.add_option('--disable-shared', dest='build_shared_lib',
+ action='store_false',
+ help='disable building a shared library')
+
+ build_group.add_option('--enable-asm', dest='asm_ok',
+ action='store_true', default=True,
+ help=SUPPRESS_HELP)
+ build_group.add_option('--disable-asm', dest='asm_ok',
+ action='store_false',
+ help='disallow use of assembler')
+
+ build_group.add_option('--enable-debug', dest='debug_build',
+ action='store_true', default=False,
+ help='enable debug build')
+ build_group.add_option('--disable-debug', dest='debug_build',
+ action='store_false', help=SUPPRESS_HELP)
+
+ build_group.add_option('--with-tr1-implementation', metavar='WHICH',
+ dest='with_tr1', default=None,
+ help='enable TR1 (options: none, system, boost)')
+
+ build_group.add_option('--with-build-dir',
+ metavar='DIR', default='',
+ help='setup the build in DIR')
+
+ build_group.add_option('--makefile-style', metavar='STYLE', default=None,
+ help='choose a makefile style (unix, nmake)')
+
+ build_group.add_option('--with-local-config',
+ dest='local_config', metavar='FILE',
+ help='include the contents of FILE into build.h')
+
+ build_group.add_option('--dumb-gcc', dest='dumb_gcc',
+ action='store_true', default=False,
+ help=SUPPRESS_HELP)
+
+ mods_group = OptionGroup(parser, 'Module selection')
+
+ mods_group.add_option('--enable-modules', dest='enabled_modules',
+ metavar='MODS', action='append', default=[],
+ help='enable specific modules')
+ mods_group.add_option('--disable-modules', dest='disabled_modules',
+ metavar='MODS', action='append', default=[],
+ help='disable specific modules')
+ mods_group.add_option('--no-autoload', action='store_true', default=False,
+ help='disable automatic loading')
+
+ for mod in ['openssl', 'gnump', 'bzip2', 'zlib']:
+
+ # This is just an implementation of Optik's append_const action,
+ # but that is not available in Python 2.4's optparse, so use a
+ # callback instead
+
+ def optparse_callback(option, opt, value, parser, dest, mod):
+ parser.values.__dict__[dest].append(mod)
+
+ mods_group.add_option('--with-%s' % (mod),
+ action='callback',
+ callback=optparse_callback,
+ callback_kwargs = {
+ 'dest': 'enabled_modules', 'mod': mod }
+ )
+
+ mods_group.add_option('--without-%s' % (mod), help=SUPPRESS_HELP,
+ action='callback',
+ callback=optparse_callback,
+ callback_kwargs = {
+ 'dest': 'disabled_modules', 'mod': mod }
+ )
+
+ install_group = OptionGroup(parser, 'Installation options')
+
+ install_group.add_option('--prefix', metavar='DIR',
+ help='set the base install directory')
+ install_group.add_option('--docdir', metavar='DIR',
+ help='set the documentation install directory')
+ install_group.add_option('--libdir', metavar='DIR',
+ help='set the library install directory')
+ install_group.add_option('--includedir', metavar='DIR',
+ help='set the include file install directory')
+
+ parser.add_option_group(target_group)
+ parser.add_option_group(build_group)
+ parser.add_option_group(mods_group)
+ parser.add_option_group(install_group)
+
+ # These exist only for autoconf compatability (requested by zw for mtn)
+ compat_with_autoconf_options = [
+ 'bindir',
+ 'datadir',
+ 'datarootdir',
+ 'dvidir',
+ 'exec-prefix',
+ 'htmldir',
+ 'infodir',
+ 'libexecdir',
+ 'localedir',
+ 'localstatedir',
+ 'mandir',
+ 'oldincludedir',
+ 'pdfdir',
+ 'psdir',
+ 'sbindir',
+ 'sharedstatedir',
+ 'sysconfdir'
+ ]
+
+ for opt in compat_with_autoconf_options:
+ parser.add_option('--' + opt, help=SUPPRESS_HELP)
+
+ (options, args) = parser.parse_args(args)
+
+ if args != []:
+ raise Exception('Unhandled option(s): ' + ' '.join(args))
+ if options.with_endian != None and \
+ options.with_endian not in ['little', 'big']:
+ raise Exception('Bad value to --with-endian "%s"' % (
+ options.with_endian))
+
+ def parse_module_opts(modules):
+ return sorted(set(sum([s.split(',') for s in modules], [])))
+
+ options.enabled_modules = parse_module_opts(options.enabled_modules)
+ options.disabled_modules = parse_module_opts(options.disabled_modules)
+
+ return options
+
+"""
+Generic lexer function for info.txt and src/build-data files
+"""
+def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs):
+
+ class LexerError(Exception):
+ def __init__(self, msg, line):
+ self.msg = msg
+ self.line = line
+
+ def __str__(self):
+ return '%s at %s:%d' % (self.msg, infofile, self.line)
+
+ (dirname, basename) = os.path.split(infofile)
+
+ to_obj.lives_in = dirname
+ if basename == 'info.txt':
+ (obj_dir,to_obj.basename) = os.path.split(dirname)
+ if os.access(os.path.join(obj_dir, 'info.txt'), os.R_OK):
+ to_obj.parent_module = os.path.basename(obj_dir)
+ else:
+ to_obj.parent_module = None
+ else:
+ to_obj.basename = basename.replace('.txt', '')
+
+ lexer = shlex.shlex(open(infofile), infofile, posix=True)
+ lexer.wordchars += '|:.<>/,-!' # handle various funky chars in info.txt
+
+ for group in allowed_groups:
+ to_obj.__dict__[group] = []
+ for (key,val) in name_val_pairs.iteritems():
+ to_obj.__dict__[key] = val
+
+ def lexed_tokens(): # Convert to an interator
+ token = lexer.get_token()
+ while token != None:
+ yield token
+ token = lexer.get_token()
+
+ for token in lexed_tokens():
+ match = re.match('<(.*)>', token)
+
+ # Check for a grouping
+ if match is not None:
+ group = match.group(1)
+
+ if group not in allowed_groups:
+ raise LexerError('Unknown group "%s"' % (group),
+ lexer.lineno)
+
+ end_marker = '</' + group + '>'
+
+ token = lexer.get_token()
+ while token != end_marker:
+ to_obj.__dict__[group].append(token)
+ token = lexer.get_token()
+ if token is None:
+ raise LexerError('Group "%s" not terminated' % (group),
+ lexer.lineno)
+
+ elif token in name_val_pairs.keys():
+ to_obj.__dict__[token] = lexer.get_token()
+ else: # No match -> error
+ raise LexerError('Bad token "%s"' % (token), lexer.lineno)
+
+"""
+Convert a lex'ed map (from build-data files) from a list to a dict
+"""
+def force_to_dict(l):
+ return dict(zip(l[::3],l[2::3]))
+
+"""
+Represents the information about a particular module
+"""
+class ModuleInfo(object):
+ def __init__(self, infofile):
+
+ lex_me_harder(infofile, self,
+ ['add', 'requires', 'os', 'arch', 'cc', 'libs'],
+ { 'realname': '<UNKNOWN>',
+ 'load_on': 'request',
+ 'define': None,
+ 'modset': None,
+ 'uses_tr1': 'false',
+ 'note': '',
+ 'mp_bits': 0 })
+
+ # Coerce to more useful types
+ self.libs = force_to_dict(self.libs)
+
+ def add_dir_name(filename):
+ if filename.count(':') == 0:
+ return os.path.join(self.lives_in, filename)
+
+ # modules can request to add files of the form
+ # MODULE_NAME:FILE_NAME to add a file from another module
+ # For these, assume other module is always in a
+ # neighboring directory; this is true for all current uses
+ return os.path.join(os.path.split(self.lives_in)[0],
+ *filename.split(':'))
+
+ self.add = map(add_dir_name, self.add)
+
+ self.mp_bits = int(self.mp_bits)
+
+ if self.uses_tr1 == 'yes':
+ self.uses_tr1 = True
+ else:
+ self.uses_tr1 = False
+
+ def compatible_cpu(self, arch, cpu):
+ return self.arch == [] or (arch in self.arch or cpu in self.arch)
+
+ def compatible_os(self, os):
+ return self.os == [] or os in self.os
+
+ def compatible_compiler(self, cc, with_tr1):
+ if self.uses_tr1 and with_tr1 not in ['boost', 'system']:
+ return False
+ return self.cc == [] or cc in self.cc
+
+ def dependencies(self):
+ # utils is an implicit dep (contains types, etc)
+ deps = self.requires + ['utils']
+ if self.parent_module != None:
+ deps.append(self.parent_module)
+ return deps
+
+ def __cmp__(self, other):
+ if self.basename < other.basename:
+ return -1
+ if self.basename == other.basename:
+ return 0
+ return 1
+
+class ArchInfo(object):
+ def __init__(self, infofile):
+ lex_me_harder(infofile, self,
+ ['aliases', 'submodels', 'submodel_aliases'],
+ { 'realname': '<UNKNOWN>',
+ 'default_submodel': None,
+ 'endian': None,
+ 'unaligned': 'no'
+ })
+
+ self.submodel_aliases = force_to_dict(self.submodel_aliases)
+
+ if self.unaligned == 'ok':
+ self.unaligned_ok = 1
+ else:
+ self.unaligned_ok = 0
+
+ def all_submodels(self):
+ return sorted(zip(self.submodels, self.submodels) +
+ self.submodel_aliases.items(),
+ key = lambda k: len(k[0]), reverse = True)
+
+ def defines(self, target_submodel, with_endian):
+ macros = ['TARGET_ARCH_IS_%s' % (self.basename.upper())]
+
+ def form_cpu_macro(cpu_name):
+ return cpu_name.upper().replace('.', '').replace('-', '_')
+
+ if self.basename != target_submodel:
+ macros.append('TARGET_CPU_IS_%s' % (
+ form_cpu_macro(target_submodel)))
+
+ if with_endian:
+ macros.append('TARGET_CPU_IS_%s_ENDIAN' % (with_endian.upper()))
+ elif self.endian != None:
+ macros.append('TARGET_CPU_IS_%s_ENDIAN' % (self.endian.upper()))
+
+ macros.append('TARGET_UNALIGNED_LOADSTOR_OK %d' % (self.unaligned_ok))
+
+ return macros
+
+class CompilerInfo(object):
+ def __init__(self, infofile):
+ lex_me_harder(infofile, self,
+ ['so_link_flags', 'mach_opt', 'mach_abi_linking'],
+ { 'realname': '<UNKNOWN>',
+ 'binary_name': None,
+ 'compile_option': '-c ',
+ 'output_to_option': '-o ',
+ 'add_include_dir_option': '-I',
+ 'add_lib_dir_option': '-L',
+ 'add_lib_option': '-l',
+ 'lib_opt_flags': '',
+ 'check_opt_flags': '',
+ 'debug_flags': '',
+ 'no_debug_flags': '',
+ 'shared_flags': '',
+ 'lang_flags': '',
+ 'warning_flags': '',
+ 'dll_import_flags': '',
+ 'dll_export_flags': '',
+ 'ar_command': None,
+ 'makefile_style': '',
+ 'compiler_has_tr1': False,
+ })
+
+ self.so_link_flags = force_to_dict(self.so_link_flags)
+ self.mach_abi_linking = force_to_dict(self.mach_abi_linking)
+
+ self.mach_opt_flags = {}
+
+ while self.mach_opt != []:
+ proc = self.mach_opt.pop(0)
+ if self.mach_opt.pop(0) != '->':
+ raise Exception('Parsing err in %s mach_opt' % (self.basename))
+
+ flags = self.mach_opt.pop(0)
+ regex = ''
+
+ if len(self.mach_opt) > 0 and \
+ (len(self.mach_opt) == 1 or self.mach_opt[1] != '->'):
+ regex = self.mach_opt.pop(0)
+
+ self.mach_opt_flags[proc] = (flags,regex)
+
+ del self.mach_opt
+
+ def mach_abi_link_flags(self, osname, arch, submodel):
+
+ abi_link = set()
+ for what in ['all', osname, arch, submodel]:
+ if self.mach_abi_linking.get(what) != None:
+ abi_link.add(self.mach_abi_linking.get(what))
+
+ if len(abi_link) == 0:
+ return ''
+ return ' ' + ' '.join(abi_link)
+
+ def mach_opts(self, arch, submodel):
+
+ def submodel_fixup(tup):
+ return tup[0].replace('SUBMODEL', submodel.replace(tup[1], ''))
+
+ if submodel == arch:
+ return ''
+
+ if submodel in self.mach_opt_flags:
+ return submodel_fixup(self.mach_opt_flags[submodel])
+ if arch in self.mach_opt_flags:
+ return submodel_fixup(self.mach_opt_flags[arch])
+
+ return ''
+
+ def so_link_command_for(self, osname):
+ if osname in self.so_link_flags:
+ return self.so_link_flags[osname]
+ return self.so_link_flags['default']
+
+ def defines(self, with_tr1):
+ if with_tr1:
+ if with_tr1 == 'boost':
+ return ['USE_BOOST_TR1']
+ elif with_tr1 == 'system':
+ return ['USE_STD_TR1']
+ elif self.compiler_has_tr1:
+ return ['USE_STD_TR1']
+
+ return []
+
+class OsInfo(object):
+ def __init__(self, infofile):
+ lex_me_harder(infofile, self,
+ ['aliases', 'target_features', 'supports_shared'],
+ { 'realname': '<UNKNOWN>',
+ 'os_type': None,
+ 'obj_suffix': 'o',
+ 'so_suffix': 'so',
+ 'static_suffix': 'a',
+ 'ar_command': 'ar crs',
+ 'ar_needs_ranlib': False,
+ 'install_root': '/usr/local',
+ 'header_dir': 'include',
+ 'lib_dir': 'lib',
+ 'doc_dir': 'share/doc',
+ 'install_cmd_data': 'install -m 644',
+ 'install_cmd_exec': 'install -m 755'
+ })
+
+ self.ar_needs_ranlib = bool(self.ar_needs_ranlib)
+
+ def ranlib_command(self):
+ if self.ar_needs_ranlib:
+ return 'ranlib'
+ else:
+ return 'true' # no-op
+
+ def defines(self):
+ return ['TARGET_OS_IS_%s' % (self.basename.upper())] + \
+ ['TARGET_OS_HAS_' + feat.upper()
+ for feat in self.target_features]
+
+def canon_processor(archinfo, proc):
+ for ainfo in archinfo.values():
+ if ainfo.basename == proc or proc in ainfo.aliases:
+ return (ainfo.basename, ainfo.basename)
+ else:
+ for (match,submodel) in ainfo.all_submodels():
+ if re.search(match, proc) != None:
+ return (ainfo.basename, submodel)
+
+ raise Exception('Unknown or unidentifiable processor "%s"' % (proc))
+
+def guess_processor(archinfo):
+ base_proc = platform.machine()
+
+ if base_proc == '':
+ raise Exception('Could not determine target CPU; set with --cpu')
+
+ full_proc = platform.processor().lower().replace(' ', '')
+ for junk in ['(tm)', '(r)']:
+ full_proc = full_proc.replace(junk, '')
+
+ if full_proc == '':
+ full_proc = base_proc
+
+ for ainfo in archinfo.values():
+ if ainfo.basename == base_proc or base_proc in ainfo.aliases:
+ for (match,submodel) in ainfo.all_submodels():
+ if re.search(match, full_proc) != None:
+ return (ainfo.basename, submodel)
+
+ return canon_processor(archinfo, ainfo.basename)
+
+ # No matches, so just use the base proc type
+ return canon_processor(archinfo, base_proc)
+
+"""
+Read a whole file into memory as a string
+"""
+def slurp_file(filename):
+ if filename is None:
+ return ''
+ return ''.join(open(filename).readlines())
+
+"""
+Perform template substitution
+"""
+def process_template(template_file, variables):
+ class PercentSignTemplate(string.Template):
+ delimiter = '%'
+
+ try:
+ template = PercentSignTemplate(slurp_file(template_file))
+ return template.substitute(variables)
+ except KeyError, e:
+ raise Exception('Unbound var %s in template %s' % (e, template_file))
+
+"""
+Create the template variables needed to process the makefile, build.h, etc
+"""
+def create_template_vars(build_config, options, modules, cc, arch, osinfo):
+ def make_cpp_macros(macros):
+ return '\n'.join(['#define BOTAN_' + macro for macro in macros])
+
+ """
+ Figure out what external libraries are needed based on selected modules
+ """
+ def link_to():
+ libs = set()
+ for module in modules:
+ for (osname,link_to) in module.libs.iteritems():
+ if osname == 'all' or osname == osinfo.basename:
+ libs.add(link_to)
+ else:
+ match = re.match('^all!(.*)', osname)
+ if match is not None:
+ exceptions = match.group(1).split(',')
+ if osinfo.basename not in exceptions:
+ libs.add(link_to)
+ return sorted(libs)
+
+ def objectfile_list(sources, obj_dir):
+ for src in sources:
+ basename = os.path.basename(src)
+
+ for src_suffix in ['.cpp', '.S']:
+ basename = basename.replace(src_suffix,
+ '.' + osinfo.obj_suffix)
+
+ yield os.path.join(obj_dir, basename)
+
+
+ def choose_mp_bits():
+ mp_bits = [mod.mp_bits for mod in modules if mod.mp_bits != 0]
+
+ if mp_bits == []:
+ return 32 # default
+
+ # Check that settings are consistent across modules
+ for mp_bit in mp_bits[1:]:
+ if mp_bit != mp_bits[0]:
+ raise Exception('Incompatible mp_bits settings found')
+
+ return mp_bits[0]
+
+ """
+ Form snippets of makefile for building each source file
+ """
+ def build_commands(sources, obj_dir, flags):
+ for (obj_file,src) in zip(objectfile_list(sources, obj_dir), sources):
+ yield '%s: %s\n\t$(CXX) %s%s $(%s_FLAGS) %s$? %s$@\n' % (
+ obj_file, src,
+ cc.add_include_dir_option,
+ build_config.include_dir,
+ flags,
+ cc.compile_option,
+ cc.output_to_option)
+
+ def makefile_list(items):
+ items = list(items) # force evaluation so we can slice it
+ return (' '*16).join([item + ' \\\n' for item in items[:-1]] +
+ [items[-1]])
+
+ def prefix_with_build_dir(path):
+ if options.with_build_dir != None:
+ return os.path.join(options.with_build_dir, path)
+ return path
+
+ return {
+ 'version_major': build_config.version_major,
+ 'version_minor': build_config.version_minor,
+ 'version_patch': build_config.version_patch,
+ 'version': build_config.version_string,
+ 'so_version': build_config.soversion_string,
+
+ 'timestamp': build_config.timestamp(),
+ 'user': build_config.username(),
+ 'hostname': build_config.hostname(),
+ 'command_line': ' '.join(sys.argv),
+ 'local_config': slurp_file(options.local_config),
+ 'makefile_style': options.makefile_style or cc.makefile_style,
+
+ 'makefile_path': prefix_with_build_dir('Makefile'),
+
+ 'prefix': options.prefix or osinfo.install_root,
+ 'libdir': options.libdir or osinfo.lib_dir,
+ 'includedir': options.includedir or osinfo.header_dir,
+ 'docdir': options.docdir or osinfo.doc_dir,
+
+ 'doc_src_dir': 'doc',
+ 'build_dir': build_config.build_dir,
+
+ 'os': options.os,
+ 'arch': options.arch,
+ 'submodel': options.cpu,
+
+ 'mp_bits': choose_mp_bits(),
+
+ 'cc': cc.binary_name + cc.mach_abi_link_flags(options.os,
+ options.arch,
+ options.cpu),
+
+ 'lib_opt': cc.lib_opt_flags,
+ 'mach_opt': cc.mach_opts(options.arch, options.cpu),
+ 'check_opt': cc.check_opt_flags,
+ 'lang_flags': cc.lang_flags + options.extra_flags,
+ 'warn_flags': cc.warning_flags,
+ 'shared_flags': cc.shared_flags,
+ 'dll_export_flags': cc.dll_export_flags,
+
+ 'so_link': cc.so_link_command_for(osinfo.basename),
+
+ 'link_to': ' '.join([cc.add_lib_option + lib for lib in link_to()]),
+
+ 'module_defines': make_cpp_macros(
+ sorted(['HAS_' + m.define for m in modules if m.define])),
+
+ 'target_os_defines': make_cpp_macros(osinfo.defines()),
+
+ 'target_compiler_defines': make_cpp_macros(
+ cc.defines(options.with_tr1)),
+
+ 'target_cpu_defines': make_cpp_macros(
+ arch.defines(options.cpu, options.with_endian)),
+
+ 'include_files': makefile_list(build_config.headers),
+
+ 'lib_objs': makefile_list(
+ objectfile_list(build_config.sources,
+ build_config.libobj_dir)),
+
+ 'check_objs': makefile_list(
+ objectfile_list(build_config.check_sources,
+ build_config.checkobj_dir)),
+
+ 'lib_build_cmds': '\n'.join(
+ build_commands(build_config.sources,
+ build_config.libobj_dir, 'LIB')),
+
+ 'check_build_cmds': '\n'.join(
+ build_commands(build_config.check_sources,
+ build_config.checkobj_dir, 'CHECK')),
+
+ 'ar_command': cc.ar_command or osinfo.ar_command,
+ 'ranlib_command': osinfo.ranlib_command(),
+ 'install_cmd_exec': osinfo.install_cmd_exec,
+ 'install_cmd_data': osinfo.install_cmd_data,
+
+ 'check_prefix': prefix_with_build_dir(''),
+ 'lib_prefix': prefix_with_build_dir(''),
+
+ 'static_suffix': osinfo.static_suffix,
+ 'so_suffix': osinfo.so_suffix,
+
+ 'botan_config': prefix_with_build_dir(
+ os.path.join(build_config.build_dir, 'botan-config')),
+ 'botan_pkgconfig': prefix_with_build_dir(
+ os.path.join(build_config.build_dir,
+ build_config.pkg_config_file())),
+
+ 'doc_files': makefile_list(build_config.doc_files()),
+
+ 'mod_list': '\n'.join(['%s (%s)' % (m.basename, m.realname)
+ for m in sorted(modules)]),
+ }
+
+"""
+Determine which modules to load based on options, target, etc
+"""
+def choose_modules_to_use(options, modules):
+
+ to_load = []
+ maybe_dep = []
+ not_using_because = {}
+
+ def cannot_use_because(mod, reason):
+ not_using_because.setdefault(reason, []).append(mod)
+
+ for (modname, module) in modules.iteritems():
+ if modname in options.disabled_modules:
+ cannot_use_because(modname, 'disabled by user')
+ elif modname in options.enabled_modules:
+ to_load.append(modname) # trust the user
+
+ elif not module.compatible_cpu(options.arch, options.cpu):
+ cannot_use_because(modname, 'CPU incompatible')
+ elif not module.compatible_os(options.os):
+ cannot_use_because(modname, 'OS incompatible')
+ elif not module.compatible_compiler(options.compiler,
+ options.with_tr1):
+ cannot_use_because(modname, 'compiler incompatible')
+
+ else:
+ if module.load_on == 'never':
+ cannot_use_because(modname, 'disabled as buggy')
+ elif module.load_on == 'request':
+ cannot_use_because(modname, 'loaded on request only')
+ elif module.load_on == 'dep':
+ maybe_dep.append(modname)
+
+ elif module.load_on == 'always':
+ to_load.append(modname)
+
+ elif module.load_on == 'asm_ok':
+ if options.asm_ok:
+ if options.no_autoload:
+ maybe_dep.append(modname)
+ else:
+ to_load.append(modname)
+ else:
+ cannot_use_because(modname,
+ 'uses assembly and --disable-asm set')
+ elif module.load_on == 'auto':
+ if options.no_autoload:
+ maybe_dep.append(modname)
+ else:
+ to_load.append(modname)
+ else:
+ logging.warning('Unknown load_on %s in %s' % (
+ module.load_on, modname))
+
+ dependency_failure = True
+
+ while dependency_failure:
+ dependency_failure = False
+ for modname in to_load:
+ for deplist in map(lambda s: s.split('|'),
+ modules[modname].dependencies()):
+
+ dep_met = False
+ for mod in deplist:
+ if dep_met is True:
+ break
+
+ if mod in to_load:
+ dep_met = True
+ elif mod in maybe_dep:
+ maybe_dep.remove(mod)
+ to_load.append(mod)
+ dep_met = True
+
+ if dep_met == False:
+ dependency_failure = True
+ if modname in to_load:
+ to_load.remove(modname)
+ if modname in maybe_dep:
+ maybe_dep.remove(modname)
+ cannot_use_because(modname, 'of dependency failure')
+
+ for not_a_dep in maybe_dep:
+ cannot_use_because(not_a_dep, 'loaded only if needed by dependency')
+
+ for reason in sorted(not_using_because.keys()):
+ disabled_mods = sorted(set([mod for mod in not_using_because[reason]]))
+
+ if disabled_mods != []:
+ logging.info('Skipping mod because %s - %s' % (
+ reason, ' '.join(disabled_mods)))
+
+ logging.debug('Loading modules %s', ' '.join(sorted(to_load)))
+
+ return [modules[mod] for mod in to_load]
+
+"""
+Load the info files about modules, targets, etc
+"""
+def load_info_files(options):
+
+ def find_files_named(desired_name, in_path):
+ for (dirpath, dirnames, filenames) in os.walk(in_path):
+ if desired_name in filenames:
+ yield os.path.join(dirpath, desired_name)
+
+ modules = dict([(mod.basename, mod) for mod in
+ [ModuleInfo(info) for info in
+ find_files_named('info.txt', options.src_dir)]])
+
+ def list_files_in_build_data(subdir):
+ for (dirpath, dirnames, filenames) in \
+ os.walk(os.path.join(options.build_data, subdir)):
+ for filename in filenames:
+ if filename.endswith('.txt'):
+ yield os.path.join(dirpath, filename)
+
+ def form_name(filepath):
+ return os.path.basename(filepath).replace('.txt', '')
+
+ archinfo = dict([(form_name(info), ArchInfo(info))
+ for info in list_files_in_build_data('arch')])
+
+ osinfo = dict([(form_name(info), OsInfo(info))
+ for info in list_files_in_build_data('os')])
+
+ ccinfo = dict([(form_name(info), CompilerInfo(info))
+ for info in list_files_in_build_data('cc')])
+
+ if 'defaults' in osinfo:
+ del osinfo['defaults'] # FIXME (remove the file)
+
+ return (modules, archinfo, ccinfo, osinfo)
+
+"""
+Perform the filesystem operations needed to setup the build
+"""
+def setup_build(build_config, options, template_vars):
+
+ """
+ Copy or link the file, depending on what the platform offers
+ """
+ def portable_symlink(filename, target_dir):
+
+ if not os.access(filename, os.R_OK):
+ logging.warning('Missing file %s' % (filename))
+ return
+
+ if 'symlink' in os.__dict__:
+ def count_dirs(dir, accum = 0):
+ if dir == '' or dir == os.path.curdir:
+ return accum
+ (dir,basename) = os.path.split(dir)
+ return accum + 1 + count_dirs(dir)
+
+ dirs_up = count_dirs(target_dir)
+
+ source = os.path.join(os.path.join(*[os.path.pardir]*dirs_up),
+ filename)
+
+ target = os.path.join(target_dir, os.path.basename(filename))
+
+ os.symlink(source, target)
+
+ elif 'link' in os.__dict__:
+ os.link(filename,
+ os.path.join(target_dir, os.path.basename(filename)))
+
+ else:
+ shutil.copy(filename, target_dir)
+
+ def choose_makefile_template(style):
+ if style == 'nmake':
+ return 'nmake.in'
+ elif style == 'unix':
+ if options.build_shared_lib:
+ return 'unix_shr.in'
+ else:
+ return 'unix.in'
+ else:
+ raise Exception('Unknown makefile style "%s"' % (style))
+
+ # First delete the build tree, if existing
+ try:
+ shutil.rmtree(build_config.build_dir)
+ except OSError, e:
+ logging.debug('Error while removing build dir: %s' % (e))
+
+ for dirs in [build_config.checkobj_dir,
+ build_config.libobj_dir,
+ build_config.full_include_dir]:
+ os.makedirs(dirs)
+
+ makefile_template = os.path.join(
+ options.makefile_dir,
+ choose_makefile_template(template_vars['makefile_style']))
+
+ logging.debug('Using makefile template %s' % (makefile_template))
+
+ templates_to_proc = {
+ makefile_template: template_vars['makefile_path']
+ }
+
+ for (template, sink) in [('buildh.in', 'build.h'),
+ ('botan-config.in', 'botan-config'),
+ ('botan.pc.in', build_config.pkg_config_file()),
+ ('botan.doxy.in', 'botan.doxy')]:
+ templates_to_proc[os.path.join(options.build_data, template)] = \
+ os.path.join(build_config.build_dir, sink)
+
+ for (template, sink) in templates_to_proc.items():
+ try:
+ f = open(sink, 'w')
+ f.write(process_template(template, template_vars))
+ finally:
+ f.close()
+
+ logging.debug('Linking %d header files in %s' % (
+ len(build_config.headers), build_config.full_include_dir))
+
+ for header_file in build_config.headers:
+ portable_symlink(header_file, build_config.full_include_dir)
+
+"""
+Main driver
+"""
+def main(argv = None):
+ if argv is None:
+ argv = sys.argv
+
+ logging.basicConfig(stream = sys.stdout,
+ format = '%(levelname) 7s: %(message)s',
+ level = logging.INFO)
+
+ logging.debug('%s invoked with options "%s"' % (
+ argv[0], ' '.join(argv[1:])))
+
+ logging.debug('Platform: OS="%s" machine="%s" proc="%s"' % (
+ platform.system(), platform.machine(), platform.processor()))
+
+ options = process_command_line(argv[1:])
+
+ if options.os == "java":
+ raise Exception("Jython detected: need --os and --cpu to set target")
+
+ options.base_dir = os.path.dirname(argv[0])
+ options.src_dir = os.path.join(options.base_dir, 'src')
+
+ options.build_data = os.path.join(options.src_dir, 'build-data')
+ options.makefile_dir = os.path.join(options.build_data, 'makefile')
+
+ (modules, archinfo, ccinfo, osinfo) = load_info_files(options)
+
+ if options.compiler is None:
+ if options.os == 'windows':
+ options.compiler = 'msvc'
+ else:
+ options.compiler = 'gcc'
+ logging.info('Guessing to use compiler %s' % (options.compiler))
+
+ if options.compiler not in ccinfo:
+ raise Exception('Unknown compiler "%s"; available options: %s' % (
+ options.compiler, ' '.join(sorted(ccinfo.keys()))))
+
+ if options.os not in osinfo:
+
+ def find_canonical_os_name(os):
+ for (name, info) in osinfo.items():
+ if os in info.aliases:
+ return name
+ return os # not found
+
+ options.os = find_canonical_os_name(options.os)
+
+ if options.os not in osinfo:
+ raise Exception('Unknown OS "%s"; available options: %s' % (
+ options.os, ' '.join(sorted(osinfo.keys()))))
+
+ if options.cpu is None:
+ (options.arch, options.cpu) = guess_processor(archinfo)
+ logging.info('Guessing target processor is a %s/%s' % (
+ options.arch, options.cpu))
+ else:
+ (options.arch, options.cpu) = canon_processor(archinfo, options.cpu)
+ logging.debug('Canonicalizized --cpu to %s/%s' % (
+ options.arch, options.cpu))
+
+ logging.info('Target is %s-%s-%s-%s' % (
+ options.compiler, options.os, options.arch, options.cpu))
+
+ # Kind of a hack...
+ options.extra_flags = ''
+ if options.compiler == 'gcc':
+
+ def is_64bit_arch(arch):
+ if arch.endswith('64') or arch in ['alpha', 's390x']:
+ return True
+ return False
+
+ if not is_64bit_arch(options.arch) and not options.dumb_gcc:
+ try:
+
+ matching_version = '(4\.[01234]\.)|(3\.[34]\.)|(2\.95\.[0-4])'
+
+ gcc_version = ''.join(
+ subprocess.Popen(['g++', '-v'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).communicate())
+
+ if re.search(matching_version, gcc_version):
+ options.dumb_gcc = True
+ except OSError, e:
+ logging.info('Could not execute GCC for version check')
+
+ if options.dumb_gcc is True:
+ logging.info('Setting -fpermissive to work around gcc bug')
+ options.extra_flags = ' -fpermissive'
+
+ if options.with_tr1 == None:
+ if ccinfo[options.compiler].compiler_has_tr1:
+ options.with_tr1 = 'system'
+ else:
+ options.with_tr1 = 'none'
+
+ modules_to_use = choose_modules_to_use(options, modules)
+
+ build_config = BuildConfigurationInformation(options, modules_to_use)
+ build_config.headers.append(
+ os.path.join(build_config.build_dir, 'build.h'))
+
+ template_vars = create_template_vars(build_config, options,
+ modules_to_use,
+ ccinfo[options.compiler],
+ archinfo[options.arch],
+ osinfo[options.os])
+
+ # Performs the I/O
+ setup_build(build_config, options, template_vars)
+
+ logging.info('Botan %s build setup is complete' % (
+ build_config.version_string))
+
+if __name__ == '__main__':
+ try:
+ main()
+ except Exception, e:
+ print >>sys.stderr, e
+ #import traceback
+ #traceback.print_exc(file=sys.stderr)
+ sys.exit(1)
+ sys.exit(0)
diff --git a/botan/doc/api.pdf b/botan/doc/api.pdf
new file mode 100644
index 0000000..a9939f2
--- /dev/null
+++ b/botan/doc/api.pdf
Binary files differ
diff --git a/botan/doc/api.tex b/botan/doc/api.tex
new file mode 100644
index 0000000..556e76a
--- /dev/null
+++ b/botan/doc/api.tex
@@ -0,0 +1,3103 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan API Reference}}
+\author{}
+\date{2009/2/19}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\keyword}[1]{\texttt{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+\newcommand{\namespace}[1]{\texttt{#1}}
+
+\newcommand{\url}[1]{\texttt{#1}}
+
+\newcommand{\ie}[0]{\emph{i.e.}}
+\newcommand{\eg}[0]{\emph{e.g.}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+
+\pagebreak
+\section{Introduction}
+
+Botan is a C++ library that attempts to provide the most common
+cryptographic algorithms and operations in an easy to use, efficient,
+and portable way. It runs on a wide variety of systems, and can be
+used with a number of different compilers.
+
+The base library is written in ISO C++, so it can be ported with
+minimal fuss, but Botan also supports a modules system. This system
+exposes system dependent code to the library through portable
+interfaces, extending the set of services available to users.
+
+\subsection{Targets}
+
+Botan's primary targets (system-wise) are 32 and 64-bit CPUs, with a
+flat memory address space of at least 32 bits. Generally, given the
+choice between optimizing for 32-bit systems and 64-bit systems, Botan
+is written to prefer 64-bit, simply on the theory that where
+performance is a real concern, modern 64-bit processors are the
+obvious choice. However in most cases this is not an issue, as many
+algorithms are specified in terms of 32-bit operations precisely to
+target commodity processors.
+
+Smaller handhelds, set-top boxes, and the bigger smart phones and smart
+cards, are also capable of using Botan. However, Botan uses a fairly
+large amount of code space (up to several megabytes, depending upon
+the compiler and options used), which could be prohibitive in some
+systems. Usage of RAM is fairly modest, usually under 64K.
+
+Botan's design makes it quite easy to remove unused algorithms in such
+a way that applications do not need to be recompiled to work, even
+applications that use the algorithms in question. They can simply ask
+Botan if the algorithm exists, and if Botan says yes, ask the library
+to give them such an object for that algorithm.
+
+\subsection{Why Botan?}
+
+Botan may be the perfect choice for your application. Or it might be a
+terribly bad idea. This section will make clear what Botan is
+and is not.
+
+First, let's cover the major strengths:
+
+\begin{list}{$\cdot$}
+ \item Support is (usually) quickly available on the project mailing lists.
+ Commercial support licenses are available for those that desire them.
+
+ \item
+ \item Is written in a (fairly) clean object-oriented style, and the usual
+ API works in terms of reasonably high-level abstractions.
+
+ \item Supports a huge variety of algorithms, including most of the major
+ public key algorithms and standards (such as IEEE 1363, PKCS, and
+ X.509v3).
+
+ \item Supports a name-based lookup scheme, so you can get a hold of any
+ algorithm on the fly.
+
+ \item You can easily extend much of the system at application compile time or
+ at run time.
+
+ \item Works well with a wide variety of compilers, operating systems, and
+ CPUs, and more all the time.
+
+ \item Is the only open source crypto library (that I know of) that has
+ support for memory allocation techniques that prevent an attacker from
+ reading swap in an attempt to gain access to keys or other secrets. In
+ fact several different such methods are supported, depending on the
+ system (two methods for Unix, another for Windows).
+
+ \item Has (optional) support for Zlib and Bzip2 compression/decompression
+ integrated completely into the system -- it only takes a line or two of
+ code to add compression to your application.
+\end{list}
+
+\noindent
+And the major downsides and deficiencies are:
+
+\begin{list}{$\cdot$}
+ \item It's written in C++. If your application isn't, Botan is probably
+ going to be more pain than it's worth.
+ \item
+
+ \item Botan doesn't directly support higher-level protocols and
+ formats like SSL or OpenPGP. SSH support is available from a
+ third-party, and there is an alpha-level SSL/TLS library
+ currently available.
+
+ \item Doesn't currently support any very high level 'envelope' style
+ processing - support for this will probably be added once support for
+ CMS is available, so code using the high level interface will produce
+ data readable by many other libraries.
+\end{list}
+
+\pagebreak
+\section{Getting Started}
+
+\subsection{Basic Conventions}
+
+With a very small number of exceptions, declarations in the library
+are contained within the namespace \namespace{Botan}. Botan declares
+several typedef'ed types to help buffer it against changes in machine
+architecture. These types are used extensively in the interface,
+thus it would be often be convenient to use them without the
+\namespace{Botan} prefix. You can do so by \keyword{using} the
+namespace \namespace{Botan::types} (this way you can use the type
+names without the namespace prefix, but the remainder of the library
+stays out of the global namespace). The included types are \type{byte}
+and \type{u32bit}, which are unsigned integer types.
+
+The headers for Botan are usually available in the form
+\filename{botan/headername.h}. For brevity in this documentation,
+headers are always just called \filename{headername.h}, but they
+should be used with the \filename{botan/} prefix in your actual code.
+
+\subsection{Initializing the Library}
+
+There is a set of core services that the library needs access to
+while it is performing requests. To ensure these are set up, you must
+create a \type{LibraryInitializer} object (usually called 'init' in
+Botan example code; 'botan\_library' or 'botan\_init' may make more
+sense in real applications) prior to making any calls to Botan. This
+object's lifetime must exceed that of all other Botan objects your
+application creates; for this reason the best place to create the
+\type{LibraryInitializer} is at the start of your \function{main}
+function, since this guarantees that it will be created first and
+destroyed last (via standard C++ RAII rules). The initializer does
+things like setting up the memory allocation system and algorithm
+lookup tables, finding out if there is a high resolution timer
+available to use, and similar such matters. With no arguments, the
+library is initialized with various default settings. So most of the
+time (unless you are writing threaded code; see below), all you need
+is:
+
+\texttt{Botan::LibraryInitializer init;}
+
+at the start of your \texttt{main}.
+
+The constructor takes an optional string that specifies arguments.
+Currently the only possible argument is ``thread\_safe'', which must
+have an Boolean argument (for instance ``thread\_safe=false'' or
+``thread\_safe=true''). If ``thread\_safe'' is specified as true the
+library will attempt to register a mutex type to properly guard access
+to shared resources. However these locks do not protect individual
+Botan objects: explicit locking must be used in this case.
+
+If you do not create a \type{LibraryInitializer} object, pretty much
+any Botan operation will fail, because it will be unable to do basic
+things like allocate memory or get random bits. Note too, that you
+should be careful to only create one such object.
+
+It is not strictly necessary to create a \type{LibraryInitializer};
+the actual code performing the initialization and shutdown are in
+static member functions of \type{LibraryInitializer}, called
+\function{initialize} and \function{deinitialize}. A
+\type{LibraryInitializer} merely provides a convenient RAII wrapper
+for the operations (thus for the internal library state as well).
+
+\subsection{Pitfalls}
+
+There are a few things to watch out for to prevent problems when using Botan.
+
+Never allocate any kind of Botan object globally. The problem with
+doing this is that the constructor for such an object will be called
+before the library is initialized. Many Botan objects will, in their
+constructor, make one or more calls into the library global state
+object. Access to this object is checked, so an exception should be
+thrown (rather than a memory access violation or undetected
+uninitialized object access). A rough equivalent that will work is to
+keep a global pointer to the object, initializing it after creating
+your \type{LibraryInitializer}. Merely making the
+\type{LibraryInitializer} also global will probably not help, because
+C++ does not make very strong guarantees about the order that such
+objects will be created.
+
+The same rule applies for making sure the destructors of all your
+Botan objects are called before the \type{LibraryInitializer} is
+destroyed. This implies you can't have static variables that are Botan
+objects inside functions or classes (since in most C++ runtimes, these
+objects will be destroyed after main has returned). This is inelegant,
+but seems to not cause many problems in practice.
+
+Botan's memory object classes (\type{MemoryVector},
+\type{SecureVector}, \type{SecureBuffer}) are extremely primitive, and
+do not (currently) meet the requirements for an STL container
+object. After Botan starts adopting C++0x features, they will be
+replaced by typedefs of \type{std::vector} with a custom allocator.
+
+Use a \function{try}/\function{catch} block inside your
+\function{main} function, and catch any \type{std::exception} throws
+(remember to catch by reference, as \type{std::exception}'s
+\function{what} method is polymorphic). This is not strictly required,
+but if you don't, and Botan throws an exception, the runtime will call
+\function{std::terminate}, which usually calls \function{abort} or
+something like it, leaving you (or worse, a user of your application)
+wondering what went wrong.
+
+\subsection{Information Flow: Pipes and Filters}
+
+Many common uses of cryptography involve processing one or more
+streams of data (be it from sockets, files, or a hardware device).
+Botan provides services that make setting up data flows through
+various operations, such as compression, encryption, and base64
+encoding. Each of these operations is implemented in what are called
+\emph{filters} in Botan. A set of filters are created and placed into
+a \emph{pipe}, and information ``flows'' through the pipe until it
+reaches the end, where the output is collected for retrieval. If
+you're familiar with the Unix shell environment, this design will
+sound quite familiar.
+
+Here is an example that uses a pipe to base64 encode some strings:
+
+\begin{verbatim}
+ Pipe pipe(new Base64_Encoder); // pipe owns the pointer
+ pipe.start_msg();
+ pipe.write(``message 1'');
+ pipe.end_msg(); // flushes buffers, increments message number
+
+ // process_msg(x) is start_msg() && write(x) && end_msg()
+ pipe.process_msg(``message2'');
+
+ std::string m1 = pipe.read_all_as_string(0); // ``message1''
+ std::string m2 = pipe.read_all_as_string(1); // ``message2''
+\end{verbatim}
+
+Bytestreams in the pipe are grouped into messages; blocks of data that
+are processed in an identical fashion (\ie, with the same sequence of
+\type{Filter}s). Messages are delimited by calls to
+\function{start\_msg} and \function{end\_msg}. Each message in a pipe
+has its own identifier, which currently is an integer that increments
+up from zero.
+
+As you can see, the \type{Base64\_Encoder} was allocated using
+\keyword{new}; but where was it deallocated? When a filter object is
+passed to a \type{Pipe}, the pipe takes ownership of the object, and
+will deallocate it when it is no longer needed.
+
+There are two different ways to make use of messages. One is to send
+several messages through a \type{Pipe} without changing the
+\type{Pipe}'s configuration, so you end up with a sequence of
+messages; one use of this would be to send a sequence of identically
+encrypted UDP packets, for example (note that the \emph{data} need not
+be identical; it is just that each is encrypted, encoded, signed, etc
+in an identical fashion). Another is to change the filters that are
+used in the \type{Pipe} between each message, by adding or removing
+\type{Filter}s; functions that let you do this are documented in the
+Pipe API section.
+
+Most operations in Botan have a corresponding filter for use in Pipe.
+Here's code that encrypts a string with AES-128 in CBC mode:
+
+\begin{verbatim}
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 16); // a random 128-bit key
+ InitializationVector iv(rng, 16); // a random 128-bit IV
+
+ // Notice the algorithm we want is specified by a string
+ Pipe pipe(get_cipher(``AES-128/CBC'', key, iv, ENCRYPTION));
+
+ pipe.process_msg(``secrets'');
+ pipe.process_msg(``more secrets'');
+
+ MemoryVector<byte> c1 = pipe.read_all(0);
+
+ byte c2[4096] = { 0 };
+ u32bit got_out = pipe.read(c2, sizeof(c2), 1);
+ // use c2[0...got_out]
+\end{verbatim}
+
+Note the use of \type{AutoSeeded\_RNG}, which is a random number
+generator. If you want to, you can explicitly set up the random number
+generators and entropy sources you want to, however for 99\% of cases
+\type{AutoSeeded\_RNG} is preferable.
+
+\type{Pipe} also has convenience methods for dealing with
+\type{std::iostream}s. Here is an example of those, using the
+\type{Bzip\_Compression} filter (included as a module; if you have
+bzlib available, check \filename{building.pdf} for how to enable it)
+to compress a file:
+
+\begin{verbatim}
+ std::ifstream in(``data.bin'', std::ios::binary)
+ std::ofstream out(``data.bin.bz2'', std::ios::binary)
+
+ Pipe pipe(new Bzip_Compression);
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ out << pipe;
+\end{verbatim}
+
+However there is a hitch to the code above; the complete contents of
+the compressed data will be held in memory until the entire message
+has been compressed, at which time the statement \verb|out << pipe| is
+executed, and the data is freed as it is read from the pipe and
+written to the file. But if the file is very large, we might not have
+enough physical memory (or even enough virtual memory!) for that to be
+practical. So instead of storing the compressed data in the pipe for
+reading it out later, we divert it directly to the file:
+
+\begin{verbatim}
+ std::ifstream in(``data.bin'', std::ios::binary)
+ std::ofstream out(``data.bin.bz2'', std::ios::binary)
+
+ Pipe pipe(new Bzip_Compression, new DataSink_Stream(out));
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+\end{verbatim}
+
+This is the first code we've seen so far that uses more than one
+filter in a pipe. The output of the compressor is sent to the
+\type{DataSink\_Stream}. Anything written to a \type{DataSink\_Stream}
+is written to a file; the filter produces no output. As soon as the
+compression algorithm finishes up a block of data, it will send it along,
+at which point it will immediately be written to disk; if you were to
+call \verb|pipe.read_all()| after \verb|pipe.end_msg()|, you'd get an
+empty vector out.
+
+Here's an example using two computational filters:
+
+\begin{verbatim}
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 32);
+ InitializationVector iv(rng, 16);
+
+ Pipe encryptor(get_cipher("AES/CBC/PKCS7", key, iv, ENCRYPTION),
+ new Base64_Encoder);
+
+ encryptor.start_msg();
+ file >> encryptor;
+ encryptor.end_msg(); // flush buffers, complete computations
+ std::cout << encryptor;
+\end{verbatim}
+
+\subsection{Fork}
+
+It is fairly common that you might receive some data and want to
+perform more than one operation on it (\ie, encrypt it with Serpent
+and calculate the SHA-256 hash of the plaintext at the same
+time). That's where \type{Fork} comes in. \type{Fork} is a filter that
+takes input and passes it on to \emph{one or more} \type{Filter}s
+that are attached to it. \type{Fork} changes the nature of the pipe
+system completely. Instead of being a linked list, it becomes a tree.
+
+Each \type{Filter} in the fork is given its own output buffer, and
+thus its own message. For example, if you had previously written two
+messages into a \type{Pipe}, then you start a new one with a
+\type{Fork} that has three paths of \type{Filter}'s inside it, you
+add three new messages to the \type{Pipe}. The data you put into the
+\type{Pipe} is duplicated and sent into each set of \type{Filter}s,
+and the eventual output is placed into a dedicated message slot in the
+\type{Pipe}.
+
+Messages in the \type{Pipe} are allocated in a depth-first manner. This is only
+interesting if you are using more than one \type{Fork} in a single \type{Pipe}.
+As an example, consider the following:
+
+\begin{verbatim}
+ Pipe pipe(new Fork(
+ new Fork(
+ new Base64_Encoder,
+ new Fork(
+ NULL,
+ new Base64_Encoder
+ )
+ ),
+ new Hex_Encoder
+ )
+ );
+\end{verbatim}
+
+In this case, message 0 will be the output of the first \type{Base64\_Encoder},
+message 1 will be a copy of the input (see below for how \type{Fork} interprets
+NULL pointers), message 2 will be the output of the second
+\type{Base64\_Encoder}, and message 3 will be the output of the
+\type{Hex\_Encoder}. As you can see, this results in message numbers being
+allocated in a top to bottom fashion, when looked at on the screen. However,
+note that there could be potential for bugs if this is not anticipated. For
+example, if your code is passed a \type{Filter}, and you assume it is a
+``normal'' one that only uses one message, your message offsets would be
+wrong, leading to some confusion during output.
+
+If Fork's first argument is a null pointer, but a later argument is
+not, then Fork will feed a copy of its input directly through. Here's
+a case where that is useful:
+
+\begin{verbatim}
+ // have std::string ciphertext, auth_code, key, iv, mac_key;
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher(``AES-128'', key, iv, DECRYPTION),
+ new Fork(
+ 0
+ new MAC_Filter(``HMAC(SHA-1)'', mac_key)
+ )
+ );
+
+ pipe.process_msg(ciphertext);
+ std::string plaintext = pipe.read_all_as_string(0);
+ SecureVector<byte> mac = pipe.read_all(1);
+
+ if(mac != auth_code)
+ error();
+\end{verbatim}
+
+Here we wanted to not only decrypt the message, but send the decrypted
+text through an additional computation, in order to compute the
+authentication code.
+
+Any \type{Filter}s that are attached to the \type{Pipe} after the
+\type{Fork} are implicitly attached onto the first branch created by
+the fork. For example, let's say you created this \type{Pipe}:
+
+\begin{verbatim}
+Pipe pipe(new Fork(new Hash_Filter("MD5"), new Hash_Filter("SHA-1")),
+ new Hex_Encoder);
+\end{verbatim}
+
+And then called \function{start\_msg}, inserted some data, then
+\function{end\_msg}. Then \arg{pipe} would contain two messages. The
+first one (message number 0) would contain the MD5 sum of the input in
+hex encoded form, and the other would contain the SHA-1 sum of the
+input in raw binary. However, it's much better to use a \type{Chain}
+instead.
+
+\subsubsection{Chain}
+
+A \type{Chain} filter creates a chain of \type{Filter}s and
+encapsulates them inside a single filter (itself). This allows a
+sequence of filters to become a single filter, to be passed into or
+out of a function, or to a \type{Fork} constructor.
+
+You can call \type{Chain}'s constructor with up to 4 \type{Filter*}s
+(they will be added in order), or with an array of \type{Filter*}s and
+a \type{u32bit} that tells \type{Chain} how many \type{Filter*}s are
+in the array (again, they will be attached in order). Here's the
+example from the last section, using chain instead of relying on the
+obscure rule that version used.
+
+\begin{verbatim}
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("MD5"), new Hex_Encoder),
+ new Hash_Filter("SHA-1")
+ )
+ );
+\end{verbatim}
+
+\subsection{The Pipe API}
+
+\subsubsection{Initializing Pipe}
+
+By default, \type{Pipe} will do nothing at all; any input placed into
+the \type{Pipe} will be read back unchanged. Obviously, this has
+limited utility, and presumably you want to use one or more
+\type{Filter}s to somehow process the data. First, you can choose a
+set of \type{Filter}s to initialize the \type{Pipe} via the
+constructor. You can pass it either a set of up to 4 \type{Filter*}s,
+or a pre-defined array and a length:
+
+\begin{verbatim}
+ Pipe pipe1(new Filter1(/*args*/), new Filter2(/*args*/),
+ new Filter3(/*args*/), new Filter4(/*args*/));
+ Pipe pipe2(new Filter1(/*args*/), new Filter2(/*args*/));
+
+ Filter* filters[5] = {
+ new Filter1(/*args*/), new Filter2(/*args*/), new Filter3(/*args*/),
+ new Filter4(/*args*/), new Filter5(/*args*/) /* more if desired... */
+ };
+ Pipe pipe3(filters, 5);
+\end{verbatim}
+
+This is by far the most common way to initialize a \type{Pipe}. However,
+occasionally a more flexible initialization strategy is necessary; this is
+supported by 4 member functions: \function{prepend}(\type{Filter*}),
+\function{append}(\type{Filter*}), \function{pop}(), and \function{reset}().
+These functions may only be used while the \type{Pipe} in question is not in
+use; that is, either before calling \function{start\_msg}, or after
+\function{end\_msg} has been called (and no new calls to \function{start\_msg}
+have been made yet).
+
+The function \function{reset}() simply removes all the \type{Filter}s
+that the \type{Pipe} is currently using~--~it is reset to an
+initialize, ``empty'' state. Any data that is being retained by the
+\type{Pipe} is retained after a \function{reset}(), and
+\function{reset}() does not affect the message numbers (discussed
+later).
+
+Calling \function{prepend} and \function{append} will either prepend
+or append the passed \type{Filter} object to the list of
+transformations. For example, if you \function{prepend} a
+\type{Filter} implementing encryption, and the \type{Pipe} already had
+a \type{Filter} that hex encoded the input, then the next set of
+input would be first encrypted, then hex encoded. Alternately, if you
+called \function{append}, then the input would be first be hex
+encoded, and then encrypted (which is not terribly useful in this
+particular example).
+
+Finally, calling \function{pop}() will remove the first transformation
+of the \type{Pipe}. Say we had called \function{prepend} to put an
+encryption \type{Filter} into a \type{Pipe}; calling \function{pop}()
+would remove this \type{Filter} and return the \type{Pipe} to its
+state before we called \function{prepend}.
+
+\subsubsection{Giving Data to a Pipe}
+
+Input to a \type{Pipe} is delimited into messages, which can be read from
+independently (\ie, you can read 5 bytes from one message, and then all of
+another message, without either read affecting any other messages). The
+messages are delimited by calls to \function{start\_msg} and
+\function{end\_msg}. In between these two calls, you can write data into a
+\type{Pipe}, and it will be processed by the \type{Filter}(s) that it
+contains. Writes at any other time are invalid, and will result in an
+exception.
+
+As to writing, you can call any of the functions called \function{write}(),
+that can take any of: a \type{byte[]}/\type{u32bit} pair, a
+\type{SecureVector<byte>}, a \type{std::string}, a \type{DataSource\&}, or a
+single \type{byte}.
+
+Sometimes, you may want to do only a single write per message. In this case,
+you can use the \function{process\_msg} series of functions, which start a
+message, write their argument into the \type{Pipe}, and then end the
+message. In this case you would not make any explicit calls to
+\function{start\_msg}/\function{end\_msg}. The version of \function{write}
+that takes a single \type{byte} is not supported by \function{process\_msg},
+but all the other variants are.
+
+\type{Pipe} can also be used with the \verb|>>| operator, and will accept a
+\type{std::istream}, (or on Unix systems with the \verb|fd_unix| module), a
+Unix file descriptor. In either case, the entire contents of the file will be
+read into the \type{Pipe}.
+
+\subsubsection{Getting Output from a Pipe}
+
+Retrieving the processed data from a \type{Pipe} is a bit more complicated, for
+various reasons. In particular, because \type{Pipe} will separate each message
+into a separate buffer, you have to be able to retrieve data from each message
+independently. Each of \type{Pipe}'s read functions has a final parameter that
+specifies what message to read from (as a 32-bit integer). If this parameter is
+set to \type{Pipe::DEFAULT\_MESSAGE}, it will read the current default message
+(\type{DEFAULT\_MESSAGE} is also the default value of this parameter). The
+parameter will not be mentioned in further discussion of the reading API, but
+it is always there (unless otherwise noted).
+
+Reading is done with a variety of functions. The most basic are \type{u32bit}
+\function{read}(\type{byte} \arg{out}[], \type{u32bit} \arg{len}) and
+\type{u32bit} \function{read}(\type{byte\&} \arg{out}). Each reads into
+\arg{out} (either up to \arg{len} bytes, or a single byte for the one taking a
+\type{byte\&}), and returns the total number of bytes read. There is a variant
+of these functions, all named \function{peek}, which performs the same
+operations, but does not remove the bytes from the message (reading is a
+destructive operation with a \type{Pipe}).
+
+There are also the functions \type{SecureVector<byte>} \function{read\_all}(),
+and \type{std::string} \function{read\_all\_as\_string}(), which return the
+entire contents of the message, either as a memory buffer, or a
+\type{std::string} (which is generally only useful if the \type{Pipe} has
+encoded the message into a text string, such as when a \type{Base64\_Encoder}
+is used).
+
+To determine how many bytes are left in a message, call \type{u32bit}
+\function{remaining}() (which can also take an optional message
+number). Finally, there are some functions for managing the default message
+number: \type{u32bit} \function{default\_msg}() will return the current default
+message, \type{u32bit} \function{message\_count}() will return the total number
+of messages (0...\function{message\_count}()-1), and
+\function{set\_default\_msg}(\type{u32bit} \arg{msgno}) will set a new default
+message number (which must be a valid message number for that \type{Pipe}). The
+ability to set the default message number is particularly important in the case
+of using the file output operations (\verb|<<| with a \type{std::ostream} or
+Unix file descriptor), because there is no way to specify it explicitly when
+using the output operator.
+
+\subsection{A Filter Example}
+
+Here is some code that takes one or more filenames in \arg{argv} and
+calculates the result of several hash functions for each file. The complete
+program can be found as \filename{hasher.cpp} in the Botan distribution. For
+brevity, most error checking has been removed.
+
+\begin{verbatim}
+ string name[3] = { "MD5", "SHA-1", "RIPEMD-160" };
+ Botan::Filter* hash[3] = {
+ new Botan::Chain(new Botan::Hash_Filter(name[0]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[1]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[2]),
+ new Botan::Hex_Encoder) };
+
+ Botan::Pipe pipe(new Botan::Fork(hash, COUNT));
+
+ for(u32bit j = 1; argv[j] != 0; j++)
+ {
+ ifstream file(argv[j]);
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ for(u32bit k = 0; k != 3; k++)
+ {
+ pipe.set_default_msg(3*(j-1)+k);
+ cout << name[k] << "(" << argv[j] << ") = " << pipe << endl;
+ }
+ }
+\end{verbatim}
+
+
+\subsection{Filter Catalog}
+
+This section contains descriptions of every \type{Filter} included in
+the portable sections of Botan. \type{Filter}s provided by modules
+are documented elsewhere.
+
+\subsubsection{Keyed Filters}
+
+A few sections ago, it was mentioned that \type{Pipe} can process multiple
+messages, treating each of them exactly the same. Well, that was a bit of a
+lie. There are some algorithms (in particular, block ciphers not in ECB mode,
+and all stream ciphers) that change their state as data is put through them.
+
+Naturally, you might well want to reset the keys or (in the case of block
+cipher modes) IVs used by such filters, so multiple messages can be processed
+using completely different keys, or new IVs, or new keys and IVs, or whatever.
+And in fact, even for a MAC or an ECB block cipher, you might well want to
+change the key used from message to message.
+
+Enter \type{Keyed\_Filter}, which acts as an abstract interface for
+any filter that is uses keys: block cipher modes, stream ciphers,
+MACs, and so on. It has two functions, \function{set\_key} and
+\function{set\_iv}. Calling \function{set\_key} will, naturally, set
+(or reset) the key used by the algorithm. Setting the IV only makes
+sense in certain algorithms -- a call to \function{set\_iv} on an
+object that doesn't support IVs will be ignored. You \emph{must} call
+\function{set\_key} before calling \function{set\_iv}: while not all
+\type{Keyed\_Filter} objects require this, you should assume it is
+required anytime you are using a \type{Keyed\_Filter}.
+
+Here's a example:
+
+\begin{verbatim}
+ Keyed_Filter *cast, *hmac;
+ Pipe pipe(new Base64_Decoder,
+ // Note the assignments to the cast and hmac variables
+ cast = new CBC_Decryption("CAST-128", "PKCS7", cast_key, iv),
+ new Fork(
+ 0, // Read the section 'Fork' to understand this
+ new Chain(
+ hmac = new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+ pipe.start_msg();
+ [use pipe for a while, decrypt some stuff, derive new keys and IVs]
+ pipe.end_msg();
+
+ cast->set_key(cast_key2);
+ cast->set_iv(iv2);
+ hmac->set_key(mac_key2);
+
+ pipe.start_msg();
+ [use pipe for some other things]
+ pipe.end_msg();
+\end{verbatim}
+
+There are some requirements to using \type{Keyed\_Filter} that you must
+follow. If you call \function{set\_key} or \function{set\_iv} on a filter that
+is owned by a \type{Pipe}, you must do so while the \type{Pipe} is
+``unlocked''. This refers to the times when no messages are being processed by
+\type{Pipe} -- either before \type{Pipe}'s \function{start\_msg} is called, or
+after \function{end\_msg} is called (and no new call to \function{start\_msg}
+has happened yet). Doing otherwise will result in undefined behavior, probably
+silently getting invalid output.
+
+And remember: if you're resetting both values, reset the key \emph{first}.
+
+\subsubsection{Cipher Filters}
+
+Getting a hold of a \type{Filter} implementing a cipher is very easy. Simply
+make sure you're including the header \filename{lookup.h}, and call
+\function{get\_cipher}. Generally you will pass the return value directly into
+a \type{Pipe}. There are actually a couple different functions, which do pretty
+much the same thing:
+
+\function{get\_cipher}(\type{std::string} \arg{cipher\_spec},
+ \type{SymmetricKey} \arg{key},
+ \type{InitializationVector} \arg{iv},
+ \type{Cipher\_Dir} \arg{dir});
+
+\function{get\_cipher}(\type{std::string} \arg{cipher\_spec},
+ \type{SymmetricKey} \arg{key},
+ \type{Cipher\_Dir} \arg{dir});
+
+The version that doesn't take an IV is useful for things that don't use them,
+like block ciphers in ECB mode, or most stream ciphers. If you specify a
+\arg{cipher\_spec} that does want a IV, and you use the version that doesn't
+take one, an exception will be thrown. The \arg{dir} argument can be either
+\type{ENCRYPTION} or \type{DECRYPTION}. In a few cases, like most (but not all)
+stream ciphers, these are equivalent, but even then it provides a way of
+showing the ``intent'' of the operation to readers of your code.
+
+The \arg{cipher\_spec} is a string that specifies what cipher is to be
+used. The general syntax for \arg{cipher\_spec} is ``STREAM\_CIPHER'',
+``BLOCK\_CIPHER/MODE'', or ``BLOCK\_CIPHER/MODE/PADDING''. In the case of
+stream ciphers, no mode is necessary, so just the name is sufficient. A block
+cipher requires a mode of some sort, which can be ``ECB'', ``CBC'', ``CFB(n)'',
+``OFB'', ``CTR-BE'', or ``EAX(n)''. The argument to CFB mode is how many bits
+of feedback should be used. If you just use ``CFB'' with no argument, it will
+default to using a feedback equal to the block size of the cipher. EAX mode
+also takes an optional bit argument, which tells EAX how large a tag size to
+use~--~generally this is the size of the block size of the cipher, which is the
+default if you don't specify any argument.
+
+In the case of the ECB and CBC modes, a padding method can also be
+specified. If it is not supplied, ECB defaults to not padding, and CBC defaults
+to using PKCS \#5/\#7 compatible padding. The padding methods currently
+available are ``NoPadding'', ``PKCS7'', ``OneAndZeros'', and ``CTS''. CTS
+padding is currently only available for CBC mode, but the others can also be
+used in ECB mode.
+
+Some example \arg{cipher\_spec} arguments are: ``DES/CFB(32)'',
+``TripleDES/OFB'', ``Blowfish/CBC/CTS'', ``SAFER-SK(10)/CBC/OneAndZeros'',
+``AES/EAX'', ``ARC4''
+
+``CTR-BE'' refers to counter mode where the counter is incremented as if it
+were a big-endian encoded integer. This is compatible with most other
+implementations, but it is possible some will use the incompatible little
+endian convention. This version would be denoted as ``CTR-LE'' if it were
+supported.
+
+``EAX'' is a new cipher mode designed by Wagner, Rogaway, and Bellare. It is an
+authenticated cipher mode (that is, no separate authentication is needed), has
+provable security, and is free from patent entanglements. It runs about half as
+fast as most of the other cipher modes (like CBC, OFB, or CTR), which is not
+bad considering you don't need to use an authentication code.
+
+\subsubsection{Hashes and MACs}
+
+Hash functions and MACs don't need anything special when it comes to
+filters. Both just take their input and produce no output until
+\function{end\_msg()} is called, at which time they complete the hash or MAC
+and send that as output.
+
+These \type{Filter}s take a string naming the type to be used. If for some
+reason you name something that doesn't exist, an exception will be thrown.
+
+\noindent
+\function{Hash\_Filter}(\type{std::string} \arg{hash},
+ \type{u32bit} \arg{outlength}):
+
+This type hashes its input with \arg{hash}. When \function{end\_msg} is called
+on the owning \type{Pipe}, the hash is completed and the digest is sent on to
+the next thing in the pipe. The argument \arg{outlength} specifies how much of
+the output of the hash will be passed along to the next filter when
+\function{end\_msg} is called. By default, it will pass the entire hash.
+
+Examples of names for \function{Hash\_Filter} are ``SHA-1'' and ``Whirlpool''.
+
+\noindent
+\function{MAC\_Filter}(\type{std::string} \arg{mac},
+ \type{const SymmetricKey\&} \arg{key},
+ \type{u32bit} \arg{outlength}):
+
+The constructor for a \type{MAC\_Filter} takes a key, used in calculating the
+MAC, and a length parameter, which has semantics exactly the same as the one
+passed to \type{Hash\_Filter}s constructor.
+
+Examples for \arg{mac} are ``HMAC(SHA-1)'', ``CMAC(AES-128)'', and the
+exceptionally long, strange, and probably useless name
+``CMAC(Lion(Tiger(20,3),MARK-4,1024))''.
+
+\subsubsection{PK Filters}
+
+There are four classes in this category, \type{PK\_Encryptor\_Filter},
+\type{PK\_Decryptor\_Filter}, \type{PK\_Signer\_Filter}, and
+\type{PK\_Verifier\_Filter}. Each takes a pointer to an object of the
+appropriate type (\type{PK\_Encryptor}, \type{PK\_Decryptor}, etc) that is
+deleted by the destructor. These classes are found in \filename{pk\_filts.h}.
+
+Three of these, for encryption, decryption, and signing are pretty much
+identical conceptually. Each of them buffers its input until the end of the
+message is marked with a call to the \function{end\_msg} function. Then they
+encrypt, decrypt, or sign their input and send the output (the ciphertext, the
+plaintext, or the signature) into the next filter.
+
+Signature verification works a little differently, because it needs to know
+what the signature is in order to check it. You can either pass this in along
+with the constructor, or call the function \function{set\_signature} -- with
+this second method, you need to keep a pointer to the filter around so you can
+send it this command. In either case, after \function{end\_msg} is called, it
+will try to verify the signature (if the signature has not been set by either
+method, an exception will be thrown here). It will then send a single byte onto
+the next filter -- a 1 or a 0, which specifies whether the signature verified
+or not (respectively).
+
+For more information about PK algorithms (including creating the appropriate
+objects to pass to the constructors), read the section ``Public Key
+Cryptography'' in this manual.
+
+\subsubsection{Encoders}
+
+Often you want your data to be in some form of text (for sending over channels
+that aren't 8-bit clean, printing it, etc). The filters \type{Hex\_Encoder}
+and \type{Base64\_Encoder} will convert arbitrary binary data into hex or
+base64 formats. Not surprisingly, you can use \type{Hex\_Decoder} and
+\type{Base64\_Decoder} to convert it back into its original form.
+
+Both of the encoders can take a few options about how the data should be
+formatted (all of which have defaults). The first is a \type{bool} which simply
+says if the encoder should insert line breaks. This defaults to
+false. Line breaks don't matter either way to the decoder, but it makes the
+output a bit more appealing to the human eye, and a few transport mechanisms
+(notably some email systems) limit the maximum line length.
+
+The second encoder option is an integer specifying how long such lines will be
+(obviously this will be ignored if line-breaking isn't being used). The default
+tends to be in the range of 60-80 characters, but is not specified exactly. If
+you want a specific value, set it. Otherwise the default should be fine.
+
+Lastly, \type{Hex\_Encoder} takes an argument of type \type{Case}, which can be
+\type{Uppercase} or \type{Lowercase} (default is \type{Uppercase}). This
+specifies what case the characters A-F should be output as. The base64 encoder
+has no such option, because it uses both upper and lower case letters for its
+output.
+
+The decoders both take a single option, which tells it how the object should
+behave in the case of invalid input. The enum (called \type{Decoder\_Checking})
+can take on any of three values: \type{NONE}, \type{IGNORE\_WS}, and
+\type{FULL\_CHECK}. With \type{NONE} (the default, for compatibility with
+previous releases), invalid input (for example, a ``z'' character in supposedly
+hex input) will simply be ignored. With \type{IGNORE\_WS}, whitespace will be
+ignored by the decoder, but receiving other non-valid data will raise an
+exception. Finally, \type{FULL\_CHECK} will raise an exception for \emph{any}
+characters not in the encoded character set, including whitespace.
+
+You can find the declarations for these types in \filename{hex.h} and
+\filename{base64.h}.
+
+\subsection{Rolling Your Own}
+
+The system of filters and pipes was designed in an attempt to make it
+as simple as possible to write new \type{Filter} objects. There are
+essentially four functions that need to be implemented by an object
+deriving from \type{Filter}:
+
+\noindent
+\type{void} \function{write}(\type{byte} \arg{input}[], \type{u32bit}
+\arg{length}):
+
+The \function{write} function is what is called when a filter receives input
+for it to process. The filter is \emph{not} required to process it right away;
+many filters buffer their input before producing any output. A filter will
+usually have \function{write} called many times during its lifetime.
+
+\noindent
+\type{void} \function{send}(\type{byte} \arg{output}[], \type{u32bit}
+\arg{length}):
+
+Eventually, a filter will want to produce some output to send along to the next
+filter in the pipeline. It does so by calling \function{send} with whatever it
+wants to send along to the next filter. There is also a version of
+\function{send} taking a single byte argument, as a convenience.
+
+\noindent
+\type{void} \function{start\_msg()}:
+
+This function is optional. Implement it if your \type{Filter} would like to do
+some processing or setup at the start of each message (for an example, see the
+Zlib compression module).
+
+\noindent
+\type{void} \function{end\_msg()}:
+
+Implementing the \function{end\_msg} function is optional. It is called when it
+has been requested that filters finish up their computations. Note that they
+must \emph{not} deallocate their resources; this should be done by their
+destructor. They should simply finish up with whatever computation they have
+been working on (for example, a compressing filter would flush the compressor
+and \function{send} the final block), and empty any buffers in preparation for
+processing a fresh new set of input. It is essentially the inverse of
+\function{start\_msg}.
+
+Additionally, if necessary, filters can define a constructor that takes any
+needed arguments, and a destructor to deal with deallocating memory, closing
+files, etc.
+
+There is also a \type{BufferingFilter} class (in \filename{buf\_filt.h}) that
+will take a message and split it up into an initial block that can be of any
+size (including zero), a sequence of fixed sized blocks of any non-zero size,
+and last (possibly zero-sized) final block. This might make a useful base class
+for your filters, depending on what you have in mind.
+
+
+\pagebreak
+\section{Public Key Cryptography}
+
+Let's create a 1024-bit RSA private key, encode the public key as a
+PKCS \#1 file with PEM encoding (which can be understood by many other
+cryptographic programs)
+
+\begin{verbatim}
+// everyone does:
+AutoSeeded_RNG rng;
+
+// Alice
+RSA_PrivateKey priv_rsa(rng, 1024 /* bits */);
+
+std::string alice_pem = X509::PEM_encode(priv_rsa);
+
+// send alice_pem to Bob, who does
+
+// Bob
+std::auto_ptr<X509_PublicKey> alice(load_key(alice_pem));
+
+RSA_PublicKey* alice_rsa = dynamic_cast<RSA_PublicKey>(alice);
+if(alice_rsa)
+ {
+ /* ... */
+ }
+
+\end{verbatim}
+
+\subsection{Creating PK Algorithm Key Objects}
+
+The library has interfaces for encryption, signatures, etc that do not require
+knowing the exact algorithm in use (for example RSA and Rabin-Williams
+signatures are handled by the exact same code path).
+
+One place where we \emph{do} need to know exactly what kind of algorithm is in
+use is when we are creating a key (\emph{But}: read the section ``Importing and
+Exporting PK Keys'', later in this manual).
+
+There are (currently) two kinds of public key algorithms in Botan: ones based
+on integer factorization (RSA and Rabin-Williams), and ones based on the
+discrete logarithm problem (DSA, Diffie-Hellman, Nyberg-Rueppel, and
+ElGamal). Since discrete logarithm parameters (primes and generators) can be
+shared among many keys, there is the notion of these being a combined type
+(called \type{DL\_Group}).
+
+There are two ways to create a DL private key (such as
+\type{DSA\_PrivateKey}). One is to pass in just a \type{DL\_Group} object -- a
+new key will automatically be generated. The other involves passing in a group
+to use, along with both the public and private values (private value first).
+
+Since in integer factorization algorithms, the modulus used isn't shared by
+other keys, we don't use this notion. You can create a new key by passing in a
+\type{u32bit} telling how long (in bits) the key should be, or you can copy an
+pre-existing key by passing in the appropriate parameters (primes, exponents,
+etc). For RSA and Rabin-Williams (the two IF schemes in Botan), the parameters
+are all \type{BigInt}s: prime 1, prime 2, encryption exponent, decryption
+exponent, modulus. The last two are optional, since they can easily be derived
+from the first three.
+
+\subsubsection{Creating a DL\_Group}
+
+There are quite a few ways to get a \type{DL\_Group} object. The best is to use
+the function \function{get\_dl\_group}, which takes a string naming a group; it
+will either return that group, if it knows about it, or throw an
+exception. Names it knows about include ``IETF-n'' where n is 768, 1024, 1536,
+2048, 3072, or 4096, and ``DSA-n'', where n is 512, 768, or 1024. The IETF
+groups are the ones specified for use with IPSec, and the DSA ones are the
+default DSA parameters specified by Java's JCE. For DSA and Nyberg-Rueppel, you
+should only use the ``DSA-n'' groups, while Diffie-Hellman and ElGamal can use
+either type (keep in mind that some applications/standards require DH/ELG to
+use DSA-style primes, while others require strong prime groups).
+
+You can also generate a new random group. This is not recommend, because it is
+quite slow, especially for safe primes.
+
+\subsection{Key Checking}
+
+Most public key algorithms have limitations or restrictions on their
+parameters. For example RSA requires an odd exponent, and algorithms based on
+the discrete logarithm problem need a generator $> 1$.
+
+Each low-level public key type has a function named \function{check\_key} that
+takes a \type{bool}. This function returns a Boolean value that declares
+whether or not the key is valid (from an algorithmic standpoint). For example,
+it will check to make sure that the prime parameters of a DSA key are, in fact,
+prime. It does not have anything to do with the validity of the key for any
+particular use, nor does it have anything to do with certificates that link a
+key (which, after all, is just some numbers) with a user or other entity. If
+\function{check\_key}'s argument is \type{true}, then it does ``strong''
+checking, which includes fairly expensive operations like primality checking.
+
+Keys are always checked when they are loaded or generated, so typically there
+is no reason to use this function directly. However, you can disable or reduce
+the checks for particular cases (public keys, loaded private keys, generated
+private keys) by setting the right config toggle (see the section on the
+configuration subsystem for details).
+
+\subsection{Getting a PK algorithm object}
+
+The key types, like \type{RSA\_PrivateKey}, do not implement any kind
+of padding or encoding (which is generally necessary for security). To
+get an object like this, the easiest thing to do is call the functions
+found in \filename{look\_pk.h}. Generally these take a key, followed
+by a string that specified what hashing and encoding method(s) to
+use. Examples of such strings are ``EME1(SHA-256)'' for OAEP
+encryption and ``EMSA4(SHA-256)'' for PSS signatures (where the
+message is hashed using SHA-256).
+
+Here are some basic examples (using an RSA key) to give you a feel for the
+possibilities. These examples assume \type{rsakey} is an
+\type{RSA\_PrivateKey}, since otherwise we would not be able to create a
+decryption or signature object with it (you can create encryption or signature
+verification objects with public keys, naturally). Remember to delete these
+objects when you're done with them.
+
+\begin{verbatim}
+ // PKCS #1 v2.0 / IEEE 1363 compatible encryption
+ PK_Encryptor* rsa_enc1 = get_pk_encryptor(rsakey, "EME1(RIPEMD-160)");
+ // PKCS #1 v1.5 compatible encryption
+ PK_Encryptor* rsa_enc2 = get_pk_encryptor(rsakey, "PKCS1v15");
+
+ // Raw encryption: no padding, input is directly encrypted by the key
+ // Don't use this unless you know what you're doing
+ PK_Encryptor* rsa_enc3 = get_pk_encryptor(rsakey, "Raw");
+
+ // This object can decrypt things encrypted by rsa_enc1
+ PK_Decryptor* rsa_dec1 = get_pk_decryptor(rsakey, "EME1(RIPEMD-160)");
+
+ // PKCS #1 v1.5 compatible signatures
+ PK_Signer* rsa_sig = get_pk_signer(rsakey, "EMSA3(MD5)");
+ PK_Verifier* rsa_verify = get_pk_verifier(rsakey, "EMSA3(MD5)");
+
+ // PKCS #1 v2.1 compatible signatures
+ PK_Signer* rsa_sig2 = get_pk_signer(rsakey, "EMSA4(SHA-1)");
+ PK_Verifier* rsa_verify2 = get_pk_verifier(rsakey, "EMSA4(SHA-1)");
+
+ // Hash input with SHA-1, but don't pad the input in any way; usually
+ // used with DSA/NR, not RSA
+ PK_Signer* rsa_sig = get_pk_signer(rsakey, "EMSA1(SHA-1)");
+\end{verbatim}
+
+\subsection{Encryption}
+
+The \type{PK\_Encryptor} and \type{PK\_Decryptor} classes are the interface for
+encryption and decryption, respectively.
+
+Calling \function{encrypt} with a \type{byte} array, a length
+parameter, and an RNG object will return the input encrypted with
+whatever scheme is being used. Calling the similar \function{decrypt}
+will perform the inverse operation. You can also do these operations
+with \type{SecureVector<byte>}s. In all cases, the output is returned
+via a \type{SecureVector<byte>}.
+
+If you attempt an operation with a larger size than the key can
+support (this limit varies based on the algorithm, the key size, and
+the padding method used (if any)), an exception will be
+thrown. Alternately, you can call \function{maximum\_input\_size},
+that will return the maximum size you can safely encrypt. In fact,
+you can often encrypt an object that is one byte longer, but only if
+enough of the high bits of the leading byte are set to zero. Since
+this is pretty dicey, it's best to stick with the advertised maximum.
+
+Available public key encryption algorithms in Botan are RSA and ElGamal. The
+encoding methods are EME1, denoted by ``EME1(HASHNAME)'', PKCS \#1 v1.5,
+called ``PKCS1v15'' or ``EME-PKCS1-v1\_5'', and raw encoding (``Raw'').
+
+For compatibility reasons, PKCS \#1 v1.5 is recommend for use with
+ElGamal (most other implementations of ElGamal do not support any
+other encoding format). RSA can also be used with PKCS \# 1 encoding,
+but because of various possible attacks, EME1 is the preferred
+encoding. EME1 requires the use of a hash function: unless a competent
+applied cryptographer tells you otherwise, you should use SHA-256 or
+SHA-512.
+
+Don't use ``Raw'' encoding unless you need it for backward
+compatibility with old protocols. There are many possible attacks
+against both ElGamal and RSA when they are used in this way.
+
+\subsection{Signatures}
+
+The signature algorithms look quite a bit like the hash functions. You
+can repeatedly call \function{update}, giving more and more of a
+message you wish to sign, and then call \function{signature}, which
+will return a signature for that message. If you want to do it all in
+one shot, call \function{sign\_message}, which will just call
+\function{update} with its argument and then return whatever
+\function{signature} returns. Generating a signature requires random
+numbers with some schemes, so \function{signature} and
+\function{sign\_message} both take a \type{RandomNumberGenerator\&}.
+
+You can validate a signature by updating the verifier class, and finally seeing
+the if the value returned from \function{check\_signature} is true (you pass
+the supposed signature to the \function{check\_signature} function as a byte
+array and a length or as a \type{MemoryRegion<byte>}). There is another
+function, \function{verify\_message}, which takes a pair of byte array/length
+pairs (or a pair of \type{MemoryRegion<byte>} objects), the first of which is
+the message, the second being the (supposed) signature. It returns true if the
+signature is valid and false otherwise.
+
+Available public key signature algorithms in Botan are RSA, DSA,
+Nyberg-Rueppel, and Rabin-Williams. Signature encoding methods include EMSA1,
+EMSA2, EMSA3, EMSA4, and Raw. All of them, except Raw, take a parameter naming
+a message digest function to hash the message with. Raw actually signs the
+input directly; if the message is too big, the signing operation will fail. Raw
+is not useful except in very specialized applications.
+
+There are various interactions that make certain encoding schemes and signing
+algorithms more or less useful.
+
+EMSA2 is the usual method for encoding Rabin-William signatures, so for
+compatibility with other implementations you may have to use that. EMSA4 (also
+called PSS), also works with Rabin-Williams. EMSA1 and EMSA3 do \emph{not} work
+with Rabin-Williams.
+
+RSA can be used with any of the available encoding methods. EMSA4 is by far the
+most secure, but is not (as of now) widely implemented. EMSA3 (also called
+``EMSA-PKCS1-v1\_5'') is commonly used with RSA (for example in SSL). EMSA1
+signs the message digest directly, without any extra padding or encoding. This
+may be useful, but is not as secure as either EMSA3 or EMSA4. EMSA2 may be used
+but is not recommended.
+
+For DSA and Nyberg-Rueppel, you should use EMSA1. None of the other encoding
+methods are particularly useful for these algorithms.
+
+\subsection{Key Agreement}
+
+You can get a hold of a \type{PK\_Key\_Agreement\_Scheme} object by calling
+\function{get\_pk\_kas} with a key that is of a type that supports key
+agreement (such as a Diffie-Hellman key stored in a \type{DH\_PrivateKey}
+object), and the name of a key derivation function. This can be ``Raw'',
+meaning the output of the primitive itself is returned as the key, or
+``KDF1(hash)'' or ``KDF2(hash)'' where ``hash'' is any string you happen to
+like (hopefully you like strings like ``SHA-256'' or ``RIPEMD-160''), or
+``X9.42-PRF(keywrap)'', which uses the PRF specified in ANSI X9.42. It takes
+the name or OID of the key wrap algorithm that will be used to encrypt a
+content encryption key.
+
+How key agreement generally works is that you trade public values with some
+other party, and then each of you runs a computation with the other's value and
+your key (this should return the same result to both parties). This computation
+can be called by using \function{derive\_key} with either a byte array/length
+pair, or a \type{SecureVector<byte>} than holds the public value of the other
+party. The last argument to either call is a number that specifies how long a
+key you want.
+
+Depending on the key derivation function you're using, you many not
+\emph{actually} get back a key of that size. In particular, ``Raw'' will return
+a number about the size of the Diffie-Hellman modulus, and KDF1 can only return
+a key that is the same size as the output of the hash. KDF2, on the other
+hand, will always give you a key exactly as long as you request, regardless of
+the underlying hash used with it. The key returned is a \type{SymmetricKey},
+ready to pass to a block cipher, MAC, or other symmetric algorithm.
+
+The public value that should be used can be obtained by calling
+\function{public\_data}, which exists for any key that is associated with a
+key agreement algorithm. It returns a \type{SecureVector<byte>}.
+
+``KDF2(SHA-256)'' is by far the preferred algorithm for key derivation
+in new applications. The X9.42 algorithm may be useful in some
+circumstances, but unless you need X9.42 compatibility, KDF2 is easier
+to use.
+
+There is a Diffie-Hellman example included in the distribution, which you may
+want to examine.
+
+\subsection{Importing and Exporting PK Keys}
+
+[This section mentions \type{Pipe} and \type{DataSource}, which is not covered
+until later in the manual. Please read those sections for more about
+\type{Pipe} and \type{DataSource} and their uses.]
+
+There are many, many different (often conflicting) standards surrounding public
+key cryptography. There is, thankfully, only two major standards surrounding
+the representation of a public or private key: X.509 (for public keys), and
+PKCS \#8 (for private keys). Other crypto libraries, like OpenSSL and B-SAFE,
+also support these formats, so you can easily exchange keys with software that
+doesn't use Botan.
+
+In addition to ``plain'' public keys, Botan also supports X.509 certificates.
+These are documented in the section ``Certificate Handling'', later in this
+manual.
+
+\subsubsection{Public Keys}
+
+The interfaces for doing either of these are quite similar. Let's look at the
+X.509 stuff first:
+\begin{verbatim}
+namespace X509 {
+ void encode(const X509_PublicKey& key, Pipe& out, X509_Encoding enc = PEM);
+ std::string PEM_encode(const X509_PublicKey& out);
+
+ X509_PublicKey* load_key(DataSource& in);
+ X509_PublicKey* load_key(const std::string& file);
+ X509_PublicKey* load_key(const SecureVector<byte>& buffer);
+}
+\end{verbatim}
+
+Basically, \function{X509::encode} will take an \type{X509\_PublicKey}
+(as of now, that's any RSA, DSA, or Diffie-Hellman key) and encodes it
+using \arg{enc}, which can be either \type{PEM} or
+\type{RAW\_BER}. Using \type{PEM} is \emph{highly} recommended for
+many reasons, including compatibility with other software, for
+transmission over 8-bit unclean channels, because it can be identified
+by a human without special tools, and because it sometimes allows more
+sane behavior of tools that process the data. It will place the
+encoding into \arg{out}. Remember that if you have just created the
+\type{Pipe} that you are passing to \function{X509::encode}, you need
+to call \function{start\_msg} first. Particularly with public keys,
+about 99\% of the time you just want to PEM encode the key and then
+write it to a file or something. In this case, it's probably easier to
+use \function{X509::PEM\_encode}. This function will simply return the
+PEM encoding of the key as a \type{std::string}.
+
+For loading a public key, the preferred method is one of the variants
+of \function{load\_key}. This function will return a newly allocated
+key based on the data from whatever source it is using (assuming, of
+course, the source is in fact storing a representation of a public
+key). The encoding used (PEM or BER) need not be specified; the format
+will be detected automatically. The key is allocated with
+\function{new}, and should be released with \function{delete} when you
+are done with it. The first takes a generic \type{DataSource} that
+you have to allocate~--~the others are simple wrapper functions that
+take either a filename or a memory buffer.
+
+So what can you do with the return value of \function{load\_key}? On
+its own, a \type{X509\_PublicKey} isn't particularly useful; you can't
+encrypt messages or verify signatures, or much else. But, using
+\function{dynamic\_cast}, you can figure out what kind of operations
+the key supports. Then, you can cast the key to the appropriate type
+and pass it to a higher-level class. For example:
+
+\begin{verbatim}
+ /* Might be RSA, might be ElGamal, might be ... */
+ X509_PublicKey* key = X509::load_key("pubkey.asc");
+ /* You MUST use dynamic_cast to convert, because of virtual bases */
+ PK_Encrypting_Key* enc_key = dynamic_cast<PK_Encrypting_Key*>(key);
+ if(!enc_key)
+ throw Some_Exception();
+ PK_Encryptor* enc = get_pk_encryptor(*enc_key, "EME1(SHA-256)");
+ SecureVector<byte> cipher = enc->encrypt(some_message, size_of_message);
+\end{verbatim}
+
+\subsubsection{Private Keys}
+
+There are two different options for private key import/export. The first is a
+plaintext version of the private key. This is supported by the following
+functions:
+
+\begin{verbatim}
+namespace PKCS8 {
+ void encode(const PKCS8_PrivateKey& key, Pipe& to, X509_Encoding enc = PEM);
+
+ std::string PEM_encode(const PKCS8_PrivateKey& key);
+}
+\end{verbatim}
+
+These functions are basically the same as the X.509 functions described
+previously. The only difference is that they take a \type{PKCS8\_PrivateKey}
+type (which, again, can be either RSA, DSA, or Diffie-Hellman, but this time
+the key must be a private key). In most situations, using these is a bad idea,
+because anyone can come along and grab the private key without having to know
+any passwords or other secrets. Unless you have very particular security
+requirements, always use the versions that encrypt the key based on a
+passphrase. For importing, the same functions can be used for encrypted and
+unencrypted keys.
+
+The other way to export a PKCS \#8 key is to first encode it in the same manner
+as done above, then encrypt it (using a passphrase and the techniques of PKCS
+\#5), and store the whole thing into another structure. This method is
+definitely preferred, since otherwise the private key is unprotected. The
+following functions support this technique:
+
+\begin{verbatim}
+namespace PKCS8 {
+ void encrypt_key(const PKCS8_PrivateKey& key, Pipe& out,
+ std::string passphrase, std::string pbe = "",
+ X509_Encoding enc = PEM);
+
+ std::string PEM_encode(const PKCS8_PrivateKey& key, std::string passphrase,
+ std::string pbe = "");
+}
+\end{verbatim}
+
+To export an encrypted private key, call \function{PKCS8::encrypt\_key}. The
+\arg{key}, \arg{out}, and \arg{enc} arguments are similar in usage to the ones
+for \function{PKCS8::encode}. As you might notice, there are two new arguments
+for \function{PKCS8::encrypt\_key}, however. The first is a passphrase (which
+you presumably got from a user somehow). This will be used to encrypt the key.
+The second new argument is \arg{pbe}; this specifies a particular password
+based encryption (or PBE) algorithm.
+
+The \function{PEM\_encode} version shown here is similar to the one that
+doesn't take a passphrase. Essentially it encrypts the key (using the default
+PBE algorithm), and then returns a C++ string with the PEM encoding of the key.
+
+If \arg{pbe} is blank, then the default algorithm (controlled by the
+``base/default\_pbe'' option) will be used. As shipped, this default is
+``PBE-PKCS5v20(SHA-1,TripleDES/CBC)'' . This is among the more secure options
+of PKCS \#5, and is widely supported among implementations of PKCS \#5 v2.0. It
+offers 168 bits of security against attacks, which should be more that
+sufficient. If you need compatibility with systems that only support PKCS \#5
+v1.5, pass ``PBE-PKCS5v15(MD5,DES/CBC)'' as \arg{pbe}. However, be warned that
+this PBE algorithm only has 56 bits of security against brute force attacks. As
+of 1.4.5, all three keylengths of AES are also available as options, which can
+be used with by specifying a PBE algorithm of
+``PBE-PKCS5v20(SHA-1,AES-256/CBC)'' (or ``AES-128'' or ``AES-192''). Support
+for AES is slightly non-standard, and some applications or libraries might not
+handle it. It is known that OpenSSL (0.9.7 and later) do handle AES for private
+key encryption.
+
+There may be some strange programs out there that support the v2.0 extensions
+to PBES1 but not PBES2; if you need to inter-operate with a program like that,
+use ``PBE-PKCS5v15(MD5,RC2/CBC)''. For example, OpenSSL supports this format
+(though since it also supports the v2.0 schemes, there is no reason not to just
+use TripleDES or AES). This scheme uses a 64-bit key that, while
+significantly better than a 56-bit key, is a bit too small for comfort.
+
+Last but not least, there are some functions that are basically identical to
+\function{X509::load\_key} that will load, and possibly decrypt, a PKCS \#8
+private key:
+
+\begin{verbatim}
+namespace PKCS8 {
+ PKCS8_PrivateKey* load_key(DataSource& in,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+ PKCS8_PrivateKey* load_key(DataSource& in,
+ RandomNumberGenerator& rng,
+ std::string passphrase = "");
+
+ PKCS8_PrivateKey* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+ PKCS8_PrivateKey* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& passphrase = "");
+}
+\end{verbatim}
+
+The versions that take \type{std::string} \arg{passphrase}s are primarily for
+compatibility, but they are useful in limited circumstances. The
+\type{User\_Interface} versions are how \function{load\_key} is actually
+implemented, and provides for much more flexibility. Essentially, if the
+passphrase given to the function is not correct, then an exception is thrown
+and that is that. However, if you pass in an UI object instead, then the UI
+object can keep asking the user for the passphrase until they get it right (or
+until they cancel the action, though the UI interface). A
+\type{User\_Interface} has very little to do with talking to users; it's just a
+way to glue together Botan and whatever user interface you happen to be
+using. You can think of it as a user interface interface. The default
+\type{User\_Interface} is actually very dumb, and effectively acts just like
+the versions taking the \type{std::string}.
+
+All versions need access to a \type{RandomNumberGenerator} in order to
+perform probabilistic tests on the loaded key material.
+
+After loading a key, you can use \function{dynamic\_cast} to find out what
+operations it supports, and use it appropriately. Remember to \function{delete}
+it once you are done with it.
+
+\subsubsection{Limitations}
+
+As of now Nyberg-Rueppel and Rabin-Williams keys cannot be imported or
+exported, because they have no official ASN.1 OID or definition. ElGamal keys
+can (as of Botan 1.3.8) be imported and exported, but the only other
+implementation that supports the format is Peter Gutmann's Cryptlib. If you
+can help it, stick to RSA and DSA.
+
+\emph{Note}: Currently NR and RW are given basic ASN.1 key formats (which
+mirror DSA and RSA, respectively), which means that, if they are assigned an
+OID, they can be imported and exported just as easily as RSA and DSA. You can
+assign them an OID by putting a line in a Botan configuration file, calling
+\function{OIDS::add\_oid}, or editing \filename{src/policy.cpp}. Be warned that
+it is possible that a future version will use a format that is different from
+the current one (\ie, a newly standardized format).
+
+\pagebreak
+\section{Certificate Handling}
+
+A certificate is essentially a binding between some identifying information of
+a person or other entity (called a \emph{subject}) and a public key. This
+binding is asserted by a signature on the certificate, which is placed there by
+some authority (the \emph{issuer}) that at least claims that it knows the
+subject named in the certificate really ``owns'' the private key
+corresponding to the public key in the certificate.
+
+The major certificate format in use today is X.509v3, designed by ISO and
+further hacked on by dozens (hundreds?) of other organizations.
+
+When working with certificates, the main class to remember is
+\type{X509\_Certificate}. You can read an object of this type, but you can't
+create one on the fly; a CA object is necessary for actually making a new
+certificate. So for the most part, you only have to worry about reading them
+in, verifying the signatures, and getting the bits of data in them (most
+commonly the public key, and the information about the user of that key). An
+X.509v3 certificate can contain a literally infinite number of items related to
+all kinds of things. Botan doesn't support a lot of them, simply because nobody
+uses them and they're an impossible mess to work with. This section only
+documents the most commonly used ones of the ones that are supported; for the
+rest, read \filename{x509cert.h} and \filename{asn1\_obj.h} (which has the
+definitions of various common ASN.1 constructs used in X.509).
+
+\subsection{So what's in an X.509 certificate?}
+
+Obviously, you want to be able to get the public key. This is achieved by
+calling the member function \function{subject\_public\_key}, which will return
+a \type{X509\_PublicKey*}. As to what to do with this, read about
+\function{load\_key} in the section ``Importing and Exporting PK Keys''. In the
+general case, this could be any kind of public key, though 99\% of the time it
+will be an RSA key. However, Diffie-Hellman and DSA keys are also supported, so
+be careful about how you treat this. It is also a wise idea to examine the
+value returned by \function{constraints}, to see what uses the public key is
+approved for.
+
+The second major piece of information you'll want is the name/email/etc of the
+person to whom this certificate is assigned. Here is where things get a little
+nasty. X.509v3 has two (well, mostly just two $\ldots$) different places where
+you can stick information about the user: the \emph{subject} field, and in an
+extension called \emph{subjectAlternativeName}. The \emph{subject} field is
+supposed to only included the following information: country, organization
+(possibly), an organizational sub-unit name (possibly), and a so-called common
+name. The common name is usually the name of the person, or it could be a title
+associated with a position of some sort in the organization. It may also
+include fields for state/province and locality. What exactly a locality is,
+nobody knows, but it's usually given as a city name.
+
+Botan doesn't currently support any of the Unicode variants used in ASN.1
+(UTF-8, UCS-2, and UCS-4), any of which could be used for the fields in the
+DN. This could be problematic, particularly in Asia and other areas where
+non-ASCII characters are needed for most names. The UTF-8 and UCS-2 string
+types \emph{are} accepted (in fact, UTF-8 is used when encoding much of the
+time), but if any of the characters included in the string are not in ISO
+8859-1 (\ie 0 \ldots 255), an exception will get thrown. Currently the
+\type{ASN1\_String} type holds its data as ISO 8859-1 internally (regardless
+of local character set); this would have to be changed to hold UCS-2 or UCS-4
+in order to support Unicode (also, many interfaces in the X.509 code would have
+to accept or return a \type{std::wstring} instead of a \type{std::string}).
+
+Like the distinguished names, subject alternative names can contain a lot of
+things that Botan will flat out ignore (most of which you would never actually
+want to use). However, there are three very useful pieces of information that
+this extension might hold: an email address (``person@site1.com''), a DNS name
+(``somehost.site2.com''), or a URI (``http://www.site3.com'').
+
+So, how to get the information? Simply call \function{subject\_info} with the
+name of the piece of information you want, and it will return a
+\type{std::string} that is either empty (signifying that the certificate
+doesn't have this information), or has the information requested. There are
+several names for each possible item, but the most easily readable ones are:
+``Name'', ``Country'', ``Organization'', ``Organizational Unit'', ``Locality'',
+``State'', ``RFC822'', ``URI'', and ``DNS''. These values are returned as a
+\type{std::string}.
+
+You can also get information about the issuer of the certificate in the same
+way, using \function{issuer\_info}.
+
+\subsubsection{X.509v3 Extensions}
+
+X.509v3 specifies a large number of possible extensions. Botan supports some,
+but by no means all of them. This section lists which ones are supported, and
+notes areas where there may be problems with the handling. You have to be
+pretty familiar with X.509 in order to understand what this is talking about.
+
+\begin{list}{$\cdot$}
+ \item Key Usage and Extended Key Usage: No problems known.
+ \item
+
+ \item Basic Constraints: No problems known. The default for a v1/v2
+ certificate is assume it's a CA if and only if the option
+ ``x509/default\_to\_ca'' is set. A v3 certificate is marked as a CA if
+ (and only if) the basic constraints extension is present and set for a
+ CA cert.
+
+ \item Subject Alternative Names: Only the ``rfc822Name'', ``dNSName'', and
+ ``uniformResourceIdentifier'' fields will be stored; all others are
+ ignored.
+
+ \item Issuer Alternative Names: Same restrictions as the Subject Alternative
+ Names extension. New certificates generated by Botan never include the
+ issuer alternative name.
+
+ \item Authority Key Identifier: Only the version using KeyIdentifier is
+ supported. If the GeneralNames version is used and the extension is
+ critical, an exception is thrown. If both the KeyIdentifier and
+ GeneralNames versions are present, then the KeyIdentifier will be
+ used, and the GeneralNames ignored.
+
+ \item Subject Key Identifier: No problems known.
+\end{list}
+
+\subsubsection{Revocation Lists}
+
+It will occasionally happen that a certificate must be revoked before its
+expiration date. Examples of this happening include the private key being
+compromised, or the user to which it has been assigned leaving an
+organization. Certificate revocation lists are an answer to this problem
+(though online certificate validation techniques are starting to become
+somewhat more popular). Essentially, every once in a while the CA will release
+a CRL, listing all certificates that have been revoked. Also included is
+various pieces of information like what time a particular certificate was
+revoked, and for what reason. In most systems, it is wise to support some form
+of certificate revocation, and CRLs handle this fairly easily.
+
+For most users, processing a CRL is quite easy. All you have to do is call the
+constructor, which will take a filename (or a \type{DataSource\&}). The CRLs
+can either be in raw BER/DER, or in PEM format; the constructor will figure out
+which format without any extra information. For example:
+
+\begin{verbatim}
+ X509_CRL crl1("crl1.der");
+
+ DataSource_Stream in("crl2.pem");
+ X509_CRL crl2(in);
+\end{verbatim}
+
+After that, pass the \type{X509\_CRL} object to a \type{X509\_Store} object
+with \type{X509\_Code} \function{add\_crl}(\type{X509\_CRL}), and all future
+verifications will take into account the certificates listed, assuming
+\function{add\_crl} returns \type{VERIFIED}. If it doesn't return
+\type{VERIFIED}, then the return value is an error code signifying that the CRL
+could not be processed due to some problem (which could range from the issuing
+certificate not being found, to the CRL having some format problem). For more
+about the \type{X509\_Store} API, read the section later in this chapter.
+
+\subsection{Reading Certificates}
+
+\type{X509\_Certificate} has two constructors, each of which takes a source of
+data; a filename to read, and a \type{DataSource\&}.
+
+\subsection{Storing and Using Certificates}
+
+If you read a certificate, you probably want to verify the signature on
+it. However, consider that to do so, we may have to verify the signature on the
+certificate that we used to verify the first certificate, and on and on until
+we hit the top of the certificate tree somewhere. It would be a might huge pain
+to have to handle all of that manually in every application, so there is
+something that does it for you: \type{X509\_Store}.
+
+This is a pretty easy thing to use. The basic operations are: put certificates
+and CRLs into it, search for certificates, and attempt to verify
+certificates. That's about it. In the future, there will be support for online
+retrieval of certificates and CRLs (\eg with the HTTP cert-store interface
+currently under consideration by PKIX).
+
+\subsubsection{Adding Certificates}
+
+You can add new certificates to a certificate store using any of these
+functions:
+
+\function{add\_cert}(\type{const X509\_Certificate\&} \arg{cert},
+ \type{bool} \arg{trusted} \type{= false})
+
+\function{add\_certs}(\type{DataSource\&} \arg{source})
+
+\function{add\_trusted\_certs}(\type{DataSource\&} \arg{source})
+
+The versions that take a \type{DataSource\&} will add all the certificates
+that it can find in that source.
+
+All of them add the cert(s) to the store. The 'trusted' certificates are the
+ones that you have some reason to trust are genuine. For example, say your
+application is working with certificates that are owned by employees of some
+company, and all of their certificates are signed by the company CA, whose
+certificate is in turned signed by a commercial root CA. What you would then do
+is include the certificate of the commercial CA with your application, and read
+it in as a trusted certificate. From there, you could verify the company CA's
+certificate, and then use that to verify the end user's certificates. Only
+self-signed certificates may be considered trusted.
+
+\subsubsection{Adding CRLs}
+
+\type{X509\_Code} \function{add\_crl}(\type{const X509\_CRL\&} \arg{crl});
+
+This will process the CRL and mark the revoked certificates. This will also
+work if a revoked certificate is added to the store sometime after the CRL is
+processed. The function can return an error code (listed later), or will return
+\type{VERIFIED} if everything completed successfully.
+
+\subsubsection{Storing Certificates}
+
+You can output a set of certificates by calling \function{PEM\_encode}, which
+will return a \type{std::string} containing each of the certificates in the
+store, PEM encoded and concatenated. This simple format can easily be read by
+both Botan and other libraries/applications.
+
+\subsubsection{Searching for Certificates}
+
+You can find certificates in the store with a series of functions contained
+in the \function{X509\_Store\_Search} namespace:
+
+\begin{verbatim}
+namespace X509_Store_Search {
+std::vector<X509_Certificate> by_email(const X509_Store& store,
+ const std::string& email_addr);
+std::vector<X509_Certificate> by_name(const X509_Store& store,
+ const std::string& name);
+std::vector<X509_Certificate> by_dns(const X509_Store&,
+ const std::string& dns_name);
+}
+\end{verbatim}
+
+These functions will return a (possibly empty) vector of certificates from
+\arg{store} matching your search criteria. The email address and DNS name
+searches are case-insensitive but are sensitive to extra whitespace and so
+on. The name search will do case-insensitive substring matching, so, for
+example, calling \function{X509\_Store\_Search::by\_name}(\arg{your\_store},
+``dob'') will return certificates for ``J.R. 'Bob' Dobbs'' and
+``H. Dobbertin'', assuming both of those certificates are in \arg{your\_store}.
+
+You could then display the results to a user, and allow them to select the
+appropriate one. Searching using an email address as the key is usually more
+effective than the name, since email addresses are rarely shared.
+
+\subsubsection{Certificate Stores}
+
+An object of type \type{Certificate\_Store} is a generalized interface to an
+external source for certificates (and CRLs). Examples of such a store would be
+one that looked up the certificates in a SQL database, or by contacting a CGI
+script running on a HTTP server. There are currently three mechanisms for
+looking up a certificate, and one for retrieving CRLs. By default, most of
+these mechanisms will simply return an empty \type{std::vector} of
+\type{X509\_Certificate}. This storage mechanism is \emph{only} queried when
+doing certificate validation: it allows you to distribute only the root key
+with an application, and let some online method handle getting all the other
+certificates that are needed to validate an end entity certificate. In
+particular, the search routines will not attempt to access the external
+database.
+
+The three certificate lookup methods are \function{by\_SKID} (Subject Key
+Identifier), \function{by\_name} (the CommonName DN entry), and
+\function{by\_email} (stored in either the distinguished name, or in a
+subjectAlternativeName extension). The name and email versions take a
+\type{std::string}, while the SKID version takes a \type{SecureVector<byte>}
+containing the subject key identifier in raw binary. You can choose not to
+implement \function{by\_name} or \function{by\_email}, but \function{by\_SKID}
+is mandatory to implement, and, currently, is the only version that is used by
+\type{X509\_Store}.
+
+Finally, there is a method for finding CRLs, called \function{get\_crls\_for},
+that takes an \type{X509\_Certificate} object, and returns a
+\type{std::vector} of \type{X509\_CRL}. While generally there will be only one
+CRL, the use of the vector makes it easy to return no CRLs (\eg, if the
+certificate store doesn't support retrieving them), or return multiple ones
+(for example, if the certificate store can't determine precisely which key was
+used to sign the certificate). Implementing the function is optional, and by
+default will return no CRLs. If it is available, it will be used by
+\type{X509\_CRL}.
+
+As for actually using such a store, you have to tell \type{X509\_Store} about
+it, by calling the \type{X509\_Store} member function
+
+\function{add\_new\_certstore}(\type{Certificate\_Store}* \arg{new\_store})
+
+The argument, \arg{new\_store}, will be deleted by \type{X509\_Store}'s
+destructor, so make sure to allocate it with \function{new}.
+
+\subsubsection{Verifying Certificates}
+
+There is a single function in \type{X509\_Store} related to verifying a
+certificate:
+
+\type{X509\_Code}
+\function{validate\_cert}(\type{const X509\_Certificate\&} \arg{cert},
+ \type{Cert\_Usage} \arg{usage} = \type{ANY})
+
+To sum things up simply, it returns \type{VERIFIED} if the certificate can
+safely be considered valid for the usage(s) described by \arg{usage}, and an
+error code if it is not. Naturally, things are a bit more complicated than
+that. The enum \type{Cert\_Usage} is defined inside the \type{X509\_Store}
+class, it (currently) can take on any of the values \type{ANY} (any usage is
+OK), \type{TLS\_SERVER} (for SSL/TLS server authentication), \type{TLS\_CLIENT}
+(for SSL/TLS client authentication), \type{CODE\_SIGNING},
+\type{EMAIL\_PROTECTION} (email encryption, usually this means S/MIME),
+\type{TIME\_STAMPING} (in theory any time stamp application, usually IETF
+PKIX's Time Stamp Protocol), or \type{CRL\_SIGNING}. Note that Microsoft's code
+signing system, certainly the most widely used, uses a completely different
+(and basically undocumented) method for marking certificates for code signing.
+
+First, how does it know if a certificate is valid? Basically, a certificate is
+valid if both of the following hold: a) the signature in the certificate can be
+verified using the public key in the issuer's certificate, and b) the issuer's
+certificate is a valid CA certificate. Note that this definition is
+recursive. We get out of this by ``bottoming out'' when we reach a certificate
+that we consider trusted. In general this will either be a commercial root CA,
+or an organization or application specific CA.
+
+There are actually a few other restrictions (validity periods, key usage
+restrictions, etc), but the above summarizes the major points of the validation
+algorithm. In theory, Botan implements the certificate path validation
+algorithm given in RFC 2459, but in practice it does not (yet), because we
+don't support the X.509v3 policy or name constraint extensions.
+
+Possible values for \arg{usage} are \type{TLS\_SERVER}, \type{TLS\_CLIENT},
+\type{CODE\_SIGNING}, \type{EMAIL\_PROTECTION}, \type{CRL\_SIGNING}, and
+\type{TIME\_STAMPING}, and \type{ANY}. The default \type{ANY} does not mean
+valid for any use, it means ``is valid for some usage''. This is generally
+fine, and in fact requiring that a random certificate support a particular
+usage will likely result in a lot of failures, unless your application is very
+careful to always issue certificates with the proper extensions, and you never
+use certificates generated by other apps.
+
+Return values for \function{validate\_cert} (and \function{add\_crl}) include:
+
+\begin{list}{$\cdot$}
+ \item VERIFIED: The certificate is valid for the specified use.
+ \item
+ \item INVALID\_USAGE: The certificate cannot be used for the specified use.
+
+ \item CANNOT\_ESTABLISH\_TRUST: The root certificate was not marked as
+ trusted.
+ \item CERT\_CHAIN\_TOO\_LONG: The certificate chain exceeded the length
+ allowed by a basicConstraints extension.
+ \item SIGNATURE\_ERROR: An invalid signature was found
+ \item POLICY\_ERROR: Some problem with the certificate policies was found.
+
+ \item CERT\_FORMAT\_ERROR: Some format problem was found in a certificate.
+ \item CERT\_ISSUER\_NOT\_FOUND: The issuer of a certificate could not be
+ found.
+ \item CERT\_NOT\_YET\_VALID: The certificate is not yet valid.
+ \item CERT\_HAS\_EXPIRED: The certificate has expired.
+ \item CERT\_IS\_REVOKED: The certificate has been revoked.
+
+ \item CRL\_FORMAT\_ERROR: Some format problem was found in a CRL.
+ \item CRL\_ISSUER\_NOT\_FOUND: The issuer of a CRL could not be found.
+ \item CRL\_NOT\_YET\_VALID: The CRL is not yet valid.
+ \item CRL\_HAS\_EXPIRED: The CRL has expired.
+
+ \item CA\_CERT\_CANNOT\_SIGN: The CA certificate found does not have an
+ contain a public key that allows signature verification.
+ \item CA\_CERT\_NOT\_FOR\_CERT\_ISSUER: The CA cert found is not allowed to
+ issue certificates.
+ \item CA\_CERT\_NOT\_FOR\_CRL\_ISSUER: The CA cert found is not allowed to
+ issue CRLs.
+
+ \item UNKNOWN\_X509\_ERROR: Some other error occurred.
+
+\end{list}
+
+\subsection{Certificate Authorities}
+
+Setting up a CA for X.509 certificates is actually probably the easiest thing
+to do related to X.509. A CA is represented by the type \type{X509\_CA}, which
+can be found in \filename{x509\_ca.h}. A CA always needs its own certificate,
+which can either be a self-signed certificate (see below on how to create one)
+or one issued by another CA (see the section on PKCS \#10 requests). Creating
+a CA object is done by the following constructor:
+
+\begin{verbatim}
+ X509_CA(const X509_Certificate& cert, const PKCS8_PrivateKey& key);
+\end{verbatim}
+
+The private key is the private key corresponding to the public key in the
+CA's certificate.
+
+Generally, requests for new certificates are supplied to a CA in the form on
+PKCS \#10 certificate requests (called a \type{PKCS10\_Request} object in
+Botan). These are decoded in a similar manner to
+certificates/CRLs/etc. Generally, a request is vetted by humans (who somehow
+verify that the name in the request corresponds to the name of the person who
+requested it), and then signed by a CA key, generating a new certificate.
+
+\begin{verbatim}
+ X509_Certificate sign_request(const PKCS10_Request&) const;
+\end{verbatim}
+
+\subsubsection{Generating CRLs}
+
+As mentioned previously, the ability to process CRLs is highly important in
+many PKI systems. In fact, according to strict X.509 rules, you must not
+validate any certificate if the appropriate CRLs are not available (though
+hardly any systems are that strict). In any case, a CA should have a valid CRL
+available at all times.
+
+Of course, you might be wondering what to do if no certificates have been
+revoked. In fact, CRLs can be issued without any actually revoked certificates
+- the list of certs will simply be empty. To generate a new, empty CRL, just
+call \type{X509\_CRL}
+\function{X509\_CA::new\_crl}(\type{u32bit}~\arg{seconds}~=~0)~--~it will
+create a new, empty, CRL. If \arg{seconds} is the default 0, then the normal
+default CRL next update time (the value of the ``x509/crl/next\_update'') will
+be used. If not, then \arg{seconds} specifies how long (in seconds) it will be
+until the CRL's next update time (after this time, most clients will reject the
+CRL as too old).
+
+On the other hand, you may have issued a CRL before. In that case, you will
+want to issue a new CRL that contains all previously revoked
+certificates, along with any new ones. This is done by calling the
+\type{X509\_CA} member function
+\function{update\_crl}(\type{X509\_CRL}~\arg{old\_crl},
+\type{std::vector<CRL\_Entry>}~\arg{new\_revoked},
+\type{u32bit}~\arg{seconds}~=~0), where \type{X509\_CRL} is the last CRL this
+CA issued, and \arg{new\_revoked} is a list of any newly revoked certificates.
+The function returns a new \type{X509\_CRL} to make available for clients. The
+semantics for the \arg{seconds} argument is the same as \function{new\_crl}.
+
+The \type{CRL\_Entry} type is a structure that contains, at a minimum, the
+serial number of the revoked certificate. As serial numbers are never repeated,
+the pairing of an issuer and a serial number (should) distinctly identify any
+certificate. In this case, we represent the serial number as a
+\type{SecureVector<byte>} called \arg{serial}. There are two additional
+(optional) values, an enumeration called \type{CRL\_Code} that specifies the
+reason for revocation (\arg{reason}), and an object that represents the time
+that the certificate became invalid (if this information is known).
+
+If you wish to remove an old entry from the CRL, insert a new entry for the
+same cert, with a \arg{reason} code of \type{DELETE\_CRL\_ENTRY}. For example,
+if a revoked certificate has expired 'normally', there is no reason to continue
+to explicitly revoke it, since clients will reject the cert as expired in any
+case.
+
+\subsubsection{Self-Signed Certificates}
+
+Generating a new self-signed certificate can often be useful, for example when
+setting up a new root CA, or for use in email applications. In this case,
+the solution is summed up simply as:
+
+\begin{verbatim}
+namespace X509 {
+ X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
+ const PKCS8_PrivateKey& key);
+}
+\end{verbatim}
+
+Where \arg{key} is obviously the private key you wish to use (the public key,
+used in the certificate itself, is extracted from the private key), and
+\arg{opts} is an structure that has various bits of information that will be
+used in creating the certificate (this structure, and its use, is discussed
+below). This function is found in the header \filename{x509self.h}. There is an
+example of using this function in the \filename{self\_sig} example.
+
+\subsubsection{Creating PKCS \#10 Requests}
+
+Also in \filename{x509self.h}, there is a function for generating new PKCS \#10
+certificate requests.
+
+\begin{verbatim}
+namespace X509 {
+ PKCS10_Request create_cert_req(const X509_Cert_Options&,
+ const PKCS8_PrivateKey&);
+}
+\end{verbatim}
+
+This function acts quite similarly to \function{create\_self\_signed\_cert},
+except it instead returns a PKCS \#10 certificate request. After creating it,
+one would typically transmit it to a CA, who signs it and returns a freshly
+minted X.509 certificate. There is an example of using this function in the
+\filename{pkcs10} example.
+
+\subsubsection{Certificate Options}
+
+So what is this \type{X509\_Cert\_Options} thing we've been passing around?
+Basically, it's a bunch of information that will end up being stored into the
+certificate. This information comes in 3 major flavors: information about the
+subject (CA or end-user), the validity period of the certificate, and
+restrictions on the usage of the certificate.
+
+First and foremost is a number of \type{std::string} members, which contains
+various bits of information about the user: \arg{common\_name},
+\arg{serial\_number}, \arg{country}, \arg{organization}, \arg{org\_unit},
+\arg{locality}, \arg{state}, \arg{email}, \arg{dns\_name}, and \arg{uri}. As
+many of these as possible should be filled it (especially an email address),
+though the only required ones are \arg{common\_name} and \arg{country}.
+
+There is another value that is only useful when creating a PKCS \#10 request,
+which is called \arg{challenge}. This is a challenge password, which you can
+later use to request certificate revocation (\emph{if} the CA supports doing
+revocations in this manner).
+
+Then there is the validity period; these are set with \function{not\_before}
+and \function{not\_after}. Both of these functions also take a
+\type{std::string}, which specifies when the certificate should start being
+valid, and when it should stop being valid. If you don't set the starting
+validity period, it will automatically choose the current time. If you don't
+set the ending time, it will choose the starting time plus a default time
+period. The arguments to these functions specify the time in the following
+format: ``2002/11/27 1:50:14''. The time is in 24-hour format, and the date is
+encoded as year/month/day. The date must be specified, but you can omit the
+time or trailing parts of it, for example ``2002/11/27 1:50'' or
+``2002/11/27''.
+
+Lastly, you can set constraints on a key. The one you're mostly likely to want
+to use is to create (or request) a CA certificate, which can be done by calling
+the member function \function{CA\_key}. This should only be used when needed.
+
+Other constraints can be set by calling the member functions
+\function{add\_constraints} and \function{add\_ex\_constraints}. The first
+takes a \type{Key\_Constraints} value, and replaces any previously set
+value. If no value is set, then the certificate key is marked as being valid
+for any usage. You can set it to any of the following (for more than one
+usage, OR them together): \type{DIGITAL\_SIGNATURE}, \type{NON\_REPUDIATION},
+\type{KEY\_ENCIPHERMENT}, \type{DATA\_ENCIPHERMENT}, \type{KEY\_AGREEMENT},
+\type{KEY\_CERT\_SIGN}, \type{CRL\_SIGN}, \type{ENCIPHER\_ONLY},
+\type{DECIPHER\_ONLY}. Many of these have quite special semantics, so you
+should either consult the appropriate standards document (such as RFC 3280), or
+simply not call \function{add\_constraints}, in which case the appropriate
+values will be chosen for you.
+
+The second function, \function{add\_ex\_constraints}, allows you to specify an
+OID that has some meaning with regards to restricting the key to particular
+usages. You can, if you wish, specify any OID you like, but there is a set of
+standard ones that other applications will be able to understand. These are
+the ones specified by the PKIX standard, and are named ``PKIX.ServerAuth'' (for
+TLS server authentication), ``PKIX.ClientAuth'' (for TLS client
+authentication), ``PKIX.CodeSigning'', ``PKIX.EmailProtection'' (most likely
+for use with S/MIME), ``PKIX.IPsecUser'', ``PKIX.IPsecTunnel'',
+``PKIX.IPsecEndSystem'', and ``PKIX.TimeStamping''. You can call
+\function{add\_ex\_constraints} any number of times~--~each new OID will be
+added to the list to include in the certificate.
+
+\pagebreak
+\section{The Low-Level Interface}
+
+Botan has two different interfaces. The one documented in this section is meant
+more for implementing higher-level types (see the section on filters, earlier in
+this manual) than for use by applications. Using it safely requires a solid
+knowledge of encryption techniques and best practices, so unless you know, for
+example, what CBC mode and nonces are, and why PKCS \#1 padding is important,
+you should avoid this interface in favor of something working at a higher level
+(such as the CMS interface).
+
+\subsection{Basic Algorithm Abilities}
+
+There are a small handful of functions implemented by most of Botan's
+algorithm objects. Among these are:
+
+\noindent
+\type{std::string} \function{name}():
+
+Returns a human-readable string of the name of this algorithm. Examples of
+names returned are ``Blowfish'' and ``HMAC(MD5)''. You can turn names back into
+algorithm objects using the functions in \filename{lookup.h}.
+
+\noindent
+\type{void} \function{clear}():
+
+Clear out the algorithm's internal state. A block cipher object will ``forget''
+its key, a hash function will ``forget'' any data put into it, etc. Basically,
+the object will look exactly as it did when you initially allocated it.
+
+\noindent
+\function{clone}():
+
+This function is central to Botan's name-based interface. The \function{clone}
+has many different return types, such as \type{BlockCipher*} and
+\type{HashFunction*}, depending on what kind of object it is called on. Note
+that unlike Java's clone, this returns a new object in a ``pristine'' state;
+that is, operations done on the initial object before calling \function{clone}
+do not affect the initial state of the new clone.
+
+Cloned objects can (and should) be deallocated with the C++ \texttt{delete}
+operator.
+
+\subsection{Keys and IVs}
+
+Both symmetric keys and initialization values can simply be considered byte (or
+octet) strings. These are represented by the classes \type{SymmetricKey} and
+\type{InitializationVector}, which are subclasses of \type{OctetString}.
+
+Since often it's hard to distinguish between a key and IV, many things (such as
+key derivation mechanisms) return \type{OctetString} instead of
+\type{SymmetricKey} to allow its use as a key or an IV.
+
+\noindent
+\function{OctetString}(\type{u32bit} \arg{length}):
+
+This constructor creates a new random key of size \arg{length}.
+
+\noindent
+\function{OctetString}(\type{std::string} \arg{str}):
+
+The argument \arg{str} is assumed to be a hex string; it is converted to binary
+and stored. Whitespace is ignored.
+
+\noindent
+\function{OctetString}(\type{const byte} \arg{input}[], \type{u32bit}
+\arg{length}):
+
+This constructor simply copies its input.
+
+\subsection{Symmetrically Keyed Algorithms}
+
+Block ciphers, stream ciphers, and MACs all handle keys in pretty much the same
+way. To make this similarity explicit, all algorithms of those types are
+derived from the \type{SymmetricAlgorithm} base class. This type has three
+functions:
+
+\noindent
+\type{void} \function{set\_key}(\type{const byte} \arg{key}[], \type{u32bit}
+\arg{length}):
+
+Most algorithms only accept keys of certain lengths. If you attempt to call
+\function{set\_key} with a key length that is not supported, the exception
+\type{Invalid\_Key\_Length} will be thrown. There is also another version of
+\function{set\_key} that takes a \type{SymmetricKey} as an argument.
+
+\noindent
+\type{bool} \function{valid\_keylength}(\type{u32bit} \arg{length}) const:
+
+This function returns true if a key of the given length will be accepted by
+the cipher.
+
+There are also three constant data members of every \type{SymmetricAlgorithm}
+object, which specify exactly what limits there are on keys which that object
+can accept:
+
+MAXIMUM\_KEYLENGTH: The maximum length of a key. Usually, this is at most 32
+(256 bits), even if the algorithm actually supports more. In a few rare cases
+larger keys will be supported.
+
+MINIMUM\_KEYLENGTH: The minimum length of a key. This is at least 1.
+
+KEYLENGTH\_MULTIPLE: The length of the key must be a multiple of this value.
+
+In all cases, \function{set\_key} must be called on an object before any data
+processing (encryption, decryption, etc) is done by that object. If this is not
+done, the results are undefined -- that is to say, Botan reserves the right in
+this situation to do anything from printing a nasty, insulting message on the
+screen to dumping core.
+
+\subsection{Block Ciphers}
+
+Block ciphers implement the interface \type{BlockCipher}, found in
+\filename{base.h}, as well as the \type{SymmetricAlgorithm} interface.
+
+\noindent
+\type{void} \function{encrypt}(\type{const byte} \arg{in}[BLOCK\_SIZE],
+ \type{byte} \arg{out}[BLOCK\_SIZE]) const
+
+\noindent
+\type{void} \function{encrypt}(\type{byte} \arg{block}[BLOCK\_SIZE]) const
+
+These functions apply the block cipher transformation to \arg{in} and
+place the result in \arg{out}, or encrypts \arg{block} in place
+(\arg{in} may be the same as \arg{out}). BLOCK\_SIZE is a constant
+member of each class, which specifies how much data a block cipher can
+process at one time. Note that BLOCK\_SIZE is not a static class
+member, meaning you can (given a \type{BlockCipher*} named
+\arg{cipher}), call \verb|cipher->BLOCK_SIZE| to get the block size of
+that particular object. \type{BlockCipher}s have similar functions
+\function{decrypt}, which perform the inverse operation.
+
+\begin{verbatim}
+AES_128 cipher;
+SymmetricKey key(cipher.MAXIMUM_KEYLENGTH); // randomly created
+cipher.set_key(key);
+
+byte in[16] = { /* secrets */ };
+byte out[16];
+cipher.encrypt(in, out);
+\end{verbatim}
+
+\subsection{Stream Ciphers}
+
+Stream ciphers are somewhat different from block ciphers, in that encrypting
+data results in changing the internal state of the cipher. Also, you may
+encrypt any length of data in one go (in byte amounts).
+
+\noindent
+\type{void} \function{encrypt}(\type{const byte} \arg{in}[], \type{byte}
+\arg{out}[], \type{u32bit} \arg{length})
+
+\noindent
+\type{void} \function{encrypt}(\type{byte} \arg{data}[], \type{u32bit}
+\arg{length}):
+
+These functions encrypt the arbitrary length (well, less than 4 gigabyte long)
+string \arg{in} and place it into \arg{out}, or encrypts it in place in
+\arg{data}. The \function{decrypt} functions look just like
+\function{encrypt}.
+
+Stream ciphers implement the \type{SymmetricAlgorithm} interface.
+
+Some stream ciphers support random access to any point in their cipher
+stream. For such ciphers, calling \type{void} \function{seek}(\type{u32bit}
+\arg{byte}) will change the cipher's state so that it is as if the cipher had been
+keyed as normal, then encrypted \arg{byte} -- 1 bytes of data (so the next byte
+in the cipher stream is byte number \arg{byte}).
+
+\subsection{Hash Functions / Message Authentication Codes}
+
+Hash functions take their input without producing any output, only producing
+anything when all input has already taken place. MACs are very similar, but are
+additionally keyed. Both of these are derived from the base class
+\type{BufferedComputation}, which has the following functions.
+
+\noindent
+\type{void} \function{update}(\type{const byte} \arg{input}[], \type{u32bit}
+\arg{length})
+
+\noindent
+\type{void} \function{update}(\type{byte} \arg{input})
+
+\noindent
+\type{void} \function{update}(\type{const std::string \&} \arg{input})
+
+Updates the hash/mac calculation with \arg{input}.
+
+\noindent
+\type{void} \function{final}(\type{byte} \arg{out}[OUTPUT\_LENGTH])
+
+\noindent
+\type{SecureVector<byte>} \function{final}():
+
+Complete the hash/MAC calculation and place the result into \arg{out}.
+OUTPUT\_LENGTH is a public constant in each object that gives the length of the
+hash in bytes. After you call \function{final}, the hash function is reset to
+its initial state, so it may be reused immediately.
+
+The second method of using final is to call it with no arguments at all, as
+shown in the second prototype. It will return the hash/mac value in a memory
+buffer, which will have size OUTPUT\_LENGTH.
+
+There is also a pair of functions called \function{process}. They are
+essentially a combination of a single \function{update}, and \function{final}.
+Both versions return the final value, rather than placing it an array. Calling
+\function{process} with a single byte value isn't available, mostly because it
+would rarely be useful.
+
+A MAC can be viewed (in most cases) as simply a keyed hash function, so classes
+that are derived from \type{MessageAuthenticationCode} have \function{update}
+and \function{final} classes just like a \type{HashFunction} (and like a
+\type{HashFunction}, after \function{final} is called, it can be used to make a
+new MAC right away; the key is kept around).
+
+A MAC has the \type{SymmetricAlgorithm} interface in addition to the
+\type{BufferedComputation} interface.
+
+\pagebreak
+\section{Random Number Generators}
+
+The random number generators provided in Botan are meant for creating keys,
+IVs, padding, nonces, and anything else that requires 'random' data. It is
+important to remember that the output of these classes will vary, even if they
+are supplied with exactly the same seed (\ie, two \type{Randpool} objects with
+similar initial states will not produce the same output, because the value of
+high resolution timers is added to the state at various points).
+
+To ensure good quality output, a PRNG needs to be seeded with truly random data
+(such as that produced by a hardware RNG). Typically, you will use an
+\type{EntropySource} (see below). To add entropy to a PRNG, you can use
+\type{void} \function{add\_entropy}(\type{const byte} \arg{data}[],
+\type{u32bit} \arg{length}) or (better), use the \type{EntropySource}
+interface.
+
+Once a PRNG has been initialized, you can get a single byte of random data by
+calling \type{byte} \function{random()}, or get a large block by calling
+\type{void} \function{randomize}(\type{byte} \arg{data}[], \type{u32bit}
+\arg{length}), which will put random bytes into each member of the array from
+indexes 0 $\ldots$ \arg{length} -- 1.
+
+You can avoid all the problems inherent in seeding the PRNG by using the
+globally shared PRNG, described later in this section.
+
+\subsection{Randpool}
+
+\type{Randpool} is the primary PRNG within Botan. In recent versions all uses
+of it have been wrapped by an implementation of the X9.31 PRNG (see below). If
+for some reason you should have cause to create a PRNG instead of using the
+``global'' one owned by the library, it would be wise to consider the same on
+the grounds of general caution; while \type{Randpool} is designed with known
+attacks and PRNG weaknesses in mind, it is not an standard/official PRNG. The
+remainder of this section is a (fairly technical, though high-level) description
+of the algorithms used in this PRNG. Unless you have a specific interest in
+this subject, the rest of this section might prove somewhat uninteresting.
+
+\type{Randpool} has an internal state called pool, which is 512 bytes
+long. This is where entropy is mixed into and extracted from. There is also a
+small output buffer (called buffer), which holds the data which has already
+been generated but has just not been output yet.
+
+It is based around a MAC and a block cipher (which are currently HMAC(SHA-256)
+and AES-256). Where a specific size is mentioned, it should be taken as a
+multiple of the cipher's block size. For example, if a 256-bit block cipher
+were used instead of AES, all the sizes internally would double. Every time
+some new output is needed, we compute the MAC of a counter and a high
+resolution timer. The resulting MAC is XORed into the output buffer (wrapping
+as needed), and the output buffer is then encrypted with AES, producing 16
+bytes of output.
+
+After 8 blocks (or 128 bytes) have been produced, we mix the pool. To do this,
+we first rekey both the MAC and the cipher; the new MAC key is the MAC of the
+current pool under the old MAC key, while the new cipher key is the MAC of the
+current pool under the just-chosen MAC key. We then encrypt the entire pool in
+CBC mode, using the current (unused) output buffer as the IV. We then generate
+a new output buffer, using the mechanism described in the previous paragraph.
+
+To add randomness to the PRNG, we compute the MAC of the input and XOR the
+output into the start of the pool. Then we remix the pool and produce a new
+output buffer. The initial MAC operation should make it very hard for chosen
+inputs to harm the security of \type{Randpool}, and as HMAC should be able to
+hold roughly 256 bits of state, it is unlikely that we are wasting much input
+entropy (or, if we are, it doesn't matter, because we have a very abundant
+supply).
+
+\subsection{ANSI X9.31}
+
+\type{ANSI\_X931\_PRNG} is the standard issue X9.31 Appendix A.2.4 PRNG, though
+using AES-256 instead of 3DES as the block cipher. This PRNG implementation has
+been checked against official X9.31 test vectors.
+
+Internally, the PRNG holds a pointer to another PRNG (typically
+Randpool). This internal PRNG generates the key and seed used by the
+X9.31 algorithm, as well as the date/time vectors. Each time an X9.31
+PRNG object receives entropy, it simply passes it along to the PRNG it
+is holding, and then pulls out some random bits to generate a new key
+and seed. This PRNG considers itself seeded as soon as the internal
+PRNG is seeded.
+
+As of version 1.4.7, the X9.31 PRNG is by default used for all random number
+generation.
+
+\subsection{Entropy Sources}
+
+An \type{EntropySource} is an abstract representation of some method of gather
+``real'' entropy. This tends to be very system dependent. The \emph{only} way
+you should use an \type{EntropySource} is to pass it to a PRNG that will
+extract entropy from it -- never use the output directly for any kind of key or
+nonce generation!
+
+\type{EntropySource} has a pair of functions for getting entropy from some
+external source, called \function{fast\_poll} and \function{slow\_poll}. These
+pass a buffer of bytes to be written; the functions then return how many bytes
+of entropy were actually gathered. \type{EntropySource}s are usually used to
+seed the global PRNG using the functions found in the \namespace{Global\_RNG}
+namespace.
+
+Note for writers of \type{EntropySource}s: it isn't necessary to use any kind
+of cryptographic hash on your output. The data produced by an EntropySource is
+only used by an application after it has been hashed by the
+\type{RandomNumberGenerator} that asked for the entropy, thus any hashing
+you do will be wasteful of both CPU cycles and possibly entropy.
+
+\pagebreak
+\section{User Interfaces}
+
+Botan has recently changed some infrastructure to better accommodate more
+complex user interfaces, in particular ones that are based on event
+loops. Primary among these was the fact that when doing something like loading
+a PKCS \#8 encoded private key, a passphrase might be needed, but then again it
+might not (a PKCS \#8 key doesn't have to be encrypted). Asking for a
+passphrase to decrypt an unencrypted key is rather pointless. Not only that,
+but the way to handle the user typing the wrong passphrase was complicated,
+undocumented, and inefficient.
+
+So now Botan has an object called \type{UI}, which provides a simple interface
+for the aspects of user interaction the library has to be concerned
+with. Currently, this means getting a passphrase from the user, and that's it
+(\type{UI} will probably be extended in the future to support other operations
+as they are needed). The base \type{UI} class is very stupid, because the
+library can't directly assume anything about the environment that it's running
+under (for example, if there will be someone sitting at the terminal, if the
+application is even \emph{attached} to a terminal, and so on). But since you
+can subclass \type{UI} to use whatever method happens to be appropriate for
+your application, this isn't a big deal.
+
+There is (currently) a single function that can be overridden by subclasses of
+\type{UI} (the \type{std::string} arguments are actually \type{const
+std::string\&}, but shown as simply \type{std::string} to keep the line from
+wrapping):
+
+\noindent
+\type{std::string} \function{get\_passphrase}(\type{std::string} \arg{what},
+ \type{std::string} \arg{source},
+ \type{UI\_Result\&} \arg{result}) const;
+
+The \arg{what} argument specifies what the passphrase is needed for (for
+example, PKCS \#8 key loading passes \arg{what} as ``PKCS \#8 private
+key''). This lets you provide the user with some indication of \emph{why} your
+application is asking for a passphrase; feel free to pass the string through
+\function{gettext(3)} or moral equivalent for i18n purposes. Similarly,
+\arg{source} specifies where the data in question came from, if available (for
+example, a file name). If the source is not available for whatever reason, then
+\arg{source} will be an empty string; be sure to account for this possibility
+when writing a \type{UI} subclass.
+
+The function returns the passphrase as the return value, and a status code in
+\arg{result} (either \type{OK} or \type{CANCEL\_ACTION}). If
+\type{CANCEL\_ACTION} is returned in \arg{result}, then the return value will
+be ignored, and the caller will take whatever action is necessary (typically,
+throwing an exception stating that the passphrase couldn't be determined). In
+the specific case of PKCS \#8 key decryption, a \type{Decoding\_Error}
+exception will be thrown; your UI should assume this can happen, and provide
+appropriate error handling (such as putting up a dialog box informing the user
+of the situation, and canceling the operation in progress).
+
+There is an example \type{UI} that uses GTK+ available on the web site. The
+\type{GTK\_UI} code is cleanly separated from the rest of the example, so if
+you happen to be using GTK+, you can copy (and/or adapt) that code for your
+application. If you write a \type{UI} object for another windowing system
+(Win32, Qt, wxWidgets, FOX, etc), and would like to make it available to users
+in general (ideally under a permissive license such as public domain or
+MIT/BSD), feel free to send in a copy.
+
+\pagebreak
+\section{Botan's Modules}
+
+Botan comes with a variety of modules that can be compiled into the system.
+These will not be available on all installations of the library, but you can
+check for their availability based on whether or not certain macros are
+defined.
+
+\subsection{Pipe I/O for Unix File Descriptors}
+
+This is a fairly minor feature, but it comes in handy sometimes. In all
+installations of the library, Botan's \type{Pipe} object overloads the
+\keyword{<<} and \keyword{>>} operators for C++ iostream objects, which is
+usually more than sufficient for doing I/O.
+
+However, there are cases where the iostream hierarchy does not map well to
+local 'file types', so there is also the ability to do I/O directly with Unix
+file descriptors. This is most useful when you want to read from or write to
+something like a TCP or Unix-domain socket, or a pipe, since for simple file
+access it's usually easier to just use C++'s file streams.
+
+If \macro{BOTAN\_EXT\_PIPE\_UNIXFD\_IO} is defined, then you can use the
+overloaded I/O operators with Unix file descriptors. For an example of this,
+check out the \filename{hash\_fd} example, included in the Botan distribution.
+
+\subsection{Entropy Sources}
+
+All of these are used by the \function{Global\_RNG::seed} function if they are
+available. Since this function is called by the \type{LibraryInitializer} class
+when it is created, it is fairly rare that you will need to deal with any of
+these classes directly. Even in the case of a long-running server that needs to
+renew its entropy poll, it is easier to simply call
+\function{Global\_RNG::seed} (see the section entitled ``The Global PRNG'' for
+more details).
+
+\noindent
+\type{EGD\_EntropySource}: Query an EGD socket. If the macro
+\macro{BOTAN\_EXT\_ENTROPY\_SRC\_EGD} is defined, it can be found in
+\filename{es\_egd.h}. The constructor takes a \type{std::vector<std::string>}
+that specifies the paths to look for an EGD socket.
+
+\noindent
+\type{Unix\_EntropySource}: This entropy source executes programs common on
+Unix systems (such as \filename{uptime}, \filename{vmstat}, and \filename{df})
+and adds it to a buffer. It's quite slow due to process overhead, and (roughly)
+1 bit of real entropy is in each byte that is output. It is declared in
+\filename{es\_unix.h}, if \macro{BOTAN\_EXT\_ENTROPY\_SRC\_UNIX} is
+defined. If you don't have \filename{/dev/urandom} \emph{or} EGD, this is
+probably the thing to use. For a long-running process on Unix, keep on object
+of this type around and run fast polls ever few minutes.
+
+\noindent
+\type{FTW\_EntropySource}: Walk through a filesystem (the root to start
+searching is passed as a string to the constructor), reading files. This tends
+to only be useful on things like \filename{/proc} that have a great deal of
+variability over time, and even then there is only a small amount of entropy
+gathered: about 1 bit of entropy for every 16 bits of output (and many hundreds
+of bits are read in order to get that 16 bits). It is declared in
+\filename{es\_ftw.h}, if \macro{BOTAN\_EXT\_ENTROPY\_SRC\_FTW} is defined. Only
+use this as a last resort. I don't really trust it, and neither should you.
+
+\noindent
+\type{Win32\_CAPI\_EntropySource}: This routines gathers entropy from a Win32
+CAPI module. It takes an optional \type{std::string} that will specify what
+type of CAPI provider to use. Generally the CAPI RNG is always the same
+software-based PRNG, but there are a few that may use a hardware RNG. By
+default it will use the first provider listed in the option
+``rng/ms\_capi\_prov\_type'' that is available on the machine (currently the
+providers ``RSA\_FULL'', ``INTEL\_SEC'', ``FORTEZZA'', and ``RNG'' are
+recognized).
+
+\noindent
+\type{BeOS\_EntropySource}: Query system statistics using various BeOS-specific
+APIs.
+
+\noindent
+\type{Pthread\_EntropySource}: Attempt to gather entropy based on jitter
+between a number of threads competing for a single mutex. This entropy source
+is \emph{very} slow, and highly questionable in terms of security. However, it
+provides a worst-case fallback on systems that don't have Unix-like features,
+but do support POSIX threads. This module is currently unavailable due to
+problems on some systems.
+
+\subsection{Compressors}
+
+There are two compression algorithms supported by Botan, Zlib and Bzip2 (Gzip
+and Zip encoding will be supported in future releases). Only lossless
+compression algorithms are currently supported by Botan, because they tend to
+be the most useful for cryptography. However, it is very reasonable to consider
+supporting something like GSM speech encoding (which is lossy), for use in
+encrypted voice applications.
+
+You should always compress \emph{before} you encrypt, because encryption seeks
+to hide the redundancy that compression is supposed to try to find and remove.
+
+\subsubsection{Bzip2}
+
+To test for Bzip2, check to see if \macro{BOTAN\_EXT\_COMPRESSOR\_BZIP2} is
+defined. If so, you can include \filename{bzip2.h}, which will declare a pair
+of \type{Filter} objects: \type{Bzip2\_Compression} and
+\type{Bzip2\_Decompression}.
+
+You should be prepared to take an exception when using the decompressing
+filter, for if the input is not valid Bzip2 data, that is what you will
+receive. You can specify the desired level of compression to
+\type{Bzip2\_Compression}'s constructor as an integer between 1 and 9, 1
+meaning worst compression, and 9 meaning the best. The default is to use 9,
+since small values take the same amount of time, just use a little less memory.
+
+The Bzip2 module was contributed by Peter J. Jones.
+
+\subsubsection{Zlib}
+
+Zlib compression works pretty much like Bzip2 compression. The only differences
+in this case are that the macro is \macro{BOTAN\_EXT\_COMPRESSOR\_ZLIB}, the
+header you need to include is called \filename{botan/zlib.h} (remember that you
+shouldn't just \verb|#include <zlib.h>|, or you'll get the regular zlib API,
+which is not what you want). The Botan classes for Zlib
+compression/decompression are called \type{Zlib\_Compression} and
+\type{Zlib\_Decompression}.
+
+Like Bzip2, a \type{Zlib\_Decompression} object will throw an exception if
+invalid (in the sense of not being in the Zlib format) data is passed into it.
+
+In the case of zlib's algorithm, a worse compression level will be faster than
+a very high compression ratio. For this reason, the Zlib compressor will
+default to using a compression level of 6. This tends to give a good trade off
+in terms of time spent to compression achieved. There are several factors you
+need to consider in order to decide if you should use a higher compression
+level:
+
+\begin{list}{$\cdot$}
+ \item Better security: the less redundancy in the source text, the harder it
+ is to attack your ciphertext. This is not too much of a concern,
+ because with decent algorithms using sufficiently long keys, it doesn't
+ really matter \emph{that} much (but it certainly can't hurt).
+ \item
+
+ \item Decreasing returns. Some simple experiments by the author showed
+ minimal decreases in the size between level 6 and level 9 compression
+ with large (1 to 3 megabyte) files. There was some difference, but it
+ wasn't that much.
+
+ \item CPU time. Level 9 zlib compression is often two to four times as slow
+ as level 6 compression. This can make a substantial difference in the
+ overall runtime of a program.
+\end{list}
+
+While the zlib compression library uses the same compression algorithm as the
+gzip and zip programs, the format is different. The zlib format is defined in
+RFC 1950.
+
+\subsubsection{Data Sources}
+
+A \type{DataSource} is a simple abstraction for a thing that stores bytes. This
+type is used fairly heavily in the areas of the API related to ASN.1
+encoding/decoding. The following types are \type{DataSource}s: \type{Pipe},
+\type{SecureQueue}, and a couple of special purpose ones:
+\type{DataSource\_Memory} and \type{DataSource\_Stream}.
+
+You can create a \type{DataSource\_Memory} with an array of bytes and a length
+field. The object will make a copy of the data, so you don't have to worry
+about keeping that memory allocated. This is mostly for internal use, but if it
+comes in handy, feel free to use it.
+
+A \type{DataSource\_Stream} is probably more useful than the memory based
+one. Its constructors take either a \type{std::istream} or a
+\type{std::string}. If it's a stream, the data source will use the
+\type{istream} to satisfy read requests (this is particularly useful to use
+with \type{std::cin}). If the string version is used, it will attempt to open
+up a file with that name and read from it.
+
+\subsubsection{Data Sinks}
+
+A \type{DataSink} (in \filename{data\_snk.h}) is a \type{Filter} that takes
+arbitrary amounts of input, and produces no output. Generally, this means it's
+doing something with the data outside the realm of what
+\type{Filter}/\type{Pipe} can handle, for example, writing it to a file (which
+is what the \type{DataSink\_Stream} does). There is no need for
+\type{DataSink}s that write to a \type{std::string} or memory buffer, because
+\type{Pipe} can handle that by itself.
+
+Here's a quick example of using a \type{DataSink}, which encrypts
+\filename{in.txt} and sends the output to \filename{out.txt}. There is
+no explicit output operation; the writing of \filename{out.txt} is
+implicit.
+
+\begin{verbatim}
+ DataSource_Stream in("in.txt");
+ Pipe pipe(new CBC_Encryption("Blowfish", "PKCS7", key, iv),
+ new DataSink_Stream("out.txt"));
+ pipe.process_msg(in);
+\end{verbatim}
+
+A real advantage of this is that even if ``in.txt'' is large, only as
+much memory is needed for internal I/O buffers will actually be used.
+
+\subsection{Writing Modules}
+
+It's a lot simpler to write modules for Botan that it is to write code
+in the core library, for several reasons. First, a module can rely on
+external libraries and services beyond the base ISO C++ libraries, and
+also machine dependent features. Also, the code can be added at
+configuration time on the user's end with very little effort (\ie the
+code can be distributed separately, and included by the user without
+needing to patch any existing source files).
+
+Each module lives in a subdirectory of the \filename{modules}
+directory, which exists at the top-level of the Botan source tree. The
+``short name'' of the module is the same as the name of this
+directory. The only required file in this directory is
+\filename{info.txt}, which contains directives that specify what a
+particular module does, what systems it runs on, and so on. Comments
+in \filename{info.txt} start with a \verb|#| character and continue
+to end of line.
+
+Recognized directives include:
+
+\newcommand{\directive}[2]{
+ \vskip 4pt
+ \noindent
+ \texttt{#1}: #2
+}
+
+\directive{realname <name>}{Specify that the 'real world' name of this module
+ is \texttt{<name>}.}
+
+\directive{note <note>}{Add a note that will be seen by the end-user at
+configure time if the module is included into the library.}
+
+\directive{require\_version <version>}{Require at configure time that
+the version of Botan in use be at least \texttt{<version>}.}
+
+\directive{define <macro>[,<macro>[,...]]}{Cause the macro
+ \macro{BOTAN\_EXT\_<macro>} (for each instance of \macro{<macro>}
+ in the directive) to be defined in \filename{build.h}. This should
+ only be used if the module creates user-visible changes. There is a
+ set of conventions that should be followed in deciding what to call
+ this macro (where xxx denotes some descriptive and distinguishing
+ characteristic of the thing implemented, such as
+ \macro{ALLOC\_MLOCK} or \macro{MUTEX\_PTHREAD}):
+
+\begin{itemize}
+\item Allocator: \macro{ALLOC\_xxx}
+\item Compressors: \macro{COMPRESSOR\_xxx}
+\item EntropySource: \macro{ENTROPY\_SRC\_xxx}
+\item Engines: \macro{ENGINE\_xxx}
+\item Mutex: \macro{MUTEX\_xxx}
+\item Timer: \macro{TIMER\_xxx}
+\end{itemize}
+}
+
+\directive{<libs> / </libs>}{This specifies any extra libraries to be
+linked in. It is a mapping from OS to library name, for example
+\texttt{linux -> rt}, which means that on Linux librt should be linked
+in. You can also use ``all'' to force the library to be linked in on
+all systems.}
+
+\directive{<add> / </add>}{Tell the configuration script to add the
+ files named between these two tags into the source tree. All these
+ files must exist in the current module directory.}
+
+\directive{<ignore> / </ignore>}{Tell the configuration script to
+ ignore the files named in the main source tree. This is useful, for
+ example, when replacing a C++ implementation with a pure assembly
+ version.}
+
+\directive{<replace> / </replace>}{Tell the configuration script to
+ ignore the file given in the main source tree, and instead use the
+ one in the module's directory.}
+
+Additionally, the module file can contain blocks, delimited by the
+following pairs:
+
+\texttt{<os> / </os>}, \texttt{<arch> / </arch>}, \texttt{<cc> / </cc>}
+
+\noindent
+For example, putting ``alpha'' and ``ia64'' in a \texttt{<arch>} block will
+make the configuration script only allow the module to be compiled on those
+architectures. Not having a block means any value is acceptable.
+
+\pagebreak
+\section{Miscellaneous}
+
+This section has documentation for anything that just didn't fit into any of
+the major categories. Many of them (Timers, Allocators) will rarely be used in
+actual application code, but others, like the S2K algorithms, have a wide
+degree of applicability.
+
+\subsection{S2K Algorithms}
+
+There are various procedures (usually fairly ad-hoc) for turning a passphrase
+into a (mostly) arbitrary length key for a symmetric cipher. A general
+interface for such algorithms is presented in \filename{s2k.h}. The main
+function is \function{derive\_key}, which takes a passphrase, and the desired
+length of the output key, and returns a key of that length, deterministically
+produced from the passphrase. If an algorithm can't produce a key of that size,
+it will throw an exception (most notably, PKCS \#5's PBKDF1 can only produce
+strings between 1 and $n$ bytes, where $n$ is the output size of the underlying
+hash function).
+
+Most such algorithms allow the use of a ``salt'', which provides some extra
+randomness and helps against dictionary attacks on the passphrase. Simply call
+\function{change\_salt} (there are variations of it for most of the ways you
+might wish to specify a salt, check the header for details) with a block of
+random data. You can also have the class generate a new salt for you with
+\function{new\_random\_salt}; the salt that was generated can be retrieved with
+\function{current\_salt}.
+
+Additionally some algorithms allow you to set some sort of iteration
+count, which will make the algorithm take longer to compute the final
+key (reducing the speed of brute-force attacks of various kinds). This
+can be changed with the \function{set\_iterations} function. Most
+standards recommend an iteration count of at least 1000. Currently
+defined S2K algorithms are ``PBKDF1(digest)'', ``PBKDF2(digest)'', and
+``OpenPGP-S2K(digest)''; you can retrieve any of these using the
+\function{get\_s2k}, found in \filename{lookup.h}. As of this writing,
+``PBKDF2(SHA-256)'' with 10000 iterations and an 8 byte salt is
+recommend for new applications.
+
+\subsubsection{OpenPGP S2K}
+
+There are some oddities about OpenPGP's S2K algorithms that are documented
+here. For one thing, it uses the iteration count in a strange manner; instead
+of specifying how many times to iterate the hash, it tells how many
+\emph{bytes} should be hashed in total (including the salt). So the exact
+iteration count will depend on the size of the salt (which is fixed at 8 bytes
+by the OpenPGP standard, though the implementation will allow any salt size)
+and the size of the passphrase.
+
+To get what OpenPGP calls ``Simple S2K'', set iterations to 0 (the default for
+OpenPGP S2K), and do not specify a salt. To get ``Salted S2K'', again leave the
+iteration count at 0, but give an 8-byte salt. ``Salted and Iterated S2K''
+requires an 8-byte salt and some iteration count (this should be significantly
+larger than the size of the longest passphrase that might reasonably be used;
+somewhere from 1024 to 65536 would probably be about right). Using both a
+reasonably sized salt and a large iteration count is highly recommended to
+prevent password guessing attempts.
+
+\subsection{Checksums}
+
+Checksums are very similar to hash functions, and in fact share the same
+interface. But there are some significant differences, the major ones being
+that the output size is very small (usually in the range of 2 to 4 bytes), and
+is not cryptographically secure. But for their intended purpose (error
+checking), they perform very well. Some examples of checksums included in Botan
+are the Adler32 and CRC32 checksums.
+
+\subsection{Exceptions}
+
+Sooner or later, something is going to go wrong. Botan's behavior when
+something unusual occurs, like most C++ software, is to throw an exception.
+Exceptions in Botan are derived from the \type{Exception} class. You can see
+most of the major varieties of exceptions used in Botan by looking at
+\filename{exceptn.h}. The only function you really need to concern yourself
+with is \type{const char*} \function{what()}. This will return an error message
+relevant to the error that occurred. For example:
+
+\begin{verbatim}
+try {
+ // various Botan operations
+ }
+catch(Botan::Exception& e)
+ {
+ cout << "Botan exception caught: " << e.what() << endl;
+ // error handling, or just abort
+ }
+\end{verbatim}
+
+Botan's exceptions are derived from \type{std::exception}, so you don't need
+to explicitly check for Botan exceptions if you're already catching the ISO
+standard ones.
+
+\subsection{Threads and Mutexes}
+
+Botan includes a mutex system, which is used internally to lock some shared
+data structures that must be kept shared for efficiency reasons (mostly, these
+are in the allocation systems~--~handing out 1000 separate allocators hurts
+performance and makes caching memory blocks useless). This system is supported
+by the \texttt{mux\_pthr} module, implementing the \type{Mutex} interface for
+systems that have POSIX threads.
+
+If your application is using threads, you \emph{must} add the option
+``thread\_safe'' to the options string when you create the
+\type{LibraryInitializer} object. If you specify this option and no mutex type
+is available, an exception is thrown, since otherwise you would probably be
+facing a nasty crash.
+
+\subsection{Secure Memory}
+
+A major concern with mixing modern multiuser OSes and cryptographic
+code is that at any time the code (including secret keys) could be
+swapped to disk, where it can later be read by an attacker. Botan
+stores almost everything (and especially anything sensitive) in memory
+buffers that a) clear out their contents when their destructors are
+called, and b) have easy plugins for various memory locking functions,
+such as the \function{mlock}(2) call on many Unix systems.
+
+Two of the allocation method used (``malloc'' and ``mmap'') don't
+require any extra privileges on Unix, but locking memory does. At
+startup, each allocator type will attempt to allocate a few blocks
+(typically totaling 128k), so if you want, you can run your
+application \texttt{setuid} \texttt{root}, and then drop privileges
+immediately after creating your \type{LibraryInitializer}. If you end
+up using more than what's been allocated, some of your sensitive data
+might end up being swappable, but that beats running as \texttt{root}
+all the time. BTW, I would note that, at least on Linux, you can use a
+kernel module to give your process extra privileges (such as the
+ability to call \function{mlock}) without being root. For example,
+check out my Capability Override LSM
+(\url{http://www.randombit.net/projects/cap\_over/}), which makes this
+pretty easy to do.
+
+These classes should also be used within your own code for storing sensitive
+data. They are only meant for primitive data types (int, long, etc): if you
+want a container of higher level Botan objects, you can just use a
+\verb|std::vector|, since these objects know how to clear themselves when they
+are destroyed. You cannot, however, have a \verb|std::vector| (or any other
+container) of \type{Pipe}s or \type{Filter}s, because these types have pointers
+to other \type{Filter}s, and implementing copy constructors for these types
+would be both hard and quite expensive (vectors of pointers to such objects is
+fine, though).
+
+These types are not described in any great detail: for more information,
+consult the definitive sources~--~the header files \filename{secmem.h} and
+\filename{allocate.h}.
+
+\type{SecureBuffer} is a simple array type, whose size is specified at compile
+time. It will automatically convert to a pointer of the appropriate type, and
+has a number of useful functions, including \function{clear()}, and
+\type{u32bit} \function{size()}, which returns the length of the array. It is a
+template that takes as parameters a type, and a constant integer which is how
+long the array is (for example: \verb|SecureBuffer<byte, 8> key;|).
+
+\type{SecureVector} is a variable length array. Its size can be increased or
+decreased as need be, and it has a wide variety of functions useful for copying
+data into its buffer. Like \type{SecureBuffer}, it implements \function{clear}
+and \function{size}.
+
+\subsection{Allocators}
+
+The containers described above get their memory from allocators. As a user of
+the library, you can add new allocator methods at run time for containers,
+including the ones used internally by the library, to use. The interface to
+this is in \filename{allocate.h}. Basically how it works is that code needing
+an allocator uses \function{get\_allocator}, which returns a pointer to an
+allocator. This pointer should not be freed: the caller does not own the
+allocator (it is shared among multiple users, and locks itself as needed). It
+is possible to call \function{get\_allocator} with a specific name to request a
+particular type of allocator, otherwise, a default allocator type is returned.
+
+At start time, the only allocator known is a \type{Default\_Allocator}, which
+just allocates memory using \function{malloc}, and \function{memset}s it to 0
+when the memory is released. It is known by the name ``malloc''. If you ask for
+another type of allocator (``locking'' and ``mmap'' are currently used), and it
+is not available, some other allocator will be returned.
+
+You can add in a new allocator type using \function{add\_allocator\_type}. This
+function takes a string and a pointer to an allocator. The string gives this
+allocator type a name to which it can be referred when one is requesting it
+with \function{get\_allocator}. If an error occurs (such as the name being
+already registered), this function returns false. It will return true if the
+allocator was successfully registered. If you ask it to,
+\type{LibraryInitializer} will do this for you.
+
+Finally, you can set the default allocator type that will be returned using
+the policy setting ``default\_alloc'' to the name of any previously registered
+allocator.
+
+\subsection{BigInt}
+
+\type{BigInt} is Botan's implementation of a multiple-precision
+integer. Thanks to C++'s operator overloading features, using \type{BigInt} is
+often quite similar to using a native integer type. The number of functions
+related to \type{BigInt} is quite large. You can find most of them in
+\filename{bigint.h} and \filename{numthry.h}.
+
+Due to the sheer number of functions involved, only a few, which a regular user
+of the library might have to deal with, are mentioned here. Fully documenting
+the MPI library would take a significant while, so if you need to use it now,
+the best way to learn is to look at the headers.
+
+Probably the most important are the encoding/decoding functions, which
+transform the normal representation of a \type{BigInt} into some other form,
+such as a decimal string. The most useful of these functions are
+
+\type{SecureVector<byte>} \function{BigInt::encode}(\type{BigInt},
+\type{Encoding})
+
+\noindent
+and
+
+\type{BigInt} \function{BigInt::decode}(\type{SecureVector<byte>},
+\type{Encoding})
+
+\type{Encoding} is an enum that has values \type{Binary}, \type{Octal},
+\type{Decimal}, and \type{Hexadecimal}. The parameter will default to
+\type{Binary}. These functions are static member functions, so they would be
+called like this:
+
+\begin{verbatim}
+ BigInt n1; // some number
+ SecureVector<byte> n1_encoded = BigInt::encode(n1);
+ BigInt n2 = BigInt::decode(n1_encoded);
+ // now n1 == n2
+\end{verbatim}
+
+There are also C++-style I/O operators defined for use with \type{BigInt}. The
+input operator understands negative numbers, hexadecimal numbers (marked with a
+leading ``0x''), and octal numbers (marked with a leading '0'). The '-' must
+come before the ``0x'' or '0' marker. The output operator will never adorn the
+output; for example, when printing a hexadecimal number, there will not be a
+leading ``0x'' (though a leading '-' will be printed if the number is
+negative). If you want such things, you'll have to do them yourself.
+
+\type{BigInt} has constructors that can create a \type{BigInt} from an unsigned
+integer or a string. You can also decode a \type{byte}[] / length pair into a
+BigInt. There are several other \type{BigInt} constructors, which I would
+seriously recommend you avoid, as they are only intended for use internally by
+the library, and may arbitrarily change, or be removed, in a future release.
+
+An essentially random sampling of \type{BigInt} related functions:
+
+\type{u32bit} \function{BigInt::bytes}(): Return the size of this \type{BigInt}
+in bytes.
+
+\type{BigInt} \function{random\_prime(\type{u32bit} \arg{b})}: Return a prime
+number \arg{b} bits long.
+
+\type{BigInt} \function{gcd}(\type{BigInt} \arg{x}, \type{BigInt} \arg{y}):
+Returns the greatest common divisor of \arg{x} and \arg{y}. Uses the binary
+GCD algorithm.
+
+\type{bool} \function{is\_prime}(\type{BigInt} \arg{x}): Returns true if
+\arg{x} is a (possible) prime number. Uses the Miller-Rabin probabilistic
+primality test with fixed bases. For higher assurance, use
+\function{verify\_prime}, which uses more rounds and randomized 48-bit bases.
+
+\subsubsection{Efficiency Hints}
+
+If you can, always use expressions of the form \verb|a += b| over
+\verb|a = a + b|. The difference can be \emph{very} substantial, because the
+first form prevents at least one needless memory allocation, and possibly as
+many as three.
+
+If you're doing repeated modular exponentiations with the same modulus, create
+a \type{BarrettReducer} ahead of time. If the exponent or base is a constant,
+use the classes in \filename{mod\_exp.h}. This stuff is all handled for you by
+the normal high-level interfaces, of course.
+
+Never use the low-level MPI functions (those that begin with
+\texttt{bigint\_}). These are completely internal to the library, and
+may make arbitrarily strange and undocumented assumptions about their
+inputs, and don't check to see if they are actually true, on the
+assumption that only the library itself calls them, and that the
+library knows what the assumptions are. The interfaces for these
+functions can change completely without notice.
+
+\pagebreak
+\section{Algorithms}
+
+\subsection{Recommended Algorithms}
+
+This section is by no means the last word on selecting which algorithms to use.
+However, Botan includes a sometimes bewildering array of possible algorithms,
+and unless you're familiar with the latest developments in the field, it can be
+hard to know what is secure and what is not. The following attributes of the
+algorithms were evaluated when making this list: security, standardization,
+patent status, support by other implementations, and efficiency (in roughly
+that order).
+
+It is intended as a set of simple guidelines for developers, and nothing more.
+It's entirely possible that there are algorithms in Botan that will turn out to
+be more secure than the ones listed, but the algorithms listed here are
+(currently) thought to be safe.
+
+\begin{list}{$\cdot$}
+ \item Block ciphers: AES or Serpent in CBC or CTR mode
+
+ \item Hash functions: SHA-256, SHA-512
+
+ \item MACs: HMAC with any recommended hash function
+
+ \item Public Key Encryption: RSA with ``EME1(SHA-256)''
+
+ \item Public Key Signatures: RSA with EMSA4 and any recommended hash, or DSA
+ with ``EMSA1(SHA-256)''
+
+ \item Key Agreement: Diffie-Hellman, with ``KDF2(SHA-256)''
+\end{list}
+
+\subsection{Compliance with Standards}
+
+Botan is/should be at least roughly compatible with many cryptographic
+standards, including the following:
+
+\newcommand{\standard}[2]{
+ \vskip 4pt
+ * #1: \textbf{#2}
+}
+
+\standard{RSA}{PKCS \#1 v2.1, ANSI X9.31}
+
+\standard{DSA}{ANSI X9.30, FIPS 186-2}
+
+\standard{Diffie-Hellman}{ANSI X9.42, PKCS \#3}
+
+\standard{Certificates}{ITU X.509, RFC 3280/3281 (PKIX), PKCS \#9 v2.0,
+PKCS \#10}
+
+\standard{Private Key Formats}{PKCS \#5 v2.0, PKCS \#8}
+
+\standard{DES/DES-EDE}{FIPS 46-3, ANSI X3.92, ANSI X3.106}
+
+\standard{SHA-1}{FIPS 180-2}
+
+\standard{HMAC}{ANSI X9.71, FIPS 198}
+
+\standard{ANSI X9.19 MAC}{ANSI X9.9, ANSI X9.19}
+
+\vskip 8pt
+\noindent
+There is also support for the very general standards of \textbf{IEEE 1363-2000}
+and \textbf{1363a}. Most of the contents of such are included in the standards
+mentioned above, in various forms (usually with extra restrictions that 1363
+does not impose).
+
+\subsection{Algorithms Listing}
+
+Botan includes a very sizable number of cryptographic algorithms. In
+nearly all cases, you never need to know the header file or type name
+to use them. However, you do need to know what string (or strings) are
+used to identify that algorithm. Generally, these names conform to
+those set out by SCAN (Standard Cryptographic Algorithm Naming), which
+is a document that specifies how strings are mapped onto algorithm
+objects, which is useful for a wide variety of crypto APIs (SCAN is
+oriented towards Java, but Botan and several other non-Java libraries
+also make at least some use of it). For full details, read the SCAN
+document, which can be found at
+\url{http://www.users.zetnet.co.uk/hopwood/crypto/scan/}
+
+Many of these algorithms can take options (such as the number of
+rounds in a block cipher, the output size of a hash function,
+etc). These are shown in the following list; all of them default to
+reasonable values (unless otherwise marked). There are
+algorithm-specific limits on most of them. When you see something like
+``HASH'' or ``BLOCK'', that means you should insert the name of some
+algorithm of that type. There are no defaults for those options.
+
+A few very obscure algorithms are skipped; if you need one of them,
+you'll know it, and you can look in the appropriate header to see what
+that classes' \function{name} function returns (the names tend to
+match that in SCAN, if it's defined there).
+
+\begin{list}{$\cdot$}
+ \item ROUNDS: The number of rounds in a block cipher.
+ \item
+ \item OUTSZ: The output size of a hash function or MAC
+ \item PASS: The number of passes in a hash function (more passes generally
+ means more security).
+\end{list}
+
+\vskip .05in
+\noindent
+\textbf{Block Ciphers:} ``AES'', ``Blowfish'', ``CAST-128'',
+``CAST-256'', ``DES'', ``DESX'', ``TripleDES'', ``GOST'', ``IDEA'',
+``MARS'', ``MISTY1(ROUNDS)'', ``RC2'', ``RC5(ROUNDS)'', ``RC6'',
+``SAFER-SK(ROUNDS)'', ``SEED'', ``Serpent'', ``Skipjack'', ``Square'',
+``TEA'', ``Twofish'', ``XTEA''
+
+\noindent
+\textbf{Stream Ciphers:} ``ARC4'', ``MARK4'', ``Turing'', ``WiderWake4+1-BE''
+
+\noindent
+\textbf{Hash Functions:} ``FORK-256'', ``HAS-160'', ``GOST-34.11'',
+``MD2'', ``MD4'', ``MD5'', ``RIPEMD-128'', ``RIPEMD-160'',
+``SHA-160'', ``SHA-256'', ``SHA-384'', ``SHA-512'', ``Skein-512'',
+``Tiger(OUTSZ,PASS)'', ``Whirlpool''
+
+\noindent
+\textbf{MACs:} ``HMAC(HASH)'', ``CMAC(BLOCK)'', ``X9.19-MAC''
+
+\subsection{Compatibility}
+
+Generally, cryptographic algorithms are well standardized, thus
+compatibility between implementations is relatively simple (of course, not all
+algorithms are supported by all implementations). But there are a few
+algorithms that are poorly specified, and these should be avoided if you wish
+your data to be processed in the same way by another implementation (including
+future versions of Botan).
+
+The block cipher GOST has a particularly poor specification: there are no
+standard Sboxes, and the specification does not give test vectors even for
+sample boxes, which leads to issues of endian conventions, etc.
+
+If you wish maximum portability between different implementations of an
+algorithm, it's best to stick to strongly defined and well standardized
+algorithms, TripleDES, AES, HMAC, and SHA-256 all being good examples.
+
+\pagebreak
+\section{Support and Further Information}
+
+\subsection{Patents}
+
+Some of the algorithms implemented by Botan may be covered by patents in some
+locations. Algorithms known to have patent claims on them in the United States
+and that are not available in a license-free/royalty-free manner include:
+IDEA, MISTY1, RC5, RC6, and Nyberg-Rueppel.
+
+You must not assume that, just because an algorithm is not listed here, it is
+not encumbered by patents. If you have any concerns about the patent status of
+any algorithm you are considering using in an application, please discuss it
+with your attorney.
+
+\subsection{Recommended Reading}
+
+It's a very good idea if you have some knowledge of cryptography prior
+to trying to use this stuff. You really should read one or more of
+these books before seriously using the library (note that the Handbook
+of Applied Cryptography is available for free online):
+
+\setlength{\parskip}{5pt}
+
+\noindent
+\textit{Handbook of Applied Cryptography}, Alfred J. Menezes,
+Paul C. Van Oorschot, and Scott A. Vanstone; CRC Press
+
+\noindent
+\textit{Security Engineering -- A Guide to Building Dependable Distributed
+Systems}, Ross Anderson; Wiley
+
+\noindent
+\textit{Cryptography: Theory and Practice}, Douglas R. Stinson; CRC Press
+
+\noindent
+\textit{Applied Cryptography, 2nd Ed.}, Bruce Schneier; Wiley
+
+\noindent
+Once you've got the basics down, these are good things to at least take a look
+at: IEEE 1363 and 1363a, SCAN, NESSIE, PKCS \#1 v2.1, the security related FIPS
+documents, and the CFRG RFCs.
+
+\subsection{Support}
+
+Questions or problems you have with Botan can be directed to the
+development mailing list. Joining this list is highly recommended if
+you're going to be using Botan, since often advance notice of upcoming
+changes is sent there. ``Philosophical'' bug reports, announcements of
+programs using Botan, and basically anything else having to do with
+Botan are also welcome.
+
+The lists can be found at
+\url{http://lists.randombit.net/mailman/listinfo/}.
+
+\subsection{Contact Information}
+
+A PGP key with a fingerprint of
+\verb|621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC| is used to sign all
+Botan releases. This key can be found in the file \filename{doc/pgpkeys.asc};
+PGP keys for the developers are also stored there.
+
+\vskip 5pt \noindent
+Web Site: \url{http://botan.randombit.net}
+
+\subsection{License}
+
+Copyright \copyright 2000-2008, Jack Lloyd
+
+Licensed under the same terms as the Botan source
+
+\end{document}
diff --git a/botan/doc/architecture.pdf b/botan/doc/architecture.pdf
new file mode 100644
index 0000000..f0edc3f
--- /dev/null
+++ b/botan/doc/architecture.pdf
Binary files differ
diff --git a/botan/doc/building.pdf b/botan/doc/building.pdf
new file mode 100644
index 0000000..9b7d45a
--- /dev/null
+++ b/botan/doc/building.pdf
Binary files differ
diff --git a/botan/doc/building.tex b/botan/doc/building.tex
new file mode 100644
index 0000000..aa4435c
--- /dev/null
+++ b/botan/doc/building.tex
@@ -0,0 +1,398 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan Build Guide}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{2008-11-24}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\module}[1]{\texttt{#1}}
+
+\newcommand{\type}[1]{\texttt{#1}}
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+\pagebreak
+
+\section{Introduction}
+
+This document describes how to build Botan on Unix/POSIX and MS
+Windows systems. The POSIX oriented descriptions should apply to most
+common Unix systems (including MacOS X), along with POSIX-ish systems
+like BeOS, QNX, and Plan 9. Currently, systems other than Windows and
+POSIX (such as VMS, MacOS 9, OS/390, OS/400, ...) are not supported by
+the build system, primarily due to lack of access. Please contact the
+maintainer if you would like to build Botan on such a system.
+
+Botan's build is controlled by configure.pl, which is a Perl
+script. Perl 5.6 or later is required.
+
+\section{For the Impatient}
+
+\begin{verbatim}
+$ ./configure.pl [--prefix=/some/directory]
+$ make
+$ make install
+\end{verbatim}
+
+Or using \verb|nmake|, if you're compiling on Windows with Visual
+C++. On platforms that do not understand the '\#!' convention for
+beginning script files, or that have Perl installed in an unusual
+spot, you might need to prefix the \texttt{configure.pl} command with
+\texttt{perl} or \texttt{/path/to/perl}.
+
+\section{Building the Library}
+
+The first step is to run \filename{configure.pl}, which is a Perl
+script that creates various directories, config files, and a Makefile
+for building everything. The script requires at least Perl 5.6; any
+later version should also work.
+
+The script will attempt to guess what kind of system you are trying
+to compile for (and will print messages telling you what it guessed).
+You can override this process by passing the options \verb|--cc|,
+\verb|--os|, and \verb|--cpu| -- acceptable values are printed if
+you run \verb|configure.pl| with \verb|--help|.
+
+You can pass basically anything reasonable with \verb|--cpu|: the
+script knows about a large number of different architectures, their
+sub-models, and common aliases for them. The script does not display
+all the possibilities in its help message because there are simply too
+many entries. You should only select the 64-bit version of a CPU (such
+as ``sparc64'' or ``mips64'') if your operating system knows how to
+handle 64-bit object code -- a 32-bit kernel on a 64-bit CPU will
+generally not like 64-bit code.
+
+By default the script tries to figure out what will work on your
+system, and use that. It will print a display at the end showing
+which algorithms have and have not been abled. For instance on one
+system we might see the line:
+
+\begin{verbatim}
+ (loading): entropy: [beos_stats] buf_es [cryptoapi_rng]
+ dev_random egd proc_walk unix_procs [win32_stats]
+\end{verbatim}
+
+The names listed in brackets are disabled, the others are
+enabled. Here we see the list of entropy sources which are going to be
+compiled into Botan. Since this particular line comes when Botan was
+configuring for a Linux system, the Win32 and BeOS specific modules
+were disabled, while modules that use Unix APIs and /dev/random are
+built.
+
+You can control which algorithms and modules are built using the
+options ``\verb|--enable-modules=MODS|'' and
+``\verb|--disable-modules=MODS|'', for instance \\
+``\verb|--enable-modules=blowfish,md5,rsa,zlib --disable-modules=arc4,cmac|''.
+Modules not listed on the command line will simply be loaded if needed
+or if configured to load by default.
+
+Not all OSes or CPUs have specific support in
+\filename{configure.pl}. If the CPU architecture of your system isn't
+supported by \filename{configure.pl}, use 'generic'. This setting
+disables machine-specific optimization flags. Similarly, setting OS to
+'generic' disables things which depend greatly on OS support
+(specifically, shared libraries).
+
+However, it's impossible to guess which options to give to a system
+compiler. Thus, if you want to compile Botan with a compiler which
+\filename{configure.pl} does not support, you will need to tell it how
+that compiler works. This is done by adding a new file in the
+directory \filename{src/build-data/cc}; the existing files should put you
+in the right direction.
+
+The script tries to guess what kind of makefile to generate, and it
+almost always guesses correctly (basically, Visual C++ uses NMAKE with
+Windows commands, and everything else uses Unix make with POSIX
+commands). Just in case, you can override it with
+\verb|--make-style=somestyle|. The styles Botan currently knows about
+are 'unix' (normal Unix makefiles), and 'nmake', the make variant
+commonly used by Windows compilers. To add a new variant (eg, a build
+script for VMS), you will need to create a new template file in
+\filename{src/build-data/makefile}.
+
+\pagebreak
+
+\subsection{POSIX / Unix}
+
+The basic build procedure on Unix and Unix-like systems is:
+
+\begin{verbatim}
+ $ ./configure.pl [--enable-modules=<list>] [--cc=CC]
+ $ make
+ # You may need to set your LD_LIBRARY_PATH or equivalent for ./check to run
+ $ make check # optional, but a good idea
+ $ make install
+\end{verbatim}
+
+This will probably default to using GCC, depending on what can be
+found within your PATH.
+
+The \verb|make install| target has a default directory in which it
+will install Botan (typically \verb|/usr/local|). You can override
+this by using the \texttt{--prefix} argument to
+\filename{configure.pl}, like so:
+
+\verb|./configure.pl --prefix=/opt <other arguments>|
+
+On some systems shared libraries might not be immediately visible to
+the runtime linker. For example, on Linux you may have to edit
+\filename{/etc/ld.so.conf} and run \texttt{ldconfig} (as root) in
+order for new shared libraries to be picked up by the linker. An
+alternative is to set your \texttt{LD\_LIBRARY\_PATH} shell variable
+to include the directory that the Botan libraries were installed into.
+
+\subsection{MS Windows}
+
+The situation is not much different here. We'll assume you're using Visual C++
+(for Cygwin, the Unix instructions are probably more relevant). You need to
+have a copy of Perl installed, and have both Perl and Visual C++ in your path.
+
+\begin{verbatim}
+ > perl configure.pl --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU]
+ > nmake
+ > nmake check # optional, but recommended
+\end{verbatim}
+
+For Win95 pre OSR2, the \verb|cryptoapi_rng| module will not work,
+because CryptoAPI didn't exist. And all versions of NT4 lack the
+ToolHelp32 interface, which is how \verb|win32_stats| does its slow
+polls, so a version of the library built with that module will not
+load under NT4. Later systems (98/ME/2000/XP) support both methods, so
+this shouldn't be much of an issue.
+
+Unfortunately, there currently isn't an install script usable on
+Windows. Basically all you have to do is copy the newly created
+\filename{libbotan.lib} to someplace where you can find it later (say,
+\verb|C:\botan\|). Then copy the entire \verb|build\include\botan|
+directory, which was constructed when you built the library, into the
+same directory.
+
+When building your applications, all you have to do is tell the
+compiler to look for both include files and library files in
+\verb|C:\botan|, and it will find both. Or you can move them to a
+place where they will be in the default compiler search paths (consult
+your documentation and/or local expert for details).
+
+\pagebreak
+
+\subsection{Configuration Parameters}
+
+There are some configuration parameters which you may want to tweak
+before building the library. These can be found in
+\filename{config.h}. This file is overwritten every time the configure
+script is run (and does not exist until after you run the script for
+the first time).
+
+Also included in \filename{build/build.h} are macros which are defined
+if one or more extensions are available. All of them begin with
+\verb|BOTAN_HAS_|. For example, if \verb|BOTAN_HAS_COMPRESSOR_BZIP2|
+is defined, then an application using Botan can include
+\filename{<botan/bzip2.h>} and use the Bzip2 filters.
+
+\macro{BOTAN\_MP\_WORD\_BITS}: This macro controls the size of the
+words used for calculations with the MPI implementation in Botan. You
+can choose 8, 16, 32, or 64, with 32 being the default. You can use 8,
+16, or 32 bit words on any CPU, but the value should be set to the
+same size as the CPU's registers for best performance. You can only
+use 64-bit words if an assembly module (such as \module{mp\_ia32} or
+\module{mp\_asm64}) is used. If the appropriate module is available,
+64 bits are used, otherwise this is set to 32. Unless you are building
+for a 8 or 16-bit CPU, this isn't worth messing with.
+
+\macro{BOTAN\_VECTOR\_OVER\_ALLOCATE}: The memory container
+\type{SecureVector} will over-allocate requests by this amount (in
+elements). In several areas of the library, we grow a vector fairly often. By
+over-allocating by a small amount, we don't have to do allocations as often
+(which is good, because the allocators can be quite slow). If you \emph{really}
+want to reduce memory usage, set it to 0. Otherwise, the default should be
+perfectly fine.
+
+\macro{BOTAN\_DEFAULT\_BUFFER\_SIZE}: This constant is used as the size of
+buffers throughout Botan. A good rule of thumb would be to use the page size of
+your machine. The default should be fine for most, if not all, purposes.
+
+\macro{BOTAN\_GZIP\_OS\_CODE}: The OS code is included in the Gzip header when
+compressing. The default is 255, which means 'Unknown'. You can look in RFC
+1952 for the full list; the most common are Windows (0) and Unix (3). There is
+also a Macintosh (7), but it probably makes more sense to use the Unix code on
+OS X.
+
+\subsection{Multiple Builds}
+
+It may be useful to run multiple builds with different
+configurations. Specify \verb|--build-dir=<dir>| to set up a build
+environment in a different directory.
+
+\subsection{Local Configuration}
+
+You may want to do something peculiar with the configuration; to
+support this there is a flag to \filename{configure.pl} called
+\texttt{--with-local-config=<file>}. The contents of the file are
+inserted into \filename{build/build.h} which is (indirectly) included
+into every Botan header and source file.
+
+\pagebreak
+
+\section{Modules}
+
+There are a fairly large number of modules included with Botan. Some
+of these are extremely useful, while others are only necessary in very
+unusual circumstances. The modules included with this release are:
+
+\newcommand{\mod}[2]{\textbf{#1}: #2}
+
+\begin{list}{$\cdot$}
+ \item \mod{alloc\_mmap}{Allocates memory using memory mappings of temporary
+ files. This means that if the OS swaps all or part of the application,
+ the sensitive data will be swapped to where we can later clean it,
+ rather than somewhere in the swap partition.}
+
+ \item \mod{bzip2}{Enables an application to perform bzip2 compression
+ and decompression using the library. Available on any system that has
+ bzip2.}
+
+ \item \mod{zlib}{Enables an application to perform zlib compression and
+ decompression using the library. Available on any system that has
+ zlib.}
+
+ %\item \mod{eng\_aep}{An engine that uses any available AEP accelerator card
+ % to speed up PK operations. You have to have the AEP drivers installed
+ % for this to link correctly, but you don't have to have a card
+ % installed - it will automatically be enabled if a card is detected at
+ % run time.}
+
+ \item \mod{gnump}{An engine that uses GNU MP to speed up PK operations.
+ GNU MP 4.1 or later is required.}
+
+ \item \mod{openssl}{An engine that uses OpenSSL to speed up public key
+ operations and some ciphers/hashes. OpenSSL 0.9.7 or
+ later is required.}
+
+ \item \mod{beos\_stats}{An entropy source that uses BeOS-specific
+ APIs to gather (hopefully unpredictable) data from the system.}
+
+ \item \mod{cryptoapi\_rng}{An entropy source that uses the Win32
+ CryptoAPI function \texttt{CryptGenRandom} to gather
+ entropy. Supported on NT4, Win95 OSR2, and all later Windows
+ systems.}
+
+ \item \mod{egd}{An entropy source that accesses EGD (the entropy
+ gathering daemon). Common on Unix systems that don't have
+ \texttt{/dev/random}.}
+
+ \item \mod{proc\_walk}{Gather entropy by reading files from a particular file
+ tree. Usually used with \texttt{/proc}; most other file trees don't
+ have sufficient variability over time to be useful.}
+
+ \item \mod{unix\_procs}{Gather entropy by running various Unix programs, like
+ \texttt{arp} and \texttt{vmstat}, and reading their output in the
+ hopes that at least some of it will be unpredictable to an attacker.}
+
+ \item \mod{win32\_stats}{Gather entropy by walking through various pieces of
+ information about processes running on the system. Does not run on
+ NT4, but should run on all other Win32 systems.}
+
+ \item \mod{fd\_unix}{Let the users of \texttt{Pipe} perform I/O with Unix
+ file descriptors in addition to \texttt{iostream} objects.}
+
+ \item \mod{pthread}{Add support for using \texttt{pthread} mutexes to
+ lock internal data structures. Important if you are using threads
+ with the library.}
+
+ \item \mod{qt\_mutex}{Add support for using Qt mutexes to lock internal data
+ structures.}
+
+ \item \mod{cpu\_counter}{Use the contents of the CPU cycle counter when
+ generating random bits to further randomize the results. Works on x86
+ (Pentium and up), Alpha, and SPARCv9.}
+
+ \item \mod{posix\_rt}{Use the POSIX realtime clock as a high-resolution
+ timer.}
+
+ \item \mod{gettimeofday}{Use the traditional Unix
+ \texttt{gettimeofday} as a high resolution timer.}
+
+ \item \mod{win32\_query\_perf\_ctr}{Use Win32's
+ \texttt{QueryPerformanceCounter} as a high resolution timer.}
+
+\end{list}
+
+\pagebreak
+
+\section{Building Applications}
+
+\subsection{Unix}
+
+Botan usually links in several different system libraries (such as
+\texttt{librt} and \texttt{libz}), depending on which modules are
+configured at compile time. In many environments, particularly ones
+using static libraries, an application has to link against the same
+libraries as Botan for the linking step to succeed. But how does it
+figure out what libraries it \emph{is} linked against?
+
+The answer is to ask the \filename{botan-config} script. This
+basically solves the same problem all the other \filename{*-config}
+scripts solve, and in basically the same manner.
+
+There are 4 options:
+
+\texttt{--prefix[=DIR]}: If no argument, print the prefix where Botan
+is installed (such as \filename{/opt} or \filename{/usr/local}). If an
+argument is specified, other options given with the same command will
+execute as if Botan as actually installed at \filename{DIR} and not
+where it really is; or at least where \filename{botan-config} thinks
+it really is. I should mention that it
+
+\texttt{--version}: Print the Botan version number.
+
+\texttt{--cflags}: Print options that should be passed to the compiler
+whenever a C++ file is compiled. Typically this is used for setting
+include paths.
+
+\texttt{--libs}: Print options for which libraries to link to (this includes
+\texttt{-lbotan}).
+
+Your \filename{Makefile} can run \filename{botan-config} and get the
+options necessary for getting your application to compile and link,
+regardless of whatever crazy libraries Botan might be linked against.
+
+Botan also by default installs a file for \texttt{pkg-config},
+namespaced by the major and minor versions. So it can be used,
+for instance, as
+
+\begin{verbatim}
+$ pkg-config botan-1.8 --modversion
+1.8.0
+$ pkg-config botan-1.8 --cflags
+-I/usr/local/include
+$ pkg-config botan-1.8 --libs
+-L/usr/local/lib -lbotan -lm -lbz2 -lpthread -lrt
+\end{verbatim}
+
+\subsection{MS Windows}
+
+No special help exists for building applications on Windows. However,
+given that typically Windows software is distributed as binaries, this
+is less of a problem - only the developer needs to worry about it. As
+long as they can remember where they installed Botan, they just have
+to set the appropriate flags in their Makefile/project file.
+
+\end{document}
diff --git a/botan/doc/credits.txt b/botan/doc/credits.txt
new file mode 100644
index 0000000..ef2ee6b
--- /dev/null
+++ b/botan/doc/credits.txt
@@ -0,0 +1,78 @@
+ This is the credits file of people that have contributed to Botan. It uses
+ the same format as the Linux credits file. Please keep it sorted by last
+ name.
+
+ The fields are:
+ N - name
+ E - email
+ W - web URL
+ P - PGP fingerprint
+ D - description
+ S - meatspace location
+----------
+
+N - Charles Brockman
+W - http://www.securitygenetics.com/
+D - documentation editing
+S - Oregon, USA
+
+N: Martin Doering
+E: doering@cdc.informatik.tu-darmstadt.de
+D: GF(p) arithmetic
+
+N: Matthew Gregan
+D: Binary file I/O support, allocator fixes
+
+N: Hany Greiss
+D: Windows porting
+
+N: Manuel Hartl
+E: hartl@flexsecure.de
+W: http://www.flexsecure.de/
+D: ECDSA, ECKAEG
+
+N: Yves Jerschow
+E: yves.jerschow@uni-duesseldorf.de
+D: Optimizations for memory load/store and HMAC
+D: Support for IPv4 addresses in X.509 alternative names
+S: Germany
+
+N: Matt Johnston
+D: Allocator fixes and optimizations, decompressor fixes
+
+N: Peter J. Jones
+E: pjones@pmade.org
+D: Bzip2 compression module
+S: Colorado, USA
+
+N: Justin Karneges
+D: Qt support modules (mutexes and types), X.509 API design
+
+N: Jack Lloyd
+E: lloyd@randombit.net
+W: http://www.randombit.net/
+P: 3F69 2E64 6D92 3BBE E7AE 9258 5C0F 96E8 4EC1 6D6B
+D: Original designer/author, maintainer 2001-current
+S: Vermont, USA
+
+N: Joel Low
+D: DLL symbol visibility
+
+N: Christoph Ludwig
+E: ludwig@fh-worms.de
+D: GP(p) arithmetic
+
+N: Vaclav Ovsik
+E: vaclav.ovsik@i.cz
+D: Perl XS module
+
+N: Luca Piccarreta
+E: luca.piccarreta@gmail.com
+D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
+S: Italy
+
+N: Falko Strenzke
+E: strenzke@flexsecure.de
+W: http://www.flexsecure.de/
+D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm
+S: Darmstadt, Germany
diff --git a/botan/doc/examples/GNUmakefile b/botan/doc/examples/GNUmakefile
new file mode 100644
index 0000000..d854c81
--- /dev/null
+++ b/botan/doc/examples/GNUmakefile
@@ -0,0 +1,21 @@
+
+BOTAN_CONFIG = botan-config
+
+CXX = g++
+CFLAGS = -O2 -ansi -W -Wall $(shell $(BOTAN_CONFIG) --cflags)
+LIBS = $(shell $(BOTAN_CONFIG) --libs)
+
+SRCS=$(wildcard *.cpp)
+
+PROGS=$(patsubst %.cpp,%,$(SRCS))
+
+all: $(PROGS)
+
+clean:
+ @rm -f $(PROGS)
+
+%: %.cpp
+ $(CXX) $(CFLAGS) $? $(LIBS) -o $@
+
+eax_test: eax_test.cpp
+ $(CXX) $(CFLAGS) $? $(LIBS) -lboost_regex -o $@
diff --git a/botan/doc/examples/asn1.cpp b/botan/doc/examples/asn1.cpp
new file mode 100644
index 0000000..e8fc015
--- /dev/null
+++ b/botan/doc/examples/asn1.cpp
@@ -0,0 +1,312 @@
+/*
+ A simple ASN.1 parser, similiar to 'dumpasn1' or 'openssl asn1parse', though
+ without some of the bells and whistles of those. Primarily used for testing
+ the BER decoder. The output format is modeled loosely on 'asn1parse -i'
+
+ The output is actually less precise than the other decoders named, because
+ the underlying BER_Decoder hides quite a bit from userspace, such as the use
+ of indefinite length encodings (and the EOC markers). At some point it will
+ also hide the constructed string types from the user, but right now you'll
+ seem them as-is.
+
+ Written by Jack Lloyd, November 9-10, 2003
+ - Nov 22: Updated to new BER_Object format (tag -> class_tag/type_tag)
+ - Nov 25: Much improved BIT STRING output
+ Can deal with non-constructed taggings
+ Can produce UTF-8 output
+
+ This file is in the public domain.
+*/
+
+/*******************************************************************/
+
+// Set this if your terminal understands UTF-8; otherwise output is in Latin-1
+#define UTF8_TERMINAL 1
+
+/*
+ What level the outermost layer of stuff is at. Probably 0 or 1; asn1parse
+ uses 0 as the outermost, while 1 makes more sense to me. 2+ doesn't make
+ much sense at all.
+*/
+#define INITIAL_LEVEL 0
+
+/*******************************************************************/
+
+#include <botan/botan.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <botan/charset.h>
+using namespace Botan;
+
+#include <stdio.h>
+#include <ctype.h>
+
+void decode(BER_Decoder&, u32bit);
+void emit(const std::string&, u32bit, u32bit, const std::string& = "");
+std::string type_name(ASN1_Tag);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ printf("Usage: %s <file>\n", argv[0]);
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ DataSource_Stream in(argv[1]);
+
+ if(!PEM_Code::matches(in))
+ {
+ BER_Decoder decoder(in);
+ decode(decoder, INITIAL_LEVEL);
+ }
+ else
+ {
+ std::string label; // ignored
+ BER_Decoder decoder(PEM_Code::decode(in, label));
+ decode(decoder, INITIAL_LEVEL);
+ }
+
+ }
+ catch(std::exception& e)
+ {
+ printf("%s\n", e.what());
+ return 1;
+ }
+ return 0;
+ }
+
+void decode(BER_Decoder& decoder, u32bit level)
+ {
+ BER_Object obj = decoder.get_next_object();
+
+ while(obj.type_tag != NO_OBJECT)
+ {
+ const ASN1_Tag type_tag = obj.type_tag;
+ const ASN1_Tag class_tag = obj.class_tag;
+ const u32bit length = obj.value.size();
+
+ /* hack to insert the tag+length back in front of the stuff now
+ that we've gotten the type info */
+ DER_Encoder encoder;
+ encoder.add_object(type_tag, class_tag, obj.value, obj.value.size());
+ SecureVector<byte> bits = encoder.get_contents();
+
+ BER_Decoder data(bits);
+
+ if(class_tag & CONSTRUCTED)
+ {
+ BER_Decoder cons_info(obj.value);
+ if(type_tag == SEQUENCE)
+ {
+ emit("SEQUENCE", level, length);
+ decode(cons_info, level+1);
+ }
+ else if(type_tag == SET)
+ {
+ emit("SET", level, length);
+ decode(cons_info, level+1);
+ }
+ else
+ {
+ std::string name;
+
+ if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC) ||
+ (class_tag & PRIVATE))
+ {
+ name = "cons [" + to_string(type_tag) + "]";
+
+ if(class_tag & APPLICATION)
+ name += " appl";
+ if(class_tag & CONTEXT_SPECIFIC)
+ name += " context";
+ if(class_tag & PRIVATE)
+ name += " private";
+ }
+ else
+ name = type_name(type_tag) + " (cons)";
+
+ emit(name, level, length);
+ decode(cons_info, level+1);
+ }
+ }
+ else if(class_tag == APPLICATION || class_tag == CONTEXT_SPECIFIC ||
+ class_tag == PRIVATE)
+ {
+ bool not_text = false;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ if(!isgraph(bits[j]) && !isspace(bits[j]))
+ not_text = true;
+
+ Pipe pipe(((not_text) ? new Hex_Encoder : 0));
+ pipe.process_msg(bits);
+ emit("[" + to_string(type_tag) + "]", level, length,
+ pipe.read_all_as_string());
+ }
+ else if(type_tag == OBJECT_ID)
+ {
+ OID oid;
+ data.decode(oid);
+
+ std::string out = OIDS::lookup(oid);
+ if(out != oid.as_string())
+ out += " [" + oid.as_string() + "]";
+
+ emit(type_name(type_tag), level, length, out);
+ }
+ else if(type_tag == INTEGER)
+ {
+ BigInt number;
+ data.decode(number);
+
+ SecureVector<byte> rep;
+
+ /* If it's small, it's probably a number, not a hash */
+ if(number.bits() <= 16)
+ rep = BigInt::encode(number, BigInt::Decimal);
+ else
+ rep = BigInt::encode(number, BigInt::Hexadecimal);
+
+ std::string str;
+ for(u32bit j = 0; j != rep.size(); j++)
+ str += (char)rep[j];
+
+ emit(type_name(type_tag), level, length, str);
+ }
+ else if(type_tag == BOOLEAN)
+ {
+ bool boolean;
+ data.decode(boolean);
+ emit(type_name(type_tag),
+ level, length, (boolean ? "true" : "false"));
+ }
+ else if(type_tag == NULL_TAG)
+ {
+ emit(type_name(type_tag), level, length);
+ }
+ else if(type_tag == OCTET_STRING)
+ {
+ SecureVector<byte> bits;
+ data.decode(bits, type_tag);
+ bool not_text = false;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ if(!isgraph(bits[j]) && !isspace(bits[j]))
+ not_text = true;
+
+ Pipe pipe(((not_text) ? new Hex_Encoder : 0));
+ pipe.process_msg(bits);
+ emit(type_name(type_tag), level, length, pipe.read_all_as_string());
+ }
+ else if(type_tag == BIT_STRING)
+ {
+ SecureVector<byte> bits;
+ data.decode(bits, type_tag);
+
+ std::vector<bool> bit_set;
+
+ for(u32bit j = 0; j != bits.size(); j++)
+ for(u32bit k = 0; k != 8; k++)
+ bit_set.push_back((bool)((bits[bits.size()-j-1] >> (7-k)) & 1));
+
+ std::string bit_str;
+ for(u32bit j = 0; j != bit_set.size(); j++)
+ {
+ bool the_bit = bit_set[bit_set.size()-j-1];
+
+ if(!the_bit && bit_str.size() == 0)
+ continue;
+ bit_str += (the_bit ? "1" : "0");
+ }
+
+ emit(type_name(type_tag), level, length, bit_str);
+ }
+ else if(type_tag == PRINTABLE_STRING ||
+ type_tag == NUMERIC_STRING ||
+ type_tag == IA5_STRING ||
+ type_tag == T61_STRING ||
+ type_tag == VISIBLE_STRING ||
+ type_tag == UTF8_STRING ||
+ type_tag == BMP_STRING)
+ {
+ ASN1_String str;
+ data.decode(str);
+ if(UTF8_TERMINAL)
+ emit(type_name(type_tag), level, length,
+ Charset::transcode(str.iso_8859(),
+ LATIN1_CHARSET, UTF8_CHARSET));
+ else
+ emit(type_name(type_tag), level, length, str.iso_8859());
+ }
+ else if(type_tag == UTC_TIME || type_tag == GENERALIZED_TIME)
+ {
+ X509_Time time;
+ data.decode(time);
+ emit(type_name(type_tag), level, length, time.readable_string());
+ }
+ else
+ fprintf(stderr, "Unknown tag: class=%02X, type=%02X\n",
+ class_tag, type_tag);
+
+ obj = decoder.get_next_object();
+ }
+ }
+
+void emit(const std::string& type, u32bit level, u32bit length,
+ const std::string& value)
+ {
+ const u32bit LIMIT = 128;
+ const u32bit BIN_LIMIT = 64;
+
+ int written = 0;
+ written += printf(" d=%2d, l=%4d: ", level, length);
+ for(u32bit j = INITIAL_LEVEL; j != level; j++)
+ written += printf(" ");
+ written += printf("%s ", type.c_str());
+
+ bool should_skip = false;
+ if(value.length() > LIMIT) should_skip = true;
+ if((type == "OCTET STRING" || type == "BIT STRING") &&
+ value.length() > BIN_LIMIT)
+ should_skip = true;
+
+ if(value != "" && !should_skip)
+ {
+ if(written % 2 == 0) printf(" ");
+ while(written < 50) written += printf(" ");
+ printf(":%s\n", value.c_str());
+ }
+ else
+ printf("\n");
+ }
+
+std::string type_name(ASN1_Tag type)
+ {
+ if(type == PRINTABLE_STRING) return "PRINTABLE STRING";
+ if(type == NUMERIC_STRING) return "NUMERIC STRING";
+ if(type == IA5_STRING) return "IA5 STRING";
+ if(type == T61_STRING) return "T61 STRING";
+ if(type == UTF8_STRING) return "UTF8 STRING";
+ if(type == VISIBLE_STRING) return "VISIBLE STRING";
+ if(type == BMP_STRING) return "BMP STRING";
+
+ if(type == UTC_TIME) return "UTC TIME";
+ if(type == GENERALIZED_TIME) return "GENERALIZED TIME";
+
+ if(type == OCTET_STRING) return "OCTET STRING";
+ if(type == BIT_STRING) return "BIT STRING";
+
+ if(type == INTEGER) return "INTEGER";
+ if(type == NULL_TAG) return "NULL";
+ if(type == OBJECT_ID) return "OBJECT";
+ if(type == BOOLEAN) return "BOOLEAN";
+ return "(UNKNOWN)";
+ }
diff --git a/botan/doc/examples/base.cpp b/botan/doc/examples/base.cpp
new file mode 100644
index 0000000..eca0ccf
--- /dev/null
+++ b/botan/doc/examples/base.cpp
@@ -0,0 +1,44 @@
+/*
+ A simple template for Botan applications, showing startup, etc
+*/
+#include <botan/botan.h>
+using namespace Botan;
+
+/* This is how you can do compile-time version checking */
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,6,3)
+ #error Your Botan installation is too old; upgrade to 1.6.3 or later
+#endif
+
+#include <iostream>
+
+int main(int argc, char* argv[])
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ /* Put it inside the try block so exceptions at startup/shutdown will
+ get caught.
+
+ It will be initialized with default options
+ */
+
+ if(argc > 2)
+ {
+ std::cout << "Usage: " << argv[0] << "[initializer args]\n";
+ return 2;
+ }
+
+ std::string args = (argc == 2) ? argv[1] : "";
+
+ LibraryInitializer init(args);
+ // your operations here
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/base64.cpp b/botan/doc/examples/base64.cpp
new file mode 100644
index 0000000..d35aaf5
--- /dev/null
+++ b/botan/doc/examples/base64.cpp
@@ -0,0 +1,82 @@
+/*
+An Botan example application which emulates a poorly written version of
+"uuencode -m"
+
+Written by Jack Lloyd (lloyd@randombit.net), in maybe an hour scattered
+over 2000/2001
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <cstdlib>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-w] [-c n] [-e|-d] files...\n"
+ " -e : Encode input to base64 strings (default) \n"
+ " -d : Decode base64 input\n"
+ " -w : Wrap lines\n"
+ " -c n: Wrap lines at column n, default 78\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ int column = 78;
+ bool wrap = false;
+ bool encoding = true;
+ std::vector<std::string> files;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ std::string this_arg = argv[j];
+
+ if(this_arg == "-w")
+ wrap = true;
+ else if(this_arg == "-e");
+ else if(this_arg == "-d")
+ encoding = false;
+ else if(this_arg == "-c")
+ {
+ if(argv[j+1])
+ { column = atoi(argv[j+1]); j++; }
+ else
+ {
+ std::cout << "No argument for -c option" << std::endl;
+ return 1;
+ }
+ }
+ else files.push_back(argv[j]);
+ }
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::istream* stream;
+ if(files[j] == "-") stream = &std::cin;
+ else stream = new std::ifstream(files[j].c_str());
+
+ if(!*stream)
+ {
+ std::cout << "ERROR, couldn't open " << files[j] << std::endl;
+ continue;
+ }
+
+ Botan::Pipe pipe((encoding) ?
+ ((Botan::Filter*)new Botan::Base64_Encoder(wrap, column)) :
+ ((Botan::Filter*)new Botan::Base64_Decoder));
+ pipe.start_msg();
+ *stream >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ std::cout << pipe;
+ if(files[j] != "-") delete stream;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/bench.cpp b/botan/doc/examples/bench.cpp
new file mode 100644
index 0000000..37ef110
--- /dev/null
+++ b/botan/doc/examples/bench.cpp
@@ -0,0 +1,98 @@
+#include <botan/benchmark.h>
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/libstate.h>
+
+using namespace Botan;
+
+#include <iostream>
+
+double best_speed(const std::string& algorithm,
+ u32bit milliseconds,
+ RandomNumberGenerator& rng,
+ Timer& timer)
+ {
+ std::map<std::string, double> speeds =
+ algorithm_benchmark(algorithm, milliseconds,
+ timer, rng,
+ global_state().algorithm_factory());
+
+ double best_time = 0;
+
+ for(std::map<std::string, double>::const_iterator i = speeds.begin();
+ i != speeds.end(); ++i)
+ if(i->second > best_time)
+ best_time = i->second;
+
+ return best_time;
+ }
+
+const std::string algos[] = {
+ "AES-128",
+ "AES-192",
+ "AES-256",
+ "Blowfish",
+ "CAST-128",
+ "CAST-256",
+ "DES",
+ "DESX",
+ "TripleDES",
+ "GOST",
+ "IDEA",
+ "KASUMI",
+ "Lion(SHA-256,Turing,8192)",
+ "Luby-Rackoff(SHA-512)",
+ "MARS",
+ "MISTY1",
+ "Noekeon",
+ "RC2",
+ "RC5(12)",
+ "RC5(16)",
+ "RC6",
+ "SAFER-SK(10)",
+ "SEED",
+ "Serpent",
+ "Skipjack",
+ "Square",
+ "TEA",
+ "Twofish",
+ "XTEA",
+ "Adler32",
+ "CRC32",
+ "FORK-256",
+ "GOST-34.11",
+ "HAS-160",
+ "HAS-V",
+ "MD2",
+ "MD4",
+ "MD5",
+ "RIPEMD-128",
+ "RIPEMD-160",
+ "SHA-160",
+ "SHA-256",
+ "SHA-384",
+ "SHA-512",
+ "Skein-512",
+ "Tiger",
+ "Whirlpool",
+ "CMAC(AES-128)",
+ "HMAC(SHA-1)",
+ "X9.19-MAC",
+ "",
+};
+
+int main()
+ {
+ LibraryInitializer init;
+
+ u32bit milliseconds = 1000;
+ AutoSeeded_RNG rng;
+ Default_Benchmark_Timer timer;
+
+ for(u32bit i = 0; algos[i] != ""; ++i)
+ {
+ std::string algo = algos[i];
+ std::cout << algo << ' '
+ << best_speed(algo, milliseconds, rng, timer) << "\n";
+ }
+ }
diff --git a/botan/doc/examples/benchmark.cpp b/botan/doc/examples/benchmark.cpp
new file mode 100644
index 0000000..d046e8d
--- /dev/null
+++ b/botan/doc/examples/benchmark.cpp
@@ -0,0 +1,41 @@
+#include <botan/botan.h>
+#include <botan/benchmark.h>
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <cstdlib>
+
+int main(int argc, char* argv[])
+ {
+ if(argc <= 2)
+ {
+ std::cout << "Usage: " << argv[0] << " seconds <algo1> <algo2> ...\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ Botan::AutoSeeded_RNG rng;
+ Botan::Default_Benchmark_Timer timer;
+
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+
+ double ms = 1000 * std::atof(argv[1]);
+
+ for(size_t i = 2; argv[i]; ++i)
+ {
+ std::string algo = argv[i];
+
+ std::map<std::string, double> results =
+ Botan::algorithm_benchmark(algo, ms, timer, rng, af);
+
+ std::cout << algo << ":\n";
+ for(std::map<std::string, double>::iterator r = results.begin();
+ r != results.end(); ++r)
+ {
+ std::cout << " " << r->first << ": " << r->second << " MiB/s\n";
+ }
+ std::cout << "\n";
+ }
+ }
diff --git a/botan/doc/examples/bzip.cpp b/botan/doc/examples/bzip.cpp
new file mode 100644
index 0000000..02252fb
--- /dev/null
+++ b/botan/doc/examples/bzip.cpp
@@ -0,0 +1,108 @@
+/*
+An Botan example application which emulates a poorly written version of bzip2
+
+Written by Jack Lloyd (lloyd@randombit.net), Jun 9, 2001
+
+This file is in the public domain
+*/
+#include <string>
+#include <cstring>
+#include <vector>
+#include <fstream>
+#include <iostream>
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_BZIP2)
+ #include <botan/bzip2.h>
+#endif
+
+const std::string SUFFIX = ".bz2";
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " [-s] [-d] [-1...9] <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::vector<std::string> files;
+ bool decompress = false, small = false;
+ int level = 9;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-d") == 0) { decompress = true; continue; }
+ if(std::strcmp(argv[j], "-s") == 0) { small = true; continue; }
+ if(std::strcmp(argv[j], "-1") == 0) { level = 1; continue; }
+ if(std::strcmp(argv[j], "-2") == 0) { level = 2; continue; }
+ if(std::strcmp(argv[j], "-3") == 0) { level = 3; continue; }
+ if(std::strcmp(argv[j], "-4") == 0) { level = 4; continue; }
+ if(std::strcmp(argv[j], "-5") == 0) { level = 5; continue; }
+ if(std::strcmp(argv[j], "-6") == 0) { level = 6; continue; }
+ if(std::strcmp(argv[j], "-7") == 0) { level = 7; continue; }
+ if(std::strcmp(argv[j], "-8") == 0) { level = 8; continue; }
+ if(std::strcmp(argv[j], "-9") == 0) { level = 9; continue; }
+ files.push_back(argv[j]);
+ }
+
+ try {
+
+ Botan::Filter* bzip = 0;
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
+ if(decompress)
+ bzip = new Botan::Bzip_Decompression(small);
+ else
+ bzip = new Botan::Bzip_Compression(level);
+#endif
+
+ if(!bzip)
+ {
+ std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
+ return 1;
+ }
+
+ Botan::Pipe pipe(bzip);
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::string infile = files[j], outfile = files[j];
+ if(!decompress)
+ outfile = outfile += SUFFIX;
+ else
+ outfile = outfile.replace(outfile.find(SUFFIX),
+ SUFFIX.length(), "");
+
+ std::ifstream in(infile.c_str());
+ std::ofstream out(outfile.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: could not read " << infile << std::endl;
+ continue;
+ }
+ if(!out)
+ {
+ std::cout << "ERROR: could not write " << outfile << std::endl;
+ continue;
+ }
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ out << pipe;
+
+ in.close();
+ out.close();
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/ca.cpp b/botan/doc/examples/ca.cpp
new file mode 100644
index 0000000..41dd409
--- /dev/null
+++ b/botan/doc/examples/ca.cpp
@@ -0,0 +1,74 @@
+/*
+ Implement the functionality of a simple CA: read in a CA certificate,
+ the associated private key, and a PKCS #10 certificate request. Sign the
+ request and print out the new certificate.
+
+ File names are hardcoded for simplicity.
+ cacert.pem: The CA's certificate (perhaps created by self_sig)
+ caprivate.pem: The CA's private key
+ req.pem: The user's PKCS #10 certificate request
+
+ Written by Jack Lloyd, May 19, 2003
+
+ This file is in the public domain.
+*/
+
+#include <botan/botan.h>
+#include <botan/x509_ca.h>
+#include <botan/util.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 5)
+ {
+ std::cout << "Usage: " << argv[0] << " <passphrase> "
+ << "<ca cert> <ca key> <pkcs10>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ const std::string arg_passphrase = argv[1];
+ const std::string arg_ca_cert = argv[2];
+ const std::string arg_ca_key = argv[3];
+ const std::string arg_req_file = argv[4];
+
+ AutoSeeded_RNG rng;
+
+ X509_Certificate ca_cert(arg_ca_cert);
+
+ std::auto_ptr<PKCS8_PrivateKey> privkey(
+ PKCS8::load_key(arg_ca_key, rng, arg_passphrase)
+ );
+
+ X509_CA ca(ca_cert, *privkey);
+
+ // got a request
+ PKCS10_Request req(arg_req_file);
+
+ // you would insert checks here, and perhaps modify the request
+ // (this example should be extended to show how)
+
+ // now sign the request
+ X509_Time start_time(system_time());
+ X509_Time end_time(system_time() + 365 * 60 * 60 * 24);
+
+ X509_Certificate new_cert = ca.sign_request(req, rng,
+ start_time, end_time);
+
+ // send the new cert back to the requestor
+ std::cout << new_cert.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/checksum.cpp b/botan/doc/examples/checksum.cpp
new file mode 100644
index 0000000..232be05
--- /dev/null
+++ b/botan/doc/examples/checksum.cpp
@@ -0,0 +1,31 @@
+#include <botan/botan.h>
+#include <botan/filters.h>
+
+#include <iostream>
+
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " filename\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("CRC24"), new Hex_Encoder),
+ new Chain(new Hash_Filter("CRC32"), new Hex_Encoder),
+ new Chain(new Hash_Filter("Adler32"), new Hex_Encoder)
+ ));
+
+ DataSource_Stream in(argv[1]);
+
+ pipe.process_msg(in);
+
+ std::cout << pipe.read_all_as_string(0) << "\n";
+ std::cout << pipe.read_all_as_string(1) << "\n";
+ std::cout << pipe.read_all_as_string(2) << "\n";
+ }
diff --git a/botan/doc/examples/cms_dec.cpp b/botan/doc/examples/cms_dec.cpp
new file mode 100644
index 0000000..3fa2853
--- /dev/null
+++ b/botan/doc/examples/cms_dec.cpp
@@ -0,0 +1,116 @@
+#include <botan/botan.h>
+#include <botan/pkcs8.h>
+#include <botan/cms_dec.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ AutoSeeded_RNG rng;
+
+ X509_Certificate mycert("mycert.pem");
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
+
+ X509_Certificate yourcert("yourcert.pem");
+ X509_Certificate cacert("cacert.pem");
+ X509_Certificate int_ca("int_ca.pem");
+
+ X509_Store store;
+ store.add_cert(mycert);
+ store.add_cert(yourcert);
+ store.add_cert(cacert, true);
+ store.add_cert(int_ca);
+
+ DataSource_Stream message(argv[1]);
+
+ User_Interface ui;
+
+ CMS_Decoder decoder(message, store, ui, mykey);
+
+ while(decoder.layer_type() != CMS_Decoder::DATA)
+ {
+ CMS_Decoder::Status status = decoder.layer_status();
+ CMS_Decoder::Content_Type content = decoder.layer_type();
+
+ if(status == CMS_Decoder::FAILURE)
+ {
+ std::cout << "Failure reading CMS data" << std::endl;
+ break;
+ }
+
+ if(content == CMS_Decoder::DIGESTED)
+ {
+ std::cout << "Digested data, hash = " << decoder.layer_info()
+ << std::endl;
+ std::cout << "Hash is "
+ << ((status == CMS_Decoder::GOOD) ? "good" : "bad")
+ << std::endl;
+ }
+
+ if(content == CMS_Decoder::SIGNED)
+ {
+ // how to handle multiple signers? they can all exist within a
+ // single level...
+
+ std::cout << "Signed by " << decoder.layer_info() << std::endl;
+ //std::cout << "Sign time: " << decoder.xxx() << std::endl;
+ std::cout << "Signature is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no known cert)";
+ std::cout << std::endl;
+ }
+ if(content == CMS_Decoder::ENVELOPED ||
+ content == CMS_Decoder::COMPRESSED ||
+ content == CMS_Decoder::AUTHENTICATED)
+ {
+ if(content == CMS_Decoder::ENVELOPED)
+ std::cout << "Enveloped";
+ if(content == CMS_Decoder::COMPRESSED)
+ std::cout << "Compressed";
+ if(content == CMS_Decoder::AUTHENTICATED)
+ std::cout << "MACed";
+
+ std::cout << ", algo = " << decoder.layer_info() << std::endl;
+
+ if(content == CMS_Decoder::AUTHENTICATED)
+ {
+ std::cout << "MAC status is ";
+ if(status == CMS_Decoder::GOOD)
+ std::cout << "valid";
+ else if(status == CMS_Decoder::BAD)
+ std::cout << "bad";
+ else if(status == CMS_Decoder::NO_KEY)
+ std::cout << "(cannot check, no key)";
+ std::cout << std::endl;
+ }
+ }
+ decoder.next_layer();
+ }
+
+ if(decoder.layer_type() == CMS_Decoder::DATA)
+ std::cout << "Message is \"" << decoder.get_data()
+ << '"' << std::endl;
+ else
+ std::cout << "No data anywhere?" << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/cms_enc.cpp b/botan/doc/examples/cms_enc.cpp
new file mode 100644
index 0000000..de16bba
--- /dev/null
+++ b/botan/doc/examples/cms_enc.cpp
@@ -0,0 +1,53 @@
+#include <botan/botan.h>
+#include <botan/cms_enc.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try {
+
+ X509_Certificate mycert("mycert.pem");
+ X509_Certificate mycert2("mycert2.pem");
+ X509_Certificate yourcert("yourcert.pem");
+ X509_Certificate cacert("cacert.pem");
+ X509_Certificate int_ca("int_ca.pem");
+
+ AutoSeeded_RNG rng;
+
+ X509_Store store;
+ store.add_cert(mycert);
+ store.add_cert(mycert2);
+ store.add_cert(yourcert);
+ store.add_cert(int_ca);
+ store.add_cert(cacert, true);
+
+ const std::string msg = "prioncorp: we don't toy\n";
+
+ CMS_Encoder encoder(msg);
+
+ encoder.compress("Zlib");
+ encoder.digest();
+ encoder.encrypt(rng, mycert);
+
+ /*
+ PKCS8_PrivateKey* mykey = PKCS8::load_key("mykey.pem", rng, "cut");
+ encoder.sign(store, *mykey);
+ */
+
+ SecureVector<byte> raw = encoder.get_contents();
+ std::ofstream out("out.der");
+
+ out.write((const char*)raw.begin(), raw.size());
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/cryptobox.cpp b/botan/doc/examples/cryptobox.cpp
new file mode 100644
index 0000000..0a769b0
--- /dev/null
+++ b/botan/doc/examples/cryptobox.cpp
@@ -0,0 +1,50 @@
+/*
+* Cryptobox example
+*/
+#include <botan/botan.h>
+#include <botan/cryptobox.h>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ if(argc != 3)
+ {
+ std::cout << "Usage: cryptobox pass filename\n";
+ return 1;
+ }
+
+ std::string pass = argv[1];
+ std::string filename = argv[2];
+
+ std::ifstream input(filename.c_str());
+
+ std::vector<byte> file_contents;
+ while(input.good())
+ {
+ byte filebuf[4096] = { 0 };
+ input.read((char*)filebuf, sizeof(filebuf));
+ size_t got = input.gcount();
+
+ file_contents.insert(file_contents.end(), filebuf, filebuf+got);
+ }
+
+ std::string ciphertext = CryptoBox::encrypt(&file_contents[0],
+ file_contents.size(),
+ pass, rng);
+
+ std::cout << ciphertext;
+
+ /*
+ std::cout << CryptoBox::decrypt((const byte*)&ciphertext[0],
+ ciphertext.length(),
+ pass);
+ */
+ }
diff --git a/botan/doc/examples/decrypt.cpp b/botan/doc/examples/decrypt.cpp
new file mode 100644
index 0000000..68d5f89
--- /dev/null
+++ b/botan/doc/examples/decrypt.cpp
@@ -0,0 +1,158 @@
+/*
+Decrypt files encrypted with the 'encrypt' example application.
+
+I'm being lazy and writing the output to stdout rather than stripping off the
+".enc" suffix and writing it there. So all diagnostics go to stderr so there is
+no confusion.
+
+Written by Jack Lloyd (lloyd@randombit.net) on August 5, 2002
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <memory>
+
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ #include <botan/zlib.h>
+#endif
+
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string&);
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-p passphrase] file\n"
+ << " -p : Use this passphrase to decrypt\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string filename, passphrase;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-p") == 0)
+ {
+ if(argv[j+1])
+ {
+ passphrase = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -p option" << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ if(filename != "")
+ {
+ std::cout << "You can only specify one file at a time\n";
+ return 1;
+ }
+ filename = argv[j];
+ }
+ }
+
+ if(passphrase == "")
+ {
+ std::cout << "You have to specify a passphrase!" << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: couldn't open " << filename << std::endl;
+ return 1;
+ }
+
+ std::string algo;
+
+ try {
+ std::string header, salt_str, mac_str;
+ std::getline(in, header);
+ std::getline(in, algo);
+ std::getline(in, salt_str);
+ std::getline(in, mac_str);
+
+ if(header != "-------- ENCRYPTED FILE --------")
+ {
+ std::cout << "ERROR: File is missing the usual header" << std::endl;
+ return 1;
+ }
+
+ if(!have_block_cipher(algo))
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+
+ const u32bit key_len = max_keylength_of(algo);
+ const u32bit iv_len = block_size_of(algo);
+
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
+ s2k->set_iterations(8192);
+ s2k->change_salt(b64_decode(salt_str));
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher(algo + "/CBC", bc_key, iv, DECRYPTION),
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ new Zlib_Decompression,
+#endif
+ new Fork(
+ 0,
+ new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Base64_Encoder)
+ )
+ );
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ std::string our_mac = pipe.read_all_as_string(1);
+ if(our_mac != mac_str)
+ std::cout << "WARNING: MAC in message failed to verify\n";
+
+ std::cout << pipe.read_all_as_string(0);
+ }
+ catch(Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+ catch(Decoding_Error)
+ {
+ std::cout << "Bad passphrase or corrupt file\n";
+ return 1;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
diff --git a/botan/doc/examples/dh.cpp b/botan/doc/examples/dh.cpp
new file mode 100644
index 0000000..c808928
--- /dev/null
+++ b/botan/doc/examples/dh.cpp
@@ -0,0 +1,59 @@
+/*
+ A simple DH example
+
+ Written by Jack Lloyd (lloyd@randombit.net), on December 24, 2003
+
+ This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/dh.h>
+#include <botan/rng.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ // Alice creates a DH key and sends (the public part) to Bob
+ DH_PrivateKey private_a(rng, DL_Group("modp/ietf/1024"));
+ DH_PublicKey public_a = private_a; // Bob gets this
+
+ // Bob creates a key with a matching group
+ DH_PrivateKey private_b(rng, public_a.get_domain());
+
+ // Bob sends the key back to Alice
+ DH_PublicKey public_b = private_b; // Alice gets this
+
+ // Both of them create a key using their private key and the other's
+ // public key
+ SymmetricKey alice_key = private_a.derive_key(public_b);
+ SymmetricKey bob_key = private_b.derive_key(public_a);
+
+ if(alice_key == bob_key)
+ {
+ std::cout << "The two keys matched, everything worked\n";
+ std::cout << "The shared key was: " << alice_key.as_string() << "\n";
+ }
+ else
+ {
+ std::cout << "The two keys didn't match!\n";
+ std::cout << "Alice's key was: " << alice_key.as_string() << "\n";
+ std::cout << "Bob's key was: " << bob_key.as_string() << "\n";
+ }
+
+ // Now Alice and Bob hash the key and use it for something
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/dsa_kgen.cpp b/botan/doc/examples/dsa_kgen.cpp
new file mode 100644
index 0000000..4669cf7
--- /dev/null
+++ b/botan/doc/examples/dsa_kgen.cpp
@@ -0,0 +1,66 @@
+/*
+Generate a 1024 bit DSA key and put it into a file. The public key format is
+that specified by X.509, while the private key format is PKCS #8.
+
+The domain parameters are the ones specified as the Java default DSA
+parameters. There is nothing special about these, it's just the only 1024-bit
+DSA parameter set that's included in Botan at the time of this writing. The
+application always reads/writes all of the domain parameters to/from the file,
+so a new set could be used without any problems. We could generate a new set
+for each key, or read a set of DSA params from a file and use those, but they
+mostly seem like needless complications.
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 and PKCS #8 formats, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <botan/botan.h>
+#include <botan/dsa.h>
+#include <botan/rng.h>
+using namespace Botan;
+
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 1 && argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [passphrase]" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ofstream priv("dsapriv.pem");
+ std::ofstream pub("dsapub.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
+
+ DSA_PrivateKey key(rng, group);
+
+ pub << X509::PEM_encode(key);
+ if(argc == 1)
+ priv << PKCS8::PEM_encode(key);
+ else
+ priv << PKCS8::PEM_encode(key, rng, argv[1]);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/dsa_sign.cpp b/botan/doc/examples/dsa_sign.cpp
new file mode 100644
index 0000000..caf0503
--- /dev/null
+++ b/botan/doc/examples/dsa_sign.cpp
@@ -0,0 +1,83 @@
+/*
+Decrypt an encrypted DSA private key. Then use that key to sign a message.
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 and PKCS #8 format keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+const std::string SUFFIX = ".sig";
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile passphrase"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ std::string passphrase(argv[3]);
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::string outfile = argv[2] + SUFFIX;
+ std::ofstream sigfile(outfile.c_str());
+ if(!sigfile)
+ {
+ std::cout << "Couldn't write the signature to "
+ << outfile << std::endl;
+ return 1;
+ }
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PKCS8_PrivateKey> key(
+ PKCS8::load_key(argv[1], rng, passphrase)
+ );
+
+ DSA_PrivateKey* dsakey = dynamic_cast<DSA_PrivateKey*>(key.get());
+
+ if(!dsakey)
+ {
+ std::cout << "The loaded key is not a DSA key!\n";
+ return 1;
+ }
+
+ PK_Signer signer(*dsakey, get_emsa("EMSA1(SHA-1)"));
+
+ DataSource_Stream in(message);
+ byte buf[4096] = { 0 };
+ while(u32bit got = in.read(buf, sizeof(buf)))
+ signer.update(buf, got);
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(signer.signature(rng));
+ sigfile << pipe.read_all_as_string() << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/dsa_ver.cpp b/botan/doc/examples/dsa_ver.cpp
new file mode 100644
index 0000000..3b7ea02
--- /dev/null
+++ b/botan/doc/examples/dsa_ver.cpp
@@ -0,0 +1,92 @@
+/*
+Grab an DSA public key from the file given as an argument, grab a signature
+from another file, and verify the message (which, suprise, is also in a file).
+
+The signature format isn't particularly standard, but it's not bad. It's simply
+the IEEE 1363 signature format, encoded into base64 with a trailing newline
+
+Written by Jack Lloyd (lloyd@randombit.net), August 5, 2002
+ Updated to use X.509 format keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <cstdlib>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " keyfile messagefile sigfile" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::ifstream sigfile(argv[3]);
+ if(!sigfile)
+ {
+ std::cout << "Couldn't read the signature file." << std::endl;
+ return 1;
+ }
+
+ try {
+ std::string sigstr;
+ getline(sigfile, sigstr);
+
+ std::auto_ptr<X509_PublicKey> key(X509::load_key(argv[1]));
+ DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get());
+ if(!dsakey)
+ {
+ std::cout << "The loaded key is not a DSA key!\n";
+ return 1;
+ }
+
+ SecureVector<byte> sig = b64_decode(sigstr);
+
+ std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*dsakey, "EMSA1(SHA-1)"));
+
+ DataSource_Stream in(message);
+ byte buf[4096] = { 0 };
+ while(u32bit got = in.read(buf, sizeof(buf)))
+ ver->update(buf, got);
+
+ bool ok = ver->check_signature(sig);
+
+ if(ok)
+ std::cout << "Signature verified\n";
+ else
+ std::cout << "Signature did NOT verify\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/eax_test.cpp b/botan/doc/examples/eax_test.cpp
new file mode 100644
index 0000000..283e335
--- /dev/null
+++ b/botan/doc/examples/eax_test.cpp
@@ -0,0 +1,241 @@
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <boost/regex.hpp>
+
+#include <botan/botan.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+unsigned to_string(const std::string& s)
+ {
+ std::istringstream stream(s);
+ unsigned n;
+ stream >> n;
+ return n;
+ }
+
+std::string seq(unsigned n)
+ {
+ std::string s;
+
+ for(unsigned i = 0; i != n; ++i)
+ {
+ unsigned char b = (i & 0xFF);
+
+ const char bin2hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ s += bin2hex[(b >> 4)];
+ s += bin2hex[(b & 0x0f)];
+ }
+
+ return s;
+ }
+
+void eax_test(const std::string& algo,
+ const std::string& key_str,
+ const std::string& nonce_str,
+ const std::string& header_str,
+ const std::string& tag_str,
+ const std::string& plaintext_str,
+ const std::string& ciphertext)
+ {
+ /*
+ printf("EAX(algo=%s key=%s nonce=%s header=%s tag=%s pt=%s ct=%s)\n",
+ algo.c_str(), key_str.c_str(), nonce_str.c_str(), header_str.c_str(), tag_str.c_str(),
+ plaintext_str.c_str(), ciphertext.c_str());
+ */
+
+ SymmetricKey key(key_str);
+ InitializationVector iv(nonce_str);
+
+ EAX_Encryption* enc;
+
+ Pipe pipe(new Hex_Decoder,
+ enc = new EAX_Encryption(get_block_cipher(algo)),
+ new Hex_Encoder);
+
+ enc->set_key(key);
+ enc->set_iv(iv);
+
+ OctetString header(header_str);
+
+ enc->set_header(header.begin(), header.length());
+
+ pipe.start_msg();
+ pipe.write(plaintext_str);
+ pipe.end_msg();
+
+ std::string out = pipe.read_all_as_string();
+
+ if(out != ciphertext + tag_str)
+ {
+ printf("BAD enc %s '%s' != '%s%s'\n", algo.c_str(),
+ out.c_str(), ciphertext.c_str(), tag_str.c_str());
+ }
+ else
+ printf("OK enc %s\n", algo.c_str());
+
+ try
+ {
+ EAX_Decryption* dec;
+ Pipe pipe2(new Hex_Decoder,
+ dec = new EAX_Decryption(get_block_cipher(algo)),
+ new Hex_Encoder);
+
+ dec->set_key(key);
+ dec->set_iv(iv);
+
+ dec->set_header(header.begin(), header.length());
+
+ pipe2.start_msg();
+ pipe2.write(ciphertext);
+ pipe2.write(tag_str);
+ pipe2.end_msg();
+
+ std::string out2 = pipe2.read_all_as_string();
+
+ if(out2 != plaintext_str)
+ {
+ printf("BAD decrypt %s '%s'\n", algo.c_str(), out2.c_str());
+ }
+ else
+ printf("OK decrypt %s\n", algo.c_str());
+ }
+ catch(std::exception& e)
+ {
+ printf("%s\n", e.what());
+ }
+
+ }
+
+std::pair<std::string, int> translate_algo(const std::string& in)
+ {
+ if(in == "aes (16 byte key)")
+ return std::make_pair("AES-128", 16);
+
+ if(in == "blowfish (8 byte key)")
+ return std::make_pair("Blowfish", 8);
+
+ if(in == "rc2 (8 byte key)")
+ return std::make_pair("RC2", 8);
+
+ if(in == "rc5 (8 byte key)")
+ return std::make_pair("RC5", 8);
+
+ if(in == "rc6 (16 byte key)")
+ return std::make_pair("RC6", 16);
+
+ if(in == "safer-sk128 (16 byte key)")
+ return std::make_pair("SAFER-SK(10)", 16);
+
+ if(in == "twofish (16 byte key)")
+ return std::make_pair("Twofish", 16);
+
+ if(in == "des (8 byte key)")
+ return std::make_pair("DES", 8);
+
+ if(in == "3des (24 byte key)")
+ return std::make_pair("TripleDES", 24);
+
+ // These 3 are disabled due to differences in base algorithm.
+
+#if 0
+ // XTEA: LTC uses little endian, Botan (and Crypto++) use big-endian
+ // I swapped to LE in XTEA and the vectors did match
+ if(in == "xtea (16 byte key)")
+ return std::make_pair("XTEA", 16);
+
+ // Skipjack: LTC uses big-endian, Botan (and Crypto++) use
+ // little-endian I am not sure if that was the full difference
+ // though, was unable to replicate LTC's EAX vectors with Skipjack
+ if(in == "skipjack (10 byte key)")
+ return std::make_pair("Skipjack", 10);
+
+ // Noekeon: unknown cause, though LTC's lone test vector does not
+ // match Botan
+
+ if(in == "noekeon (16 byte key)")
+ return std::make_pair("Noekeon", 16);
+
+#endif
+
+ return std::make_pair("", 0);
+ }
+
+std::string rep(const std::string& s_in, unsigned n)
+ {
+ std::string s_out;
+
+ for(unsigned i = 0; i != n; ++i)
+ s_out += s_in[i % s_in.size()];
+
+ return s_out;
+ }
+
+void run_tests(std::istream& in)
+ {
+ std::string algo;
+ std::string key;
+
+ while(in.good())
+ {
+ std::string line;
+
+ std::getline(in, line);
+
+ if(line == "")
+ continue;
+
+ if(line.size() > 5 && line.substr(0, 4) == "EAX-")
+ {
+ std::pair<std::string, int> name_and_keylen =
+ translate_algo(line.substr(4));
+
+ algo = name_and_keylen.first;
+ key = seq(name_and_keylen.second);
+ }
+ else if(algo != "")
+ {
+ boost::regex vec_regex("^([ 0-9]{3}): (.*), (.*)$");
+
+ boost::smatch what;
+
+ if(boost::regex_match(line, what, vec_regex, boost::match_extra))
+ {
+ unsigned n = to_string(what[1]);
+ std::string ciphertext = what[2];
+ std::string tag = what[3];
+
+ std::string plaintext = seq(n);
+ std::string header = seq(n);
+ std::string nonce = seq(n);
+
+ eax_test(algo, key, nonce, header, tag,
+ plaintext, ciphertext);
+
+ key = rep(tag, key.size()); // repeat as needed
+ }
+ }
+ }
+
+
+ }
+
+int main()
+ {
+ std::ifstream in("eax_tv.txt");
+
+ Botan::LibraryInitializer init;
+
+ if(!in)
+ {
+ std::cerr << "Couldn't read input file\n";
+ return 1;
+ }
+
+ run_tests(in);
+
+ }
diff --git a/botan/doc/examples/eax_tv.txt b/botan/doc/examples/eax_tv.txt
new file mode 100644
index 0000000..95cd7c1
--- /dev/null
+++ b/botan/doc/examples/eax_tv.txt
@@ -0,0 +1,461 @@
+EAX Test Vectors. Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key. The outputs
+are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous
+step repeated sufficiently.
+
+EAX-aes (16 byte key)
+ 0: , 9AD07E7DBFF301F505DE596B9615DFFF
+ 1: 47, 57C4AC75A42D05260AFA093ACD4499ED
+ 2: C4E2, 26C5AB00325306772E6F6E4C8093F3D2
+ 3: 16177B, 852260F91F27898D4FC176E311F6E1D1
+ 4: F09F68BE, 700766CA231643B5D60C3B91B1B700C1
+ 5: 8472705EDF, AC4C3359326EEA4CF71FC03E0E0292F2
+ 6: 14C25EB5FD0D, 8DBD749CA79CCF11C1B370F8C975858C
+ 7: F6A37F60670A85, AFBD1D5921557187504ADE61014C9622
+ 8: 1AACFEAE8FBAD833, 82F477325D6F76BB81940AE25F9801C2
+ 9: 069414324EC293697C, B980E21C09CA129B69E9032D980A9DC5
+ 10: D8174DE9A2FC92B7DA9C, 1E42CC58BA2C8BFD83806444EA29DB61
+ 11: 2C087DEA30F8B7EE510990, 83DB400A080C4D43CAA6EC3F1085A923
+ 12: F36B93C272A703D3422C6A11, 1370C3AF2F3392916364BBBCC2C62EC1
+ 13: A0F33477BAE2E28E6747AA3193, B626DC719528CAC65DB0EF94E35422CE
+ 14: FCF5193506052E8BFA095C1A5205, F5BD02E0B3C91CC7D6FAAA8A9A76CE6A
+ 15: 3797D7F8599B8EEAB39C56241880DC, 0B70003E77146B903F06EF294FECD517
+ 16: C4BAD0E0356FFD369110C048D45D81BE, DE7C2B1D83BE2CC8EA402ABE1038BB79
+ 17: AF5C358BD31CDCAC2F0EA5252F1C3BE1E4, 2D700986F93B22DFE6695C2A243B4E42
+ 18: 7DEF9056FBDAF491D7206B26B19DEF617AA1, E71A7D00BE972D85C77931D7591B2151
+ 19: 6E9B2C0A90BF9D38A6EA3B5D2B9B2D97F938EB, 5B483D7F15C39602C2918181E57DA341
+ 20: 7C5F68DEE9BBA3B04F11D5FC7C9C7FE6E8B5025C, 0AE6A12D37A9C10BB1A494E16705DC05
+ 21: AF0A886BF673BC72045FC074F06A0176C96105E2E6, 06B2DC9A2868C23F86D710E01E37E07B
+ 22: 5F228A986DFE4301EDBAF07A02E114F1B30932995CD1, 74EBF68627C78B1FD024A59B56B2A8FA
+ 23: 911322F60555118CBECD8DD82F186AC19514316E8D48BA, B6A8BAF2F175CD0C71B63B1EF37E185E
+ 24: E7F52730CFB808EFDB376A5D5DF31A7EF8292DC5FC37E9BC, BA2AD158A2D2E5CE01296402B592E1DB
+ 25: B3F8D7CA47D8D86E94D670AFBAFA3B8D9E186C97DC029D4705, 709D2D2B9975D4729C19D4EAC430E65E
+ 26: 7178FEC027AFADDC2C03518E75CF34D207CAC2EB1537A0DBA520, A315F034CE5E66601444402520F55DE2
+ 27: FC230B2B8522F53459D0B968421469BBA7E683ACB0190393B2870F, 48679A78E470E175CF3D3E9B46CEDFCE
+ 28: 35A641127C78C721ECDC50866C21637FDC9515E41CE60F09015EA713, 0062987222F6412B7AAF8A9ABF6FBF98
+ 29: 3D42D6C113421743C08A6F682CFA0E517D5531BB66241C02EC4DCC26F7, B1AAFE11FA2D6E0C870177DDD7F98FF0
+ 30: DAD065B4669B7C59C8392D8E7BD7E64BC01CEFFF27E335B25A328D356F0E, 8973B9B9ECF26DAB58CCF0787EE928E5
+ 31: EBE626F9E241FD233D9781C359430C982667AA26921B62E98FAEC502C01B0B, 2AC0D7052A2CDCCE8E26FEA7595198AA
+ 32: 64D842B66796A797C2B4C6905742FDF2148FFC445E192F9E03B53810C082F788, 9778B345EC12D222DCC6DBABD2651750
+
+EAX-blowfish (8 byte key)
+ 0: , D8C4C23A6AC0B7B7
+ 1: 2A, 5E0E4BDDB60772FB
+ 2: 7695, 7581B16CCC9C45F1
+ 3: EB14C8, 6223A121CFA216C7
+ 4: 5A5C809C, 4A47658796337D6A
+ 5: 8BC2041181, E1FBA8DBA00571FC
+ 6: 89C666F015FA, 2B4A76A0E699FCFE
+ 7: 86C1FA92484AF6, 31B3B738A261D6F5
+ 8: D1F401C145C9328B, 4C4A045EB489F59C
+ 9: 70C9C7753698324A73, AB298B5B20567EB4
+ 10: A50D9D88DC101B6DC8D2, 529DFCBFD13B8E6C
+ 11: 7CC2885C2BE79C44F28FF2, 566255022B40C81C
+ 12: 6902D58347C29250EE07981C, 34619AF18E14C690
+ 13: AB6C3C4AD3EC45143392B642DA, E6D2DD323DA175BB
+ 14: 7065B28BA8AB67B2FB7B6D5E3FAF, AEDCAA54F4B0772F
+ 15: CBBA14A74AD4ADC0EF036EDAE42D51, F2BFFA4D81BAC034
+ 16: 60A315193F58144F5701D547C79FEEED, 912FDBDB05467DF5
+
+EAX-xtea (16 byte key)
+ 0: , 86881D824E3BC561
+ 1: EE, 4C3505F04611D9C2
+ 2: 80C8, 6A3428BEEAD60738
+ 3: BF88E7, 04F1E99E9F5906C2
+ 4: E06574B7, 33B0153AAEF9776F
+ 5: 42D950AF63, 4A0F415640322FDF
+ 6: C30F6AD46EC9, 9646FE909D2B95CB
+ 7: A0049FCA856A14, A0257289C6BBF278
+ 8: 2814B0C1358440E0, C4B0A2354925E887
+ 9: BF4F062B52C1E489CF, B56442A3CA57A041
+ 10: 63DF433956831B8780FC, ADF9ED0B46DCA19E
+ 11: C317FD079817F50E0E8A16, 2EA0EC993FC603AE
+ 12: 2BD12FDDD81EB11660346D2A, FBC6F69125BBA88D
+ 13: 85D356536FE2843C6BBE60EDBC, BB2FEFD04F230E79
+ 14: 22493009DB01B4746F4927A8C4FB, 64CC08471D93C9AC
+ 15: C0F3C0DB08DC93FBA725D1E02DE084, 77B762213DDCCFFE
+ 16: 568B66D3112556BD98FF9339E9C002E5, C8355F508219FE0C
+
+EAX-rc5 (8 byte key)
+ 0: , 169C7954341EF44D
+ 1: 22, DABFDA9A0B0BA067
+ 2: 2E54, 6A3D6D9AA5877C5A
+ 3: 2A6ECF, 2A34A3AF5DE8919E
+ 4: 9CC5F84F, D3F673EDAF75E3B5
+ 5: FF5611756C, CC647FAAC8D49BF1
+ 6: 74C939BEB31C, C335999CCFE8F5FA
+ 7: 7976B6F7709B5F, 2A7969C5FD063A88
+ 8: 421EEC5022276174, 2C9BFB1EAC3C54A2
+ 9: 6A4761CD266B1C0ECB, 3EA3CCEBC85FAC4E
+ 10: 7C09201098E764239A2E, 8043ABA9BF4D5AEE
+ 11: 8CE26277562F646DE33C88, D72AED48895E3B40
+ 12: 52150F44D37D121560DA87F6, 58E865E22B485906
+ 13: BA0A73B45F93ECFBFC3AB3D8D0, 683D52FA47FB1A52
+ 14: 96546CBE01054AD24CC95DB54724, D80D0D530E5D1DDE
+ 15: 61E654BB18CD26FC36C09F874DC2C7, C65884CB9D9FEC1E
+ 16: 1D77B8BF02CDEAB4A707C07628826D5B, F18D1730C3D64701
+
+EAX-rc6 (16 byte key)
+ 0: , 1DF8B0B92A3F0C951C425AF4830E63FD
+ 1: 1A, 8A2959EBBE90180999994DEB7036DB85
+ 2: 435D, 7EF00CB57DB7B4155DB530D75CE6B025
+ 3: 08A6CF, 2ED6AF0F2D5BAB05F623D389480A01F2
+ 4: A86E54D3, FC69547C8BD922A5BF2F7B26C4D20F98
+ 5: ED0822E439, 0007A3C6DEFC6C912C0E5B853B520368
+ 6: 7BEFC7FD4054, D32C43A4D1086D57C5BCFAEE04EBC600
+ 7: 5235E58E79287C, A27E9C781327C0FC7C55410EB0C828A9
+ 8: CEB5EE99BE521F4D, 547F46383987F2A3582A81A3BCF9B280
+ 9: 0358B063D5F99C3770, C0A73730512CDA6AD49599775D59EDA1
+ 10: 434B9AEE07DFADD0A332, 499BD88881E558E09A8E822BE27D2496
+ 11: D47849E650F350BB622D74, 638E37A84E7FAAF8F5D77F1B061773DC
+ 12: 814592F568284085E79A024B, 9EB1405E8422FE50BC0D88D837A2C650
+ 13: 6F2B55EC91B591082053AF692E, C48F91EF01AA43A1EE3B36D233DDD48B
+ 14: 506CBDD2901838EE2F178B6953DA, 03778957F536509BFCA577B23A18F726
+ 15: 446EE435D3D1848B51BB8C5F7BE4A1, 1129EAEAADE534940546D43242A4C839
+ 16: FB9D2B150C42465B1685D8F069CC06DB, 41E2940F5DC63CB4E2FBEC25ED8A31E6
+ 17: 9684F683260107BE8FEBBEE1D3EEDAA7BD, BAE7C116F7FF96631F4ACEE95C65CEF3
+ 18: 5082B1FE48CD3AB58F63C2DCFDD4069AC736, 19AC7B8EE315CBB7131A283851B32266
+ 19: 8C72AE495B6F003A3C784D144E84E88885F78E, FA4CEC023740A8D670E351FBCF62C1CB
+ 20: 815D6361C7AE34C9D796ADF9C71ABC46AEF88BC9, 9A1F7288C61A6623B9A82748137ED7CC
+ 21: 904A853E2E96BD2B85AAB3F5DFB900E9B3642EE667, 9AA90DBDD461CAD20495DCFBCB513DD2
+ 22: 79D738A462F727B3D3C529ED999B6FDCCD991D1C5A4D, BF0987BEDDE650D73CAE7D380FED3431
+ 23: B2DEFDB7D503A84E83155A04B8DE8C8DBB68C2FC475007, B7CE900CF43CD518024123C76F6DA328
+ 24: 9E723E15439E12F6C46DF8A309AE1E97B6FD18436259CFB0, DF8B6E1E23512CC4CF5FF531A1908F69
+ 25: A7F0AD03CEBCC9202718AA164886E1026975306A664C5AC7A9, 4A771BF8B9A4325705C85E5499FD98E9
+ 26: A53A92AD1C6835F28E04EF591E783D36F3D76E489B31B87BEB7A, AA263B52A6E6A043DE4D7029D4DC73F5
+ 27: 79BE3C38291A7F77E932C8A9DEAC08DE6442EA9B3895B101A14E7B, 33B84DE06342E675E019CD0237292ED0
+ 28: FA108123C5A69571CFDFE8C3D00535121FDE3096DDC0D700F8F26A5A, 764025D7CA1A3F2C54D28956423B0C77
+ 29: 36EC2D67FD977BD2B73DB6D8EB756B3EADA13690E1B6DFC12A4781B34B, 4BC6B38DE3B02283D92F4DF19A5C48C5
+ 30: 96D3243C945905C9732B5927E46F00886D511463B38C86002FC26B65AB8C, 5B5511CDEC35687AB8425AB22D58B4F1
+ 31: 9CF83B87BEA3374AF7722E999863E3DABB858B0383383EAC7757F5B80FD44B, 1E0CBC961940FDA93B73A92DACFD67F3
+ 32: CE3BC3C9FA5EF4AFE5272B3EDD24B1B003FED2C2E501528CFF44D3FABFF52CB4, DC94FDDC78AAB2B7CAA1E1EF149AC355
+
+EAX-safer+ (16 byte key)
+ 0: , B120C7B37450C46189712E4DFD1F0C44
+ 1: CA, 82BA1869C5FF1EF2A4F6ADC1E7DC1F1D
+ 2: DD20, 6BD5601B16C9943A84AC1F99A176E6D1
+ 3: C1C09F, 0911DC63AA414C004E2BD825BECDC93B
+ 4: 27E43F59, BD858F084B082F76814DC385E1FB20D1
+ 5: 2A9A92F246, 5ADC4A32491934AC0BD00FCE686B26F1
+ 6: 52C78C0CD6F4, F35886F46C03EDCA10B3D01CF07B1E0A
+ 7: 23E0D3CED3795F, FE33D96FC98B78A30C0A412C60E93992
+ 8: CD3FC9961559F239, 9982364A61609FC41068260267231EE9
+ 9: 6EA46CB7AD7505C1BC, BB15053EF0F78B9091B3064118F3E9BF
+ 10: 05D9BA230A56CCA0703A, 1338E68E3DC992B6EB2685C668E75869
+ 11: 7AAD6049DFDCA6771AE42B, 35267E431051E1812495615324C4CBE6
+ 12: 8695091532B83B23C296F620, 7B2EEA861E9A91E6B6A911E10FC3FDD1
+ 13: D909DA4BC7372ACAEA78E6A0EE, EA6C1CD16180DF0B07F4E204A4B4FACB
+ 14: 7DEC8443600D0563AEFE87A2064F, DA454728069B3B409889664783588189
+ 15: C042FE656742CD2FE5D9C212D18C6C, 5929E4AECC2CA047BAE948E7023FE4D0
+ 16: 0B84D3CF59EEF7319633F4A397D47CF8, 31F892FFDB7535DF5D9143456E404163
+ 17: 8C9E57AAFA7969B142742B63AB73286600, C418231C44F96660DDBA8C26B3BB3681
+ 18: E9EED66D370A3A6A39C7E0E570D96F807EAC, A4AFE8D1D3C31B956A3BDBD043E7A665
+ 19: 1A5D47992DA5597D1449B4C8DD47B7404C7657, F3ECEE5182014FC3365FDBC4C33CC06A
+ 20: E7C7945FD1AFD3F5DCE666D8A5A2E8A3C11A7A5F, 86D78B2FBA7597B8806BED505B52BDF6
+ 21: 9E2165B47B29CBC4ACD50660E011D691F061209969, E9B1E860BD02085177E1A94E1EE6F3F0
+ 22: 48EA2945C8DD3FE09407BAC8973A861DB15B788C8FFD, 502926712EDB1B3DD13806052C6C75D7
+ 23: F37D46B35B60819EA52B00457D79155C04B55972D0DFA9, BB2B7D210BF0570F422640BF81F39B9E
+ 24: 12E85C0C78227205CC682360C79E35BF58EC6551CF8FE2D0, 042990D7A58D458C570A15DD375DB4E7
+ 25: 4F6C15109DE980DD14A7F4C27F48671E4787C53A564232F427, B097A5990D8067DD89C21473150C070F
+ 26: AAC472E49DB101B564A8A01E2C80C0C6AE9065D332C2DE79FAB6, ACDD587A7DB86542E195DF73AF1C1CBC
+ 27: B9912CE18019C31692A1F7E11D9CCB20297ACCB9DC62C47C01D2C2, B0ACBF028CA5B15E0035D2EB8CA916BE
+ 28: B4F2B1FE14A1ECDC9C8EA1A0120395E6ED1E69D3FC85DD0F3F90F350, 9A561EBC769369B95B9CB74FC6AC27D3
+ 29: 3FE397C8AD02689B7437A37861F0907AF1F6014A293B46419348771C5A, 6B7BEB9BD5018FECD71BE5081C7C2544
+ 30: 5019089142199F7207E1B7731B8B247A18A685B231499DF12A73F5D67D37, 307E93446777005BA1B088F178A0DB6E
+ 31: EAE8F9F02F8DB3D70B78B08CFB0949D99F1A86C958A8E3823736BCEAB86BE1, 6C94F48591C18BF9C450515B73379973
+ 32: B9C795F7A87305B4AD36DBA10B3B1C70B329D29E49C8C6A932D96A74334AEE4A, D18E6E233FEFD6E5C7148BDC1504299C
+
+EAX-twofish (16 byte key)
+ 0: , DB0C02CB069E3773296D3BD4A87A381B
+ 1: 99, 7D21D19E9C440F68E99F1F2EA2668694
+ 2: 0696, EA590EC417C88E23FD23917F9ECFB0C6
+ 3: B9B082, 82D4C9B68DDB02C906496413E13A2D68
+ 4: D6B29D74, 5BCE5CA4F662E883BF7FCAAE5FB2CE01
+ 5: A59C9CB009, CBFB04226D1029A7EC9D64A48A6729BE
+ 6: F4924FE3E355, 3D85B3900DECA0528C815F1447A1F209
+ 7: 679C88D52FB519, 931C7A863C3701D8015FDBD8696C6C30
+ 8: 26DA41C0D115375E, 7627E23E791A4DCB0FA5ED71B1ED2288
+ 9: 8FEC6EB7016AD2B178, F65ED0286A724F0CB2EA317D5022B0D8
+ 10: B5F22415B1334133C531, 87C4F3A8991BBB85984BC4D3305A5CF1
+ 11: 23E1D0ED2E820AFE7DA2FE, 100499F1093FAB2ECF73B643594E98E3
+ 12: 79519ABA91F46B8DAD6D5335, FBDCD1FCDB20AB99135F28A714C6992F
+ 13: 5968D0B4198A0AAD3D0395018F, 781F22E2DA98F83398FCF911B2010057
+ 14: 4E55B14432B601E3EF2EF567CB15, 8BF6E53D7657E56EA3DA1BFD9C9EC06E
+ 15: 6ED89651CE19B3DD1EE5C8780B5015, 131CFD657D32D4E1B35140ADDCA0E13A
+ 16: 2295A968B4D072D12757756247554850, F35FAC95C2AA4155450EAAA6E2E789B5
+ 17: F9B2AA2AA502EA79BBA0C5EAD932B8E1EE, 0ED81AA40B9BF39A9AAEDDDB7A04BEA6
+ 18: 385055F1C1C26C0472A504B4CD225DCA55FE, 24831680B56368231AC54227D737F582
+ 19: 771529585C741A3F8B1C973709892F255A99EE, 2A132B4BF96FD5109DB04459103F5E84
+ 20: E7A2197D9FAA8AB8B303B5EC71AE34AD5EC5DD66, CCAB6518371EC8E0A9E9EE4F7CA5878B
+ 21: 279E54F755EAC6B57375B9EC4406E43DB3139D740C, 7B6F26F2C0ECC9F2DF4EDD7513E6E0B7
+ 22: 27816AA94CBA2BF98E49E595AF5B3FAD12BF1D6F1AC6, D04876C5492D275F15C834E3CF794F0E
+ 23: B5658DC148855F68B282211D879F688F3C142FE555CF81, 4539CDA8A65DB9047AAD76B421B81120
+ 24: 72F0BD4F939C2C9B4FA734DCB0AE4FB9BD342BC8459ED2FE, CEA8469BC0457EBF3418C1114288C904
+ 25: 70568245E6E6BD5D11AD0C74030D7AE08BA05057DEA0FBF4AD, 71554FDE6B87477A51EE4499D78783D2
+ 26: 8702D35BE07D7ADF70684046CC6C72FBBBF821E0BBCCBC973601, 33CC6FBFDA15E306919E0C3BB2E22BB6
+ 27: 0BA23F4A6174165D4A8BA80B7C875340B0F8B2A6967D34E106BC22, 00E6679496714236EECEC84B9AF3072E
+ 28: B9E25ABA84C6BD95B5149E7616FE2E1D6FAACEAAD77A636C60279176, 8D8AD0B9D4C709E1DA370EE01611482A
+ 29: 74759711F6D542581F9F83498FB616638D092732BA07109BF4B5BE045C, 71A40DC777BD09F75362F7B20E0B7576
+ 30: ADBF7E98926484BA2C7F6CD7CD9734FC19265F68AF3BFCAEB025F6296E37, 8DF15B5F69B67F7DABE44E3666B55047
+ 31: 2DC26D449379997D110309B2A0DC2760FCE8CADB4B14ED580F86C70F69C9BA, EFCB60EB2B25737E256BC76700B198EF
+ 32: 2B1890EB9FC0B8293E45D42D2126F4072754AA54E220C853C5F20FBA86BE0795, 1A1B15BBC287372FB9AF035FB124B6A1
+
+EAX-safer-k64 (8 byte key)
+ 0: , 9065118C8F6F7842
+ 1: A1, 1926B3F5112C33BA
+ 2: 2E9A, 5FA6078A0AA7B7C8
+ 3: 56FCE2, 984E385F9441FEC8
+ 4: C33ACE8A, 24AC1CBBCCD0D00A
+ 5: 24307E196B, DD2D52EFCA571B68
+ 6: 31471EAA5155, EB41C2B36FAAA774
+ 7: 03D397F6CFFF62, 7DFBC8485C8B169B
+ 8: 8FA39E282C21B5B2, 2C7EC769966B36D7
+ 9: FEA5402D9A8BE34946, A058E165B5FFB556
+ 10: 6CDEF76554CA845193F0, FED516001FFE039A
+ 11: DC50D19E98463543D94820, 8F9CCF32394498A1
+ 12: 42D8DC34F1974FB4EB2535D7, 77F648526BCBB5AF
+ 13: B75F1299EF6211A6318F6A8EAA, C5086AEA1BE7640B
+ 14: 1E28D68373330829DD1FFC5D083E, 33EDA06A7B5929A2
+ 15: 85529CF87C4706751B0D47CC89CEA6, D031905D6141CBED
+ 16: FE5CB61BAF93B30ED3C296EE85F51864, CC484888F0ABD922
+
+EAX-safer-sk64 (8 byte key)
+ 0: , 5254AB3079CDCB78
+ 1: 75, 798DCF14FEF8F4D1
+ 2: 0300, D5FCA75DAC97849C
+ 3: 520F98, 10E357957CE20898
+ 4: 80E2764D, 5C7F46656C6A46EA
+ 5: C48960CDAA, 3CCF44BD41F01CA8
+ 6: E0E60BD9AA2C, EBB493983FCEE79D
+ 7: D13D8804906A1B, 6EDDCA919978F0B6
+ 8: B7AE14C37A343BFB, 2369E38A9B686747
+ 9: 5DE326BBCC7D0D35E9, 041E5EE8568E941C
+ 10: 13494F5B0635BA3D6E53, EAEEA8AFA55141DD
+ 11: A9BB35B14C831FDA0D83F7, 4002A696F1363987
+ 12: E242043A1C355409819FABFC, 63A085B8886C5FDC
+ 13: 204598B889272C6FE694BDBB4D, 194A1530138EFECE
+ 14: EE3F39E0823A82615679C664DEBF, 1EFF8134C8BEFB3A
+ 15: 8579D87FD3B5E2780BC229665F1D1B, A832CD3E1C1C2289
+ 16: 74D7290D72DA67C4A9EAD434AE3A0A85, 96BAA615A5253CB5
+
+EAX-safer-k128 (16 byte key)
+ 0: , 7E32E3F943777EE7
+ 1: D1, BA00336F561731A7
+ 2: F6D7, 8E3862846CD1F482
+ 3: 5323B5, BD1B8C27B061969B
+ 4: A3EC3416, 170BBB9CE17D1D62
+ 5: 0C74D66716, 7BD024B890C5CE01
+ 6: 6158A630EB37, B5C5BD0652ACB712
+ 7: 17F2D0E019947D, F9FF81E2638EC21C
+ 8: 68E135CC154509C8, AA9EAEF8426886AA
+ 9: EDB1ABE0B486749C21, 355C99E4651C0400
+ 10: DB0C30E9367A72E8F5B2, 631B5671B8A1DB9A
+ 11: D4E5453D9A4C9DB5170FCE, 75A2DF0042E14D82
+ 12: 3F429CC9A550CBDA44107AA7, 2C2977EA13FEBD45
+ 13: A7CA22A97C2361171B415E7083, BFE81185F31727A8
+ 14: 170F79D8B0E3F77299C44208C5B1, D5ED9F9459DF9C22
+ 15: 2E24312D2AE5D5F09D5410900A4BBA, 2FC865CA96EA5A7E
+ 16: 8F3C49A316BA27067FF2C6D99EC8C846, 9D840F40CDB62E4B
+
+EAX-safer-sk128 (16 byte key)
+ 0: , 22D90A75BBA5F298
+ 1: 3F, 98C31AB2DE61DE82
+ 2: 584D, F4701D4A1A09928C
+ 3: B9DEAD, 6E221A98505153DA
+ 4: 06D4A6EB, 0E57C51B96BA13B6
+ 5: 7B58B441CA, E28CCF271F5D0A29
+ 6: 7950E0D1EC24, 2ACDDE6E38180C07
+ 7: 65A4F4E098D7C6, 7DC1C9E9602BACF2
+ 8: FEBE4E72BAA0848F, C4607EA3F138BAD9
+ 9: 9B7BD6D6D655985AA3, 8B2C58A9530EA6AC
+ 10: 60C92F925D1478470203, 51E6F5F6DC996F84
+ 11: 7B40769370E651F64AA654, 74F1F8A8D3F4B9AF
+ 12: 7215832C2FB9C54DF7A9C686, 9BF9AEF14F9151D1
+ 13: AD0F9C79008572AB8AE2466EFF, F375D0583D921B69
+ 14: C05076E2C330A0D25D7CEC80597F, 843C12F84B00A8E0
+ 15: D18F0563AB0278140B0CD9A9B07B34, 262B1688E16A171E
+ 16: 650747091F5C532EE37D2D78EE1EC605, 1BAC36144F9A0E8D
+
+EAX-rc2 (8 byte key)
+ 0: , D6CC8632EEE0F46B
+ 1: 4C, EA19572CB8970CB4
+ 2: 5537, 3EDD3253F6D0C1A8
+ 3: 206FA6, 20FA88F03F240D31
+ 4: 17EE8B40, 702E8194F1FCBFDE
+ 5: 2A89287136, 31C5534786E15FB3
+ 6: 3A6AEDC7066B, 3C663A4081E1D243
+ 7: 8BC5203947A644, 6AAC806C92BFBD6E
+ 8: 2E0274BBE14D21A3, CEB0E0CB73C3664C
+ 9: 9C4B292B0CF17E3A29, F23CD535559023EC
+ 10: 8E322734308F85662877, 46363D7EFC322821
+ 11: C413C405767FF5F98E3667, E7BA35D8F3678E7E
+ 12: D77806B7A218098B1569EADC, BA67C306E5C0181B
+ 13: 4BE5EF74F9E9799A4D636FEA9F, 4C511C44ADBA4030
+ 14: 7E19969170C2C8D8AEBA8C7FBC2C, 54CC6D466A2DF6DA
+ 15: 2EF1CEDC1DD3403CF440FC5561BE33, 61C6FB277E93701F
+ 16: DE052719153EBACE9D7B19F52AC4282F, 4AC2A96F2FA8634C
+
+EAX-des (8 byte key)
+ 0: , 44048B7F240B6F5F
+ 1: 0A, 37009B7D4E09953A
+ 2: 03BA, BFD2FD7758961728
+ 3: 37EE10, 16A6AF96DE888A19
+ 4: 07F44290, 100CA84AA0EDAA1D
+ 5: 389EF0023B, 9614FB800A533268
+ 6: 3F4DBA8AA01C, EFA6B55B7ED5E40F
+ 7: 8C7B837896EAE7, C113CE8F664CE3D4
+ 8: 7011D993D8EDB0C7, B4C370A919F60497
+ 9: 0DEB30A31351B13D7B, 00ABC82DC5F3A1AF
+ 10: 8D3897B2CBE323D6EE1C, 7A2D15627CA1441B
+ 11: DBC002C817DEBFB419F94B, D8EB87F86D6ACDEF
+ 12: 17048E2976FA85AA849E9A80, 229FCD1C9D1E3B9C
+ 13: 30B989EF646544885A478AC198, C1B7EB4F799105C8
+ 14: 5C2E12A7F118A08D6FD585F9C839, C358679FEE6FE7D7
+ 15: 8D1A1E888BBB8648E638C4E74E11B8, 685E006C441448B8
+ 16: 93AE906B8BE4EAC8ED6D8F48F04A7AFF, 71DD7AF752FE28FB
+
+EAX-3des (24 byte key)
+ 0: , 8914311BB990B725
+ 1: D8, 2094EDC5D03E54B1
+ 2: FEE5, 781CFB0EBE3895CA
+ 3: DECF5E, 59918E8A5C4B459B
+ 4: BD583AAD, 2013BEEBEEA795A1
+ 5: 2BC01C6C78, 0B1134DBBEAB5D3F
+ 6: 4D5EAF01A895, AB4D17516ECBA50A
+ 7: AF229F90614480, D3113C0A9D133CD4
+ 8: BCA6F375DF4568E0, 8E9EAEC8E77786BC
+ 9: 575F34219E6DD8DB4C, B40C75139E5D1860
+ 10: A199B8AC433B615EC96F, 774AF803698ADE3D
+ 11: 718A2975DD9A872A68AE10, 3B9460F849CBA7FB
+ 12: AB38E148180F6E2FFBB96F91, E3EE3B8FC50DADBC
+ 13: EB10E0233507459D4A6C29EE80, 8D90B46BB1EAB27E
+ 14: EB48559C320DFB056C37458E19B5, 9315F0C4AF8500EB
+ 15: 9E8C73EADA105749B5D8D97392EDC3, 2E749EE66C1E6A16
+ 16: 600FA4149AF252C87B828C780AEFF8BC, 33D7D11DCDC19936
+
+EAX-cast5 (8 byte key)
+ 0: , 382FB8F7E9F69FDC
+ 1: 99, 20DA959849B3F7AB
+ 2: C54B, D05547C6AFA3484A
+ 3: 579836, AAA92B2321FC50C5
+ 4: FEB7AE55, 639EDF01C4FB965D
+ 5: EA8A6023FA, 01274B3ED5CE102C
+ 6: B7C4E995121F, 712BFE27CAFF6DDE
+ 7: F44236660B0004, FAC51D1DF8EC7093
+ 8: 01CD7E3D0BF29E8A, 049C47A45D868D0B
+ 9: DAB170493DFD6E0365, 6F3AEDD9A3ECF4FD
+ 10: 82C9EEC4803D9CD11FA8, 32683C0A9128C6EA
+ 11: 324AC59E87B244ECE0F32F, F6B095AAB49353CF
+ 12: DBDDAB11D02C9CA5843C406E, EA728FC46DDD3B04
+ 13: D67376C2A4AD92E7DD80E39303, CAF72B7E7C237EB3
+ 14: F2B9BBEF08036C2982C6DDD06918, 70A29D780C22752C
+ 15: 96E3D9141F8EBF520540C2BC9A9C23, CEFC86A1CD48203D
+ 16: 70CABBA983179106AE7FCD5F1F31D5C3, BF7F9168F4F82F56
+
+EAX-noekeon (16 byte key)
+ 0: , 556805EEA595CFB9A30FAD196103D7FD
+ 1: F5, 0A7DAEDFB656526CEF4DDBA8087A227A
+ 2: 7B8C, 249895D79962D5B4D18FE07366281B72
+ 3: ACFF15, DCC489D24832EB106F576AE6B6EB957A
+ 4: 08ADE7DB, 0D3215999E9960EDAB29B78744C7F139
+ 5: 66139213F6, 505E1E7141D043E903C26EE0959EEECD
+ 6: 078B79F880A8, 35B7EB326A55E50332866EEDB682EC20
+ 7: 2809E34D9667D4, FFDEC555F68524A09A6ABACA372077D9
+ 8: 93D267DE1EC635D3, 4FF3561990A56E4B374618722EF850FF
+ 9: F377A4D93FF32F4A51, 91D4070423A90FC54D305169C03F49ED
+ 10: 6244B717E082993EB7A1, 2E3A8A354AFA9473667ED7FDD46BE9FC
+ 11: E917559625D25E6E5F2EDA, 19295C37A70314CC9A1D11FDE8D23C92
+ 12: 1E6DF2EE112A893AB14DFA92, 12C4A89D4CD65F8116A03A135AFD3701
+ 13: 47B18CD762E011770E203CF605, 434909A97E118B20D3AEDC79AFE33A9E
+ 14: 72D9A1A7DA6F33D5E0B927F9F32C, 779C23714FCAA2B2321EC7FB5B03E222
+ 15: DA8B830FFCB3DB274807F780D33240, EDC2F1C8A401F328A53392597730B007
+ 16: B53DD2BB840AD933D36A7B5FFDCCFBBB, 4EC0E6D1F916BF633869239B672B37A1
+ 17: 42936BB9A936C30408660855F4F47F3314, F0DAA6DDA15585E1697ABBB4790B15B5
+ 18: 00372E47F5BA016F1B2A1E680B76AB02052A, CDBF3D241BF7FF96D3DFBEDDB872E901
+ 19: 8AA236B0C8BEF6F67A97C2DF90628F6E5838FF, 731DCD61F7F26004C03519F9500EA824
+ 20: 55338647812FC9D86CBDDCED7120268A4D43F8BA, 0E61B3C835CAD95FD49FEF002C014E72
+ 21: 435820B28E52154B47A04D5E635D8FE37FA47FC985, F6A96DCE4917E8D7C610923627E80970
+ 22: 0D30C15B6FEB4A48B14DD15D41A4B25D442AA677B25C, 28E15CCB74AE992C68BDDC8D87802050
+ 23: D9D701F9AD6B0E13D2CDDA15A5194E7CE8BD2C02137391, 2DB9A15884E9C996C3D6B5BDA44B9598
+ 24: E2390AC5CE10CCFBC72106A52C7F180CB477E3C193CBACA8, 22D3F7DCD6947EA4E78DF57A8E1A9A59
+ 25: ADEFB7D9500658D34996AF6BE6336CD78891064EA1DB8E9785, F239D67D039A15C620A7CD4BE4796B3F
+ 26: 89964C90ABF54A6DF9F13C3681E70C702D80A17BE79F8160F30E, 6336F729ECE1ED7368669D75B7E2DCBA
+ 27: 576B2813CECDA4F905BD5D58349EF070FF41B7EB6BB2B01B061B0B, 125324CBF2ACF1011A44A99A11EC8AFC
+ 28: 430B957481748519A60494F0B5F698F34B1A8235B00AC0D1F0A4442E, 1E80A7FCEBBB8E1E12D6831906154485
+ 29: E781BFE5FCDE0BFC056CC86C4A0B9DD3B815BE8CA678204CF47289B5B5, 190D5AAA9EC1CB4CC86FACE53BF1201B
+ 30: 78BFAC07A9B7B2AE9329BF9F9BF18A1A49DD9587001EFCA00E9AD9752764, 4FB5ECBEEB0995C150EBC66508FA19C1
+ 31: 7D6C20694109DE21F7955855A8FF832347518DD496C2A114DF142C68ACDEAA, B25D4BB34056DC091A7A3950D46C32EC
+ 32: 3E1E4395DEC1AFEA9212B95F37E679B6E2D14DF23C5DE49018C2C8038CC4AD45, 9A6DE7BD41A21918AD504490EF4E581D
+
+EAX-skipjack (10 byte key)
+ 0: , 85F74B6AFFB10ACD
+ 1: 3F, 604DF8BDD98A0B3F
+ 2: EA87, 792374FE07588BF9
+ 3: 0169CA, 489AB8AF69DA3306
+ 4: A7AC3EB1, 428DAF508E24B583
+ 5: AA9028D5B3, C0A44EDA71FB2C86
+ 6: DA97BA88A061, DA2EC34077F42585
+ 7: 7E25FAA41CEBC8, 36D4987551E06D5B
+ 8: F662DA6C9001CBFE, B7DEF76680C316A9
+ 9: 6D3F73EC716E1DA897, 5F0F83BAE4D3513B
+ 10: 2A300F585BEE9C889743, F4756C24DEB72A9C
+ 11: 80518B010DD77C82D19106, 50FF5CAA365F4A70
+ 12: 6E579A2173C861B6F37B4CD3, 81E3E5ABBA8F0292
+ 13: 5B04829880A72C38871C7021F3, 6B26F463708A3294
+ 14: 934177878E9A9A9FB4DEB3895922, EBC1C32F0A2A3E96
+ 15: 07AF486D1C458AAB2DBF13C3243FAD, 87288E41A9E64089
+ 16: 84059283DF9A2A8563E7AF69235F26DF, 351652A0DBCE9D6E
+
+EAX-anubis (16 byte key)
+ 0: , 8E20F19D9BA22ABA09FB86FDE6B9EF38
+ 1: 3B, F4201E546A9160F989191942EC8FD1D3
+ 2: 9F38, 4E3CEAE3E1CB954E021A10E814B71732
+ 3: 4F4769, 3E8F35A6A5B11200E9F1AA38590066CD
+ 4: AB41F5FC, EC4C97A8892AAF5433106D4AC8A49843
+ 5: 414F95D61B, BF831E34D1E3FECB973A8C730ECA2E6D
+ 6: 4798322F06D1, 005BBC30BFEDBE6463536C4F80D1A071
+ 7: F256B6CD1BF4F5, 468A28F0661884B846B191B530C8D064
+ 8: 90906F27A633ADDE, 6D9200A37A7F6A456CB103673184C2E5
+ 9: 16CD3C17C9B4EAB135, 6D716E23D7B35109F55B036EDFA7742E
+ 10: 7AD1C22F1F06298DFB25, B076990F8193543C8F3185D3792BCE56
+ 11: 0476F2ABCD057FE6FEE39D, BB2876DB18C00038FADBBD9B264ACC3C
+ 12: B69EDE336407DBC2EE735857, AB63E5906116A8BE22C52B5DA31B1839
+ 13: C3864C1354065A56470669E602, C72BFD3A0BC73BFF051C9AB2F0DFED93
+ 14: 296D8F183A59020D33890420DD7B, C9D90B9EB42C32EDCF6223587D1598A6
+ 15: 256ED8E9D982616680559979BDF2E9, 179FE4E7BA7E966050D35900317E9916
+ 16: D4ED8F30FF9C0470D75B3B16750A3AE4, 5D50F05BB270A292DFF9F67A3BA84675
+ 17: 40CDEB6388274143CA3C4F6020BD9A4875, B27C7DFB1BFBB3FCCEE0171852C7924E
+ 18: 54EF262EC1801D505C7629D038654EBA0594, 9D2060FCD0A2C577511C7752ADE60BBE
+ 19: F39EE54A37F16DD38B624D7AB8F0D9CBD4B981, BC056C7D2C09D813703CDD63C1C69F44
+ 20: F4E7AD474FCA153ABD670E43081ED09EB2C4CC1A, F244BD4D630272F0D98FCA04226C04F1
+ 21: 039ECC36A0A16273E7246CA1FF19D213AC87B53F29, 3056DB6916C925DF220B6C9980EE141A
+ 22: 7DE1DCDEF01447CA2FE83375A48DD84E4A7CB7C01992, 79AFEA4816EAF8DAC8A5E93960F1594F
+ 23: A886C4B914BF0983003272F226F9B2197EF2DC05ACDDE0, B59D85A0FDA5FA4422F7203C055B97A9
+ 24: 00B3E1E91448E250AAFB695C0643A6577AB453EFECFABF53, 4A7EFF1CBC1AB535122A017203616D85
+ 25: 85E972E774D66D0531E40B8FE9E264A77B50FA883AB0943080, B18E164BF89B7E7AB0DC256DFEC7C72F
+ 26: 004849E39334969B392CB0CF3FDEFB3D792DCBBC15F8328C7EDC, 3C51295711F5F878DE8F0B2B5A26A227
+ 27: A0BAD6C2264AB1578993BA49E59D4598822FFED20A57D88F756FF1, 2EB9D525697A419A10DB2A84AEEA5FBC
+ 28: C34DD806EAB5AD823D78BCA78A7709A705FC94ECC521A367D76C9588, 3C57580C7903039D645C06DBAF07B477
+ 29: C447EC77512938CF7862388C32AF22ACE6B5E4CBAA998BE4F5CBC4D215, 43425D09B7ACFD90371C08953946A955
+ 30: 2C16993AAE624CBA4CDAF34FE3D368559E6BE548292B281439866375013B, 3B7360C3FA8FB1C15D19F567153CB46C
+ 31: 538E5DFAF14854A786851E4165F2E01CDDA963E318FCE4FB58E31A6B5CFC33, 2F8EA13B7A6873FE556CA535ABA0968B
+ 32: 5E29CDB7D9695A110043E9C260104BDF020A3A2A139D4112E918AB584BDD7EDA, 9133213AA7BCF062D2BD37F866683D3F
+
+EAX-khazad (16 byte key)
+ 0: , 75968E54452F6781
+ 1: 95, ADAF5949F09B5A22
+ 2: 6B8F, A06B201947424A11
+ 3: 5BE668, 3251416625DF347A
+ 4: 5A92E82B, 33E25772427D9786
+ 5: 62F9F2ABCC, DE714F5F5D17D6D0
+ 6: 0E3CD825BD8D, A7991C8CB8975ED9
+ 7: 4AD0D999503AAD, 53A827D7886F7227
+ 8: BB08E6FAED1DAEE8, 91A118749B7AB9F3
+ 9: 16E30CB12E20D18495, F8F8B8C1280158F9
+ 10: 616DBCC6346959D89E4A, 506BF35A70297D53
+ 11: F86B022D4B28FDB1F0B7D3, EA42220C805FD759
+ 12: 9B8A3D9CDBADD9BBCCCD2B28, BB478D3CE9A229C9
+ 13: CDC4AB4EF2D5B46E87827241F0, 658EDB9497A91823
+ 14: 1A113D96B21B4AEBDB13E34C381A, 63AD0C4084AC84B0
+ 15: 14DA751E5AF7E01F35B3CE74EE1ACF, 3C76AB64E1724DCE
+ 16: A13BBC7E408D2C550634CBC64690B8FE, 3D4BBC0C76536730
+
diff --git a/botan/doc/examples/ecdsa.cpp b/botan/doc/examples/ecdsa.cpp
new file mode 100644
index 0000000..065203a
--- /dev/null
+++ b/botan/doc/examples/ecdsa.cpp
@@ -0,0 +1,57 @@
+#include <botan/botan.h>
+#include <botan/ecdsa.h>
+#include <botan/pubkey.h>
+#include <botan/look_pk.h>
+
+#include <memory>
+#include <iostream>
+
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ EC_Domain_Params params = get_EC_Dom_Pars_by_oid("1.3.132.0.8");
+
+ ECDSA_PrivateKey ecdsa(rng, params);
+
+ ECDSA_PublicKey ecdsa_pub = ecdsa;
+
+ /*
+ std::cout << params.get_curve().get_p() << "\n";
+ std::cout << params.get_order() << "\n";
+ std::cout << X509::PEM_encode(ecdsa);
+ std::cout << PKCS8::PEM_encode(ecdsa);
+ */
+
+ std::auto_ptr<PK_Signer> signer(get_pk_signer(ecdsa, "EMSA1(SHA-256)"));
+
+ const char* message = "Hello World";
+
+ signer->update((const byte*)message, strlen(message));
+
+ SecureVector<byte> sig = signer->signature(rng);
+
+ std::cout << sig.size() << "\n";
+
+ std::auto_ptr<PK_Verifier> verifier(
+ get_pk_verifier(ecdsa_pub, "EMSA1(SHA-256)"));
+
+ verifier->update((const byte*)message, strlen(message));
+
+ bool ok = verifier->check_signature(sig);
+ if(ok)
+ std::cout << "Signature valid\n";
+ else
+ std::cout << "Bad signature\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+ }
diff --git a/botan/doc/examples/encrypt.cpp b/botan/doc/examples/encrypt.cpp
new file mode 100644
index 0000000..348ee8d
--- /dev/null
+++ b/botan/doc/examples/encrypt.cpp
@@ -0,0 +1,179 @@
+/*
+Encrypt a file using a block cipher in CBC mode. Compresses the plaintext
+with Zlib, MACs with HMAC(SHA-1). Stores the block cipher used in the file,
+so you don't have to specify it when decrypting.
+
+What a real application would do (and what this example should do), is test for
+the presence of the Zlib module, and use it only if it's available. Then add
+some marker to the stream so the other side knows whether or not the plaintext
+was compressed. Bonus points for supporting multiple compression schemes.
+
+Another flaw is that is stores the entire ciphertext in memory, so if the file
+you're encrypting is 1 Gb... you better have a lot of RAM.
+
+Based on the base64 example, of all things
+
+Written by Jack Lloyd (lloyd@randombit.net) on August 5, 2002
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <memory>
+
+#include <botan/botan.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ #include <botan/zlib.h>
+#endif
+
+using namespace Botan;
+
+std::string b64_encode(const SecureVector<byte>&);
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-c algo] -p passphrase file\n"
+ " -p : Use this passphrase to encrypt\n"
+ " -c : Encrypt with block cipher 'algo' (default 3DES)\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string algo = "TripleDES";
+ std::string filename, passphrase;
+
+ // Holy hell, argument processing is a PITA
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-c") == 0)
+ {
+ if(argv[j+1])
+ {
+ algo = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -c option" << std::endl;
+ return 1;
+ }
+ }
+ else if(std::strcmp(argv[j], "-p") == 0)
+ {
+ if(argv[j+1])
+ {
+ passphrase = argv[j+1];
+ j++;
+ }
+ else
+ {
+ std::cout << "No argument for -p option" << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ if(filename != "")
+ {
+ std::cout << "You can only specify one file at a time\n";
+ return 1;
+ }
+ filename = argv[j];
+ }
+ }
+
+ if(passphrase == "")
+ {
+ std::cout << "You have to specify a passphrase!" << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename.c_str());
+ if(!in)
+ {
+ std::cout << "ERROR: couldn't open " << filename << std::endl;
+ return 1;
+ }
+
+ std::string outfile = filename + ".enc";
+ std::ofstream out(outfile.c_str());
+ if(!out)
+ {
+ std::cout << "ERROR: couldn't open " << outfile << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ if(!have_block_cipher(algo))
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+
+ const u32bit key_len = max_keylength_of(algo);
+ const u32bit iv_len = block_size_of(algo);
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
+ s2k->set_iterations(8192);
+ s2k->new_random_salt(rng, 8);
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+
+ // Just to be all fancy we even write a (simple) header.
+ out << "-------- ENCRYPTED FILE --------" << std::endl;
+ out << algo << std::endl;
+ out << b64_encode(s2k->current_salt()) << std::endl;
+
+ Pipe pipe(new Fork(
+ new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Base64_Encoder
+ ),
+ new Chain(
+#ifdef BOTAN_HAS_COMPRESSOR_ZLIB
+ new Zlib_Compression,
+#endif
+ get_cipher(algo + "/CBC", bc_key, iv, ENCRYPTION),
+ new Base64_Encoder(true)
+ )
+ )
+ );
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ out << pipe.read_all_as_string(0) << std::endl;
+ out << pipe.read_all_as_string(1);
+
+ }
+ catch(Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the block cipher \"" << algo << "\"\n";
+ return 1;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+std::string b64_encode(const SecureVector<byte>& in)
+ {
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(in);
+ return pipe.read_all_as_string();
+ }
diff --git a/botan/doc/examples/encrypt2.cpp b/botan/doc/examples/encrypt2.cpp
new file mode 100644
index 0000000..4af0cf0
--- /dev/null
+++ b/botan/doc/examples/encrypt2.cpp
@@ -0,0 +1,55 @@
+#include <botan/botan.h>
+#include <botan/pbkdf2.h>
+#include <botan/hmac.h>
+#include <botan/sha160.h>
+
+#include <fstream>
+
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ std::string passphrase = "secret";
+
+ std::ifstream infile("readme.txt");
+ std::ofstream outfile("readme.txt.enc");
+
+ PKCS5_PBKDF2 pbkdf2(new HMAC(new SHA_160));
+
+ pbkdf2.set_iterations(4096);
+ pbkdf2.new_random_salt(rng, 8);
+ SecureVector<byte> the_salt = pbkdf2.current_salt();
+
+ SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase).bits_of();
+
+ KDF* kdf = get_kdf("KDF2(SHA-1)");
+
+ SymmetricKey key = kdf->derive_key(20, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(20, master_key, "hmac key");
+ InitializationVector iv = kdf->derive_key(8, master_key, "cipher iv");
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Blowfish/CBC/PKCS7", key, iv, ENCRYPTION),
+ new Base64_Encoder,
+ new DataSink_Stream(outfile)
+ ),
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key),
+ new Hex_Encoder)
+ )
+ );
+
+ outfile.write((const char*)the_salt.begin(), the_salt.size());
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.begin(), hmac.size());
+ }
diff --git a/botan/doc/examples/factor.cpp b/botan/doc/examples/factor.cpp
new file mode 100644
index 0000000..ff3c23c
--- /dev/null
+++ b/botan/doc/examples/factor.cpp
@@ -0,0 +1,144 @@
+/*
+ Factor integers using a combination of trial division by small primes,
+ and Pollard's Rho algorithm
+*/
+#include <botan/botan.h>
+#include <botan/reducer.h>
+#include <botan/numthry.h>
+using namespace Botan;
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+
+// Pollard's Rho algorithm, as described in the MIT algorithms book
+
+// We use (x^2+x) mod n instead of (x*2-1) mod n as the random function,
+// it _seems_ to lead to faster factorization for the values I tried.
+
+BigInt rho(const BigInt& n, RandomNumberGenerator& rng)
+ {
+ BigInt x = BigInt::random_integer(rng, 0, n-1);
+ BigInt y = x;
+ BigInt d = 0;
+
+ Modular_Reducer mod_n(n);
+
+ u32bit i = 1, k = 2;
+ while(true)
+ {
+ i++;
+
+ if(i == 0) // overflow, bail out
+ break;
+
+ x = mod_n.multiply((x + 1), x);
+
+ d = gcd(y - x, n);
+ if(d != 1 && d != n)
+ return d;
+
+ if(i == k)
+ {
+ y = x;
+ k = 2*k;
+ }
+ }
+ return 0;
+ }
+
+// Remove (and return) any small (< 2^16) factors
+std::vector<BigInt> remove_small_factors(BigInt& n)
+ {
+ std::vector<BigInt> factors;
+
+ while(n.is_even())
+ {
+ factors.push_back(2);
+ n /= 2;
+ }
+
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; j++)
+ {
+ if(n < PRIMES[j])
+ break;
+
+ BigInt x = gcd(n, PRIMES[j]);
+
+ if(x != 1)
+ {
+ n /= x;
+
+ u32bit occurs = 0;
+ while(x != 1)
+ {
+ x /= PRIMES[j];
+ occurs++;
+ }
+
+ for(u32bit k = 0; k != occurs; k++)
+ factors.push_back(PRIMES[j]);
+ }
+ }
+
+ return factors;
+ }
+
+std::vector<BigInt> factorize(const BigInt& n_in,
+ RandomNumberGenerator& rng)
+ {
+ BigInt n = n_in;
+ std::vector<BigInt> factors = remove_small_factors(n);
+
+ while(n != 1)
+ {
+ if(is_prime(n, rng))
+ {
+ factors.push_back(n);
+ break;
+ }
+
+ BigInt a_factor = 0;
+ while(a_factor == 0)
+ a_factor = rho(n, rng);
+
+ std::vector<BigInt> rho_factored = factorize(a_factor, rng);
+ for(u32bit j = 0; j != rho_factored.size(); j++)
+ factors.push_back(rho_factored[j]);
+
+ n /= a_factor;
+ }
+ return factors;
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " integer\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ BigInt n(argv[1]);
+
+ AutoSeeded_RNG rng;
+
+ std::vector<BigInt> factors = factorize(n, rng);
+ std::sort(factors.begin(), factors.end());
+
+ std::cout << n << ": ";
+ for(u32bit j = 0; j != factors.size(); j++)
+ std::cout << factors[j] << " ";
+ std::cout << "\n";
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/gen_certs.cpp b/botan/doc/examples/gen_certs.cpp
new file mode 100644
index 0000000..f635e1c
--- /dev/null
+++ b/botan/doc/examples/gen_certs.cpp
@@ -0,0 +1,124 @@
+/*
+* Generate a root CA plus httpd, dovecot, and postfix certs/keys
+*
+*/
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+#include <botan/util.h>
+#include <botan/x509self.h>
+#include <botan/x509_ca.h>
+
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+
+void fill_commoninfo(X509_Cert_Options& opts)
+ {
+ opts.country = "US";
+ opts.organization = "randombit.net";
+ opts.email = "admin@randombit.net";
+ opts.locality = "Vermont";
+ }
+
+X509_Certificate make_ca_cert(RandomNumberGenerator& rng,
+ const Private_Key& priv_key,
+ const X509_Time& now,
+ const X509_Time& later)
+ {
+ X509_Cert_Options opts;
+ fill_commoninfo(opts);
+ opts.common_name = "randombit.net CA";
+ opts.start = now;
+ opts.end = later;
+ opts.CA_key();
+
+ return X509::create_self_signed_cert(opts, priv_key, rng);
+ }
+
+PKCS10_Request make_server_cert_req(const Private_Key& key,
+ const std::string& hostname,
+ RandomNumberGenerator& rng)
+ {
+ X509_Cert_Options opts;
+ opts.common_name = hostname;
+ fill_commoninfo(opts);
+
+ opts.add_ex_constraint("PKIX.ServerAuth");
+
+ return X509::create_cert_req(opts, key, rng);
+ }
+
+void save_pair(const std::string& name,
+ const std::string& password,
+ const X509_Certificate& cert,
+ const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ std::string cert_fsname = name + "_cert.pem";
+ std::string key_fsname = name + "_key.pem";
+
+ std::ofstream cert_out(cert_fsname.c_str());
+ cert_out << cert.PEM_encode() << "\n";
+ cert_out.close();
+
+ std::ofstream key_out(key_fsname.c_str());
+ if(password != "")
+ key_out << PKCS8::PEM_encode(key, rng, password);
+ else
+ key_out << PKCS8::PEM_encode(key);
+ key_out.close();
+ }
+
+int main()
+ {
+ const u32bit seconds_in_a_year = 31556926;
+
+ const u32bit current_time = system_time();
+
+ X509_Time now = X509_Time(current_time);
+ X509_Time later = X509_Time(current_time + 4*seconds_in_a_year);
+
+ LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey ca_key(rng, 2048);
+
+ X509_Certificate ca_cert = make_ca_cert(rng, ca_key, now, later);
+
+ const std::string ca_password = "sekrit";
+
+ save_pair("ca", ca_password, ca_cert, ca_key, rng);
+
+ X509_CA ca(ca_cert, ca_key);
+
+ RSA_PrivateKey httpd_key(rng, 1536);
+ X509_Certificate httpd_cert = ca.sign_request(
+ make_server_cert_req(httpd_key, "www.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("httpd", "", httpd_cert, httpd_key, rng);
+
+ RSA_PrivateKey bugzilla_key(rng, 1536);
+ X509_Certificate bugzilla_cert = ca.sign_request(
+ make_server_cert_req(bugzilla_key, "bugs.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("bugzilla", "", bugzilla_cert, bugzilla_key, rng);
+
+ RSA_PrivateKey postfix_key(rng, 1536);
+ X509_Certificate postfix_cert = ca.sign_request(
+ make_server_cert_req(postfix_key, "mail.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("postfix", "", postfix_cert, postfix_key, rng);
+
+ RSA_PrivateKey dovecot_key(rng, 1536);
+ X509_Certificate dovecot_cert = ca.sign_request(
+ make_server_cert_req(dovecot_key, "imap.randombit.net", rng),
+ rng, now, later);
+
+ save_pair("dovecot", "", dovecot_cert, dovecot_key, rng);
+ }
diff --git a/botan/doc/examples/gtk/dsa.cpp b/botan/doc/examples/gtk/dsa.cpp
new file mode 100644
index 0000000..dff5477
--- /dev/null
+++ b/botan/doc/examples/gtk/dsa.cpp
@@ -0,0 +1,556 @@
+/*
+ This shows some of the details involved in a GUI application that uses
+ Botan. Actually most of the code is just dealing with GTK+, but it shows how
+ the password callback and pulse function stuff works. (See gtk_ui.cpp for the
+ acutal password callback code.)
+
+ The major points of interest (assuming what you care about is how to use
+ Botan from a GUI, and not looking at my terrible GTK code) are gtk_ui.cpp
+ and, in this file, GTK_Pulse, gen_key(), and get_key():
+
+ gtk_ui.cpp and get_key() show how to get a passphrase from a user for
+ decrypting (well, in theory, anything), but in this case, PKCS #8 private
+ keys. Which is coincidentally the only thing Botan currently uses UI
+ objects for, though that will probably change eventually. GTK_UI does
+ double duty, for getting passphrases for encryption as well (in
+ do_save_key).
+
+ gen_key() and GTK_Pulse show how to do an activity meter while doing a
+ long-term operation inside Botan. Since, typically, the only operations
+ which take a long time and can't be broken up into smaller parts are prime
+ generation/testing, that is currently where the pulse hooks are
+ called. It's certainly not the most general callback method in the world,
+ but it's general enough that it's usable without getting in the way too
+ much. The callbacks will eventually be extended to other parts of the
+ library (Pipe, maybe) where it's useful.
+
+ This program is in the public domain.
+*/
+#include <fstream>
+#include <iostream>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/libstate.h>
+#include <botan/look_pk.h>
+#include <botan/filters.h>
+#include <botan/dsa.h>
+// we don't have a 'using namespace' here, so it's easy to grep for code that
+// is actually dealing with the library (rather than messing around with GTK).
+
+#include <gtk/gtk.h>
+#include "gtk_ui.h"
+
+/*************************************************
+* Pop up an message box *
+*************************************************/
+static void show_dialog(const std::string& about_message,
+ const std::string& dialog_name)
+ {
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(dialog_name.c_str(),
+ NULL, flags,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_NONE,
+ NULL);
+ GtkWidget* label = gtk_label_new(NULL);
+ gtk_label_set_markup(GTK_LABEL(label), about_message.c_str());
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
+ G_CALLBACK(gtk_widget_destroy),
+ GTK_OBJECT(dialog));
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+ gtk_widget_show_all(dialog);
+ }
+
+/*************************************************
+* Pop up an About box *
+*************************************************/
+static void show_about()
+ {
+ const std::string about_message =
+ "<big>DSA Utility</big>\n"
+ "\n"
+ "A simple application showing how to use Botan within a GUI.\n"
+ "It lets you generate or load keys, and sign text files.\n"
+ "\n"
+ "Send comments/questions to <tt>lloyd@randombit.net</tt>";
+
+ show_dialog(about_message, "About");
+ }
+
+/*************************************************
+* Pop up a help box *
+*************************************************/
+static void show_help()
+ {
+ const std::string help_message =
+ "<big>DSA Utility Help</big>\n"
+ "\n"
+ "Simply, this is a (very) simple text editor, with the added ability\n"
+ "of being able to generate or read a DSA private key, and sign the\n"
+ "text buffer using that key.\n"
+ "\n"
+ "You can load, edit, and save text files as you would normally. If a\n"
+ "key is loaded (done using the commands in the Keys menu), you can\n"
+ "also use the Sign command (in the Signing menu) to generate a\n"
+ "signature for the current file. It will be displayed at the bottom\n"
+ "of the screen (if it has been calculated for the current buffer\n"
+ "contents), and can be saved using the \"Save Sig\" command.\n"
+ "\n"
+ "Signatures generated by this program can be verified using a the\n"
+ "<tt>dsa_ver</tt> example included in the Botan distribution.\n";
+
+ show_dialog(help_message, "Help");
+ }
+
+/*************************************************
+* Get and return a filename from the user *
+*************************************************/
+static std::string get_filename(const std::string& title)
+ {
+ GtkWidget* dialog = gtk_file_selection_new(title.c_str());
+
+ /* Some window managers don't display the titles of transient windows,
+ put a message elsewhere for those people.
+ */
+ GtkWidget* label = gtk_label_new(title.c_str());
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+
+ std::string fsname;
+
+ gtk_widget_show(label); /* dialog_run won't show sub-widgets */
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ fsname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog));
+ gtk_widget_destroy(dialog);
+
+ /* If it's a directory, that's no good */
+ if(fsname.size() && fsname[fsname.size()-1] == '/')
+ return "";
+
+ return fsname;
+ }
+
+/*************************************************
+* Global state *
+*************************************************/
+static Botan::DSA_PrivateKey* key = 0; // our key
+static GtkTextBuffer* buffer = 0; // the text buffer
+static std::string buffer_source;
+ // what file (if any) the buffer's data came from
+static GtkWidget* sig_view = 0; // the signature
+
+/*************************************************
+* Zap the currently set signature (if any) *
+*************************************************/
+static void zap_sig()
+ {
+ gtk_editable_delete_text(GTK_EDITABLE(sig_view), 0, -1);
+ }
+
+/*************************************************
+* Save the current key *
+*************************************************/
+static void do_save_key(const std::string& title)
+ {
+ if(key == 0)
+ return;
+
+ std::string filename = get_filename(title.c_str());
+
+ if(filename != "")
+ {
+ const std::string msg = "Select a passphrase to encrypt the key:";
+
+ std::ofstream out_priv(filename.c_str());
+
+ GTK_UI ui;
+ Botan::User_Interface::UI_Result result;
+ std::string passphrase = ui.get_passphrase(msg, result);
+
+ if(result == Botan::User_Interface::OK)
+ out_priv << Botan::PKCS8::PEM_encode(*key, passphrase);
+ else
+ out_priv << Botan::PKCS8::PEM_encode(*key);
+
+ // for testing
+ //std::cout << X509::PEM_encode(*key);
+ }
+ }
+
+/*************************************************
+* Generate a signature for the text buffer *
+*************************************************/
+static void sign_buffer()
+ {
+ /* No key? Ignore request. */
+ if(key == 0)
+ return;
+
+ /* same format as the text-mode dsa_sign example */
+ Botan::Pipe pipe(new Botan::PK_Signer_Filter(
+ Botan::get_pk_signer(*key, "EMSA1(SHA-1)")
+ ),
+ new Botan::Base64_Encoder
+ );
+
+ /* It would probably be smart to do this a little bit at a time */
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ size_t length = strlen(bits);
+
+ pipe.start_msg();
+ pipe.write((unsigned char*)bits, length);
+ pipe.end_msg();
+
+ std::string sig = pipe.read_all_as_string();
+
+ zap_sig();
+
+ gint position = 0;
+ gtk_editable_insert_text(GTK_EDITABLE(sig_view), sig.c_str(), sig.length(),
+ &position);
+
+ g_free(bits);
+ }
+
+/*************************************************
+* GTK+ pulse callback *
+*************************************************/
+class GTK_Pulse : public Botan::Library_State::UI
+ {
+ public:
+ void pulse(Botan::Pulse_Type);
+ };
+
+void GTK_Pulse::pulse(Botan::Pulse_Type)
+ {
+ /* We need this to flush the updates, otherwise GTK+ will wait until we're
+ done with the computation before doing any updates (generally the right
+ thing, but not with a progress bar).
+ */
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+/*************************************************
+* Actual do the pulse (as a GTK+ timeout func) *
+*************************************************/
+static gboolean gtk_pulse_timeout(void* pbar)
+ {
+ GtkWidget* progress_bar = (GtkWidget*)pbar;
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar));
+ return TRUE; /* keep calling us */
+ }
+
+/*************************************************
+* Generate a new key *
+*************************************************/
+static void gen_key()
+ {
+ /* This gives a nice smooth progress bar, though we do use up quite a bit of
+ CPU for it. Keep in mind that if PULSE_INTERVAL is significantly less
+ than the average time between pulses from the library, the progress bar
+ will jerk around going slower or faster. Keep it at at least 50ms.
+ */
+ const double PROGRESS_PER_PULSE = .01; /* % of bar */
+ const guint32 PULSE_INTERVAL = 30; /* ms */
+
+ delete key;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog =
+ gtk_dialog_new_with_buttons("Generating Key", NULL, flags, NULL);
+
+ GtkWidget* label = gtk_label_new(" Generating new key, please wait... \n");
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
+
+ GtkWidget* progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress_bar),
+ PROGRESS_PER_PULSE);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), progress_bar);
+
+ guint timer_id = gtk_timeout_add(PULSE_INTERVAL, gtk_pulse_timeout,
+ progress_bar);
+
+ gtk_widget_show_all(dialog);
+
+ while(gtk_events_pending())
+ gtk_main_iteration();
+
+ /* Register gtk_pulse so it will be called every so often when we embark
+ on our prime generation quest...
+ */
+ /* this just updates the GUI; the GTK+ timeout function actually updates
+ the progress bar. That's because the amount of time between pulses
+ from the library is rather irregular, so the progress bar looks jerky.
+ */
+ Botan::global_state().set_ui(new GTK_Pulse);
+
+ /* Not generally recommended, since it's slow and there's not much point.
+ However, *because* it's slow, we'll want to put up a progress bar or
+ something, and part of this whole thing is to show how to do that and get
+ the pulse functions to do the right thing.
+ */
+ Botan::DL_Group group(1024, Botan::DL_Group::DSA_Kosherizer);
+ key = new Botan::DSA_PrivateKey(group);
+
+ gtk_timeout_remove(timer_id);
+ Botan::global_state().set_ui(0); // unset the pulse function
+
+ gtk_widget_destroy(dialog);
+
+ do_save_key("Save New Key");
+
+ /* new key, any old sigs are no longer useful */
+ zap_sig();
+ }
+
+/*************************************************
+* Load up a key *
+*************************************************/
+static void get_key()
+ {
+ std::string fsname = get_filename("Select a DSA Key");
+
+ if(fsname != "")
+ {
+ try {
+ delete key;
+ key = 0;
+ zap_sig();
+
+ /*
+ A GTK_UI is a subclass of User_Interface that pops up a dialog that
+ asks the user for a passphrase. It actually works quite well,
+ though the fixed upper limit on the passphrase size is not
+ ideal. Feel free to use it as-is or modify it however you like
+ (gtk_ui.* is public domain).
+ */
+ GTK_UI ui;
+ Botan::PKCS8_PrivateKey* p8_key = Botan::PKCS8::load_key(fsname, ui);
+ key = dynamic_cast<Botan::DSA_PrivateKey*>(p8_key);
+ if(!key)
+ show_dialog("The key in " + fsname + " is not a DSA key",
+ "Failure");
+ }
+ catch(std::exception)
+ {
+ key = 0; // make sure it's not something random
+ show_dialog("Loading the key from " + fsname + " failed.", "Failure");
+ }
+ }
+ }
+
+static void really_sign_buffer()
+ {
+ /* No key? Ask the user for one. */
+ if(key == 0)
+ get_key();
+ sign_buffer();
+ }
+
+/*************************************************
+* Clear the text buffer *
+*************************************************/
+static void new_buffer()
+ {
+ /*
+ In theory, it would be nice to check if this was unsaved text and prompt
+ to save it. However, this really isn't supposed to be a GTK+ example, so
+ we won't.
+ */
+ gtk_text_buffer_set_text(buffer, "", -1);
+ buffer_source = "";
+ }
+
+/*************************************************
+* Put the contents of a file into the buffer *
+*************************************************/
+static void open_buffer()
+ {
+ std::string filename = get_filename("Select File");
+
+ if(filename == "")
+ return;
+
+ std::ifstream in(filename.c_str());
+
+ new_buffer();
+ buffer_source = filename;
+
+ while(in.good())
+ {
+ char buf[1024] = { 0 };
+
+ in.read(buf, 1024);
+ size_t got = in.gcount();
+
+ GtkTextIter iter;
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+ gtk_text_buffer_insert(buffer, &iter, buf, got);
+ }
+ }
+
+/*************************************************
+* Save the signature to a file *
+*************************************************/
+static void save_sig()
+ {
+ std::string sig_file = buffer_source;
+
+ /* No sig, nothing to save */
+ const gchar* sig = gtk_entry_get_text(GTK_ENTRY(sig_view));
+ if(strlen(sig) == 0)
+ return;
+
+ if(sig_file == "")
+ sig_file = get_filename("Select Signature Output File");
+ else
+ sig_file += ".sig";
+
+ std::ofstream out(sig_file.c_str());
+ out << sig << std::endl;
+ }
+
+/*************************************************
+* Save the current key *
+*************************************************/
+static void save_key()
+ {
+ do_save_key("Save Current Key");
+ }
+
+/*************************************************
+* Common case of Save/Save As *
+*************************************************/
+static void do_save(const std::string& filename)
+ {
+ std::ofstream out(filename.c_str());
+
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ out.write(bits, strlen(bits));
+ g_free(bits);
+ buffer_source = filename;
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer_as()
+ {
+ std::string filename = get_filename("Select Output File");
+ if(filename != "")
+ do_save(filename);
+ }
+
+/*************************************************
+* Save the buffer *
+*************************************************/
+static void save_buffer()
+ {
+ if(buffer_source != "")
+ do_save(buffer_source);
+ else
+ save_buffer_as();
+ }
+
+/*************************************************
+* Make a menubar for the app *
+*************************************************/
+static GtkWidget* make_menubar(GtkWidget *window)
+ {
+ static GtkItemFactoryEntry menu_items[] = {
+ { "/_File", NULL, NULL, 0, "<Branch>", NULL },
+ { "/File/_New", "<control>N", new_buffer, 0, NULL, NULL },
+ { "/File/_Open", "<control>O", open_buffer, 0, NULL, NULL },
+ { "/File/_Save", "<control>S", save_buffer, 0, NULL, NULL },
+ { "/File/Save _As", NULL, save_buffer_as, 0, NULL, NULL },
+ { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/Save Sig", NULL, save_sig, 0, NULL, NULL },
+ { "/File/sep2", NULL, NULL, 0, "<Separator>", NULL },
+ { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL, NULL },
+
+ { "/_Keys", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Keys/Open", NULL, get_key, 0, NULL, NULL },
+ { "/Keys/_Generate", NULL, gen_key, 0, NULL, NULL },
+ { "/Keys/Save Current", NULL, save_key, 0, NULL, NULL },
+
+ { "/Signing", NULL, NULL, 0, "<Branch>", NULL },
+ { "/Signing/Sign", NULL, really_sign_buffer, 0, NULL, NULL },
+
+ { "/_Help", NULL, NULL, 0, "<LastBranch>", NULL },
+ { "/Help/Help", NULL, show_help, 0, NULL, NULL },
+ { "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL },
+ { "/Help/About", NULL, show_about, 0, NULL, NULL },
+ };
+
+ GtkAccelGroup* accel_group = gtk_accel_group_new();
+ GtkItemFactory* item_factory =
+ gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
+ const gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
+ gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
+ gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+ return gtk_item_factory_get_widget(item_factory, "<main>");
+ }
+
+int main(int argc, char *argv[])
+ {
+ gtk_init(&argc, &argv);
+
+ try {
+ Botan::LibraryInitializer init;
+
+ /* Create a new top-level window */
+ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "DSA Utility");
+ gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+ gtk_main_quit, NULL);
+
+ /* Create the vbox to hold our stuff */
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 1);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ /* Create the menu bar */
+ GtkWidget *menubar = make_menubar(window);
+
+ /* Create the entry that holds the signature */
+ sig_view = gtk_entry_new();
+ gtk_editable_set_editable(GTK_EDITABLE(sig_view), FALSE);
+
+ /* Create the text box */
+ GtkWidget* view = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
+
+ gtk_widget_set_size_request(view, 640, 480);
+ gtk_text_buffer_set_text(buffer, "Some initial contents.", -1);
+
+ // Resign it on each change: fast enough, but probably not really useful
+ //g_signal_connect(G_OBJECT(buffer), "changed", sign_buffer, 0);
+ g_signal_connect(G_OBJECT(buffer), "changed", zap_sig, 0);
+
+ gtk_container_add(GTK_CONTAINER(vbox), menubar);
+ gtk_container_add(GTK_CONTAINER(vbox), view);
+ gtk_container_add(GTK_CONTAINER(vbox), sig_view);
+
+ gtk_widget_show_all(window);
+
+ gtk_main();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/gtk/gtk_ui.cpp b/botan/doc/examples/gtk/gtk_ui.cpp
new file mode 100644
index 0000000..515fbc5
--- /dev/null
+++ b/botan/doc/examples/gtk/gtk_ui.cpp
@@ -0,0 +1,78 @@
+/*************************************************
+* GTK+ User Interface Source File *
+*************************************************/
+
+#include "gtk_ui.h"
+
+/*************************************************
+* GTK+ Callback *
+*************************************************/
+void GTK_UI::callback(GtkWidget* entry, gpointer passphrase_ptr)
+ {
+ const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ char* passphrase = (char*)passphrase_ptr;
+ strcpy(passphrase, entry_text);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& what,
+ const std::string& source,
+ UI_Result& result) const
+ {
+ std::string msg = "A passphrase is needed to access the " + what;
+ if(source != "") msg += "\nin " + source;
+ return get_passphrase(msg, result);
+ }
+
+/*************************************************
+* Get a passphrase from the user *
+*************************************************/
+std::string GTK_UI::get_passphrase(const std::string& label_text,
+ UI_Result& result) const
+ {
+ const int MAX_PASSPHRASE = 64;
+
+ GtkDialogFlags flags =
+ (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
+
+ GtkWidget* dialog = gtk_dialog_new_with_buttons(
+ "Enter Passphrase",
+ NULL, flags,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+
+ GtkWidget* label = gtk_label_new(label_text.c_str());
+
+ GtkWidget* entry = gtk_entry_new();
+ gtk_entry_set_visibility(GTK_ENTRY(entry), 0);
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+ gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_PASSPHRASE);
+
+ char passphrase_buf[MAX_PASSPHRASE + 1] = { 0 };
+
+ gtk_signal_connect(GTK_OBJECT(entry), "activate",
+ GTK_SIGNAL_FUNC(callback), passphrase_buf);
+
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
+ gtk_widget_show_all(vbox);
+
+ /* Block until we get something back */
+ result = CANCEL_ACTION;
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ result = OK;
+
+ gtk_widget_destroy(dialog);
+
+ if(result == OK)
+ return std::string(passphrase_buf);
+ return "";
+ }
diff --git a/botan/doc/examples/gtk/gtk_ui.h b/botan/doc/examples/gtk/gtk_ui.h
new file mode 100644
index 0000000..9ced83a
--- /dev/null
+++ b/botan/doc/examples/gtk/gtk_ui.h
@@ -0,0 +1,25 @@
+/*************************************************
+* GTK+ User Interface Header File *
+*************************************************/
+
+#ifndef BOTAN_EXT_GTK_UI__
+#define BOTAN_EXT_GTK_UI__
+
+#include <botan/ui.h>
+#include <gtk/gtk.h>
+
+/*************************************************
+* GTK+ Passphrase Callback Object *
+*************************************************/
+class GTK_UI : public Botan::User_Interface
+ {
+ public:
+ std::string get_passphrase(const std::string&, const std::string&,
+ UI_Result&) const;
+
+ std::string get_passphrase(const std::string&, UI_Result&) const;
+
+ static void callback(GtkWidget*, gpointer);
+ };
+
+#endif
diff --git a/botan/doc/examples/gtk/readme.txt b/botan/doc/examples/gtk/readme.txt
new file mode 100644
index 0000000..4f36911
--- /dev/null
+++ b/botan/doc/examples/gtk/readme.txt
@@ -0,0 +1,18 @@
+
+This is an example of how to use Botan in a GUI. You need at least
+Botan 1.6.0.
+
+You'll also need GTK+ 2.x (tested with GTK+ 2.10; should work with
+most versions). Keep in mind that I was learning GTK as I was writing
+this code, so it is not exactly the best GTK code you're likely to
+see.
+
+dsa.cpp is the main GTK+ driver. It has some comments at the top which
+point out major areas of interest.
+
+gtk_ui.* implement a User_Interface object that opens up a GTK+ dialog
+box that asks the user for their passphrase. It works pretty well, the
+only major deficiency is a fixed upper limit on the size of the
+passphrase (currently 64). You may want to use this in your own code,
+assuming you use GTK. If not, it should at least provide an outline
+for writing a version for your favorite windowing system.
diff --git a/botan/doc/examples/hash.cpp b/botan/doc/examples/hash.cpp
new file mode 100644
index 0000000..a97cd60
--- /dev/null
+++ b/botan/doc/examples/hash.cpp
@@ -0,0 +1,64 @@
+/*
+Prints the message digest of files, using an arbitrary hash function
+chosen by the user. This is less flexible that I might like, for example:
+ ./hash sha1 some_file [or md5 or sha-1 or ripemd160 or ...]
+will not work, cause the name lookup is case-sensitive. Oh well...
+
+Written by Jack Lloyd (lloyd@randombit.net), on August 4, 2002
+ - December 16, 2003: "Fixed" to accept "sha1" or "md5" as a hash name
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 3)
+ {
+ std::cout << "Usage: " << argv[0] << " digest <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string hash = argv[1];
+ /* a couple of special cases, kind of a crock */
+ if(hash == "sha1") hash = "SHA-1";
+ if(hash == "md5") hash = "MD5";
+
+ try {
+ if(!Botan::have_hash(hash))
+ {
+ std::cout << "Unknown hash \"" << argv[1] << "\"" << std::endl;
+ return 1;
+ }
+
+ Botan::Pipe pipe(new Botan::Hash_Filter(hash),
+ new Botan::Hex_Encoder);
+
+ int skipped = 0;
+ for(int j = 2; argv[j] != 0; j++)
+ {
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j-2-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/hash_fd.cpp b/botan/doc/examples/hash_fd.cpp
new file mode 100644
index 0000000..82ca2c3
--- /dev/null
+++ b/botan/doc/examples/hash_fd.cpp
@@ -0,0 +1,71 @@
+/*
+Written by Jack Lloyd (lloyd@randombit.net), on Prickle-Prickle,
+the 10th of Bureaucracy, 3167.
+
+This file is in the public domain
+
+This is just like the normal hash application, but uses the Unix I/O system
+calls instead of C++ iostreams. Previously, this version was much faster and
+smaller, but GCC 3.1's libstdc++ seems to have been improved enough that the
+difference is now fairly minimal.
+
+Nicely enough, doing the change required changing only about 3 lines of code.
+
+Note that this requires you to be on a machine running some sort of Unix. Well,
+I guess any POSIX.1 compliant OS (in theory).
+*/
+
+#include <iostream>
+#include <botan/botan.h>
+
+#if !defined(BOTAN_HAS_PIPE_UNIXFD_IO)
+ #error "You didn't compile the pipe_unixfd module into Botan"
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 3)
+ {
+ std::cout << "Usage: " << argv[0] << " digest <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ Botan::Pipe pipe(new Botan::Hash_Filter(argv[1]),
+ new Botan::Hex_Encoder);
+
+ int skipped = 0;
+ for(int j = 2; argv[j] != 0; j++)
+ {
+ int file = open(argv[j], O_RDONLY);
+ if(file == -1)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ close(file);
+ pipe.set_default_msg(j-2-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ }
+ catch(Botan::Algorithm_Not_Found)
+ {
+ std::cout << "Don't know about the hash function \"" << argv[1] << "\""
+ << std::endl;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/hash_quickly.cpp b/botan/doc/examples/hash_quickly.cpp
new file mode 100644
index 0000000..e719a71
--- /dev/null
+++ b/botan/doc/examples/hash_quickly.cpp
@@ -0,0 +1,90 @@
+#include <botan/botan.h>
+#include <botan/benchmark.h>
+#include <botan/filters.h>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <map>
+#include <cstdlib>
+
+/*
+Try to find the fastest SHA-1 implementation and use it to hash
+files. In most programs this isn't worth the bother and
+overhead. However with large amount of input, it is worth it. On tests
+on a Core2 system with the SHA-1 SSE2 code enabled, over a few hundred
+Mb or so the overhead paid for itself.
+
+Of course you could also just do this once and save it as an
+application config, which is probably the smart thing to do.
+*/
+
+void set_fastest_implementation(const std::string& algo,
+ Botan::RandomNumberGenerator& rng,
+ double ms = 30)
+ {
+ Botan::Default_Benchmark_Timer timer;
+
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+
+ std::map<std::string, double> results =
+ Botan::algorithm_benchmark(algo, ms, timer, rng, af);
+
+ std::string fastest_provider = "";
+ double best_res = 0;
+
+ for(std::map<std::string, double>::iterator r = results.begin();
+ r != results.end(); ++r)
+ {
+ std::cout << r->first << " @ " << r->second << " MiB/sec\n";
+
+ if(fastest_provider == "" || r->second > best_res)
+ {
+ fastest_provider = r->first;
+ best_res = r->second;
+ }
+ }
+
+ std::cout << "Using " << fastest_provider << "\n";
+
+ af.set_preferred_provider(algo, fastest_provider);
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc <= 1)
+ {
+ std::cout << "Usage: " << argv[0] << " <file> <file> ...\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+ Botan::AutoSeeded_RNG rng;
+
+ const std::string hash = "SHA-1";
+
+ set_fastest_implementation(hash, rng);
+
+ // Here we intentionally use the 'old style' lookup interface
+ // which will also respect the provider settings. Or can use:
+ // global_state().algorithm_factory().make_hash_function(hash)
+ Botan::Pipe pipe(
+ new Botan::Hash_Filter(Botan::get_hash(hash)),
+ new Botan::Hex_Encoder
+ );
+
+ for(size_t i = 1; argv[i]; ++i)
+ {
+ std::ifstream in(argv[i]);
+ if(!in)
+ continue;
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+
+ std::cout << argv[i] << " = "
+ << pipe.read_all_as_string(Botan::Pipe::LAST_MESSAGE) << "\n";
+
+ }
+ }
diff --git a/botan/doc/examples/hasher.cpp b/botan/doc/examples/hasher.cpp
new file mode 100644
index 0000000..5ba982f
--- /dev/null
+++ b/botan/doc/examples/hasher.cpp
@@ -0,0 +1,58 @@
+/*
+A Botan example application which emulates a
+poorly written version of "gpg --print-md"
+
+Written by Jack Lloyd (lloyd@randombit.net), quite a while ago (as of June
+2001)
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ const int COUNT = 3;
+ std::string name[COUNT] = { "MD5", "SHA-1", "RIPEMD-160" };
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ Botan::Filter* hash[COUNT] = {
+ new Botan::Chain(new Botan::Hash_Filter(name[0]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[1]),
+ new Botan::Hex_Encoder),
+ new Botan::Chain(new Botan::Hash_Filter(name[2]),
+ new Botan::Hex_Encoder)
+ };
+
+ Botan::Pipe pipe(new Botan::Fork(hash, COUNT));
+
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ for(int k = 0; k != COUNT; k++)
+ {
+ pipe.set_default_msg(k);
+ std::cout << name[k] << "(" << argv[j] << ") = " << pipe << std::endl;
+ }
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/hasher2.cpp b/botan/doc/examples/hasher2.cpp
new file mode 100644
index 0000000..12d3c85
--- /dev/null
+++ b/botan/doc/examples/hasher2.cpp
@@ -0,0 +1,72 @@
+/*
+Identical to hasher.cpp, but uses Pipe in a different way.
+
+Note this tends to be much less efficient than hasher.cpp, because it does
+three passes over the file. For a small file, it doesn't really matter. But for
+a large file, or for something you can't re-read easily (socket, stdin, ...)
+this is a bad idea.
+
+Written by Jack Lloyd (lloyd@randombit.net), Feb 8 2001
+
+This file is in the public domain
+*/
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ const int COUNT = 3;
+ std::string name[COUNT] = { "MD5", "SHA-1", "RIPEMD-160" };
+
+ Botan::Pipe pipe;
+
+ int skipped = 0;
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ Botan::Filter* hash[COUNT] = {
+ new Botan::Hash_Filter(name[0]),
+ new Botan::Hash_Filter(name[1]),
+ new Botan::Hash_Filter(name[2]),
+ };
+
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ for(int k = 0; k != COUNT; k++)
+ {
+ pipe.reset();
+ pipe.append(hash[k]);
+ pipe.append(new Botan::Hex_Encoder);
+ pipe.start_msg();
+
+ // trickiness: the >> op reads until EOF, but seekg won't work
+ // unless we're in the "good" state (which EOF is not).
+ file.clear();
+ file.seekg(0, std::ios::beg);
+ file >> pipe;
+ pipe.end_msg();
+ }
+ file.close();
+ for(int k = 0; k != COUNT; k++)
+ {
+ std::string out = pipe.read_all_as_string(COUNT*(j-1-skipped) + k);
+ std::cout << name[k] << "(" << argv[j] << ") = " << out << std::endl;
+ }
+ }
+
+ return 0;
+ }
diff --git a/botan/doc/examples/make_prime.cpp b/botan/doc/examples/make_prime.cpp
new file mode 100644
index 0000000..0c90b2b
--- /dev/null
+++ b/botan/doc/examples/make_prime.cpp
@@ -0,0 +1,73 @@
+#include <botan/numthry.h>
+#include <botan/auto_rng.h>
+#include <botan/botan.h>
+
+using namespace Botan;
+
+#include <set>
+#include <iostream>
+#include <iterator>
+#include <map>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+ AutoSeeded_RNG rng;
+
+ std::set<BigInt> primes;
+
+ std::map<int, int> bit_count;
+
+ int not_new = 0;
+
+ while(primes.size() < 10000)
+ {
+ u32bit start_cnt = primes.size();
+
+ u32bit bits = 18;
+
+ if(rng.next_byte() % 128 == 0)
+ bits -= rng.next_byte() % (bits-2);
+
+ bit_count[bits]++;
+
+ //std::cout << "random_prime(" << bits << ")\n";
+
+ BigInt p = random_prime(rng, bits);
+
+ if(p.bits() != bits)
+ {
+ std::cout << "Asked for " << bits << " got " << p
+ << " " << p.bits() << " bits\n";
+ return 1;
+ }
+
+ primes.insert(random_prime(rng, bits));
+
+ if(primes.size() != start_cnt)
+ std::cout << primes.size() << "\n";
+ else
+ not_new++;
+
+ //std::cout << "miss: " << not_new << "\n";
+
+ if(not_new % 100000 == 0)
+ {
+ for(std::map<int, int>::iterator i = bit_count.begin();
+ i != bit_count.end(); ++i)
+ std::cout << "bit_count[" << i->first << "] = "
+ << i->second << "\n";
+ std::copy(primes.begin(), primes.end(),
+ std::ostream_iterator<BigInt>(std::cout, " "));
+ }
+ }
+
+ std::cout << "Generated all? primes\n";
+ /*
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
+ {
+ if(primes.count(PRIMES[j]) != 1)
+ std::cout << "Missing " << PRIMES[j] << "\n";
+ }
+ */
+ }
diff --git a/botan/doc/examples/passhash.cpp b/botan/doc/examples/passhash.cpp
new file mode 100644
index 0000000..7f5bbc2
--- /dev/null
+++ b/botan/doc/examples/passhash.cpp
@@ -0,0 +1,86 @@
+#include <botan/botan.h>
+#include <botan/pbkdf2.h>
+#include <botan/hmac.h>
+#include <botan/sha160.h>
+#include <iostream>
+#include <memory>
+
+using namespace Botan;
+
+std::string password_hash(const std::string& pass,
+ RandomNumberGenerator& rng);
+bool password_hash_ok(const std::string& pass, const std::string& hash);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cerr << "Usage: " << argv[0] << " password\n";
+ std::cerr << "Usage: " << argv[0] << " password hash\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+
+ if(argc == 2)
+ {
+ AutoSeeded_RNG rng;
+
+ std::cout << "H('" << argv[1] << "') = "
+ << password_hash(argv[1], rng) << '\n';
+ }
+ else
+ {
+ bool ok = password_hash_ok(argv[1], argv[2]);
+ if(ok)
+ std::cout << "Password and hash match\n";
+ else
+ std::cout << "Password and hash do not match\n";
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << '\n';
+ return 1;
+ }
+ return 0;
+ }
+
+std::string password_hash(const std::string& pass,
+ RandomNumberGenerator& rng)
+ {
+ PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
+
+ kdf.set_iterations(10000);
+ kdf.new_random_salt(rng, 6); // 48 bits
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.start_msg();
+ pipe.write(kdf.current_salt());
+ pipe.write(kdf.derive_key(12, pass).bits_of());
+ pipe.end_msg();
+
+ return pipe.read_all_as_string();
+ }
+
+bool password_hash_ok(const std::string& pass, const std::string& hash)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.start_msg();
+ pipe.write(hash);
+ pipe.end_msg();
+
+ SecureVector<byte> hash_bin = pipe.read_all();
+
+ PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
+
+ kdf.set_iterations(10000);
+ kdf.change_salt(hash_bin, 6);
+
+ SecureVector<byte> cmp = kdf.derive_key(12, pass).bits_of();
+
+ return same_mem(cmp.begin(), hash_bin.begin() + 6, 12);
+ }
diff --git a/botan/doc/examples/pkcs10.cpp b/botan/doc/examples/pkcs10.cpp
new file mode 100644
index 0000000..d719baf
--- /dev/null
+++ b/botan/doc/examples/pkcs10.cpp
@@ -0,0 +1,73 @@
+/*
+Generate a 1024 bit RSA key, and then create a PKCS #10 certificate request for
+that key. The private key will be stored as an encrypted PKCS #8 object, and
+stored in another file.
+
+Written by Jack Lloyd (lloyd@randombit.net), April 7, 2003
+
+This file is in the public domain
+*/
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 6)
+ {
+ std::cout << "Usage: " << argv[0] <<
+ " passphrase name country_code organization email" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey priv_key(rng, 1024);
+ // If you want a DSA key instead of RSA, comment out the above line and
+ // uncomment this one:
+ //DSA_PrivateKey priv_key(DL_Group("dsa/jce/1024"));
+
+ std::ofstream key_file("private.pem");
+ key_file << PKCS8::PEM_encode(priv_key, rng, argv[1]);
+
+ X509_Cert_Options opts;
+
+ opts.common_name = argv[2];
+ opts.country = argv[3];
+ opts.organization = argv[4];
+ opts.email = argv[5];
+
+ /* Some hard-coded options, just to give you an idea of what's there */
+ opts.challenge = "a fixed challenge passphrase";
+ opts.locality = "Baltimore";
+ opts.state = "MD";
+ opts.org_unit = "Testing";
+ opts.add_ex_constraint("PKIX.ClientAuth");
+ opts.add_ex_constraint("PKIX.IPsecUser");
+ opts.add_ex_constraint("PKIX.EmailProtection");
+
+ opts.xmpp = "someid@xmpp.org";
+
+ PKCS10_Request req = X509::create_cert_req(opts, priv_key, rng);
+
+ std::ofstream req_file("req.pem");
+ req_file << req.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/pqg_gen.cpp b/botan/doc/examples/pqg_gen.cpp
new file mode 100644
index 0000000..e4b9598
--- /dev/null
+++ b/botan/doc/examples/pqg_gen.cpp
@@ -0,0 +1,116 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/auto_rng.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+#include <botan/numthry.h>
+#include <botan/dl_group.h>
+using namespace Botan;
+
+bool check(RandomNumberGenerator& rng,
+ std::map<std::string, std::string>);
+
+int main()
+ {
+ try {
+ Botan::LibraryInitializer init("use_engines");
+
+ AutoSeeded_RNG rng;
+
+ std::ifstream in("PQGGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "H")
+ {
+ bool result = check(rng, inputs);
+ std::cout << "." << std::flush;
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+
+ std::cout << "\n";
+ }
+
+ inputs.clear();
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(RandomNumberGenerator& rng,
+ std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ h("0x"+inputs["H"]);
+
+ if(h < 1 || h >= p-1) return false;
+
+ //u32bit c = to_u32bit(inputs["c"]);
+
+ Pipe pipe(new Hex_Decoder);
+ pipe.process_msg(inputs["Seed"]);
+ SecureVector<byte> seed = pipe.read_all();
+
+ BigInt our_p, our_q;
+
+ u32bit qbits = (p.bits() <= 1024) ? 160 : 256;
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ bool found = generate_dsa_primes(rng, af, our_p, our_q,
+ p.bits(), qbits, seed);
+
+ if(!found) /* bad seed */
+ return false;
+
+ if(our_p != p) return false;
+ if(our_q != q) return false;
+
+ BigInt our_g = power_mod(h, (p-1)/q, p);
+
+ if(our_g != g) return false;
+
+ return true;
+ }
diff --git a/botan/doc/examples/readme.txt b/botan/doc/examples/readme.txt
new file mode 100644
index 0000000..48686db
--- /dev/null
+++ b/botan/doc/examples/readme.txt
@@ -0,0 +1,77 @@
+This directory contains some simple example applications for the Botan crypto
+library. If you want to see something a bit more complicated, check out the
+stuff in the checks/ directory. Both it and the files in this directory are in
+the public domain, and you may do with them however you please.
+
+The makefile assumes that you built the library with g++; you'll have to change
+it if this assumption proves incorrect.
+
+Some of these examples will not build on all configurations of the library,
+particularly 'bzip', 'encrypt', 'decrypt', and 'hash_fd', as they require
+various extensions.
+
+The examples are fairly small (50-150 lines). And that's with argument
+processing, I/O, error checking, etc (which counts for 40% or more of most of
+them). This is partially to make them easy to understand, and partially because
+I'm lazy. For the most part, the examples cover the stuff a 'regular'
+application might need.
+
+Feel free to contribute new examples. You too can gain fame and fortune by
+writing example apps for obscure libraries!
+
+The examples are:
+
+* X.509 examples
+--------
+ca: A (very) simple CA application
+
+x509info: Prints some information about an X.509 certificate
+
+pkcs10: Generates a PKCS #10 certificate request for a 1024 bit RSA key
+
+self_sig: Generates a self-signed X.509v3 certificate with a 1024 bit RSA key
+--------
+
+* RSA examples (also uses X.509, PKCS #8, block ciphers, MACs, S2K algorithms)
+--------
+rsa_kgen: Generate an RSA key, encrypt the private key with a passphrase,
+ output the keys to a pair of files
+rsa_enc: Take a public key (generated by rsa_kgen) and encrypt a file
+ using CAST-128, MAC it with HMAC(SHA-1)
+rsa_dec: Decrypt a file encrypted by rsa_enc
+
+* DSA examples (also uses X.509, PKCS #8)
+--------
+dsa_kgen: Generates a DSA key, encrypts the private key with a passphrase
+ and stores it in PKCS #8 format.
+dsa_sign: Produce a DSA signature for a file. Uses SHA-1
+dsa_ver: Verify a message signed with dsa_sign
+
+* Encryption examples
+--------
+encrypt: Encrypt a file in CBC mode with a block cipher of your choice. Adds
+ a MAC for authentication, and compresses the plaintext with Zlib.
+
+decrypt: Decrypt the result of 'encrypt'
+
+xor_ciph: Shows how to add a new algorithm from application code
+
+* Hash function examples (also shows different methods of using Pipe)
+--------
+hash: Print digests of files, using any chosen hash function
+
+hash_fd: Same as hash, except that it uses Unix file I/O. Requires the
+ pipe_unixfd extension
+
+hasher: Print MD5, SHA-1, and RIPEMD-160 digests of files
+
+hasher2: Same as hasher, just shows an alternate method
+
+stack: A demonstration of some more advanced Pipe functionality. Prints
+ MD5 hashes
+
+* Misc examples
+--------
+base64: Simple base64 encoding/decoding tool
+
+bzip: Bzip2 compression/decompression.
diff --git a/botan/doc/examples/ressol.cpp b/botan/doc/examples/ressol.cpp
new file mode 100644
index 0000000..43bb68d
--- /dev/null
+++ b/botan/doc/examples/ressol.cpp
@@ -0,0 +1,80 @@
+#include <botan/numthry.h>
+#include <botan/auto_rng.h>
+#include <botan/botan.h>
+
+using namespace Botan;
+
+#include <iostream>
+
+void test_ressol(const BigInt& p, RandomNumberGenerator& rng)
+ {
+ std::cout << p << std::endl;
+
+ // const BigInt p_16 = p / 16;
+
+ int noroot = 0, false_result = 0;
+
+ for(int j = 0; j != 1000; ++j)
+ {
+ BigInt x = BigInt::random_integer(rng, 0, p);
+ //if(x % p_16 == 0)
+ //std::cout << "p = " << p << " x = " << x << "\n";
+
+ BigInt sqrt_x = ressol(x, p);
+
+ if(sqrt_x < 0)
+ {
+ ++noroot;
+ continue;
+ }
+
+ BigInt check = square(sqrt_x) % p;
+
+ if(check != x % p)
+ {
+ std::cout << "FAIL "
+ << "x = " << x << "; "
+ << "p = " << p << "; "
+ << "s = " << sqrt_x << "; "
+ << "s^2%p = " << check << "\n";
+ ++false_result;
+ }
+ }
+ /*
+ std::cout << "nomatch=" << nomatch << " "
+ << "noroot=" << noroot << " "
+ << "false=" << false_result << "\n";
+ */
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+ AutoSeeded_RNG rng;
+
+#if 0
+ std::cout << ressol(8, 17) << "\n";
+ std::cout << ressol_orig(8, 17) << "\n";
+#endif
+
+#if 1
+ for(int j = 16; j != 1024; ++j)
+ {
+ std::cout << "Round " << j << "\n";
+ BigInt p = random_prime(rng, j);
+ test_ressol(p, rng);
+ //printf("%d\n", j);
+
+
+ }
+#endif
+ /*
+ for(u32bit j = 9; j != PRIME_TABLE_SIZE; ++j)
+ {
+ std::cout << "PRIME[" << j << "] == " << PRIMES[j] << std::endl;
+ //printf("%d - ", PRIMES[j]);
+ test_ressol(PRIMES[j], rng);
+ //printf("\n");
+ }
+ */
+ }
diff --git a/botan/doc/examples/rng_test.cpp b/botan/doc/examples/rng_test.cpp
new file mode 100644
index 0000000..8d4253a
--- /dev/null
+++ b/botan/doc/examples/rng_test.cpp
@@ -0,0 +1,143 @@
+#include <botan/botan.h>
+#include <botan/x931_rng.h>
+#include <botan/filters.h>
+#include <botan/lookup.h>
+
+#include <iostream>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include <stdexcept>
+
+using namespace Botan;
+
+std::vector<std::pair<std::string, std::string> > read_file(const std::string&);
+
+SecureVector<byte> decode_hex(const std::string& in)
+ {
+ SecureVector<byte> result;
+
+ try {
+ Botan::Pipe pipe(new Botan::Hex_Decoder);
+ pipe.process_msg(in);
+ result = pipe.read_all();
+ }
+ catch(std::exception& e)
+ {
+ result.destroy();
+ }
+ return result;
+ }
+
+std::string hex_encode(const byte in[], u32bit len)
+ {
+ Botan::Pipe pipe(new Botan::Hex_Encoder);
+ pipe.process_msg(in, len);
+ return pipe.read_all_as_string();
+ }
+
+class Fixed_Output_RNG : public RandomNumberGenerator
+ {
+ public:
+ bool is_seeded() const { return !buf.empty(); }
+
+ byte random()
+ {
+ if(buf.empty())
+ throw std::runtime_error("Out of bytes");
+
+ byte out = buf.front();
+ buf.pop_front();
+ return out;
+ }
+
+ void randomize(byte out[], u32bit len) throw()
+ {
+ for(u32bit j = 0; j != len; j++)
+ out[j] = random();
+ }
+
+ std::string name() const { return "Fixed_Output_RNG"; }
+
+ void reseed(u32bit) {}
+
+ void clear() throw() {}
+
+ void add_entropy(const byte in[], u32bit len)
+ {
+ buf.insert(buf.end(), in, in + len);
+ }
+
+ void add_entropy_source(EntropySource* es) { delete es; }
+
+ Fixed_Output_RNG() {}
+ private:
+ std::deque<byte> buf;
+ };
+
+void x931_tests(std::vector<std::pair<std::string, std::string> > vecs,
+ const std::string& cipher)
+ {
+ for(size_t j = 0; j != vecs.size(); ++j)
+ {
+ const std::string result = vecs[j].first;
+ const std::string input = vecs[j].second;
+
+ ANSI_X931_RNG prng(get_block_cipher(cipher),
+ new Fixed_Output_RNG);
+
+ SecureVector<byte> x = decode_hex(input);
+ prng.add_entropy(x.begin(), x.size());
+
+ SecureVector<byte> output(result.size() / 2);
+ prng.randomize(output, output.size());
+
+ if(decode_hex(result) != output)
+ std::cout << "FAIL";
+ else
+ std::cout << "PASS";
+
+ std::cout << " Seed " << input << " "
+ << "Got " << hex_encode(output, output.size()) << " "
+ << "Exp " << result << "\n";
+ }
+
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ x931_tests(read_file("ANSI931_AES128VST.txt.vst"), "AES-128");
+ x931_tests(read_file("ANSI931_AES192VST.txt.vst"), "AES-192");
+ x931_tests(read_file("ANSI931_AES256VST.txt.vst"), "AES-256");
+ x931_tests(read_file("ANSI931_TDES2VST.txt.vst"), "TripleDES");
+ x931_tests(read_file("ANSI931_TDES3VST.txt.vst"), "TripleDES");
+ }
+
+
+std::vector<std::pair<std::string, std::string> >
+read_file(const std::string& fsname)
+ {
+ std::ifstream in(fsname.c_str());
+
+ std::vector<std::pair<std::string, std::string> > out;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "")
+ break;
+
+ std::vector<std::string> l;
+ boost::split(l, line, boost::is_any_of(":"));
+
+ if(l.size() != 2)
+ throw std::runtime_error("Bad line " + line);
+
+ out.push_back(std::make_pair(l[0], l[1]));
+ }
+
+ return out;
+ }
diff --git a/botan/doc/examples/row_encryptor.cpp b/botan/doc/examples/row_encryptor.cpp
new file mode 100644
index 0000000..1dac82f
--- /dev/null
+++ b/botan/doc/examples/row_encryptor.cpp
@@ -0,0 +1,143 @@
+#include <string>
+#include <memory>
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+
+#include <botan/botan.h>
+#include <botan/filters.h>
+#include <botan/eax.h>
+
+using namespace Botan;
+
+/**
+Encrypt and decrypt small rows
+*/
+class Row_Encryptor
+ {
+ public:
+ Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng);
+
+ std::string encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ std::string decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt);
+
+ private:
+ Row_Encryptor(const Row_Encryptor&) {}
+ Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); }
+
+ Pipe enc_pipe, dec_pipe;
+ EAX_Encryption* eax_enc; // owned by enc_pipe
+ EAX_Decryption* eax_dec; // owned by dec_pipe;
+ };
+
+Row_Encryptor::Row_Encryptor(const std::string& passphrase,
+ RandomNumberGenerator& rng)
+ {
+ std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-160)"));
+
+ s2k->set_iterations(10000);
+
+ s2k->new_random_salt(rng, 10); // 10 bytes == 80 bits
+
+ SecureVector<byte> key = s2k->derive_key(32, passphrase).bits_of();
+
+ /*
+ Save pointers to the EAX objects so we can change the IV as needed
+ */
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* proto = af.prototype_block_cipher("Serpent");
+
+ if(!proto)
+ throw std::runtime_error("Could not get a Serpent proto object");
+
+ enc_pipe.append(eax_enc = new EAX_Encryption(proto->clone()));
+ dec_pipe.append(eax_dec = new EAX_Decryption(proto->clone()));
+
+ eax_enc->set_key(key);
+ eax_dec->set_key(key);
+ }
+
+std::string Row_Encryptor::encrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_enc->set_iv(salt);
+
+ enc_pipe.start_msg();
+ enc_pipe.write(input);
+ enc_pipe.end_msg();
+
+ return enc_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+std::string Row_Encryptor::decrypt(const std::string& input,
+ const MemoryRegion<byte>& salt)
+ {
+ eax_dec->set_iv(salt);
+
+ dec_pipe.start_msg();
+ dec_pipe.write(input);
+ dec_pipe.end_msg();
+
+ return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE);
+ }
+
+/*************************
+ Test code follows:
+*/
+
+#include <botan/loadstor.h>
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ Row_Encryptor encryptor("secret passphrase", rng);
+
+ std::vector<std::string> original_inputs;
+
+ for(u32bit i = 0; i != 15000; ++i)
+ {
+ std::ostringstream out;
+
+ // This will actually generate variable length inputs (when
+ // there are leading 0s, which are skipped), which is good
+ // since it assures performance is OK across a mix of lengths
+ // TODO: Maybe randomize the length slightly?
+
+ for(u32bit j = 0; j != 32; ++j)
+ out << std::hex << (int)rng.next_byte();
+
+ original_inputs.push_back(out.str());
+ }
+
+ std::vector<std::string> encrypted_values;
+ MemoryVector<byte> salt(4); // keep out of loop to avoid excessive dynamic allocation
+
+ for(u32bit i = 0; i != original_inputs.size(); ++i)
+ {
+ std::string input = original_inputs[i];
+ store_le(i, salt);
+
+ encrypted_values.push_back(encryptor.encrypt(input, salt));
+ }
+
+ for(u32bit i = 0; i != encrypted_values.size(); ++i)
+ {
+ std::string ciphertext = encrypted_values[i];
+ store_le(i, salt); // NOTE: same salt value as previous loop (index value)
+
+ std::string output = encryptor.decrypt(ciphertext, salt);
+
+ if(output != original_inputs[i])
+ std::cout << "BOOM " << i << "\n";
+ }
+
+ }
diff --git a/botan/doc/examples/rsa_dec.cpp b/botan/doc/examples/rsa_dec.cpp
new file mode 100644
index 0000000..25ce33f
--- /dev/null
+++ b/botan/doc/examples/rsa_dec.cpp
@@ -0,0 +1,127 @@
+/*
+Decrypt an encrypted RSA private key. Then use that key to decrypt a
+message. This program can decrypt messages generated by rsa_enc, and uses the
+same key format as that generated by rsa_kgen.
+
+Written by Jack Lloyd (lloyd@randombit.net), June 3-5, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h> // for get_kdf
+#include <botan/rsa.h>
+using namespace Botan;
+
+SecureVector<byte> b64_decode(const std::string&);
+SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
+
+const std::string SUFFIX = ".enc";
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 4)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile passphrase"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PKCS8_PrivateKey> key(
+ PKCS8::load_key(argv[1], rng, argv[3]));
+
+ RSA_PrivateKey* rsakey = dynamic_cast<RSA_PrivateKey*>(key.get());
+ if(!rsakey)
+ {
+ std::cout << "The loaded key is not a RSA key!\n";
+ return 1;
+ }
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ std::string outfile(argv[2]);
+ outfile = outfile.replace(outfile.find(SUFFIX), SUFFIX.length(), "");
+
+ std::ofstream plaintext(outfile.c_str());
+ if(!plaintext)
+ {
+ std::cout << "Couldn't write the plaintext to "
+ << outfile << std::endl;
+ return 1;
+ }
+
+ std::string enc_masterkey_str;
+ std::getline(message, enc_masterkey_str);
+ std::string mac_str;
+ std::getline(message, mac_str);
+
+ SecureVector<byte> enc_masterkey = b64_decode(enc_masterkey_str);
+
+ std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsakey,
+ "EME1(SHA-1)"));
+ SecureVector<byte> masterkey = decryptor->decrypt(enc_masterkey);
+
+ SymmetricKey cast_key = derive_key("CAST", masterkey, 16);
+ InitializationVector iv = derive_key("IV", masterkey, 8);
+ SymmetricKey mac_key = derive_key("MAC", masterkey, 16);
+
+ Pipe pipe(new Base64_Decoder,
+ get_cipher("CAST-128/CBC/PKCS7", cast_key, iv, DECRYPTION),
+ new Fork(
+ 0,
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+
+ pipe.start_msg();
+ message >> pipe;
+ pipe.end_msg();
+
+ std::string our_mac = pipe.read_all_as_string(1);
+
+ if(our_mac != mac_str)
+ std::cout << "WARNING: MAC in message failed to verify\n";
+
+ plaintext << pipe.read_all_as_string(0);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+SecureVector<byte> b64_decode(const std::string& in)
+ {
+ Pipe pipe(new Base64_Decoder);
+ pipe.process_msg(in);
+ return pipe.read_all();
+ }
+
+SymmetricKey derive_key(const std::string& param,
+ const SymmetricKey& masterkey,
+ u32bit outputlength)
+ {
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
+ return kdf->derive_key(outputlength, masterkey.bits_of(), param);
+ }
diff --git a/botan/doc/examples/rsa_enc.cpp b/botan/doc/examples/rsa_enc.cpp
new file mode 100644
index 0000000..f9b8c55
--- /dev/null
+++ b/botan/doc/examples/rsa_enc.cpp
@@ -0,0 +1,151 @@
+/*
+ Grab an RSA public key from the file given as an argument, grab a message
+ from another file, and encrypt the message.
+
+ Algorithms used:
+ RSA with EME1(SHA-1) padding to encrypt the master key
+ CAST-128 in CBC mode with PKCS#7 padding to encrypt the message.
+ HMAC with SHA-1 is used to authenticate the message
+
+ The keys+IV used are derived from the master key (the thing that's encrypted
+ with RSA) using KDF2(SHA-1). The 3 outputs of KDF2 are parameterized by P,
+ where P is "CAST", "IV" or "MAC", in order to make each key/IV unique.
+
+ The format is:
+ 1) First line is the master key, encrypted with the recipients public key
+ using EME1(SHA-1), and then base64 encoded.
+ 2) Second line is the first 96 bits (12 bytes) of the HMAC(SHA-1) of
+ the _plaintext_
+ 3) Following lines are base64 encoded ciphertext (CAST-128 as described),
+ each broken after ~72 characters.
+
+Written by Jack Lloyd (lloyd@randombit.net), June 3, 2002
+ Updated to use KDF2, September 8, 2002
+ Updated to read X.509 keys, October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/rsa.h>
+using namespace Botan;
+
+std::string b64_encode(const SecureVector<byte>&);
+SymmetricKey derive_key(const std::string&, const SymmetricKey&, u32bit);
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " keyfile messagefile" << std::endl;
+ return 1;
+ }
+
+ std::ifstream message(argv[2]);
+ if(!message)
+ {
+ std::cout << "Couldn't read the message file." << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string output_name(argv[2]);
+ output_name += ".enc";
+ std::ofstream ciphertext(output_name.c_str());
+ if(!ciphertext)
+ {
+ std::cout << "Couldn't write the ciphertext to " << output_name
+ << std::endl;
+ return 1;
+ }
+
+ try {
+ std::auto_ptr<X509_PublicKey> key(X509::load_key(argv[1]));
+ RSA_PublicKey* rsakey = dynamic_cast<RSA_PublicKey*>(key.get());
+ if(!rsakey)
+ {
+ std::cout << "The loaded key is not a RSA key!\n";
+ return 1;
+ }
+
+ AutoSeeded_RNG rng;
+
+ std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsakey,
+ "EME1(SHA-1)"));
+
+ /* Generate the master key (the other keys are derived from this)
+
+ Basically, make the key as large as can be encrypted by this key, up
+ to a limit of 256 bits. For 512 bit keys, the master key will be >160
+ bits. A >600 bit key will use the full 256 bit master key.
+
+ In theory, this is not enough, because we derive 16+16+8=40 bytes of
+ secrets (if you include the IV) using the master key, so they are not
+ statistically indepedent. Practically speaking I don't think this is
+ a problem.
+ */
+ SymmetricKey masterkey(rng,
+ std::min(32U, encryptor->maximum_input_size()));
+
+ SymmetricKey cast_key = derive_key("CAST", masterkey, 16);
+ SymmetricKey mac_key = derive_key("MAC", masterkey, 16);
+ SymmetricKey iv = derive_key("IV", masterkey, 8);
+
+ SecureVector<byte> encrypted_key =
+ encryptor->encrypt(masterkey.bits_of(), rng);
+
+ ciphertext << b64_encode(encrypted_key) << std::endl;
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("CAST-128/CBC/PKCS7", cast_key, iv,
+ ENCRYPTION),
+ new Base64_Encoder(true) // true == do linebreaking
+ ),
+ new Chain(
+ new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
+ new Base64_Encoder
+ )
+ )
+ );
+
+ pipe.start_msg();
+ message >> pipe;
+ pipe.end_msg();
+
+ /* Write the MAC as the second line. That way we can pull it off right
+ from the start, and feed the rest of the file right into a pipe on the
+ decrypting end.
+ */
+
+ ciphertext << pipe.read_all_as_string(1) << std::endl;
+ ciphertext << pipe.read_all_as_string(0);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << std::endl;
+ }
+ return 0;
+ }
+
+std::string b64_encode(const SecureVector<byte>& in)
+ {
+ Pipe pipe(new Base64_Encoder);
+ pipe.process_msg(in);
+ return pipe.read_all_as_string();
+ }
+
+SymmetricKey derive_key(const std::string& param,
+ const SymmetricKey& masterkey,
+ u32bit outputlength)
+ {
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)"));
+ return kdf->derive_key(outputlength, masterkey.bits_of(), param);
+ }
diff --git a/botan/doc/examples/rsa_kgen.cpp b/botan/doc/examples/rsa_kgen.cpp
new file mode 100644
index 0000000..b7e90ef
--- /dev/null
+++ b/botan/doc/examples/rsa_kgen.cpp
@@ -0,0 +1,65 @@
+/*
+Generate an RSA key of a specified bitlength, and put it into a pair of key
+files. One is the public key in X.509 format (PEM encoded), the private key is
+in PKCS #8 format (also PEM encoded).
+
+Written by Jack Lloyd (lloyd@randombit.net), June 2-3, 2002
+ Updated to use X.509 and PKCS #8 on October 21, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+using namespace Botan;
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " bitsize [passphrase]"
+ << std::endl;
+ return 1;
+ }
+
+ u32bit bits = std::atoi(argv[1]);
+ if(bits < 1024 || bits > 4096)
+ {
+ std::cout << "Invalid argument for bitsize" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::ofstream pub("rsapub.pem");
+ std::ofstream priv("rsapriv.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey key(rng, bits);
+ pub << X509::PEM_encode(key);
+
+ if(argc == 2)
+ priv << PKCS8::PEM_encode(key);
+ else
+ priv << PKCS8::PEM_encode(key, rng, argv[2]);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/rsa_manykey.cpp b/botan/doc/examples/rsa_manykey.cpp
new file mode 100644
index 0000000..4122bc8
--- /dev/null
+++ b/botan/doc/examples/rsa_manykey.cpp
@@ -0,0 +1,36 @@
+/*
+Generate a whole sequence of keys (for benchmarking)
+*/
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/rsa.h>
+#include <botan/parsing.h>
+using namespace Botan;
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+ AutoSeeded_RNG rng;
+
+ for(u32bit j = 512; j <= 8192; j += 256)
+ {
+ std::cout << j << "...";
+
+ RSA_PrivateKey key(rng, j);
+
+ std::ofstream priv(("rsa/" + to_string(j) + ".pem").c_str());
+ priv << PKCS8::PEM_encode(key);
+ priv.close();
+
+ std::cout << " done" << std::endl;
+ }
+
+ return 0;
+ }
diff --git a/botan/doc/examples/self_sig.cpp b/botan/doc/examples/self_sig.cpp
new file mode 100644
index 0000000..0bf17e3
--- /dev/null
+++ b/botan/doc/examples/self_sig.cpp
@@ -0,0 +1,79 @@
+/*
+Generate a 1024 bit RSA key, and then create a self-signed X.509v3 certificate
+with that key. If the do_CA variable is set to true, then it will be marked for
+CA use, otherwise it will get extensions appropriate for use with a client
+certificate. The private key is stored as an encrypted PKCS #8 object in
+another file.
+
+Written by Jack Lloyd (lloyd@randombit.net), April 7, 2003
+
+This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 7)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " passphrase [CA|user] name country_code organization email"
+ << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ std::string CA_flag = argv[2];
+ bool do_CA = false;
+
+ if(CA_flag == "CA") do_CA = true;
+ else if(CA_flag == "user") do_CA = false;
+ else
+ {
+ std::cout << "Bad flag for CA/user switch: " << CA_flag << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey key(rng, 1024);
+
+ std::ofstream priv_key("private.pem");
+ priv_key << PKCS8::PEM_encode(key, rng, argv[1]);
+
+ X509_Cert_Options opts;
+
+ opts.common_name = argv[3];
+ opts.country = argv[4];
+ opts.organization = argv[5];
+ opts.email = argv[6];
+ /* Fill in other values of opts here */
+
+ //opts.xmpp = "lloyd@randombit.net";
+
+ if(do_CA)
+ opts.CA_key();
+
+ X509_Certificate cert = X509::create_self_signed_cert(opts, key, rng);
+
+ std::ofstream cert_file("cert.pem");
+ cert_file << cert.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << std::endl;
+ return 1;
+ }
+
+ return 0;
+ }
diff --git a/botan/doc/examples/sig_gen.cpp b/botan/doc/examples/sig_gen.cpp
new file mode 100644
index 0000000..6dd7490
--- /dev/null
+++ b/botan/doc/examples/sig_gen.cpp
@@ -0,0 +1,90 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include <botan/botan.h>
+#include <botan/look_pk.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+bool check(std::map<std::string, std::string>);
+
+int main()
+ {
+ try {
+ Botan::LibraryInitializer init;
+
+ std::ifstream in("SigGen.rsp");
+ if(!in)
+ throw Exception("Can't open response file");
+
+ std::map<std::string, std::string> inputs;
+
+ while(in.good())
+ {
+ std::string line;
+ std::getline(in, line);
+
+ if(line == "" || line[0] == '[' || line[0] == '#')
+ continue;
+
+ std::vector<std::string> name_and_val = split_on(line, '=');
+
+ if(name_and_val.size() != 2)
+ throw Decoding_Error("Unexpected input: " + line);
+
+ name_and_val[0].erase(name_and_val[0].size()-1);
+ name_and_val[1].erase(0, 1);
+
+ std::string name = name_and_val[0], value = name_and_val[1];
+
+ inputs[name] = value;
+
+ if(name == "S")
+ {
+ bool result = check(inputs);
+ if(result == false)
+ {
+ std::cout << " Check failed\n";
+
+ std::map<std::string, std::string>::const_iterator i;
+
+ for(i = inputs.begin(); i != inputs.end(); i++)
+ std::cout << i->first << " = " << i->second << "\n";
+ }
+ inputs["Msg"] = inputs["R"] = inputs["S"] = "";
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
+
+bool check(std::map<std::string, std::string> inputs)
+ {
+ BigInt p("0x"+inputs["P"]),
+ q("0x"+inputs["Q"]),
+ g("0x"+inputs["G"]),
+ y("0x"+inputs["Y"]);
+
+ DSA_PublicKey key(DL_Group(p, q, g), y);
+
+ Pipe pipe(new Hex_Decoder);
+
+ pipe.process_msg(inputs["Msg"]);
+ pipe.start_msg();
+ pipe.write(inputs["R"]);
+ pipe.write(inputs["S"] );
+ pipe.end_msg();
+
+ std::auto_ptr<PK_Verifier> verify(get_pk_verifier(key, "EMSA1(SHA-1)"));
+
+ return verify->verify_message(pipe.read_all(0), pipe.read_all(1));
+ }
diff --git a/botan/doc/examples/stack.cpp b/botan/doc/examples/stack.cpp
new file mode 100644
index 0000000..1522b05
--- /dev/null
+++ b/botan/doc/examples/stack.cpp
@@ -0,0 +1,86 @@
+/*
+An Botan example application showing how to use the pop and prepend functions
+of Pipe. Based on the md5 example. It's output should always be identical to
+such.
+
+Written by Jack Lloyd (lloyd@randombit.net), Feb 3, 2002
+
+This file is in the public domain
+*/
+
+#include <iostream>
+#include <fstream>
+#include <botan/botan.h>
+
+int main(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <filenames>" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ // this is a pretty vacuous example, but it's useful as a test
+ Botan::Pipe pipe;
+
+ // CPS == Current Pipe Status, ie what Filters are set up
+
+ pipe.prepend(new Botan::Hash_Filter("MD5"));
+ // CPS: MD5
+
+ pipe.prepend(new Botan::Hash_Filter("RIPEMD-160"));
+ // CPS: RIPEMD-160 | MD5
+
+ pipe.prepend(new Botan::Chain(
+ new Botan::Hash_Filter("RIPEMD-160"),
+ new Botan::Hash_Filter("RIPEMD-160")));
+ // CPS: (RIPEMD-160 | RIPEMD-160) | RIPEMD-160 | MD5
+
+ pipe.pop(); // will pop everything inside the Chain as well as Chain itself
+ // CPS: RIPEMD-160 | MD5
+
+ pipe.pop(); // will get rid of the RIPEMD-160 Hash_Filter
+ // CPS: MD5
+
+ pipe.prepend(new Botan::Hash_Filter("SHA-1"));
+ // CPS: SHA-1 | MD5
+
+ pipe.append(new Botan::Hex_Encoder);
+ // CPS: SHA-1 | MD5 | Hex_Encoder
+
+ pipe.prepend(new Botan::Hash_Filter("SHA-1"));
+ // CPS: SHA-1 | SHA-1 | MD5 | Hex_Encoder
+
+ pipe.pop(); // Get rid of the Hash_Filter(SHA-1)
+ pipe.pop(); // Get rid of the other Hash_Filter(SHA-1)
+ // CPS: MD5 | Hex_Encoder
+ // The Hex_Encoder is safe because it is at the end of the Pipe,
+ // and pop() pulls off the Filter that is at the start.
+
+ pipe.prepend(new Botan::Hash_Filter("RIPEMD-160"));
+ // CPS: RIPEMD-160 | MD5 | Hex_Encoder
+
+ pipe.pop(); // Get rid of that last prepended Hash_Filter(RIPEMD-160)
+ // CPS: MD5 | Hex_Encoder
+
+ int skipped = 0;
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ std::ifstream file(argv[j]);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ file.close();
+ pipe.set_default_msg(j-1-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/test_es.cpp b/botan/doc/examples/test_es.cpp
new file mode 100644
index 0000000..951d51a
--- /dev/null
+++ b/botan/doc/examples/test_es.cpp
@@ -0,0 +1,115 @@
+#include <botan/botan.h>
+#include <stdio.h>
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ #include <botan/es_dev.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ #include <botan/es_egd.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ #include <botan/es_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ #include <botan/es_beos.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ #include <botan/es_capi.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ #include <botan/es_ftw.h>
+#endif
+
+
+using namespace Botan;
+
+class Saver_Of_Bytes : public Entropy_Accumulator
+ {
+ public:
+ Saver_Of_Bytes(u32bit bits) :
+ Entropy_Accumulator(bits), outbuf(64), written(0) {}
+
+ void add_bytes(const byte in[], u32bit length)
+ {
+ for(size_t i = 0; i != length; ++i)
+ outbuf[i % outbuf.size()] ^= in[i];
+
+ written += length;
+ }
+
+ void trunc() { if(written < 64) outbuf.resize(written); }
+
+ std::vector<byte> outbuf;
+ u32bit written;
+ };
+
+void test_entropy_source(EntropySource* es)
+ {
+ // sometimes iostreams really is just a pain
+
+ printf("Polling '%s':\n", es->name().c_str());
+
+ Saver_Of_Bytes accum(128);
+
+ es->poll(accum);
+
+ accum.trunc();
+
+ printf("Got %d bytes\n", accum.written);
+ for(size_t i = 0; i != accum.outbuf.size(); ++i)
+ printf("%02X", accum.outbuf[i]);
+ printf("\n");
+
+ delete es;
+ }
+
+int main()
+ {
+ Botan::LibraryInitializer init;
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ test_entropy_source(
+ new Device_EntropySource(
+ split_on("/dev/random:/dev/srandom:/dev/urandom", ':')
+ )
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ test_entropy_source(
+ new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ test_entropy_source(new Win32_CAPI_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ test_entropy_source(new FTW_EntropySource("/proc"));
+#endif
+
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ test_entropy_source(new Win32_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ test_entropy_source(new BeOS_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ test_entropy_source(
+ new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
+ );
+#endif
+ }
diff --git a/botan/doc/examples/x509info.cpp b/botan/doc/examples/x509info.cpp
new file mode 100644
index 0000000..0e34f2f
--- /dev/null
+++ b/botan/doc/examples/x509info.cpp
@@ -0,0 +1,154 @@
+/*
+ Read an X.509 certificate, and print various things about it
+
+ Written by Jack Lloyd, March 23 2003
+ - October 31, 2003: Prints the public key
+ - November 1, 2003: Removed the -d flag; it can tell automatically now
+
+ This file is in the public domain
+*/
+#include <botan/botan.h>
+#include <botan/x509cert.h>
+#include <botan/oids.h>
+using namespace Botan;
+
+#include <iostream>
+#include <iterator>
+#include <algorithm>
+
+std::string to_hex(const SecureVector<byte>& bin)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(bin);
+ if(pipe.remaining())
+ return pipe.read_all_as_string();
+ else
+ return "(none)";
+ }
+
+void do_print(const std::string& what,
+ const std::vector<std::string>& vals)
+ {
+ if(vals.size() == 0)
+ return;
+
+ std::cout << " " << what << ": ";
+ std::copy(vals.begin(), vals.end(),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << "\n";
+ }
+
+void do_subject(const X509_Certificate& cert, const std::string& what)
+ {
+ do_print(what, cert.subject_info(what));
+ }
+
+void do_issuer(const X509_Certificate& cert, const std::string& what)
+ {
+ do_print(what, cert.issuer_info(what));
+ }
+
+int main(int argc, char* argv[])
+ {
+ if(argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " <x509cert>\n";
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
+ try {
+ X509_Certificate cert(argv[1]);
+
+ std::cout << "Version: " << cert.x509_version() << std::endl;
+
+ std::cout << "Subject" << std::endl;
+ do_subject(cert, "Name");
+ do_subject(cert, "Email");
+ do_subject(cert, "Organization");
+ do_subject(cert, "Organizational Unit");
+ do_subject(cert, "Locality");
+ do_subject(cert, "State");
+ do_subject(cert, "Country");
+ do_subject(cert, "IP");
+ do_subject(cert, "DNS");
+ do_subject(cert, "URI");
+ do_subject(cert, "PKIX.XMPPAddr");
+
+ std::cout << "Issuer" << std::endl;
+ do_issuer(cert, "Name");
+ do_issuer(cert, "Email");
+ do_issuer(cert, "Organization");
+ do_issuer(cert, "Organizational Unit");
+ do_issuer(cert, "Locality");
+ do_issuer(cert, "State");
+ do_issuer(cert, "Country");
+ do_issuer(cert, "IP");
+ do_issuer(cert, "DNS");
+ do_issuer(cert, "URI");
+
+ std::cout << "Validity" << std::endl;
+
+ std::cout << " Not before: " << cert.start_time() << std::endl;
+ std::cout << " Not after: " << cert.end_time() << std::endl;
+
+ std::cout << "Constraints" << std::endl;
+ Key_Constraints constraints = cert.constraints();
+ if(constraints == NO_CONSTRAINTS)
+ std::cout << "No constraints" << std::endl;
+ else
+ {
+ if(constraints & DIGITAL_SIGNATURE)
+ std::cout << " Digital Signature\n";
+ if(constraints & NON_REPUDIATION)
+ std::cout << " Non-Repuidation\n";
+ if(constraints & KEY_ENCIPHERMENT)
+ std::cout << " Key Encipherment\n";
+ if(constraints & DATA_ENCIPHERMENT)
+ std::cout << " Data Encipherment\n";
+ if(constraints & KEY_AGREEMENT)
+ std::cout << " Key Agreement\n";
+ if(constraints & KEY_CERT_SIGN)
+ std::cout << " Cert Sign\n";
+ if(constraints & CRL_SIGN)
+ std::cout << " CRL Sign\n";
+ }
+
+ std::vector<std::string> policies = cert.policies();
+ if(policies.size())
+ {
+ std::cout << "Policies: " << std::endl;
+ for(u32bit j = 0; j != policies.size(); j++)
+ std::cout << " " << policies[j] << std::endl;
+ }
+
+ std::vector<std::string> ex_constraints = cert.ex_constraints();
+ if(ex_constraints.size())
+ {
+ std::cout << "Extended Constraints: " << std::endl;
+ for(u32bit j = 0; j != ex_constraints.size(); j++)
+ std::cout << " " << ex_constraints[j] << std::endl;
+ }
+
+ std::cout << "Signature algorithm: " <<
+ OIDS::lookup(cert.signature_algorithm().oid) << std::endl;
+
+ std::cout << "Serial: "
+ << to_hex(cert.serial_number()) << std::endl;
+ std::cout << "Authority keyid: "
+ << to_hex(cert.authority_key_id()) << std::endl;
+ std::cout << "Subject keyid: "
+ << to_hex(cert.subject_key_id()) << std::endl;
+
+ X509_PublicKey* pubkey = cert.subject_public_key();
+ std::cout << "Public Key:\n" << X509::PEM_encode(*pubkey);
+ delete pubkey;
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/botan/doc/examples/xor_ciph.cpp b/botan/doc/examples/xor_ciph.cpp
new file mode 100644
index 0000000..6a914b1
--- /dev/null
+++ b/botan/doc/examples/xor_ciph.cpp
@@ -0,0 +1,96 @@
+/*
+ An implementation of the highly secure (not) XOR cipher. AKA, how to write
+ and use your own cipher object. DO NOT make up your own ciphers. Please.
+
+ Written by Jack Lloyd (lloyd@randombit.net) on Feb 17, 2004
+ Update November 21 2008 for new algorithm factory in 1.8
+
+ This file is in the public domain
+*/
+
+#include <botan/stream_cipher.h>
+#include <botan/init.h>
+using namespace Botan;
+
+class XOR_Cipher : public StreamCipher
+ {
+ public:
+ void clear() throw() { mask.destroy(); mask_pos = 0; }
+
+ // what we want to call this cipher
+ std::string name() const { return "XOR"; }
+
+ // return a new object of this type
+ StreamCipher* clone() const { return new XOR_Cipher; }
+
+ XOR_Cipher() : StreamCipher(1, 32) { mask_pos = 0; }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ SecureVector<byte> mask;
+ u32bit mask_pos;
+ };
+
+void XOR_Cipher::cipher(const byte in[], byte out[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j++)
+ {
+ out[j] = in[j] ^ mask[mask_pos];
+ mask_pos = (mask_pos + 1) % mask.size();
+ }
+ }
+
+void XOR_Cipher::key_schedule(const byte key[], u32bit length)
+ {
+ mask.set(key, length);
+ }
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+
+#include <botan/lookup.h>
+#include <botan/filters.h>
+#include <botan/libstate.h>
+
+int main()
+ {
+
+ Botan::LibraryInitializer init;
+
+ global_state().algorithm_factory().add_stream_cipher(new XOR_Cipher, "app");
+
+ // a hex key value
+ SymmetricKey key("010203040506070809101112AAFF");
+
+ /*
+ Since stream ciphers are typically additive, the encryption and
+ decryption ops are the same, so this isn't terribly interesting.
+
+ If this where a block cipher you would have to add a cipher mode and
+ padding method, such as "/CBC/PKCS7".
+ */
+ Pipe enc(get_cipher("XOR", key, ENCRYPTION), new Hex_Encoder);
+ Pipe dec(new Hex_Decoder, get_cipher("XOR", key, DECRYPTION));
+
+ // I think the pigeons are actually asleep at midnight...
+ std::string secret = "The pigeon flys at midnight.";
+
+ std::cout << "The secret message is '" << secret << "'" << std::endl;
+
+ enc.process_msg(secret);
+ std::string cipher = enc.read_all_as_string();
+
+ std::cout << "The encrypted secret message is " << cipher << std::endl;
+
+ dec.process_msg(cipher);
+ secret = dec.read_all_as_string();
+
+ std::cout << "The decrypted secret message is '"
+ << secret << "'" << std::endl;
+
+ return 0;
+ }
diff --git a/botan/doc/fips140.tex b/botan/doc/fips140.tex
new file mode 100644
index 0000000..8b20045
--- /dev/null
+++ b/botan/doc/fips140.tex
@@ -0,0 +1,156 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in}
+\setlength{\textheight}{9in}
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan FIPS 140-2 Security Policy}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\module}[1]{\texttt{#1}}
+
+\newcommand{\type}[1]{\texttt{#1}}
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+%\baselineskip=15pt
+
+\pagebreak
+
+\section{Introduction}
+
+\emph{Note that this is a draft, and almost certainly does not comply with what
+FIPS 140-2 wants (also it's incomplete). In any case, there is no way for me to
+afford paying the validation lab, so this is all theoretical.}
+
+\emph{I would welcome comments from people who are familiar with the FIPS 140
+process. I am currently basing this off a few dozen other security policies and
+the FIPS itself.}
+
+\subsection{Purpose}
+
+This document is a security policy for the Botan C++ crypto library for use in
+a FIPS 140-2 Level 1 validation process. It describes how to configure and use
+the library to comply with the requirements of FIPS 140-2.
+
+This document is non-proprietary, and may be freely reproduced and distributed
+in unmodified form.
+
+\subsection{Product Description}
+
+The Botan C++ crypto library (hereafter ``Botan'' or ``the library'') is an
+open source C++ class library providing a general-purpose interface to a wide
+variety of cryptographic algorithms and formats (such as X.509v3 and PKCS
+\#10). It runs on most Win32 and POSIX-like systems, including Windows
+NT/2000/XP, MacOS X, Linux, Solaris, FreeBSD, and QNX. However, only versions
+running on \emph{(goal:)} Windows XP, Linux, and Solaris have been validated by
+FIPS 140-2 at this time.
+
+\subsection{Algorithms}
+
+The library contains the following FIPS Approved algorithms: RSA, DSA, DES,
+TripleDES, Skipjack, AES, SHA-1, HMAC, the X9.19 DES MAC, and the FIPS 186-2
+SHA-1 RNG. Other (non-Approved) algorithms, such as MD5 and Diffie-Hellman, are
+also included.
+
+\section{Initialization}
+
+Certain tests are only performed if the flag ``fips140'' is passed as part of
+the initialization process to the library (the argument to
+\type{LibraryInitializer} or \function{Init::initialize}). Known answer tests
+and key generation self-checks for RSA and DSA are always performed, regardless
+of this setting. This flag must be passed by any application which desires
+using the FIPS 140 mode of operation.
+
+\section{Roles and Services}
+
+Botan supports two roles, the User and the Crypto Officer. Authentication is
+not performed by the module; all authentication is implicitly done by the
+operating system.
+
+\subsection{User Role}
+
+The user has the ability to access the services of the module. This role is
+implicitly selected whenever the module's services are accessed.
+
+\subsection{Crypto Officer Role}
+
+The crypto officer has all of the powers of the user, and in addition has the
+power to install and uninstall the module and to configure the operating
+system. This role is implicitly selected whenever these actions are performed.
+
+\section{Key Management}
+
+\subsection{Key Import/Export}
+
+Symmetric keys can be imported and exported in either unencrypted, encrypted,
+or split-knowledge forms, as the application desires. Private keys for
+asymmetric algorithms can be imported and exported as either encrypted or
+unencrypted PKCS \#8 structures. The library natively supports PKCS \#5
+encryption with TripleDES for encrypting private keys.
+
+\subsection{Key Storage}
+
+In no case does the library itself import or export keys from/to an external
+storage device; all such operations are done explicitly by the application. It
+is the responsibly of the operator to ensure than any such operations comply
+with the requirements of FIPS 140-2 Level 1.
+
+\subsection{Key Generation}
+
+Keys for symmetric algorithms (such as DES, AES, and HMAC) are generated by an
+Approved RNG, by generating a random byte string of the appropriate size, and
+using it as a key.
+
+DSA keys are generated as specified in FIPS 186-2 (or not?). RSA keys are
+generated as specified in ANSI X9.31 (\emph{I think...}). Diffie-Hellman keys
+are generated in a manner compatible with ANSI X9.42. All newly created DSA and
+RSA keys are checked with a pairwise consistency test before being returned to
+the caller. A pairwise consistency check can be performed on any RSA, DSA, or
+Diffie-Hellman key by calling the \function{check\_key} member function with
+an argument of \type{true}.
+
+\subsection{Key Establishment}
+
+Botan supports using RSA or Diffie-Hellman to establish keys. RSA can be used
+with PKCS \#1 v1.5 or OAEP padding. None of these methods are FIPS Approved,
+but Annex D of FIPS 140-2 allows for their use until such time as a FIPS
+Approved asymmetric key establishment method is established.
+
+\subsection{Key Protection / Zeroization}
+
+Keys are protected against external access by the operating system's memory and
+process protection mechanisms. If the library is used by multiple processes at
+once, the OS virtual memory mechanisms ensure that each version will have it's
+own data space (and thus, keys are not shared among multiple processes).
+
+All keys and other sensitive materials are zeroed in memory before being
+released to the system.
+
+On Windows systems the \function{VirtualLock} system call is used to notify the
+operating system that the memory containing potentially sensitive keying
+material is not swapped to disk, preventing an attacker from applying disk
+forenistics techniques to recovery data.
+
+On Unix systems, Botan allocates memory from file-backed memory mappings, which
+are thoroughly erased when the memory is freed.
+
+\section{References}
+
+\end{document}
diff --git a/botan/doc/indent.el b/botan/doc/indent.el
new file mode 100644
index 0000000..9811bf8
--- /dev/null
+++ b/botan/doc/indent.el
@@ -0,0 +1,57 @@
+; This Emacs Lips code defines the indentation style used in Botan. If doesn't
+; get everything perfectly correct, but it's pretty close. Copy this code into
+; your .emacs file, or use M-x eval-buffer. Make sure to also set
+; indent-tabs-mode to nil so spaces are inserted instead.
+
+; This style is basically Whitesmiths style with 3 space indents (the Emacs
+; "whitesmith" style seems more like a weird Whitesmiths/Allman mutant style).
+
+; To activate using this style, open the file you want to edit and run this:
+; M-x c-set-style <RET> and then enter "botan". Alternately, put something
+; like this in your .emacs file to make it the default style:
+
+; (add-hook 'c++-mode-common-hook
+; (function (lambda()
+; (c-add-style "botan" botan t))))
+
+(setq botan '(
+ (c-basic-offset . 3)
+ (c-comment-only-line-offset . 0)
+ (c-offsets-alist
+ (c . 0)
+ (comment-intro . 0)
+
+ (statement-block-intro . 0)
+ (statement-cont . +)
+
+ (substatement . +)
+ (substatement-open . +)
+
+ (block-open . +)
+ (block-close . 0)
+
+ (defun-open . +)
+ (defun-close . 0)
+ (defun-block-intro . 0)
+ (func-decl-cont . +)
+
+ (class-open . +)
+ (class-close . +)
+ (inclass . +)
+ (access-label . -)
+ (inline-open . +)
+ (inline-close . 0)
+
+ (extern-lang-open . 0)
+ (extern-lang-close . 0)
+ (inextern-lang . 0)
+
+ (statement-case-open +)
+
+ (namespace-open . 0)
+ (namespace-close . 0)
+ (innamespace . 0)
+
+ (label . 0)
+ )
+))
diff --git a/botan/doc/insito_manual.pdf b/botan/doc/insito_manual.pdf
new file mode 100644
index 0000000..b071469
--- /dev/null
+++ b/botan/doc/insito_manual.pdf
Binary files differ
diff --git a/botan/doc/internals.tex b/botan/doc/internals.tex
new file mode 100644
index 0000000..5b1650f
--- /dev/null
+++ b/botan/doc/internals.tex
@@ -0,0 +1,179 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.75in} % 1 inch side margins
+\setlength{\textheight}{9in} % ~1 inch top and bottom margins
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{Botan Internals}
+\author{Jack Lloyd (lloyd@randombit.net)}
+\date{August 20, 2006}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+
+\section{Introduction}
+
+This document is intended to document some of the trickier and/or more
+complicated parts of Botan. This is not going to be terribly useful if
+you just want to use the library, but for people wishing to understand
+how it works, or contribute new code to it, it will hopefully prove
+helpful.
+
+I've realized that a lot of things Botan does internally are pretty
+hard to understand, and that a lot of things are only inside my head,
+which is a bad place for them to be (things tend to get lost in there,
+not to mention the possibility that I'll get hit by a truck next
+week).
+
+This document is currently very incomplete. I'll be working on it as I
+have time.
+
+\pagebreak
+
+\section{Filter}
+
+\type{Filter} is one of the core abstractions of the library. It is
+used to represent any sort of transformation. Nearly all
+\type{Filter}s are linear; they take input from a single source and
+send their output (if any) to another single \type{Filter}. The one
+exception is \type{Fanout\_Filter}, which uses friend access to
+\type{Filter} in order to allow for multiple \type{Filter}s to attach
+to its output. This special access is used by the Chain and Fork
+filters; Chain encapsulates one or more \type{Filter}s into a single
+Filter, and Fork sends its input to a set of several \type{Filter}
+objects.
+
+The majority of the relations between filters is maintained by the
+\type{Pipe} object which ``owns'' the \type{Filter}s.
+
+\section{Pipe}
+
+\type{Pipe} is, conceptually, a tree structure of \type{Filter}
+objects. There is a single unique top, and an arbitrary number of
+leaves (which are \type{SecureQueue} objects). \type{SecureQueue} is a
+simple \type{Filter} that buffers its input.
+
+Writing into the pipe writes into the top of the tree. The filter at
+the top of the tree writes its output into the next \type{Filter}, and
+so on until eventually data trickles down into the bottommost
+\type{Filter}s, where the data is stored for later retrieval.
+
+When a new message is started, \type{Pipe} searches through the tree
+of \type{Filter}s and finds places where the \arg{next} field of the
+\type{Filter} is NULL. This implies that it was the lowest layer of
+the \type{Filter} tree that the user added. It then adds
+\type{SecureQueue} objects onto these \type{Filter}s. These queues are
+also stored in an deque; this is so \type{Pipe} can read from them
+later without doing a tree traversal each time.
+
+\type{Pipe} will, if asked, destroy the existing tree structure, in
+order to create a new one. However, the queue objects are not deleted,
+because \type{Pipe} might be asked to read from them later (while
+\type{Pipe} could delete all the messages in this case, the principle
+of least astonishment suggested keeping them).
+
+What I wrote about \type{Pipe} keeing the queues in a deque is a
+lie. Sort of. It keeps them in an object called
+\type{Output\_Buffers}, which keeps them in a
+deque. \type{Output\_Buffers} is intended to abstract away how message
+queues are stored from \type{Pipe}. After a queue has been added to
+the output buffers object, \type{Pipe} keeps no references to it
+whatsoever; all access is mediated by the \type{Output\_Buffers}.
+This allows queues which have been read to be deleted, rather than
+leaving empty queue objects all over the place.
+
+\section{Library Initialization}
+
+WRITEME
+
+\section{Lookup Mechanism}
+
+Most objects know their name, and they know how to create a new copy
+of themselves. We build mapping tables that map from an algorithm name
+into a single instance of that algorithm. The tables themselves can be
+found in \filename{src/lookup.cpp}.
+
+There are a set of functions named \function{add\_algorithm} that can
+be used to populate the tables. We get something out of the table with
+\function{retrieve\_x}, where x is the name of a type
+(\texttt{block\_cipher}, \texttt{hash}, etc). This returns a const
+pointer to the single unique instance of the algorithm that the lookup
+tables know about. If it doesn't know about it, it falls back on
+calling a function called \function{try\_to\_get\_x}. These functions
+live in \filename{src/algolist.cpp}. They are mostly used to handle
+algorithms which need (or at least can have) arguments passed to them,
+like \type{HMAC} and \type{SAFER\_SK}. It will return NULL if it can't
+find the algorithm at all.
+
+When it's asked for an algorithm it doesn't know about (ie, isn't in
+the mapping tables), the retrieval functions will ask the try-to-get
+functions if \emph{they} know about it. If they do, then the object
+returned will be stored into the table for later retrieval.
+
+The functions \function{get\_x} call the retrieval functions. If we
+get back NULL, an exception is thrown. Otherwise it will call the
+\function{clone} method to get a new copy of the algorithm, which it
+returns.
+
+The various functions like \function{output\_length\_of} call the
+retrieval function for each type of object that the parameter in
+question (in this case, \texttt{OUTPUT\_LENGTH}) might be meaningful
+for. If it manages to get back an object, it will return (in this
+case) the \texttt{OUTPUT\_LENGTH} field of the object. No allocations
+are required to call this function: all of its operations work
+directly on the copies living in the lookup tables.
+
+\section{Allocators}
+
+A big (slow) mess.
+
+\section{BigInt}
+
+Read ``Handbook of Applied Cryptography''.
+
+\section{PEM/BER Identification}
+
+We have a specific algorithm for figuring out if something is PEM or
+BER. Previous versions (everything before 1.3.0) requried that the
+caller specify which one it was, and they had to be right. Now we use
+a hueristic (aka, an algorithm that sometimes doesn't work right) to
+figure it out. If the first character is not 0x30 (equal to ASCII
+'0'), then it can't possibly be BER (because everything we care about
+is enclosed in an ASN.1 SEQUENCE, which for BER/DER is encoded as
+beginning with 0x30). Roughly 99.9% of PEM blocks \emph{won't} have a
+random 0 character in front of them, so we are mostly safe (unless
+someone does it on purpose, in which case, please hit them for me).
+But to be sure, if there is a 0, then we search the first \emph{N}
+bytes of the block for the string ``-----BEGIN ``, which marks the
+typical start of a PEM block. The specific \emph{N} depends on the
+variable ``base/pem\_search'', which defaults to 4 kilobytes.
+
+So, you can actually fool it either way: that a PEM file is really
+BER, or that a BER file is actually PEM. To fool it that a BER file is
+PEM, just have the string ``-----BEGIN `` somewhere (I can't imagine
+this string shows up in certificates or CRLs too often, so if it is
+there it means somebody is being a jerk). If a file starts with 0 and
+has at least ``base/pem\_search'' byte more junk in the way, it won't
+notice that its PEM at all. In either case, of course, the loading
+will fail, and you'll get a nice exception saying that the decoding
+failed.
+
+\end{document}
diff --git a/botan/doc/license.txt b/botan/doc/license.txt
new file mode 100644
index 0000000..9d1067c
--- /dev/null
+++ b/botan/doc/license.txt
@@ -0,0 +1,40 @@
+Botan (http://botan.randombit.net/) is distributed under these terms:
+
+Copyright (C) 1999-2009 Jack Lloyd
+ 2001 Peter J Jones
+ 2004-2007 Justin Karneges
+ 2005 Matthew Gregan
+ 2005-2006 Matt Johnston
+ 2006 Luca Piccarreta
+ 2007 Yves Jerschow
+ 2007-2008 FlexSecure GmbH
+ 2007-2008 Technische Universitat Darmstadt
+ 2007-2008 Falko Strenzke
+ 2007-2008 Martin Doering
+ 2007 Manuel Hartl
+ 2007 Christoph Ludwig
+ 2007 Patrick Sona
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/botan/doc/log.txt b/botan/doc/log.txt
new file mode 100644
index 0000000..97476c3
--- /dev/null
+++ b/botan/doc/log.txt
@@ -0,0 +1,1323 @@
+
+* 1.8.8, 2009-11-03
+ - Alter Skein-512 to match the tweaked 1.2 specification
+ - Fix use of inline asm for access to x86 bswap function
+ - Allow building the library without AES enabled
+ - Add 'powerpc64' alias to ppc64 arch for Gentoo ebuild
+
+* 1.8.7, 2009-09-09
+ - Fix processing multiple messages in XTS mode
+ - Add --no-autoload option to configure.py, for minimized builds
+
+* 1.8.6, 2009-08-13
+ - Add Cryptobox, a set of simple password-based encryption routines
+ - Only read world-readable files when walking /proc for entropy
+ - Fix building with TR1 disabled
+ - Fix x86 bswap support for Visual C++
+ - Fixes for compilation under Sun C++
+ - Add support for Dragonfly BSD (contributed by Patrick Georgi)
+ - Add support for the Open64 C++ compiler
+ - Build fixes for MIPS systems running Linux
+ - Minor changes to license, now equivalent to the FreeBSD/NetBSD license
+
+* 1.8.5, 2009-07-23
+ - Change configure.py to work on stock Python 2.4
+ - Avoid a crash in Skein_512::add_data processing a zero-length input
+ - Small build fixes for SPARC, ARM, and HP-PA processors
+ - The test suite now returns an error code from main() if any tests failed
+
+* 1.8.4, 2009-07-12
+ - Fix a bug in nonce generation in the Miller-Rabin test
+
+* 1.8.3, 2009-07-11
+ - Add a new Python configuration script
+ - Add the Skein-512 SHA-3 candidate hash function
+ - Add the XTS block cipher mode from IEEE P1619
+ - Fix random_prime when generating a prime of less than 7 bits
+ - Improve handling of low-entropy situations during PRNG seeding
+ - Change random device polling to prefer /dev/urandom over /dev/random
+ - Use an input insensitive implementation of same_mem instead of memcmp
+ - Correct DataSource::discard_next to return the number of discarded bytes
+ - Provide a default value for AutoSeeded_RNG::reseed
+ - Fix Gentoo bug 272242
+
+* 1.8.2, 2009-04-07
+ - Make entropy polling more flexible and in most cases faster
+ - GOST 28147 now supports multiple sbox parameters
+ - Added the GOST 34.11 hash function
+ - Fix botan-config problems on MacOS X
+
+* 1.8.1, 2009-01-20
+ - Avoid a valgrind warning in es_unix.cpp on 32-bit Linux
+ - Fix memory leak in PKCS8 load_key and encrypt_key
+ - Relicense api.tex from CC-By-SA 2.5 to BSD
+ - Fix botan-config on MacOS X, Solaris
+
+* 1.8.0, 2008-12-08
+ - Fix compilation on Solaris with GCC
+
+* 1.7.24, 2008-12-01
+ - Fix a compatibility problem with SHA-512/EMSA3 signature padding
+ - Fix bug preventing EGD/PRNGD entropy poller from working
+ - Fix integer overflow in Pooling_Allocator::get_more_core (bug id #27)
+ - Add EMSA3_Raw, a variant of EMSA3 called CKM_RSA_PKCS in PKCS #11
+ - Add support for SHA-224 in EMSA2 and EMSA3 PK signature padding schemes
+ - Add many more test vectors for RSA with EMSA2, EMSA3, and EMSA4
+ - Wrap private structs in SSE2 SHA-1 code in anonymous namespace
+ - Change configure.pl's CPU autodetection output to be more consistent
+ - Disable using OpenSSL's AES due to crashes of unknown cause
+ - Fix warning in /proc walking entropy poller
+ - Fix compilation with IBM XLC for Cell 0.9-200709
+
+* 1.7.23, 2008-11-23
+ - Change to use TR1 (thus enabling ECDSA) with GCC and ICC
+ - Optimize almost all hash functions, especially MD4 and Tiger
+ - Add configure.pl options --{with,without}-{bzip2,zlib,openssl,gnump}
+ - Change Timer to be pure virtual, and add ANSI_Clock_Timer
+ - Cache socket descriptors in the EGD entropy source
+ - Avoid bogging down startup in /proc walking entropy source
+ - Remove Buffered_EntropySource helper class
+ - Add a Default_Benchmark_Timer typedef in benchmark.h
+ - Add examples using benchmark.h and Algorithm_Factory
+ - Add ECC tests from InSiTo
+ - Minor documentation updates
+
+* 1.7.22, 2008-11-17
+ - Add provider preferences to Algorithm_Factory
+ - Fix memory leaks in PBE_PKCS5v20 and get_pbe introduced in 1.7.21
+ - Optimize AES encryption and decryption (about 10% faster)
+ - Enable SSE2 optimized SHA-1 implementation on Intel Prescott CPUs
+ - Fix nanoseconds overflow in benchmark code
+ - Remove Engine::add_engine
+
+* 1.7.21, 2008-11-11
+ - Make algorithm lookup much more configuable
+ - Add facilities for runtime performance testing of algorithms
+ - Drop use of entropy estimation in the PRNGs
+ - Increase intervals between HMAC_RNG automatic reseeding
+ - Drop InitializerOptions class, all options but thread safety
+
+* 1.7.20, 2008-11-09
+ - Namespace pkg-config file by major and minor versions
+ - Cache device descriptors in Device_EntropySource
+ - Split base.h into {block_cipher,stream_cipher,mac,hash}.h
+ - Removed get_mgf function from lookup.h
+
+* 1.7.19, 2008-11-06
+ - Add HMAC_RNG, based on a design by Hugo Krawczyk
+ - Optimized the Turing stream cipher (about 20% faster on x86-64)
+ - Modify Randpool's reseeding algorithm to poll more sources
+ - Add a new AutoSeeded_RNG in auto_rng.h
+ - OpenPGP_S2K changed to take hash object instead of name
+ - Add automatic identification for Intel's Prescott processors
+
+* 1.7.18, 2008-10-22
+ - Add Doxygen comments from InSiTo
+ - Add ECDSA and ECKAEG benchmarks
+ - Add configure.pl switch --with-tr1-implementation
+ - Fix configure.pl's --with-endian and --with-unaligned-mem options
+ - Added support for pkg-config
+ - Optimize byteswap with x86 inline asm for Visual C++ by Yves Jerschow
+ - Use const references to avoid copying overhead in CurveGFp, GFpModulus
+
+* 1.7.17, 2008-10-12
+ - Add missing ECDSA object identifiers
+ - Fix error in x86 and x86-64 assembler affecting GF(p) math
+ - Remove Boost dependency from GF(p) math
+ - Modify botan-config to not print -L/usr/lib or -L/usr/local/lib
+ - Add BOTAN_DLL macro to over 30 classes missing it
+ - Rename the two SHA-2 base classes for consistency
+
+* 1.7.16, 2008-10-09
+ - Add several missing pieces needed for ECDSA and ECKAEG
+ - Add Card Verifiable Certificates from InSiTo
+ - Add SHA-224 from InSiTo
+ - Add BSI variant of EMSA1 from InSiTo
+ - Add GF(p) and ECDSA tests from InSiTo
+ - Split ECDSA and ECKAEG into distinct modules
+ - Allow OpenSSL and GNU MP engines to be built with public key algos disabled
+ - Rename sha256.h to sha2_32.h and sha_64.h to sha2_64.h
+
+* 1.7.15, 2008-10-07
+ - Add GF(p) arithmetic from InSiTo
+ - Add ECDSA and ECKAEG implementations from InSiTo
+ - Minimize internal dependencies, allowing for smaller build configurations
+ - Add new User Manual and Architecture Guide from FlexSecure GmbH
+ - Alter configure.pl options for better autotools compatibility
+ - Update build instructions for recent changes to configure.pl
+ - Fix CPU detection using /proc/cpuinfo
+
+* 1.7.14, 2008-09-30
+ - Split library into parts allowing modular builds
+ - Add (very preliminary) CMS support to the main library
+ - Some constructors now require object pointers instead of names
+ - Support multiple implementations of the same algorithm
+ - Build support for Pentium-M processors, from Derek Scherger
+ - Build support for MinGW/MSYS, from Zbigniew Zagorski
+ - Use inline assembly for bswap on 32-bit x86
+
+* 1.7.13, 2008-09-27
+ - Add SSLv3 MAC, SSLv3 PRF, and TLS v1.0 PRF from Ajisai
+ - Allow all examples to compile even if compression not enabled
+ - Make CMAC's polynomial doubling operation a public class method
+ - Use the -m64 flag when compiling with Sun Forte on x86-64
+ - Clean up and slightly optimize CMAC::final_result
+
+* 1.7.12, 2008-09-18
+ - Add x86 assembly for Visual Studio C++, by Luca Piccarreta
+ - Add a Perl XS module, by Vaclav Ovsik
+ - Add SWIG-based wrapper for Botan
+ - Add SSE2 implementation of SHA-1, by Dean Gaudet
+ - Remove the BigInt::sig_words cache due to bugs
+ - Combined the 4 Blowfish sboxes, suggested by Yves Jerschow
+ - Changed BigInt::grow_by and BigInt::grow_to to be non-const
+ - Add private assignment operators to classes that don't support assignment
+ - Benchmark RSA encryption and signatures
+ - Added test programs for random_prime and ressol
+ - Add high resolution timers for IA-64, HP-PA, S390x
+ - Reduce use of the RNG during benchmarks
+ - Fix builds on STI Cell PPU
+ - Add support for IBM's XLC compiler
+ - Add IETF 8192 bit MODP group
+
+* 1.7.11, 2008-09-11
+ - Added the Salsa20 stream cipher
+ - Optimized Montgomery reduction, Karatsuba squaring
+ - Added 16x16->32 word Comba multiplication and squaring
+ - Use a much larger Karatsuba cutoff point
+ - Remove bigint_mul_add_words
+ - Inlined several BigInt functions
+ - Add useful information to the generated build.h
+ - Rename alg_{ia32,amd64} modules to asm_{ia32,amd64}
+ - Fix the Windows build
+
+* 1.7.10, 2008-09-05
+ - Public key benchmarks run using a selection of random keys
+ - New benchmark timer options are clock_gettime, gettimeofday, times, clock
+ - Including reinterpret_cast optimization for xor_buf in default header
+ - Split byte swapping and word rotation functions into distinct headers
+ - Add IETF modp 6144 group and 2048 and 3072 bit DSS groups
+ - Optimizes BigInt right shift
+ - Add aliases in DL_Group::Format enum
+ - BigInt now caches the significant word count
+
+* 1.7.9, 2008-08-27
+ - Make clear() in most algorithm base classes a pure virtual
+ - Add noexec stack marker for GNU linker in assembly code
+ - Avoid string operations in ressol
+ - Compilation fixes for MinGW and Visual Studio C++ 2008
+ - Some autoconfiguration fixes for Windows
+
+* 1.6.5, 2008-08-27
+ - Add noexec stack marker for GNU linker in assembly code
+ - Fix autoconfiguration problem on x86 with GCC 4.2 and 4.3
+
+* 1.7.8, 2008-07-15
+ - Added the block cipher Noekeon
+ - Remove global deref_alias function
+ - X509_Store takes timeout options as constructor arguments
+ - Add Shanks-Tonelli algorithm, contributed by FlexSecure GmbH
+ - Extend random_prime() for generating primes of any bit length
+ - Remove Config class
+ - Allow adding new entropy via base RNG interface
+ - Reseeding a X9.31 PRNG also reseeds the underlying PRNG
+
+* 1.7.7, 2008-06-28
+ - Remove the global PRNG object
+ - The PK filter objects were removed
+ - Add a test suite for the ANSI X9.31 PRNG
+ - Much cleaner and (mostly) thread-safe reimplementation of es_ftw
+ - Remove both default arguments to ANSI_X931_RNG's constructor
+ - Remove the randomizing version of OctetString::change
+ - Make the cipher and MAC to use in Randpool configurable
+ - Move RandomNumberGenerator declaration to rng.h
+ - RSA_PrivateKey will not generate keys smaller than 1024 bits
+ - Fix an error decoding BER UNIVERSAL types with special taggings
+
+* 1.7.6, 2008-05-05
+ - Initial support for Windows DLLs, from Joel Low
+ - Reset the position pointer when a new block is generated in X9.32 PRNG
+ - Timer objects are now treated as entropy sources
+ - Moved several ASN.1-related enums from enums.h to an appropriate header
+ - Removed the AEP module, due to inability to test
+ - Removed Global_RNG and rng.h
+ - Removed system_clock
+ - Removed Library_State::UI and the pulse callback logic
+
+* 1.7.5, 2008-04-12
+ - The API of X509_CA::sign_request was altered to avoid race conditions
+ - New type Pipe::message_id to represent the Pipe message number
+ - Remove the Named_Mutex_Holder for a small performance gain
+ - Removed several unused or rarely used functions from Config
+ - Ignore spaces inside of a decimal string in BigInt::decode
+ - Allow using a std::istream to initialize a DataSource_Stream object
+ - Fix compilation problem in zlib compression module
+ - The chunk sized used by Pooling_Allocator is now a compile time setting
+ - The size of random blinding factors is now a compile time setting
+ - The install target no longer tries to set a particular owner/group
+
+* 1.7.4, 2008-03-10
+ - Use unaligned memory read/writes on systems that allow it, for performance
+ - Assembly for x86-64 for accessing the bswap instruction
+ - Use larger buffers in ARC4 and WiderWAKE for significant throughput increase
+ - Unroll loops in SHA-160 for a few percent increase in performance
+ - Fix compilation with GCC 3.2 in es_ftw and es_unix
+ - Build fix for NetBSD systems
+ - Prevent es_dev from being built except on Unix systems
+
+* 1.6.4, 2008-03-08
+ - Fix a compilation problem with Visual Studio C++ 2003
+
+* 1.7.3, 2008-01-23
+ - New invocation syntax for configure.pl with several new options
+ - Support for IPv4 addresses in a subject alternative name
+ - New fast poll for the generic Unix entropy source (es_unix)
+ - The es_file entropy source has been replaced by the es_dev module
+ - The malloc allocator does not inherit from Pooling_Allocator anymore
+ - The path that es_unix will search in are now fully user-configurable
+ - Truncate X9.42 PRF output rather than allow counter overflow
+ - PowerPC is now assumed to be big-endian
+
+* 1.7.2, 2007-10-13
+ - Initialize the global library state lazily
+ - Add plain CBC-MAC for backwards compatibility with old systems
+ - Clean up some of the self test code
+ - Throw a sensible exception if a DL_Group is not found
+ - Truncate KDF2 output rather than allowing counter overflow
+ - Add newly assigned OIDs for SHA-2 and DSA with SHA-224/256
+ - Fix a Visual Studio compilation problem in x509stat.cpp
+
+* 1.6.3, 2007-07-23
+ - Fix a race condition in the algorithm lookup cache
+ - Fix problems building the memory pool on some versions of Visual C++
+
+* 1.7.1, 2007-07-23
+ - Fix a race condition in the algorithm object cache
+ - HMAC key schedule optimization
+ - The build header sets a macro defining endianness, if known
+ - New word load/store abstraction allowing further optimization
+ - Modify most of the library to avoid use the C-style casts
+ - Use higher resolution timers in symmetric benchmarks
+
+* 1.7.0, 2007-05-19
+ - DSA parameter generation now follows FIPS 186-3
+ - Added OIDs for Rabin-Williams and Nyberg-Rueppel
+ - Somewhat better support for out of tree builds
+ - Minor optimizations for RC2 and Tiger
+ - Documentation updates
+ - Update the todo list
+
+* 1.6.2, 2007-03-24
+ - Fix autodection on Athlon64s running Linux
+ - Fix builds on QNX and compilers using STLport
+ - Remove a call to abort() that crept into production
+
+* 1.6.1, 2007-01-20
+ - Fix some base64 decoder bugs
+ - Add a new option to base64 encoding, to always append a newline
+ - Fix some build problems under Visual Studio with debug enabled
+ - Fix a bug in BER_Decoder that was triggered under some compilers
+
+* 1.6.0, 2006-12-17
+ - Minor cleanups versus 1.5.13
+
+* 1.5.13, 2006-12-10
+ - Compilation fixes for the bzip2, zlib, and GNU MP modules
+ - Better support for Intel C++ and EKOpath C++ on x86-64
+
+* 1.5.12, 2006-10-27
+ - Cleanups in the initialization routines
+ - Add some x86-64 assembly for multiply-add
+ - Fix problems generating very small (below 384 bit) RSA keys
+ - Support out of tree builds
+ - Bring some of the documentation up to date
+ - More improvements to the Python bindings
+
+* 1.5.11, 2006-09-10
+ - Removed the Algorithm base class
+ - Various cleanups in the public key inheritance hierarchy
+ - Major overhaul of the configure/build setup
+ - Added x86 assembler implementations of Serpent and low-level MPI code
+ - Optimizations for the SHA-1 x86 assembler
+ - Various improvements to the Python wrappers
+ - Work around a Visual Studio compiler bug
+
+* 1.5.10, 2006-08-13
+ - Add x86 assembler versions of MD4, MD5, and SHA-1
+ - Expand InitializerOptions' language to support on/off switches
+ - Fix definition of OID 2.5.4.8; was accidentally changed in 1.5.9
+ - Fix possible resource leaks in the mmap allocator
+ - Slightly optimized buffering in MDx_HashFunction
+ - Initialization failures are dealt with somewhat better
+ - Add an example implementing Pollard's Rho algorithm
+ - Better option handling in the test/benchmark tool
+ - Expand the xor_ciph example to support longer keys
+ - Some updates to the documentation
+
+* 1.5.9, 2006-07-12
+ - Fixed bitrot in the AEP engine
+ - Fix support for marking certificate/CRL extensions as critical
+ - Significant cleanups in the library state / initialization code
+ - LibraryInitializer takes an explicit InitializerOptions object
+ - Make Mutex_Factory an abstract class, add Default_Mutex_Factory
+ - Change configuration access to using global_state()
+ - Add support for global named mutexes throughout the library
+ - Add some STL wrappers for the delete operator
+ - Change how certificates are created to be more flexible and general
+
+* 1.5.8, 2006-06-23
+ - Many internal cleanups to the X.509 cert/CRL code
+ - Allow for application code to support new X.509 extensions
+ - Change the return type of X509_Certificate::{subject,issuer}_info
+ - Allow for alternate character set handling mechanisms
+ - Fix a bug that was slowing squaring performance somewhat
+ - Fix a very hard to hit overflow bug in the C version of word3_muladd
+ - Minor cleanups to the assembler modules
+ - Disable es_unix module on FreeBSD due to build problem on FreeBSD 6.1
+ - Support for GCC 2.95.x has been dropped in this release
+
+* 1.5.7, 2006-05-28
+ - Further, major changes to the BER/DER coding system
+ - Updated the Qt mutex module to use Mutex_Factory
+ - Moved the library global state object into an anonymous namespace
+ - Drop the Visual C++ x86 assembly module due to bugs
+
+* 1.5.6, 2006-03-01
+ - The low-level DER/BER coding system was redesigned and rewritten
+ - Portions of the certificate code were cleaned up internally
+ - Use macros to substantially clean up the GCC assembly code
+ - Added 32-bit x86 assembly for Visual C++ (by Luca Piccarreta)
+ - Avoid a couple of spurious warnings under Visual C++
+ - Some slight cleanups in X509_PublicKey::key_id
+
+* 1.5.5, 2006-02-04
+ - Fixed a potential infinite loop in the memory pool code (Matt Johnston)
+ - Made Pooling_Allocator::Memory_Block an actual class of sorts
+ - Some small optimizations to the division and modulo computations
+ - Cleaned up the implementation of some of the BigInt operators
+ - Reduced use of dynamic memory allocation in low-level BigInt functions
+ - A few simplifications in the Randpool mixing function
+ - Removed power(), as it was not particularly useful (or fast)
+ - Fixed some annoying bugs in the benchmark code
+ - Added a real credits file
+
+* 1.5.4, 2006-01-29
+ - Integrated x86 and amd64 assembly code, contributed by Luca Piccarreta
+ - Fixed a memory access off-by-one in the Karatsuba code
+ - Changed Pooling_Allocator's free list search to a log(N) algorithm
+ - Merged ModularReducer with its only subclass, Barrett_Reducer
+ - Fixed sign-handling bugs in some of the division and modulo code
+ - Renamed the module description files to modinfo.txt
+ - Further cleanups in the initialization code
+ - Removed BigInt::add and BigInt::sub
+ - Merged all the division-related functions into just divide()
+ - Modified the <mp_asmi.h> functions to allow for better optimizations
+ - Made the number of bits polled from an EntropySource user configurable
+ - Avoid including <algorithm> in <botan/secmem.h>
+ - Fixed some build problems with Sun Forte
+ - Removed some dead code from bigint_modop
+ - Fix the definition of same_mem
+
+* 1.5.3, 2006-01-24
+ - Many optimizations in the low-level multiple precision integer code
+ - Added hooks for assembly implementations of the MPI code
+ - Support for the X.509 issuer alternative name extension in new certs
+ - Fixed a bug in the decompression modules; found and patched by Matt Johnston
+ - New Windows mutex module (mux_win32), by Luca Piccarreta
+ - Changed the Windows timer module to use QueryPerformanceCounter
+ - mem_pool.cpp was using std::set iterators instead of std::multiset ones
+ - Fixed a bug in X509_CA preventing users from disabling particular extensions
+ - Fixed the mp_asm64 module, which was entirely broken in 1.5.2
+ - Fixed some module build problems on FreeBSD and Tru64
+
+* 1.4.12, 2006-01-15
+ - Fixed an off-by-one memory read in MISTY1::key()
+ - Fixed a nasty memory leak in Output_Buffers::retire()
+ - Changed maximum HMAC keylength to 1024 bits
+ - Fixed a build problem in the hardware timer module on 64-bit PowerPC
+
+* 1.5.2, 2006-01-15
+ - Fixed an off-by-one memory read in MISTY1::key()
+ - Fixed a nasty memory leak in Output_Buffers::retire()
+ - Reimplemented the memory allocator from scratch
+ - Improved memory caching in Montgomery exponentiation
+ - Optimizations for multiple precision addition and subtraction
+ - Fixed a build problem in the hardware timer module on 64-bit PowerPC
+ - Changed default Karatsuba cutoff to 12 words (was 14)
+ - Removed MemoryRegion::bits(), which was unused and incorrect
+ - Changed maximum HMAC keylength to 1024 bits
+ - Various minor Makefile and build system changes
+ - Avoid using std::min in <secmem.h> to bypass Windows libc macro pollution
+ - Switched checks/clock.cpp back to using clock() by default
+ - Enabled the symmetric algorithm tests, which were accidentally off in 1.5.1
+ - Removed the Default_Mutex's unused clone() member function
+
+* 1.5.1, 2006-01-08
+ - Implemented Montgomery exponentiation
+ - Implemented generalized Karatsuba multiplication and squaring
+ - Implemented Comba squaring for 4, 6, and 8 word inputs
+ - Added new Modular_Exponentiator and Power_Mod classes
+ - Removed FixedBase_Exp and FixedExponent_Exp
+ - Fixed a performance regression in get_allocator introduced in 1.5.0
+ - Engines can now offer S2K algorithms and block cipher padding methods
+ - Merged the remaining global 'algolist' code into Default_Engine
+ - The low-level MPI code is linked as C again
+ - Replaced BigInt's get_nibble with the more general get_substring
+ - Some documentation updates
+
+* 1.5.0, 2006-01-01
+ - Moved all global/shared library state into a single object
+ - Mutex objects are created through mutex factories instead of a global
+ - Removed ::get_mutex(), ::initialize_mutex(), and Mutex::clone()
+ - Removed the RNG_Quality enum entirely
+ - There is now only a single global-use PRNG
+ - Removed the no_aliases and no_oids options for LibraryInitializer
+ - Removed the deprecated algorithms SEAL, ISAAC, and HAVAL
+ - Change es_ftw to use unbuffered I/O
+
+* 1.4.11, 2005-12-31
+ - Changed Whirlpool diffusion matrix to match updated algorithm spec
+ - Fixed several engine module build errors introduced in 1.4.10
+ - Fixed two build problems in es_capi; reported by Matthew Gregan
+ - Added a constructor to DataSource_Memory taking a std::string
+ - Placing the same Filter in multiple Pipes triggers an exception
+ - The configure script accepts --docdir and --libdir
+ - Merged doc/rngs.txt into the main API document
+ - Thanks to Joel Low for several bug reports on early tarballs of 1.4.11
+
+* 1.4.10, 2005-12-18
+ - Added an implementation of KASUMI, the block cipher used in 3G phones
+ - Refactored Pipe; output queues are now managed by a distinct class
+ - Made certain Filter facilities only available to subclasses of Fanout_Filter
+ - There is no longer any overhead in Pipe for a message that has been read out
+ - It is now possible to generate RSA keys as small as 128 bits
+ - Changed some of the core classes to derive from Algorithm as a virtual base
+ - Changed Randpool to use HMAC instead of a plain hash as the mixing function
+ - Fixed a bug in the allocators; found and fixed by Matthew Gregan
+ - Enabled the use of binary file I/O, when requested by the application
+ - The OpenSSL engine's block cipher code was missing some deallocation calls
+ - Disabled the es_ftw module on NetBSD, due to header problems there
+ - Fixed a problem preventing tm_hard from building on MacOS X on PowerPC
+ - Some cleanups for the modules that use inline assembler
+ - config.h is now stored in build/ instead of build/include/botan/
+ - The header util.h was split into bit_ops.h, parsing.h, and util.h
+ - Cleaned up some redundant include directives
+
+* 1.4.9, 2005-11-06
+ - Added the IBM-created AES candidate algorithm MARS
+ - Added the South Korean block cipher SEED
+ - Added the stream cipher Turing
+ - Added the new hash function FORK-256
+ - Deprecated the ISAAC stream cipher
+ - Twofish and RC6 are significantly faster with GCC
+ - Much better support for 64-bit PowerPC
+ - Added support for high-resolution PowerPC timers
+ - Fixed a bug in the configure script causing problems on FreeBSD
+ - Changed ANSI X9.31 to support arbitrary block ciphers
+ - Make the configure script a bit less noisy
+ - Added more test vectors for some algorithms, including all the AES finalists
+ - Various cosmetic source code cleanups
+
+* 1.4.8, 2005-10-16
+ - Resolved a bad performance problem in the allocators; fix by Matt Johnston
+ - Worked around a Visual Studio 2003 compilation problem introduced in 1.4.7
+ - Renamed OMAC to CMAC to match the official NIST naming
+ - Added single byte versions of update() to PK_Signer and PK_Verifier
+ - Removed the unused reverse_bits and reverse_bytes functions
+
+* 1.4.7, 2005-09-25
+ - Fixed major performance problems with recent versions of GNU C++
+ - Added an implementation of the X9.31 PRNG
+ - Removed the X9.17 and FIPS 186-2 PRNG algorithms
+ - Changed defaults to use X9.31 PRNGs as global PRNG objects
+ - Documentation updates to reflect the PRNG changes
+ - Some cleanups related to the engine code
+ - Removed two useless headers, base_eng.h and secalloc.h
+ - Removed PK_Verifier::valid_signature
+ - Fixed configure/build system bugs affecting MacOS X builds
+ - Added support for the EKOPath x86-64 compiler
+ - Added missing destructor for BlockCipherModePaddingMethod
+ - Fix some build problems with Visual C++ 2005 beta
+ - Fix some build problems with Visual C++ 2003 Workshop
+
+* 1.4.6, 2005-03-13
+ - Fix an error in the shutdown code introduced in 1.4.5
+ - Setting base/pkcs8_tries to 0 disables the builtin fail-out
+ - Support for XMPP identifiers in X.509 certificates
+ - Duplicate entries in X.509 DNs are removed
+ - More fixes for Borland C++, from Friedemann Kleint
+ - Add a workaround for buggy iostreams
+
+* 1.4.5, 2005-02-26
+ - Add support for AES encryption of private keys
+ - Minor fixes for PBES2 parameter decoding
+ - Internal cleanups for global state variables
+ - GCC 3.x version detection was broken in non-English locales
+ - Work around a Sun Forte bug affecting mem_pool.h
+ - Several fixes for Borland C++ 5.5, from Friedemann Kleint
+ - Removed inclusion of init.h into base.h
+ - Fixed a major bug in reading from certificate stores
+ - Cleaned up a couple of mutex leaks
+ - Removed some left-over debugging code
+ - Removed SSL3_MAC, SSL3_PRF, and TLS_PRF
+
+* 1.4.4, 2004-12-02
+ - Further tweaks to the pooling allocator
+ - Modified EMSA3 to support SSL/TLS signatures
+ - Changes to support Qt/QCA, from Justin Karneges
+ - Moved mux_qt module code into mod_qt
+ - Fixes for HP-UX from Mike Desjardins
+
+* 1.4.3, 2004-11-06
+ - Split up SecureAllocator into Allocator and Pooling_Allocator
+ - Memory locking allocators are more likely to be used
+ - Fixed the placement of includes in some modules
+ - Fixed broken installation procedure
+ - Fixes in configure script to support alternate install programs
+ - Modules can specify the minimum version they support
+
+* 1.4.2, 2004-10-31
+ - Fixed a major CRL handling bug
+ - Cipher and hash operations can be offloaded to engines
+ - Added support for cipher and hash offload in OpenSSL engine
+ - Improvements for 64-bit CPUs without a widening multiply instruction
+ - Support for SHA2-* and Whirlpool with EMSA2
+ - Fixed a long-standing build problem with conflicting include files
+ - Fixed some examples that hadn't been updated for 1.4.x
+ - Portability fixes for Solaris, *BSD, HP-UX, and others
+ - Lots of fixes and cleanups in the configure script
+ - Updated the Gentoo ebuild file
+
+* 1.4.1, 2004-10-10
+ - Fixed major errors in the X.509 and PKCS #8 copy_key functions
+ - Added a LAST_MESSAGE meta-message number for Pipe
+ - Added new aliases (3DES and DES-EDE) for Triple-DES
+ - Added some new functions to PK_Verifier
+ - Cleaned up the KDF interface
+ - Disabled tm_posix on *BSD due to header issues
+ - Fixed a build problem on PowerPC with GNU C++ pre-3.4
+
+* 1.4.0, 2004-06-26
+ - Added the FIPS 186 RNG back
+ - Added copy_key functions for X.509 public keys and PKCS #8 private keys
+ - Fixed PKCS #1 signatures with RIPEMD-128
+ - Moved some code around to avoid warnings with Sun ONE compiler
+ - Fixed a bug in botan-config affecting OpenBSD
+ - Fixed some build problems on Tru64, HP-UX
+ - Fixed compile problems with Intel C++, Compaq C++
+
+* 1.3.14, 2004-06-12
+ - Added support for AEP's AEP1000/AEP2000 crypto cards
+ - Added a Mutex module using Qt, from Justin Karneges
+ - Added support for engine loading in LibraryInitializer
+ - Tweaked SecureAllocator, giving 20% better performance under heavy load
+ - Added timer and memory locking modules for Win32 (tm_win32, ml_win32)
+ - Renamed PK_Engine to Engine_Core
+ - Improved the Karatsuba cutoff points
+ - Fixes for compiling with GCC 3.4 and Sun C++ 5.5
+ - Fixes for Linux/s390, OpenBSD, and Solaris
+ - Added support for Linux/s390x
+ - The configure script was totally broken for 'generic' OS
+ - Removed Montgomery reduction due to bugs
+ - Removed an unused header, pkcs8alg.h
+ - check --validate returns an error code if any tests failed
+ - Removed duplicate entry in Unix command list for es_unix
+ - Moved the Cert_Usage enumeration into X509_Store
+ - Added new timing methods for PK benchmarks, clock_gettime and RDTSC
+ - Fixed a few minor bugs in the configure script
+ - Removed some deprecated functions from x509cert.h and pkcs10.h
+ - Removed the 'minimal' module, has to be updated for Engine support
+ - Changed MP_WORD_BITS macro to BOTAN_MP_WORD_BITS to clean up namespace
+ - Documentation updates
+
+* 1.3.13, 2004-05-15
+ - Major fixes for Cygwin builds
+ - Minor MacOS X install fixes
+ - The configure script is a little better at picking the right modules
+ - Removed ml_unix from the 'unix' module set for Cygwin compatibility
+ - Fixed a stupid compile problem in pkcs10.h
+
+* 1.3.12, 2004-05-02
+ - Added ability to remove old entries from CRLs
+ - Swapped the first two arguments of X509_CA::update_crl()
+ - Added an < operator for MemoryRegion, so it can be used as a std::map key
+ - Changed X.509 searching by DNS name from substring to full string compares
+ - Renamed a few X509_Certificate and PKCS10_Request member functions
+ - Fixed a problem when decoding some PKCS #10 requests
+ - Hex_Decoder would not check inputs, reported by Vaclav Ovsik
+ - Changed default CRL expire time from 30 days to 7 days
+ - X509_CRL's default PEM header is now "X509 CRL", for OpenSSL compatibility
+ - Corrected errors in the API doc, fixes from Ken Perano
+ - More documentation about the Pipe/Filter code
+
+* 1.3.11, 2004-04-01
+ - Fixed two show-stopping bugs in PKCS10_Request
+ - Added some sanity checks in Pipe/Filter
+ - The DNS and URI entries would get swapped in subjectAlternativeNames
+ - MAC_Filter is now willing to not take a key at creation time
+ - Setting the expiration times of certs and CRLs is more flexible
+ - Fixed problems building on AIX with GCC
+ - Fixed some problems in the tutorial pointed out by Dominik Vogt
+ - Documentation updates
+
+* 1.3.10, 2004-03-27
+ - Added support for OpenPGP's ASCII armor format
+ - Cleaned up the RNG system; seeding is much more flexible
+ - Added simple autoconfiguration abilities to configure.pl
+ - Fixed a GCC 2.95.x compile problem
+ - Updated the example configuration file
+ - Documentation updates
+
+* 1.3.9, 2004-03-07
+ - Added an engine using OpenSSL (requires 0.9.7 or later)
+ - X509_Certificate would lose email addresses stored in the DN
+ - Fixed a missing initialization in a BigInt constructor
+ - Fixed several Visual C++ compile problems
+ - Fixed some BeOS build problems
+ - Fixed the WiderWake benchmark
+
+* 1.3.8, 2003-12-30
+ - Internal changes to PK algorithms to divide data and algorithms
+ - DSA/DH/NR/ElGamal constructors accept taking just the private key again
+ - ElGamal keys now support being imported/exported as ASN.1 objects
+ - Much more consistent and complete error checking in PK algorithms
+ - Support for arbitrary backends (engines) for PK operations
+ - Added Montgomery reductions
+ - Added an engine that uses GNU MP (requires 4.1 or later)
+ - Removed the obsolete mp_gmp module
+ - Moved several initialization/shutdown functions to init.h
+ - Major refactoring of the memory containers
+ - New non-locking container, MemoryVector
+ - Fixed 64-bit problems in BigInt::set_bit/clear_bit
+ - Renamed PK_Key::check_params() to check_key()
+ - Some incompatible changes to OctetString
+ - Added version checking macros in version.h
+ - Removed the fips140 module pending rewrite
+ - Added some functions and hooks to help GUIs
+ - Moved more shared code into MDx_HashFunction
+ - Added a policy hook for specifying the encoding of X.509 strings
+
+* 1.3.7, 2003-12-12
+ - Fixed a big security problem in es_unix
+ - Fixed several stability problems in es_unix
+ - Expanded the list of programs es_unix will try to use
+ - SecureAllocator now only preallocates blocks in special cases
+ - Added a special case in Global_RNG::seed for forcing a full poll
+ - Removed the FIPS 186 RNG added in 1.3.5 pending further testing
+ - Configure updates for PowerPC CPUs
+ - Removed the (never tested) VAX support
+ - Added support for S/390 Linux
+
+* 1.3.6, 2003-12-07
+ - Added a new module 'minimal', which disables most algorithms
+ - SecureAllocator allocates a few blocks at startup
+ - A few minor MPI cleanups
+ - RPM spec file cleanups and fixes
+
+* 1.3.5, 2003-11-30
+ - Major improvements in ASN.1 string handling
+ - Added partial support for ASN.1 UTF8 STRINGs and BMP STRINGs
+ - Added partial support for the X.509v3 certificate policies extension
+ - Centralized the handling of character set information
+ - Added FIPS 140-2 startup self tests
+ - Added a module (fips140) for doing extra FIPS 140-2 tests
+ - Added FIPS 186-2 RNG
+ - Improved ASN.1 BIT STRING handling
+ - Removed a memory leak in PKCS10_Request
+ - The encoding of DirectoryString now follows PKIX guidelines
+ - Fixed some of the character set dependencies
+ - Fixed a DER encoding error for tags greater than 30
+ - The BER decoder can now handle tags larger than 30
+ - Fixed tm_hard.cpp to recognize SPARC on more systems
+ - Workarounds for a GCC 2.95.x bug in x509find.cpp
+ - RPM changed to install into /usr instead of /usr/local
+ - Added support for QNX
+
+* 1.2.8, 2003-11-21
+ - Merged several important bug fixes from 1.3.x
+
+* 1.3.4, 2003-11-21
+ - Added a module that does certain MPI operations using GNU MP
+ - Added the X9.42 Diffie-Hellman PRF
+ - The Zlib and Bzip2 objects now use custom allocators
+ - Added member functions for directly hashing/MACing SecureVectors
+ - Minor optimizations to the MPI addition and subtraction algorithms
+ - Some cleanups in the low-level MPI code
+ - Created separate AES-{128,192,256} objects
+
+* 1.3.3, 2003-11-17
+ - The library can now be repeatedly initialized and shutdown without crashing
+ - Fixed an off-by-one error in the CTS code
+ - Fixed an error in the EMSA4 verification code
+ - Fixed a memory leak in mutex.cpp (pointed out by James Widener)
+ - Fixed a memory leak in Pthread_Mutex
+ - Fixed several memory leaks in the testing code
+ - Bulletproofed the EMSA/EME/KDF/MGF retrieval functions
+ - Minor cleanups in SecureAllocator
+ - Removed a needless mutex guarding the (stateless) global timer
+ - Fixed a piece of bash-specific code in botan-config
+ - X.509 objects report more information about decoding errors
+ - Cleaned up some of the exception handling
+ - Updated the example config file with new OIDSs
+ - Moved the build instructions into a separate document, building.tex
+
+* 1.3.2, 2003-11-13
+ - Fixed a bug preventing DSA signatures from verifying on X.509 objects
+ - Made the X509_Store search routines more efficient and flexible
+ - Added a function to X509_PublicKey to do easy public/private key matching
+ - Added support for decoding indefinite length BER data
+ - Changed Pipe's peek() to take an offset
+ - Removed Filter::set_owns in favor of the new incr_owns function
+ - Removed BigInt::zero() and BigInt::one()
+ - Renamed the PEM related options from base/pem_* to pem/*
+ - Added an option to specify the line width when encoding PEM
+ - Removed the "rng/safe_longterm" option; it's always on now
+ - Changed the cipher used for RNG super-encryption from ARC4 to WiderWake4+1
+ - Cleaned up the base64/hex encoders and decoders
+ - Added an ASN.1/BER decoder as an example
+ - AES had its internals marked 'public' in previous versions
+ - Changed the value of the ASN.1 NO_OBJECT enum
+ - Various new hacks in the configure script
+ - Removed the already nominal support for SunOS
+
+* 1.3.1, 2003-11-04
+ - Generalized a few pieces of the DER encoder
+ - PKCS8::load_key would fail if handed an unencrypted key
+ - Added a failsafe so PKCS #8 key decoding can't go into an infinite loop
+
+* 1.3.0, 2003-11-02
+ - Major redesign of the PKCS #8 private key import/export system
+ - Added a small amount of UI interface code for getting passphrases
+ - Added heuristics that tell if a key, cert, etc is stored as PEM or BER
+ - Removed CS-Cipher, SHARK, ThreeWay, MD5-MAC, and EMAC
+ - Removed certain deprecated constructors of RSA, DSA, DH, RW, NR
+ - Made PEM decoding more forgiving of extra text before the header
+
+* 1.2.7, 2003-10-31
+ - Added support for reading configuration files
+ - Added constructors so NR and RW keys can be imported easily
+ - Fixed mp_asm64, which was completely broken in 1.2.6
+ - Removed tm_hw_ia32 module; replaced by tm_hard
+ - Added support for loading certain oddly formed RSA certificates
+ - Fixed spelling of NON_REPUDIATION enum
+ - Renamed the option default_to_ca to v1_assume_ca
+ - Fixed a minor bug in X.509 certificate generation
+ - Fixed a latent bug in the OID lookup code
+ - Updated the RPM spec file
+ - Added to the tutorial
+
+* 1.2.6, 2003-07-04
+ - Major performance increase for PK algorithms on most 64-bit systems
+ - Cleanups in the low-level MPI code to support asm implementations
+ - Fixed build problems with some versions of Compaq's C++ compiler
+ - Removed useless constructors for NR public and private keys
+ - Removed support for the patch_file directive in module files
+ - Removed several deprecated functions
+
+* 1.2.5, 2003-06-22
+ - Fixed a tricky and long-standing memory leak in Pipe
+ - Major cleanups and fixes in the memory allocation system
+ - Removed alloc_mlock, which has been superseded by the ml_unix module
+ - Removed a denial of service vulnerability in X509_Store
+ - Fixed compilation problems with VS .NET 2003 and Codewarrior 8
+ - Added another variant of PKCS8::load_key, taking a memory buffer
+ - Fixed various minor/obscure bugs which occurred when MP_WORD_BITS != 32
+ - BigInt::operator%=(word) was a no-op if the input was a power of 2
+ - Fixed portability problems in BigInt::to_u32bit
+ - Fixed major bugs in SSL3-MAC
+ - Cleaned up some messes in the PK algorithms
+ - Cleanups and extensions for OMAC and EAX
+ - Made changes to the entropy estimation function
+ - Added a 'beos' module set for use on BeOS
+ - Officially deprecated a few X509:: and PKCS8:: functions
+ - Moved the contents of primes.h to numthry.h
+ - Moved the contents of x509opt.h to x509self.h
+ - Removed the (empty) desx.h header
+ - Documentation updates
+
+* 1.2.4, 2003-05-29
+ - Fixed a bug in EMSA1 affecting NR signature verification
+ - Fixed a few latent bugs in BigInt related to word size
+ - Removed an unused function, mp_add2_nc, from the MPI implementation
+ - Reorganized the core MPI files
+
+* 1.2.3, 2003-05-20
+ - Fixed a bug that prevented DSA/NR key generation
+ - Fixed a bug that prevented importing some root CA certs
+ - Fixed a bug in the BER decoder when handing optional bit or byte strings
+ - Fixed the encoding of authorityKeyIdentifier in X509_CA
+ - Added a sanity check in PBKDF2 for zero length passphrases
+ - Added versions of X509::load_key and PKCS8::load_key that take a file name
+ - X509_CA generates 128 bit serial numbers now
+ - Added tests to check PK key generation
+ - Added a simplistic X.509 CA example
+ - Cleaned up some of the examples
+
+* 1.2.2, 2003-05-13
+ - Add checks to prevent any BigInt bugs from revealing an RSA or RW key
+ - Changed the interface of Global_RNG::seed
+ - Major improvements for the es_unix module
+ - Added another Win32 entropy source, es_win32
+ - The Win32 CryptoAPI entropy source can now poll multiple providers
+ - Improved the BeOS entropy source
+ - Renamed pipe_unixfd module to fd_unix
+ - Fixed a file descriptor leak in the EGD module
+ - Fixed a few locking bugs
+
+* 1.2.1, 2003-05-06
+ - Added ANSI X9.23 compatible CBC padding
+ - Added an entropy source using Win32 CryptoAPI
+ - Removed the Pipe I/O operators taking a FILE*
+ - Moved the BigInt encoding/decoding functions into the BigInt class
+ - Integrated several fixes for VC++ 7 (from Hany Greiss)
+ - Fixed the configure.pl script for Windows builds
+
+* 1.2.0, 2003-04-28
+ - Tweaked the Karatsuba cut-off points
+ - Increased the allowed keylength of HMAC and Blowfish
+ - Removed the 'mpi_ia32' module, pending rewrite
+ - Workaround a GCC 2.95.x bug in eme1.cpp
+
+* 1.1.13, 2003-04-22
+ - Added OMAC
+ - Added EAX authenticated cipher mode
+ - Diffie-Hellman would not do blinding in some cases
+ - Optimized the OFB and CTR modes
+ - Corrected Skipjack's word ordering, as per NIST clarification
+ - Support for all subject/issuer attribute types required by RFC 3280
+ - The removeFromCRL CRL reason code is now handled correctly
+ - Increased the flexibility of the allocators
+ - Renamed Rijndael to AES, created aes.h, deleted rijndael.h
+ - Removed support for the 'no_timer' LibraryInitializer option
+ - Removed 'es_pthr' module, pending further testing
+ - Cleaned up get_ciph.cpp
+
+* 1.1.12, 2003-04-15
+ - Fixed a ASN.1 string encoding bug
+ - Fixed a pair of X509_DN encoding problems
+ - Base64_Decoder and Hex_Decoder can now validate input
+ - Removed support for the LibraryInitializer option 'egd_path'
+ - Added tests for DSA X.509 and PKCS #8 key formats
+ - Removed a long deprecated feature of DH_PrivateKey's constructor
+ - Updated the RPM .spec file
+ - Major documentation updates
+
+* 1.1.11, 2003-04-07
+ - Added PKCS #10 certificate requests
+ - Changed X509_Store searching interface to be more flexible
+ - Added a generic Certificate_Store interface
+ - Added a function for generating self-signed X.509 certs
+ - Cleanups and changes to X509_CA
+ - New examples for PKCS #10 and self-signed certificates
+ - Some documentation updates
+
+* 1.1.10, 2003-04-03
+ - X509_CA can now generate new X.509 CRLs
+ - Added blinding for RSA, RW, DH, and ElGamal to prevent timing attacks
+ - More certificate and CRL extensions/attributes are supported
+ - Better DN handling in X.509 certificates/CRLs
+ - Added a DataSink hierarchy (suggested by Jim Darby)
+ - Consolidated SecureAllocator and ManagedAllocator
+ - Many cleanups and generalizations
+ - Added a (slow) pthreads based EntropySource
+ - Fixed some threading bugs
+
+* 1.1.9, 2003-02-25
+ - Added support for using X.509v2 CRLs
+ - Fixed several bugs in the path validation algorithm
+ - Certificates can be verified for a particular usage
+ - Algorithm for comparing distinguished names now follows X.509
+ - Cleaned up the code for the es_beos, es_ftw, es_unix modules
+ - Documentation updates
+
+* 1.1.8, 2003-01-29
+ - Fixes for the certificate path validation algorithm in X509_Store
+ - Fixed a bug affecting X509_Certificate::is_ca_cert()
+ - Added a general configuration interface for policy issues
+ - Cleanups and API changes in the X.509 CA, cert, and store code
+ - Made various options available for X509_CA users
+ - Changed X509_Time's interface to work around time_t problems
+ - Fixed a theoretical weakness in Randpool's entropy mixing function
+ - Fixed problems compiling with GCC 2.95.3 and GCC 2.96
+ - Fixed a configure bug (reported by Jon Wilson) affecting MinGW
+
+* 1.1.7, 2003-01-12
+ - Fixed an obscure but dangerous bug in SecureVector::swap
+ - Consolidated SHA-384 and SHA-512 to save code space
+ - Added SSL3-MAC and SSL3-PRF
+ - Documentation updates, including a new tutorial
+
+* 1.0.2, 2003-01-12
+ - Fixed an obscure SEGFAULT causing bug in Pipe
+ - Fixed an obscure but dangerous bug in SecureVector::swap
+
+* 1.1.6, 2002-12-10
+ - Initial support for X.509v3 certificates and CAs
+ - Major redesign/rewrite of the ASN.1 encoding/decoding code
+ - Added handling for DSA/NR signatures encoded as DER SEQUENCEs
+ - Documented the generic cipher lookup interface
+ - Added an (untested) entropy source for BeOS
+ - Various cleanups and bug fixes
+
+* 1.1.5, 2002-11-17
+ - Added the discrete logarithm integrated encryption system (DLIES)
+ - Various optimizations for BigInt
+ - Added support for assembler optimizations in modules
+ - Added BigInt x86 optimizations module (mpi_ia32)
+
+* 1.1.4, 2002-11-10
+ - Speedup of 15-30% for PK algorithms
+ - Implemented the PBES2 encryption scheme
+ - Fixed a potential bug in decoding RSA and RW private keys
+ - Changed the DL_Group class interface to handle different formats better
+ - Added support for PKCS #3 encoded DH parameters
+ - X9.42 DH parameters use a PEM label of 'X942 DH PARAMETERS'
+ - Added key pair consistency checking
+ - Fixed a compatibility problem with gcc 2.96 (pointed out by Hany Greiss)
+ - A botan-config script is generated at configure time
+ - Documentation updates
+
+* 1.1.3, 2002-11-03
+ - Added a generic public/private key loading interface
+ - Fixed a small encoding bug in RSA, RW, and DH
+ - Changed the PK encryption/decryption interface classes
+ - ECB supports using padding methods
+ - Added a function-based interface for library initialization
+ - Added support for RIPEMD-128 and Tiger PKCS#1 v1.5 signatures
+ - The cipher mode benchmarks now use 128-bit AES instead of DES
+ - Removed some obsolete typedefs
+ - Removed OpenCL support (opencl.h, the OPENCL_* macros, etc)
+ - Added tests for PKCS #8 encoding/decoding
+ - Added more tests for ECB and CBC
+
+* 1.1.2, 2002-10-21
+ - Support for PKCS #8 encoded RSA, DSA, and DH private keys
+ - Support for Diffie-Hellman X.509 public keys
+ - Major reorganization of how X.509 keys are handled
+ - Added PKCS #5 v2.0's PBES1 encryption scheme
+ - Added a generic cipher lookup interface
+ - Added the WiderWake4+1 stream cipher
+ - Added support for sync-able stream ciphers
+ - Added a 'paranoia level' option for the LibraryInitializer
+ - More security for RNG output meant for long term keys
+ - Added documentation for some of the new 1.1.x features
+ - CFB's feedback argument is now specified in bits
+ - Renamed CTR class to CTR_BE
+ - Updated the RSA and DSA examples to use X.509 and PKCS #8 key formats
+
+* 1.1.1, 2002-10-15
+ - Added the Korean hash function HAS-160
+ - Partial support for RSA and DSA X.509 public keys
+ - Added a mostly functional BER encoder/decoder
+ - Added support for non-deterministic MAC functions
+ - Initial support for PEM encoding/decoding
+ - Internal cleanups in the PK algorithms
+ - Several new convenience functions in Pipe
+ - Fixed two nasty bugs in Pipe
+ - Messed with the entropy sources for es_unix
+ - Discrete logarithm groups are checked for safety more closely now
+ - For compatibility with GnuPG, ElGamal now supports DSA-style groups
+
+* 1.1.0, 2002-09-14
+ - Added entropy estimation to the RNGs
+ - Improved the overall design of both Randpool and ANSI_X917_RNG
+ - Added a separate RNG for nonce generation
+ - Added window exponentiation support in power_mod
+ - Added a get_s2k function and the PKCS #5 S2K algorithms
+ - Added the TLSv1 PRF
+ - Replaced BlockCipherModeIV typedef with InitializationVector class
+ - Renamed PK_Key_Agreement_Scheme to PK_Key_Agreement
+ - Renamed SHA1 -> SHA_160 and SHA2_x -> SHA_x
+ - Added support for RIPEMD-160 PKCS#1 v1.5 signatures
+ - Changed the key agreement scheme interface
+ - Changed the S2K and KDF interfaces
+ - Better SCAN compatibility for HAVAL, Tiger, MISTY1, SEAL, RC5, SAFER-SK
+ - Added support for variable-pass Tiger
+ - Major speedup for Rabin-Williams key generation
+
+* 1.0.1, 2002-09-14
+ - Fixed a minor bug in Randpool::random()
+ - Added some new aliases and typedefs for 1.1.x compatibility
+ - The 4096-bit RSA benchmark key was decimal instead of hex
+ - EMAC was returning an incorrect name
+
+* 1.0.0, 2002-08-26
+ - Octal I/O of BigInt is now supported
+ - Fixed portability problems in the es_egd module
+ - Generalized IV handling in the block cipher modes
+ - Added Karatsuba multiplication and k-ary exponentiation
+ - Fixed a problem in the multiplication routines
+
+* 0.9.2, 2002-08-18
+ - DH_PrivateKey::public_value() was returning the wrong value
+ - Various BigInt optimizations
+ - The filters.h header now includes hex.h and base64.h
+ - Moved Counter mode to ctr.h
+ - Fixed a couple minor problems with VC++ 7
+ - Fixed problems with the RPM spec file
+
+* 0.9.1, 2002-08-10
+ - Grand rename from OpenCL to Botan
+ - Major optimizations for the PK algorithms
+ - Added ElGamal encryption
+ - Added Whirlpool
+ - Tweaked memory allocation parameters
+ - Improved the method of seeding the global RNG
+ - Moved pkcs1.h to eme_pkcs.h
+ - Added more test vectors for some algorithms
+ - Fixed error reporting in the BigInt tests
+ - Removed Default_Timer, it was pointless
+ - Added some new example applications
+ - Removed some old examples that weren't that interesting
+ - Documented the compression modules
+
+* 0.9.0, 2002-08-03
+ - EMSA4 supports variable salt size
+ - PK_* can take a string naming the encoding method to use
+ - Started writing some internals documentation
+
+* 0.8.7, 2002-07-30
+ - Fixed bugs in EME1 and EMSA4
+ - Fixed a potential crash at shutdown
+ - Cipher modes returned an ill-formed name
+ - Removed various deprecated types and headers
+ - Cleaned up the Pipe interface a bit
+ - Minor additions to the documentation
+ - First stab at a Visual C++ makefile (doc/Makefile.vc7)
+
+* 0.8.6, 2002-07-25
+ - Added EMSA4 (aka PSS)
+ - Brought the manual up to date; many corrections and additions
+ - Added a parallel hash function construction
+ - Lookup supports all available algorithms now
+ - Lazy initialization of the lookup tables
+ - Made more discrete logarithm groups available through get_dl_group()
+ - StreamCipher_Filter supports seeking (if the underlying cipher does)
+ - Minor optimization for GCD calculations
+ - Renamed SAFER_SK128 to SAFER_SK
+ - Removed many previously deprecated functions
+ - Some now-obsolete functions, headers, and types have been deprecated
+ - Fixed some bugs in DSA prime generation
+ - DL_Group had a constructor for DSA-style prime gen but it wasn't defined
+ - Reversed the ordering of the two arguments to SEAL's constructor
+ - Fixed a threading problem in the PK algorithms
+ - Fixed a minor memory leak in lookup.cpp
+ - Fixed pk_types.h (it was broken in 0.8.5)
+ - Made validation tests more verbose
+ - Updated the check and example applications
+
+* 0.8.5, 2002-07-21
+ - Major changes to constructors for DL-based cryptosystems (DSA, NR, DH)
+ - Added a DL_Group class
+ - Reworking of the pubkey internals
+ - Support in lookup for aliases and PK algorithms
+ - Renamed CAST5 to CAST_128 and CAST256 to CAST_256
+ - Added EMSA1
+ - Reorganization of header files
+ - LibraryInitializer will install new allocator types if requested
+ - Fixed a bug in Diffie-Hellman key generation
+ - Did a workaround in pipe.cpp for GCC 2.95.x on Linux
+ - Removed some debugging code from init.cpp that made FTW ES useless
+ - Better checking for invalid arguments in the PK algorithms
+ - Reduced Base64 and Hex default line length (if line breaking is used)
+ - Fixes for HP's aCC compiler
+ - Cleanups in BigInt
+
+* 0.8.4, 2002-07-14
+ - Added Nyberg-Rueppel signatures
+ - Added Diffie-Hellman key exchange (kex interface is subject to change)
+ - Added KDF2
+ - Enhancements to the lookup API
+ - Many things formerly taking pointers to algorithms now take names
+ - Speedups for prime generation
+ - LibraryInitializer has support for seeding the global RNG
+ - Reduced SAFER-SK128 memory consumption
+ - Reversed the ordering of public and private key values in DSA constructor
+ - Fixed serious bugs in MemoryMapping_Allocator
+ - Fixed memory leak in Lion
+ - FTW_EntropySource was not closing the files it read
+ - Fixed line breaking problem in Hex_Encoder
+
+* 0.8.3, 2002-06-09
+ - Added DSA and Rabin-Williams signature schemes
+ - Added EMSA3
+ - Added PKCS#1 v1.5 encryption padding
+ - Added Filters for PK algorithms
+ - Added a Keyed_Filter class
+ - LibraryInitializer processes arguments now
+ - Major revamp of the PK interface classes
+ - Changed almost all of the Filters for non-template operation
+ - Changed HMAC, Lion, Luby-Rackoff to non-template classes
+ - Some fairly minor BigInt optimizations
+ - Added simple benchmarking for PK algorithms
+ - Added hooks for fixed base and fixed exponent modular exponentiation
+ - Added some examples for using RSA
+ - Numerous bugfixes and cleanups
+ - Documentation updates
+
+* 0.8.2, 2002-05-18
+ - Added an (experimental) algorithm lookup interface
+ - Added code for directly testing BigInt
+ - Added SHA2-384
+ - Optimized SHA2-512
+ - Major optimization for Adler32 (thanks to Dan Nicolaescu)
+ - Various minor optimizations in BigInt and related areas
+ - Fixed two bugs in X9.19 MAC, both reported by Darren Starsmore
+ - Fixed a bug in BufferingFilter
+ - Made a few fixes for MacOS X
+ - Added a workaround in configure.pl for GCC 2.95.x
+ - Better support for PowerPC, ARM, and Alpha
+ - Some more cleanups
+
+* 0.8.1, 2002-05-06
+ - Major code cleanup (check doc/deprecated.txt)
+ - Various bugs fixed, including several portability problems
+ - Renamed MessageAuthCode to MessageAuthenticationCode
+ - A replacement for X917 is in x917_rng.h
+ - Changed EMAC to non-template class
+ - Added ANSI X9.19 compatible CBC-MAC
+ - TripleDES now supports 128 bit keys
+
+* 0.8.0, 2002-04-24
+ - Merged BigInt: many bugfixes and optimizations since alpha2
+ - Added RSA (rsa.h)
+ - Added EMSA2 (emsa2.h)
+ - Lots of new interface code for public key algorithms (pk_base.h, pubkey.h)
+ - Changed some interfaces, including SymmetricKey, to support the global rng
+ - Fixed a serious bug in ManagedAllocator
+ - Renamed RIPEMD128 to RIPEMD_128 and RIPEMD160 to RIPEMD_160
+ - Removed some deprecated stuff
+ - Added a global random number generator (rng.h)
+ - Added clone functions to most of the basic algorithms
+ - Added a library initializer class (init.h)
+ - Version macros in version.h
+ - Moved the base classes from opencl.h to base.h
+ - Renamed the bzip2 module to comp_bzip2 and zlib to comp_zlib
+ - Documentation updates for the new stuff (still incomplete)
+ - Many new deprecated things: check doc/deprecated.txt
+
+* 0.7.10, 2002-04-07
+ - Added EGD_EntropySource module (es_egd)
+ - Added a file tree walking EntropySource (es_ftw)
+ - Added MemoryLocking_Allocator module (alloc_mlock)
+ - Renamed the pthr_mux, unix_rnd, and mmap_mem modules
+ - Changed timer mechanism; the clock method can be switched on the fly.
+ - Renamed MmapDisk_Allocator to MemoryMapping_Allocator
+ - Renamed ent_file.h to es_file.h (ent_file.h is around, but deprecated)
+ - Fixed several bugs in MemoryMapping_Allocator
+ - Added more default sources for Unix_EntropySource
+ - Changed SecureBuffer to use same allocation methods as SecureVector
+ - Added bigint_divcore into mp_core to support BigInt alpha2 release
+ - Removed some Pipe functions deprecated since 0.7.8
+ - Some fixes for the configure program
+
+* 0.7.9, 2002-03-19
+ - Memory allocation substantially revamped
+ - Added memory allocation method based on mmap(2) in the mmap_mem module
+ - Added ECB and CTS block cipher modes (ecb.h, cts.h)
+ - Added a Mutex interface (mutex.h)
+ - Added module pthr_mux, implementing the Mutex interface
+ - Added Threaded Filter interface (thr_filt.h)
+ - All algorithms can now by keyed with SymmetricKey objects
+ - More testing occurs with --validate (expected failures)
+ - Fixed two bugs reported by Hany Greiss, in Luby-Rackoff and RC6
+ - Fixed a buffering bug in Bzip_Decompress and Zlib_Decompress
+ - Made X917 safer (and about 1/3 as fast)
+ - Documentation updates
+
+* 0.7.8, 2002-02-28
+ - More capabilities for Pipe, inspired by SysV STREAMS, including peeking,
+ better buffering, and stack ops. NOT BACKWARDS COMPATIBLE: SEE DOCUMENTATION
+ - Added a BufferingFilter class
+ - Added popen() based EntropySource for generic Unix systems (unix_rnd)
+ - Moved 'devrand' module into main distribution (ent_file.h), renamed to
+ File_EntropySource, and changed interface somewhat.
+ - Made Randpool somewhat more conservative and also 25% faster
+ - Minor fixes and updates for the configure script
+ - Added some tweaks for memory allocation
+ - Documentation updates for the new Pipe interface
+ - Fixed various minor bugs
+ - Added a couple of new example programs (stack and hasher2)
+
+* 0.7.7, 2001-11-24
+ - Filter::send now works in the constructor of a Filter subclass
+ - You may now have to include <opencl/pipe.h> explicitly in some code
+ - Added preliminary PK infrastructure classes in pubkey.h and pkbase.h
+ - Enhancements to SecureVector (append, destroy functions)
+ - New infrastructure for secure memory allocation
+ - Added IEEE P1363 primitives MGF1, EME1, KDF1
+ - Rijndael optimizations and cleanups
+ - Changed CipherMode<B> to BlockCipherMode(B*)
+ - Fixed a nasty bug in pipe_unixfd
+ - Added portions of the BigInt code into the main library
+ - Support for VAX, SH, POWER, PowerPC-64, Intel C++
+
+* 0.7.6, 2001-10-14
+ - Fixed several serious bugs in SecureVector created in 0.7.5
+ - Square optimizations
+ - Fixed shared objects on MacOS X and HP-UX
+ - Fixed static libs for KCC 4.0; works with KCC 3.4g as well
+ - Full support for Athlon and K6 processors using GCC
+ - Added a table of prime numbers < 2**16 (primes.h)
+ - Some minor documentation updates
+
+* 0.7.5, 2001-08-19
+ - Split checksum.h into adler32.h, crc24.h, and crc32.h
+ - Split modes.h into cbc.h, cfb.h, and ofb.h
+ - CBC_wPadding* has been replaced by CBC_Encryption and CBC_Decryption
+ - Added OneAndZeros and NoPadding methods for CBC
+ - Added Lion, a very fast block cipher construction
+ - Added an S2K base class (s2k.h) and an OpenPGP_S2K class (pgp_s2k.h)
+ - Basic types (ciphers, hashes, etc) know their names now (call name())
+ - Changed the EntropySource type somewhat
+ - Big speed-ups for ISAAC, Adler32, CRC24, and CRC32
+ - Optimized CAST-256, DES, SAFER-SK, Serpent, SEAL, MD2, and RIPEMD-160
+ - Some semantics of SecureVector have changed slightly
+ - The mlock module has been removed for the time being
+ - Added string handling functions for hashes and MACs
+ - Various non-user-visible cleanups
+ - Shared library soname is now set to the full version number
+
+* 0.7.4, 2001-07-15
+ - New modules: Zlib, gettimeofday and x86 RTC timers, Unix I/O for Pipe
+ - Fixed a vast number of errors in the config script/makefile/specfile
+ - Pipe now has a stdio(3) interface as well as C++ iostreams
+ - ARC4 supports skipping the first N bytes of the cipher stream (ala MARK4)
+ - Bzip2 supports decompressing multiple concatenated streams, and flushing
+ - Added a simple 'overall average' score to the benchmarks
+ - Fixed a small bug in the POSIX timer module
+ - Removed a very-unlikely-to-occur bug in most of the hash functions
+ - filtbase.h now includes <iosfwd>, not <iostream>
+ - Minor documentation updates
+
+* 0.7.3, 2001-06-08
+ - Fix build problems on Solaris/SPARC
+ - Fix build problems with Perl versions < 5.6
+ - Fixed some stupid code that broke on a few compilers
+ - Added string handling functions to Pipe
+ - MISTY1 optimizations
+
+* 0.7.2, 2001-06-03
+ - Build system supports modules
+ - Added modules for mlock, a /dev/random EntropySource, POSIX1.b timers
+ - Added Bzip2 compression filter, contributed by Peter Jones
+ - GNU make no longer required (tested with 4.4BSD pmake and Solaris make)
+ - Fixed minor bug in several of the hash functions
+ - Various other minor fixes and changes
+ - Updates to the documentation
+
+* 0.7.1, 2001-05-16
+ - Rewrote configure script: more consistent and complete
+ - Made it easier to find out parameters of types at run time (opencl.h)
+ - New functions for finding the version being used (version.h)
+ - New SymmetricKey interface for Filters (symkey.h)
+ - InvalidKeyLength now records what the invalid key length was
+ - Optimized DES, CS-Cipher, MISTY1, Skipjack, XTEA
+ - Changed GOST to use correct S-box ordering (incompatible change)
+ - Benchmark code was almost totally rewritten
+ - Many more entries in the test vector file
+ - Fixed minor and idiotic bug in check.cpp
+
+* 0.7.0, 2001-03-01
+ - First public release
+
diff --git a/botan/doc/pgpkeys.asc b/botan/doc/pgpkeys.asc
new file mode 100644
index 0000000..378230f
--- /dev/null
+++ b/botan/doc/pgpkeys.asc
@@ -0,0 +1,83 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.9 (GNU/Linux)
+
+mQGiBDqZbS4RBACH3vOrWo72lWh/lbECfIfGdtl+YDgyGMB2BiGDJG7Kzbg9IB2e
+no0Du+omligWpgWlYdkiJ+/wpCJlBxd/P3rEegp822aeV1eD3E03wxWUvhyWgy+8
+I8POrcCjC9RkrTGTl5RiFdaRVCG93vzmJFUJoI1Kt0F5AnTJXJm4VgNo0wCg4F/M
+jN7YfhrUroE8ksTGPiCeNocD/R6wGZ0FFtYHdK5W19u/vM9JfAXxoK+OmDheFSVL
+oIWVCXacwvbVQ15MfdQxaRyZmkWD9jgm2Omr8II6iK12B3WLRb96bkQzC0Sd25Xm
+2tLKUDBwK0meG/8cRj3hE4WFF6VBdhWNtRhbby6Le9JHC+ylMrHwMy+HHXl5a2gf
+ycCmA/9LU5GukTKfaBz9OPrVkMf2n0RbdBgn5hxtDeZ5iV6JMosEGobMnZ77n44M
+VdGk6NWlMZqmwy6tJg2CdKPiQtjJaPuIR6qM0rtc8tpnhJSqq2c3KNOcaTennJsc
+H3MNtT6FeZH1pZOhcmLjs7wb267NgR89vBQd2l46qWYSaBCASbQWQm90YW4gRGlz
+dHJpYnV0aW9uIEtleYhiBBMRAgAaBQsHCgMEAxUDAgMWAgECF4ACGQEFAkkXKWoA
+EgdlR1BHAAEBCRCmPyy9+gL7zKhdAKCfZvYBJeZaVW+Cq8S463bbw9vtJACg29tp
+zrPhPtU4baw3ngVFUjUcLCyJAhwEEAECAAYFAkkq4q8ACgkQXA+W6E7BbWuJmg/+
+NTxLCg0I527bNowv/pEBrN26Aghwu3/Gn6QrRz2bFQ1A/8LNw2w8eKY0w/b5ieiC
+kYy/DmkcDFkspmtaVvA0A+hK/NIIEbFqllKnTQ2BK5EdqQxS+OuBZN4BbJJ2XzKD
+6bUcmIEpzymVah/r49D09VG7TQeBequcER9DumSuKhDM10Jt594tkjUo8E7BO8Np
+54T2MXX3Nk839eZLihnSh5Cnj6pmLlr/4Tx8iXQTuk2CKkOWxCXaE1CJlUnaXTTy
+T16na7PdWPKUR1x2cNY9uL+r5RwSRebV2iV3620MzFHYIAbFYrRdew8HnBnzrwgE
+gk4z8fFFSDwIkkGVIkZMqchyWQySJ8UIQpUPVM0/EA+ejgMbLx/Xt6ONIZQiq9Cc
+8AaPsoEXFlQHRFN65BB8GIYUdraw/yHwTWX4UNtyNNTq6zgwnsvik6ZJN7RNdgea
+rZavW8svXsDZgwEVDI3ps19B1yD0AxC/IJ9uqxqTKn+dYciiZJCMBUTITb6lVs6b
+SnMNqdllE2z591cQH02rInHH25WiMjoPeboUozLZ7tyWZtv7/CP4a+IcNqB7LmET
+qNTWki3cAnLw5UfPVYrnunI5jHG2eFCjHk3cGAM/AcWRs+wqRfUAqzjs/rRUH8QD
+n4vADnCuKHle3dRFq3Dy+fCZe/7yEmeAyJ8FbmSQRgOZAgsEQX8lLwEQALecnQ3J
+k1iajTjKoUryWAs8orDTBxiOkYQuwD1g01Geu5XMcDx0ykqPPer1688QN2P/4Lc6
+zN4B0h3SNn8zmz9MI9afCaL3DPynogKX4/zPvSSAITiSytClKNbpSRoqjpdXeoUU
+cW7gs8+d81bYJtgBtATtVHDZXzDO32wbPT1Zi+IdI+19R84tgWZBDgLYdQIaUa+G
++j14Gdubc4nFfP6h/UmWC7r6xo0TeQsNLUv2c9nyMeUUKeKZwBar0349sWKihjLf
+ne9TXPgdEpg0C9fYAlxTOBa+hIbESVie/4BxtvSHk+wWFpRZtBkS43SDF5qZY0TX
+uZJmt3YhiX/zlRut1nhLtqxzNVMIZtNZkD4MrMl7+mHManITkCMBS5NmpmXdlBES
+Si+cPVMD91fEAuILczJj/VCUl1pn83kIlD9wxDNQcFdMzuicvFneEszW7UCdvPUC
+3UcFQcsxAuYUEPr/H9Qraogm8/UE7+fTb8pTSt06KsZR3nMLLMKICcgLpraDQENZ
+GCcK8js82FsB+6ccQ5WB1nMDfdDbYNyRKv/bgPmKxOw74jo24wSeio4zFHBzVXYQ
+CLleO52H+w5jz4vEXhC3IEqoLhJHAIW41yl3pqx1qeZ0XwOfGP67nQzI+YhUn59+
+OBngAVQ8rdfWxopzVTI7oRlQafFbTyN/sReTAAYptC5KYWNrIExsb3lkIChTaWdu
+aW5nIEtleSkgPGxsb3lkQHJhbmRvbWJpdC5uZXQ+iQIuBBMBAgAYAhsDAh4BAheA
+BQJBgDp5AwsJAgQVAgMIAAoJEFwPluhOwW1roTQP+QFzRSVwJYzHUebr1nQSS65b
+/9EeX3tSI8ZnKEMAIAYn3YvnYhZxKwdFvCWKZJXfPcaJqv+xWEvArsYEbj6n4AJw
+73V27USLqvqNnBleeQluM1nm8AYvmukHXUDmTOCRhqL1rK70DKTRB3Q08sgnmuRF
+8sMuG6TRPm8zk9N87zI8fYbT7hWxoO6E9wXPOr+4cYirmtbPY0Ni5bWvd/JrRzWa
+2e/UVrpvoBE6kPaF6mxK8oDTGmRr+yKjEsxsTKYQJbguzDYtjEvjoDxScYfegk7n
+5PdOGyhjDV/EjC/I7HcJNDVg72szmNLaNskoiHZaEiiTKD60gWFRwQJfNRYiZk0J
+x1707wNZCzjKVkeD5U8x4uWchkWjXft0XdCYsKdZQ/GTepcIwz683wicdCVAMcUt
+vy43i5DaPelOV22TqL6coLoelso1AURHAwfgBc/cqCsweUVotNA8SvsYMTaXuNMm
+578Cs44AEXrWY0sLFCYEu6rA47HV7FXoaruK7Qjo/IopqsLd42g7HBR993tEl7j5
+3lK0VGHdFI0I4kw/tWSVXqH5vK12WLg0mc+21KGoLjkGSdPsKNUP2xhZaiK8fAB9
+2WonnGMAVUXwQ4Tu9gGzA4KzjZv5RLWvOnbRc8Vh1ppXXoSrlRkHJXT6wHfNDrvf
+ZJuOruFauUJmw1CEQcKyiQEiBBABAgAMBQJBugFKBQMAEnUAAAoJEJcQuJvKV618
+KrcIAJ0f1Js973k2ednThL7Fy1B68KZ/DOpbWqB8R53oJ/aaIU0TpXqKFN+amy1N
+qrC2lLh7DebBJkan+UNJ6l/uj6cR0q+D1VeDjrFKgS9D7WwjXthik6Ph/nMnd9jz
+TH7+8CxN3h0BAlaysxbM/gXjPYd/z05yYdtMayE/hnUhG1ysKrWdVzZv68qBesi+
+h0Z5b7IsfdlTtBi+0Y/wNDiOl8dg7UIkNjYveNgv02yR6InQEnAW6ESEiJ5/p4fi
+CPtyTk3Hz8biM4I7oTKPNYhnpp7LxVMQbeWck3mb9Yjr2uqjNMiFuBHslmAZvtBn
+hj55BU0GwM7ukMNkQLWICfftXGmIRgQTEQIABgUCQjkXLAAKCRBG+5XZXjRWKC0P
+AKCHLrGe1Lz/4sxvKhROPiGFAEOPoACfRYNAzEZJ2iqeb6JxQuu3gxH3XVuZAQsE
+QYPWPQEIAMfE8mQ9yMkT7gOWKzHaFVzQOPokjUxIuuQzxH7Zs6FVRJ96vE9PUQw+
+F+sB04dMCWjK9FOEnO2dmw0qp8svj0YZwEt0QYBU2SzWkbftN7N7kvHVci7MkWuj
+MvayoHLkLqcekWB3W1wPrxFqHbCnS7ZxH2jBd/Uiop0R+6jrrX4xO/vBMHXiEpXv
+mcHtk7rrvpIRlEgtgz7tEnAoAoSYQ8lzqER/3hVef15w3NpOUeBiSOHP11ss53eh
+31e+5TD4sxHV3AGozFu9H3QyJeNt50MSRsCtxkH1g4Ai8Rf+ULeppbhcm3iLAdaX
+9hVkR8Aty9DLB7YIOsfmE7v3jB30ykEABim0FkJvdGFuIERpc3RyaWJ1dGlvbiBL
+ZXmJATQEEwECAB4FAkGD1j0CGwMGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQYhHr
+8e+637yzmAf/VTzFHTY/JoehmaXmoQflhDT2gvHCRi1cWv0g1nxPMLAgN44KHRQp
+ckgO8edO6QYI9zTxwa+WQxt+WqX8qv8/MAKjhqsLIB/XBF2+FwW6RXcO9t7gwKDY
+6ufUuN7Lju0CIZrXYVUqSdwLzwG6MiTc170aYranq1riRtmtRwhubvIMRo3bkxZX
+RPWHpm535h7Cfos7AKj+kq/Q3IlBhnmuSLS2H05rceLQ37VHi/xJOqqRZiJndSPy
+gP3uKII1fOaLu74YKGSerXeWtCzzA5XzCZRov0z74CnTRKwT5u5hf4zp9doMi+DV
+sjtXTqXDHM8snA2tvPASNW67uK+v7WnZmYkCHAQTAQIABgUCQYPWUgAKCRBcD5bo
+TsFta+r9EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU
+8WIcFO1A59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18h
+mqqwNlKY97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8c
+r+C9HTs1Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65
+MbJGlwWpw/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt
+4XkS51yWZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2US
+yLI+mm9diMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5
+MnplTWwi40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMP
+oueF9mKZCf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqM
+ACFuTNdBsjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsq
+oTJ8asY2VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2Zg==
+=QyrG
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/botan/doc/scripts/comba.py b/botan/doc/scripts/comba.py
new file mode 100644
index 0000000..ce3cfed
--- /dev/null
+++ b/botan/doc/scripts/comba.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+import sys
+
+def comba_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ x += [(j,i-j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_sqr_indexes(N):
+
+ indexes = []
+
+ for i in xrange(0, 2*N):
+ x = []
+
+ for j in xrange(max(0, i-N+1), min(N, i+1)):
+ if j < i-j:
+ x += [(j,i-j)]
+ else:
+ x += [(i-j,j)]
+ indexes += [sorted(x)]
+
+ return indexes
+
+def comba_multiply_code(N):
+ indexes = comba_indexes(N)
+
+ for (i,idx) in zip(range(0, len(indexes)), indexes):
+ for pair in idx:
+ print "word3_muladd(&w2, &w1, &w0, x[%2d], y[%2d]);" % (pair)
+ print "z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;" % (i)
+
+def comba_square_code(N):
+ indexes = comba_sqr_indexes(N)
+
+ for (rnd,idx) in zip(range(0, len(indexes)), indexes):
+ for (i,pair) in zip(range(0, len(idx)), idx):
+ if pair[0] == pair[1]:
+ print " word3_muladd(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair)
+ elif i % 2 == 0:
+ print " word3_muladd_2(&w2, &w1, &w0, x[%2d], x[%2d]);" % (pair[0], pair[1])
+ if rnd < len(idx)-2:
+ print " z[%2d] = w0; w0 = w1; w1 = w2; w2 = 0;\n" % (rnd)
+ elif rnd == len(idx)-1:
+ print " z[%2d] = w0;\n" % (rnd)
+ else:
+ print " z[%2d] = w1;\n" % (rnd)
+
+def main(args = None):
+ if args is None:
+ args = sys.argv
+ #comba_square_code(int(args[1]))
+ comba_multiply_code(int(args[1]))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/botan/doc/scripts/combine_bmarks.pl b/botan/doc/scripts/combine_bmarks.pl
new file mode 100644
index 0000000..b643649
--- /dev/null
+++ b/botan/doc/scripts/combine_bmarks.pl
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my %results;
+my %pk;
+
+my %pk_algos;
+my %algos;
+
+my %filename_to_desc;
+
+for my $filename (@ARGV) {
+
+ open IN, "<$filename" or die "Couldn't read $filename ($!)\n";
+
+ my $desc = <IN>;
+ chomp $desc;
+
+ $results{$desc} = {};
+
+ while(<IN>) {
+ if(/(.*): +(.*) Mbytes\/sec/) {
+ $results{$desc}{$1} = $2;
+ $algos{$1} = undef;
+ }
+ if(/(.*): (.*) ops \/ second \((.*)\)/) {
+ my $alg = "$1";
+ $alg = "$alg $3" if defined($3);
+ $pk{$desc}{$alg} = $2;
+ $pk_algos{$alg} = undef;
+ }
+ }
+}
+
+
+sub print_table {
+ my @columns = sort keys %results;
+
+ print "\n<P>All results are in MiB / second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ $line = '';
+
+ foreach my $algo (sort keys %algos) {
+ $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $results{$col}{$algo};
+ $result = "-" if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ $line = '';
+ }
+
+ print "</TABLE>\n";
+}
+
+
+sub print_pk_table {
+ my @columns = sort keys %pk;
+
+ print "\n<P>All results are in operations per second:\n";
+ print "<TABLE BORDER CELLSPACING=1>\n<THEAD>\n";
+
+ my %col_index = ();
+
+ my $line = "<TR><TH>Algorithm ";
+
+ foreach my $col (@columns) {
+ $col_index{$col} = length($line);
+ $line .= "<TH>" . $col . " ";
+ }
+
+ $line .= "\n<TBODY>\n";
+
+ print $line;
+
+ foreach my $algo (sort keys %pk_algos) {
+ my $line = " <TR><TH>$algo ";
+
+ for my $col (@columns) {
+ my $result = $pk{$col}{$algo};
+ $result = '-' if not defined($result);
+
+ $result = "<TH>$result";
+
+ $line .= ' ' while(length($line) < ($col_index{$col}));
+ $line .= $result;
+
+ }
+
+ print $line, "\n";
+ }
+
+ print "</TABLE>\n";
+}
+
+print_table();
+print_pk_table();
diff --git a/botan/doc/scripts/dist.sh b/botan/doc/scripts/dist.sh
new file mode 100644
index 0000000..9629446
--- /dev/null
+++ b/botan/doc/scripts/dist.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# This is probably only useful if run on my machine, which is not
+# exactly ideal
+
+SELECTOR=h:net.randombit.botan.1_8
+KEY_ID=EFBADFBC
+MTN_DB=/storage/mtn/botan.mtn
+WEB_DIR=~/projects/www
+DIST_DIR=~/Botan-dist
+
+# You shouldn't have to change anything after this
+mkdir -p $DIST_DIR
+cd $DIST_DIR
+
+mtn -d $MTN_DB checkout -r $SELECTOR Botan
+
+VERSION=$(Botan/configure.py --version)
+
+mv Botan Botan-$VERSION
+
+cd Botan-$VERSION
+rm -rf _MTN
+rm -f .mtn-ignore
+
+# Build docs
+cd doc
+
+for doc in api tutorial building
+do
+ latex $doc.tex
+ latex $doc.tex
+ dvips $doc.dvi -o
+ pdflatex $doc.tex
+ pdflatex $doc.tex
+ cp $doc.pdf $DIST_DIR
+ mv $doc.ps $DIST_DIR
+ # Clean up after TeX
+ rm -f $doc.aux $doc.log $doc.dvi $doc.toc
+done
+
+cp log.txt ../..
+
+cd .. # topdir
+cd .. # now in DIST_DIR
+
+tar -cf Botan-$VERSION.tar Botan-$VERSION
+
+bzip2 -9 -k Botan-$VERSION.tar
+gzip -9 Botan-$VERSION.tar
+
+rm -rf Botan-$VERSION
+
+mv Botan-$VERSION.tar.gz Botan-$VERSION.tgz
+mv Botan-$VERSION.tar.bz2 Botan-$VERSION.tbz
+
+echo "*****************************************************"
+read -a PASSWORD -p "Enter PGP password (or ^C to skip signatures): "
+
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tgz
+echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tbz
+
+mv Botan-$VERSION.tgz* $WEB_DIR/files/botan/v1.8
+mv Botan-$VERSION.tbz* $WEB_DIR/files/botan/v1.8
diff --git a/botan/doc/scripts/primes.py b/botan/doc/scripts/primes.py
new file mode 100644
index 0000000..cf4d139
--- /dev/null
+++ b/botan/doc/scripts/primes.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import sys
+
+def gcd(x,y):
+ if x <= 0 or y <= 0:
+ raise ValueError, "Arguments must be positive integers"
+ g = y
+ while x > 0:
+ g = x
+ x = y % x
+ y = g
+ return g
+
+
+def gen_primes():
+ primes = [2,3,5,7,11]
+
+ # Primes < 11351 fit into less than 256x64 bits
+ for i in xrange(1+primes[-1], 11351+1):
+ for prime in primes:
+ if gcd(i, prime) != 1:
+ break
+ else:
+ primes.append(i)
+
+ return primes
+
+def extract_product(primes):
+ product = 1
+
+ used = set()
+
+ for prime in sorted(primes, reverse=True):
+ if product * prime < 2**64:
+ product *= prime
+ used.add(prime)
+
+ primes -= used
+
+ return product
+
+def main():
+ primes = gen_primes()
+
+ primes.sort()
+ primes.reverse()
+
+ primes = set(primes)
+
+ while len(primes):
+ print "0x%016X, " % extract_product(primes)
+
+ #product = 1
+ #for prime in primes:
+ # product *= prime
+
+ # if product >= 2**64:
+ # print "%016X" % (product/prime)
+ # product = prime
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/botan/doc/scripts/print_deps.py b/botan/doc/scripts/print_deps.py
new file mode 100644
index 0000000..b92c433
--- /dev/null
+++ b/botan/doc/scripts/print_deps.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+"""
+Analyze the botan source tree and print the module interdependencies
+
+(C) 2009 Jack Lloyd
+Distributed under the terms of the Botan license
+"""
+
+import os
+import os.path
+import sys
+import re
+
+def find_deps_in(filename):
+ # By convention #include's with spaces before them are
+ # always wrapped in #ifdef blocks
+ regexp = re.compile('^#include <botan/(.*)>')
+
+ for line in open(filename).readlines():
+ match = regexp.match(line)
+ if match != None:
+ yield match.group(1)
+
+def get_dependencies(dirname):
+ all_dirdeps = {}
+ file_homes = {}
+
+ is_sourcefile = re.compile('\.(cpp|h|S)$')
+
+ for (dirpath, dirnames, filenames) in os.walk('src'):
+ dirdeps = set()
+ for filename in filenames:
+ if is_sourcefile.search(filename) != None:
+ file_homes[filename] = os.path.basename(dirpath)
+
+ for dep in find_deps_in(os.path.join(dirpath, filename)):
+ if dep not in filenames and dep != 'build.h':
+ dirdeps.add(dep)
+
+ dirdeps = sorted(dirdeps)
+ if dirdeps != []:
+ all_dirdeps[dirpath] = dirdeps
+
+ return (all_dirdeps, file_homes)
+
+def main():
+ (all_dirdeps, file_homes) = get_dependencies('src')
+
+ def interesting_dep_for(dirname):
+ def interesting_dep(dep):
+ if dep == 'utils':
+ return False # everything depends on it
+
+ # block/serpent depends on block, etc
+ if dirname.find('/%s/' % (dep)) > 0:
+ return False
+ return True
+ return interesting_dep
+
+ for dirname in sorted(all_dirdeps.keys()):
+ depdirs = sorted(set(map(lambda x: file_homes[x], all_dirdeps[dirname])))
+
+ depdirs = filter(interesting_dep_for(dirname), depdirs)
+
+ if depdirs != []:
+ print "%s: %s" % (dirname, ' '.join(depdirs))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/botan/doc/scripts/update_deps.py b/botan/doc/scripts/update_deps.py
new file mode 100644
index 0000000..61aa887
--- /dev/null
+++ b/botan/doc/scripts/update_deps.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+import sys
+import re
+import os.path
+
+def update_requires(dir, deps):
+ lines = map(lambda x: x.strip(),
+ open(os.path.join(dir, 'info.txt')).readlines())
+
+ if '<requires>' in lines:
+ start = lines.index('<requires>')
+
+ while lines.pop(start) != '</requires>':
+ pass
+
+ while lines[-1] == '':
+ lines = lines[:-1]
+
+ if len(deps) > 0:
+ lines.append('')
+ lines.append('<requires>')
+ for dep in deps:
+ lines.append(dep)
+ lines.append('</requires>')
+ lines.append('')
+
+ lines = "\n".join(lines).replace("\n\n\n", "\n\n")
+
+ output = open(os.path.join(dir, 'info.txt'), 'w')
+ output.write(lines)
+ output.close()
+
+def main():
+ for line in sys.stdin.readlines():
+ (dirname, deps) = line.split(':')
+ deps = deps.strip().split(' ')
+ update_requires(dirname, deps)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/botan/doc/thanks.txt b/botan/doc/thanks.txt
new file mode 100644
index 0000000..caa2fb5
--- /dev/null
+++ b/botan/doc/thanks.txt
@@ -0,0 +1,49 @@
+
+The following people (sorted alphabetically) contributed bug reports, useful
+information, or were generally just helpful people to talk to:
+
+Jeff B
+Rickard Bondesson
+Mike Desjardins
+Matthew Gregan
+Hany Greiss
+Friedemann Kleint
+Ying-Chieh Liao
+Dan Nicolaescu
+Vaclav Ovsik
+Ken Perano
+Darren Starsmore
+Kaushik Veeraraghavan
+Dominik Vogt
+James Widener
+
+Cerulean Studios, creators of the Trillian instant messaging client,
+has provided financial assistance to the project.
+
+Barry Kavanagh of AEP Systems Ltd kindly provided an AEP2000 crypto card and
+drivers, enabling the creation of Botan's AEP engine module.
+
+In addition, the following people have unknowingly contributed help:
+
+ Dean Gaudet <dean@arctic.org> wrote the SSE2 implementation of SHA-1
+
+ The implementation of DES is based off a public domain implementation by Phil
+ Karn from 1994 (he, in turn, credits Richard Outerbridge and Jim Gillogly).
+
+ Rijndael and Square are based on the reference implementations written by
+ the inventors, Joan Daemen and Vincent Rijmen.
+
+ The Serpent S-boxes used were discovered by Dag Arne Osvik and detailed in
+ his paper "Speeding Up Serpent".
+
+ Matthew Skala's public domain twofish.c (as given in GnuPG 0.9.8) provided
+ the basis for my Twofish code (particularly the key schedule).
+
+ Some of the hash functions (MD5, SHA-1, etc) use an optimized implementation
+ of one of the boolean functions, which was discovered by Colin Plumb.
+
+ The design of Randpool takes some of it's design principles from those
+ suggested by Eric A. Young in his SSLeay documentation, Peter Gutmann's paper
+ "Software Generation of Practically Strong Random Numbers", and the paper
+ "Cryptanalytic Attacks on Pseudorandom Number Generators", by Kelsey,
+ Schneier, Wagner, and Hall.
diff --git a/botan/doc/tutorial.pdf b/botan/doc/tutorial.pdf
new file mode 100644
index 0000000..2a68d62
--- /dev/null
+++ b/botan/doc/tutorial.pdf
Binary files differ
diff --git a/botan/doc/tutorial.tex b/botan/doc/tutorial.tex
new file mode 100644
index 0000000..9229cb8
--- /dev/null
+++ b/botan/doc/tutorial.tex
@@ -0,0 +1,883 @@
+\documentclass{article}
+
+\setlength{\textwidth}{6.5in} % 1 inch side margins
+\setlength{\textheight}{9in} % ~1 inch top and bottom margins
+
+\setlength{\headheight}{0in}
+\setlength{\topmargin}{0in}
+\setlength{\headsep}{0in}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+
+\title{\textbf{Botan Tutorial}}
+\author{Jack Lloyd \\
+ \texttt{lloyd@randombit.net}}
+\date{2009/07/08}
+
+\newcommand{\filename}[1]{\texttt{#1}}
+\newcommand{\manpage}[2]{\texttt{#1}(#2)}
+
+\newcommand{\macro}[1]{\texttt{#1}}
+
+\newcommand{\function}[1]{\textbf{#1}}
+\newcommand{\type}[1]{\texttt{#1}}
+\renewcommand{\arg}[1]{\textsl{#1}}
+\newcommand{\variable}[1]{\textsl{#1}}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\parskip=5pt
+\pagebreak
+
+\section{Introduction}
+
+This document essentially sets up various simple scenarios and then
+shows how to solve the problems using Botan. It's fairly simple, and
+doesn't cover many of the available APIs and algorithms, especially
+the more obscure or unusual ones. It is a supplement to the API
+documentation and the example applications, which are included in the
+distribution.
+
+To quote the Perl man page: '``There's more than one way to do it.''
+Divining how many more is left as an exercise to the reader.'
+
+This is \emph{not} a general introduction to cryptography, and most simple
+terms and ideas are not explained in any great detail.
+
+Finally, most of the code shown in this tutorial has not been tested, it was
+just written down from memory. If you find errors, please let me know.
+
+\section{Initializing the Library}
+
+The first step to using Botan is to create a \type{LibraryInitializer} object,
+which handles creating various internal structures, and also destroying them at
+shutdown. Essentially:
+
+\begin{verbatim}
+#include <botan/botan.h>
+/* include other headers here */
+
+int main()
+ {
+ LibraryInitializer init;
+ /* now do stuff */
+ return 0;
+ }
+\end{verbatim}
+
+\section{Hashing a File}
+
+\section{Symmetric Cryptography}
+
+\subsection{Encryption with a passphrase}
+
+Probably the most common crypto problem is encrypting a file (or some data that
+is in-memory) using a passphrase. There are a million ways to do this, most of
+them bad. In particular, you have to protect against weak passphrases,
+people reusing a passphrase many times, accidental and deliberate modification,
+and a dozen other potential problems.
+
+We'll start with a simple method that is commonly used, and show the problems
+that can arise. Each subsequent solution will modify the previous one to
+prevent one or more common problems, until we arrive at a good version.
+
+In these examples, we'll always use Serpent in Cipher-Block Chaining
+(CBC) mode. Whenever we need a hash function, we'll use SHA-256, since
+that is a common and well-known hash that is thought to be secure.
+
+In all examples, we choose to derive the Initialization Vector (IV) from the
+passphrase. Another (probably more common) alternative is to generate the IV
+randomly and include it at the beginning of the message. Either way is
+acceptable, and can be secure. The method used here was chosen to make for more
+interesting examples (because it's harder to get right), and may not be an
+appropriate choice for some environments.
+
+First, some notation. The passphrase is stored as a \type{std::string} named
+\variable{passphrase}. The input and output files (\variable{infile} and
+\variable{outfile}) are of types \type{std::ifstream} and \type{std::ofstream}
+(respectively).
+
+\subsubsection{First try}
+
+We hash the passphrase with SHA-256, and use the resulting hash to key
+Serpent. To generate the IV, we prepend a single '0' character to the
+passphrase, hash it, and truncate it to 16 bytes (which is Serpent's
+block size).
+
+\begin{verbatim}
+ HashFunction* hash = get_hash("SHA-256");
+
+ SymmetricKey key = hash->process(passphrase);
+ SecureVector<byte> raw_iv = hash->process('0' + passphrase);
+ InitializationVector iv(raw_iv, 16);
+
+ Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION));
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+ outfile << pipe;
+\end{verbatim}
+
+\subsubsection{Problem 1: Buffering}
+
+There is a problem with the above code, if the input file is fairly large as
+compared to available memory. Specifically, all the encrypted data is stored
+in memory, and then flushed to \variable{outfile} in a single go at the very
+end. If the input file is big (say, a gigabyte), this will be most problematic.
+
+The solution is to use a \type{DataSink} to handle the output for us (writing
+to \arg{outfile} will be implicit with writing to the \type{Pipe}). We can do
+this by replacing the last few lines with:
+
+\begin{verbatim}
+ Pipe pipe(get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile));
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+\end{verbatim}
+
+\subsubsection{Problem 2: Deriving the key and IV}
+
+Hash functions like SHA-256 are deterministic; if the same passphrase
+is supplied twice, then the key (and in our case, the IV) will be the
+same. This is very dangerous, and could easily open the whole system
+up to attack. What we need to do is introduce a salt (or nonce) into
+the generation of the key from the passphrase. This will mean that the
+key will not be the same each time the same passphrase is typed in by
+a user.
+
+There is another problem with using a bare hash function to derive
+keys. While it's inconceivable (based on our current understanding of
+thermodynamics and theories of computation) that an attacker could
+brute-force a 256-bit key, it would be fairly simple for them to
+compute the SHA-256 hashes of various common passwords ('password',
+the name of the dog, the significant other's middle name, favorite
+sports team) and try those as keys. So we want to slow the attacker
+down if we can, and an easy way to do that is to iterate the hash
+function a bunch of times (say, 1024 to 4096 times). This will involve
+only a small amount of effort for a legitimate user (since they only
+have to compute the hashes once, when they type in their passphrase),
+but an attacker, trying out a large list of potential passphrases,
+will be seriously annoyed (and slowed down) by this.
+
+In this iteration of the example, we'll kill these two birds with one
+stone, and derive the key from the passphrase using a S2K (string to
+key) algorithm (these are also often called PBKDF algorithms, for
+Password-Based Key Derivation Function). In this example, we use
+PBKDF2 with Hash Message Authentication Code (HMAC(SHA-256)), which is
+specified in PKCS \#5. We replace the first four lines of code from
+the first example with:
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ // hard-coded iteration count for simplicity; should be sufficient
+ s2k->set_iterations(4096);
+ // 8 octets == 64-bit salt; again, good enough
+ s2k->new_random_salt(8);
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ // 48 octets == 32 for key + 16 for IV
+ SecureVector<byte> key_and_IV = s2k->derive_key(48, passphrase).bits_of();
+
+ SymmetricKey key(key_and_IV, 32);
+ InitializationVector iv(key_and_IV + 32, 16);
+\end{verbatim}
+
+To complete the example, we have to remember to write out the salt (stored in
+\variable{the\_salt}) at the beginning of the file. The receiving side needs to
+know this value in order to restore it (by calling the \variable{s2k} object's
+\function{change\_salt} function) so it can derive the same key and IV from the
+passphrase.
+
+\subsubsection{Problem 3: Protecting against modification}
+
+As it is, an attacker can undetectably alter the message while it is
+in transit. It is vital to remember that encryption does not imply
+authentication (except when using special modes that are specifically
+designed to provide authentication along with encryption, like OCB and
+EAX). For this purpose, we will append a message authentication code
+to the encrypted message. Specifically, we will generate an extra 256
+bits of key data, and use it to key the ``HMAC(SHA-256)'' MAC
+function. We don't want to have the MAC and the cipher to share the
+same key; that is very much a no-no.
+
+\begin{verbatim}
+ // 80 octets == 32 for cipher key + 16 for IV + 32 for hmac key
+ SecureVector<byte> keys_and_IV = s2k->derive_key(80, passphrase);
+
+ SymmetricKey key(keys_and_IV, 32);
+ InitializationVector iv(keys_and_IV + 32, 16);
+ SymmetricKey mac_key(keys_and_IV + 32 + 16, 32);
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile)
+ ),
+ new MAC_Filter("HMAC(SHA-256)", mac_key)
+ )
+ );
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ // now read the MAC from message #2. Message numbers start from 0
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.ptr(), hmac.size());
+\end{verbatim}
+
+The receiver can check the size of the file (in bytes), and since it knows how
+long the MAC is, can figure out how many bytes of ciphertext there are. Then it
+reads in that many bytes, sending them to a Serpent/CBC decryption object
+(which could be obtained by calling \verb|get_cipher| with an argument of
+\type{DECRYPTION} instead of \type{ENCRYPTION}), and storing the final bytes to
+authenticate the message with.
+
+\subsubsection{Problem 4: Cleaning up the key generation}
+
+The method used to derive the keys and IV is rather inelegant, and it would be
+nice to clean that up a bit, algorithmically speaking. A nice solution for this
+is to generate a master key from the passphrase and salt, and then generate the
+two keys and the IV (the cryptovariables) from that.
+
+Starting from the master key, we derive the cryptovariables using a KDF
+algorithm, which is designed, among other things, to ``separate'' keys so that
+we can derive several different keys from the single master key. For this
+purpose, we will use KDF2, which is a generally useful KDF function (defined in
+IEEE 1363a, among other standards). The use of different labels (``cipher
+key'', etc) makes sure that each of the three derived variables will have
+different values.
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ // hard-coded iteration count for simplicity; should be sufficient
+ s2k->set_iterations(4096);
+ // 8 octet == 64-bit salt; again, good enough
+ s2k->new_random_salt(8);
+ // store the salt so we can write it to a file later
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ SymmetricKey master_key = s2k->derive_key(48, passphrase);
+
+ KDF* kdf = get_kdf("KDF2(SHA-256)");
+
+ SymmetricKey key = kdf->derive_key(32, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(32, master_key, "hmac key");
+ InitializationVector iv = kdf->derive_key(16, master_key, "cipher iv");
+\end{verbatim}
+
+\subsubsection{Final version}
+
+Here is the final version of the encryption code, with all the changes we've
+made:
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ s2k->set_iterations(4096);
+ s2k->new_random_salt(8);
+ SecureVector<byte> the_salt = s2k->current_salt();
+
+ SymmetricKey master_key = s2k->derive_key(48, passphrase);
+
+ KDF* kdf = get_kdf("KDF2(SHA-256)");
+
+ SymmetricKey key = kdf->derive_key(32, master_key, "cipher key");
+ SymmetricKey mac_key = kdf->derive_key(32, masterkey, "hmac key");
+ InitializationVector iv = kdf->derive_key(16, masterkey, "cipher iv");
+
+ Pipe pipe(new Fork(
+ new Chain(
+ get_cipher("Serpent/CBC/PKCS7", key, iv, ENCRYPTION),
+ new DataSink_Stream(outfile)
+ ),
+ new MAC_Filter("HMAC(SHA-256)", mac_key)
+ )
+ );
+
+ outfile.write((const char*)the_salt.ptr(), the_salt.size());
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+
+ SecureVector<byte> hmac = pipe.read_all(1);
+ outfile.write((const char*)hmac.ptr(), hmac.size());
+\end{verbatim}
+
+\subsubsection{Another buffering technique}
+
+Sometimes the use of \type{DataSink\_Stream} is not practical for whatever
+reason. In this case, an alternate buffering mechanism might be useful. Here is
+some code which will write all the processed data as quickly as possible, so
+that memory pressure is reduced in the case of large inputs.
+
+\begin{verbatim}
+ pipe.start_msg();
+ SecureBuffer<byte, 1024> buffer;
+ while(infile.good())
+ {
+ infile.read((char*)buffer.ptr(), buffer.size());
+ u32bit got_from_infile = infile.gcount();
+ pipe.write(buffer, got_from_infile);
+
+ if(infile.eof())
+ pipe.end_msg();
+
+ while(pipe.remaining() > 0)
+ {
+ u32bit buffered = pipe.read(buffer, buffer.size());
+ outfile.write((const char*)buffer.ptr(), buffered);
+ }
+ }
+ if(infile.bad() || (infile.fail() && !infile.eof()))
+ throw Some_Exception();
+\end{verbatim}
+
+\pagebreak
+
+\subsection{Authentication}
+
+After doing the encryption routines, doing message authentication keyed off a
+passphrase is not very difficult. In fact it's much easier than the encryption
+case, for the following reasons: a) we only need one key, and b) we don't have
+to store anything, so all the input can be done in a single step without
+worrying about it taking up a lot of memory if the input file is large.
+
+In this case, we'll hex-encode the salt and the MAC, and output them both to
+standard output (the salt followed by the MAC).
+
+\begin{verbatim}
+ S2K* s2k = get_s2k("PBKDF2(SHA-256)");
+ s2k->set_iterations(4096);
+ s2k->new_random_salt(8);
+ OctetString the_salt = s2k->current_salt();
+
+ SymmetricKey hmac_key = s2k->derive_key(32, passphrase);
+
+ Pipe pipe(new MAC_Filter("HMAC(SHA-256)", mac_key),
+ new Hex_Encoder
+ );
+
+ std::cout << the_salt.to_string(); // hex encoded
+
+ pipe.start_msg();
+ infile >> pipe;
+ pipe.end_msg();
+ std::cout << pipe.read_all_as_string() << std::endl;
+\end{verbatim}
+
+\subsection{User Authentication}
+
+Doing user authentication off a shared passphrase is fairly easy. Essentially,
+a challenge-response protocol is used - the server sends a random challenge,
+and the client responds with an appropriate response to the challenge. The idea
+is that only someone who knows the passphrase can generate or check to see if a
+response is valid.
+
+Let's say we use 160-bit (20 byte) challenges, which seems fairly
+reasonable. We can create this challenge using the global random
+number generator (RNG):
+
+\begin{verbatim}
+ byte challenge[20];
+ Global_RNG::randomize(challenge, sizeof(challenge), Nonce);
+ // send challenge to client
+\end{verbatim}
+
+After reading the challenge, the client generates a response based on
+the challenge and the passphrase. In this case, we will do it by
+repeatedly hashing the challenge, the passphrase, and (if applicable)
+the previous digest. We iterate this construction 4096 times, to make
+brute force attacks on the passphrase hard to do. Since we are already
+using 160-bit challenges, a 160-bit response seems warranted, so we'll
+use SHA-1.
+
+\begin{verbatim}
+ HashFunction* hash = get_hash("SHA-1");
+ SecureVector<byte> digest;
+ for(u32bit j = 0; j != 4096; j++)
+ {
+ hash->update(digest, digest.size());
+ hash->update(passphrase);
+ hash->update(challenge, challenge.size());
+ digest = hash->final();
+ }
+ delete hash;
+ // send value of digest to the server
+\end{verbatim}
+
+Upon receiving the response from the client, the server computes what the
+response should have been based on the challenge it sent out, and the
+passphrase. If the two responses match, the client is authenticated.
+Otherwise, it is not.
+
+An alternate method is to use PBKDF2 again, using the challenge as the salt. In
+this case, the response could (for example) be the hash of the key produced by
+PBKDF2. There is no reason to have an explicit iteration loop, as PBKDF2 is
+designed to prevent dictionary attacks (assuming PBKDF2 is set up for a large
+iteration count internally).
+
+\pagebreak
+
+\section{Public Key Cryptography}
+
+\subsection{Basic Operations}
+
+In this section, we'll assume we have a \type{X509\_PublicKey*} named
+\arg{pubkey}, and, if necessary, a private key type (a
+\type{PKCS8\_PrivateKey*}) named \arg{privkey}. A description of these types,
+how to create them, and related details appears later in this tutorial. In this
+section, we will use various functions that are defined in
+\filename{look\_pk.h} -- you will have to include this header explicitly.
+
+\subsubsection{Encryption}
+
+Basically, pick an encoding method, create a \type{PK\_Encryptor} (with
+\function{get\_pk\_encryptor}()), and use it. But first we have to make sure
+the public key can actually be used for public key encryption. For encryption
+(and decryption), the key could be RSA, ElGamal, or (in future versions) some
+other public key encryption scheme, like Rabin or an elliptic curve scheme.
+
+\begin{verbatim}
+ PK_Encrypting_Key* key = dynamic_cast<PK_Encrypting_Key*>(pubkey);
+ if(!key)
+ error();
+ PK_Encryptor* enc = get_pk_encryptor(*key, "EME1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ // will also accept a SecureVector<byte> as input
+ SecureVector<byte> ciphertext = enc->encrypt(msg, sizeof(msg));
+\end{verbatim}
+
+\subsubsection{Decryption}
+
+This is essentially the same as the encryption operation, but using a private
+key instead. One major difference is that the decryption operation can fail due
+to the fact that the ciphertext was invalid (most common padding schemes, such
+as ``EME1(SHA-256)'', include various pieces of redundancy, which are checked
+after decryption).
+
+\begin{verbatim}
+ PK_Decrypting_Key* key = dynamic_cast<PK_Decrypting_Key*>(privkey);
+ if(!key)
+ error();
+ PK_Decryptor* dec = get_pk_decryptor(*key, "EME1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ SecureVector<byte> plaintext;
+
+ try {
+ // will also accept a SecureVector<byte> as input
+ plaintext = dec->decrypt(msg, sizeof(msg));
+ }
+ catch(Decoding_Error)
+ {
+ /* the ciphertext was invalid */
+ }
+\end{verbatim}
+
+\subsubsection{Signature Generation}
+
+There is one difficulty with signature generation that does not occur with
+encryption or decryption. Specifically, there are various padding methods which
+can be useful for different signature algorithms, and not all are appropriate
+for all signature schemes. The following table breaks down what algorithms
+support which encodings:
+
+\begin{tabular}{|c|c|c|} \hline
+Signature Algorithm & Usable Encoding Methods & Preferred Encoding(s) \\ \hline
+DSA / NR & EMSA1 & EMSA1 \\ \hline
+RSA & EMSA1, EMSA2, EMSA3, EMSA4 & EMSA3, EMSA4 \\ \hline
+Rabin-Williams & EMSA2, EMSA4 & EMSA2, EMSA4 \\ \hline
+\end{tabular}
+
+For new applications, use EMSA4 with both RSA and Rabin-Williams, as it is
+significantly more secure than the alternatives. However, most current
+applications/libraries only support EMSA2 with Rabin-Williams and EMSA3 with
+RSA. Given this, you may be forced to use less secure encoding methods for the
+near future. In these examples, we punt on the problem, and hard-code using
+EMSA1 with SHA-256.
+
+\begin{verbatim}
+ PK_Signing_Key* key = dynamic_cast<PK_Signing_Key*>(privkey);
+ if(!key)
+ error();
+ PK_Signer* signer = get_pk_signer(*key, "EMSA1(SHA-256)");
+
+ byte msg[] = { /* ... */ };
+
+ /*
+ You can also repeatedly call update(const byte[], u32bit), followed
+ by a call to signature(), which will return the final signature of
+ all the data that was passed through update(). sign_message() is
+ just a stub that calls update() once, and returns the value of
+ signature().
+ */
+
+ SecureVector<byte> signature = signer->sign_message(msg, sizeof(msg));
+\end{verbatim}
+
+\pagebreak
+
+\subsubsection{Signature Verification}
+
+In addition to all the problems with choosing the correct padding method,
+there is yet another complication with verifying a signature. Namely, there are
+two varieties of signature algorithms - those providing message recovery (that
+is, the value that was signed can be directly recovered by someone verifying
+the signature), and those without message recovery (the verify operation simply
+returns if the signature was valid, without telling you exactly what was
+signed). This leads to two slightly different implementations of the
+verification operation, which user code has to work with. As you can see
+however, the implementation is still not at all difficult.
+
+\begin{verbatim}
+ PK_Verifier* verifier = 0;
+
+ PK_Verifying_with_MR_Key* key1 =
+ dynamic_cast<PK_Verifying_with_MR_Key*>(pubkey);
+ PK_Verifying_wo_MR_Key* key2 =
+ dynamic_cast<PK_Verifying_wo_MR_Key*>(pubkey);
+
+ if(key1)
+ verifier = get_pk_verifier(*key1, "EMSA1(SHA-256)");
+ else if(key2)
+ verifier = get_pk_verifier(*key2, "EMSA1(SHA-256)");
+ else
+ error();
+
+ byte msg[] = { /* ... */ };
+ byte sig[] = { /* ... */ };
+
+ /*
+ Like PK_Signer, you can also do repeated calls to
+ void update(const byte some_data[], u32bit length)
+ followed by a call to
+ bool check_signature(const byte the_sig[], u32bit length)
+ which will return true (valid signature) or false (bad signature).
+ The function verify_message() is a simple wrapper around update() and
+ check_signature().
+
+ */
+ bool is_valid = verifier->verify_message(msg, sizeof(msg), sig, sizeof(sig));
+\end{verbatim}
+
+\subsubsection{Key Agreement}
+
+WRITEME
+
+\pagebreak
+
+\subsection{Working with Keys}
+
+\subsubsection{Reading Public Keys (X.509 format)}
+
+There are two separate ways to read X.509 public keys. Remember that the X.509
+public keys are simply that: public keys. There is no associated information
+(such as the owner of that key) included with the public key itself. If you
+need that kind of information, you'll need to use X.509 certificates.
+
+However, there are surely times when a simple public key is sufficient. The
+most obvious is when the key is implicitly trusted, for example if access
+and/or modification of it is controlled by something else (like filesystem
+ACLs). In other cases, it is a perfectly reasonable proposition to use them
+over the network as an anonymous key exchange mechanism. This is, admittedly,
+vulnerable to man-in-the-middle attacks, but it's simple enough that it's hard
+to mess up (see, for example, Peter Guttman's paper ``Lessons Learned in
+Implementing and Deploying Crypto Software'' in Usenix '02).
+
+The way to load a key is basically to set up a \type{DataSource} and then call
+\function{X509::load\_key}, which will return a \type{X509\_PublicKey*}. For
+example:
+
+\begin{verbatim}
+ DataSource_Stream somefile("somefile.pem"); // has 3 public keys
+ X509_PublicKey* key1 = X509::load_key(somefile);
+ X509_PublicKey* key2 = X509::load_key(somefile);
+ X509_PublicKey* key3 = X509::load_key(somefile);
+ // Now we have them all loaded. Huzah!
+\end{verbatim}
+
+At this point you can use \function{dynamic\_cast} to find the operations the
+key supports (by seeing if a cast to \type{PK\_Encrypting\_Key},
+\type{PK\_Verifying\_with\_MR\_Key}, or \type{PK\_Verifying\_wo\_MR\_Key}
+succeeds).
+
+There is a variant of \function{X509::load\_key} (and of
+\function{PKCS8::load\_key}, described in the next section) which take a
+filename (as a \type{std::string}). These are just convenience functions which
+create the appropriate \type{DataSource} for you and call the main
+\function{X509::load\_key}.
+
+\subsubsection{Reading Private Keys (PKCS \#8 format)}
+
+This is very similar to reading raw public keys, with the difference that the
+key may be encrypted with a user passphrase:
+
+\begin{verbatim}
+ // rng is a RandomNumberGenerator, like AutoSeeded_RNG
+
+ DataSource_Stream somefile("somefile");
+ std::string a_passphrase = /* get from the user */
+ PKCS8_PrivateKey* key = PKCS8::load_key(somefile, rng, a_passphrase);
+\end{verbatim}
+
+You can, by the way, convert a \type{PKCS8\_PrivateKey} to a
+\type{X509\_PublicKey} simply by casting it (with \function{dynamic\_cast}), as
+the private key type is derived from \type{X509\_PublicKey}. As with
+\type{X509\_PublicKey}, you can use \function{dynamic\_cast} to figure out what
+operations the private key is capable of; in particular, you can attempt to
+cast it to \type{PK\_Decrypting\_Key}, \type{PK\_Signing\_Key}, or
+\type{PK\_Key\_Agreement\_Key}.
+
+Sometimes you can get away with having a static passphrase passed to
+\function{load\_key}. Typically, however, you'll have to do some user
+interaction to get the appropriate passphrase. In that case you'll want to use
+the \type{UI} related interface, which is fully described in the API
+documentation.
+
+\subsubsection{Generating New Private Keys}
+
+Generate a new private key is the one operation which requires you to
+explicitly name the type of key you are working with. There are (currently) two
+kinds of public key algorithms in Botan: ones based on the integer
+factorization (IF) problem (RSA and Rabin-Williams), and ones based on the
+discrete logarithm (DL) problem (DSA, Diffie-Hellman, Nyberg-Rueppel, and
+ElGamal). Since discrete logarithm parameters (primes and generators) can be
+shared among many keys, there is the notion of these being a combined type
+(called \type{DL\_Group}).
+
+To create a new DL-based private key, simply pass a desired \type{DL\_Group} to
+the constructor of the private key - a new public/private key pair will be
+generated. Since in IF-based algorithms, the modulus used isn't shared by other
+keys, we don't use this notion. You can create a new key by passing in a
+\type{u32bit} telling how long (in bits) the key should be.
+
+There are quite a few ways to get a \type{DL\_Group} object. The best is to use
+the function \function{get\_dl\_group}, which takes a string naming a group; it
+will either return that group, if it knows about it, or throw an
+exception. Names it knows about include ``IETF-n'' where n is 768, 1024, 1536,
+2048, 3072, or 4096, and ``DSA-n'', where n is 512, 768, or 1024. The IETF
+groups are the ones specified for use with IPSec, and the DSA ones are the
+default DSA parameters specified by Java's JCE. For DSA and Nyberg-Rueppel, use
+the ``DSA-n'' groups, and for Diffie-Hellman and ElGamal, use the ``IETF-n''
+groups.
+
+You can also generate a new random group. This is not recommend, because it is
+very slow, particularly for ``safe'' primes, which are needed for
+Diffie-Hellman and ElGamal.
+
+Some examples:
+
+\begin{verbatim}
+ RSA_PrivateKey rsa1(512); // 512-bit RSA key
+ RSA_PrivateKey rsa2(2048); // 2048-bit RSA key
+
+ RW_PrivateKey rw1(1024); // 1024-bit Rabin-Williams key
+ RW_PrivateKey rw2(1536); // 1536-bit Rabin-Williams key
+
+ DSA_PrivateKey dsa(get_dl_group("DSA-512")); // 512-bit DSA key
+ DH_PrivateKey dh(get_dl_group("IETF-4096")); // 4096-bit DH key
+ NR_PrivateKey nr(get_dl_group("DSA-1024")); // 1024-bit NR key
+ ElGamal_PrivateKey elg(get_dl_group("IETF-1536")); // 1536-bit ElGamal key
+\end{verbatim}
+
+To export your newly created private key, use the PKCS \#8 routines in
+\filename{pkcs8.h}:
+
+\begin{verbatim}
+ std::string a_passphrase = /* get from the user */
+ std::string the_key = PKCS8::PEM_encode(rsa2, a_passphrase);
+\end{verbatim}
+
+You can read the key back in using \function{PKCS8::load\_key}, described in
+the section ``Reading Private Keys (PKCS \#8 format)'', above. Unfortunately,
+this only works with keys that have an assigned algorithm identifier and
+standardized format. Currently this is only the RSA, DSA, DH, and ElGamal
+algorithms, though RW and NR keys can also be imported and exported by
+assigning them an OID (this can be done either through a configuration file, or
+by calling the function \function{OIDS::add\_oid} in \filename{oids.h}). Be
+aware that the OID and format for ElGamal keys is not exactly standard, but
+there does exist at least one other crypto library which will accept the
+format.
+
+The raw public can be exported using:
+
+\begin{verbatim}
+ std::string the_public_key = X509::PEM_encode(rsa2);
+\end{verbatim}
+
+\pagebreak
+
+\section{X.509v3 Certificates}
+
+Using certificates is rather complicated, so only the very basic mechanisms are
+going to be covered here. The section ``Setting up a CA'' goes into reasonable
+detail about CRLs and certificate requests, but there is a lot that isn't
+covered (else this section would get quite long and complicated).
+
+\subsection{Importing and Exporting Certificates}
+
+Importing and exporting X.509 certificates is easy. Simply call the constructor
+with either a \type{DataSource\&}, or the name of a file:
+
+\begin{verbatim}
+ X509_Certificate cert1("cert1.pem");
+
+ /* This file contains two certificates, concatenated */
+ DataSource_Stream in("certs2_and_3.pem");
+
+ X509_Certificate cert2(in); // read the first cert
+ X509_Certificate cert3(in); // read the second cert
+\end{verbatim}
+
+Exporting the certificate is a simple matter of calling the member function
+\function{PEM\_encode}(), which returns a \type{std::string} containing the
+certificate in PEM encoding.
+
+\begin{verbatim}
+ std::cout << cert3.PEM_encode();
+ some_ostream_object << cert1.PEM_encode();
+ std::string cert2_str = cert2.PEM_encode();
+\end{verbatim}
+
+\subsection{Verifying Certificates}
+
+Verifying a certificate requires that we build up a chain of trust, starting
+from the root (usually a commercial CA), down through some number of
+intermediate CAs, and finally reaching the actual certificate in
+question. Thus, to verify, we actually have to have all those certificates
+on hand (or at the very least, know where we can get the ones we need).
+
+The class which handles both storing certificates, and verifying them, is
+called \type{X509\_Store}. We'll start by assuming that we have all the
+certificates we need, and just want to verify a cert. This is done by calling
+the member function \function{validate\_cert}, which takes the
+\type{X509\_Certificate} in question, and an optional argument of type
+\type{Cert\_Usage} (which is ignored here; read the section in the API doc
+titled ``Verifying Certificates for information). It returns an enum;
+\type{X509\_Code}, which, for most purposes, is either \type{VERIFIED}, or
+something else (which specifies what circumstance caused the certificate to be
+considered invalid). Really, that's it.
+
+Now, how to let \type{X509\_Store} know about all those certificates and CRLs
+we have lying around? The simplest method is to add them directly, using the
+functions \function{add\_cert}, \function{add\_certs},
+\function{add\_trusted\_certs}, and \function{add\_crl}; for details, consult
+the API doc or read the \filename{x509stor.h} header. There is also a much more
+elegant and powerful method: \type{Certificate\_Store}s. A certificate store
+refers to an object that knows how to retrieve certificates from some external
+source (a file, an LDAP directory, a HTTP server, a SQL database, or anything
+else). By calling the function \function{add\_new\_certstore}, you can register
+a new certificate store, which \type{X509\_Store} will use to find certificates
+it needs. Thus, you can get away with only adding whichever root CA cert(s) you
+want to use, letting some online source handle the storage of all intermediate
+X.509 certificates. The API documentation has a more complete discussion of
+\type{Certificate\_Store}.
+
+\subsection{Setting up a CA}
+
+WRITEME
+
+\pagebreak
+
+\section{Special Topics}
+
+This chapter is for subjects that don't really fit into the API documentation
+or into other chapters of the tutorial.
+
+\subsection{GUIs}
+
+There is nothing particularly special about using Botan in a GUI-based
+application. However there are a few tricky spots, as well as a few ways to
+take advantage of an event-based application.
+
+\subsubsection{Initialization}
+
+Generally you will create the \type{LibraryInitializer} somewhere in
+\texttt{main}, before entering the event loop. One problem is that some GUI
+libraries take over \texttt{main} and drop you right into the event loop; the
+question then is how to initialize the library? The simplest way is probably to
+have a static flag that marks if you have already initialized the library or
+not. When you enter the event loop, check to see if this flag has not been set,
+and if so, initialize the library using the function-based initializers. Using
+\type{LibraryInitializer} obviously won't work in this case, since it would be
+destroyed as soon as the current event handler finished. You then deinitialize
+the library whenever your application is signaled to quit.
+
+\subsubsection{Interacting With the Library}
+
+In the simple case, the user will do stuff asynchronously, and then in response
+your code will do things like encrypt a file or whatever, which can all be done
+synchronously, since the data is right there for you. An application doing
+something like this is basically going to look exactly like a command line
+application that uses Botan, the only major difference being that the calls to
+the library are inside event handlers.
+
+Much harder is something like an SSH client, where you're acting as a layer
+between two asynchronous things (the user and the network). This actually isn't
+restricted to GUIs at all (text-mode SSH clients have to deal with most of the
+same problems), but it is probably more common with a GUI app. The following
+discussion is fairly vague, but hopefully somewhat useful.
+
+There are a few facilities in Botan that are primarily designed to be used by
+applications based on an event loop. See the section ``User Interfaces'' in the
+main API doc for details.
+
+\subsubsection{Entropy}
+
+One nice advantage of using a GUI is opening a new method of gathering entropy
+for the library. This is especially handy on Windows, where the available
+sources of entropy are pretty questionable. In many versions,
+\texttt{CryptGenRandom} is really rather poor, and the Toolhelp functions may
+not provide much data on a small system (such as a handheld). For example, in
+GTK+, you can use the following callback to get information about mouse
+movements:
+
+\begin{verbatim}
+static gint add_entropy(GtkWidget* widget, GdkEventMotion* event)
+ {
+ if(event)
+ Global_RNG::add_entropy(event, sizeof(GdkEventMotion));
+ return FALSE;
+ }
+\end{verbatim}
+
+And then register it with your main GTK window (presumably named
+\variable{window}) as follows:
+
+\begin{verbatim}
+gtk_signal_connect(GTK_OBJECT(window), "motion_notify_event",
+ GTK_SIGNAL_FUNC(add_entropy), NULL);
+
+gtk_widget_set_events(window, GDK_POINTER_MOTION_MASK);
+\end{verbatim}
+
+Even though we're catching all mouse movements, and hashing the results into
+the entropy pool, this doesn't use up more than a few percent of even a
+relatively slow desktop CPU. Note that in the case of using X over a network,
+catching all mouse events would cause large amounts of X traffic over the
+network, which might make your application slow, or even unusable (I haven't
+tried it, though).
+
+This could be made nicer if the collection function did something like
+calculating deltas between each run, storing them into a buffer, and then when
+enough of them have been added, hashing them and send them all to the PRNG in
+one shot. This would not only reduce load, but also prevent the PRNG from
+overestimating the amount of entropy it's getting, since its estimates don't
+(can't) take history into account. For example, you could move the mouse back
+and forth one pixel, and the PRNG would think it was getting a full load of
+entropy each time, when actually it was getting (at best) a bit or two.
+
+\end{document}
diff --git a/botan/readme.txt b/botan/readme.txt
new file mode 100644
index 0000000..965de00
--- /dev/null
+++ b/botan/readme.txt
@@ -0,0 +1,44 @@
+Botan 1.8.8 2009-11-03
+
+Botan is a C++ class library for performing a wide variety of
+cryptographic operations.
+
+I consider this release the best version available, and recommend all
+users upgrade from 1.6 or earlier versions as soon as possible. Some
+APIs have changed incompatibly since the 1.6 release series, but most
+applications should work as-is or with only simple modifications.
+
+Botan is under a BSD-like license, the details of which can be found
+in license.txt. More information about the authors and contributors
+can be found in credits.txt and thanks.txt. All of these files are
+included in the doc/ directory of the source distribution.
+
+You can file bugs in Bugzilla, which can be accessed at
+ http://www.randombit.net/bugzilla/
+or by sending a report to the botan-devel mailing list
+ http://lists.randombit.net/mailman/listinfo/botan-devel/
+
+In the doc directory, there should be a set of PDFs, including
+
+building.pdf - build instructions
+api.pdf - the API reference manual
+tutorial.pdf - a set of simple examples and tutorials
+
+A set of example programs can be found in the doc/examples directory.
+
+Some higher level cryptographic protocols are implemented using
+Botan in:
+
+- NetSieben SSH Library (SSHv2)
+ http://www.netsieben.com/products/ssh/
+- Ajisai (SSLv3/TLSv1)
+ http://www.randombit.net/code/ajisai/
+
+Check the project's website at http://botan.randombit.net/ for
+announcements and new releases. If you'll be developing code using
+this library, consider joining the mailing lists to keep up to date
+with changes and new releases.
+
+As always, feel free to contact me with any questions or comments.
+
+-Jack Lloyd (lloyd@randombit.net)
diff --git a/botan/src/Makefile b/botan/src/Makefile
new file mode 100644
index 0000000..648b30a
--- /dev/null
+++ b/botan/src/Makefile
@@ -0,0 +1,1628 @@
+#############################################################################
+# Makefile for building: libBotan_debug.1.0.0.dylib
+# Generated by qmake (2.01a) (Qt 4.7.0) on: Sat Jun 26 13:13:55 2010
+# Project: src.pro
+# Template: lib
+# Command: /opt/Qt/4.7/bin/qmake -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile src.pro
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = gcc
+CXX = g++
+DEFINES = -DIDE_LIBRARY_BASENAME=\"lib\" -DWITH_TESTS -DQT_NO_CAST_TO_ASCII -DQT_TESTLIB_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
+CFLAGS = -pipe -fPIC -ansi -fpermissive -finline-functions -Wno-long-long -g -gdwarf-2 -arch x86_64 -Xarch_x86_64 -mmacosx-version-min=10.5 -fvisibility=hidden -Wall -W -fPIC $(DEFINES)
+CXXFLAGS = -pipe -fPIC -ansi -fpermissive -finline-functions -Wno-long-long -g -gdwarf-2 -arch x86_64 -Xarch_x86_64 -mmacosx-version-min=10.5 -fvisibility=hidden -Wall -W -fPIC $(DEFINES)
+INCPATH = -I/opt/Qt/4.7/mkspecs/macx-g++ -I. -I/opt/Qt/4.7/lib/QtCore.framework/Versions/4/Headers -I/opt/Qt/4.7/include/QtCore -I/opt/Qt/4.7/lib/QtGui.framework/Versions/4/Headers -I/opt/Qt/4.7/include/QtGui -I/opt/Qt/4.7/lib/QtTest.framework/Versions/4/Headers -I/opt/Qt/4.7/include/QtTest -I/opt/Qt/4.7/include -I../../../../libs -I/Users/ebaak/depot/creator-qtest/tools -I. -I../build -I../build/botan -I.moc/debug-shared -F/opt/Qt/4.7/lib
+LINK = g++
+LFLAGS = -headerpad_max_install_names -arch x86_64 -Xarch_x86_64 -mmacosx-version-min=10.5 -single_module -dynamiclib -compatibility_version 1.0 -current_version 1.0.0 -Wl,-install_name,@executable_path/../PlugIns/libBotan_debug.1.dylib
+LIBS = $(SUBLIBS) -F/opt/Qt/4.7/lib -L/opt/Qt/4.7/lib -L/Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns -framework QtTest -L/opt/Qt/4.7/lib -F/opt/Qt/4.7/lib -framework IOKit -framework ApplicationServices -framework Security -framework QtGui -framework QtCore
+AR = ar cq
+RANLIB = ranlib -s
+QMAKE = /opt/Qt/4.7/bin/qmake
+TAR = tar -cf
+COMPRESS = gzip -9f
+COPY = cp -f
+SED = sed
+COPY_FILE = cp -f
+COPY_DIR = cp -f -R
+STRIP =
+INSTALL_FILE = $(COPY_FILE)
+INSTALL_DIR = $(COPY_DIR)
+INSTALL_PROGRAM = $(COPY_FILE)
+DEL_FILE = rm -f
+SYMLINK = ln -f -s
+DEL_DIR = rmdir
+MOVE = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+export MACOSX_DEPLOYMENT_TARGET = 10.4
+
+####### Output directory
+
+OBJECTS_DIR = .obj/debug-shared/
+
+####### Files
+
+SOURCES = algo_factory/algo_factory.cpp \
+ algo_factory/prov_weight.cpp \
+ alloc/mem_pool/mem_pool.cpp \
+ alloc/system_alloc/defalloc.cpp \
+ asn1/alg_id.cpp \
+ asn1/asn1_alt.cpp \
+ asn1/asn1_att.cpp \
+ asn1/asn1_dn.cpp \
+ asn1/asn1_int.cpp \
+ asn1/asn1_oid.cpp \
+ asn1/asn1_str.cpp \
+ asn1/asn1_tm.cpp \
+ asn1/ber_dec.cpp \
+ asn1/der_enc.cpp \
+ benchmark/benchmark.cpp \
+ block/aes/aes.cpp \
+ block/aes/aes_tab.cpp \
+ block/blowfish/blfs_tab.cpp \
+ block/blowfish/blowfish.cpp \
+ block/cast/cast128.cpp \
+ block/cast/cast256.cpp \
+ block/cast/cast_tab.cpp \
+ block/des/des.cpp \
+ block/des/des_tab.cpp \
+ block/des/desx.cpp \
+ block/gost_28147/gost_28147.cpp \
+ block/idea/idea.cpp \
+ block/kasumi/kasumi.cpp \
+ block/lion/lion.cpp \
+ block/lubyrack/lubyrack.cpp \
+ block/mars/mars.cpp \
+ block/mars/mars_tab.cpp \
+ block/misty1/misty1.cpp \
+ block/noekeon/noekeon.cpp \
+ block/rc2/rc2.cpp \
+ block/rc5/rc5.cpp \
+ block/rc6/rc6.cpp \
+ block/safer/safe_tab.cpp \
+ block/safer/safer_sk.cpp \
+ block/seed/seed.cpp \
+ block/seed/seed_tab.cpp \
+ block/serpent/serpent.cpp \
+ block/skipjack/skipjack.cpp \
+ block/square/sqr_tab.cpp \
+ block/square/square.cpp \
+ block/tea/tea.cpp \
+ block/twofish/two_tab.cpp \
+ block/twofish/twofish.cpp \
+ block/xtea/xtea.cpp \
+ cert/x509/certstor.cpp \
+ cert/x509/crl_ent.cpp \
+ cert/x509/pkcs10.cpp \
+ cert/x509/x509_ca.cpp \
+ cert/x509/x509_crl.cpp \
+ cert/x509/x509_ext.cpp \
+ cert/x509/x509_obj.cpp \
+ cert/x509/x509cert.cpp \
+ cert/x509/x509find.cpp \
+ cert/x509/x509opt.cpp \
+ cert/x509/x509self.cpp \
+ cert/x509/x509stor.cpp \
+ checksum/adler32/adler32.cpp \
+ checksum/crc24/crc24.cpp \
+ checksum/crc32/crc32.cpp \
+ cms/cms_algo.cpp \
+ cms/cms_comp.cpp \
+ cms/cms_dalg.cpp \
+ cms/cms_dec.cpp \
+ cms/cms_ealg.cpp \
+ cms/cms_enc.cpp \
+ codec/base64/b64_char.cpp \
+ codec/base64/base64.cpp \
+ codec/hex/hex.cpp \
+ codec/hex/hex_char.cpp \
+ codec/openpgp/openpgp.cpp \
+ codec/pem/pem.cpp \
+ cryptobox/cryptobox.cpp \
+ engine/def_engine/def_mode.cpp \
+ engine/def_engine/def_pk_ops.cpp \
+ engine/def_engine/def_powm.cpp \
+ engine/def_engine/lookup_block.cpp \
+ engine/def_engine/lookup_hash.cpp \
+ engine/def_engine/lookup_mac.cpp \
+ engine/def_engine/lookup_stream.cpp \
+ filters/algo_filt.cpp \
+ filters/basefilt.cpp \
+ filters/buf_filt.cpp \
+ filters/data_snk.cpp \
+ filters/data_src.cpp \
+ filters/filter.cpp \
+ filters/out_buf.cpp \
+ filters/pipe.cpp \
+ filters/pipe_io.cpp \
+ filters/pipe_rw.cpp \
+ filters/secqueue.cpp \
+ hash/fork256/fork256.cpp \
+ hash/gost_3411/gost_3411.cpp \
+ hash/has160/has160.cpp \
+ hash/md2/md2.cpp \
+ hash/md4/md4.cpp \
+ hash/md5/md5.cpp \
+ hash/mdx_hash/mdx_hash.cpp \
+ hash/par_hash/par_hash.cpp \
+ hash/rmd128/rmd128.cpp \
+ hash/rmd160/rmd160.cpp \
+ hash/sha1/sha160.cpp \
+ hash/sha2/sha2_32.cpp \
+ hash/sha2/sha2_64.cpp \
+ hash/skein/skein_512.cpp \
+ hash/tiger/tig_tab.cpp \
+ hash/tiger/tiger.cpp \
+ hash/whirlpool/whrl_tab.cpp \
+ hash/whirlpool/whrlpool.cpp \
+ kdf/kdf.cpp \
+ kdf/kdf1/kdf1.cpp \
+ kdf/kdf2/kdf2.cpp \
+ kdf/mgf1/mgf1.cpp \
+ kdf/ssl_prf/prf_ssl3.cpp \
+ kdf/tls_prf/prf_tls.cpp \
+ kdf/x942_prf/prf_x942.cpp \
+ libstate/get_enc.cpp \
+ libstate/init.cpp \
+ libstate/libstate.cpp \
+ libstate/look_pk.cpp \
+ libstate/lookup.cpp \
+ libstate/oid_lookup/oids.cpp \
+ libstate/pk_engine.cpp \
+ libstate/policy.cpp \
+ libstate/scan_name.cpp \
+ mac/cbc_mac/cbc_mac.cpp \
+ mac/cmac/cmac.cpp \
+ mac/hmac/hmac.cpp \
+ mac/mac.cpp \
+ mac/ssl3mac/ssl3_mac.cpp \
+ mac/x919_mac/x919_mac.cpp \
+ math/bigint/big_code.cpp \
+ math/bigint/big_io.cpp \
+ math/bigint/big_ops2.cpp \
+ math/bigint/big_ops3.cpp \
+ math/bigint/big_rand.cpp \
+ math/bigint/bigint.cpp \
+ math/bigint/divide.cpp \
+ math/bigint/monty_generic/mp_monty.cpp \
+ math/bigint/mp_asm.cpp \
+ math/bigint/mp_comba.cpp \
+ math/bigint/mp_karat.cpp \
+ math/bigint/mp_misc.cpp \
+ math/bigint/mp_shift.cpp \
+ math/bigint/mulop_generic/mp_mulop.cpp \
+ math/numbertheory/blinding.cpp \
+ math/numbertheory/dsa_gen.cpp \
+ math/numbertheory/jacobi.cpp \
+ math/numbertheory/make_prm.cpp \
+ math/numbertheory/mp_numth.cpp \
+ math/numbertheory/numthry.cpp \
+ math/numbertheory/pow_mod.cpp \
+ math/numbertheory/powm_fw.cpp \
+ math/numbertheory/powm_mnt.cpp \
+ math/numbertheory/primes.cpp \
+ math/numbertheory/reducer.cpp \
+ math/numbertheory/ressol.cpp \
+ modes/cbc/cbc.cpp \
+ modes/cfb/cfb.cpp \
+ modes/ctr/ctr.cpp \
+ modes/cts/cts.cpp \
+ modes/eax/eax.cpp \
+ modes/eax/eax_dec.cpp \
+ modes/ecb/ecb.cpp \
+ modes/mode_pad/mode_pad.cpp \
+ modes/modebase.cpp \
+ modes/ofb/ofb.cpp \
+ modes/xts/xts.cpp \
+ mutex/noop_mutex/mux_noop.cpp \
+ pbe/get_pbe.cpp \
+ pbe/pbes1/pbes1.cpp \
+ pbe/pbes2/pbes2.cpp \
+ pk_pad/eme.cpp \
+ pk_pad/eme1/eme1.cpp \
+ pk_pad/eme_pkcs/eme_pkcs.cpp \
+ pk_pad/emsa1/emsa1.cpp \
+ pk_pad/emsa1_bsi/emsa1_bsi.cpp \
+ pk_pad/emsa2/emsa2.cpp \
+ pk_pad/emsa3/emsa3.cpp \
+ pk_pad/emsa4/emsa4.cpp \
+ pk_pad/emsa_raw/emsa_raw.cpp \
+ pk_pad/hash_id/hash_id.cpp \
+ pubkey/dh/dh.cpp \
+ pubkey/dh/dh_core.cpp \
+ pubkey/dl_algo/dl_algo.cpp \
+ pubkey/dl_group/dl_group.cpp \
+ pubkey/dlies/dlies.cpp \
+ pubkey/dsa/dsa.cpp \
+ pubkey/dsa/dsa_core.cpp \
+ pubkey/dsa/dsa_op.cpp \
+ pubkey/elgamal/elg_core.cpp \
+ pubkey/elgamal/elg_op.cpp \
+ pubkey/elgamal/elgamal.cpp \
+ pubkey/if_algo/if_algo.cpp \
+ pubkey/if_algo/if_core.cpp \
+ pubkey/if_algo/if_op.cpp \
+ pubkey/keypair/keypair.cpp \
+ pubkey/nr/nr.cpp \
+ pubkey/nr/nr_core.cpp \
+ pubkey/nr/nr_op.cpp \
+ pubkey/pk_algs.cpp \
+ pubkey/pk_codecs/pkcs8.cpp \
+ pubkey/pk_codecs/x509_key.cpp \
+ pubkey/pk_filts.cpp \
+ pubkey/pk_keys.cpp \
+ pubkey/pubkey.cpp \
+ pubkey/pubkey_enums.cpp \
+ pubkey/rsa/rsa.cpp \
+ pubkey/rw/rw.cpp \
+ rng/auto_rng/auto_rng.cpp \
+ rng/hmac_rng/hmac_rng.cpp \
+ rng/randpool/randpool.cpp \
+ rng/rng.cpp \
+ rng/x931_rng/x931_rng.cpp \
+ s2k/pbkdf1/pbkdf1.cpp \
+ s2k/pbkdf2/pbkdf2.cpp \
+ s2k/pgps2k/pgp_s2k.cpp \
+ s2k/s2k.cpp \
+ selftest/selftest.cpp \
+ stream/arc4/arc4.cpp \
+ stream/salsa20/salsa20.cpp \
+ stream/stream_cipher.cpp \
+ stream/turing/tur_tab.cpp \
+ stream/turing/turing.cpp \
+ stream/wid_wake/wid_wake.cpp \
+ sym_algo/symkey.cpp \
+ timer/timer.cpp \
+ utils/charset.cpp \
+ utils/datastor/datastor.cpp \
+ utils/exceptn.cpp \
+ utils/mlock.cpp \
+ utils/parsing.cpp \
+ utils/ui.cpp \
+ utils/util.cpp \
+ utils/version.cpp \
+ alloc/alloc_mmap/mmap_mem.cpp \
+ cert/cvc/asn1_eac_str.cpp \
+ cert/cvc/asn1_eac_tm.cpp \
+ cert/cvc/cvc_ado.cpp \
+ cert/cvc/cvc_ca.cpp \
+ cert/cvc/cvc_cert.cpp \
+ cert/cvc/cvc_req.cpp \
+ cert/cvc/cvc_self.cpp \
+ cert/cvc/ecdsa_sig.cpp \
+ cert/cvc/signed_obj.cpp \
+ entropy/dev_random/es_dev.cpp \
+ entropy/egd/es_egd.cpp \
+ entropy/proc_walk/es_ftw.cpp \
+ entropy/unix_procs/es_unix.cpp \
+ entropy/unix_procs/unix_cmd.cpp \
+ entropy/unix_procs/unix_src.cpp \
+ filters/fd_unix/fd_unix.cpp \
+ math/gfpmath/curve_gfp.cpp \
+ math/gfpmath/gfp_element.cpp \
+ math/gfpmath/point_gfp.cpp \
+ mutex/pthreads/mux_pthr.cpp \
+ pubkey/ec_dompar/ec_dompar.cpp \
+ pubkey/ecc_key/ecc_key.cpp \
+ pubkey/ecdsa/ecdsa.cpp \
+ pubkey/ecdsa/ecdsa_core.cpp \
+ pubkey/ecdsa/ecdsa_op.cpp \
+ pubkey/eckaeg/eckaeg.cpp \
+ pubkey/eckaeg/eckaeg_core.cpp \
+ pubkey/eckaeg/eckaeg_op.cpp \
+ timer/gettimeofday/tm_unix.cpp
+OBJECTS = .obj/debug-shared/algo_factory.o \
+ .obj/debug-shared/prov_weight.o \
+ .obj/debug-shared/mem_pool.o \
+ .obj/debug-shared/defalloc.o \
+ .obj/debug-shared/alg_id.o \
+ .obj/debug-shared/asn1_alt.o \
+ .obj/debug-shared/asn1_att.o \
+ .obj/debug-shared/asn1_dn.o \
+ .obj/debug-shared/asn1_int.o \
+ .obj/debug-shared/asn1_oid.o \
+ .obj/debug-shared/asn1_str.o \
+ .obj/debug-shared/asn1_tm.o \
+ .obj/debug-shared/ber_dec.o \
+ .obj/debug-shared/der_enc.o \
+ .obj/debug-shared/benchmark.o \
+ .obj/debug-shared/aes.o \
+ .obj/debug-shared/aes_tab.o \
+ .obj/debug-shared/blfs_tab.o \
+ .obj/debug-shared/blowfish.o \
+ .obj/debug-shared/cast128.o \
+ .obj/debug-shared/cast256.o \
+ .obj/debug-shared/cast_tab.o \
+ .obj/debug-shared/des.o \
+ .obj/debug-shared/des_tab.o \
+ .obj/debug-shared/desx.o \
+ .obj/debug-shared/gost_28147.o \
+ .obj/debug-shared/idea.o \
+ .obj/debug-shared/kasumi.o \
+ .obj/debug-shared/lion.o \
+ .obj/debug-shared/lubyrack.o \
+ .obj/debug-shared/mars.o \
+ .obj/debug-shared/mars_tab.o \
+ .obj/debug-shared/misty1.o \
+ .obj/debug-shared/noekeon.o \
+ .obj/debug-shared/rc2.o \
+ .obj/debug-shared/rc5.o \
+ .obj/debug-shared/rc6.o \
+ .obj/debug-shared/safe_tab.o \
+ .obj/debug-shared/safer_sk.o \
+ .obj/debug-shared/seed.o \
+ .obj/debug-shared/seed_tab.o \
+ .obj/debug-shared/serpent.o \
+ .obj/debug-shared/skipjack.o \
+ .obj/debug-shared/sqr_tab.o \
+ .obj/debug-shared/square.o \
+ .obj/debug-shared/tea.o \
+ .obj/debug-shared/two_tab.o \
+ .obj/debug-shared/twofish.o \
+ .obj/debug-shared/xtea.o \
+ .obj/debug-shared/certstor.o \
+ .obj/debug-shared/crl_ent.o \
+ .obj/debug-shared/pkcs10.o \
+ .obj/debug-shared/x509_ca.o \
+ .obj/debug-shared/x509_crl.o \
+ .obj/debug-shared/x509_ext.o \
+ .obj/debug-shared/x509_obj.o \
+ .obj/debug-shared/x509cert.o \
+ .obj/debug-shared/x509find.o \
+ .obj/debug-shared/x509opt.o \
+ .obj/debug-shared/x509self.o \
+ .obj/debug-shared/x509stor.o \
+ .obj/debug-shared/adler32.o \
+ .obj/debug-shared/crc24.o \
+ .obj/debug-shared/crc32.o \
+ .obj/debug-shared/cms_algo.o \
+ .obj/debug-shared/cms_comp.o \
+ .obj/debug-shared/cms_dalg.o \
+ .obj/debug-shared/cms_dec.o \
+ .obj/debug-shared/cms_ealg.o \
+ .obj/debug-shared/cms_enc.o \
+ .obj/debug-shared/b64_char.o \
+ .obj/debug-shared/base64.o \
+ .obj/debug-shared/hex.o \
+ .obj/debug-shared/hex_char.o \
+ .obj/debug-shared/openpgp.o \
+ .obj/debug-shared/pem.o \
+ .obj/debug-shared/cryptobox.o \
+ .obj/debug-shared/def_mode.o \
+ .obj/debug-shared/def_pk_ops.o \
+ .obj/debug-shared/def_powm.o \
+ .obj/debug-shared/lookup_block.o \
+ .obj/debug-shared/lookup_hash.o \
+ .obj/debug-shared/lookup_mac.o \
+ .obj/debug-shared/lookup_stream.o \
+ .obj/debug-shared/algo_filt.o \
+ .obj/debug-shared/basefilt.o \
+ .obj/debug-shared/buf_filt.o \
+ .obj/debug-shared/data_snk.o \
+ .obj/debug-shared/data_src.o \
+ .obj/debug-shared/filter.o \
+ .obj/debug-shared/out_buf.o \
+ .obj/debug-shared/pipe.o \
+ .obj/debug-shared/pipe_io.o \
+ .obj/debug-shared/pipe_rw.o \
+ .obj/debug-shared/secqueue.o \
+ .obj/debug-shared/fork256.o \
+ .obj/debug-shared/gost_3411.o \
+ .obj/debug-shared/has160.o \
+ .obj/debug-shared/md2.o \
+ .obj/debug-shared/md4.o \
+ .obj/debug-shared/md5.o \
+ .obj/debug-shared/mdx_hash.o \
+ .obj/debug-shared/par_hash.o \
+ .obj/debug-shared/rmd128.o \
+ .obj/debug-shared/rmd160.o \
+ .obj/debug-shared/sha160.o \
+ .obj/debug-shared/sha2_32.o \
+ .obj/debug-shared/sha2_64.o \
+ .obj/debug-shared/skein_512.o \
+ .obj/debug-shared/tig_tab.o \
+ .obj/debug-shared/tiger.o \
+ .obj/debug-shared/whrl_tab.o \
+ .obj/debug-shared/whrlpool.o \
+ .obj/debug-shared/kdf.o \
+ .obj/debug-shared/kdf1.o \
+ .obj/debug-shared/kdf2.o \
+ .obj/debug-shared/mgf1.o \
+ .obj/debug-shared/prf_ssl3.o \
+ .obj/debug-shared/prf_tls.o \
+ .obj/debug-shared/prf_x942.o \
+ .obj/debug-shared/get_enc.o \
+ .obj/debug-shared/init.o \
+ .obj/debug-shared/libstate.o \
+ .obj/debug-shared/look_pk.o \
+ .obj/debug-shared/lookup.o \
+ .obj/debug-shared/oids.o \
+ .obj/debug-shared/pk_engine.o \
+ .obj/debug-shared/policy.o \
+ .obj/debug-shared/scan_name.o \
+ .obj/debug-shared/cbc_mac.o \
+ .obj/debug-shared/cmac.o \
+ .obj/debug-shared/hmac.o \
+ .obj/debug-shared/mac.o \
+ .obj/debug-shared/ssl3_mac.o \
+ .obj/debug-shared/x919_mac.o \
+ .obj/debug-shared/big_code.o \
+ .obj/debug-shared/big_io.o \
+ .obj/debug-shared/big_ops2.o \
+ .obj/debug-shared/big_ops3.o \
+ .obj/debug-shared/big_rand.o \
+ .obj/debug-shared/bigint.o \
+ .obj/debug-shared/divide.o \
+ .obj/debug-shared/mp_monty.o \
+ .obj/debug-shared/mp_asm.o \
+ .obj/debug-shared/mp_comba.o \
+ .obj/debug-shared/mp_karat.o \
+ .obj/debug-shared/mp_misc.o \
+ .obj/debug-shared/mp_shift.o \
+ .obj/debug-shared/mp_mulop.o \
+ .obj/debug-shared/blinding.o \
+ .obj/debug-shared/dsa_gen.o \
+ .obj/debug-shared/jacobi.o \
+ .obj/debug-shared/make_prm.o \
+ .obj/debug-shared/mp_numth.o \
+ .obj/debug-shared/numthry.o \
+ .obj/debug-shared/pow_mod.o \
+ .obj/debug-shared/powm_fw.o \
+ .obj/debug-shared/powm_mnt.o \
+ .obj/debug-shared/primes.o \
+ .obj/debug-shared/reducer.o \
+ .obj/debug-shared/ressol.o \
+ .obj/debug-shared/cbc.o \
+ .obj/debug-shared/cfb.o \
+ .obj/debug-shared/ctr.o \
+ .obj/debug-shared/cts.o \
+ .obj/debug-shared/eax.o \
+ .obj/debug-shared/eax_dec.o \
+ .obj/debug-shared/ecb.o \
+ .obj/debug-shared/mode_pad.o \
+ .obj/debug-shared/modebase.o \
+ .obj/debug-shared/ofb.o \
+ .obj/debug-shared/xts.o \
+ .obj/debug-shared/mux_noop.o \
+ .obj/debug-shared/get_pbe.o \
+ .obj/debug-shared/pbes1.o \
+ .obj/debug-shared/pbes2.o \
+ .obj/debug-shared/eme.o \
+ .obj/debug-shared/eme1.o \
+ .obj/debug-shared/eme_pkcs.o \
+ .obj/debug-shared/emsa1.o \
+ .obj/debug-shared/emsa1_bsi.o \
+ .obj/debug-shared/emsa2.o \
+ .obj/debug-shared/emsa3.o \
+ .obj/debug-shared/emsa4.o \
+ .obj/debug-shared/emsa_raw.o \
+ .obj/debug-shared/hash_id.o \
+ .obj/debug-shared/dh.o \
+ .obj/debug-shared/dh_core.o \
+ .obj/debug-shared/dl_algo.o \
+ .obj/debug-shared/dl_group.o \
+ .obj/debug-shared/dlies.o \
+ .obj/debug-shared/dsa.o \
+ .obj/debug-shared/dsa_core.o \
+ .obj/debug-shared/dsa_op.o \
+ .obj/debug-shared/elg_core.o \
+ .obj/debug-shared/elg_op.o \
+ .obj/debug-shared/elgamal.o \
+ .obj/debug-shared/if_algo.o \
+ .obj/debug-shared/if_core.o \
+ .obj/debug-shared/if_op.o \
+ .obj/debug-shared/keypair.o \
+ .obj/debug-shared/nr.o \
+ .obj/debug-shared/nr_core.o \
+ .obj/debug-shared/nr_op.o \
+ .obj/debug-shared/pk_algs.o \
+ .obj/debug-shared/pkcs8.o \
+ .obj/debug-shared/x509_key.o \
+ .obj/debug-shared/pk_filts.o \
+ .obj/debug-shared/pk_keys.o \
+ .obj/debug-shared/pubkey.o \
+ .obj/debug-shared/pubkey_enums.o \
+ .obj/debug-shared/rsa.o \
+ .obj/debug-shared/rw.o \
+ .obj/debug-shared/auto_rng.o \
+ .obj/debug-shared/hmac_rng.o \
+ .obj/debug-shared/randpool.o \
+ .obj/debug-shared/rng.o \
+ .obj/debug-shared/x931_rng.o \
+ .obj/debug-shared/pbkdf1.o \
+ .obj/debug-shared/pbkdf2.o \
+ .obj/debug-shared/pgp_s2k.o \
+ .obj/debug-shared/s2k.o \
+ .obj/debug-shared/selftest.o \
+ .obj/debug-shared/arc4.o \
+ .obj/debug-shared/salsa20.o \
+ .obj/debug-shared/stream_cipher.o \
+ .obj/debug-shared/tur_tab.o \
+ .obj/debug-shared/turing.o \
+ .obj/debug-shared/wid_wake.o \
+ .obj/debug-shared/symkey.o \
+ .obj/debug-shared/timer.o \
+ .obj/debug-shared/charset.o \
+ .obj/debug-shared/datastor.o \
+ .obj/debug-shared/exceptn.o \
+ .obj/debug-shared/mlock.o \
+ .obj/debug-shared/parsing.o \
+ .obj/debug-shared/ui.o \
+ .obj/debug-shared/util.o \
+ .obj/debug-shared/version.o \
+ .obj/debug-shared/mmap_mem.o \
+ .obj/debug-shared/asn1_eac_str.o \
+ .obj/debug-shared/asn1_eac_tm.o \
+ .obj/debug-shared/cvc_ado.o \
+ .obj/debug-shared/cvc_ca.o \
+ .obj/debug-shared/cvc_cert.o \
+ .obj/debug-shared/cvc_req.o \
+ .obj/debug-shared/cvc_self.o \
+ .obj/debug-shared/ecdsa_sig.o \
+ .obj/debug-shared/signed_obj.o \
+ .obj/debug-shared/es_dev.o \
+ .obj/debug-shared/es_egd.o \
+ .obj/debug-shared/es_ftw.o \
+ .obj/debug-shared/es_unix.o \
+ .obj/debug-shared/unix_cmd.o \
+ .obj/debug-shared/unix_src.o \
+ .obj/debug-shared/fd_unix.o \
+ .obj/debug-shared/curve_gfp.o \
+ .obj/debug-shared/gfp_element.o \
+ .obj/debug-shared/point_gfp.o \
+ .obj/debug-shared/mux_pthr.o \
+ .obj/debug-shared/ec_dompar.o \
+ .obj/debug-shared/ecc_key.o \
+ .obj/debug-shared/ecdsa.o \
+ .obj/debug-shared/ecdsa_core.o \
+ .obj/debug-shared/ecdsa_op.o \
+ .obj/debug-shared/eckaeg.o \
+ .obj/debug-shared/eckaeg_core.o \
+ .obj/debug-shared/eckaeg_op.o \
+ .obj/debug-shared/tm_unix.o
+DIST = /opt/Qt/4.7/mkspecs/common/unix.conf \
+ /opt/Qt/4.7/mkspecs/common/mac.conf \
+ /opt/Qt/4.7/mkspecs/common/mac-g++.conf \
+ /opt/Qt/4.7/mkspecs/qconfig.pri \
+ /opt/Qt/4.7/mkspecs/features/qt_functions.prf \
+ /opt/Qt/4.7/mkspecs/features/qt_config.prf \
+ /opt/Qt/4.7/mkspecs/features/exclusive_builds.prf \
+ /opt/Qt/4.7/mkspecs/features/default_pre.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_pre.prf \
+ /Users/ebaak/depot/creator-qtest/qtcreator.pri \
+ ../../../../rpath.pri \
+ ../../../../qtcreatorlibrary.pri \
+ /opt/Qt/4.7/mkspecs/features/mac/dwarf2.prf \
+ /opt/Qt/4.7/mkspecs/features/debug.prf \
+ /opt/Qt/4.7/mkspecs/features/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/x86_64.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/objective_c.prf \
+ /opt/Qt/4.7/mkspecs/features/unix/hide_symbols.prf \
+ /opt/Qt/4.7/mkspecs/features/dll.prf \
+ /opt/Qt/4.7/mkspecs/features/shared.prf \
+ /opt/Qt/4.7/mkspecs/features/warn_on.prf \
+ /opt/Qt/4.7/mkspecs/modules/qt_webkit_version.pri \
+ /opt/Qt/4.7/mkspecs/features/qt.prf \
+ /opt/Qt/4.7/mkspecs/features/unix/thread.prf \
+ /opt/Qt/4.7/mkspecs/features/moc.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/rez.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/sdk.prf \
+ /opt/Qt/4.7/mkspecs/features/resources.prf \
+ /opt/Qt/4.7/mkspecs/features/uic.prf \
+ /opt/Qt/4.7/mkspecs/features/yacc.prf \
+ /opt/Qt/4.7/mkspecs/features/lex.prf \
+ src.pro
+QMAKE_TARGET = Botan_debug
+DESTDIR = /Users/ebaak/depot/creator-qtest/bin/Qt Creator.app/Contents/PlugIns/
+TARGET = libBotan_debug.1.0.0.dylib
+TARGETA = /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/libBotan_debug.a
+TARGETD = libBotan_debug.1.0.0.dylib
+TARGET0 = libBotan_debug.dylib
+TARGET1 = libBotan_debug.1.dylib
+TARGET2 = libBotan_debug.1.0.dylib
+
+####### Custom Compiler Variables
+QMAKE_COMP_QMAKE_OBJECTIVE_CFLAGS = -pipe \
+ -fPIC \
+ -ansi \
+ -fpermissive \
+ -finline-functions \
+ -Wno-long-long \
+ -g \
+ -gdwarf-2 \
+ -arch \
+ x86_64 \
+ -Xarch_x86_64 \
+ -mmacosx-version-min=10.5 \
+ -fvisibility=hidden \
+ -Wall \
+ -W
+
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .o .c .cpp .cc .cxx .C
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
+
+####### Build rules
+
+all: Makefile /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET)
+
+/Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET): $(OBJECTS) $(SUBLIBS) $(OBJCOMP)
+ @$(CHK_DIR_EXISTS) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/ || $(MKDIR) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/
+ -$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2)
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)
+ -ln -s $(TARGET) $(TARGET0)
+ -ln -s $(TARGET) $(TARGET1)
+ -ln -s $(TARGET) $(TARGET2)
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET)
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET0)
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET1)
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/$(TARGET2)
+ -$(MOVE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) /Users/ebaak/depot/creator-qtest/bin/Qt\ Creator.app/Contents/PlugIns/
+
+
+
+staticlib: $(TARGETA)
+
+$(TARGETA): $(OBJECTS) $(OBJCOMP)
+ -$(DEL_FILE) $(TARGETA)
+ $(AR) $(TARGETA) $(OBJECTS)
+ $(RANLIB) $(TARGETA)
+
+Makefile: src.pro /opt/Qt/4.7/mkspecs/macx-g++/qmake.conf /opt/Qt/4.7/mkspecs/common/unix.conf \
+ /opt/Qt/4.7/mkspecs/common/mac.conf \
+ /opt/Qt/4.7/mkspecs/common/mac-g++.conf \
+ /opt/Qt/4.7/mkspecs/qconfig.pri \
+ /opt/Qt/4.7/mkspecs/features/qt_functions.prf \
+ /opt/Qt/4.7/mkspecs/features/qt_config.prf \
+ /opt/Qt/4.7/mkspecs/features/exclusive_builds.prf \
+ /opt/Qt/4.7/mkspecs/features/default_pre.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_pre.prf \
+ /Users/ebaak/depot/creator-qtest/qtcreator.pri \
+ ../../../../rpath.pri \
+ ../../../../qtcreatorlibrary.pri \
+ /opt/Qt/4.7/mkspecs/features/mac/dwarf2.prf \
+ /opt/Qt/4.7/mkspecs/features/debug.prf \
+ /opt/Qt/4.7/mkspecs/features/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/default_post.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/x86_64.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/objective_c.prf \
+ /opt/Qt/4.7/mkspecs/features/unix/hide_symbols.prf \
+ /opt/Qt/4.7/mkspecs/features/dll.prf \
+ /opt/Qt/4.7/mkspecs/features/shared.prf \
+ /opt/Qt/4.7/mkspecs/features/warn_on.prf \
+ /opt/Qt/4.7/mkspecs/modules/qt_webkit_version.pri \
+ /opt/Qt/4.7/mkspecs/features/qt.prf \
+ /opt/Qt/4.7/mkspecs/features/unix/thread.prf \
+ /opt/Qt/4.7/mkspecs/features/moc.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/rez.prf \
+ /opt/Qt/4.7/mkspecs/features/mac/sdk.prf \
+ /opt/Qt/4.7/mkspecs/features/resources.prf \
+ /opt/Qt/4.7/mkspecs/features/uic.prf \
+ /opt/Qt/4.7/mkspecs/features/yacc.prf \
+ /opt/Qt/4.7/mkspecs/features/lex.prf \
+ /opt/Qt/4.7/lib/QtTest.framework/QtTest.prl \
+ /opt/Qt/4.7/lib/QtCore.framework/QtCore.prl \
+ /opt/Qt/4.7/lib/QtGui.framework/QtGui.prl
+ $(QMAKE) -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile src.pro
+/opt/Qt/4.7/mkspecs/common/unix.conf:
+/opt/Qt/4.7/mkspecs/common/mac.conf:
+/opt/Qt/4.7/mkspecs/common/mac-g++.conf:
+/opt/Qt/4.7/mkspecs/qconfig.pri:
+/opt/Qt/4.7/mkspecs/features/qt_functions.prf:
+/opt/Qt/4.7/mkspecs/features/qt_config.prf:
+/opt/Qt/4.7/mkspecs/features/exclusive_builds.prf:
+/opt/Qt/4.7/mkspecs/features/default_pre.prf:
+/opt/Qt/4.7/mkspecs/features/mac/default_pre.prf:
+/Users/ebaak/depot/creator-qtest/qtcreator.pri:
+../../../../rpath.pri:
+../../../../qtcreatorlibrary.pri:
+/opt/Qt/4.7/mkspecs/features/mac/dwarf2.prf:
+/opt/Qt/4.7/mkspecs/features/debug.prf:
+/opt/Qt/4.7/mkspecs/features/default_post.prf:
+/opt/Qt/4.7/mkspecs/features/mac/default_post.prf:
+/opt/Qt/4.7/mkspecs/features/mac/x86_64.prf:
+/opt/Qt/4.7/mkspecs/features/mac/objective_c.prf:
+/opt/Qt/4.7/mkspecs/features/unix/hide_symbols.prf:
+/opt/Qt/4.7/mkspecs/features/dll.prf:
+/opt/Qt/4.7/mkspecs/features/shared.prf:
+/opt/Qt/4.7/mkspecs/features/warn_on.prf:
+/opt/Qt/4.7/mkspecs/modules/qt_webkit_version.pri:
+/opt/Qt/4.7/mkspecs/features/qt.prf:
+/opt/Qt/4.7/mkspecs/features/unix/thread.prf:
+/opt/Qt/4.7/mkspecs/features/moc.prf:
+/opt/Qt/4.7/mkspecs/features/mac/rez.prf:
+/opt/Qt/4.7/mkspecs/features/mac/sdk.prf:
+/opt/Qt/4.7/mkspecs/features/resources.prf:
+/opt/Qt/4.7/mkspecs/features/uic.prf:
+/opt/Qt/4.7/mkspecs/features/yacc.prf:
+/opt/Qt/4.7/mkspecs/features/lex.prf:
+/opt/Qt/4.7/lib/QtTest.framework/QtTest.prl:
+/opt/Qt/4.7/lib/QtCore.framework/QtCore.prl:
+/opt/Qt/4.7/lib/QtGui.framework/QtGui.prl:
+qmake: FORCE
+ @$(QMAKE) -spec /opt/Qt/4.7/mkspecs/macx-g++ -o Makefile src.pro
+
+dist:
+ @$(CHK_DIR_EXISTS) .obj/debug-shared/Botan_debug1.0.0 || $(MKDIR) .obj/debug-shared/Botan_debug1.0.0
+ $(COPY_FILE) --parents $(SOURCES) $(DIST) .obj/debug-shared/Botan_debug1.0.0/ && $(COPY_FILE) --parents algo_factory/algo_cache.h algo_factory/algo_factory.h alloc/allocate.h alloc/mem_pool/mem_pool.h alloc/secmem.h alloc/system_alloc/defalloc.h asn1/alg_id.h asn1/asn1_int.h asn1/asn1_obj.h asn1/asn1_oid.h asn1/ber_dec.h asn1/der_enc.h benchmark/benchmark.h block/aes/aes.h block/block_cipher.h block/blowfish/blowfish.h block/cast/cast128.h block/cast/cast256.h block/des/des.h block/des/desx.h block/gost_28147/gost_28147.h block/idea/idea.h block/kasumi/kasumi.h block/lion/lion.h block/lubyrack/lubyrack.h block/mars/mars.h block/misty1/misty1.h block/noekeon/noekeon.h block/rc2/rc2.h block/rc5/rc5.h block/rc6/rc6.h block/safer/safer_sk.h block/seed/seed.h block/serpent/serpent.h block/skipjack/skipjack.h block/square/square.h block/tea/tea.h block/twofish/twofish.h block/xtea/xtea.h cert/x509/certstor.h cert/x509/crl_ent.h cert/x509/pkcs10.h cert/x509/x509_ca.h cert/x509/x509_crl.h cert/x509/x509_ext.h cert/x509/x509_obj.h cert/x509/x509cert.h cert/x509/x509find.h cert/x509/x509self.h cert/x509/x509stor.h checksum/adler32/adler32.h checksum/crc24/crc24.h checksum/crc32/crc32.h cms/cms_dec.h cms/cms_enc.h codec/base64/base64.h codec/hex/hex.h codec/openpgp/openpgp.h codec/pem/pem.h cryptobox/cryptobox.h engine/def_engine/def_eng.h engine/engine.h entropy/entropy_src.h filters/basefilt.h filters/buf_filt.h filters/data_snk.h filters/data_src.h filters/filter.h filters/filters.h filters/out_buf.h filters/pbe.h filters/pipe.h filters/secqueue.h hash/fork256/fork256.h hash/gost_3411/gost_3411.h hash/has160/has160.h hash/hash.h hash/md2/md2.h hash/md4/md4.h hash/md5/md5.h hash/mdx_hash/mdx_hash.h hash/par_hash/par_hash.h hash/rmd128/rmd128.h hash/rmd160/rmd160.h hash/sha1/sha160.h hash/sha2/sha2_32.h hash/sha2/sha2_64.h hash/skein/skein_512.h hash/tiger/tiger.h hash/whirlpool/whrlpool.h kdf/kdf.h kdf/kdf1/kdf1.h kdf/kdf2/kdf2.h kdf/mgf1/mgf1.h kdf/ssl_prf/prf_ssl3.h kdf/tls_prf/prf_tls.h kdf/x942_prf/prf_x942.h libstate/botan.h libstate/init.h libstate/libstate.h libstate/look_pk.h libstate/lookup.h libstate/oid_lookup/oids.h libstate/pk_engine.h libstate/scan_name.h mac/cbc_mac/cbc_mac.h mac/cmac/cmac.h mac/hmac/hmac.h mac/mac.h mac/ssl3mac/ssl3_mac.h mac/x919_mac/x919_mac.h math/bigint/bigint.h math/bigint/divide.h math/bigint/mp_core.h math/bigint/mp_generic/mp_asm.h math/bigint/mp_generic/mp_asmi.h math/bigint/mp_types.h math/numbertheory/blinding.h math/numbertheory/def_powm.h math/numbertheory/numthry.h math/numbertheory/pow_mod.h math/numbertheory/reducer.h modes/cbc/cbc.h modes/cfb/cfb.h modes/ctr/ctr.h modes/cts/cts.h modes/eax/eax.h modes/ecb/ecb.h modes/mode_pad/mode_pad.h modes/modebase.h modes/ofb/ofb.h modes/xts/xts.h mutex/mutex.h mutex/noop_mutex/mux_noop.h pbe/get_pbe.h pbe/pbes1/pbes1.h pbe/pbes2/pbes2.h pk_pad/eme.h pk_pad/eme1/eme1.h pk_pad/eme_pkcs/eme_pkcs.h pk_pad/emsa.h pk_pad/emsa1/emsa1.h pk_pad/emsa1_bsi/emsa1_bsi.h pk_pad/emsa2/emsa2.h pk_pad/emsa3/emsa3.h pk_pad/emsa4/emsa4.h pk_pad/emsa_raw/emsa_raw.h pk_pad/hash_id/hash_id.h pubkey/dh/dh.h pubkey/dh/dh_core.h pubkey/dh/dh_op.h pubkey/dl_algo/dl_algo.h pubkey/dl_group/dl_group.h pubkey/dlies/dlies.h pubkey/dsa/dsa.h pubkey/dsa/dsa_core.h pubkey/dsa/dsa_op.h pubkey/elgamal/elg_core.h pubkey/elgamal/elg_op.h pubkey/elgamal/elgamal.h pubkey/if_algo/if_algo.h pubkey/if_algo/if_core.h pubkey/if_algo/if_op.h pubkey/keypair/keypair.h pubkey/nr/nr.h pubkey/nr/nr_core.h pubkey/nr/nr_op.h pubkey/pk_algs.h pubkey/pk_codecs/pkcs8.h pubkey/pk_codecs/x509_key.h pubkey/pk_filts.h pubkey/pk_keys.h pubkey/pubkey.h pubkey/pubkey_enums.h pubkey/rsa/rsa.h pubkey/rw/rw.h rng/auto_rng/auto_rng.h rng/hmac_rng/hmac_rng.h rng/randpool/randpool.h rng/rng.h rng/x931_rng/x931_rng.h s2k/pbkdf1/pbkdf1.h s2k/pbkdf2/pbkdf2.h s2k/pgps2k/pgp_s2k.h s2k/s2k.h selftest/selftest.h stream/arc4/arc4.h stream/salsa20/salsa20.h stream/stream_cipher.h stream/turing/turing.h stream/wid_wake/wid_wake.h sym_algo/sym_algo.h sym_algo/symkey.h timer/timer.h utils/bit_ops.h utils/bswap.h utils/buf_comp/buf_comp.h utils/charset.h utils/datastor/datastor.h utils/exceptn.h utils/loadstor.h utils/mem_ops.h utils/parsing.h utils/rotate.h utils/stl_util.h utils/types.h utils/ui.h utils/util.h utils/version.h utils/xor_buf.h alloc/alloc_mmap/mmap_mem.h cert/cvc/cvc_ado.h cert/cvc/cvc_ca.h cert/cvc/cvc_cert.h cert/cvc/cvc_gen_cert.h cert/cvc/cvc_key.h cert/cvc/cvc_req.h cert/cvc/cvc_self.h cert/cvc/eac_asn_obj.h cert/cvc/eac_obj.h cert/cvc/ecdsa_sig.h cert/cvc/freestore.h cert/cvc/signed_obj.h entropy/dev_random/es_dev.h entropy/egd/es_egd.h entropy/proc_walk/es_ftw.h entropy/unix_procs/es_unix.h entropy/unix_procs/unix_cmd.h filters/fd_unix/fd_unix.h math/gfpmath/curve_gfp.h math/gfpmath/gfp_element.h math/gfpmath/gfp_modulus.h math/gfpmath/point_gfp.h mutex/pthreads/mux_pthr.h pubkey/ec_dompar/ec_dompar.h pubkey/ecc_key/ecc_key.h pubkey/ecdsa/ecdsa.h pubkey/ecdsa/ecdsa_core.h pubkey/ecdsa/ecdsa_op.h pubkey/eckaeg/eckaeg.h pubkey/eckaeg/eckaeg_core.h pubkey/eckaeg/eckaeg_op.h timer/gettimeofday/tm_unix.h .obj/debug-shared/Botan_debug1.0.0/ && $(COPY_FILE) --parents algo_factory/algo_factory.cpp algo_factory/prov_weight.cpp alloc/mem_pool/mem_pool.cpp alloc/system_alloc/defalloc.cpp asn1/alg_id.cpp asn1/asn1_alt.cpp asn1/asn1_att.cpp asn1/asn1_dn.cpp asn1/asn1_int.cpp asn1/asn1_oid.cpp asn1/asn1_str.cpp asn1/asn1_tm.cpp asn1/ber_dec.cpp asn1/der_enc.cpp benchmark/benchmark.cpp block/aes/aes.cpp block/aes/aes_tab.cpp block/blowfish/blfs_tab.cpp block/blowfish/blowfish.cpp block/cast/cast128.cpp block/cast/cast256.cpp block/cast/cast_tab.cpp block/des/des.cpp block/des/des_tab.cpp block/des/desx.cpp block/gost_28147/gost_28147.cpp block/idea/idea.cpp block/kasumi/kasumi.cpp block/lion/lion.cpp block/lubyrack/lubyrack.cpp block/mars/mars.cpp block/mars/mars_tab.cpp block/misty1/misty1.cpp block/noekeon/noekeon.cpp block/rc2/rc2.cpp block/rc5/rc5.cpp block/rc6/rc6.cpp block/safer/safe_tab.cpp block/safer/safer_sk.cpp block/seed/seed.cpp block/seed/seed_tab.cpp block/serpent/serpent.cpp block/skipjack/skipjack.cpp block/square/sqr_tab.cpp block/square/square.cpp block/tea/tea.cpp block/twofish/two_tab.cpp block/twofish/twofish.cpp block/xtea/xtea.cpp cert/x509/certstor.cpp cert/x509/crl_ent.cpp cert/x509/pkcs10.cpp cert/x509/x509_ca.cpp cert/x509/x509_crl.cpp cert/x509/x509_ext.cpp cert/x509/x509_obj.cpp cert/x509/x509cert.cpp cert/x509/x509find.cpp cert/x509/x509opt.cpp cert/x509/x509self.cpp cert/x509/x509stor.cpp checksum/adler32/adler32.cpp checksum/crc24/crc24.cpp checksum/crc32/crc32.cpp cms/cms_algo.cpp cms/cms_comp.cpp cms/cms_dalg.cpp cms/cms_dec.cpp cms/cms_ealg.cpp cms/cms_enc.cpp codec/base64/b64_char.cpp codec/base64/base64.cpp codec/hex/hex.cpp codec/hex/hex_char.cpp codec/openpgp/openpgp.cpp codec/pem/pem.cpp cryptobox/cryptobox.cpp engine/def_engine/def_mode.cpp engine/def_engine/def_pk_ops.cpp engine/def_engine/def_powm.cpp engine/def_engine/lookup_block.cpp engine/def_engine/lookup_hash.cpp engine/def_engine/lookup_mac.cpp engine/def_engine/lookup_stream.cpp filters/algo_filt.cpp filters/basefilt.cpp filters/buf_filt.cpp filters/data_snk.cpp filters/data_src.cpp filters/filter.cpp filters/out_buf.cpp filters/pipe.cpp filters/pipe_io.cpp filters/pipe_rw.cpp filters/secqueue.cpp hash/fork256/fork256.cpp hash/gost_3411/gost_3411.cpp hash/has160/has160.cpp hash/md2/md2.cpp hash/md4/md4.cpp hash/md5/md5.cpp hash/mdx_hash/mdx_hash.cpp hash/par_hash/par_hash.cpp hash/rmd128/rmd128.cpp hash/rmd160/rmd160.cpp hash/sha1/sha160.cpp hash/sha2/sha2_32.cpp hash/sha2/sha2_64.cpp hash/skein/skein_512.cpp hash/tiger/tig_tab.cpp hash/tiger/tiger.cpp hash/whirlpool/whrl_tab.cpp hash/whirlpool/whrlpool.cpp kdf/kdf.cpp kdf/kdf1/kdf1.cpp kdf/kdf2/kdf2.cpp kdf/mgf1/mgf1.cpp kdf/ssl_prf/prf_ssl3.cpp kdf/tls_prf/prf_tls.cpp kdf/x942_prf/prf_x942.cpp libstate/get_enc.cpp libstate/init.cpp libstate/libstate.cpp libstate/look_pk.cpp libstate/lookup.cpp libstate/oid_lookup/oids.cpp libstate/pk_engine.cpp libstate/policy.cpp libstate/scan_name.cpp mac/cbc_mac/cbc_mac.cpp mac/cmac/cmac.cpp mac/hmac/hmac.cpp mac/mac.cpp mac/ssl3mac/ssl3_mac.cpp mac/x919_mac/x919_mac.cpp math/bigint/big_code.cpp math/bigint/big_io.cpp math/bigint/big_ops2.cpp math/bigint/big_ops3.cpp math/bigint/big_rand.cpp math/bigint/bigint.cpp math/bigint/divide.cpp math/bigint/monty_generic/mp_monty.cpp math/bigint/mp_asm.cpp math/bigint/mp_comba.cpp math/bigint/mp_karat.cpp math/bigint/mp_misc.cpp math/bigint/mp_shift.cpp math/bigint/mulop_generic/mp_mulop.cpp math/numbertheory/blinding.cpp math/numbertheory/dsa_gen.cpp math/numbertheory/jacobi.cpp math/numbertheory/make_prm.cpp math/numbertheory/mp_numth.cpp math/numbertheory/numthry.cpp math/numbertheory/pow_mod.cpp math/numbertheory/powm_fw.cpp math/numbertheory/powm_mnt.cpp math/numbertheory/primes.cpp math/numbertheory/reducer.cpp math/numbertheory/ressol.cpp modes/cbc/cbc.cpp modes/cfb/cfb.cpp modes/ctr/ctr.cpp modes/cts/cts.cpp modes/eax/eax.cpp modes/eax/eax_dec.cpp modes/ecb/ecb.cpp modes/mode_pad/mode_pad.cpp modes/modebase.cpp modes/ofb/ofb.cpp modes/xts/xts.cpp mutex/noop_mutex/mux_noop.cpp pbe/get_pbe.cpp pbe/pbes1/pbes1.cpp pbe/pbes2/pbes2.cpp pk_pad/eme.cpp pk_pad/eme1/eme1.cpp pk_pad/eme_pkcs/eme_pkcs.cpp pk_pad/emsa1/emsa1.cpp pk_pad/emsa1_bsi/emsa1_bsi.cpp pk_pad/emsa2/emsa2.cpp pk_pad/emsa3/emsa3.cpp pk_pad/emsa4/emsa4.cpp pk_pad/emsa_raw/emsa_raw.cpp pk_pad/hash_id/hash_id.cpp pubkey/dh/dh.cpp pubkey/dh/dh_core.cpp pubkey/dl_algo/dl_algo.cpp pubkey/dl_group/dl_group.cpp pubkey/dlies/dlies.cpp pubkey/dsa/dsa.cpp pubkey/dsa/dsa_core.cpp pubkey/dsa/dsa_op.cpp pubkey/elgamal/elg_core.cpp pubkey/elgamal/elg_op.cpp pubkey/elgamal/elgamal.cpp pubkey/if_algo/if_algo.cpp pubkey/if_algo/if_core.cpp pubkey/if_algo/if_op.cpp pubkey/keypair/keypair.cpp pubkey/nr/nr.cpp pubkey/nr/nr_core.cpp pubkey/nr/nr_op.cpp pubkey/pk_algs.cpp pubkey/pk_codecs/pkcs8.cpp pubkey/pk_codecs/x509_key.cpp pubkey/pk_filts.cpp pubkey/pk_keys.cpp pubkey/pubkey.cpp pubkey/pubkey_enums.cpp pubkey/rsa/rsa.cpp pubkey/rw/rw.cpp rng/auto_rng/auto_rng.cpp rng/hmac_rng/hmac_rng.cpp rng/randpool/randpool.cpp rng/rng.cpp rng/x931_rng/x931_rng.cpp s2k/pbkdf1/pbkdf1.cpp s2k/pbkdf2/pbkdf2.cpp s2k/pgps2k/pgp_s2k.cpp s2k/s2k.cpp selftest/selftest.cpp stream/arc4/arc4.cpp stream/salsa20/salsa20.cpp stream/stream_cipher.cpp stream/turing/tur_tab.cpp stream/turing/turing.cpp stream/wid_wake/wid_wake.cpp sym_algo/symkey.cpp timer/timer.cpp utils/charset.cpp utils/datastor/datastor.cpp utils/exceptn.cpp utils/mlock.cpp utils/parsing.cpp utils/ui.cpp utils/util.cpp utils/version.cpp alloc/alloc_mmap/mmap_mem.cpp cert/cvc/asn1_eac_str.cpp cert/cvc/asn1_eac_tm.cpp cert/cvc/cvc_ado.cpp cert/cvc/cvc_ca.cpp cert/cvc/cvc_cert.cpp cert/cvc/cvc_req.cpp cert/cvc/cvc_self.cpp cert/cvc/ecdsa_sig.cpp cert/cvc/signed_obj.cpp entropy/dev_random/es_dev.cpp entropy/egd/es_egd.cpp entropy/proc_walk/es_ftw.cpp entropy/unix_procs/es_unix.cpp entropy/unix_procs/unix_cmd.cpp entropy/unix_procs/unix_src.cpp filters/fd_unix/fd_unix.cpp math/gfpmath/curve_gfp.cpp math/gfpmath/gfp_element.cpp math/gfpmath/point_gfp.cpp mutex/pthreads/mux_pthr.cpp pubkey/ec_dompar/ec_dompar.cpp pubkey/ecc_key/ecc_key.cpp pubkey/ecdsa/ecdsa.cpp pubkey/ecdsa/ecdsa_core.cpp pubkey/ecdsa/ecdsa_op.cpp pubkey/eckaeg/eckaeg.cpp pubkey/eckaeg/eckaeg_core.cpp pubkey/eckaeg/eckaeg_op.cpp timer/gettimeofday/tm_unix.cpp .obj/debug-shared/Botan_debug1.0.0/ && (cd `dirname .obj/debug-shared/Botan_debug1.0.0` && $(TAR) Botan_debug1.0.0.tar Botan_debug1.0.0 && $(COMPRESS) Botan_debug1.0.0.tar) && $(MOVE) `dirname .obj/debug-shared/Botan_debug1.0.0`/Botan_debug1.0.0.tar.gz . && $(DEL_FILE) -r .obj/debug-shared/Botan_debug1.0.0
+
+
+clean:compiler_clean
+ -$(DEL_FILE) $(OBJECTS)
+ -$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt Creator.app/Contents/PlugIns/$(TARGET)
+ -$(DEL_FILE) /Users/ebaak/depot/creator-qtest/bin/Qt Creator.app/Contents/PlugIns/$(TARGET0) /Users/ebaak/depot/creator-qtest/bin/Qt Creator.app/Contents/PlugIns/$(TARGET1) /Users/ebaak/depot/creator-qtest/bin/Qt Creator.app/Contents/PlugIns/$(TARGET2) $(TARGETA)
+ -$(DEL_FILE) Makefile
+
+
+check: first
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+
+compiler_objective_c_make_all:
+compiler_objective_c_clean:
+compiler_moc_header_make_all:
+compiler_moc_header_clean:
+compiler_rcc_make_all:
+compiler_rcc_clean:
+compiler_image_collection_make_all: qmake_image_collection.cpp
+compiler_image_collection_clean:
+ -$(DEL_FILE) qmake_image_collection.cpp
+compiler_moc_source_make_all:
+compiler_moc_source_clean:
+compiler_rez_source_make_all:
+compiler_rez_source_clean:
+compiler_uic_make_all:
+compiler_uic_clean:
+compiler_yacc_decl_make_all:
+compiler_yacc_decl_clean:
+compiler_yacc_impl_make_all:
+compiler_yacc_impl_clean:
+compiler_lex_make_all:
+compiler_lex_clean:
+compiler_clean:
+
+####### Compile
+
+.obj/debug-shared/algo_factory.o: algo_factory/algo_factory.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/algo_factory.o algo_factory/algo_factory.cpp
+
+.obj/debug-shared/prov_weight.o: algo_factory/prov_weight.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/prov_weight.o algo_factory/prov_weight.cpp
+
+.obj/debug-shared/mem_pool.o: alloc/mem_pool/mem_pool.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mem_pool.o alloc/mem_pool/mem_pool.cpp
+
+.obj/debug-shared/defalloc.o: alloc/system_alloc/defalloc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/defalloc.o alloc/system_alloc/defalloc.cpp
+
+.obj/debug-shared/alg_id.o: asn1/alg_id.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/alg_id.o asn1/alg_id.cpp
+
+.obj/debug-shared/asn1_alt.o: asn1/asn1_alt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_alt.o asn1/asn1_alt.cpp
+
+.obj/debug-shared/asn1_att.o: asn1/asn1_att.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_att.o asn1/asn1_att.cpp
+
+.obj/debug-shared/asn1_dn.o: asn1/asn1_dn.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_dn.o asn1/asn1_dn.cpp
+
+.obj/debug-shared/asn1_int.o: asn1/asn1_int.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_int.o asn1/asn1_int.cpp
+
+.obj/debug-shared/asn1_oid.o: asn1/asn1_oid.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_oid.o asn1/asn1_oid.cpp
+
+.obj/debug-shared/asn1_str.o: asn1/asn1_str.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_str.o asn1/asn1_str.cpp
+
+.obj/debug-shared/asn1_tm.o: asn1/asn1_tm.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_tm.o asn1/asn1_tm.cpp
+
+.obj/debug-shared/ber_dec.o: asn1/ber_dec.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ber_dec.o asn1/ber_dec.cpp
+
+.obj/debug-shared/der_enc.o: asn1/der_enc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/der_enc.o asn1/der_enc.cpp
+
+.obj/debug-shared/benchmark.o: benchmark/benchmark.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/benchmark.o benchmark/benchmark.cpp
+
+.obj/debug-shared/aes.o: block/aes/aes.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/aes.o block/aes/aes.cpp
+
+.obj/debug-shared/aes_tab.o: block/aes/aes_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/aes_tab.o block/aes/aes_tab.cpp
+
+.obj/debug-shared/blfs_tab.o: block/blowfish/blfs_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/blfs_tab.o block/blowfish/blfs_tab.cpp
+
+.obj/debug-shared/blowfish.o: block/blowfish/blowfish.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/blowfish.o block/blowfish/blowfish.cpp
+
+.obj/debug-shared/cast128.o: block/cast/cast128.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cast128.o block/cast/cast128.cpp
+
+.obj/debug-shared/cast256.o: block/cast/cast256.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cast256.o block/cast/cast256.cpp
+
+.obj/debug-shared/cast_tab.o: block/cast/cast_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cast_tab.o block/cast/cast_tab.cpp
+
+.obj/debug-shared/des.o: block/des/des.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/des.o block/des/des.cpp
+
+.obj/debug-shared/des_tab.o: block/des/des_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/des_tab.o block/des/des_tab.cpp
+
+.obj/debug-shared/desx.o: block/des/desx.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/desx.o block/des/desx.cpp
+
+.obj/debug-shared/gost_28147.o: block/gost_28147/gost_28147.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/gost_28147.o block/gost_28147/gost_28147.cpp
+
+.obj/debug-shared/idea.o: block/idea/idea.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/idea.o block/idea/idea.cpp
+
+.obj/debug-shared/kasumi.o: block/kasumi/kasumi.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/kasumi.o block/kasumi/kasumi.cpp
+
+.obj/debug-shared/lion.o: block/lion/lion.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lion.o block/lion/lion.cpp
+
+.obj/debug-shared/lubyrack.o: block/lubyrack/lubyrack.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lubyrack.o block/lubyrack/lubyrack.cpp
+
+.obj/debug-shared/mars.o: block/mars/mars.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mars.o block/mars/mars.cpp
+
+.obj/debug-shared/mars_tab.o: block/mars/mars_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mars_tab.o block/mars/mars_tab.cpp
+
+.obj/debug-shared/misty1.o: block/misty1/misty1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/misty1.o block/misty1/misty1.cpp
+
+.obj/debug-shared/noekeon.o: block/noekeon/noekeon.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/noekeon.o block/noekeon/noekeon.cpp
+
+.obj/debug-shared/rc2.o: block/rc2/rc2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rc2.o block/rc2/rc2.cpp
+
+.obj/debug-shared/rc5.o: block/rc5/rc5.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rc5.o block/rc5/rc5.cpp
+
+.obj/debug-shared/rc6.o: block/rc6/rc6.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rc6.o block/rc6/rc6.cpp
+
+.obj/debug-shared/safe_tab.o: block/safer/safe_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/safe_tab.o block/safer/safe_tab.cpp
+
+.obj/debug-shared/safer_sk.o: block/safer/safer_sk.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/safer_sk.o block/safer/safer_sk.cpp
+
+.obj/debug-shared/seed.o: block/seed/seed.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/seed.o block/seed/seed.cpp
+
+.obj/debug-shared/seed_tab.o: block/seed/seed_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/seed_tab.o block/seed/seed_tab.cpp
+
+.obj/debug-shared/serpent.o: block/serpent/serpent.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/serpent.o block/serpent/serpent.cpp
+
+.obj/debug-shared/skipjack.o: block/skipjack/skipjack.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/skipjack.o block/skipjack/skipjack.cpp
+
+.obj/debug-shared/sqr_tab.o: block/square/sqr_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/sqr_tab.o block/square/sqr_tab.cpp
+
+.obj/debug-shared/square.o: block/square/square.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/square.o block/square/square.cpp
+
+.obj/debug-shared/tea.o: block/tea/tea.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/tea.o block/tea/tea.cpp
+
+.obj/debug-shared/two_tab.o: block/twofish/two_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/two_tab.o block/twofish/two_tab.cpp
+
+.obj/debug-shared/twofish.o: block/twofish/twofish.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/twofish.o block/twofish/twofish.cpp
+
+.obj/debug-shared/xtea.o: block/xtea/xtea.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/xtea.o block/xtea/xtea.cpp
+
+.obj/debug-shared/certstor.o: cert/x509/certstor.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/certstor.o cert/x509/certstor.cpp
+
+.obj/debug-shared/crl_ent.o: cert/x509/crl_ent.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/crl_ent.o cert/x509/crl_ent.cpp
+
+.obj/debug-shared/pkcs10.o: cert/x509/pkcs10.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pkcs10.o cert/x509/pkcs10.cpp
+
+.obj/debug-shared/x509_ca.o: cert/x509/x509_ca.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509_ca.o cert/x509/x509_ca.cpp
+
+.obj/debug-shared/x509_crl.o: cert/x509/x509_crl.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509_crl.o cert/x509/x509_crl.cpp
+
+.obj/debug-shared/x509_ext.o: cert/x509/x509_ext.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509_ext.o cert/x509/x509_ext.cpp
+
+.obj/debug-shared/x509_obj.o: cert/x509/x509_obj.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509_obj.o cert/x509/x509_obj.cpp
+
+.obj/debug-shared/x509cert.o: cert/x509/x509cert.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509cert.o cert/x509/x509cert.cpp
+
+.obj/debug-shared/x509find.o: cert/x509/x509find.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509find.o cert/x509/x509find.cpp
+
+.obj/debug-shared/x509opt.o: cert/x509/x509opt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509opt.o cert/x509/x509opt.cpp
+
+.obj/debug-shared/x509self.o: cert/x509/x509self.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509self.o cert/x509/x509self.cpp
+
+.obj/debug-shared/x509stor.o: cert/x509/x509stor.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509stor.o cert/x509/x509stor.cpp
+
+.obj/debug-shared/adler32.o: checksum/adler32/adler32.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/adler32.o checksum/adler32/adler32.cpp
+
+.obj/debug-shared/crc24.o: checksum/crc24/crc24.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/crc24.o checksum/crc24/crc24.cpp
+
+.obj/debug-shared/crc32.o: checksum/crc32/crc32.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/crc32.o checksum/crc32/crc32.cpp
+
+.obj/debug-shared/cms_algo.o: cms/cms_algo.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_algo.o cms/cms_algo.cpp
+
+.obj/debug-shared/cms_comp.o: cms/cms_comp.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_comp.o cms/cms_comp.cpp
+
+.obj/debug-shared/cms_dalg.o: cms/cms_dalg.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_dalg.o cms/cms_dalg.cpp
+
+.obj/debug-shared/cms_dec.o: cms/cms_dec.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_dec.o cms/cms_dec.cpp
+
+.obj/debug-shared/cms_ealg.o: cms/cms_ealg.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_ealg.o cms/cms_ealg.cpp
+
+.obj/debug-shared/cms_enc.o: cms/cms_enc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cms_enc.o cms/cms_enc.cpp
+
+.obj/debug-shared/b64_char.o: codec/base64/b64_char.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/b64_char.o codec/base64/b64_char.cpp
+
+.obj/debug-shared/base64.o: codec/base64/base64.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/base64.o codec/base64/base64.cpp
+
+.obj/debug-shared/hex.o: codec/hex/hex.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/hex.o codec/hex/hex.cpp
+
+.obj/debug-shared/hex_char.o: codec/hex/hex_char.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/hex_char.o codec/hex/hex_char.cpp
+
+.obj/debug-shared/openpgp.o: codec/openpgp/openpgp.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/openpgp.o codec/openpgp/openpgp.cpp
+
+.obj/debug-shared/pem.o: codec/pem/pem.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pem.o codec/pem/pem.cpp
+
+.obj/debug-shared/cryptobox.o: cryptobox/cryptobox.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cryptobox.o cryptobox/cryptobox.cpp
+
+.obj/debug-shared/def_mode.o: engine/def_engine/def_mode.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/def_mode.o engine/def_engine/def_mode.cpp
+
+.obj/debug-shared/def_pk_ops.o: engine/def_engine/def_pk_ops.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/def_pk_ops.o engine/def_engine/def_pk_ops.cpp
+
+.obj/debug-shared/def_powm.o: engine/def_engine/def_powm.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/def_powm.o engine/def_engine/def_powm.cpp
+
+.obj/debug-shared/lookup_block.o: engine/def_engine/lookup_block.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lookup_block.o engine/def_engine/lookup_block.cpp
+
+.obj/debug-shared/lookup_hash.o: engine/def_engine/lookup_hash.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lookup_hash.o engine/def_engine/lookup_hash.cpp
+
+.obj/debug-shared/lookup_mac.o: engine/def_engine/lookup_mac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lookup_mac.o engine/def_engine/lookup_mac.cpp
+
+.obj/debug-shared/lookup_stream.o: engine/def_engine/lookup_stream.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lookup_stream.o engine/def_engine/lookup_stream.cpp
+
+.obj/debug-shared/algo_filt.o: filters/algo_filt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/algo_filt.o filters/algo_filt.cpp
+
+.obj/debug-shared/basefilt.o: filters/basefilt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/basefilt.o filters/basefilt.cpp
+
+.obj/debug-shared/buf_filt.o: filters/buf_filt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/buf_filt.o filters/buf_filt.cpp
+
+.obj/debug-shared/data_snk.o: filters/data_snk.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/data_snk.o filters/data_snk.cpp
+
+.obj/debug-shared/data_src.o: filters/data_src.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/data_src.o filters/data_src.cpp
+
+.obj/debug-shared/filter.o: filters/filter.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/filter.o filters/filter.cpp
+
+.obj/debug-shared/out_buf.o: filters/out_buf.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/out_buf.o filters/out_buf.cpp
+
+.obj/debug-shared/pipe.o: filters/pipe.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pipe.o filters/pipe.cpp
+
+.obj/debug-shared/pipe_io.o: filters/pipe_io.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pipe_io.o filters/pipe_io.cpp
+
+.obj/debug-shared/pipe_rw.o: filters/pipe_rw.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pipe_rw.o filters/pipe_rw.cpp
+
+.obj/debug-shared/secqueue.o: filters/secqueue.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/secqueue.o filters/secqueue.cpp
+
+.obj/debug-shared/fork256.o: hash/fork256/fork256.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/fork256.o hash/fork256/fork256.cpp
+
+.obj/debug-shared/gost_3411.o: hash/gost_3411/gost_3411.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/gost_3411.o hash/gost_3411/gost_3411.cpp
+
+.obj/debug-shared/has160.o: hash/has160/has160.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/has160.o hash/has160/has160.cpp
+
+.obj/debug-shared/md2.o: hash/md2/md2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/md2.o hash/md2/md2.cpp
+
+.obj/debug-shared/md4.o: hash/md4/md4.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/md4.o hash/md4/md4.cpp
+
+.obj/debug-shared/md5.o: hash/md5/md5.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/md5.o hash/md5/md5.cpp
+
+.obj/debug-shared/mdx_hash.o: hash/mdx_hash/mdx_hash.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mdx_hash.o hash/mdx_hash/mdx_hash.cpp
+
+.obj/debug-shared/par_hash.o: hash/par_hash/par_hash.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/par_hash.o hash/par_hash/par_hash.cpp
+
+.obj/debug-shared/rmd128.o: hash/rmd128/rmd128.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rmd128.o hash/rmd128/rmd128.cpp
+
+.obj/debug-shared/rmd160.o: hash/rmd160/rmd160.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rmd160.o hash/rmd160/rmd160.cpp
+
+.obj/debug-shared/sha160.o: hash/sha1/sha160.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/sha160.o hash/sha1/sha160.cpp
+
+.obj/debug-shared/sha2_32.o: hash/sha2/sha2_32.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/sha2_32.o hash/sha2/sha2_32.cpp
+
+.obj/debug-shared/sha2_64.o: hash/sha2/sha2_64.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/sha2_64.o hash/sha2/sha2_64.cpp
+
+.obj/debug-shared/skein_512.o: hash/skein/skein_512.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/skein_512.o hash/skein/skein_512.cpp
+
+.obj/debug-shared/tig_tab.o: hash/tiger/tig_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/tig_tab.o hash/tiger/tig_tab.cpp
+
+.obj/debug-shared/tiger.o: hash/tiger/tiger.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/tiger.o hash/tiger/tiger.cpp
+
+.obj/debug-shared/whrl_tab.o: hash/whirlpool/whrl_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/whrl_tab.o hash/whirlpool/whrl_tab.cpp
+
+.obj/debug-shared/whrlpool.o: hash/whirlpool/whrlpool.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/whrlpool.o hash/whirlpool/whrlpool.cpp
+
+.obj/debug-shared/kdf.o: kdf/kdf.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/kdf.o kdf/kdf.cpp
+
+.obj/debug-shared/kdf1.o: kdf/kdf1/kdf1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/kdf1.o kdf/kdf1/kdf1.cpp
+
+.obj/debug-shared/kdf2.o: kdf/kdf2/kdf2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/kdf2.o kdf/kdf2/kdf2.cpp
+
+.obj/debug-shared/mgf1.o: kdf/mgf1/mgf1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mgf1.o kdf/mgf1/mgf1.cpp
+
+.obj/debug-shared/prf_ssl3.o: kdf/ssl_prf/prf_ssl3.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/prf_ssl3.o kdf/ssl_prf/prf_ssl3.cpp
+
+.obj/debug-shared/prf_tls.o: kdf/tls_prf/prf_tls.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/prf_tls.o kdf/tls_prf/prf_tls.cpp
+
+.obj/debug-shared/prf_x942.o: kdf/x942_prf/prf_x942.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/prf_x942.o kdf/x942_prf/prf_x942.cpp
+
+.obj/debug-shared/get_enc.o: libstate/get_enc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/get_enc.o libstate/get_enc.cpp
+
+.obj/debug-shared/init.o: libstate/init.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/init.o libstate/init.cpp
+
+.obj/debug-shared/libstate.o: libstate/libstate.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/libstate.o libstate/libstate.cpp
+
+.obj/debug-shared/look_pk.o: libstate/look_pk.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/look_pk.o libstate/look_pk.cpp
+
+.obj/debug-shared/lookup.o: libstate/lookup.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/lookup.o libstate/lookup.cpp
+
+.obj/debug-shared/oids.o: libstate/oid_lookup/oids.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/oids.o libstate/oid_lookup/oids.cpp
+
+.obj/debug-shared/pk_engine.o: libstate/pk_engine.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pk_engine.o libstate/pk_engine.cpp
+
+.obj/debug-shared/policy.o: libstate/policy.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/policy.o libstate/policy.cpp
+
+.obj/debug-shared/scan_name.o: libstate/scan_name.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/scan_name.o libstate/scan_name.cpp
+
+.obj/debug-shared/cbc_mac.o: mac/cbc_mac/cbc_mac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cbc_mac.o mac/cbc_mac/cbc_mac.cpp
+
+.obj/debug-shared/cmac.o: mac/cmac/cmac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cmac.o mac/cmac/cmac.cpp
+
+.obj/debug-shared/hmac.o: mac/hmac/hmac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/hmac.o mac/hmac/hmac.cpp
+
+.obj/debug-shared/mac.o: mac/mac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mac.o mac/mac.cpp
+
+.obj/debug-shared/ssl3_mac.o: mac/ssl3mac/ssl3_mac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ssl3_mac.o mac/ssl3mac/ssl3_mac.cpp
+
+.obj/debug-shared/x919_mac.o: mac/x919_mac/x919_mac.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x919_mac.o mac/x919_mac/x919_mac.cpp
+
+.obj/debug-shared/big_code.o: math/bigint/big_code.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/big_code.o math/bigint/big_code.cpp
+
+.obj/debug-shared/big_io.o: math/bigint/big_io.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/big_io.o math/bigint/big_io.cpp
+
+.obj/debug-shared/big_ops2.o: math/bigint/big_ops2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/big_ops2.o math/bigint/big_ops2.cpp
+
+.obj/debug-shared/big_ops3.o: math/bigint/big_ops3.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/big_ops3.o math/bigint/big_ops3.cpp
+
+.obj/debug-shared/big_rand.o: math/bigint/big_rand.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/big_rand.o math/bigint/big_rand.cpp
+
+.obj/debug-shared/bigint.o: math/bigint/bigint.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/bigint.o math/bigint/bigint.cpp
+
+.obj/debug-shared/divide.o: math/bigint/divide.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/divide.o math/bigint/divide.cpp
+
+.obj/debug-shared/mp_monty.o: math/bigint/monty_generic/mp_monty.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_monty.o math/bigint/monty_generic/mp_monty.cpp
+
+.obj/debug-shared/mp_asm.o: math/bigint/mp_asm.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_asm.o math/bigint/mp_asm.cpp
+
+.obj/debug-shared/mp_comba.o: math/bigint/mp_comba.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_comba.o math/bigint/mp_comba.cpp
+
+.obj/debug-shared/mp_karat.o: math/bigint/mp_karat.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_karat.o math/bigint/mp_karat.cpp
+
+.obj/debug-shared/mp_misc.o: math/bigint/mp_misc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_misc.o math/bigint/mp_misc.cpp
+
+.obj/debug-shared/mp_shift.o: math/bigint/mp_shift.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_shift.o math/bigint/mp_shift.cpp
+
+.obj/debug-shared/mp_mulop.o: math/bigint/mulop_generic/mp_mulop.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_mulop.o math/bigint/mulop_generic/mp_mulop.cpp
+
+.obj/debug-shared/blinding.o: math/numbertheory/blinding.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/blinding.o math/numbertheory/blinding.cpp
+
+.obj/debug-shared/dsa_gen.o: math/numbertheory/dsa_gen.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dsa_gen.o math/numbertheory/dsa_gen.cpp
+
+.obj/debug-shared/jacobi.o: math/numbertheory/jacobi.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/jacobi.o math/numbertheory/jacobi.cpp
+
+.obj/debug-shared/make_prm.o: math/numbertheory/make_prm.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/make_prm.o math/numbertheory/make_prm.cpp
+
+.obj/debug-shared/mp_numth.o: math/numbertheory/mp_numth.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mp_numth.o math/numbertheory/mp_numth.cpp
+
+.obj/debug-shared/numthry.o: math/numbertheory/numthry.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/numthry.o math/numbertheory/numthry.cpp
+
+.obj/debug-shared/pow_mod.o: math/numbertheory/pow_mod.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pow_mod.o math/numbertheory/pow_mod.cpp
+
+.obj/debug-shared/powm_fw.o: math/numbertheory/powm_fw.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/powm_fw.o math/numbertheory/powm_fw.cpp
+
+.obj/debug-shared/powm_mnt.o: math/numbertheory/powm_mnt.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/powm_mnt.o math/numbertheory/powm_mnt.cpp
+
+.obj/debug-shared/primes.o: math/numbertheory/primes.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/primes.o math/numbertheory/primes.cpp
+
+.obj/debug-shared/reducer.o: math/numbertheory/reducer.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/reducer.o math/numbertheory/reducer.cpp
+
+.obj/debug-shared/ressol.o: math/numbertheory/ressol.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ressol.o math/numbertheory/ressol.cpp
+
+.obj/debug-shared/cbc.o: modes/cbc/cbc.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cbc.o modes/cbc/cbc.cpp
+
+.obj/debug-shared/cfb.o: modes/cfb/cfb.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cfb.o modes/cfb/cfb.cpp
+
+.obj/debug-shared/ctr.o: modes/ctr/ctr.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ctr.o modes/ctr/ctr.cpp
+
+.obj/debug-shared/cts.o: modes/cts/cts.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cts.o modes/cts/cts.cpp
+
+.obj/debug-shared/eax.o: modes/eax/eax.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eax.o modes/eax/eax.cpp
+
+.obj/debug-shared/eax_dec.o: modes/eax/eax_dec.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eax_dec.o modes/eax/eax_dec.cpp
+
+.obj/debug-shared/ecb.o: modes/ecb/ecb.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecb.o modes/ecb/ecb.cpp
+
+.obj/debug-shared/mode_pad.o: modes/mode_pad/mode_pad.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mode_pad.o modes/mode_pad/mode_pad.cpp
+
+.obj/debug-shared/modebase.o: modes/modebase.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/modebase.o modes/modebase.cpp
+
+.obj/debug-shared/ofb.o: modes/ofb/ofb.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ofb.o modes/ofb/ofb.cpp
+
+.obj/debug-shared/xts.o: modes/xts/xts.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/xts.o modes/xts/xts.cpp
+
+.obj/debug-shared/mux_noop.o: mutex/noop_mutex/mux_noop.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mux_noop.o mutex/noop_mutex/mux_noop.cpp
+
+.obj/debug-shared/get_pbe.o: pbe/get_pbe.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/get_pbe.o pbe/get_pbe.cpp
+
+.obj/debug-shared/pbes1.o: pbe/pbes1/pbes1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pbes1.o pbe/pbes1/pbes1.cpp
+
+.obj/debug-shared/pbes2.o: pbe/pbes2/pbes2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pbes2.o pbe/pbes2/pbes2.cpp
+
+.obj/debug-shared/eme.o: pk_pad/eme.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eme.o pk_pad/eme.cpp
+
+.obj/debug-shared/eme1.o: pk_pad/eme1/eme1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eme1.o pk_pad/eme1/eme1.cpp
+
+.obj/debug-shared/eme_pkcs.o: pk_pad/eme_pkcs/eme_pkcs.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eme_pkcs.o pk_pad/eme_pkcs/eme_pkcs.cpp
+
+.obj/debug-shared/emsa1.o: pk_pad/emsa1/emsa1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa1.o pk_pad/emsa1/emsa1.cpp
+
+.obj/debug-shared/emsa1_bsi.o: pk_pad/emsa1_bsi/emsa1_bsi.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa1_bsi.o pk_pad/emsa1_bsi/emsa1_bsi.cpp
+
+.obj/debug-shared/emsa2.o: pk_pad/emsa2/emsa2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa2.o pk_pad/emsa2/emsa2.cpp
+
+.obj/debug-shared/emsa3.o: pk_pad/emsa3/emsa3.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa3.o pk_pad/emsa3/emsa3.cpp
+
+.obj/debug-shared/emsa4.o: pk_pad/emsa4/emsa4.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa4.o pk_pad/emsa4/emsa4.cpp
+
+.obj/debug-shared/emsa_raw.o: pk_pad/emsa_raw/emsa_raw.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/emsa_raw.o pk_pad/emsa_raw/emsa_raw.cpp
+
+.obj/debug-shared/hash_id.o: pk_pad/hash_id/hash_id.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/hash_id.o pk_pad/hash_id/hash_id.cpp
+
+.obj/debug-shared/dh.o: pubkey/dh/dh.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dh.o pubkey/dh/dh.cpp
+
+.obj/debug-shared/dh_core.o: pubkey/dh/dh_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dh_core.o pubkey/dh/dh_core.cpp
+
+.obj/debug-shared/dl_algo.o: pubkey/dl_algo/dl_algo.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dl_algo.o pubkey/dl_algo/dl_algo.cpp
+
+.obj/debug-shared/dl_group.o: pubkey/dl_group/dl_group.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dl_group.o pubkey/dl_group/dl_group.cpp
+
+.obj/debug-shared/dlies.o: pubkey/dlies/dlies.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dlies.o pubkey/dlies/dlies.cpp
+
+.obj/debug-shared/dsa.o: pubkey/dsa/dsa.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dsa.o pubkey/dsa/dsa.cpp
+
+.obj/debug-shared/dsa_core.o: pubkey/dsa/dsa_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dsa_core.o pubkey/dsa/dsa_core.cpp
+
+.obj/debug-shared/dsa_op.o: pubkey/dsa/dsa_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/dsa_op.o pubkey/dsa/dsa_op.cpp
+
+.obj/debug-shared/elg_core.o: pubkey/elgamal/elg_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/elg_core.o pubkey/elgamal/elg_core.cpp
+
+.obj/debug-shared/elg_op.o: pubkey/elgamal/elg_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/elg_op.o pubkey/elgamal/elg_op.cpp
+
+.obj/debug-shared/elgamal.o: pubkey/elgamal/elgamal.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/elgamal.o pubkey/elgamal/elgamal.cpp
+
+.obj/debug-shared/if_algo.o: pubkey/if_algo/if_algo.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/if_algo.o pubkey/if_algo/if_algo.cpp
+
+.obj/debug-shared/if_core.o: pubkey/if_algo/if_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/if_core.o pubkey/if_algo/if_core.cpp
+
+.obj/debug-shared/if_op.o: pubkey/if_algo/if_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/if_op.o pubkey/if_algo/if_op.cpp
+
+.obj/debug-shared/keypair.o: pubkey/keypair/keypair.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/keypair.o pubkey/keypair/keypair.cpp
+
+.obj/debug-shared/nr.o: pubkey/nr/nr.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/nr.o pubkey/nr/nr.cpp
+
+.obj/debug-shared/nr_core.o: pubkey/nr/nr_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/nr_core.o pubkey/nr/nr_core.cpp
+
+.obj/debug-shared/nr_op.o: pubkey/nr/nr_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/nr_op.o pubkey/nr/nr_op.cpp
+
+.obj/debug-shared/pk_algs.o: pubkey/pk_algs.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pk_algs.o pubkey/pk_algs.cpp
+
+.obj/debug-shared/pkcs8.o: pubkey/pk_codecs/pkcs8.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pkcs8.o pubkey/pk_codecs/pkcs8.cpp
+
+.obj/debug-shared/x509_key.o: pubkey/pk_codecs/x509_key.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x509_key.o pubkey/pk_codecs/x509_key.cpp
+
+.obj/debug-shared/pk_filts.o: pubkey/pk_filts.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pk_filts.o pubkey/pk_filts.cpp
+
+.obj/debug-shared/pk_keys.o: pubkey/pk_keys.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pk_keys.o pubkey/pk_keys.cpp
+
+.obj/debug-shared/pubkey.o: pubkey/pubkey.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pubkey.o pubkey/pubkey.cpp
+
+.obj/debug-shared/pubkey_enums.o: pubkey/pubkey_enums.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pubkey_enums.o pubkey/pubkey_enums.cpp
+
+.obj/debug-shared/rsa.o: pubkey/rsa/rsa.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rsa.o pubkey/rsa/rsa.cpp
+
+.obj/debug-shared/rw.o: pubkey/rw/rw.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rw.o pubkey/rw/rw.cpp
+
+.obj/debug-shared/auto_rng.o: rng/auto_rng/auto_rng.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/auto_rng.o rng/auto_rng/auto_rng.cpp
+
+.obj/debug-shared/hmac_rng.o: rng/hmac_rng/hmac_rng.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/hmac_rng.o rng/hmac_rng/hmac_rng.cpp
+
+.obj/debug-shared/randpool.o: rng/randpool/randpool.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/randpool.o rng/randpool/randpool.cpp
+
+.obj/debug-shared/rng.o: rng/rng.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/rng.o rng/rng.cpp
+
+.obj/debug-shared/x931_rng.o: rng/x931_rng/x931_rng.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/x931_rng.o rng/x931_rng/x931_rng.cpp
+
+.obj/debug-shared/pbkdf1.o: s2k/pbkdf1/pbkdf1.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pbkdf1.o s2k/pbkdf1/pbkdf1.cpp
+
+.obj/debug-shared/pbkdf2.o: s2k/pbkdf2/pbkdf2.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pbkdf2.o s2k/pbkdf2/pbkdf2.cpp
+
+.obj/debug-shared/pgp_s2k.o: s2k/pgps2k/pgp_s2k.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/pgp_s2k.o s2k/pgps2k/pgp_s2k.cpp
+
+.obj/debug-shared/s2k.o: s2k/s2k.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/s2k.o s2k/s2k.cpp
+
+.obj/debug-shared/selftest.o: selftest/selftest.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/selftest.o selftest/selftest.cpp
+
+.obj/debug-shared/arc4.o: stream/arc4/arc4.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/arc4.o stream/arc4/arc4.cpp
+
+.obj/debug-shared/salsa20.o: stream/salsa20/salsa20.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/salsa20.o stream/salsa20/salsa20.cpp
+
+.obj/debug-shared/stream_cipher.o: stream/stream_cipher.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/stream_cipher.o stream/stream_cipher.cpp
+
+.obj/debug-shared/tur_tab.o: stream/turing/tur_tab.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/tur_tab.o stream/turing/tur_tab.cpp
+
+.obj/debug-shared/turing.o: stream/turing/turing.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/turing.o stream/turing/turing.cpp
+
+.obj/debug-shared/wid_wake.o: stream/wid_wake/wid_wake.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/wid_wake.o stream/wid_wake/wid_wake.cpp
+
+.obj/debug-shared/symkey.o: sym_algo/symkey.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/symkey.o sym_algo/symkey.cpp
+
+.obj/debug-shared/timer.o: timer/timer.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/timer.o timer/timer.cpp
+
+.obj/debug-shared/charset.o: utils/charset.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/charset.o utils/charset.cpp
+
+.obj/debug-shared/datastor.o: utils/datastor/datastor.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/datastor.o utils/datastor/datastor.cpp
+
+.obj/debug-shared/exceptn.o: utils/exceptn.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/exceptn.o utils/exceptn.cpp
+
+.obj/debug-shared/mlock.o: utils/mlock.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mlock.o utils/mlock.cpp
+
+.obj/debug-shared/parsing.o: utils/parsing.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/parsing.o utils/parsing.cpp
+
+.obj/debug-shared/ui.o: utils/ui.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ui.o utils/ui.cpp
+
+.obj/debug-shared/util.o: utils/util.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/util.o utils/util.cpp
+
+.obj/debug-shared/version.o: utils/version.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/version.o utils/version.cpp
+
+.obj/debug-shared/mmap_mem.o: alloc/alloc_mmap/mmap_mem.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mmap_mem.o alloc/alloc_mmap/mmap_mem.cpp
+
+.obj/debug-shared/asn1_eac_str.o: cert/cvc/asn1_eac_str.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_eac_str.o cert/cvc/asn1_eac_str.cpp
+
+.obj/debug-shared/asn1_eac_tm.o: cert/cvc/asn1_eac_tm.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/asn1_eac_tm.o cert/cvc/asn1_eac_tm.cpp
+
+.obj/debug-shared/cvc_ado.o: cert/cvc/cvc_ado.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cvc_ado.o cert/cvc/cvc_ado.cpp
+
+.obj/debug-shared/cvc_ca.o: cert/cvc/cvc_ca.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cvc_ca.o cert/cvc/cvc_ca.cpp
+
+.obj/debug-shared/cvc_cert.o: cert/cvc/cvc_cert.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cvc_cert.o cert/cvc/cvc_cert.cpp
+
+.obj/debug-shared/cvc_req.o: cert/cvc/cvc_req.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cvc_req.o cert/cvc/cvc_req.cpp
+
+.obj/debug-shared/cvc_self.o: cert/cvc/cvc_self.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/cvc_self.o cert/cvc/cvc_self.cpp
+
+.obj/debug-shared/ecdsa_sig.o: cert/cvc/ecdsa_sig.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecdsa_sig.o cert/cvc/ecdsa_sig.cpp
+
+.obj/debug-shared/signed_obj.o: cert/cvc/signed_obj.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/signed_obj.o cert/cvc/signed_obj.cpp
+
+.obj/debug-shared/es_dev.o: entropy/dev_random/es_dev.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/es_dev.o entropy/dev_random/es_dev.cpp
+
+.obj/debug-shared/es_egd.o: entropy/egd/es_egd.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/es_egd.o entropy/egd/es_egd.cpp
+
+.obj/debug-shared/es_ftw.o: entropy/proc_walk/es_ftw.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/es_ftw.o entropy/proc_walk/es_ftw.cpp
+
+.obj/debug-shared/es_unix.o: entropy/unix_procs/es_unix.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/es_unix.o entropy/unix_procs/es_unix.cpp
+
+.obj/debug-shared/unix_cmd.o: entropy/unix_procs/unix_cmd.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/unix_cmd.o entropy/unix_procs/unix_cmd.cpp
+
+.obj/debug-shared/unix_src.o: entropy/unix_procs/unix_src.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/unix_src.o entropy/unix_procs/unix_src.cpp
+
+.obj/debug-shared/fd_unix.o: filters/fd_unix/fd_unix.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/fd_unix.o filters/fd_unix/fd_unix.cpp
+
+.obj/debug-shared/curve_gfp.o: math/gfpmath/curve_gfp.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/curve_gfp.o math/gfpmath/curve_gfp.cpp
+
+.obj/debug-shared/gfp_element.o: math/gfpmath/gfp_element.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/gfp_element.o math/gfpmath/gfp_element.cpp
+
+.obj/debug-shared/point_gfp.o: math/gfpmath/point_gfp.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/point_gfp.o math/gfpmath/point_gfp.cpp
+
+.obj/debug-shared/mux_pthr.o: mutex/pthreads/mux_pthr.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/mux_pthr.o mutex/pthreads/mux_pthr.cpp
+
+.obj/debug-shared/ec_dompar.o: pubkey/ec_dompar/ec_dompar.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ec_dompar.o pubkey/ec_dompar/ec_dompar.cpp
+
+.obj/debug-shared/ecc_key.o: pubkey/ecc_key/ecc_key.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecc_key.o pubkey/ecc_key/ecc_key.cpp
+
+.obj/debug-shared/ecdsa.o: pubkey/ecdsa/ecdsa.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecdsa.o pubkey/ecdsa/ecdsa.cpp
+
+.obj/debug-shared/ecdsa_core.o: pubkey/ecdsa/ecdsa_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecdsa_core.o pubkey/ecdsa/ecdsa_core.cpp
+
+.obj/debug-shared/ecdsa_op.o: pubkey/ecdsa/ecdsa_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/ecdsa_op.o pubkey/ecdsa/ecdsa_op.cpp
+
+.obj/debug-shared/eckaeg.o: pubkey/eckaeg/eckaeg.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eckaeg.o pubkey/eckaeg/eckaeg.cpp
+
+.obj/debug-shared/eckaeg_core.o: pubkey/eckaeg/eckaeg_core.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eckaeg_core.o pubkey/eckaeg/eckaeg_core.cpp
+
+.obj/debug-shared/eckaeg_op.o: pubkey/eckaeg/eckaeg_op.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/eckaeg_op.o pubkey/eckaeg/eckaeg_op.cpp
+
+.obj/debug-shared/tm_unix.o: timer/gettimeofday/tm_unix.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/debug-shared/tm_unix.o timer/gettimeofday/tm_unix.cpp
+
+####### Install
+
+install: FORCE
+
+uninstall: FORCE
+
+FORCE:
+
diff --git a/botan/src/algo_factory/algo_cache.h b/botan/src/algo_factory/algo_cache.h
new file mode 100644
index 0000000..17ea996
--- /dev/null
+++ b/botan/src/algo_factory/algo_cache.h
@@ -0,0 +1,224 @@
+/**
+* An algorithm cache (used by Algorithm_Factory)
+*/
+
+#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
+#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
+
+#include <botan/mutex.h>
+#include <botan/stl_util.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* @param prov_name a provider name
+* @return weight for this provider
+*/
+u32bit static_provider_weight(const std::string& prov_name);
+
+/**
+* Algorithm_Cache (used by Algorithm_Factory)
+*/
+template<typename T>
+class Algorithm_Cache
+ {
+ public:
+ const T* get(const std::string& algo_spec,
+ const std::string& pref_provider);
+
+ /**
+ * Add a new algorithm implementation to the cache
+ */
+ void add(T* algo,
+ const std::string& requested_name,
+ const std::string& provider_name);
+
+ /**
+ * Set the preferred provider
+ */
+ void set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider);
+
+ /**
+ * Return the list of providers of this algorithm
+ */
+ std::vector<std::string> providers_of(const std::string& algo_name);
+
+ Algorithm_Cache(Mutex* m) : mutex(m) {}
+ ~Algorithm_Cache();
+ private:
+ typedef typename std::map<std::string, std::map<std::string, T*> >::iterator
+ algorithms_iterator;
+
+ typedef typename std::map<std::string, T*>::iterator provider_iterator;
+
+ algorithms_iterator find_algorithm(const std::string& algo_spec);
+
+ Mutex* mutex;
+ std::map<std::string, std::string> aliases;
+ std::map<std::string, std::string> pref_providers;
+ std::map<std::string, std::map<std::string, T*> > algorithms;
+ };
+
+/**
+* Look for an algorithm implementation in the cache, also checking aliases
+* Assumes object lock is held
+*/
+template<typename T>
+typename Algorithm_Cache<T>::algorithms_iterator
+Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
+ {
+ algorithms_iterator algo = algorithms.find(algo_spec);
+
+ // Not found? Check if a known alias
+ if(algo == algorithms.end())
+ {
+ std::map<std::string, std::string>::const_iterator alias =
+ aliases.find(algo_spec);
+
+ if(alias != aliases.end())
+ algo = algorithms.find(alias->second);
+ }
+
+ return algo;
+ }
+
+/**
+* Look for an algorithm implementation by a particular provider
+*/
+template<typename T>
+const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
+ const std::string& requested_provider)
+ {
+ Mutex_Holder lock(mutex);
+
+ algorithms_iterator algo = find_algorithm(algo_spec);
+ if(algo == algorithms.end()) // algo not found at all (no providers)
+ return 0;
+
+ // If a provider is requested specifically, return it or fail entirely
+ if(requested_provider != "")
+ {
+ provider_iterator prov = algo->second.find(requested_provider);
+ if(prov != algo->second.end())
+ return prov->second;
+ return 0;
+ }
+
+ const T* prototype = 0;
+ std::string prototype_provider;
+ u32bit prototype_prov_weight = 0;
+
+ const std::string pref_provider = search_map(pref_providers, algo_spec);
+
+ for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
+ {
+ const std::string prov_name = i->first;
+ const u32bit prov_weight = static_provider_weight(prov_name);
+
+ // preferred prov exists, return immediately
+ if(prov_name == pref_provider)
+ return i->second;
+
+ if(prototype == 0 || prov_weight > prototype_prov_weight)
+ {
+ prototype = i->second;
+ prototype_provider = i->first;
+ prototype_prov_weight = prov_weight;
+ }
+ }
+
+ return prototype;
+ }
+
+/**
+* Add an implementation to the cache
+*/
+template<typename T>
+void Algorithm_Cache<T>::add(T* algo,
+ const std::string& requested_name,
+ const std::string& provider)
+ {
+ if(!algo)
+ return;
+
+ Mutex_Holder lock(mutex);
+
+ delete algorithms[algo->name()][provider];
+ algorithms[algo->name()][provider] = algo;
+
+ if(algo->name() != requested_name &&
+ aliases.find(requested_name) == aliases.end())
+ {
+ aliases[requested_name] = algo->name();
+ }
+ }
+
+/**
+* Find the providers of this algo (if any)
+*/
+template<typename T> std::vector<std::string>
+Algorithm_Cache<T>::providers_of(const std::string& algo_name)
+ {
+ Mutex_Holder lock(mutex);
+
+ std::vector<std::string> providers;
+
+ algorithms_iterator algo = find_algorithm(algo_name);
+
+ if(algo != algorithms.end())
+ {
+ provider_iterator provider = algo->second.begin();
+
+ while(provider != algo->second.end())
+ {
+ providers.push_back(provider->first);
+ ++provider;
+ }
+ }
+
+ return providers;
+ }
+
+/**
+* Set the preferred provider for an algorithm
+*/
+template<typename T>
+void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ Mutex_Holder lock(mutex);
+
+ pref_providers[algo_spec] = provider;
+ }
+
+/**
+* Algorithm_Cache<T> Destructor
+*/
+template<typename T>
+Algorithm_Cache<T>::~Algorithm_Cache()
+ {
+ algorithms_iterator algo = algorithms.begin();
+
+ while(algo != algorithms.end())
+ {
+ provider_iterator provider = algo->second.begin();
+
+ while(provider != algo->second.end())
+ {
+ delete provider->second;
+ ++provider;
+ }
+
+ ++algo;
+ }
+
+ delete mutex;
+ }
+
+}
+
+#endif
diff --git a/botan/src/algo_factory/algo_factory.cpp b/botan/src/algo_factory/algo_factory.cpp
new file mode 100644
index 0000000..269c58c
--- /dev/null
+++ b/botan/src/algo_factory/algo_factory.cpp
@@ -0,0 +1,286 @@
+/*
+Algorithm Factory
+(C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/algo_factory.h>
+#include <botan/algo_cache.h>
+#include <botan/stl_util.h>
+#include <botan/engine.h>
+#include <botan/exceptn.h>
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/**
+* Template functions for the factory prototype/search algorithm
+*/
+template<typename T>
+T* engine_get_algo(Engine* engine, const SCAN_Name& request,
+ Algorithm_Factory& af)
+ { return 0; }
+
+template<>
+BlockCipher* engine_get_algo(Engine* engine, const SCAN_Name& request,
+ Algorithm_Factory& af)
+ { return engine->find_block_cipher(request, af); }
+
+template<>
+StreamCipher* engine_get_algo(Engine* engine, const SCAN_Name& request,
+ Algorithm_Factory& af)
+ { return engine->find_stream_cipher(request, af); }
+
+template<>
+HashFunction* engine_get_algo(Engine* engine, const SCAN_Name& request,
+ Algorithm_Factory& af)
+ { return engine->find_hash(request, af); }
+
+template<>
+MessageAuthenticationCode* engine_get_algo(Engine* engine,
+ const SCAN_Name& request,
+ Algorithm_Factory& af)
+ { return engine->find_mac(request, af); }
+
+template<typename T>
+const T* factory_prototype(const std::string& algo_spec,
+ const std::string& provider,
+ const std::vector<Engine*>& engines,
+ Algorithm_Factory& af,
+ Algorithm_Cache<T>* cache)
+ {
+ if(const T* cache_hit = cache->get(algo_spec, provider))
+ return cache_hit;
+
+ SCAN_Name scan_name(algo_spec);
+ for(u32bit i = 0; i != engines.size(); ++i)
+ {
+ if(provider == "" || engines[i]->provider_name() == provider)
+ {
+ T* impl = engine_get_algo<T>(engines[i], scan_name, af);
+ if(impl)
+ cache->add(impl, algo_spec, engines[i]->provider_name());
+ }
+ }
+
+ return cache->get(algo_spec, provider);
+ }
+
+}
+
+/**
+* Setup caches
+*/
+Algorithm_Factory::Algorithm_Factory(const std::vector<Engine*>& engines_in,
+ Mutex_Factory& mf)
+ {
+ engines = engines_in;
+
+ block_cipher_cache = new Algorithm_Cache<BlockCipher>(mf.make());
+ stream_cipher_cache = new Algorithm_Cache<StreamCipher>(mf.make());
+ hash_cache = new Algorithm_Cache<HashFunction>(mf.make());
+ mac_cache = new Algorithm_Cache<MessageAuthenticationCode>(mf.make());
+ }
+
+/**
+* Delete all engines
+*/
+Algorithm_Factory::~Algorithm_Factory()
+ {
+ std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
+
+ delete block_cipher_cache;
+ delete stream_cipher_cache;
+ delete hash_cache;
+ delete mac_cache;
+ }
+
+/**
+* Set the preferred provider for an algorithm
+*/
+void Algorithm_Factory::set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ if(prototype_block_cipher(algo_spec))
+ block_cipher_cache->set_preferred_provider(algo_spec, provider);
+ else if(prototype_stream_cipher(algo_spec))
+ stream_cipher_cache->set_preferred_provider(algo_spec, provider);
+ else if(prototype_hash_function(algo_spec))
+ hash_cache->set_preferred_provider(algo_spec, provider);
+ else if(prototype_mac(algo_spec))
+ mac_cache->set_preferred_provider(algo_spec, provider);
+ }
+
+/**
+* Get an engine out of the list
+*/
+Engine* Algorithm_Factory::get_engine_n(u32bit n) const
+ {
+ if(n >= engines.size())
+ return 0;
+ return engines[n];
+ }
+
+/**
+* Return the possible providers of a request
+* Note: assumes you don't have different types by the same name
+*/
+std::vector<std::string>
+Algorithm_Factory::providers_of(const std::string& algo_spec)
+ {
+ /* The checks with if(prototype_X(algo_spec)) have the effect of
+ forcing a full search, since otherwise there might not be any
+ providers at all in the cache.
+ */
+
+ if(prototype_block_cipher(algo_spec))
+ return block_cipher_cache->providers_of(algo_spec);
+ else if(prototype_stream_cipher(algo_spec))
+ return stream_cipher_cache->providers_of(algo_spec);
+ else if(prototype_hash_function(algo_spec))
+ return hash_cache->providers_of(algo_spec);
+ else if(prototype_mac(algo_spec))
+ return mac_cache->providers_of(algo_spec);
+ else
+ return std::vector<std::string>();
+ }
+
+/**
+* Return the prototypical block cipher corresponding to this request
+*/
+const BlockCipher*
+Algorithm_Factory::prototype_block_cipher(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ return factory_prototype<BlockCipher>(algo_spec, provider, engines,
+ *this, block_cipher_cache);
+ }
+
+/**
+* Return the prototypical stream cipher corresponding to this request
+*/
+const StreamCipher*
+Algorithm_Factory::prototype_stream_cipher(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ return factory_prototype<StreamCipher>(algo_spec, provider, engines,
+ *this, stream_cipher_cache);
+ }
+
+/**
+* Return the prototypical object corresponding to this request (if found)
+*/
+const HashFunction*
+Algorithm_Factory::prototype_hash_function(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ return factory_prototype<HashFunction>(algo_spec, provider, engines,
+ *this, hash_cache);
+ }
+
+/**
+* Return the prototypical object corresponding to this request
+*/
+const MessageAuthenticationCode*
+Algorithm_Factory::prototype_mac(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ return factory_prototype<MessageAuthenticationCode>(algo_spec, provider,
+ engines,
+ *this, mac_cache);
+ }
+
+/**
+* Return a new block cipher corresponding to this request
+*/
+BlockCipher*
+Algorithm_Factory::make_block_cipher(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ if(const BlockCipher* proto = prototype_block_cipher(algo_spec, provider))
+ return proto->clone();
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/**
+* Return a new stream cipher corresponding to this request
+*/
+StreamCipher*
+Algorithm_Factory::make_stream_cipher(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ if(const StreamCipher* proto = prototype_stream_cipher(algo_spec, provider))
+ return proto->clone();
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/**
+* Return a new object corresponding to this request
+*/
+HashFunction*
+Algorithm_Factory::make_hash_function(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ if(const HashFunction* proto = prototype_hash_function(algo_spec, provider))
+ return proto->clone();
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/**
+* Return a new object corresponding to this request
+*/
+MessageAuthenticationCode*
+Algorithm_Factory::make_mac(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ if(const MessageAuthenticationCode* proto = prototype_mac(algo_spec, provider))
+ return proto->clone();
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/**
+* Add a new block cipher
+*/
+void Algorithm_Factory::add_block_cipher(BlockCipher* block_cipher,
+ const std::string& provider)
+ {
+ block_cipher_cache->add(block_cipher, block_cipher->name(), provider);
+ }
+
+/**
+* Add a new stream cipher
+*/
+void Algorithm_Factory::add_stream_cipher(StreamCipher* stream_cipher,
+ const std::string& provider)
+ {
+ stream_cipher_cache->add(stream_cipher, stream_cipher->name(), provider);
+ }
+
+/**
+* Add a new hash
+*/
+void Algorithm_Factory::add_hash_function(HashFunction* hash,
+ const std::string& provider)
+ {
+ hash_cache->add(hash, hash->name(), provider);
+ }
+
+/**
+* Add a new mac
+*/
+void Algorithm_Factory::add_mac(MessageAuthenticationCode* mac,
+ const std::string& provider)
+ {
+ mac_cache->add(mac, mac->name(), provider);
+ }
+
+}
diff --git a/botan/src/algo_factory/algo_factory.h b/botan/src/algo_factory/algo_factory.h
new file mode 100644
index 0000000..73e5920
--- /dev/null
+++ b/botan/src/algo_factory/algo_factory.h
@@ -0,0 +1,132 @@
+/**
+* Algorithm Factory
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALGORITHM_FACTORY_H__
+#define BOTAN_ALGORITHM_FACTORY_H__
+
+#include <botan/mutex.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Forward declarations (don't need full definitions here)
+*/
+class BlockCipher;
+class StreamCipher;
+class HashFunction;
+class MessageAuthenticationCode;
+
+template<typename T> class Algorithm_Cache;
+
+class Engine;
+
+/**
+* Algorithm Factory
+*/
+class BOTAN_DLL Algorithm_Factory
+ {
+ public:
+ /**
+ * Constructor
+ * @param engines_in the list of engines to use
+ * @param mf a mutex factory
+ */
+ Algorithm_Factory(const std::vector<Engine*>& engines_in,
+ Mutex_Factory& mf);
+
+ /**
+ * Destructor
+ */
+ ~Algorithm_Factory();
+
+ /*
+ * Provider management
+ */
+ std::vector<std::string> providers_of(const std::string& algo_spec);
+
+ void set_preferred_provider(const std::string& algo_spec,
+ const std::string& provider);
+
+ /*
+ * Block cipher operations
+ */
+ const BlockCipher*
+ prototype_block_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ BlockCipher* make_block_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_block_cipher(BlockCipher* hash, const std::string& provider);
+
+ /*
+ * Stream cipher operations
+ */
+ const StreamCipher*
+ prototype_stream_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ StreamCipher* make_stream_cipher(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_stream_cipher(StreamCipher* hash, const std::string& provider);
+
+ /*
+ * Hash function operations
+ */
+ const HashFunction*
+ prototype_hash_function(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ HashFunction* make_hash_function(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_hash_function(HashFunction* hash, const std::string& provider);
+
+ /*
+ * MAC operations
+ */
+ const MessageAuthenticationCode*
+ prototype_mac(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ MessageAuthenticationCode* make_mac(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ void add_mac(MessageAuthenticationCode* mac,
+ const std::string& provider);
+
+ /*
+ * Deprecated
+ */
+ class BOTAN_DLL Engine_Iterator
+ {
+ public:
+ class Engine* next() { return af.get_engine_n(n++); }
+ Engine_Iterator(const Algorithm_Factory& a) : af(a) { n = 0; }
+ private:
+ const Algorithm_Factory& af;
+ u32bit n;
+ };
+ friend class Engine_Iterator;
+
+ private:
+ class Engine* get_engine_n(u32bit) const;
+
+ std::vector<class Engine*> engines;
+
+ Algorithm_Cache<BlockCipher>* block_cipher_cache;
+ Algorithm_Cache<StreamCipher>* stream_cipher_cache;
+ Algorithm_Cache<HashFunction>* hash_cache;
+ Algorithm_Cache<MessageAuthenticationCode>* mac_cache;
+ };
+
+}
+
+#endif
diff --git a/botan/src/algo_factory/info.txt b/botan/src/algo_factory/info.txt
new file mode 100644
index 0000000..dfc4223
--- /dev/null
+++ b/botan/src/algo_factory/info.txt
@@ -0,0 +1,21 @@
+realname "Algorithm Factory"
+
+load_on auto
+
+define ALGORITHM_FACTORY
+
+<add>
+algo_factory.cpp
+algo_factory.h
+algo_cache.h
+prov_weight.cpp
+</add>
+
+<requires>
+block
+engine
+hash
+mac
+mutex
+stream
+</requires>
diff --git a/botan/src/algo_factory/prov_weight.cpp b/botan/src/algo_factory/prov_weight.cpp
new file mode 100644
index 0000000..a55a8b1
--- /dev/null
+++ b/botan/src/algo_factory/prov_weight.cpp
@@ -0,0 +1,33 @@
+/**
+* Default provider weights for Algorithm_Cache
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/algo_cache.h>
+
+namespace Botan {
+
+/**
+* Return a static provider weighing
+*/
+u32bit static_provider_weight(const std::string& prov_name)
+ {
+ /*
+ * Prefer asm over C++, but prefer anything over OpenSSL or GNU MP; to use
+ * them, set the provider explicitly for the algorithms you want
+ */
+
+ if(prov_name == "core") return 5;
+ if(prov_name == "ia32") return 6;
+ if(prov_name == "amd64") return 7;
+ if(prov_name == "sse2") return 8;
+
+ if(prov_name == "openssl") return 2;
+ if(prov_name == "gmp") return 1;
+
+ return 0; // other
+ }
+
+}
diff --git a/botan/src/alloc/alloc_mmap/info.txt b/botan/src/alloc/alloc_mmap/info.txt
new file mode 100644
index 0000000..65d9b29
--- /dev/null
+++ b/botan/src/alloc/alloc_mmap/info.txt
@@ -0,0 +1,30 @@
+realname "Disk Based Allocation System"
+
+define ALLOC_MMAP
+modset unix
+
+load_on auto
+
+<add>
+mmap_mem.cpp
+mmap_mem.h
+</add>
+
+<os>
+linux
+freebsd
+dragonfly
+openbsd
+netbsd
+solaris
+qnx
+darwin
+tru64
+
+# Only without -ansi, otherwise can't get mkstemp
+#cygwin
+</os>
+
+<requires>
+mem_pool
+</requires>
diff --git a/botan/src/alloc/alloc_mmap/mmap_mem.cpp b/botan/src/alloc/alloc_mmap/mmap_mem.cpp
new file mode 100644
index 0000000..546da7a
--- /dev/null
+++ b/botan/src/alloc/alloc_mmap/mmap_mem.cpp
@@ -0,0 +1,124 @@
+/*
+* Memory Mapping Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mmap_mem.h>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#ifndef MAP_FAILED
+ #define MAP_FAILED -1
+#endif
+
+namespace Botan {
+
+namespace {
+
+/*
+* MemoryMapping_Allocator Exception
+*/
+class MemoryMapping_Failed : public Exception
+ {
+ public:
+ MemoryMapping_Failed(const std::string& msg) :
+ Exception("MemoryMapping_Allocator: " + msg) {}
+ };
+
+}
+
+/*
+* Memory Map a File into Memory
+*/
+void* MemoryMapping_Allocator::alloc_block(u32bit n)
+ {
+ class TemporaryFile
+ {
+ public:
+ int get_fd() const { return fd; }
+ const std::string path() const { return filepath; }
+
+ TemporaryFile(const std::string& base)
+ {
+ const std::string path = base + "XXXXXX";
+
+ filepath = new char[path.length() + 1];
+ std::strcpy(filepath, path.c_str());
+
+ mode_t old_umask = ::umask(077);
+ fd = ::mkstemp(filepath);
+ ::umask(old_umask);
+ }
+
+ ~TemporaryFile()
+ {
+ delete[] filepath;
+ if(fd != -1 && ::close(fd) == -1)
+ throw MemoryMapping_Failed("Could not close file");
+ }
+ private:
+ int fd;
+ char* filepath;
+ };
+
+ TemporaryFile file("/tmp/botan_");
+
+ if(file.get_fd() == -1)
+ throw MemoryMapping_Failed("Could not create file");
+
+ if(::unlink(file.path().c_str()))
+ throw MemoryMapping_Failed("Could not unlink file '" + file.path() + "'");
+
+ if(::lseek(file.get_fd(), n-1, SEEK_SET) < 0)
+ throw MemoryMapping_Failed("Could not seek file");
+
+ if(::write(file.get_fd(), "\0", 1) != 1)
+ throw MemoryMapping_Failed("Could not write to file");
+
+#ifndef MAP_NOSYNC
+ #define MAP_NOSYNC 0
+#endif
+
+ void* ptr = ::mmap(0, n,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_NOSYNC,
+ file.get_fd(), 0);
+
+ if(ptr == static_cast<void*>(MAP_FAILED))
+ throw MemoryMapping_Failed("Could not map file");
+
+ return ptr;
+ }
+
+/*
+* Remove a Memory Mapping
+*/
+void MemoryMapping_Allocator::dealloc_block(void* ptr, u32bit n)
+ {
+ if(ptr == 0)
+ return;
+
+ const byte PATTERNS[] = { 0x00, 0xFF, 0xAA, 0x55, 0x73, 0x8C, 0x5F, 0xA0,
+ 0x6E, 0x91, 0x30, 0xCF, 0xD3, 0x2C, 0xAC, 0x00 };
+
+ for(u32bit j = 0; j != sizeof(PATTERNS); j++)
+ {
+ std::memset(ptr, PATTERNS[j], n);
+
+ if(::msync(ptr, n, MS_SYNC))
+ throw MemoryMapping_Failed("Sync operation failed");
+ }
+
+ if(::munmap(ptr, n))
+ throw MemoryMapping_Failed("Could not unmap file");
+ }
+
+}
diff --git a/botan/src/alloc/alloc_mmap/mmap_mem.h b/botan/src/alloc/alloc_mmap/mmap_mem.h
new file mode 100644
index 0000000..bef166a
--- /dev/null
+++ b/botan/src/alloc/alloc_mmap/mmap_mem.h
@@ -0,0 +1,30 @@
+/*
+* Memory Mapping Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MMAP_ALLOCATOR_H__
+#define BOTAN_MMAP_ALLOCATOR_H__
+
+#include <botan/mem_pool.h>
+
+namespace Botan {
+
+/*
+* Memory Mapping Allocator
+*/
+class BOTAN_DLL MemoryMapping_Allocator : public Pooling_Allocator
+ {
+ public:
+ MemoryMapping_Allocator(Mutex* m) : Pooling_Allocator(m) {}
+ std::string type() const { return "mmap"; }
+ private:
+ void* alloc_block(u32bit);
+ void dealloc_block(void*, u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/src/alloc/allocate.h b/botan/src/alloc/allocate.h
new file mode 100644
index 0000000..180f2c0
--- /dev/null
+++ b/botan/src/alloc/allocate.h
@@ -0,0 +1,37 @@
+/*
+* Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALLOCATOR_H__
+#define BOTAN_ALLOCATOR_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Allocator Interface
+*/
+class BOTAN_DLL Allocator
+ {
+ public:
+ static Allocator* get(bool);
+
+ virtual void* allocate(u32bit) = 0;
+ virtual void deallocate(void*, u32bit) = 0;
+
+ virtual std::string type() const = 0;
+
+ virtual void init() {}
+ virtual void destroy() {}
+
+ virtual ~Allocator() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/alloc/info.txt b/botan/src/alloc/info.txt
new file mode 100644
index 0000000..fa50aa0
--- /dev/null
+++ b/botan/src/alloc/info.txt
@@ -0,0 +1,8 @@
+realname "Allocator"
+
+load_on auto
+
+<add>
+allocate.h
+secmem.h
+</add>
diff --git a/botan/src/alloc/mem_pool/info.txt b/botan/src/alloc/mem_pool/info.txt
new file mode 100644
index 0000000..0a762cc
--- /dev/null
+++ b/botan/src/alloc/mem_pool/info.txt
@@ -0,0 +1,12 @@
+realname "Memory Pool Allocator"
+
+load_on auto
+
+<add>
+mem_pool.cpp
+mem_pool.h
+</add>
+
+<requires>
+mutex
+</requires>
diff --git a/botan/src/alloc/mem_pool/mem_pool.cpp b/botan/src/alloc/mem_pool/mem_pool.cpp
new file mode 100644
index 0000000..a6ebef3
--- /dev/null
+++ b/botan/src/alloc/mem_pool/mem_pool.cpp
@@ -0,0 +1,265 @@
+/*
+* Pooling Allocator
+* (C) 1999-2008 Jack Lloyd
+* 2005 Matthew Gregan
+* 2005-2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mem_pool.h>
+#include <botan/util.h>
+#include <botan/mem_ops.h>
+#include <algorithm>
+#include <exception>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Memory Allocation Exception
+*/
+struct Memory_Exhaustion : public std::bad_alloc
+ {
+ const char* what() const throw()
+ { return "Ran out of memory, allocation failed"; }
+ };
+
+}
+
+/*
+* Memory_Block Constructor
+*/
+Pooling_Allocator::Memory_Block::Memory_Block(void* buf)
+ {
+ buffer = static_cast<byte*>(buf);
+ bitmap = 0;
+ buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE);
+ }
+
+/*
+* See if ptr is contained by this block
+*/
+bool Pooling_Allocator::Memory_Block::contains(void* ptr,
+ u32bit length) const throw()
+ {
+ return ((buffer <= ptr) &&
+ (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE));
+ }
+
+/*
+* Allocate some memory, if possible
+*/
+byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) throw()
+ {
+ if(n == 0 || n > BITMAP_SIZE)
+ return 0;
+
+ if(n == BITMAP_SIZE)
+ {
+ if(bitmap)
+ return 0;
+ else
+ {
+ bitmap = ~bitmap;
+ return buffer;
+ }
+ }
+
+ bitmap_type mask = (static_cast<bitmap_type>(1) << n) - 1;
+ u32bit offset = 0;
+
+ while(bitmap & mask)
+ {
+ mask <<= 1;
+ ++offset;
+
+ if((bitmap & mask) == 0)
+ break;
+ if(mask >> 63)
+ break;
+ }
+
+ if(bitmap & mask)
+ return 0;
+
+ bitmap |= mask;
+ return buffer + offset * BLOCK_SIZE;
+ }
+
+/*
+* Mark this memory as free, if we own it
+*/
+void Pooling_Allocator::Memory_Block::free(void* ptr, u32bit blocks) throw()
+ {
+ clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE);
+
+ const u32bit offset = (static_cast<byte*>(ptr) - buffer) / BLOCK_SIZE;
+
+ if(offset == 0 && blocks == BITMAP_SIZE)
+ bitmap = ~bitmap;
+ else
+ {
+ for(u32bit j = 0; j != blocks; ++j)
+ bitmap &= ~(static_cast<bitmap_type>(1) << (j+offset));
+ }
+ }
+
+/*
+* Pooling_Allocator Constructor
+*/
+Pooling_Allocator::Pooling_Allocator(Mutex* m) : mutex(m)
+ {
+ last_used = blocks.begin();
+ }
+
+/*
+* Pooling_Allocator Destructor
+*/
+Pooling_Allocator::~Pooling_Allocator()
+ {
+ delete mutex;
+ if(blocks.size())
+ throw Invalid_State("Pooling_Allocator: Never released memory");
+ }
+
+/*
+* Free all remaining memory
+*/
+void Pooling_Allocator::destroy()
+ {
+ Mutex_Holder lock(mutex);
+
+ blocks.clear();
+
+ for(u32bit j = 0; j != allocated.size(); ++j)
+ dealloc_block(allocated[j].first, allocated[j].second);
+ allocated.clear();
+ }
+
+/*
+* Allocation
+*/
+void* Pooling_Allocator::allocate(u32bit n)
+ {
+ const u32bit BITMAP_SIZE = Memory_Block::bitmap_size();
+ const u32bit BLOCK_SIZE = Memory_Block::block_size();
+
+ Mutex_Holder lock(mutex);
+
+ if(n <= BITMAP_SIZE * BLOCK_SIZE)
+ {
+ const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
+
+ byte* mem = allocate_blocks(block_no);
+ if(mem)
+ return mem;
+
+ get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE);
+
+ mem = allocate_blocks(block_no);
+ if(mem)
+ return mem;
+
+ throw Memory_Exhaustion();
+ }
+
+ void* new_buf = alloc_block(n);
+ if(new_buf)
+ return new_buf;
+
+ throw Memory_Exhaustion();
+ }
+
+/*
+* Deallocation
+*/
+void Pooling_Allocator::deallocate(void* ptr, u32bit n)
+ {
+ const u32bit BITMAP_SIZE = Memory_Block::bitmap_size();
+ const u32bit BLOCK_SIZE = Memory_Block::block_size();
+
+ if(ptr == 0 || n == 0)
+ return;
+
+ Mutex_Holder lock(mutex);
+
+ if(n > BITMAP_SIZE * BLOCK_SIZE)
+ dealloc_block(ptr, n);
+ else
+ {
+ const u32bit block_no = round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
+
+ std::vector<Memory_Block>::iterator i =
+ std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr));
+
+ if(i == blocks.end() || !i->contains(ptr, block_no))
+ throw Invalid_State("Pointer released to the wrong allocator");
+
+ i->free(ptr, block_no);
+ }
+ }
+
+/*
+* Try to get some memory from an existing block
+*/
+byte* Pooling_Allocator::allocate_blocks(u32bit n)
+ {
+ if(blocks.empty())
+ return 0;
+
+ std::vector<Memory_Block>::iterator i = last_used;
+
+ do
+ {
+ byte* mem = i->alloc(n);
+ if(mem)
+ {
+ last_used = i;
+ return mem;
+ }
+
+ ++i;
+ if(i == blocks.end())
+ i = blocks.begin();
+ }
+ while(i != last_used);
+
+ return 0;
+ }
+
+/*
+* Allocate more memory for the pool
+*/
+void Pooling_Allocator::get_more_core(u32bit in_bytes)
+ {
+ const u32bit BITMAP_SIZE = Memory_Block::bitmap_size();
+ const u32bit BLOCK_SIZE = Memory_Block::block_size();
+
+ const u32bit TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE;
+
+ // upper bound on allocation is 1 MiB
+ in_bytes = std::min<u32bit>(in_bytes, 1024 * 1024);
+
+ const u32bit in_blocks = round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE;
+ const u32bit to_allocate = in_blocks * TOTAL_BLOCK_SIZE;
+
+ void* ptr = alloc_block(to_allocate);
+ if(ptr == 0)
+ throw Memory_Exhaustion();
+
+ allocated.push_back(std::make_pair(ptr, to_allocate));
+
+ for(u32bit j = 0; j != in_blocks; ++j)
+ {
+ byte* byte_ptr = static_cast<byte*>(ptr);
+ blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE));
+ }
+
+ std::sort(blocks.begin(), blocks.end());
+ last_used = std::lower_bound(blocks.begin(), blocks.end(),
+ Memory_Block(ptr));
+ }
+
+}
diff --git a/botan/src/alloc/mem_pool/mem_pool.h b/botan/src/alloc/mem_pool/mem_pool.h
new file mode 100644
index 0000000..a578009
--- /dev/null
+++ b/botan/src/alloc/mem_pool/mem_pool.h
@@ -0,0 +1,74 @@
+/*
+* Pooling Allocator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POOLING_ALLOCATOR_H__
+#define BOTAN_POOLING_ALLOCATOR_H__
+
+#include <botan/allocate.h>
+#include <botan/exceptn.h>
+#include <botan/mutex.h>
+#include <utility>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Pooling Allocator
+*/
+class BOTAN_DLL Pooling_Allocator : public Allocator
+ {
+ public:
+ void* allocate(u32bit);
+ void deallocate(void*, u32bit);
+
+ void destroy();
+
+ Pooling_Allocator(Mutex*);
+ ~Pooling_Allocator();
+ private:
+ void get_more_core(u32bit);
+ byte* allocate_blocks(u32bit);
+
+ virtual void* alloc_block(u32bit) = 0;
+ virtual void dealloc_block(void*, u32bit) = 0;
+
+ class BOTAN_DLL Memory_Block
+ {
+ public:
+ Memory_Block(void*);
+
+ static u32bit bitmap_size() { return BITMAP_SIZE; }
+ static u32bit block_size() { return BLOCK_SIZE; }
+
+ bool contains(void*, u32bit) const throw();
+ byte* alloc(u32bit) throw();
+ void free(void*, u32bit) throw();
+
+ bool operator<(const Memory_Block& other) const
+ {
+ if(buffer < other.buffer && other.buffer < buffer_end)
+ return false;
+ return (buffer < other.buffer);
+ }
+ private:
+ typedef u64bit bitmap_type;
+ static const u32bit BITMAP_SIZE = 8 * sizeof(bitmap_type);
+ static const u32bit BLOCK_SIZE = 64;
+
+ bitmap_type bitmap;
+ byte* buffer, *buffer_end;
+ };
+
+ std::vector<Memory_Block> blocks;
+ std::vector<Memory_Block>::iterator last_used;
+ std::vector<std::pair<void*, u32bit> > allocated;
+ Mutex* mutex;
+ };
+
+}
+
+#endif
diff --git a/botan/src/alloc/secmem.h b/botan/src/alloc/secmem.h
new file mode 100644
index 0000000..d64a376
--- /dev/null
+++ b/botan/src/alloc/secmem.h
@@ -0,0 +1,438 @@
+/*
+* Secure Memory Buffers
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
+#define BOTAN_SECURE_MEMORY_BUFFERS_H__
+
+#include <botan/allocate.h>
+#include <botan/mem_ops.h>
+#include <algorithm>
+
+namespace Botan {
+
+/**
+* This class represents variable length memory buffers.
+*/
+template<typename T>
+class MemoryRegion
+ {
+ public:
+ /**
+ * Find out the size of the buffer, i.e. how many objects of type T it
+ * contains.
+ * @return the size of the buffer
+ */
+ u32bit size() const { return used; }
+
+ /**
+ * Find out whether this buffer is empty.
+ * @return true if the buffer is empty, false otherwise
+ */
+ bool is_empty() const { return (used == 0); }
+
+ /**
+ * Find out whether this buffer is non-empty
+ * @return true if the buffer is non-empty, false otherwise
+ */
+ bool has_items() const { return (used != 0); }
+
+ /**
+ * Get a pointer to the first element in the buffer.
+ * @return a pointer to the first element in the buffer
+ */
+ operator T* () { return buf; }
+
+ /**
+ * Get a constant pointer to the first element in the buffer.
+ * @return a constant pointer to the first element in the buffer
+ */
+ operator const T* () const { return buf; }
+
+ /**
+ * Get a pointer to the first element in the buffer.
+ * @return a pointer to the first element in the buffer
+ */
+ T* begin() { return buf; }
+
+ /**
+ * Get a constant pointer to the first element in the buffer.
+ * @return a constant pointer to the first element in the buffer
+ */
+ const T* begin() const { return buf; }
+
+ /**
+ * Get a pointer to the last element in the buffer.
+ * @return a pointer to the last element in the buffer
+ */
+ T* end() { return (buf + size()); }
+
+ /**
+ * Get a constant pointer to the last element in the buffer.
+ * @return a constant pointer to the last element in the buffer
+ */
+ const T* end() const { return (buf + size()); }
+
+ /**
+ * Check two buffers for equality.
+ * @return true iff the content of both buffers is byte-wise equal
+ */
+ bool operator==(const MemoryRegion<T>& other) const
+ {
+ return (size() == other.size() &&
+ same_mem(buf, other.buf, size()));
+ }
+
+ /**
+ * Compare two buffers lexicographically.
+ * @return true if this buffer is lexicographically smaller than other.
+ */
+ bool operator<(const MemoryRegion<T>& other) const;
+
+ /**
+ * Check two buffers for inequality.
+ * @return false if the content of both buffers is byte-wise equal, true
+ * otherwise.
+ */
+ bool operator!=(const MemoryRegion<T>& in) const
+ { return (!(*this == in)); }
+
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * The former contents of *this are discarded.
+ * @param in the buffer to copy the contents from.
+ * @return a reference to *this
+ */
+ MemoryRegion<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * The use of this function is discouraged because of the risk of memory
+ * errors. Use MemoryRegion<T>::set()
+ * instead.
+ * Copy the contents of an array of objects of type T into this buffer.
+ * The former contents of *this are discarded.
+ * The length of *this must be at least n, otherwise memory errors occur.
+ * @param in the array to copy the contents from
+ * @param n the length of in
+ */
+ void copy(const T in[], u32bit n)
+ { copy(0, in, n); }
+
+ /**
+ * The use of this function is discouraged because of the risk of memory
+ * errors. Use MemoryRegion<T>::set()
+ * instead.
+ * Copy the contents of an array of objects of type T into this buffer.
+ * The former contents of *this are discarded.
+ * The length of *this must be at least n, otherwise memory errors occur.
+ * @param off the offset position inside this buffer to start inserting
+ * the copied bytes
+ * @param in the array to copy the contents from
+ * @param n the length of in
+ */
+ void copy(u32bit off, const T in[], u32bit n)
+ { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); }
+
+ /**
+ * Set the contents of this according to the argument. The size of
+ * *this is increased if necessary.
+ * @param in the array of objects of type T to copy the contents from
+ * @param n the size of array in
+ */
+ void set(const T in[], u32bit n) { create(n); copy(in, n); }
+
+ /**
+ * Set the contents of this according to the argument. The size of
+ * *this is increased if necessary.
+ * @param in the buffer to copy the contents from
+ */
+ void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); }
+
+ /**
+ * Append data to the end of this buffer.
+ * @param data the array containing the data to append
+ * @param n the size of the array data
+ */
+ void append(const T data[], u32bit n)
+ { grow_to(size()+n); copy(size() - n, data, n); }
+
+ /**
+ * Append a single element.
+ * @param x the element to append
+ */
+ void append(T x) { append(&x, 1); }
+
+ /**
+ * Append data to the end of this buffer.
+ * @param data the buffer containing the data to append
+ */
+ void append(const MemoryRegion<T>& x) { append(x.begin(), x.size()); }
+
+ /**
+ * Zeroise the bytes of this buffer. The length remains unchanged.
+ */
+ void clear() { clear_mem(buf, allocated); }
+
+ /**
+ * Reset this buffer to an empty buffer with size zero.
+ */
+ void destroy() { create(0); }
+
+ /**
+ * Reset this buffer to a buffer of specified length. The content will be
+ * initialized to zero bytes.
+ * @param n the new length of the buffer
+ */
+ void create(u32bit n);
+
+ /**
+ * Preallocate memory, so that this buffer can grow up to size n without
+ * having to perform any actual memory allocations. (This is
+ * the same principle as for std::vector::reserve().)
+ */
+ void grow_to(u32bit N);
+
+ /**
+ * Swap this buffer with another object.
+ */
+ void swap(MemoryRegion<T>& other);
+
+ ~MemoryRegion() { deallocate(buf, allocated); }
+ protected:
+ MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; }
+ MemoryRegion(const MemoryRegion<T>& other)
+ {
+ buf = 0;
+ used = allocated = 0;
+ alloc = other.alloc;
+ set(other.buf, other.used);
+ }
+
+ void init(bool locking, u32bit length = 0)
+ { alloc = Allocator::get(locking); create(length); }
+ private:
+ T* allocate(u32bit n)
+ {
+ return static_cast<T*>(alloc->allocate(sizeof(T)*n));
+ }
+
+ void deallocate(T* p, u32bit n)
+ { alloc->deallocate(p, sizeof(T)*n); }
+
+ T* buf;
+ u32bit used;
+ u32bit allocated;
+ Allocator* alloc;
+ };
+
+/*
+* Create a new buffer
+*/
+template<typename T>
+void MemoryRegion<T>::create(u32bit n)
+ {
+ if(n <= allocated) { clear(); used = n; return; }
+ deallocate(buf, allocated);
+ buf = allocate(n);
+ allocated = used = n;
+ }
+
+/*
+* Increase the size of the buffer
+*/
+template<typename T>
+void MemoryRegion<T>::grow_to(u32bit n)
+ {
+ if(n > used && n <= allocated)
+ {
+ clear_mem(buf + used, n - used);
+ used = n;
+ return;
+ }
+ else if(n > allocated)
+ {
+ T* new_buf = allocate(n);
+ copy_mem(new_buf, buf, used);
+ deallocate(buf, allocated);
+ buf = new_buf;
+ allocated = used = n;
+ }
+ }
+
+/*
+* Compare this buffer with another one
+*/
+template<typename T>
+bool MemoryRegion<T>::operator<(const MemoryRegion<T>& in) const
+ {
+ if(size() < in.size()) return true;
+ if(size() > in.size()) return false;
+
+ for(u32bit j = 0; j != size(); j++)
+ {
+ if(buf[j] < in[j]) return true;
+ if(buf[j] > in[j]) return false;
+ }
+
+ return false;
+ }
+
+/*
+* Swap this buffer with another one
+*/
+template<typename T>
+void MemoryRegion<T>::swap(MemoryRegion<T>& x)
+ {
+ std::swap(buf, x.buf);
+ std::swap(used, x.used);
+ std::swap(allocated, x.allocated);
+ std::swap(alloc, x.alloc);
+ }
+
+/**
+* This class represents variable length buffers that do not
+* make use of memory locking.
+*/
+template<typename T>
+class MemoryVector : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ MemoryVector<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the specified length.
+ * @param n the length of the buffer to create.
+
+ */
+ MemoryVector(u32bit n = 0) { MemoryRegion<T>::init(false, n); }
+
+ /**
+ * Create a buffer with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the arry in
+ */
+ MemoryVector(const T in[], u32bit n)
+ { MemoryRegion<T>::init(false); set(in, n); }
+
+ /**
+ * Copy constructor.
+ */
+ MemoryVector(const MemoryRegion<T>& in)
+ { MemoryRegion<T>::init(false); set(in); }
+
+ /**
+ * Create a buffer whose content is the concatenation of two other
+ * buffers.
+ * @param in1 the first part of the new contents
+ * @param in2 the contents to be appended to in1
+ */
+ MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
+ { MemoryRegion<T>::init(false); set(in1); append(in2); }
+ };
+
+/**
+* This class represents variable length buffers using the operating
+* systems capability to lock memory, i.e. keeping it from being
+* swapped out to disk. In this way, a security hole allowing attackers
+* to find swapped out secret keys is closed. Please refer to
+* Botan::InitializerOptions::secure_memory() for restrictions and
+* further details.
+*/
+template<typename T>
+class SecureVector : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ SecureVector<T>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the specified length.
+ * @param n the length of the buffer to create.
+
+ */
+ SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); }
+
+ /**
+ * Create a buffer with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the array in
+ */
+ SecureVector(const T in[], u32bit n)
+ { MemoryRegion<T>::init(true); set(in, n); }
+
+ /**
+ * Create a buffer with contents specified contents.
+ * @param in the buffer holding the contents that will be
+ * copied into the newly created buffer.
+ */
+ SecureVector(const MemoryRegion<T>& in)
+ { MemoryRegion<T>::init(true); set(in); }
+
+ /**
+ * Create a buffer whose content is the concatenation of two other
+ * buffers.
+ * @param in1 the first part of the new contents
+ * @param in2 the contents to be appended to in1
+ */
+ SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
+ { MemoryRegion<T>::init(true); set(in1); append(in2); }
+ };
+
+/**
+* This class represents fixed length buffers using the operating
+* systems capability to lock memory, i.e. keeping it from being
+* swapped out to disk. In this way, a security hole allowing attackers
+* to find swapped out secret keys is closed. Please refer to
+* Botan::InitializerOptions::secure_memory() for restrictions and
+* further details.
+*/
+template<typename T, u32bit L>
+class SecureBuffer : public MemoryRegion<T>
+ {
+ public:
+ /**
+ * Copy the contents of another buffer into this buffer.
+ * @param in the buffer to copy the contents from
+ * @return a reference to *this
+ */
+ SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in)
+ { if(this != &in) set(in); return (*this); }
+
+ /**
+ * Create a buffer of the length L.
+ */
+ SecureBuffer() { MemoryRegion<T>::init(true, L); }
+
+ /**
+ * Create a buffer of size L with the specified contents.
+ * @param in the array containing the data to be initially copied
+ * into the newly created buffer
+ * @param n the size of the array in
+ */
+ SecureBuffer(const T in[], u32bit n)
+ { MemoryRegion<T>::init(true, L); copy(in, n); }
+ private:
+ SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in)
+ { if(this != &in) set(in); return (*this); }
+ };
+
+}
+
+#endif
diff --git a/botan/src/alloc/system_alloc/defalloc.cpp b/botan/src/alloc/system_alloc/defalloc.cpp
new file mode 100644
index 0000000..8791c74
--- /dev/null
+++ b/botan/src/alloc/system_alloc/defalloc.cpp
@@ -0,0 +1,100 @@
+/*
+* Basic Allocators
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/defalloc.h>
+#include <botan/libstate.h>
+#include <botan/util.h>
+#include <cstdlib>
+#include <cstring>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Perform Memory Allocation
+*/
+void* do_malloc(u32bit n, bool do_lock)
+ {
+ void* ptr = std::malloc(n);
+
+ if(!ptr)
+ return 0;
+
+ if(do_lock)
+ lock_mem(ptr, n);
+
+ std::memset(ptr, 0, n);
+ return ptr;
+ }
+
+/*
+* Perform Memory Deallocation
+*/
+void do_free(void* ptr, u32bit n, bool do_lock)
+ {
+ if(!ptr)
+ return;
+
+ std::memset(ptr, 0, n);
+ if(do_lock)
+ unlock_mem(ptr, n);
+
+ std::free(ptr);
+ }
+
+}
+
+/*
+* Malloc_Allocator's Allocation
+*/
+void* Malloc_Allocator::allocate(u32bit n)
+ {
+ return do_malloc(n, false);
+ }
+
+/*
+* Malloc_Allocator's Deallocation
+*/
+void Malloc_Allocator::deallocate(void* ptr, u32bit n)
+ {
+ do_free(ptr, n, false);
+ }
+
+/*
+* Locking_Allocator's Allocation
+*/
+void* Locking_Allocator::alloc_block(u32bit n)
+ {
+ return do_malloc(n, true);
+ }
+
+/*
+* Locking_Allocator's Deallocation
+*/
+void Locking_Allocator::dealloc_block(void* ptr, u32bit n)
+ {
+ do_free(ptr, n, true);
+ }
+
+/*
+* Get an allocator
+*/
+Allocator* Allocator::get(bool locking)
+ {
+ std::string type = "";
+ if(!locking)
+ type = "malloc";
+
+ Allocator* alloc = global_state().get_allocator(type);
+ if(alloc)
+ return alloc;
+
+ throw Exception("Couldn't find an allocator to use in get_allocator");
+ }
+
+}
diff --git a/botan/src/alloc/system_alloc/defalloc.h b/botan/src/alloc/system_alloc/defalloc.h
new file mode 100644
index 0000000..627e8df
--- /dev/null
+++ b/botan/src/alloc/system_alloc/defalloc.h
@@ -0,0 +1,43 @@
+/*
+* Basic Allocators
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASIC_ALLOC_H__
+#define BOTAN_BASIC_ALLOC_H__
+
+#include <botan/mem_pool.h>
+
+namespace Botan {
+
+/*
+* Malloc Allocator
+*/
+class BOTAN_DLL Malloc_Allocator : public Allocator
+ {
+ public:
+ void* allocate(u32bit);
+ void deallocate(void*, u32bit);
+
+ std::string type() const { return "malloc"; }
+ };
+
+/*
+* Locking Allocator
+*/
+class BOTAN_DLL Locking_Allocator : public Pooling_Allocator
+ {
+ public:
+ Locking_Allocator(Mutex* m) : Pooling_Allocator(m) {}
+
+ std::string type() const { return "locking"; }
+ private:
+ void* alloc_block(u32bit);
+ void dealloc_block(void*, u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/src/alloc/system_alloc/info.txt b/botan/src/alloc/system_alloc/info.txt
new file mode 100644
index 0000000..5fade38
--- /dev/null
+++ b/botan/src/alloc/system_alloc/info.txt
@@ -0,0 +1,13 @@
+realname "Default (Malloc) Allocators"
+
+load_on auto
+
+<add>
+defalloc.cpp
+defalloc.h
+</add>
+
+<requires>
+libstate
+mem_pool
+</requires>
diff --git a/botan/src/asn1/alg_id.cpp b/botan/src/asn1/alg_id.cpp
new file mode 100644
index 0000000..94709ba
--- /dev/null
+++ b/botan/src/asn1/alg_id.cpp
@@ -0,0 +1,103 @@
+/*
+* Algorithm Identifier
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/alg_id.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* Create an AlgorithmIdentifier
+*/
+AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id,
+ const MemoryRegion<byte>& param)
+ {
+ oid = alg_id;
+ parameters = param;
+ }
+
+/*
+* Create an AlgorithmIdentifier
+*/
+AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id,
+ const MemoryRegion<byte>& param)
+ {
+ oid = OIDS::lookup(alg_id);
+ parameters = param;
+ }
+
+/*
+* Create an AlgorithmIdentifier
+*/
+AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id,
+ Encoding_Option option)
+ {
+ const byte DER_NULL[] = { 0x05, 0x00 };
+
+ oid = alg_id;
+ if(option == USE_NULL_PARAM)
+ parameters.append(DER_NULL, sizeof(DER_NULL));
+ }
+
+/*
+* Create an AlgorithmIdentifier
+*/
+AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id,
+ Encoding_Option option)
+ {
+ const byte DER_NULL[] = { 0x05, 0x00 };
+
+ oid = OIDS::lookup(alg_id);
+ if(option == USE_NULL_PARAM)
+ parameters.append(DER_NULL, sizeof(DER_NULL));
+ }
+
+/*
+* Compare two AlgorithmIdentifiers
+*/
+bool operator==(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2)
+ {
+ if(a1.oid != a2.oid)
+ return false;
+ if(a1.parameters != a2.parameters)
+ return false;
+ return true;
+ }
+
+/*
+* Compare two AlgorithmIdentifiers
+*/
+bool operator!=(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2)
+ {
+ return !(a1 == a2);
+ }
+
+/*
+* DER encode an AlgorithmIdentifier
+*/
+void AlgorithmIdentifier::encode_into(DER_Encoder& codec) const
+ {
+ codec.start_cons(SEQUENCE)
+ .encode(oid)
+ .raw_bytes(parameters)
+ .end_cons();
+ }
+
+/*
+* Decode a BER encoded AlgorithmIdentifier
+*/
+void AlgorithmIdentifier::decode_from(BER_Decoder& codec)
+ {
+ codec.start_cons(SEQUENCE)
+ .decode(oid)
+ .raw_bytes(parameters)
+ .end_cons();
+ }
+
+}
diff --git a/botan/src/asn1/alg_id.h b/botan/src/asn1/alg_id.h
new file mode 100644
index 0000000..4a1ad2f
--- /dev/null
+++ b/botan/src/asn1/alg_id.h
@@ -0,0 +1,49 @@
+/*
+* Algorithm Identifier
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ALGORITHM_IDENTIFIER_H__
+#define BOTAN_ALGORITHM_IDENTIFIER_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Algorithm Identifier
+*/
+class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object
+ {
+ public:
+ enum Encoding_Option { USE_NULL_PARAM };
+
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ AlgorithmIdentifier() {}
+ AlgorithmIdentifier(const OID&, Encoding_Option);
+ AlgorithmIdentifier(const std::string&, Encoding_Option);
+
+ AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&);
+ AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&);
+
+ OID oid;
+ SecureVector<byte> parameters;
+ };
+
+/*
+* Comparison Operations
+*/
+bool BOTAN_DLL operator==(const AlgorithmIdentifier&,
+ const AlgorithmIdentifier&);
+bool BOTAN_DLL operator!=(const AlgorithmIdentifier&,
+ const AlgorithmIdentifier&);
+
+}
+
+#endif
diff --git a/botan/src/asn1/asn1_alt.cpp b/botan/src/asn1/asn1_alt.cpp
new file mode 100644
index 0000000..41974ee
--- /dev/null
+++ b/botan/src/asn1/asn1_alt.cpp
@@ -0,0 +1,228 @@
+/*
+* AlternativeName
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+#include <botan/stl_util.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Create an AlternativeName
+*/
+AlternativeName::AlternativeName(const std::string& email_addr,
+ const std::string& uri,
+ const std::string& dns,
+ const std::string& ip)
+ {
+ add_attribute("RFC822", email_addr);
+ add_attribute("DNS", dns);
+ add_attribute("URI", uri);
+ add_attribute("IP", ip);
+ }
+
+/*
+* Add an attribute to an alternative name
+*/
+void AlternativeName::add_attribute(const std::string& type,
+ const std::string& str)
+ {
+ if(type == "" || str == "")
+ return;
+
+ typedef std::multimap<std::string, std::string>::iterator iter;
+ std::pair<iter, iter> range = alt_info.equal_range(type);
+ for(iter j = range.first; j != range.second; ++j)
+ if(j->second == str)
+ return;
+
+ multimap_insert(alt_info, type, str);
+ }
+
+/*
+* Add an OtherName field
+*/
+void AlternativeName::add_othername(const OID& oid, const std::string& value,
+ ASN1_Tag type)
+ {
+ if(value == "")
+ return;
+ multimap_insert(othernames, oid, ASN1_String(value, type));
+ }
+
+/*
+* Get the attributes of this alternative name
+*/
+std::multimap<std::string, std::string> AlternativeName::get_attributes() const
+ {
+ return alt_info;
+ }
+
+/*
+* Get the otherNames
+*/
+std::multimap<OID, ASN1_String> AlternativeName::get_othernames() const
+ {
+ return othernames;
+ }
+
+/*
+* Return all of the alternative names
+*/
+std::multimap<std::string, std::string> AlternativeName::contents() const
+ {
+ std::multimap<std::string, std::string> names;
+
+ typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
+ for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j)
+ multimap_insert(names, j->first, j->second);
+
+ typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
+ for(on_iter j = othernames.begin(); j != othernames.end(); ++j)
+ multimap_insert(names, OIDS::lookup(j->first), j->second.value());
+
+ return names;
+ }
+
+/*
+* Return if this object has anything useful
+*/
+bool AlternativeName::has_items() const
+ {
+ return (alt_info.size() > 0 || othernames.size() > 0);
+ }
+
+namespace {
+
+/*
+* DER encode an AlternativeName entry
+*/
+void encode_entries(DER_Encoder& encoder,
+ const std::multimap<std::string, std::string>& attr,
+ const std::string& type, ASN1_Tag tagging)
+ {
+ typedef std::multimap<std::string, std::string>::const_iterator iter;
+
+ std::pair<iter, iter> range = attr.equal_range(type);
+ for(iter j = range.first; j != range.second; ++j)
+ {
+ if(type == "RFC822" || type == "DNS" || type == "URI")
+ {
+ ASN1_String asn1_string(j->second, IA5_STRING);
+ encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859());
+ }
+ else if(type == "IP")
+ {
+ u32bit ip = string_to_ipv4(j->second);
+ byte ip_buf[4] = { 0 };
+ store_be(ip, ip_buf);
+ encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4);
+ }
+ }
+ }
+
+}
+
+/*
+* DER encode an AlternativeName extension
+*/
+void AlternativeName::encode_into(DER_Encoder& der) const
+ {
+ der.start_cons(SEQUENCE);
+
+ encode_entries(der, alt_info, "RFC822", ASN1_Tag(1));
+ encode_entries(der, alt_info, "DNS", ASN1_Tag(2));
+ encode_entries(der, alt_info, "URI", ASN1_Tag(6));
+ encode_entries(der, alt_info, "IP", ASN1_Tag(7));
+
+ std::multimap<OID, ASN1_String>::const_iterator i;
+ for(i = othernames.begin(); i != othernames.end(); ++i)
+ {
+ der.start_explicit(0)
+ .encode(i->first)
+ .start_explicit(0)
+ .encode(i->second)
+ .end_explicit()
+ .end_explicit();
+ }
+
+ der.end_cons();
+ }
+
+/*
+* Decode a BER encoded AlternativeName
+*/
+void AlternativeName::decode_from(BER_Decoder& source)
+ {
+ BER_Decoder names = source.start_cons(SEQUENCE);
+
+ while(names.more_items())
+ {
+ BER_Object obj = names.get_next_object();
+ if((obj.class_tag != CONTEXT_SPECIFIC) &&
+ (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED)))
+ continue;
+
+ ASN1_Tag tag = obj.type_tag;
+
+ if(tag == 0)
+ {
+ BER_Decoder othername(obj.value);
+
+ OID oid;
+ othername.decode(oid);
+ if(othername.more_items())
+ {
+ BER_Object othername_value_outer = othername.get_next_object();
+ othername.verify_end();
+
+ if(othername_value_outer.type_tag != ASN1_Tag(0) ||
+ othername_value_outer.class_tag !=
+ (CONTEXT_SPECIFIC | CONSTRUCTED)
+ )
+ throw Decoding_Error("Invalid tags on otherName value");
+
+ BER_Decoder othername_value_inner(othername_value_outer.value);
+
+ BER_Object value = othername_value_inner.get_next_object();
+ othername_value_inner.verify_end();
+
+ ASN1_Tag value_type = value.type_tag;
+
+ if(is_string_type(value_type) && value.class_tag == UNIVERSAL)
+ add_othername(oid, ASN1::to_string(value), value_type);
+ }
+ }
+ else if(tag == 1 || tag == 2 || tag == 6)
+ {
+ const std::string value = Charset::transcode(ASN1::to_string(obj),
+ LATIN1_CHARSET,
+ LOCAL_CHARSET);
+
+ if(tag == 1) add_attribute("RFC822", value);
+ if(tag == 2) add_attribute("DNS", value);
+ if(tag == 6) add_attribute("URI", value);
+ }
+ else if(tag == 7)
+ {
+ if(obj.value.size() == 4)
+ {
+ u32bit ip = load_be<u32bit>(obj.value.begin(), 0);
+ add_attribute("IP", ipv4_to_string(ip));
+ }
+ }
+
+ }
+ }
+
+}
diff --git a/botan/src/asn1/asn1_att.cpp b/botan/src/asn1/asn1_att.cpp
new file mode 100644
index 0000000..c8d771e
--- /dev/null
+++ b/botan/src/asn1/asn1_att.cpp
@@ -0,0 +1,60 @@
+/*
+* Attribute
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* Create an Attribute
+*/
+Attribute::Attribute(const OID& attr_oid, const MemoryRegion<byte>& attr_value)
+ {
+ oid = attr_oid;
+ parameters = attr_value;
+ }
+
+/*
+* Create an Attribute
+*/
+Attribute::Attribute(const std::string& attr_oid,
+ const MemoryRegion<byte>& attr_value)
+ {
+ oid = OIDS::lookup(attr_oid);
+ parameters = attr_value;
+ }
+
+/*
+* DER encode a Attribute
+*/
+void Attribute::encode_into(DER_Encoder& codec) const
+ {
+ codec.start_cons(SEQUENCE)
+ .encode(oid)
+ .start_cons(SET)
+ .raw_bytes(parameters)
+ .end_cons()
+ .end_cons();
+ }
+
+/*
+* Decode a BER encoded Attribute
+*/
+void Attribute::decode_from(BER_Decoder& codec)
+ {
+ codec.start_cons(SEQUENCE)
+ .decode(oid)
+ .start_cons(SET)
+ .raw_bytes(parameters)
+ .end_cons()
+ .end_cons();
+ }
+
+}
diff --git a/botan/src/asn1/asn1_dn.cpp b/botan/src/asn1/asn1_dn.cpp
new file mode 100644
index 0000000..c5a132d
--- /dev/null
+++ b/botan/src/asn1/asn1_dn.cpp
@@ -0,0 +1,304 @@
+/*
+* X509_DN
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/stl_util.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* Create an empty X509_DN
+*/
+X509_DN::X509_DN()
+ {
+ }
+
+/*
+* Create an X509_DN
+*/
+X509_DN::X509_DN(const std::multimap<OID, std::string>& args)
+ {
+ std::multimap<OID, std::string>::const_iterator j;
+ for(j = args.begin(); j != args.end(); ++j)
+ add_attribute(j->first, j->second);
+ }
+
+/*
+* Create an X509_DN
+*/
+X509_DN::X509_DN(const std::multimap<std::string, std::string>& args)
+ {
+ std::multimap<std::string, std::string>::const_iterator j;
+ for(j = args.begin(); j != args.end(); ++j)
+ add_attribute(OIDS::lookup(j->first), j->second);
+ }
+
+/*
+* Add an attribute to a X509_DN
+*/
+void X509_DN::add_attribute(const std::string& type,
+ const std::string& str)
+ {
+ OID oid = OIDS::lookup(type);
+ add_attribute(oid, str);
+ }
+
+/*
+* Add an attribute to a X509_DN
+*/
+void X509_DN::add_attribute(const OID& oid, const std::string& str)
+ {
+ if(str == "")
+ return;
+
+ typedef std::multimap<OID, ASN1_String>::iterator rdn_iter;
+
+ std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
+ for(rdn_iter j = range.first; j != range.second; ++j)
+ if(j->second.value() == str)
+ return;
+
+ multimap_insert(dn_info, oid, ASN1_String(str));
+ dn_bits.destroy();
+ }
+
+/*
+* Get the attributes of this X509_DN
+*/
+std::multimap<OID, std::string> X509_DN::get_attributes() const
+ {
+ typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
+
+ std::multimap<OID, std::string> retval;
+ for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
+ multimap_insert(retval, j->first, j->second.value());
+ return retval;
+ }
+
+/*
+* Get the contents of this X.500 Name
+*/
+std::multimap<std::string, std::string> X509_DN::contents() const
+ {
+ typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
+
+ std::multimap<std::string, std::string> retval;
+ for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
+ multimap_insert(retval, OIDS::lookup(j->first), j->second.value());
+ return retval;
+ }
+
+/*
+* Get a single attribute type
+*/
+std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const
+ {
+ typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
+
+ const OID oid = OIDS::lookup(deref_info_field(attr));
+ std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
+
+ std::vector<std::string> values;
+ for(rdn_iter j = range.first; j != range.second; ++j)
+ values.push_back(j->second.value());
+ return values;
+ }
+
+/*
+* Handle the decoding operation of a DN
+*/
+void X509_DN::do_decode(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder sequence(bits);
+
+ while(sequence.more_items())
+ {
+ BER_Decoder rdn = sequence.start_cons(SET);
+
+ while(rdn.more_items())
+ {
+ OID oid;
+ ASN1_String str;
+
+ rdn.start_cons(SEQUENCE)
+ .decode(oid)
+ .decode(str)
+ .verify_end()
+ .end_cons();
+
+ add_attribute(oid, str.value());
+ }
+ }
+
+ dn_bits = bits;
+ }
+
+/*
+* Return the BER encoded data, if any
+*/
+MemoryVector<byte> X509_DN::get_bits() const
+ {
+ return dn_bits;
+ }
+
+/*
+* Deref aliases in a subject/issuer info request
+*/
+std::string X509_DN::deref_info_field(const std::string& info)
+ {
+ if(info == "Name" || info == "CommonName") return "X520.CommonName";
+ if(info == "SerialNumber") return "X520.SerialNumber";
+ if(info == "Country") return "X520.Country";
+ if(info == "Organization") return "X520.Organization";
+ if(info == "Organizational Unit" || info == "OrgUnit")
+ return "X520.OrganizationalUnit";
+ if(info == "Locality") return "X520.Locality";
+ if(info == "State" || info == "Province") return "X520.State";
+ if(info == "Email") return "RFC822";
+ return info;
+ }
+
+/*
+* Compare two X509_DNs for equality
+*/
+bool operator==(const X509_DN& dn1, const X509_DN& dn2)
+ {
+ typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
+
+ std::multimap<OID, std::string> attr1 = dn1.get_attributes();
+ std::multimap<OID, std::string> attr2 = dn2.get_attributes();
+
+ if(attr1.size() != attr2.size()) return false;
+
+ rdn_iter p1 = attr1.begin();
+ rdn_iter p2 = attr2.begin();
+
+ while(true)
+ {
+ if(p1 == attr1.end() && p2 == attr2.end())
+ break;
+ if(p1 == attr1.end()) return false;
+ if(p2 == attr2.end()) return false;
+ if(p1->first != p2->first) return false;
+ if(!x500_name_cmp(p1->second, p2->second))
+ return false;
+ ++p1;
+ ++p2;
+ }
+ return true;
+ }
+
+/*
+* Compare two X509_DNs for inequality
+*/
+bool operator!=(const X509_DN& dn1, const X509_DN& dn2)
+ {
+ return !(dn1 == dn2);
+ }
+
+/*
+* Compare two X509_DNs
+*/
+bool operator<(const X509_DN& dn1, const X509_DN& dn2)
+ {
+ typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
+
+ std::multimap<OID, std::string> attr1 = dn1.get_attributes();
+ std::multimap<OID, std::string> attr2 = dn2.get_attributes();
+
+ if(attr1.size() < attr2.size()) return true;
+ if(attr1.size() > attr2.size()) return false;
+
+ for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1)
+ {
+ std::multimap<OID, std::string>::const_iterator p2;
+ p2 = attr2.find(p1->first);
+ if(p2 == attr2.end()) return false;
+ if(p1->second > p2->second) return false;
+ if(p1->second < p2->second) return true;
+ }
+ return false;
+ }
+
+namespace {
+
+/*
+* DER encode a RelativeDistinguishedName
+*/
+void do_ava(DER_Encoder& encoder,
+ const std::multimap<OID, std::string>& dn_info,
+ ASN1_Tag string_type, const std::string& oid_str,
+ bool must_exist = false)
+ {
+ typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
+
+ const OID oid = OIDS::lookup(oid_str);
+ const bool exists = (dn_info.find(oid) != dn_info.end());
+
+ if(!exists && must_exist)
+ throw Encoding_Error("X509_DN: No entry for " + oid_str);
+ if(!exists) return;
+
+ std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
+
+ for(rdn_iter j = range.first; j != range.second; ++j)
+ {
+ encoder.start_cons(SET)
+ .start_cons(SEQUENCE)
+ .encode(oid)
+ .encode(ASN1_String(j->second, string_type))
+ .end_cons()
+ .end_cons();
+ }
+ }
+
+}
+
+/*
+* DER encode a DistinguishedName
+*/
+void X509_DN::encode_into(DER_Encoder& der) const
+ {
+ std::multimap<OID, std::string> dn_info = get_attributes();
+
+ der.start_cons(SEQUENCE);
+
+ if(dn_bits.has_items())
+ der.raw_bytes(dn_bits);
+ else
+ {
+ do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country", true);
+ do_ava(der, dn_info, DIRECTORY_STRING, "X520.State");
+ do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality");
+ do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization");
+ do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit");
+ do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName", true);
+ do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber");
+ }
+
+ der.end_cons();
+ }
+
+/*
+* Decode a BER encoded DistinguishedName
+*/
+void X509_DN::decode_from(BER_Decoder& source)
+ {
+ dn_info.clear();
+
+ source.start_cons(SEQUENCE)
+ .raw_bytes(dn_bits)
+ .end_cons();
+
+ do_decode(dn_bits);
+ }
+
+}
diff --git a/botan/src/asn1/asn1_int.cpp b/botan/src/asn1/asn1_int.cpp
new file mode 100644
index 0000000..5e18f39
--- /dev/null
+++ b/botan/src/asn1/asn1_int.cpp
@@ -0,0 +1,68 @@
+/*
+* ASN.1 Internals
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_int.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/data_src.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* BER Decoding Exceptions
+*/
+BER_Decoding_Error::BER_Decoding_Error(const std::string& str) :
+ Decoding_Error("BER: " + str) {}
+
+BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) :
+ BER_Decoding_Error(str + ": " + to_string(tag)) {}
+
+BER_Bad_Tag::BER_Bad_Tag(const std::string& str,
+ ASN1_Tag tag1, ASN1_Tag tag2) :
+ BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {}
+
+namespace ASN1 {
+
+/*
+* Put some arbitrary bytes into a SEQUENCE
+*/
+SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& contents)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .raw_bytes(contents)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Convert a BER object into a string object
+*/
+std::string to_string(const BER_Object& obj)
+ {
+ return std::string(reinterpret_cast<const char*>(obj.value.begin()),
+ obj.value.size());
+ }
+
+/*
+* Do heuristic tests for BER data
+*/
+bool maybe_BER(DataSource& source)
+ {
+ byte first_byte;
+ if(!source.peek_byte(first_byte))
+ throw Stream_IO_Error("ASN1::maybe_BER: Source was empty");
+
+ if(first_byte == (SEQUENCE | CONSTRUCTED))
+ return true;
+ return false;
+ }
+
+}
+
+}
diff --git a/botan/src/asn1/asn1_int.h b/botan/src/asn1/asn1_int.h
new file mode 100644
index 0000000..619f45b
--- /dev/null
+++ b/botan/src/asn1/asn1_int.h
@@ -0,0 +1,108 @@
+/*
+* ASN.1 Internals
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_H__
+#define BOTAN_ASN1_H__
+
+#include <botan/secmem.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* ASN.1 Type and Class Tags
+*/
+enum ASN1_Tag {
+ UNIVERSAL = 0x00,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xC0,
+
+ CONSTRUCTED = 0x20,
+
+ EOC = 0x00,
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ NULL_TAG = 0x05,
+ OBJECT_ID = 0x06,
+ ENUMERATED = 0x0A,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+
+ UTF8_STRING = 0x0C,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ IA5_STRING = 0x16,
+ VISIBLE_STRING = 0x1A,
+ BMP_STRING = 0x1E,
+
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+
+ NO_OBJECT = 0xFF00,
+ DIRECTORY_STRING = 0xFF01
+};
+
+/*
+* Basic ASN.1 Object Interface
+*/
+class BOTAN_DLL ASN1_Object
+ {
+ public:
+ virtual void encode_into(class DER_Encoder&) const = 0;
+ virtual void decode_from(class BER_Decoder&) = 0;
+ virtual ~ASN1_Object() {}
+ };
+
+/*
+* BER Encoded Object
+*/
+class BOTAN_DLL BER_Object
+ {
+ public:
+ void assert_is_a(ASN1_Tag, ASN1_Tag);
+
+ ASN1_Tag type_tag, class_tag;
+ SecureVector<byte> value;
+ };
+
+/*
+* ASN.1 Utility Functions
+*/
+class DataSource;
+
+namespace ASN1 {
+
+SecureVector<byte> put_in_sequence(const MemoryRegion<byte>&);
+std::string to_string(const BER_Object&);
+bool maybe_BER(DataSource&);
+
+}
+
+/*
+* General BER Decoding Error Exception
+*/
+struct BER_Decoding_Error : public Decoding_Error
+ {
+ BER_Decoding_Error(const std::string&);
+ };
+
+/*
+* Exception For Incorrect BER Taggings
+*/
+struct BER_Bad_Tag : public BER_Decoding_Error
+ {
+ BER_Bad_Tag(const std::string&, ASN1_Tag);
+ BER_Bad_Tag(const std::string&, ASN1_Tag, ASN1_Tag);
+ };
+
+}
+
+#endif
diff --git a/botan/src/asn1/asn1_obj.h b/botan/src/asn1/asn1_obj.h
new file mode 100644
index 0000000..ea21c47
--- /dev/null
+++ b/botan/src/asn1/asn1_obj.h
@@ -0,0 +1,160 @@
+/*
+* Common ASN.1 Objects
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_OBJ_H__
+#define BOTAN_ASN1_OBJ_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <botan/alg_id.h>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*
+* Attribute
+*/
+class BOTAN_DLL Attribute : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ OID oid;
+ MemoryVector<byte> parameters;
+
+ Attribute() {}
+ Attribute(const OID&, const MemoryRegion<byte>&);
+ Attribute(const std::string&, const MemoryRegion<byte>&);
+ };
+
+/*
+* X.509 Time
+*/
+class BOTAN_DLL X509_Time : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::string as_string() const;
+ std::string readable_string() const;
+ bool time_is_set() const;
+
+ s32bit cmp(const X509_Time&) const;
+
+ void set_to(const std::string&);
+ void set_to(const std::string&, ASN1_Tag);
+
+ X509_Time(u64bit);
+ X509_Time(const std::string& = "");
+ X509_Time(const std::string&, ASN1_Tag);
+ private:
+ bool passes_sanity_check() const;
+ u32bit year, month, day, hour, minute, second;
+ ASN1_Tag tag;
+ };
+
+/*
+* Simple String
+*/
+class BOTAN_DLL ASN1_String : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::string value() const;
+ std::string iso_8859() const;
+
+ ASN1_Tag tagging() const;
+
+ ASN1_String(const std::string& = "");
+ ASN1_String(const std::string&, ASN1_Tag);
+ private:
+ std::string iso_8859_str;
+ ASN1_Tag tag;
+ };
+
+/*
+* Distinguished Name
+*/
+class BOTAN_DLL X509_DN : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::multimap<OID, std::string> get_attributes() const;
+ std::vector<std::string> get_attribute(const std::string&) const;
+
+ std::multimap<std::string, std::string> contents() const;
+
+ void add_attribute(const std::string&, const std::string&);
+ void add_attribute(const OID&, const std::string&);
+
+ static std::string deref_info_field(const std::string&);
+
+ void do_decode(const MemoryRegion<byte>&);
+ MemoryVector<byte> get_bits() const;
+
+ X509_DN();
+ X509_DN(const std::multimap<OID, std::string>&);
+ X509_DN(const std::multimap<std::string, std::string>&);
+ private:
+ std::multimap<OID, ASN1_String> dn_info;
+ MemoryVector<byte> dn_bits;
+ };
+
+/*
+* Alternative Name
+*/
+class BOTAN_DLL AlternativeName : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ std::multimap<std::string, std::string> contents() const;
+
+ void add_attribute(const std::string&, const std::string&);
+ std::multimap<std::string, std::string> get_attributes() const;
+
+ void add_othername(const OID&, const std::string&, ASN1_Tag);
+ std::multimap<OID, ASN1_String> get_othernames() const;
+
+ bool has_items() const;
+
+ AlternativeName(const std::string& = "", const std::string& = "",
+ const std::string& = "", const std::string& = "");
+ private:
+ std::multimap<std::string, std::string> alt_info;
+ std::multimap<OID, ASN1_String> othernames;
+ };
+
+/*
+* Comparison Operations
+*/
+bool BOTAN_DLL operator==(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator!=(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator<=(const X509_Time&, const X509_Time&);
+bool BOTAN_DLL operator>=(const X509_Time&, const X509_Time&);
+
+bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&);
+bool BOTAN_DLL operator!=(const X509_DN&, const X509_DN&);
+bool BOTAN_DLL operator<(const X509_DN&, const X509_DN&);
+
+/*
+* Helper Functions
+*/
+bool BOTAN_DLL is_string_type(ASN1_Tag);
+
+}
+
+#endif
diff --git a/botan/src/asn1/asn1_oid.cpp b/botan/src/asn1/asn1_oid.cpp
new file mode 100644
index 0000000..531ceb9
--- /dev/null
+++ b/botan/src/asn1/asn1_oid.cpp
@@ -0,0 +1,176 @@
+/*
+* ASN.1 OID
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_oid.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bit_ops.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* ASN.1 OID Constructor
+*/
+OID::OID(const std::string& oid_str)
+ {
+ if(oid_str != "")
+ {
+ id = parse_asn1_oid(oid_str);
+ if(id.size() < 2 || id[0] > 2)
+ throw Invalid_OID(oid_str);
+ if((id[0] == 0 || id[0] == 1) && id[1] > 39)
+ throw Invalid_OID(oid_str);
+ }
+ }
+
+/*
+* Clear the current OID
+*/
+void OID::clear()
+ {
+ id.clear();
+ }
+
+/*
+* Return this OID as a string
+*/
+std::string OID::as_string() const
+ {
+ std::string oid_str;
+ for(u32bit j = 0; j != id.size(); ++j)
+ {
+ oid_str += to_string(id[j]);
+ if(j != id.size() - 1)
+ oid_str += '.';
+ }
+ return oid_str;
+ }
+
+/*
+* OID equality comparison
+*/
+bool OID::operator==(const OID& oid) const
+ {
+ if(id.size() != oid.id.size())
+ return false;
+ for(u32bit j = 0; j != id.size(); ++j)
+ if(id[j] != oid.id[j])
+ return false;
+ return true;
+ }
+
+/*
+* Append another component to the OID
+*/
+OID& OID::operator+=(u32bit component)
+ {
+ id.push_back(component);
+ return (*this);
+ }
+
+/*
+* Append another component to the OID
+*/
+OID operator+(const OID& oid, u32bit component)
+ {
+ OID new_oid(oid);
+ new_oid += component;
+ return new_oid;
+ }
+
+/*
+* OID inequality comparison
+*/
+bool operator!=(const OID& a, const OID& b)
+ {
+ return !(a == b);
+ }
+
+/*
+* Compare two OIDs
+*/
+bool operator<(const OID& a, const OID& b)
+ {
+ std::vector<u32bit> oid1 = a.get_id();
+ std::vector<u32bit> oid2 = b.get_id();
+
+ if(oid1.size() < oid2.size())
+ return true;
+ if(oid1.size() > oid2.size())
+ return false;
+ for(u32bit j = 0; j != oid1.size(); ++j)
+ {
+ if(oid1[j] < oid2[j])
+ return true;
+ if(oid1[j] > oid2[j])
+ return false;
+ }
+ return false;
+ }
+
+/*
+* DER encode an OBJECT IDENTIFIER
+*/
+void OID::encode_into(DER_Encoder& der) const
+ {
+ if(id.size() < 2)
+ throw Invalid_Argument("OID::encode_into: OID is invalid");
+
+ MemoryVector<byte> encoding;
+ encoding.append(40 * id[0] + id[1]);
+
+ for(u32bit j = 2; j != id.size(); ++j)
+ {
+ if(id[j] == 0)
+ encoding.append(0);
+ else
+ {
+ u32bit blocks = high_bit(id[j]) + 6;
+ blocks = (blocks - (blocks % 7)) / 7;
+
+ for(u32bit k = 0; k != blocks - 1; ++k)
+ encoding.append(0x80 | ((id[j] >> 7*(blocks-k-1)) & 0x7F));
+ encoding.append(id[j] & 0x7F);
+ }
+ }
+ der.add_object(OBJECT_ID, UNIVERSAL, encoding);
+ }
+
+/*
+* Decode a BER encoded OBJECT IDENTIFIER
+*/
+void OID::decode_from(BER_Decoder& decoder)
+ {
+ BER_Object obj = decoder.get_next_object();
+ if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL)
+ throw BER_Bad_Tag("Error decoding OID, unknown tag",
+ obj.type_tag, obj.class_tag);
+ if(obj.value.size() < 2)
+ throw BER_Decoding_Error("OID encoding is too short");
+
+
+ clear();
+ id.push_back(obj.value[0] / 40);
+ id.push_back(obj.value[0] % 40);
+
+ u32bit j = 0;
+ while(j != obj.value.size() - 1)
+ {
+ u32bit component = 0;
+ while(j != obj.value.size() - 1)
+ {
+ ++j;
+ component = (component << 7) + (obj.value[j] & 0x7F);
+ if(!(obj.value[j] & 0x80))
+ break;
+ }
+ id.push_back(component);
+ }
+ }
+
+}
diff --git a/botan/src/asn1/asn1_oid.h b/botan/src/asn1/asn1_oid.h
new file mode 100644
index 0000000..e6d077b
--- /dev/null
+++ b/botan/src/asn1/asn1_oid.h
@@ -0,0 +1,96 @@
+/*
+* ASN.1 OID
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ASN1_OID_H__
+#define BOTAN_ASN1_OID_H__
+
+#include <botan/asn1_int.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents ASN.1 object identifiers.
+*/
+class BOTAN_DLL OID : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Find out whether this OID is empty
+ * @return true is no OID value is set
+ */
+ bool is_empty() const { return id.size() == 0; }
+
+ /**
+ * Get this OID as list (vector) of its components.
+ * @return a vector representing this OID
+ */
+ std::vector<u32bit> get_id() const { return id; }
+
+ /**
+ * Get this OID as a string
+ * @return a string representing this OID
+ */
+ std::string as_string() const;
+
+ /**
+ * Compare two OIDs.
+ * @return true if they are equal, false otherwise
+ */
+ bool operator==(const OID&) const;
+
+ /**
+ * Reset this instance to an empty OID.
+ */
+ void clear();
+
+ /**
+ * Add a component to this OID.
+ * @param new_comp the new component to add to the end of this OID
+ * @return a reference to *this
+ */
+ OID& operator+=(u32bit new_comp);
+
+ /**
+ * Construct an OID from a string.
+ * @param str a string in the form "a.b.c" etc., where a,b,c are numbers
+ */
+ OID(const std::string& str = "");
+ private:
+ std::vector<u32bit> id;
+ };
+
+/**
+* Append another component onto the OID.
+* @param oid the OID to add the new component to
+* @param new_comp the new component to add
+*/
+OID operator+(const OID& oid, u32bit new_comp);
+
+/**
+* Compare two OIDs.
+* @param a the first OID
+* @param b the second OID
+* @return true if a is not equal to b
+*/
+bool operator!=(const OID& a, const OID& b);
+
+/**
+* Compare two OIDs.
+* @param a the first OID
+* @param b the second OID
+* @return true if a is lexicographically smaller than b
+*/
+bool operator<(const OID& a, const OID& b);
+
+}
+
+#endif
diff --git a/botan/src/asn1/asn1_str.cpp b/botan/src/asn1/asn1_str.cpp
new file mode 100644
index 0000000..25782e2
--- /dev/null
+++ b/botan/src/asn1/asn1_str.cpp
@@ -0,0 +1,160 @@
+/*
+* Simple ASN.1 String Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Choose an encoding for the string
+*/
+ASN1_Tag choose_encoding(const std::string& str,
+ const std::string& type)
+ {
+ static const byte IS_PRINTABLE[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+
+ for(u32bit j = 0; j != str.size(); ++j)
+ {
+ if(!IS_PRINTABLE[static_cast<byte>(str[j])])
+ {
+ if(type == "utf8") return UTF8_STRING;
+ if(type == "latin1") return T61_STRING;
+ throw Invalid_Argument("choose_encoding: Bad string type " + type);
+ }
+ }
+ return PRINTABLE_STRING;
+ }
+
+}
+
+/*
+* Check if type is a known ASN.1 string type
+*/
+bool is_string_type(ASN1_Tag tag)
+ {
+ if(tag == NUMERIC_STRING || tag == PRINTABLE_STRING ||
+ tag == VISIBLE_STRING || tag == T61_STRING || tag == IA5_STRING ||
+ tag == UTF8_STRING || tag == BMP_STRING)
+ return true;
+ return false;
+ }
+
+/*
+* Create an ASN1_String
+*/
+ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t)
+ {
+ iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET);
+
+ if(tag == DIRECTORY_STRING)
+ tag = choose_encoding(iso_8859_str, "latin1");
+
+ if(tag != NUMERIC_STRING &&
+ tag != PRINTABLE_STRING &&
+ tag != VISIBLE_STRING &&
+ tag != T61_STRING &&
+ tag != IA5_STRING &&
+ tag != UTF8_STRING &&
+ tag != BMP_STRING)
+ throw Invalid_Argument("ASN1_String: Unknown string type " +
+ to_string(tag));
+ }
+
+/*
+* Create an ASN1_String
+*/
+ASN1_String::ASN1_String(const std::string& str)
+ {
+ iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET);
+ tag = choose_encoding(iso_8859_str, "latin1");
+ }
+
+/*
+* Return this string in ISO 8859-1 encoding
+*/
+std::string ASN1_String::iso_8859() const
+ {
+ return iso_8859_str;
+ }
+
+/*
+* Return this string in local encoding
+*/
+std::string ASN1_String::value() const
+ {
+ return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET);
+ }
+
+/*
+* Return the type of this string object
+*/
+ASN1_Tag ASN1_String::tagging() const
+ {
+ return tag;
+ }
+
+/*
+* DER encode an ASN1_String
+*/
+void ASN1_String::encode_into(DER_Encoder& encoder) const
+ {
+ std::string value = iso_8859();
+ if(tagging() == UTF8_STRING)
+ value = Charset::transcode(value, LATIN1_CHARSET, UTF8_CHARSET);
+ encoder.add_object(tagging(), UNIVERSAL, value);
+ }
+
+/*
+* Decode a BER encoded ASN1_String
+*/
+void ASN1_String::decode_from(BER_Decoder& source)
+ {
+ BER_Object obj = source.get_next_object();
+
+ Character_Set charset_is;
+
+ if(obj.type_tag == BMP_STRING)
+ charset_is = UCS2_CHARSET;
+ else if(obj.type_tag == UTF8_STRING)
+ charset_is = UTF8_CHARSET;
+ else
+ charset_is = LATIN1_CHARSET;
+
+ *this = ASN1_String(
+ Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET),
+ obj.type_tag);
+ }
+
+}
diff --git a/botan/src/asn1/asn1_tm.cpp b/botan/src/asn1/asn1_tm.cpp
new file mode 100644
index 0000000..f85ea12
--- /dev/null
+++ b/botan/src/asn1/asn1_tm.cpp
@@ -0,0 +1,297 @@
+/*
+* X.509 Time Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <ctime>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Convert a time_t to a struct tm
+*/
+std::tm get_tm(u64bit timer)
+ {
+ std::time_t time_val = static_cast<std::time_t>(timer);
+
+ std::tm* tm_p = std::gmtime(&time_val);
+ if(tm_p == 0)
+ throw Encoding_Error("X509_Time: gmtime could not encode " +
+ to_string(timer));
+ return (*tm_p);
+ }
+
+}
+
+/*
+* Create an X509_Time
+*/
+X509_Time::X509_Time(const std::string& time_str)
+ {
+ set_to(time_str);
+ }
+
+/*
+* Create an X509_Time
+*/
+X509_Time::X509_Time(u64bit timer)
+ {
+ std::tm time_info = get_tm(timer);
+
+ year = time_info.tm_year + 1900;
+ month = time_info.tm_mon + 1;
+ day = time_info.tm_mday;
+ hour = time_info.tm_hour;
+ minute = time_info.tm_min;
+ second = time_info.tm_sec;
+
+ if(year >= 2050)
+ tag = GENERALIZED_TIME;
+ else
+ tag = UTC_TIME;
+ }
+
+/*
+* Create an X509_Time
+*/
+X509_Time::X509_Time(const std::string& t_spec, ASN1_Tag t) : tag(t)
+ {
+ set_to(t_spec, tag);
+ }
+
+/*
+* Set the time with a human readable string
+*/
+void X509_Time::set_to(const std::string& time_str)
+ {
+ if(time_str == "")
+ {
+ year = month = day = hour = minute = second = 0;
+ return;
+ }
+
+ std::vector<std::string> params;
+ std::string current;
+
+ for(u32bit j = 0; j != time_str.size(); ++j)
+ {
+ if(Charset::is_digit(time_str[j]))
+ current += time_str[j];
+ else
+ {
+ if(current != "")
+ params.push_back(current);
+ current.clear();
+ }
+ }
+ if(current != "")
+ params.push_back(current);
+
+ if(params.size() < 3 || params.size() > 6)
+ throw Invalid_Argument("Invalid time specification " + time_str);
+
+ year = to_u32bit(params[0]);
+ month = to_u32bit(params[1]);
+ day = to_u32bit(params[2]);
+ hour = (params.size() >= 4) ? to_u32bit(params[3]) : 0;
+ minute = (params.size() >= 5) ? to_u32bit(params[4]) : 0;
+ second = (params.size() == 6) ? to_u32bit(params[5]) : 0;
+
+ if(year >= 2050)
+ tag = GENERALIZED_TIME;
+ else
+ tag = UTC_TIME;
+
+ if(!passes_sanity_check())
+ throw Invalid_Argument("Invalid time specification " + time_str);
+ }
+
+/*
+* Set the time with an ISO time format string
+*/
+void X509_Time::set_to(const std::string& t_spec, ASN1_Tag tag)
+ {
+ if(tag != GENERALIZED_TIME && tag != UTC_TIME)
+ throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag));
+ if(tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15)
+ throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec);
+ if(tag == UTC_TIME && t_spec.size() != 11 && t_spec.size() != 13)
+ throw Invalid_Argument("Invalid UTCTime: " + t_spec);
+ if(t_spec[t_spec.size()-1] != 'Z')
+ throw Invalid_Argument("Invalid time encoding: " + t_spec);
+
+ const u32bit YEAR_SIZE = (tag == UTC_TIME) ? 2 : 4;
+
+ std::vector<std::string> params;
+ std::string current;
+
+ for(u32bit j = 0; j != YEAR_SIZE; ++j)
+ current += t_spec[j];
+ params.push_back(current);
+ current.clear();
+
+ for(u32bit j = YEAR_SIZE; j != t_spec.size() - 1; ++j)
+ {
+ current += t_spec[j];
+ if(current.size() == 2)
+ {
+ params.push_back(current);
+ current.clear();
+ }
+ }
+
+ year = to_u32bit(params[0]);
+ month = to_u32bit(params[1]);
+ day = to_u32bit(params[2]);
+ hour = to_u32bit(params[3]);
+ minute = to_u32bit(params[4]);
+ second = (params.size() == 6) ? to_u32bit(params[5]) : 0;
+
+ if(tag == UTC_TIME)
+ {
+ if(year >= 50) year += 1900;
+ else year += 2000;
+ }
+
+ if(!passes_sanity_check())
+ throw Invalid_Argument("Invalid time specification " + t_spec);
+ }
+
+/*
+* DER encode a X509_Time
+*/
+void X509_Time::encode_into(DER_Encoder& der) const
+ {
+ if(tag != GENERALIZED_TIME && tag != UTC_TIME)
+ throw Invalid_Argument("X509_Time: Bad encoding tag");
+ der.add_object(tag, UNIVERSAL,
+ Charset::transcode(as_string(),
+ LOCAL_CHARSET, LATIN1_CHARSET));
+ }
+
+/*
+* Decode a BER encoded X509_Time
+*/
+void X509_Time::decode_from(BER_Decoder& source)
+ {
+ BER_Object ber_time = source.get_next_object();
+ set_to(Charset::transcode(ASN1::to_string(ber_time),
+ LATIN1_CHARSET, LOCAL_CHARSET),
+ ber_time.type_tag);
+ }
+
+/*
+* Return a string representation of the time
+*/
+std::string X509_Time::as_string() const
+ {
+ if(time_is_set() == false)
+ throw Invalid_State("X509_Time::as_string: No time set");
+
+ std::string asn1rep;
+ if(tag == GENERALIZED_TIME)
+ asn1rep = to_string(year, 4);
+ else
+ {
+ if(year < 1950 || year >= 2050)
+ throw Encoding_Error("X509_Time: The time " + readable_string() +
+ " cannot be encoded as a UTCTime");
+ u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900);
+ asn1rep = to_string(asn1year, 2);
+ }
+ asn1rep += to_string(month, 2) + to_string(day, 2);
+ asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2);
+ asn1rep += "Z";
+ return asn1rep;
+ }
+
+/*
+* Return if the time has been set somehow
+*/
+bool X509_Time::time_is_set() const
+ {
+ return (year != 0);
+ }
+
+/*
+* Return a human readable string representation
+*/
+std::string X509_Time::readable_string() const
+ {
+ if(time_is_set() == false)
+ throw Invalid_State("X509_Time::readable_string: No time set");
+
+ std::string readable;
+ readable += to_string(year, 4) + "/";
+ readable += to_string(month ) + "/";
+ readable += to_string(day ) + " ";
+ readable += to_string(hour ) + ":";
+ readable += to_string(minute, 2) + ":";
+ readable += to_string(second, 2) + " UTC";
+ return readable;
+ }
+
+/*
+* Do a general sanity check on the time
+*/
+bool X509_Time::passes_sanity_check() const
+ {
+ if(year < 1950 || year > 2100)
+ return false;
+ if(month == 0 || month > 12)
+ return false;
+ if(day == 0 || day > 31)
+ return false;
+ if(hour >= 24 || minute > 60 || second > 60)
+ return false;
+ return true;
+ }
+
+/*
+* Compare this time against another
+*/
+s32bit X509_Time::cmp(const X509_Time& other) const
+ {
+ if(time_is_set() == false)
+ throw Invalid_State("X509_Time::cmp: No time set");
+
+ const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
+
+ if(year < other.year) return EARLIER;
+ if(year > other.year) return LATER;
+ if(month < other.month) return EARLIER;
+ if(month > other.month) return LATER;
+ if(day < other.day) return EARLIER;
+ if(day > other.day) return LATER;
+ if(hour < other.hour) return EARLIER;
+ if(hour > other.hour) return LATER;
+ if(minute < other.minute) return EARLIER;
+ if(minute > other.minute) return LATER;
+ if(second < other.second) return EARLIER;
+ if(second > other.second) return LATER;
+
+ return SAME_TIME;
+ }
+
+/*
+* Compare two X509_Times for in various ways
+*/
+bool operator==(const X509_Time& t1, const X509_Time& t2)
+ { return (t1.cmp(t2) == 0); }
+bool operator!=(const X509_Time& t1, const X509_Time& t2)
+ { return (t1.cmp(t2) != 0); }
+bool operator<=(const X509_Time& t1, const X509_Time& t2)
+ { return (t1.cmp(t2) <= 0); }
+bool operator>=(const X509_Time& t1, const X509_Time& t2)
+ { return (t1.cmp(t2) >= 0); }
+
+}
diff --git a/botan/src/asn1/ber_dec.cpp b/botan/src/asn1/ber_dec.cpp
new file mode 100644
index 0000000..ce60466
--- /dev/null
+++ b/botan/src/asn1/ber_dec.cpp
@@ -0,0 +1,471 @@
+/*
+* BER Decoder
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* BER decode an ASN.1 type tag
+*/
+u32bit decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag)
+ {
+ byte b;
+ if(!ber->read_byte(b))
+ {
+ class_tag = type_tag = NO_OBJECT;
+ return 0;
+ }
+
+ if((b & 0x1F) != 0x1F)
+ {
+ type_tag = ASN1_Tag(b & 0x1F);
+ class_tag = ASN1_Tag(b & 0xE0);
+ return 1;
+ }
+
+ u32bit tag_bytes = 1;
+ class_tag = ASN1_Tag(b & 0xE0);
+
+ u32bit tag_buf = 0;
+ while(true)
+ {
+ if(!ber->read_byte(b))
+ throw BER_Decoding_Error("Long-form tag truncated");
+ if(tag_buf & 0xFF000000)
+ throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
+ ++tag_bytes;
+ tag_buf = (tag_buf << 7) | (b & 0x7F);
+ if((b & 0x80) == 0) break;
+ }
+ type_tag = ASN1_Tag(tag_buf);
+ return tag_bytes;
+ }
+
+/*
+* Find the EOC marker
+*/
+u32bit find_eoc(DataSource*);
+
+/*
+* BER decode an ASN.1 length field
+*/
+u32bit decode_length(DataSource* ber, u32bit& field_size)
+ {
+ byte b;
+ if(!ber->read_byte(b))
+ throw BER_Decoding_Error("Length field not found");
+ field_size = 1;
+ if((b & 0x80) == 0)
+ return b;
+
+ field_size += (b & 0x7F);
+ if(field_size == 1) return find_eoc(ber);
+ if(field_size > 5)
+ throw BER_Decoding_Error("Length field is too large");
+
+ u32bit length = 0;
+
+ for(u32bit j = 0; j != field_size - 1; ++j)
+ {
+ if(get_byte(0, length) != 0)
+ throw BER_Decoding_Error("Field length overflow");
+ if(!ber->read_byte(b))
+ throw BER_Decoding_Error("Corrupted length field");
+ length = (length << 8) | b;
+ }
+ return length;
+ }
+
+/*
+* BER decode an ASN.1 length field
+*/
+u32bit decode_length(DataSource* ber)
+ {
+ u32bit dummy;
+ return decode_length(ber, dummy);
+ }
+
+/*
+* Find the EOC marker
+*/
+u32bit find_eoc(DataSource* ber)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data;
+
+ while(true)
+ {
+ const u32bit got = ber->peek(buffer, buffer.size(), data.size());
+ if(got == 0)
+ break;
+ data.append(buffer, got);
+ }
+
+ DataSource_Memory source(data);
+ data.destroy();
+
+ u32bit length = 0;
+ while(true)
+ {
+ ASN1_Tag type_tag, class_tag;
+ u32bit tag_size = decode_tag(&source, type_tag, class_tag);
+ if(type_tag == NO_OBJECT)
+ break;
+
+ u32bit length_size = 0;
+ u32bit item_size = decode_length(&source, length_size);
+ source.discard_next(item_size);
+
+ length += item_size + length_size + tag_size;
+
+ if(type_tag == EOC)
+ break;
+ }
+ return length;
+ }
+
+}
+
+/*
+* Check a type invariant on BER data
+*/
+void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if(this->type_tag != type_tag || this->class_tag != class_tag)
+ throw BER_Decoding_Error("Tag mismatch when decoding");
+ }
+
+/*
+* Check if more objects are there
+*/
+bool BER_Decoder::more_items() const
+ {
+ if(source->end_of_data() && (pushed.type_tag == NO_OBJECT))
+ return false;
+ return true;
+ }
+
+/*
+* Verify that no bytes remain in the source
+*/
+BER_Decoder& BER_Decoder::verify_end()
+ {
+ if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT))
+ throw Invalid_State("BER_Decoder::verify_end called, but data remains");
+ return (*this);
+ }
+
+/*
+* Save all the bytes remaining in the source
+*/
+BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out)
+ {
+ out.destroy();
+ byte buf;
+ while(source->read_byte(buf))
+ out.append(buf);
+ return (*this);
+ }
+
+/*
+* Discard all the bytes remaining in the source
+*/
+BER_Decoder& BER_Decoder::discard_remaining()
+ {
+ byte buf;
+ while(source->read_byte(buf))
+ ;
+ return (*this);
+ }
+
+/*
+* Return the BER encoding of the next object
+*/
+BER_Object BER_Decoder::get_next_object()
+ {
+ BER_Object next;
+
+ if(pushed.type_tag != NO_OBJECT)
+ {
+ next = pushed;
+ pushed.class_tag = pushed.type_tag = NO_OBJECT;
+ return next;
+ }
+
+ decode_tag(source, next.type_tag, next.class_tag);
+ if(next.type_tag == NO_OBJECT)
+ return next;
+
+ u32bit length = decode_length(source);
+ next.value.create(length);
+ if(source->read(next.value, length) != length)
+ throw BER_Decoding_Error("Value truncated");
+
+ if(next.type_tag == EOC && next.class_tag == UNIVERSAL)
+ return get_next_object();
+
+ return next;
+ }
+
+/*
+* Push a object back into the stream
+*/
+void BER_Decoder::push_back(const BER_Object& obj)
+ {
+ if(pushed.type_tag != NO_OBJECT)
+ throw Invalid_State("BER_Decoder: Only one push back is allowed");
+ pushed = obj;
+ }
+
+/*
+* Begin decoding a CONSTRUCTED type
+*/
+BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag,
+ ASN1_Tag class_tag)
+ {
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED));
+
+ BER_Decoder result(obj.value, obj.value.size());
+ result.parent = this;
+ return result;
+ }
+
+/*
+* Finish decoding a CONSTRUCTED type
+*/
+BER_Decoder& BER_Decoder::end_cons()
+ {
+ if(!parent)
+ throw Invalid_State("BER_Decoder::end_cons called with NULL parent");
+ if(!source->end_of_data())
+ throw Decoding_Error("BER_Decoder::end_cons called with data left");
+ return (*parent);
+ }
+
+/*
+* BER_Decoder Constructor
+*/
+BER_Decoder::BER_Decoder(DataSource& src)
+ {
+ source = &src;
+ owns = false;
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = 0;
+ }
+
+/*
+* BER_Decoder Constructor
+ */
+BER_Decoder::BER_Decoder(const byte data[], u32bit length)
+ {
+ source = new DataSource_Memory(data, length);
+ owns = true;
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = 0;
+ }
+
+/*
+* BER_Decoder Constructor
+*/
+BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data)
+ {
+ source = new DataSource_Memory(data);
+ owns = true;
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = 0;
+ }
+
+/*
+* BER_Decoder Copy Constructor
+*/
+BER_Decoder::BER_Decoder(const BER_Decoder& other)
+ {
+ source = other.source;
+ owns = false;
+ if(other.owns)
+ {
+ other.owns = false;
+ owns = true;
+ }
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = other.parent;
+ }
+
+/*
+* BER_Decoder Destructor
+*/
+BER_Decoder::~BER_Decoder()
+ {
+ if(owns)
+ delete source;
+ source = 0;
+ }
+
+/*
+* Request for an object to decode itself
+*/
+BER_Decoder& BER_Decoder::decode(ASN1_Object& obj)
+ {
+ obj.decode_from(*this);
+ return (*this);
+ }
+
+/*
+* Decode a BER encoded NULL
+*/
+BER_Decoder& BER_Decoder::decode_null()
+ {
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(NULL_TAG, UNIVERSAL);
+ if(obj.value.size())
+ throw BER_Decoding_Error("NULL object had nonzero size");
+ return (*this);
+ }
+
+/*
+* Decode a BER encoded BOOLEAN
+*/
+BER_Decoder& BER_Decoder::decode(bool& out)
+ {
+ return decode(out, BOOLEAN, UNIVERSAL);
+ }
+
+/*
+* Decode a small BER encoded INTEGER
+*/
+BER_Decoder& BER_Decoder::decode(u32bit& out)
+ {
+ return decode(out, INTEGER, UNIVERSAL);
+ }
+
+/*
+* Decode a BER encoded INTEGER
+*/
+BER_Decoder& BER_Decoder::decode(BigInt& out)
+ {
+ return decode(out, INTEGER, UNIVERSAL);
+ }
+
+/*
+* Decode a BER encoded BOOLEAN
+*/
+BER_Decoder& BER_Decoder::decode(bool& out,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(type_tag, class_tag);
+
+ if(obj.value.size() != 1)
+ throw BER_Decoding_Error("BER boolean value had invalid size");
+
+ out = (obj.value[0]) ? true : false;
+ return (*this);
+ }
+
+/*
+* Decode a small BER encoded INTEGER
+*/
+BER_Decoder& BER_Decoder::decode(u32bit& out,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ BigInt integer;
+ decode(integer, type_tag, class_tag);
+ out = integer.to_u32bit();
+ return (*this);
+ }
+
+/*
+* Decode a BER encoded INTEGER
+*/
+BER_Decoder& BER_Decoder::decode(BigInt& out,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(type_tag, class_tag);
+
+ if(obj.value.is_empty())
+ out = 0;
+ else
+ {
+ const bool negative = (obj.value[0] & 0x80) ? true : false;
+
+ if(negative)
+ {
+ for(u32bit j = obj.value.size(); j > 0; --j)
+ if(obj.value[j-1]--)
+ break;
+ for(u32bit j = 0; j != obj.value.size(); ++j)
+ obj.value[j] = ~obj.value[j];
+ }
+
+ out = BigInt(obj.value, obj.value.size());
+
+ if(negative)
+ out.flip_sign();
+ }
+
+ return (*this);
+ }
+
+/*
+* BER decode a BIT STRING or OCTET STRING
+*/
+BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
+ {
+ return decode(out, real_type, real_type, UNIVERSAL);
+ }
+
+/*
+* BER decode a BIT STRING or OCTET STRING
+*/
+BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if(real_type != OCTET_STRING && real_type != BIT_STRING)
+ throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);
+
+ BER_Object obj = get_next_object();
+ obj.assert_is_a(type_tag, class_tag);
+
+ if(real_type == OCTET_STRING)
+ buffer = obj.value;
+ else
+ {
+ if(obj.value[0] >= 8)
+ throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
+ buffer.set(obj.value + 1, obj.value.size() - 1);
+ }
+ return (*this);
+ }
+
+/*
+* Decode an OPTIONAL string type
+*/
+BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out,
+ ASN1_Tag real_type,
+ u16bit type_no)
+ {
+ BER_Object obj = get_next_object();
+
+ ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);
+
+ out.clear();
+ push_back(obj);
+
+ if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC)
+ decode(out, real_type, type_tag, CONTEXT_SPECIFIC);
+
+ return (*this);
+ }
+
+}
diff --git a/botan/src/asn1/ber_dec.h b/botan/src/asn1/ber_dec.h
new file mode 100644
index 0000000..2e38af3
--- /dev/null
+++ b/botan/src/asn1/ber_dec.h
@@ -0,0 +1,122 @@
+/*
+* BER Decoder
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BER_DECODER_H__
+#define BOTAN_BER_DECODER_H__
+
+#include <botan/asn1_oid.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/*
+* BER Decoding Object
+*/
+class BOTAN_DLL BER_Decoder
+ {
+ public:
+ BER_Object get_next_object();
+ void push_back(const BER_Object&);
+
+ bool more_items() const;
+ BER_Decoder& verify_end();
+ BER_Decoder& discard_remaining();
+
+ BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
+ BER_Decoder& end_cons();
+
+ BER_Decoder& raw_bytes(MemoryRegion<byte>&);
+
+ BER_Decoder& decode_null();
+ BER_Decoder& decode(bool&);
+ BER_Decoder& decode(u32bit&);
+ BER_Decoder& decode(class BigInt&);
+ BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag);
+
+ BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(u32bit&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(class BigInt&,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+
+ BER_Decoder& decode(class ASN1_Object&);
+
+ template<typename T>
+ BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T());
+
+ template<typename T>
+ BER_Decoder& decode_list(std::vector<T>&, bool = true);
+
+ BER_Decoder& decode_optional_string(MemoryRegion<byte>&,
+ ASN1_Tag, u16bit);
+
+ BER_Decoder(DataSource&);
+ BER_Decoder(const byte[], u32bit);
+ BER_Decoder(const MemoryRegion<byte>&);
+ BER_Decoder(const BER_Decoder&);
+ ~BER_Decoder();
+ private:
+ BER_Decoder& operator=(const BER_Decoder&) { return (*this); }
+
+ BER_Decoder* parent;
+ DataSource* source;
+ BER_Object pushed;
+ mutable bool owns;
+ };
+
+/*
+* Decode an OPTIONAL or DEFAULT element
+*/
+template<typename T>
+BER_Decoder& BER_Decoder::decode_optional(T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ const T& default_value)
+ {
+ BER_Object obj = get_next_object();
+
+ if(obj.type_tag == type_tag && obj.class_tag == class_tag)
+ {
+ if(class_tag & CONSTRUCTED)
+ BER_Decoder(obj.value).decode(out).verify_end();
+ else
+ {
+ push_back(obj);
+ decode(out, type_tag, class_tag);
+ }
+ }
+ else
+ {
+ out = default_value;
+ push_back(obj);
+ }
+
+ return (*this);
+ }
+
+/*
+* Decode a list of homogenously typed values
+*/
+template<typename T>
+BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec, bool clear_it)
+ {
+ if(clear_it)
+ vec.clear();
+
+ while(more_items())
+ {
+ T value;
+ decode(value);
+ vec.push_back(value);
+ }
+ return (*this);
+ }
+
+}
+
+#endif
diff --git a/botan/src/asn1/der_enc.cpp b/botan/src/asn1/der_enc.cpp
new file mode 100644
index 0000000..bee2694
--- /dev/null
+++ b/botan/src/asn1/der_enc.cpp
@@ -0,0 +1,393 @@
+/*
+* DER Encoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/der_enc.h>
+#include <botan/asn1_int.h>
+#include <botan/bigint.h>
+#include <botan/loadstor.h>
+#include <botan/bit_ops.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* DER encode an ASN.1 type tag
+*/
+SecureVector<byte> encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if((class_tag | 0xE0) != 0xE0)
+ throw Encoding_Error("DER_Encoder: Invalid class tag " +
+ to_string(class_tag));
+
+ SecureVector<byte> encoded_tag;
+ if(type_tag <= 30)
+ encoded_tag.append(static_cast<byte>(type_tag | class_tag));
+ else
+ {
+ u32bit blocks = high_bit(type_tag) + 6;
+ blocks = (blocks - (blocks % 7)) / 7;
+
+ encoded_tag.append(class_tag | 0x1F);
+ for(u32bit k = 0; k != blocks - 1; ++k)
+ encoded_tag.append(0x80 | ((type_tag >> 7*(blocks-k-1)) & 0x7F));
+ encoded_tag.append(type_tag & 0x7F);
+ }
+
+ return encoded_tag;
+ }
+
+/*
+* DER encode an ASN.1 length field
+*/
+SecureVector<byte> encode_length(u32bit length)
+ {
+ SecureVector<byte> encoded_length;
+ if(length <= 127)
+ encoded_length.append(static_cast<byte>(length));
+ else
+ {
+ const u32bit top_byte = significant_bytes(length);
+ encoded_length.append(static_cast<byte>(0x80 | top_byte));
+ for(u32bit j = 4-top_byte; j != 4; ++j)
+ encoded_length.append(get_byte(j, length));
+ }
+ return encoded_length;
+ }
+
+}
+
+/*
+* Return the encoded SEQUENCE/SET
+*/
+SecureVector<byte> DER_Encoder::DER_Sequence::get_contents()
+ {
+ const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED);
+
+ SecureVector<byte> encoded_tag = encode_tag(type_tag, real_class_tag);
+
+ if(type_tag == SET)
+ {
+ std::sort(set_contents.begin(), set_contents.end());
+ for(u32bit j = 0; j != set_contents.size(); ++j)
+ contents.append(set_contents[j]);
+ set_contents.clear();
+ }
+
+ SecureVector<byte> encoded_length = encode_length(contents.size());
+
+ SecureVector<byte> retval;
+ retval.append(encoded_tag);
+ retval.append(encoded_length);
+ retval.append(contents);
+ contents.destroy();
+ return retval;
+ }
+
+/*
+* Add an encoded value to the SEQUENCE/SET
+*/
+void DER_Encoder::DER_Sequence::add_bytes(const byte data[], u32bit length)
+ {
+ if(type_tag == SET)
+ set_contents.push_back(SecureVector<byte>(data, length));
+ else
+ contents.append(data, length);
+ }
+
+/*
+* Return the type and class taggings
+*/
+ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const
+ {
+ return ASN1_Tag(type_tag | class_tag);
+ }
+
+/*
+* DER_Sequence Constructor
+*/
+DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) :
+ type_tag(t1), class_tag(t2)
+ {
+ }
+
+/*
+* Return the encoded contents
+*/
+SecureVector<byte> DER_Encoder::get_contents()
+ {
+ if(subsequences.size() != 0)
+ throw Invalid_State("DER_Encoder: Sequence hasn't been marked done");
+
+ SecureVector<byte> retval;
+ retval = contents;
+ contents.destroy();
+ return retval;
+ }
+
+/*
+* Start a new ASN.1 SEQUENCE/SET/EXPLICIT
+*/
+DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag,
+ ASN1_Tag class_tag)
+ {
+ subsequences.push_back(DER_Sequence(type_tag, class_tag));
+ return (*this);
+ }
+
+/*
+* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT
+*/
+DER_Encoder& DER_Encoder::end_cons()
+ {
+ if(subsequences.empty())
+ throw Invalid_State("DER_Encoder::end_cons: No such sequence");
+
+ SecureVector<byte> seq = subsequences[subsequences.size()-1].get_contents();
+ subsequences.pop_back();
+ raw_bytes(seq);
+ return (*this);
+ }
+
+/*
+* Start a new ASN.1 EXPLICIT encoding
+*/
+DER_Encoder& DER_Encoder::start_explicit(u16bit type_no)
+ {
+ ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);
+
+ if(type_tag == SET)
+ throw Internal_Error("DER_Encoder.start_explicit(SET); cannot perform");
+
+ return start_cons(type_tag, CONTEXT_SPECIFIC);
+ }
+
+/*
+* Finish the current ASN.1 EXPLICIT encoding
+*/
+DER_Encoder& DER_Encoder::end_explicit()
+ {
+ return end_cons();
+ }
+
+/*
+* Write raw bytes into the stream
+*/
+DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion<byte>& val)
+ {
+ return raw_bytes(val.begin(), val.size());
+ }
+
+/*
+* Write raw bytes into the stream
+*/
+DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], u32bit length)
+ {
+ if(subsequences.size())
+ subsequences[subsequences.size()-1].add_bytes(bytes, length);
+ else
+ contents.append(bytes, length);
+
+ return (*this);
+ }
+
+/*
+* Encode a NULL object
+*/
+DER_Encoder& DER_Encoder::encode_null()
+ {
+ return add_object(NULL_TAG, UNIVERSAL, 0, 0);
+ }
+
+/*
+* DER encode a BOOLEAN
+*/
+DER_Encoder& DER_Encoder::encode(bool is_true)
+ {
+ return encode(is_true, BOOLEAN, UNIVERSAL);
+ }
+
+/*
+* DER encode a small INTEGER
+*/
+DER_Encoder& DER_Encoder::encode(u32bit n)
+ {
+ return encode(BigInt(n), INTEGER, UNIVERSAL);
+ }
+
+/*
+* DER encode a small INTEGER
+*/
+DER_Encoder& DER_Encoder::encode(const BigInt& n)
+ {
+ return encode(n, INTEGER, UNIVERSAL);
+ }
+
+/*
+* DER encode an OCTET STRING or BIT STRING
+*/
+DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes,
+ ASN1_Tag real_type)
+ {
+ return encode(bytes.begin(), bytes.size(),
+ real_type, real_type, UNIVERSAL);
+ }
+
+/*
+* Encode this object
+*/
+DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length,
+ ASN1_Tag real_type)
+ {
+ return encode(bytes, length, real_type, real_type, UNIVERSAL);
+ }
+
+/*
+* DER encode a BOOLEAN
+*/
+DER_Encoder& DER_Encoder::encode(bool is_true,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ byte val = is_true ? 0xFF : 0x00;
+ return add_object(type_tag, class_tag, &val, 1);
+ }
+
+/*
+* DER encode a small INTEGER
+*/
+DER_Encoder& DER_Encoder::encode(u32bit n,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ return encode(BigInt(n), type_tag, class_tag);
+ }
+
+/*
+* DER encode an INTEGER
+*/
+DER_Encoder& DER_Encoder::encode(const BigInt& n,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if(n == 0)
+ return add_object(type_tag, class_tag, 0);
+
+ bool extra_zero = (n.bits() % 8 == 0);
+ SecureVector<byte> contents(extra_zero + n.bytes());
+ BigInt::encode(contents.begin() + extra_zero, n);
+ if(n < 0)
+ {
+ for(u32bit j = 0; j != contents.size(); ++j)
+ contents[j] = ~contents[j];
+ for(u32bit j = contents.size(); j > 0; --j)
+ if(++contents[j-1])
+ break;
+ }
+
+ return add_object(type_tag, class_tag, contents);
+ }
+
+/*
+* DER encode an OCTET STRING or BIT STRING
+*/
+DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ return encode(bytes.begin(), bytes.size(),
+ real_type, type_tag, class_tag);
+ }
+
+/*
+* DER encode an OCTET STRING or BIT STRING
+*/
+DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length,
+ ASN1_Tag real_type,
+ ASN1_Tag type_tag, ASN1_Tag class_tag)
+ {
+ if(real_type != OCTET_STRING && real_type != BIT_STRING)
+ throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string");
+
+ if(real_type == BIT_STRING)
+ {
+ SecureVector<byte> encoded;
+ encoded.append(0);
+ encoded.append(bytes, length);
+ return add_object(type_tag, class_tag, encoded);
+ }
+ else
+ return add_object(type_tag, class_tag, bytes, length);
+ }
+
+/*
+* Conditionally write some values to the stream
+*/
+DER_Encoder& DER_Encoder::encode_if(bool cond, DER_Encoder& codec)
+ {
+ if(cond)
+ return raw_bytes(codec.get_contents());
+ return (*this);
+ }
+
+/*
+* Request for an object to encode itself
+*/
+DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj)
+ {
+ obj.encode_into(*this);
+ return (*this);
+ }
+
+/*
+* Write the encoding of the byte(s)
+*/
+DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
+ const byte rep[], u32bit length)
+ {
+ SecureVector<byte> encoded_tag = encode_tag(type_tag, class_tag);
+ SecureVector<byte> encoded_length = encode_length(length);
+
+ SecureVector<byte> buffer;
+ buffer.append(encoded_tag);
+ buffer.append(encoded_length);
+ buffer.append(rep, length);
+
+ return raw_bytes(buffer);
+ }
+
+/*
+* Write the encoding of the byte(s)
+*/
+DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
+ const MemoryRegion<byte>& rep_buf)
+ {
+ const byte* rep = rep_buf.begin();
+ const u32bit rep_len = rep_buf.size();
+ return add_object(type_tag, class_tag, rep, rep_len);
+ }
+
+/*
+* Write the encoding of the byte(s)
+*/
+DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
+ const std::string& rep_str)
+ {
+ const byte* rep = reinterpret_cast<const byte*>(rep_str.data());
+ const u32bit rep_len = rep_str.size();
+ return add_object(type_tag, class_tag, rep, rep_len);
+ }
+
+/*
+* Write the encoding of the byte
+*/
+DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag,
+ ASN1_Tag class_tag, byte rep)
+ {
+ return add_object(type_tag, class_tag, &rep, 1);
+ }
+
+}
diff --git a/botan/src/asn1/der_enc.h b/botan/src/asn1/der_enc.h
new file mode 100644
index 0000000..23b5297
--- /dev/null
+++ b/botan/src/asn1/der_enc.h
@@ -0,0 +1,91 @@
+/*
+* DER Encoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DER_ENCODER_H__
+#define BOTAN_DER_ENCODER_H__
+
+#include <botan/asn1_int.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* General DER Encoding Object
+*/
+class BOTAN_DLL DER_Encoder
+ {
+ public:
+ SecureVector<byte> get_contents();
+
+ DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL);
+ DER_Encoder& end_cons();
+
+ DER_Encoder& start_explicit(u16bit);
+ DER_Encoder& end_explicit();
+
+ DER_Encoder& raw_bytes(const byte[], u32bit);
+ DER_Encoder& raw_bytes(const MemoryRegion<byte>&);
+
+ DER_Encoder& encode_null();
+ DER_Encoder& encode(bool);
+ DER_Encoder& encode(u32bit);
+ DER_Encoder& encode(const class BigInt&);
+ DER_Encoder& encode(const MemoryRegion<byte>&, ASN1_Tag);
+ DER_Encoder& encode(const byte[], u32bit, ASN1_Tag);
+
+ DER_Encoder& encode(bool, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(u32bit, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const class BigInt&, ASN1_Tag,
+ ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const MemoryRegion<byte>&, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+ DER_Encoder& encode(const byte[], u32bit, ASN1_Tag,
+ ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC);
+
+ template<typename T>
+ DER_Encoder& encode_optional(const T& value, const T& default_value)
+ {
+ if(value != default_value)
+ encode(value);
+ return (*this);
+ }
+
+ template<typename T>
+ DER_Encoder& encode_list(const std::vector<T>& values)
+ {
+ for(u32bit j = 0; j != values.size(); ++j)
+ encode(values[j]);
+ return (*this);
+ }
+
+ DER_Encoder& encode(const class ASN1_Object&);
+ DER_Encoder& encode_if(bool, DER_Encoder&);
+
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const byte[], u32bit);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const MemoryRegion<byte>&);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const std::string&);
+ DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, byte);
+ private:
+ class DER_Sequence
+ {
+ public:
+ ASN1_Tag tag_of() const;
+ SecureVector<byte> get_contents();
+ void add_bytes(const byte[], u32bit);
+ DER_Sequence(ASN1_Tag, ASN1_Tag);
+ private:
+ ASN1_Tag type_tag, class_tag;
+ SecureVector<byte> contents;
+ std::vector< SecureVector<byte> > set_contents;
+ };
+ SecureVector<byte> contents;
+ std::vector<DER_Sequence> subsequences;
+ };
+
+}
+
+#endif
diff --git a/botan/src/asn1/info.txt b/botan/src/asn1/info.txt
new file mode 100644
index 0000000..7b8110c
--- /dev/null
+++ b/botan/src/asn1/info.txt
@@ -0,0 +1,31 @@
+realname "ASN.1/BER/DER module"
+
+define ASN1
+
+load_on auto
+
+<add>
+alg_id.cpp
+asn1_alt.cpp
+asn1_att.cpp
+asn1_dn.cpp
+asn1_int.cpp
+asn1_oid.cpp
+asn1_str.cpp
+asn1_tm.cpp
+ber_dec.cpp
+der_enc.cpp
+alg_id.h
+asn1_int.h
+asn1_obj.h
+asn1_oid.h
+ber_dec.h
+der_enc.h
+</add>
+
+<requires>
+alloc
+bigint
+filters
+oid_lookup
+</requires>
diff --git a/botan/src/benchmark/benchmark.cpp b/botan/src/benchmark/benchmark.cpp
new file mode 100644
index 0000000..01e3b94
--- /dev/null
+++ b/botan/src/benchmark/benchmark.cpp
@@ -0,0 +1,189 @@
+/**
+* Runtime benchmarking
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/benchmark.h>
+#include <botan/buf_comp.h>
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/util.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/**
+* Benchmark BufferedComputation (hash or MAC)
+*/
+std::pair<u64bit, u64bit> bench_buf_comp(BufferedComputation* buf_comp,
+ Timer& timer,
+ u64bit nanoseconds_max,
+ const byte buf[], u32bit buf_len)
+ {
+ const u64bit start = timer.clock();
+ u64bit nanoseconds_used = 0;
+ u64bit reps = 0;
+
+ while(nanoseconds_used < nanoseconds_max)
+ {
+ buf_comp->update(buf, buf_len);
+ ++reps;
+ nanoseconds_used = timer.clock() - start;
+ }
+
+ return std::make_pair(reps * buf_len, nanoseconds_used);
+ }
+
+/**
+* Benchmark block cipher
+*/
+std::pair<u64bit, u64bit>
+bench_block_cipher(BlockCipher* block_cipher,
+ Timer& timer,
+ u64bit nanoseconds_max,
+ byte buf[], u32bit buf_len)
+ {
+ const u64bit start = timer.clock();
+ u64bit nanoseconds_used = 0;
+ u64bit reps = 0;
+
+ const u32bit in_blocks = buf_len / block_cipher->BLOCK_SIZE;
+
+ while(nanoseconds_used < nanoseconds_max)
+ {
+ for(u32bit i = 0; i != in_blocks; ++i)
+ block_cipher->encrypt(buf + block_cipher->BLOCK_SIZE * i);
+
+ ++reps;
+ nanoseconds_used = timer.clock() - start;
+ }
+
+ return std::make_pair(reps * in_blocks * block_cipher->BLOCK_SIZE,
+ nanoseconds_used);
+ }
+
+/**
+* Benchmark stream
+*/
+std::pair<u64bit, u64bit>
+bench_stream_cipher(StreamCipher* stream_cipher,
+ Timer& timer,
+ u64bit nanoseconds_max,
+ byte buf[], u32bit buf_len)
+ {
+ const u64bit start = timer.clock();
+ u64bit nanoseconds_used = 0;
+ u64bit reps = 0;
+
+ while(nanoseconds_used < nanoseconds_max)
+ {
+ stream_cipher->encrypt(buf, buf_len);
+ ++reps;
+ nanoseconds_used = timer.clock() - start;
+ }
+
+ return std::make_pair(reps * buf_len, nanoseconds_used);
+ }
+
+/**
+* Benchmark hash
+*/
+std::pair<u64bit, u64bit>
+bench_hash(HashFunction* hash, Timer& timer,
+ u64bit nanoseconds_max,
+ const byte buf[], u32bit buf_len)
+ {
+ return bench_buf_comp(hash, timer, nanoseconds_max, buf, buf_len);
+ }
+
+/**
+* Benchmark MAC
+*/
+std::pair<u64bit, u64bit>
+bench_mac(MessageAuthenticationCode* mac,
+ Timer& timer,
+ u64bit nanoseconds_max,
+ const byte buf[], u32bit buf_len)
+ {
+ mac->set_key(buf, mac->MAXIMUM_KEYLENGTH);
+ return bench_buf_comp(mac, timer, nanoseconds_max, buf, buf_len);
+ }
+
+}
+
+std::map<std::string, double>
+algorithm_benchmark(const std::string& name,
+ u32bit milliseconds,
+ Timer& timer,
+ RandomNumberGenerator& rng,
+ Algorithm_Factory& af)
+ {
+ std::vector<std::string> providers = af.providers_of(name);
+ std::map<std::string, double> all_results;
+
+ if(providers.empty()) // no providers, nothing to do
+ return all_results;
+
+ const u64bit ns_per_provider =
+ ((u64bit)milliseconds * 1000 * 1000) / providers.size();
+
+ std::vector<byte> buf(16 * 1024);
+ rng.randomize(&buf[0], buf.size());
+
+ for(u32bit i = 0; i != providers.size(); ++i)
+ {
+ const std::string provider = providers[i];
+
+ std::pair<u64bit, u64bit> results(0, 0);
+
+ if(const BlockCipher* proto =
+ af.prototype_block_cipher(name, provider))
+ {
+ std::auto_ptr<BlockCipher> block_cipher(proto->clone());
+ results = bench_block_cipher(block_cipher.get(), timer,
+ ns_per_provider,
+ &buf[0], buf.size());
+ }
+ else if(const StreamCipher* proto =
+ af.prototype_stream_cipher(name, provider))
+ {
+ std::auto_ptr<StreamCipher> stream_cipher(proto->clone());
+ results = bench_stream_cipher(stream_cipher.get(), timer,
+ ns_per_provider,
+ &buf[0], buf.size());
+ }
+ else if(const HashFunction* proto =
+ af.prototype_hash_function(name, provider))
+ {
+ std::auto_ptr<HashFunction> hash(proto->clone());
+ results = bench_hash(hash.get(), timer, ns_per_provider,
+ &buf[0], buf.size());
+ }
+ else if(const MessageAuthenticationCode* proto =
+ af.prototype_mac(name, provider))
+ {
+ std::auto_ptr<MessageAuthenticationCode> mac(proto->clone());
+ results = bench_mac(mac.get(), timer, ns_per_provider,
+ &buf[0], buf.size());
+ }
+
+ if(results.first && results.second)
+ {
+ /* 953.67 == 1000 * 1000 * 1000 / 1024 / 1024 - the conversion
+ factor from bytes per nanosecond to mebibytes per second.
+ */
+ double speed = (953.67 * results.first) / results.second;
+ all_results[provider] = speed;
+ }
+ }
+
+ return all_results;
+ }
+
+}
diff --git a/botan/src/benchmark/benchmark.h b/botan/src/benchmark/benchmark.h
new file mode 100644
index 0000000..272cfdf
--- /dev/null
+++ b/botan/src/benchmark/benchmark.h
@@ -0,0 +1,59 @@
+/**
+* Runtime benchmarking
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RUNTIME_BENCHMARK_H__
+#define BOTAN_RUNTIME_BENCHMARK_H__
+
+#include <botan/algo_factory.h>
+#include <botan/timer.h>
+#include <botan/rng.h>
+#include <map>
+#include <string>
+
+/**
+* Choose some sort of default timer implementation to use, since some
+* (like hardware tick counters and current Win32 timer) are not
+* reliable for benchmarking.
+*/
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ #include <botan/tm_posix.h>
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ #include <botan/tm_unix.h>
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ typedef POSIX_Timer Default_Benchmark_Timer;
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ typedef Unix_Timer Default_Benchmark_Timer;
+#else
+ /* I have not had good success using clock(), the results seem
+ * pretty bogus, but as a last resort it works.
+ */
+ typedef ANSI_Clock_Timer Default_Benchmark_Timer;
+#endif
+
+/**
+* Algorithm benchmark
+* @param name the name of the algorithm to test (cipher, hash, or MAC)
+* @param milliseconds total time for the benchmark to run
+* @param timer the timer to use
+* @param rng the rng to use to generate random inputs
+* @param af the algorithm factory used to create objects
+* @return results a map from provider to speed in mebibytes per second
+*/
+std::map<std::string, double>
+algorithm_benchmark(const std::string& name,
+ u32bit milliseconds,
+ Timer& timer,
+ RandomNumberGenerator& rng,
+ Algorithm_Factory& af);
+
+}
+
+#endif
diff --git a/botan/src/benchmark/info.txt b/botan/src/benchmark/info.txt
new file mode 100644
index 0000000..0fbcdb2
--- /dev/null
+++ b/botan/src/benchmark/info.txt
@@ -0,0 +1,21 @@
+realname "Benchmarking"
+
+define RUNTIME_BENCHMARKING
+
+load_on auto
+
+<add>
+benchmark.cpp
+benchmark.h
+</add>
+
+<requires>
+algo_factory
+block
+buf_comp
+hash
+mac
+rng
+stream
+timer
+</requires>
diff --git a/botan/src/block/aes/aes.cpp b/botan/src/block/aes/aes.cpp
new file mode 100644
index 0000000..9072b50
--- /dev/null
+++ b/botan/src/block/aes/aes.cpp
@@ -0,0 +1,257 @@
+/**
+* AES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/aes.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/**
+* AES Encryption
+*/
+void AES::enc(const byte in[], byte out[]) const
+ {
+ const u32bit* TE0 = TE;
+ const u32bit* TE1 = TE + 256;
+ const u32bit* TE2 = TE + 512;
+ const u32bit* TE3 = TE + 768;
+
+ u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0];
+ u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1];
+ u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2];
+ u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3];
+
+ u32bit B0, B1, B2, B3;
+ B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^
+ TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4];
+ B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^
+ TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5];
+ B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^
+ TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6];
+ B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^
+ TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7];
+
+ for(u32bit j = 2; j != ROUNDS; j += 2)
+ {
+ const u32bit K0 = EK[4*j];
+ const u32bit K1 = EK[4*j+1];
+ const u32bit K2 = EK[4*j+2];
+ const u32bit K3 = EK[4*j+3];
+
+ T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^
+ TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0;
+ T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^
+ TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1;
+ T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^
+ TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2;
+ T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^
+ TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3;
+
+ const u32bit K4 = EK[4*(j+1)+0];
+ const u32bit K5 = EK[4*(j+1)+1];
+ const u32bit K6 = EK[4*(j+1)+2];
+ const u32bit K7 = EK[4*(j+1)+3];
+
+ B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^
+ TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4;
+ B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^
+ TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5;
+ B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^
+ TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6;
+ B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^
+ TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7;
+ }
+
+ /*
+ Joseph Bonneau and Ilya Mironov's paper
+ <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf">
+ Cache-Collision Timing Attacks Against AES</a> describes an attack
+ that can recover AES keys with as few as 2<sup>13</sup> samples.
+
+ """In addition to OpenSSL v. 0.9.8.(a), which was used in our
+ experiments, the AES implementations of Crypto++ 5.2.1 and
+ LibTomCrypt 1.09 use the original Rijndael C implementation with
+ very few changes and are highly vulnerable. The AES implementations
+ in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but
+ use a smaller byte-wide final table which lessens the effectiveness
+ of the attacks."""
+ */
+ out[ 0] = SE[get_byte(0, B0)] ^ ME[0];
+ out[ 1] = SE[get_byte(1, B1)] ^ ME[1];
+ out[ 2] = SE[get_byte(2, B2)] ^ ME[2];
+ out[ 3] = SE[get_byte(3, B3)] ^ ME[3];
+ out[ 4] = SE[get_byte(0, B1)] ^ ME[4];
+ out[ 5] = SE[get_byte(1, B2)] ^ ME[5];
+ out[ 6] = SE[get_byte(2, B3)] ^ ME[6];
+ out[ 7] = SE[get_byte(3, B0)] ^ ME[7];
+ out[ 8] = SE[get_byte(0, B2)] ^ ME[8];
+ out[ 9] = SE[get_byte(1, B3)] ^ ME[9];
+ out[10] = SE[get_byte(2, B0)] ^ ME[10];
+ out[11] = SE[get_byte(3, B1)] ^ ME[11];
+ out[12] = SE[get_byte(0, B3)] ^ ME[12];
+ out[13] = SE[get_byte(1, B0)] ^ ME[13];
+ out[14] = SE[get_byte(2, B1)] ^ ME[14];
+ out[15] = SE[get_byte(3, B2)] ^ ME[15];
+ }
+
+/**
+* AES Decryption
+*/
+void AES::dec(const byte in[], byte out[]) const
+ {
+ const u32bit* TD0 = TD;
+ const u32bit* TD1 = TD + 256;
+ const u32bit* TD2 = TD + 512;
+ const u32bit* TD3 = TD + 768;
+
+ u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0];
+ u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1];
+ u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2];
+ u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3];
+
+ u32bit B0, B1, B2, B3;
+ B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^
+ TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4];
+ B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^
+ TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5];
+ B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^
+ TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6];
+ B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^
+ TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7];
+
+ for(u32bit j = 2; j != ROUNDS; j += 2)
+ {
+ const u32bit K0 = DK[4*j+0];
+ const u32bit K1 = DK[4*j+1];
+ const u32bit K2 = DK[4*j+2];
+ const u32bit K3 = DK[4*j+3];
+
+ T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^
+ TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0;
+ T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^
+ TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1;
+ T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^
+ TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2;
+ T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^
+ TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3;
+
+ const u32bit K4 = DK[4*(j+1)+0];
+ const u32bit K5 = DK[4*(j+1)+1];
+ const u32bit K6 = DK[4*(j+1)+2];
+ const u32bit K7 = DK[4*(j+1)+3];
+
+ B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^
+ TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4;
+ B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^
+ TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5;
+ B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^
+ TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6;
+ B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^
+ TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7;
+ }
+
+ out[ 0] = SD[get_byte(0, B0)] ^ MD[0];
+ out[ 1] = SD[get_byte(1, B3)] ^ MD[1];
+ out[ 2] = SD[get_byte(2, B2)] ^ MD[2];
+ out[ 3] = SD[get_byte(3, B1)] ^ MD[3];
+ out[ 4] = SD[get_byte(0, B1)] ^ MD[4];
+ out[ 5] = SD[get_byte(1, B0)] ^ MD[5];
+ out[ 6] = SD[get_byte(2, B3)] ^ MD[6];
+ out[ 7] = SD[get_byte(3, B2)] ^ MD[7];
+ out[ 8] = SD[get_byte(0, B2)] ^ MD[8];
+ out[ 9] = SD[get_byte(1, B1)] ^ MD[9];
+ out[10] = SD[get_byte(2, B0)] ^ MD[10];
+ out[11] = SD[get_byte(3, B3)] ^ MD[11];
+ out[12] = SD[get_byte(0, B3)] ^ MD[12];
+ out[13] = SD[get_byte(1, B2)] ^ MD[13];
+ out[14] = SD[get_byte(2, B1)] ^ MD[14];
+ out[15] = SD[get_byte(3, B0)] ^ MD[15];
+ }
+
+/**
+* AES Key Schedule
+*/
+void AES::key_schedule(const byte key[], u32bit length)
+ {
+ static const u32bit RC[10] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
+ 0x40000000, 0x80000000, 0x1B000000, 0x36000000 };
+ ROUNDS = (length / 4) + 6;
+
+ SecureBuffer<u32bit, 64> XEK, XDK;
+
+ const u32bit X = length / 4;
+ for(u32bit j = 0; j != X; ++j)
+ XEK[j] = load_be<u32bit>(key, j);
+
+ for(u32bit j = X; j < 4*(ROUNDS+1); j += X)
+ {
+ XEK[j] = XEK[j-X] ^ S(rotate_left(XEK[j-1], 8)) ^ RC[(j-X)/X];
+ for(u32bit k = 1; k != X; ++k)
+ {
+ if(X == 8 && k == 4)
+ XEK[j+k] = XEK[j+k-X] ^ S(XEK[j+k-1]);
+ else
+ XEK[j+k] = XEK[j+k-X] ^ XEK[j+k-1];
+ }
+ }
+
+ for(u32bit j = 0; j != 4*(ROUNDS+1); j += 4)
+ {
+ XDK[j ] = XEK[4*ROUNDS-j ];
+ XDK[j+1] = XEK[4*ROUNDS-j+1];
+ XDK[j+2] = XEK[4*ROUNDS-j+2];
+ XDK[j+3] = XEK[4*ROUNDS-j+3];
+ }
+
+ for(u32bit j = 4; j != length + 24; ++j)
+ XDK[j] = TD[SE[get_byte(0, XDK[j])] + 0] ^
+ TD[SE[get_byte(1, XDK[j])] + 256] ^
+ TD[SE[get_byte(2, XDK[j])] + 512] ^
+ TD[SE[get_byte(3, XDK[j])] + 768];
+
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ store_be(XEK[j+4*ROUNDS], ME + 4*j);
+ store_be(XEK[j], MD + 4*j);
+ }
+
+ EK.copy(XEK, length + 24);
+ DK.copy(XDK, length + 24);
+ }
+
+/**
+* AES Byte Substitution
+*/
+u32bit AES::S(u32bit input)
+ {
+ return make_u32bit(SE[get_byte(0, input)], SE[get_byte(1, input)],
+ SE[get_byte(2, input)], SE[get_byte(3, input)]);
+ }
+
+/**
+* AES Constructor
+*/
+AES::AES(u32bit key_size) : BlockCipher(16, key_size)
+ {
+ if(key_size != 16 && key_size != 24 && key_size != 32)
+ throw Invalid_Key_Length(name(), key_size);
+ ROUNDS = (key_size / 4) + 6;
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void AES::clear() throw()
+ {
+ EK.clear();
+ DK.clear();
+ ME.clear();
+ MD.clear();
+ }
+
+}
diff --git a/botan/src/block/aes/aes.h b/botan/src/block/aes/aes.h
new file mode 100644
index 0000000..05e2e31
--- /dev/null
+++ b/botan/src/block/aes/aes.h
@@ -0,0 +1,81 @@
+/**
+* AES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AES_H__
+#define BOTAN_AES_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* Rijndael aka AES
+*/
+class BOTAN_DLL AES : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "AES"; }
+ BlockCipher* clone() const { return new AES; }
+ AES() : BlockCipher(16, 16, 32, 8) { ROUNDS = 14; }
+ AES(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ static u32bit S(u32bit);
+
+ static const byte SE[256];
+ static const byte SD[256];
+ static const u32bit TE[1024];
+ static const u32bit TD[1024];
+
+ u32bit ROUNDS;
+
+ SecureBuffer<u32bit, 56> EK;
+ SecureBuffer<byte, 16> ME;
+
+ SecureBuffer<u32bit, 56> DK;
+ SecureBuffer<byte, 16> MD;
+ };
+
+/**
+* AES-128
+*/
+class BOTAN_DLL AES_128 : public AES
+ {
+ public:
+ std::string name() const { return "AES-128"; }
+ BlockCipher* clone() const { return new AES_128; }
+ AES_128() : AES(16) {}
+ };
+
+/**
+* AES-192
+*/
+class BOTAN_DLL AES_192 : public AES
+ {
+ public:
+ std::string name() const { return "AES-192"; }
+ BlockCipher* clone() const { return new AES_192; }
+ AES_192() : AES(24) {}
+ };
+
+/**
+* AES-256
+*/
+class BOTAN_DLL AES_256 : public AES
+ {
+ public:
+ std::string name() const { return "AES-256"; }
+ BlockCipher* clone() const { return new AES_256; }
+ AES_256() : AES(32) {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/aes/aes_tab.cpp b/botan/src/block/aes/aes_tab.cpp
new file mode 100644
index 0000000..d42a2cd
--- /dev/null
+++ b/botan/src/block/aes/aes_tab.cpp
@@ -0,0 +1,406 @@
+/*
+* S-Box and Diffusion Tables for AES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/aes.h>
+
+namespace Botan {
+
+const byte AES::SE[256] = {
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
+ 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
+ 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
+ 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
+ 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
+ 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
+ 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
+ 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
+ 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
+ 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
+ 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
+ 0xB0, 0x54, 0xBB, 0x16 };
+
+const byte AES::SD[256] = {
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
+ 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
+ 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
+ 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
+ 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
+ 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
+ 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
+ 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
+ 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
+ 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0C, 0x7D };
+
+const u32bit AES::TE[1024] = {
+ 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,
+ 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D,
+ 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D,
+ 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
+ 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,
+ 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A,
+ 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4,
+ 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
+ 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,
+ 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D,
+ 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E,
+ 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
+ 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,
+ 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C,
+ 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46,
+ 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
+ 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,
+ 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81,
+ 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE,
+ 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
+ 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,
+ 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F,
+ 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2,
+ 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
+ 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,
+ 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C,
+ 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256,
+ 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
+ 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,
+ 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7,
+ 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA,
+ 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
+ 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,
+ 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21,
+ 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42,
+ 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
+ 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,
+ 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133,
+ 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22,
+ 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
+ 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,
+ 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11,
+ 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A, 0xA5C66363, 0x84F87C7C,
+ 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5,
+ 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7,
+ 0xE64DABAB, 0x9AEC7676, 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D,
+ 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, 0xEC41ADAD, 0x67B3D4D4,
+ 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0,
+ 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F,
+ 0x02F5F7F7, 0x4F83CCCC, 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1,
+ 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, 0x0C080404, 0x5295C7C7,
+ 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A,
+ 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727,
+ 0xCD7FB2B2, 0x9FEA7575, 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A,
+ 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, 0xF6A45252, 0x4D763B3B,
+ 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484,
+ 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC,
+ 0xC879B1B1, 0xEDB65B5B, 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939,
+ 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, 0x6BBBD0D0, 0x2AC5EFEF,
+ 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585,
+ 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C,
+ 0xBA259F9F, 0xE34BA8A8, 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F,
+ 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, 0xDF63BCBC, 0xC177B6B6,
+ 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2,
+ 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797,
+ 0xCC884444, 0x392E1717, 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D,
+ 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, 0xA0C06060, 0x98198181,
+ 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888,
+ 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E,
+ 0x1D160B0B, 0x76ADDBDB, 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A,
+ 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, 0x5D9FC2C2, 0x6EBDD3D3,
+ 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979,
+ 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5,
+ 0xD29C4E4E, 0xE049A9A9, 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA,
+ 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, 0xD56FBABA, 0x88F07878,
+ 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6,
+ 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD,
+ 0x860D8B8B, 0x850F8A8A, 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666,
+ 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, 0xA3C26161, 0x5F6A3535,
+ 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E,
+ 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9,
+ 0x89078E8E, 0xA7339494, 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9,
+ 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, 0x8F038C8C, 0xF859A1A1,
+ 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868,
+ 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454,
+ 0xD66DBBBB, 0x3A2C1616, 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B,
+ 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, 0x30506030, 0x01030201,
+ 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76,
+ 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259,
+ 0x47C98E47, 0xF00BFBF0, 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF,
+ 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, 0xB7C275B7, 0xFD1CE1FD,
+ 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC,
+ 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8,
+ 0x31536231, 0x153F2A15, 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3,
+ 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, 0x07090E07, 0x12362412,
+ 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75,
+ 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E,
+ 0x5AEEB45A, 0xA0FB5BA0, 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3,
+ 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, 0x53F5A653, 0xD168B9D1,
+ 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B,
+ 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C,
+ 0x58E8B058, 0xCF4A85CF, 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB,
+ 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, 0x45CF8A45, 0xF910E9F9,
+ 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8,
+ 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D,
+ 0x38487038, 0xF504F1F5, 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221,
+ 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, 0xCD4C81CD, 0x0C14180C,
+ 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17,
+ 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D,
+ 0x192B3219, 0x7395E673, 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC,
+ 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, 0x46CA8C46, 0xEE29C7EE,
+ 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB,
+ 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06,
+ 0x246C4824, 0x5CE4B85C, 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462,
+ 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, 0xE732D5E7, 0xC8438BC8,
+ 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9,
+ 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A,
+ 0xAEE947AE, 0x08181008, 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E,
+ 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, 0xE823CBE8, 0xDD7CA1DD,
+ 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A,
+ 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603,
+ 0xF601F7F6, 0x0E121C0E, 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9,
+ 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, 0xE138D9E1, 0xF813EBF8,
+ 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394,
+ 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55,
+ 0x28785028, 0xDF7AA5DF, 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D,
+ 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068, 0x41C38241, 0x99B02999,
+ 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16,
+ 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6,
+ 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56,
+ 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F,
+ 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
+ 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753,
+ 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C,
+ 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68, 0xA5A5F451,
+ 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
+ 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137,
+ 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF,
+ 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D,
+ 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
+ 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD,
+ 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1,
+ 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D,
+ 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
+ 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A,
+ 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE,
+ 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D,
+ 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
+ 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5,
+ 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3,
+ 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255,
+ 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
+ 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54,
+ 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28,
+ 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664,
+ 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
+ 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431,
+ 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA,
+ 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC,
+ 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
+ 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157,
+ 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E,
+ 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C,
+ 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
+ 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899,
+ 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322,
+ 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C,
+ 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
+ 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,
+ 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E,
+ 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C };
+
+const u32bit AES::TD[1024] = {
+ 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1,
+ 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25,
+ 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67,
+ 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6,
+ 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3,
+ 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD,
+ 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182,
+ 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94,
+ 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2,
+ 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5,
+ 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492,
+ 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A,
+ 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA,
+ 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46,
+ 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997,
+ 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB,
+ 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48,
+ 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927,
+ 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F,
+ 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16,
+ 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD,
+ 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD,
+ 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC,
+ 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120,
+ 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3,
+ 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422,
+ 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1,
+ 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4,
+ 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8,
+ 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3,
+ 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4,
+ 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6,
+ 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331,
+ 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815,
+ 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D,
+ 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F,
+ 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252,
+ 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89,
+ 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F,
+ 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86,
+ 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C,
+ 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190,
+ 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742, 0x5051F4A7, 0x537E4165,
+ 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303,
+ 0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB,
+ 0x80263544, 0x8FB562A3, 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0,
+ 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9, 0xE7038F5F, 0x9515929C,
+ 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8,
+ 0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD,
+ 0x66C920AC, 0xB47DCE3A, 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F,
+ 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B, 0x58704868, 0x198F45FD,
+ 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB,
+ 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5,
+ 0xBA02036A, 0x5CED1682, 0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2,
+ 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE, 0x9D342E53, 0xA0A2F355,
+ 0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10,
+ 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D,
+ 0x6F0406D4, 0xFF605015, 0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E,
+ 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE, 0x47A17C0A, 0xE97C420F,
+ 0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72,
+ 0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6,
+ 0xD19B5B54, 0x3A24362E, 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91,
+ 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A, 0x0AE293BA, 0xE5C0A02A,
+ 0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9,
+ 0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5,
+ 0xC544663B, 0x345BFB7E, 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1,
+ 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611, 0x7D854A24, 0xF8D2BB3D,
+ 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3,
+ 0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F,
+ 0xD8567D2C, 0xEF223390, 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B,
+ 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF, 0xE42C3A9D, 0x0D507892,
+ 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF,
+ 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D,
+ 0x6EE89C63, 0x7BDB3BBB, 0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A,
+ 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8, 0xD9BAE79B, 0xCE4A6F36,
+ 0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266,
+ 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA,
+ 0x0E7FCD50, 0x2F1791F6, 0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604,
+ 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551, 0x049D5EEA, 0x5D018C35,
+ 0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647,
+ 0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9,
+ 0xEDE11CE5, 0x3C7A47B1, 0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737,
+ 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB, 0x81CAAFF3, 0x3EB968C4,
+ 0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95,
+ 0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6,
+ 0x74486C5C, 0x42D0B857, 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27,
+ 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3, 0xFA552030, 0x6DF6AD76,
+ 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562,
+ 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C,
+ 0x97A38D46, 0xF9C66BD3, 0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552,
+ 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9, 0x896A75C2, 0x7978F48E,
+ 0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE,
+ 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B,
+ 0xA01CFE81, 0x2B94F908, 0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B,
+ 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655, 0x2807B2EB, 0xC2032FB5,
+ 0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16,
+ 0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605,
+ 0x621FD134, 0xFE8AC4A6, 0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6,
+ 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E, 0x8AF93E21, 0x063D96DD,
+ 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050,
+ 0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789,
+ 0x5B38E719, 0xEEDB79C8, 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000,
+ 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A, 0xFFFBFD0E, 0x38560F85,
+ 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436,
+ 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC,
+ 0x4B695A77, 0x1A161C12, 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B,
+ 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E, 0x198557F1, 0x074CAF75,
+ 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB,
+ 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263,
+ 0x22401397, 0x112084C6, 0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729,
+ 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1, 0x166C2BB3, 0xB999A970,
+ 0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233,
+ 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A,
+ 0x8E26DAB7, 0xBFA43FAD, 0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E,
+ 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3, 0x80BE9F5D, 0x937C69D0,
+ 0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B,
+ 0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF,
+ 0xCF0821BC, 0xE8E6EF15, 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0,
+ 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2, 0xBC37744E, 0xCAA6FC82,
+ 0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791,
+ 0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A,
+ 0x1FB8C12C, 0x517F4665, 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B,
+ 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6, 0x618C9AD7, 0x0C7A37A1,
+ 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47,
+ 0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD,
+ 0x6F14DF3D, 0xDB867844, 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3,
+ 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D, 0x017139A8, 0xB3DE080C,
+ 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8,
+ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F,
+ 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5,
+ 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725,
+ 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
+ 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358,
+ 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27,
+ 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 0xDF4A1863, 0x1A3182E5,
+ 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
+ 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272,
+ 0x1F8F57E3, 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3,
+ 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, 0x79B492A7,
+ 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
+ 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40,
+ 0x719F065E, 0x6E1051BD, 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D,
+ 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6,
+ 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
+ 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832,
+ 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736,
+ 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93,
+ 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
+ 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2,
+ 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3,
+ 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 0x4329768B, 0x23C6DCCB,
+ 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
+ 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC,
+ 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247,
+ 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 0x494EC787, 0x38D1C1D9,
+ 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
+ 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890,
+ 0x39F75E2E, 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF,
+ 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, 0x5918F46E,
+ 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
+ 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A,
+ 0xA59430C6, 0xA266C035, 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533,
+ 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43,
+ 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
+ 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292,
+ 0x105633E9, 0xD647136D, 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB,
+ 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55,
+ 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
+ 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC,
+ 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064,
+ 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 };
+
+}
diff --git a/botan/src/block/aes/info.txt b/botan/src/block/aes/info.txt
new file mode 100644
index 0000000..2803ccc
--- /dev/null
+++ b/botan/src/block/aes/info.txt
@@ -0,0 +1,11 @@
+realname "AES"
+
+define AES
+
+load_on auto
+
+<add>
+aes.cpp
+aes.h
+aes_tab.cpp
+</add>
diff --git a/botan/src/block/block_cipher.h b/botan/src/block/block_cipher.h
new file mode 100644
index 0000000..01c45af
--- /dev/null
+++ b/botan/src/block/block_cipher.h
@@ -0,0 +1,100 @@
+/**
+* Block Cipher Base Class
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLOCK_CIPHER_H__
+#define BOTAN_BLOCK_CIPHER_H__
+
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents a block cipher object.
+*
+* It would be very useful to extend this interface to support the
+* encryption of multiple blocks at a time. This could help
+* performance, wrt cache effects in the software implementations, and
+* could be a big deal when supporting block ciphers implemented as
+* hardware devices. It could be used by implementations of ECB, and
+* more importantly counter mode (which most designs are moving to, due
+* to the parallelism possible in counter mode which is not the case
+* with feedback-based modes like CBC).
+*
+* Probable future API here:
+* virtual void encrypt_n(const byte in[], byte out[],
+* u32bit blocks) const = 0;
+* virtual void decrypt_n(const byte in[], byte out[],
+* u32bit blocks) const = 0;
+*/
+class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * The block size of this algorithm.
+ */
+ const u32bit BLOCK_SIZE;
+
+ /**
+ * Encrypt a block.
+ * @param in The plaintext block to be encrypted as a byte array.
+ * Must be of length BLOCK_SIZE.
+ * @param out The byte array designated to hold the encrypted block.
+ * Must be of length BLOCK_SIZE.
+ */
+ void encrypt(const byte in[], byte out[]) const { enc(in, out); }
+
+ /**
+ * Decrypt a block.
+ * @param in The ciphertext block to be decypted as a byte array.
+ * Must be of length BLOCK_SIZE.
+ * @param out The byte array designated to hold the decrypted block.
+ * Must be of length BLOCK_SIZE.
+ */
+ void decrypt(const byte in[], byte out[]) const { dec(in, out); }
+
+ /**
+ * Encrypt a block.
+ * @param in The plaintext block to be encrypted as a byte array.
+ * Must be of length BLOCK_SIZE. Will hold the result when the function
+ * has finished.
+ */
+ void encrypt(byte block[]) const { enc(block, block); }
+
+ /**
+ * Decrypt a block.
+ * @param in The ciphertext block to be decrypted as a byte array.
+ * Must be of length BLOCK_SIZE. Will hold the result when the function
+ * has finished.
+ */
+ void decrypt(byte block[]) const { dec(block, block); }
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual BlockCipher* clone() const = 0;
+
+ /**
+ * Zeroize internal state
+ */
+ virtual void clear() throw() = 0;
+
+ BlockCipher(u32bit block_size,
+ u32bit key_min,
+ u32bit key_max = 0,
+ u32bit key_mod = 1) :
+ SymmetricAlgorithm(key_min, key_max, key_mod),
+ BLOCK_SIZE(block_size) {}
+
+ virtual ~BlockCipher() {}
+ private:
+ virtual void enc(const byte[], byte[]) const = 0;
+ virtual void dec(const byte[], byte[]) const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/blowfish/blfs_tab.cpp b/botan/src/block/blowfish/blfs_tab.cpp
new file mode 100644
index 0000000..070fa6c
--- /dev/null
+++ b/botan/src/block/blowfish/blfs_tab.cpp
@@ -0,0 +1,190 @@
+/*
+* S-Box and P-Box Tables for Blowfish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/blowfish.h>
+
+namespace Botan {
+
+const u32bit Blowfish::P_INIT[18] = {
+ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
+ 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+ 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B };
+
+const u32bit Blowfish::S_INIT[1024] = {
+ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96,
+ 0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+ 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658,
+ 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+ 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E,
+ 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+ 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6,
+ 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+ 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C,
+ 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+ 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1,
+ 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+ 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A,
+ 0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+ 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176,
+ 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+ 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706,
+ 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+ 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B,
+ 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+ 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C,
+ 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+ 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A,
+ 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+ 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760,
+ 0x53317B48, 0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+ 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8,
+ 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+ 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33,
+ 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+ 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0,
+ 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+ 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777,
+ 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+ 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, 0x165FA266, 0x80957705,
+ 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+ 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E,
+ 0x226800BB, 0x57B8E0AF, 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+ 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9,
+ 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+ 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F,
+ 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+ 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A, 0x4B7A70E9, 0xB5B32944,
+ 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+ 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29,
+ 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+ 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26,
+ 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+ 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, 0x3E07841C, 0x7FDEAE5C,
+ 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+ 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6,
+ 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+ 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F,
+ 0x3280BBA1, 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+ 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, 0xDE9A771F, 0xD9930810,
+ 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+ 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA,
+ 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+ 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55,
+ 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+ 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, 0x86E34570, 0xEAE96FB1,
+ 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+ 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78,
+ 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+ 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883,
+ 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+ 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, 0x1521B628, 0x29076170,
+ 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+ 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7,
+ 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+ 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099,
+ 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+ 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, 0x57F584A5, 0x1B227263,
+ 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+ 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3,
+ 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+ 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7,
+ 0xE44B476A, 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+ 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, 0x095BBF00, 0xAD19489D,
+ 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+ 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460,
+ 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+ 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484,
+ 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+ 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, 0x153E21E7, 0x8FB03D4A,
+ 0xE6E39F2B, 0xDB83ADF7, 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+ 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, 0x3320F46A,
+ 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+ 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785,
+ 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+ 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900,
+ 0x680EC0A4, 0x27A18DEE, 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+ 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, 0xD9F385B9,
+ 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+ 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397,
+ 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+ 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9,
+ 0x5EF47E1C, 0x9029317C, 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+ 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, 0x41041F0F,
+ 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+ 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E,
+ 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+ 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD,
+ 0x647D0862, 0xE7CCF5F0, 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+ 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, 0xA1EBDDF8,
+ 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+ 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C,
+ 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+ 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B,
+ 0x12754CCC, 0x782EF11C, 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+ 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, 0x0A121386,
+ 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+ 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0,
+ 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+ 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2,
+ 0xF474EF38, 0x8789BDC2, 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+ 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, 0x20B45770,
+ 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+ 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C,
+ 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+ 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA,
+ 0xA002B5C4, 0x0DE6D027, 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+ 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, 0x2338EA63,
+ 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+ 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9,
+ 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+ 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4,
+ 0x362ABFCE, 0xDDC6C837, 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,
+ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742,
+ 0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+ 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79,
+ 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+ 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A,
+ 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+ 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1,
+ 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+ 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797,
+ 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+ 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, 0xE029AC71, 0xE019A5E6,
+ 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+ 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA,
+ 0x03A16125, 0x0564F0BD, 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+ 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5,
+ 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+ 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE,
+ 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+ 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD,
+ 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+ 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB,
+ 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+ 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC,
+ 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+ 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC,
+ 0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+ 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A,
+ 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+ 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A,
+ 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+ 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B,
+ 0x4C98A0BE, 0x3278E964, 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+ 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E,
+ 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+ 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, 0xF523F357, 0xA6327623,
+ 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+ 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A,
+ 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+ 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3,
+ 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+ 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C,
+ 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+ 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 };
+
+}
diff --git a/botan/src/block/blowfish/blowfish.cpp b/botan/src/block/blowfish/blowfish.cpp
new file mode 100644
index 0000000..b0599d6
--- /dev/null
+++ b/botan/src/block/blowfish/blowfish.cpp
@@ -0,0 +1,125 @@
+/*
+* Blowfish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/blowfish.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Blowfish Encryption
+*/
+void Blowfish::enc(const byte in[], byte out[]) const
+ {
+ const u32bit* S1 = S + 0;
+ const u32bit* S2 = S + 256;
+ const u32bit* S3 = S + 512;
+ const u32bit* S4 = S + 768;
+
+ u32bit L = load_be<u32bit>(in, 0);
+ u32bit R = load_be<u32bit>(in, 1);
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ L ^= P[j];
+ R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^
+ S3[get_byte(2, L)]) + S4[get_byte(3, L)];
+
+ R ^= P[j+1];
+ L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^
+ S3[get_byte(2, R)]) + S4[get_byte(3, R)];
+ }
+
+ L ^= P[16]; R ^= P[17];
+
+ store_be(out, R, L);
+ }
+
+/*
+* Blowfish Decryption
+*/
+void Blowfish::dec(const byte in[], byte out[]) const
+ {
+ const u32bit* S1 = S + 0;
+ const u32bit* S2 = S + 256;
+ const u32bit* S3 = S + 512;
+ const u32bit* S4 = S + 768;
+
+ u32bit L = load_be<u32bit>(in, 0);
+ u32bit R = load_be<u32bit>(in, 1);
+
+ for(u32bit j = 17; j != 1; j -= 2)
+ {
+ L ^= P[j];
+ R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^
+ S3[get_byte(2, L)]) + S4[get_byte(3, L)];
+
+ R ^= P[j-1];
+ L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^
+ S3[get_byte(2, R)]) + S4[get_byte(3, R)];
+ }
+
+ L ^= P[1]; R ^= P[0];
+
+ store_be(out, R, L);
+ }
+
+/*
+* Blowfish Key Schedule
+*/
+void Blowfish::key_schedule(const byte key[], u32bit length)
+ {
+ clear();
+
+ for(u32bit j = 0, k = 0; j != 18; ++j, k += 4)
+ P[j] ^= make_u32bit(key[(k ) % length], key[(k+1) % length],
+ key[(k+2) % length], key[(k+3) % length]);
+
+ u32bit L = 0, R = 0;
+ generate_sbox(P, 18, L, R);
+ generate_sbox(S, 1024, L, R);
+ }
+
+/*
+* Generate one of the Sboxes
+*/
+void Blowfish::generate_sbox(u32bit Box[], u32bit size,
+ u32bit& L, u32bit& R) const
+ {
+ const u32bit* S1 = S + 0;
+ const u32bit* S2 = S + 256;
+ const u32bit* S3 = S + 512;
+ const u32bit* S4 = S + 768;
+
+ for(u32bit j = 0; j != size; j += 2)
+ {
+ for(u32bit k = 0; k != 16; k += 2)
+ {
+ L ^= P[k];
+ R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^
+ S3[get_byte(2, L)]) + S4[get_byte(3, L)];
+
+ R ^= P[k+1];
+ L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^
+ S3[get_byte(2, R)]) + S4[get_byte(3, R)];
+ }
+
+ u32bit T = R; R = L ^ P[16]; L = T ^ P[17];
+ Box[j] = L; Box[j+1] = R;
+ }
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Blowfish::clear() throw()
+ {
+ P.copy(P_INIT, 18);
+ S.copy(S_INIT, 1024);
+ }
+
+}
diff --git a/botan/src/block/blowfish/blowfish.h b/botan/src/block/blowfish/blowfish.h
new file mode 100644
index 0000000..f0f2641
--- /dev/null
+++ b/botan/src/block/blowfish/blowfish.h
@@ -0,0 +1,40 @@
+/*
+* Blowfish
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLOWFISH_H__
+#define BOTAN_BLOWFISH_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Blowfish
+*/
+class BOTAN_DLL Blowfish : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Blowfish"; }
+ BlockCipher* clone() const { return new Blowfish; }
+ Blowfish() : BlockCipher(8, 1, 56) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ void generate_sbox(u32bit[], u32bit, u32bit&, u32bit&) const;
+
+ static const u32bit P_INIT[18];
+ static const u32bit S_INIT[1024];
+
+ SecureBuffer<u32bit, 1024> S;
+ SecureBuffer<u32bit, 18> P;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/blowfish/info.txt b/botan/src/block/blowfish/info.txt
new file mode 100644
index 0000000..0a9d2ad
--- /dev/null
+++ b/botan/src/block/blowfish/info.txt
@@ -0,0 +1,11 @@
+realname "Blowfish"
+
+define BLOWFISH
+
+load_on auto
+
+<add>
+blfs_tab.cpp
+blowfish.cpp
+blowfish.h
+</add>
diff --git a/botan/src/block/cast/cast128.cpp b/botan/src/block/cast/cast128.cpp
new file mode 100644
index 0000000..046638a
--- /dev/null
+++ b/botan/src/block/cast/cast128.cpp
@@ -0,0 +1,172 @@
+/*
+* CAST-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cast128.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* CAST-128 Round Type 1
+*/
+inline void R1(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+ {
+ u32bit T = rotate_left(MK + R, RK);
+ L ^= (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
+ CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)];
+ }
+
+/*
+* CAST-128 Round Type 2
+*/
+inline void R2(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+ {
+ u32bit T = rotate_left(MK ^ R, RK);
+ L ^= (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] +
+ CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)];
+ }
+
+/*
+* CAST-128 Round Type 3
+*/
+inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK)
+ {
+ u32bit T = rotate_left(MK - R, RK);
+ L ^= ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^
+ CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)];
+ }
+
+}
+
+/*
+* CAST-128 Encryption
+*/
+void CAST_128::enc(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0);
+ u32bit R = load_be<u32bit>(in, 1);
+
+ R1(L, R, MK[ 0], RK[ 0]);
+ R2(R, L, MK[ 1], RK[ 1]);
+ R3(L, R, MK[ 2], RK[ 2]);
+ R1(R, L, MK[ 3], RK[ 3]);
+ R2(L, R, MK[ 4], RK[ 4]);
+ R3(R, L, MK[ 5], RK[ 5]);
+ R1(L, R, MK[ 6], RK[ 6]);
+ R2(R, L, MK[ 7], RK[ 7]);
+ R3(L, R, MK[ 8], RK[ 8]);
+ R1(R, L, MK[ 9], RK[ 9]);
+ R2(L, R, MK[10], RK[10]);
+ R3(R, L, MK[11], RK[11]);
+ R1(L, R, MK[12], RK[12]);
+ R2(R, L, MK[13], RK[13]);
+ R3(L, R, MK[14], RK[14]);
+ R1(R, L, MK[15], RK[15]);
+
+ store_be(out, R, L);
+ }
+
+/*
+* CAST-128 Decryption
+*/
+void CAST_128::dec(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0);
+ u32bit R = load_be<u32bit>(in, 1);
+
+ R1(L, R, MK[15], RK[15]);
+ R3(R, L, MK[14], RK[14]);
+ R2(L, R, MK[13], RK[13]);
+ R1(R, L, MK[12], RK[12]);
+ R3(L, R, MK[11], RK[11]);
+ R2(R, L, MK[10], RK[10]);
+ R1(L, R, MK[ 9], RK[ 9]);
+ R3(R, L, MK[ 8], RK[ 8]);
+ R2(L, R, MK[ 7], RK[ 7]);
+ R1(R, L, MK[ 6], RK[ 6]);
+ R3(L, R, MK[ 5], RK[ 5]);
+ R2(R, L, MK[ 4], RK[ 4]);
+ R1(L, R, MK[ 3], RK[ 3]);
+ R3(R, L, MK[ 2], RK[ 2]);
+ R2(L, R, MK[ 1], RK[ 1]);
+ R1(R, L, MK[ 0], RK[ 0]);
+
+ store_be(out, R, L);
+ }
+
+/*
+* CAST-128 Key Schedule
+*/
+void CAST_128::key_schedule(const byte key[], u32bit length)
+ {
+ clear();
+ SecureBuffer<u32bit, 4> X;
+ for(u32bit j = 0; j != length; ++j)
+ X[j/4] = (X[j/4] << 8) + key[j];
+
+ key_schedule(MK, X);
+ key_schedule(RK, X);
+
+ for(u32bit j = 0; j != 16; ++j)
+ RK[j] %= 32;
+ }
+
+/*
+* S-Box Based Key Expansion
+*/
+void CAST_128::key_schedule(u32bit K[16], u32bit X[4])
+ {
+ class ByteReader
+ {
+ public:
+ byte operator()(u32bit i) { return (X[i/4] >> (8*(3 - (i%4)))); }
+ ByteReader(const u32bit* x) : X(x) {}
+ private:
+ const u32bit* X;
+ };
+
+ SecureBuffer<u32bit, 4> Z;
+ ByteReader x(X), z(Z);
+
+ Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)];
+ Z[1] = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)];
+ Z[2] = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)];
+ Z[3] = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)];
+ K[ 0] = S5[z( 8)] ^ S6[z( 9)] ^ S7[z( 7)] ^ S8[z( 6)] ^ S5[z( 2)];
+ K[ 1] = S5[z(10)] ^ S6[z(11)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S6[z( 6)];
+ K[ 2] = S5[z(12)] ^ S6[z(13)] ^ S7[z( 3)] ^ S8[z( 2)] ^ S7[z( 9)];
+ K[ 3] = S5[z(14)] ^ S6[z(15)] ^ S7[z( 1)] ^ S8[z( 0)] ^ S8[z(12)];
+ X[0] = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)];
+ X[1] = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)];
+ X[2] = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)];
+ X[3] = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)];
+ K[ 4] = S5[x( 3)] ^ S6[x( 2)] ^ S7[x(12)] ^ S8[x(13)] ^ S5[x( 8)];
+ K[ 5] = S5[x( 1)] ^ S6[x( 0)] ^ S7[x(14)] ^ S8[x(15)] ^ S6[x(13)];
+ K[ 6] = S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 8)] ^ S8[x( 9)] ^ S7[x( 3)];
+ K[ 7] = S5[x( 5)] ^ S6[x( 4)] ^ S7[x(10)] ^ S8[x(11)] ^ S8[x( 7)];
+ Z[0] = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)];
+ Z[1] = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)];
+ Z[2] = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)];
+ Z[3] = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)];
+ K[ 8] = S5[z( 3)] ^ S6[z( 2)] ^ S7[z(12)] ^ S8[z(13)] ^ S5[z( 9)];
+ K[ 9] = S5[z( 1)] ^ S6[z( 0)] ^ S7[z(14)] ^ S8[z(15)] ^ S6[z(12)];
+ K[10] = S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 8)] ^ S8[z( 9)] ^ S7[z( 2)];
+ K[11] = S5[z( 5)] ^ S6[z( 4)] ^ S7[z(10)] ^ S8[z(11)] ^ S8[z( 6)];
+ X[0] = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)];
+ X[1] = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)];
+ X[2] = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)];
+ X[3] = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)];
+ K[12] = S5[x( 8)] ^ S6[x( 9)] ^ S7[x( 7)] ^ S8[x( 6)] ^ S5[x( 3)];
+ K[13] = S5[x(10)] ^ S6[x(11)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S6[x( 7)];
+ K[14] = S5[x(12)] ^ S6[x(13)] ^ S7[x( 3)] ^ S8[x( 2)] ^ S7[x( 8)];
+ K[15] = S5[x(14)] ^ S6[x(15)] ^ S7[x( 1)] ^ S8[x( 0)] ^ S8[x(13)];
+ }
+
+}
diff --git a/botan/src/block/cast/cast128.h b/botan/src/block/cast/cast128.h
new file mode 100644
index 0000000..6804814
--- /dev/null
+++ b/botan/src/block/cast/cast128.h
@@ -0,0 +1,47 @@
+/*
+* CAST-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CAST128_H__
+#define BOTAN_CAST128_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CAST-128
+*/
+class BOTAN_DLL CAST_128 : public BlockCipher
+ {
+ public:
+ void clear() throw() { MK.clear(); RK.clear(); }
+ std::string name() const { return "CAST-128"; }
+ BlockCipher* clone() const { return new CAST_128; }
+ CAST_128() : BlockCipher(8, 11, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void key_schedule(u32bit[16], u32bit[4]);
+
+ static const u32bit S5[256];
+ static const u32bit S6[256];
+ static const u32bit S7[256];
+ static const u32bit S8[256];
+
+ SecureBuffer<u32bit, 16> MK, RK;
+ };
+
+extern const u32bit CAST_SBOX1[256];
+extern const u32bit CAST_SBOX2[256];
+extern const u32bit CAST_SBOX3[256];
+extern const u32bit CAST_SBOX4[256];
+
+}
+
+#endif
diff --git a/botan/src/block/cast/cast256.cpp b/botan/src/block/cast/cast256.cpp
new file mode 100644
index 0000000..22ff876
--- /dev/null
+++ b/botan/src/block/cast/cast256.cpp
@@ -0,0 +1,165 @@
+/*
+* CAST-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cast256.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* CAST-256 Round Type 1
+*/
+void round1(u32bit& out, u32bit in, u32bit mask, u32bit rot)
+ {
+ u32bit temp = rotate_left(mask + in, rot);
+ out ^= (CAST_SBOX1[get_byte(0, temp)] ^ CAST_SBOX2[get_byte(1, temp)]) -
+ CAST_SBOX3[get_byte(2, temp)] + CAST_SBOX4[get_byte(3, temp)];
+ }
+
+/*
+* CAST-256 Round Type 2
+*/
+void round2(u32bit& out, u32bit in, u32bit mask, u32bit rot)
+ {
+ u32bit temp = rotate_left(mask ^ in, rot);
+ out ^= (CAST_SBOX1[get_byte(0, temp)] - CAST_SBOX2[get_byte(1, temp)] +
+ CAST_SBOX3[get_byte(2, temp)]) ^ CAST_SBOX4[get_byte(3, temp)];
+ }
+
+/*
+* CAST-256 Round Type 3
+*/
+void round3(u32bit& out, u32bit in, u32bit mask, u32bit rot)
+ {
+ u32bit temp = rotate_left(mask - in, rot);
+ out ^= ((CAST_SBOX1[get_byte(0, temp)] + CAST_SBOX2[get_byte(1, temp)]) ^
+ CAST_SBOX3[get_byte(2, temp)]) - CAST_SBOX4[get_byte(3, temp)];
+ }
+
+}
+
+/*
+* CAST-256 Encryption
+*/
+void CAST_256::enc(const byte in[], byte out[]) const
+ {
+ u32bit A = load_be<u32bit>(in, 0);
+ u32bit B = load_be<u32bit>(in, 1);
+ u32bit C = load_be<u32bit>(in, 2);
+ u32bit D = load_be<u32bit>(in, 3);
+
+ round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]);
+ round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]);
+ round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]);
+ round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]);
+ round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]);
+ round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]);
+ round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]);
+ round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]);
+ round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]);
+ round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]);
+ round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]);
+ round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]);
+ round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]);
+ round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]);
+ round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]);
+ round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]);
+ round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]);
+ round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]);
+ round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]);
+ round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]);
+ round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]);
+ round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]);
+ round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]);
+ round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]);
+
+ store_be(out, A, B, C, D);
+ }
+
+/*
+* CAST-256 Decryption
+*/
+void CAST_256::dec(const byte in[], byte out[]) const
+ {
+ u32bit A = load_be<u32bit>(in, 0);
+ u32bit B = load_be<u32bit>(in, 1);
+ u32bit C = load_be<u32bit>(in, 2);
+ u32bit D = load_be<u32bit>(in, 3);
+
+ round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]);
+ round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]);
+ round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]);
+ round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]);
+ round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]);
+ round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]);
+ round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]);
+ round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]);
+ round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]);
+ round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]);
+ round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]);
+ round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]);
+ round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]);
+ round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]);
+ round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]);
+ round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]);
+ round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]);
+ round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]);
+ round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]);
+ round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]);
+ round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]);
+ round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]);
+ round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]);
+ round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]);
+
+ store_be(out, A, B, C, D);
+ }
+
+/*
+* CAST-256 Key Schedule
+*/
+void CAST_256::key_schedule(const byte key[], u32bit length)
+ {
+ SecureBuffer<u32bit, 8> TMP;
+ for(u32bit j = 0; j != length; ++j)
+ TMP[j/4] = (TMP[j/4] << 8) + key[j];
+
+ u32bit A = TMP[0], B = TMP[1], C = TMP[2], D = TMP[3],
+ E = TMP[4], F = TMP[5], G = TMP[6], H = TMP[7];
+ for(u32bit j = 0; j != 48; j += 4)
+ {
+ round1(G, H, KEY_MASK[4*j+ 0], KEY_ROT[(4*j+ 0) % 32]);
+ round2(F, G, KEY_MASK[4*j+ 1], KEY_ROT[(4*j+ 1) % 32]);
+ round3(E, F, KEY_MASK[4*j+ 2], KEY_ROT[(4*j+ 2) % 32]);
+ round1(D, E, KEY_MASK[4*j+ 3], KEY_ROT[(4*j+ 3) % 32]);
+ round2(C, D, KEY_MASK[4*j+ 4], KEY_ROT[(4*j+ 4) % 32]);
+ round3(B, C, KEY_MASK[4*j+ 5], KEY_ROT[(4*j+ 5) % 32]);
+ round1(A, B, KEY_MASK[4*j+ 6], KEY_ROT[(4*j+ 6) % 32]);
+ round2(H, A, KEY_MASK[4*j+ 7], KEY_ROT[(4*j+ 7) % 32]);
+ round1(G, H, KEY_MASK[4*j+ 8], KEY_ROT[(4*j+ 8) % 32]);
+ round2(F, G, KEY_MASK[4*j+ 9], KEY_ROT[(4*j+ 9) % 32]);
+ round3(E, F, KEY_MASK[4*j+10], KEY_ROT[(4*j+10) % 32]);
+ round1(D, E, KEY_MASK[4*j+11], KEY_ROT[(4*j+11) % 32]);
+ round2(C, D, KEY_MASK[4*j+12], KEY_ROT[(4*j+12) % 32]);
+ round3(B, C, KEY_MASK[4*j+13], KEY_ROT[(4*j+13) % 32]);
+ round1(A, B, KEY_MASK[4*j+14], KEY_ROT[(4*j+14) % 32]);
+ round2(H, A, KEY_MASK[4*j+15], KEY_ROT[(4*j+15) % 32]);
+
+ RK[j ] = (A % 32);
+ RK[j+1] = (C % 32);
+ RK[j+2] = (E % 32);
+ RK[j+3] = (G % 32);
+ MK[j ] = H;
+ MK[j+1] = F;
+ MK[j+2] = D;
+ MK[j+3] = B;
+ }
+ }
+
+}
diff --git a/botan/src/block/cast/cast256.h b/botan/src/block/cast/cast256.h
new file mode 100644
index 0000000..cd48edd
--- /dev/null
+++ b/botan/src/block/cast/cast256.h
@@ -0,0 +1,44 @@
+/*
+* CAST-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CAST256_H__
+#define BOTAN_CAST256_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CAST-256
+*/
+class BOTAN_DLL CAST_256 : public BlockCipher
+ {
+ public:
+ void clear() throw() { MK.clear(); RK.clear(); }
+ std::string name() const { return "CAST-256"; }
+ BlockCipher* clone() const { return new CAST_256; }
+ CAST_256() : BlockCipher(16, 4, 32, 4) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const u32bit KEY_MASK[192];
+ static const byte KEY_ROT[32];
+
+ SecureBuffer<u32bit, 48> MK;
+ SecureBuffer<byte, 48> RK;
+ };
+
+extern const u32bit CAST_SBOX1[256];
+extern const u32bit CAST_SBOX2[256];
+extern const u32bit CAST_SBOX3[256];
+extern const u32bit CAST_SBOX4[256];
+
+}
+
+#endif
diff --git a/botan/src/block/cast/cast_tab.cpp b/botan/src/block/cast/cast_tab.cpp
new file mode 100644
index 0000000..61c8437
--- /dev/null
+++ b/botan/src/block/cast/cast_tab.cpp
@@ -0,0 +1,412 @@
+/*
+* S-Box Tables for CAST-128 and CAST-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cast128.h>
+#include <botan/cast256.h>
+
+namespace Botan {
+
+const u32bit CAST_SBOX1[256] = {
+ 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 };
+
+const u32bit CAST_SBOX2[256] = {
+ 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 };
+
+const u32bit CAST_SBOX3[256] = {
+ 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 };
+
+const u32bit CAST_SBOX4[256] = {
+ 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 };
+
+const u32bit CAST_128::S5[256] = {
+ 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 };
+
+const u32bit CAST_128::S6[256] = {
+ 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 };
+
+const u32bit CAST_128::S7[256] = {
+ 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 };
+
+const u32bit CAST_128::S8[256] = {
+ 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 };
+
+const u32bit CAST_256::KEY_MASK[192] = {
+ 0x5A827999, 0xC95C653A, 0x383650DB, 0xA7103C7C, 0x15EA281D, 0x84C413BE,
+ 0xF39DFF5F, 0x6277EB00, 0xD151D6A1, 0x402BC242, 0xAF05ADE3, 0x1DDF9984,
+ 0x8CB98525, 0xFB9370C6, 0x6A6D5C67, 0xD9474808, 0x482133A9, 0xB6FB1F4A,
+ 0x25D50AEB, 0x94AEF68C, 0x0388E22D, 0x7262CDCE, 0xE13CB96F, 0x5016A510,
+ 0xBEF090B1, 0x2DCA7C52, 0x9CA467F3, 0x0B7E5394, 0x7A583F35, 0xE9322AD6,
+ 0x580C1677, 0xC6E60218, 0x35BFEDB9, 0xA499D95A, 0x1373C4FB, 0x824DB09C,
+ 0xF1279C3D, 0x600187DE, 0xCEDB737F, 0x3DB55F20, 0xAC8F4AC1, 0x1B693662,
+ 0x8A432203, 0xF91D0DA4, 0x67F6F945, 0xD6D0E4E6, 0x45AAD087, 0xB484BC28,
+ 0x235EA7C9, 0x9238936A, 0x01127F0B, 0x6FEC6AAC, 0xDEC6564D, 0x4DA041EE,
+ 0xBC7A2D8F, 0x2B541930, 0x9A2E04D1, 0x0907F072, 0x77E1DC13, 0xE6BBC7B4,
+ 0x5595B355, 0xC46F9EF6, 0x33498A97, 0xA2237638, 0x10FD61D9, 0x7FD74D7A,
+ 0xEEB1391B, 0x5D8B24BC, 0xCC65105D, 0x3B3EFBFE, 0xAA18E79F, 0x18F2D340,
+ 0x87CCBEE1, 0xF6A6AA82, 0x65809623, 0xD45A81C4, 0x43346D65, 0xB20E5906,
+ 0x20E844A7, 0x8FC23048, 0xFE9C1BE9, 0x6D76078A, 0xDC4FF32B, 0x4B29DECC,
+ 0xBA03CA6D, 0x28DDB60E, 0x97B7A1AF, 0x06918D50, 0x756B78F1, 0xE4456492,
+ 0x531F5033, 0xC1F93BD4, 0x30D32775, 0x9FAD1316, 0x0E86FEB7, 0x7D60EA58,
+ 0xEC3AD5F9, 0x5B14C19A, 0xC9EEAD3B, 0x38C898DC, 0xA7A2847D, 0x167C701E,
+ 0x85565BBF, 0xF4304760, 0x630A3301, 0xD1E41EA2, 0x40BE0A43, 0xAF97F5E4,
+ 0x1E71E185, 0x8D4BCD26, 0xFC25B8C7, 0x6AFFA468, 0xD9D99009, 0x48B37BAA,
+ 0xB78D674B, 0x266752EC, 0x95413E8D, 0x041B2A2E, 0x72F515CF, 0xE1CF0170,
+ 0x50A8ED11, 0xBF82D8B2, 0x2E5CC453, 0x9D36AFF4, 0x0C109B95, 0x7AEA8736,
+ 0xE9C472D7, 0x589E5E78, 0xC7784A19, 0x365235BA, 0xA52C215B, 0x14060CFC,
+ 0x82DFF89D, 0xF1B9E43E, 0x6093CFDF, 0xCF6DBB80, 0x3E47A721, 0xAD2192C2,
+ 0x1BFB7E63, 0x8AD56A04, 0xF9AF55A5, 0x68894146, 0xD7632CE7, 0x463D1888,
+ 0xB5170429, 0x23F0EFCA, 0x92CADB6B, 0x01A4C70C, 0x707EB2AD, 0xDF589E4E,
+ 0x4E3289EF, 0xBD0C7590, 0x2BE66131, 0x9AC04CD2, 0x099A3873, 0x78742414,
+ 0xE74E0FB5, 0x5627FB56, 0xC501E6F7, 0x33DBD298, 0xA2B5BE39, 0x118FA9DA,
+ 0x8069957B, 0xEF43811C, 0x5E1D6CBD, 0xCCF7585E, 0x3BD143FF, 0xAAAB2FA0,
+ 0x19851B41, 0x885F06E2, 0xF738F283, 0x6612DE24, 0xD4ECC9C5, 0x43C6B566,
+ 0xB2A0A107, 0x217A8CA8, 0x90547849, 0xFF2E63EA, 0x6E084F8B, 0xDCE23B2C,
+ 0x4BBC26CD, 0xBA96126E, 0x296FFE0F, 0x9849E9B0, 0x0723D551, 0x75FDC0F2,
+ 0xE4D7AC93, 0x53B19834, 0xC28B83D5, 0x31656F76, 0xA03F5B17, 0x0F1946B8 };
+
+const byte CAST_256::KEY_ROT[32] = {
+ 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0A, 0x1B, 0x0C, 0x1D, 0x0E,
+ 0x1F, 0x10, 0x01, 0x12, 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1A,
+ 0x0B, 0x1C, 0x0D, 0x1E, 0x0F, 0x00, 0x11, 0x02 };
+
+}
diff --git a/botan/src/block/cast/info.txt b/botan/src/block/cast/info.txt
new file mode 100644
index 0000000..73d3f90
--- /dev/null
+++ b/botan/src/block/cast/info.txt
@@ -0,0 +1,13 @@
+realname "CAST"
+
+define CAST
+
+load_on auto
+
+<add>
+cast128.cpp
+cast128.h
+cast256.cpp
+cast256.h
+cast_tab.cpp
+</add>
diff --git a/botan/src/block/des/des.cpp b/botan/src/block/des/des.cpp
new file mode 100644
index 0000000..37520e0
--- /dev/null
+++ b/botan/src/block/des/des.cpp
@@ -0,0 +1,265 @@
+/*
+* DES
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/des.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* DES Key Schedule
+*/
+void des_key_schedule(u32bit round_key[32], const byte key[8])
+ {
+ static const byte ROT[16] = { 1, 1, 2, 2, 2, 2, 2, 2,
+ 1, 2, 2, 2, 2, 2, 2, 1 };
+
+ u32bit C = ((key[7] & 0x80) << 20) | ((key[6] & 0x80) << 19) |
+ ((key[5] & 0x80) << 18) | ((key[4] & 0x80) << 17) |
+ ((key[3] & 0x80) << 16) | ((key[2] & 0x80) << 15) |
+ ((key[1] & 0x80) << 14) | ((key[0] & 0x80) << 13) |
+ ((key[7] & 0x40) << 13) | ((key[6] & 0x40) << 12) |
+ ((key[5] & 0x40) << 11) | ((key[4] & 0x40) << 10) |
+ ((key[3] & 0x40) << 9) | ((key[2] & 0x40) << 8) |
+ ((key[1] & 0x40) << 7) | ((key[0] & 0x40) << 6) |
+ ((key[7] & 0x20) << 6) | ((key[6] & 0x20) << 5) |
+ ((key[5] & 0x20) << 4) | ((key[4] & 0x20) << 3) |
+ ((key[3] & 0x20) << 2) | ((key[2] & 0x20) << 1) |
+ ((key[1] & 0x20) ) | ((key[0] & 0x20) >> 1) |
+ ((key[7] & 0x10) >> 1) | ((key[6] & 0x10) >> 2) |
+ ((key[5] & 0x10) >> 3) | ((key[4] & 0x10) >> 4);
+ u32bit D = ((key[7] & 0x02) << 26) | ((key[6] & 0x02) << 25) |
+ ((key[5] & 0x02) << 24) | ((key[4] & 0x02) << 23) |
+ ((key[3] & 0x02) << 22) | ((key[2] & 0x02) << 21) |
+ ((key[1] & 0x02) << 20) | ((key[0] & 0x02) << 19) |
+ ((key[7] & 0x04) << 17) | ((key[6] & 0x04) << 16) |
+ ((key[5] & 0x04) << 15) | ((key[4] & 0x04) << 14) |
+ ((key[3] & 0x04) << 13) | ((key[2] & 0x04) << 12) |
+ ((key[1] & 0x04) << 11) | ((key[0] & 0x04) << 10) |
+ ((key[7] & 0x08) << 8) | ((key[6] & 0x08) << 7) |
+ ((key[5] & 0x08) << 6) | ((key[4] & 0x08) << 5) |
+ ((key[3] & 0x08) << 4) | ((key[2] & 0x08) << 3) |
+ ((key[1] & 0x08) << 2) | ((key[0] & 0x08) << 1) |
+ ((key[3] & 0x10) >> 1) | ((key[2] & 0x10) >> 2) |
+ ((key[1] & 0x10) >> 3) | ((key[0] & 0x10) >> 4);
+
+ for(u32bit j = 0; j != 16; ++j)
+ {
+ C = ((C << ROT[j]) | (C >> (28-ROT[j]))) & 0x0FFFFFFF;
+ D = ((D << ROT[j]) | (D >> (28-ROT[j]))) & 0x0FFFFFFF;
+ round_key[2*j ] = ((C & 0x00000010) << 22) | ((C & 0x00000800) << 17) |
+ ((C & 0x00000020) << 16) | ((C & 0x00004004) << 15) |
+ ((C & 0x00000200) << 11) | ((C & 0x00020000) << 10) |
+ ((C & 0x01000000) >> 6) | ((C & 0x00100000) >> 4) |
+ ((C & 0x00010000) << 3) | ((C & 0x08000000) >> 2) |
+ ((C & 0x00800000) << 1) | ((D & 0x00000010) << 8) |
+ ((D & 0x00000002) << 7) | ((D & 0x00000001) << 2) |
+ ((D & 0x00000200) ) | ((D & 0x00008000) >> 2) |
+ ((D & 0x00000088) >> 3) | ((D & 0x00001000) >> 7) |
+ ((D & 0x00080000) >> 9) | ((D & 0x02020000) >> 14) |
+ ((D & 0x00400000) >> 21);
+ round_key[2*j+1] = ((C & 0x00000001) << 28) | ((C & 0x00000082) << 18) |
+ ((C & 0x00002000) << 14) | ((C & 0x00000100) << 10) |
+ ((C & 0x00001000) << 9) | ((C & 0x00040000) << 6) |
+ ((C & 0x02400000) << 4) | ((C & 0x00008000) << 2) |
+ ((C & 0x00200000) >> 1) | ((C & 0x04000000) >> 10) |
+ ((D & 0x00000020) << 6) | ((D & 0x00000100) ) |
+ ((D & 0x00000800) >> 1) | ((D & 0x00000040) >> 3) |
+ ((D & 0x00010000) >> 4) | ((D & 0x00000400) >> 5) |
+ ((D & 0x00004000) >> 10) | ((D & 0x04000000) >> 13) |
+ ((D & 0x00800000) >> 14) | ((D & 0x00100000) >> 18) |
+ ((D & 0x01000000) >> 24) | ((D & 0x08000000) >> 26);
+ }
+ }
+
+/*
+* DES Encryption
+*/
+void des_encrypt(u32bit& L, u32bit& R,
+ const u32bit round_key[32])
+ {
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ u32bit T0, T1;
+
+ T0 = rotate_right(R, 4) ^ round_key[2*j];
+ T1 = R ^ round_key[2*j + 1];
+
+ L ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^
+ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^
+ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^
+ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)];
+
+ T0 = rotate_right(L, 4) ^ round_key[2*j + 2];
+ T1 = L ^ round_key[2*j + 3];
+
+ R ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^
+ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^
+ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^
+ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)];
+ }
+ }
+
+/*
+* DES Decryption
+*/
+void des_decrypt(u32bit& L, u32bit& R,
+ const u32bit round_key[32])
+ {
+ for(u32bit j = 16; j != 0; j -= 2)
+ {
+ u32bit T0, T1;
+
+ T0 = rotate_right(R, 4) ^ round_key[2*j - 2];
+ T1 = R ^ round_key[2*j - 1];
+
+ L ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^
+ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^
+ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^
+ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)];
+
+ T0 = rotate_right(L, 4) ^ round_key[2*j - 4];
+ T1 = L ^ round_key[2*j - 3];
+
+ R ^= DES_SPBOX1[get_byte(0, T0)] ^ DES_SPBOX2[get_byte(0, T1)] ^
+ DES_SPBOX3[get_byte(1, T0)] ^ DES_SPBOX4[get_byte(1, T1)] ^
+ DES_SPBOX5[get_byte(2, T0)] ^ DES_SPBOX6[get_byte(2, T1)] ^
+ DES_SPBOX7[get_byte(3, T0)] ^ DES_SPBOX8[get_byte(3, T1)];
+ }
+ }
+
+}
+
+/*
+* DES Encryption
+*/
+void DES::enc(const byte in[], byte out[]) const
+ {
+ u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
+ (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) |
+ (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) |
+ (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] );
+
+ u32bit L = static_cast<u32bit>(T >> 32);
+ u32bit R = static_cast<u32bit>(T);
+
+ des_encrypt(L, R, round_key);
+
+ T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) |
+ (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) |
+ (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) |
+ (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] );
+
+ T = rotate_left(T, 32);
+
+ store_be(T, out);
+ }
+
+/*
+* DES Decryption
+*/
+void DES::dec(const byte in[], byte out[]) const
+ {
+ u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
+ (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) |
+ (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) |
+ (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] );
+
+ u32bit L = static_cast<u32bit>(T >> 32);
+ u32bit R = static_cast<u32bit>(T);
+
+ des_decrypt(L, R, round_key);
+
+ T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) |
+ (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) |
+ (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) |
+ (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] );
+
+ T = rotate_left(T, 32);
+
+ store_be(T, out);
+ }
+
+/*
+* DES Key Schedule
+*/
+void DES::key_schedule(const byte key[], u32bit)
+ {
+ des_key_schedule(round_key.begin(), key);
+ }
+
+/*
+* TripleDES Encryption
+*/
+void TripleDES::enc(const byte in[], byte out[]) const
+ {
+ u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
+ (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) |
+ (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) |
+ (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] );
+
+ u32bit L = static_cast<u32bit>(T >> 32);
+ u32bit R = static_cast<u32bit>(T);
+
+ des_encrypt(L, R, round_key);
+ des_decrypt(R, L, round_key + 32);
+ des_encrypt(L, R, round_key + 64);
+
+ T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) |
+ (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) |
+ (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) |
+ (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] );
+
+ T = rotate_left(T, 32);
+
+ store_be(T, out);
+ }
+
+/*
+* TripleDES Decryption
+*/
+void TripleDES::dec(const byte in[], byte out[]) const
+ {
+ u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) |
+ (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) |
+ (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) |
+ (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] );
+
+ u32bit L = static_cast<u32bit>(T >> 32);
+ u32bit R = static_cast<u32bit>(T);
+
+ des_decrypt(L, R, round_key + 64);
+ des_encrypt(R, L, round_key + 32);
+ des_decrypt(L, R, round_key);
+
+ T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) |
+ (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) |
+ (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) |
+ (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] );
+
+ T = rotate_left(T, 32);
+
+ store_be(T, out);
+ }
+
+/*
+* TripleDES Key Schedule
+*/
+void TripleDES::key_schedule(const byte key[], u32bit length)
+ {
+ des_key_schedule(&round_key[0], key);
+ des_key_schedule(&round_key[32], key + 8);
+
+ if(length == 24)
+ des_key_schedule(&round_key[64], key + 16);
+ else
+ copy_mem(&round_key[64], round_key.begin(), 32);
+ }
+
+}
diff --git a/botan/src/block/des/des.h b/botan/src/block/des/des.h
new file mode 100644
index 0000000..6fa59de
--- /dev/null
+++ b/botan/src/block/des/des.h
@@ -0,0 +1,70 @@
+/*
+* DES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DES_H__
+#define BOTAN_DES_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* DES
+*/
+class BOTAN_DLL DES : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "DES"; }
+ BlockCipher* clone() const { return new DES; }
+ DES() : BlockCipher(8, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 32> round_key;
+ };
+
+/*
+* Triple DES
+*/
+class BOTAN_DLL TripleDES : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "TripleDES"; }
+ BlockCipher* clone() const { return new TripleDES; }
+ TripleDES() : BlockCipher(8, 16, 24, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 96> round_key;
+ };
+
+/*
+* DES Tables
+*/
+extern const u32bit DES_SPBOX1[256];
+extern const u32bit DES_SPBOX2[256];
+extern const u32bit DES_SPBOX3[256];
+extern const u32bit DES_SPBOX4[256];
+extern const u32bit DES_SPBOX5[256];
+extern const u32bit DES_SPBOX6[256];
+extern const u32bit DES_SPBOX7[256];
+extern const u32bit DES_SPBOX8[256];
+
+extern const u64bit DES_IPTAB1[256];
+extern const u64bit DES_IPTAB2[256];
+extern const u64bit DES_FPTAB1[256];
+extern const u64bit DES_FPTAB2[256];
+
+}
+
+#endif
diff --git a/botan/src/block/des/des_tab.cpp b/botan/src/block/des/des_tab.cpp
new file mode 100644
index 0000000..288c7f3
--- /dev/null
+++ b/botan/src/block/des/des_tab.cpp
@@ -0,0 +1,636 @@
+/*
+* Substitution/Permutation Tables for DES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/des.h>
+
+namespace Botan {
+
+const u32bit DES_SPBOX1[256] = {
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404,
+ 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
+ 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404,
+ 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000,
+ 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404,
+ 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004, 0x01010400, 0x00000000,
+ 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004,
+ 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004,
+ 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000,
+ 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004,
+ 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400,
+ 0x00000000, 0x01010004, 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400,
+ 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000,
+ 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404,
+ 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004,
+ 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400,
+ 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004,
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404,
+ 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
+ 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404,
+ 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000,
+ 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404,
+ 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004 };
+
+const u32bit DES_SPBOX2[256] = {
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020,
+ 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
+ 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000,
+ 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000,
+ 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020,
+ 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000, 0x80108020, 0x80008000,
+ 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000,
+ 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020,
+ 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000,
+ 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000,
+ 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020,
+ 0x80108020, 0x00108000, 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020,
+ 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000,
+ 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020,
+ 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020,
+ 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000,
+ 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000,
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020,
+ 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
+ 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000,
+ 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000,
+ 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020,
+ 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000 };
+
+const u32bit DES_SPBOX3[256] = {
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000,
+ 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
+ 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208,
+ 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008,
+ 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208,
+ 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200, 0x00000208, 0x08020200,
+ 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008,
+ 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200,
+ 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200,
+ 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000,
+ 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008,
+ 0x08020008, 0x00020200, 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008,
+ 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000,
+ 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000,
+ 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200,
+ 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208,
+ 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200,
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000,
+ 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
+ 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208,
+ 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008,
+ 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208,
+ 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200 };
+
+const u32bit DES_SPBOX4[256] = {
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081,
+ 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
+ 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080,
+ 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080,
+ 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001,
+ 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080, 0x00802001, 0x00002081,
+ 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000,
+ 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001,
+ 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000,
+ 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081,
+ 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000,
+ 0x00002000, 0x00802080, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000,
+ 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000,
+ 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001,
+ 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081,
+ 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080,
+ 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081,
+ 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
+ 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080,
+ 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080,
+ 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001,
+ 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080 };
+
+const u32bit DES_SPBOX5[256] = {
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100,
+ 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
+ 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000,
+ 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000,
+ 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000,
+ 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100, 0x00000100, 0x02080100,
+ 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000,
+ 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100,
+ 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000,
+ 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100,
+ 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000,
+ 0x02080100, 0x40000100, 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000,
+ 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100,
+ 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100,
+ 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100,
+ 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100,
+ 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100,
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100,
+ 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
+ 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000,
+ 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000,
+ 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000,
+ 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100 };
+
+const u32bit DES_SPBOX6[256] = {
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010,
+ 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
+ 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000,
+ 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000,
+ 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000,
+ 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010, 0x20000010, 0x20400000,
+ 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000,
+ 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000,
+ 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000,
+ 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000,
+ 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000,
+ 0x00400010, 0x20004010, 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010,
+ 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010,
+ 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010,
+ 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010,
+ 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010,
+ 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010,
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010,
+ 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
+ 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000,
+ 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000,
+ 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000,
+ 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010 };
+
+const u32bit DES_SPBOX7[256] = {
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802,
+ 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
+ 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002,
+ 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000,
+ 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000,
+ 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002, 0x00200000, 0x04200002,
+ 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000,
+ 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800,
+ 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002,
+ 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002,
+ 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800,
+ 0x00000800, 0x00200002, 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000,
+ 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000,
+ 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800,
+ 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802,
+ 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802,
+ 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002,
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802,
+ 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
+ 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002,
+ 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000,
+ 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000,
+ 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002 };
+
+const u32bit DES_SPBOX8[256] = {
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040,
+ 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
+ 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000,
+ 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040,
+ 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000,
+ 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000, 0x10001040, 0x00001000,
+ 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040,
+ 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000,
+ 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040,
+ 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040,
+ 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040,
+ 0x10000000, 0x10041000, 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000,
+ 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040,
+ 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000,
+ 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000,
+ 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000,
+ 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000,
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040,
+ 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
+ 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000,
+ 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040,
+ 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000,
+ 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000 };
+
+const u64bit DES_IPTAB1[256] = {
+(u64bit) 0x0000000000000000ULL, (u64bit) 0x0000000200000000ULL, (u64bit) (u64bit) 0x0000000000000002ULL, (u64bit) 0x0000000200000002ULL,
+(u64bit) 0x0000020000000000ULL, (u64bit) 0x0000020200000000ULL, (u64bit) 0x0000020000000002ULL, (u64bit) 0x0000020200000002ULL,
+(u64bit) 0x0000000000000200ULL, (u64bit) 0x0000000200000200ULL, (u64bit) 0x0000000000000202ULL, (u64bit) 0x0000000200000202ULL,
+(u64bit) 0x0000020000000200ULL, (u64bit) 0x0000020200000200ULL, (u64bit) 0x0000020000000202ULL, (u64bit) 0x0000020200000202ULL,
+(u64bit) 0x0002000000000000ULL, (u64bit) 0x0002000200000000ULL, (u64bit) 0x0002000000000002ULL, (u64bit) 0x0002000200000002ULL,
+(u64bit) 0x0002020000000000ULL, (u64bit) 0x0002020200000000ULL, (u64bit) 0x0002020000000002ULL, (u64bit) 0x0002020200000002ULL,
+(u64bit) 0x0002000000000200ULL, (u64bit) 0x0002000200000200ULL, (u64bit) 0x0002000000000202ULL, (u64bit) 0x0002000200000202ULL,
+(u64bit) 0x0002020000000200ULL, (u64bit) 0x0002020200000200ULL, (u64bit) 0x0002020000000202ULL, (u64bit) 0x0002020200000202ULL,
+(u64bit) 0x0000000000020000ULL, (u64bit) 0x0000000200020000ULL, (u64bit) 0x0000000000020002ULL, (u64bit) 0x0000000200020002ULL,
+(u64bit) 0x0000020000020000ULL, (u64bit) 0x0000020200020000ULL, (u64bit) 0x0000020000020002ULL, (u64bit) 0x0000020200020002ULL,
+(u64bit) 0x0000000000020200ULL, (u64bit) 0x0000000200020200ULL, (u64bit) 0x0000000000020202ULL, (u64bit) 0x0000000200020202ULL,
+(u64bit) 0x0000020000020200ULL, (u64bit) 0x0000020200020200ULL, (u64bit) 0x0000020000020202ULL, (u64bit) 0x0000020200020202ULL,
+(u64bit) 0x0002000000020000ULL, (u64bit) 0x0002000200020000ULL, (u64bit) 0x0002000000020002ULL, (u64bit) 0x0002000200020002ULL,
+(u64bit) 0x0002020000020000ULL, (u64bit) 0x0002020200020000ULL, (u64bit) 0x0002020000020002ULL, (u64bit) 0x0002020200020002ULL,
+(u64bit) 0x0002000000020200ULL, (u64bit) 0x0002000200020200ULL, (u64bit) 0x0002000000020202ULL, (u64bit) 0x0002000200020202ULL,
+(u64bit) 0x0002020000020200ULL, (u64bit) 0x0002020200020200ULL, (u64bit) 0x0002020000020202ULL, (u64bit) 0x0002020200020202ULL,
+(u64bit) 0x0200000000000000ULL, (u64bit) 0x0200000200000000ULL, (u64bit) 0x0200000000000002ULL, (u64bit) 0x0200000200000002ULL,
+(u64bit) 0x0200020000000000ULL, (u64bit) 0x0200020200000000ULL, (u64bit) 0x0200020000000002ULL, (u64bit) 0x0200020200000002ULL,
+(u64bit) 0x0200000000000200ULL, (u64bit) 0x0200000200000200ULL, (u64bit) 0x0200000000000202ULL, (u64bit) 0x0200000200000202ULL,
+(u64bit) 0x0200020000000200ULL, (u64bit) 0x0200020200000200ULL, (u64bit) 0x0200020000000202ULL, (u64bit) 0x0200020200000202ULL,
+(u64bit) 0x0202000000000000ULL, (u64bit) 0x0202000200000000ULL, (u64bit) 0x0202000000000002ULL, (u64bit) 0x0202000200000002ULL,
+(u64bit) 0x0202020000000000ULL, (u64bit) 0x0202020200000000ULL, (u64bit) 0x0202020000000002ULL, (u64bit) 0x0202020200000002ULL,
+(u64bit) 0x0202000000000200ULL, (u64bit) 0x0202000200000200ULL, (u64bit) 0x0202000000000202ULL, (u64bit) 0x0202000200000202ULL,
+(u64bit) 0x0202020000000200ULL, (u64bit) 0x0202020200000200ULL, (u64bit) 0x0202020000000202ULL, (u64bit) 0x0202020200000202ULL,
+(u64bit) 0x0200000000020000ULL, (u64bit) 0x0200000200020000ULL, (u64bit) 0x0200000000020002ULL, (u64bit) 0x0200000200020002ULL,
+(u64bit) 0x0200020000020000ULL, (u64bit) 0x0200020200020000ULL, (u64bit) 0x0200020000020002ULL, (u64bit) 0x0200020200020002ULL,
+(u64bit) 0x0200000000020200ULL, (u64bit) 0x0200000200020200ULL, (u64bit) 0x0200000000020202ULL, (u64bit) 0x0200000200020202ULL,
+(u64bit) 0x0200020000020200ULL, (u64bit) 0x0200020200020200ULL, (u64bit) 0x0200020000020202ULL, (u64bit) 0x0200020200020202ULL,
+(u64bit) 0x0202000000020000ULL, (u64bit) 0x0202000200020000ULL, (u64bit) 0x0202000000020002ULL, (u64bit) 0x0202000200020002ULL,
+(u64bit) 0x0202020000020000ULL, (u64bit) 0x0202020200020000ULL, (u64bit) 0x0202020000020002ULL, (u64bit) 0x0202020200020002ULL,
+(u64bit) 0x0202000000020200ULL, (u64bit) 0x0202000200020200ULL, (u64bit) 0x0202000000020202ULL, (u64bit) 0x0202000200020202ULL,
+(u64bit) 0x0202020000020200ULL, (u64bit) 0x0202020200020200ULL, (u64bit) 0x0202020000020202ULL, (u64bit) 0x0202020200020202ULL,
+(u64bit) 0x0000000002000000ULL, (u64bit) 0x0000000202000000ULL, (u64bit) 0x0000000002000002ULL, (u64bit) 0x0000000202000002ULL,
+(u64bit) 0x0000020002000000ULL, (u64bit) 0x0000020202000000ULL, (u64bit) 0x0000020002000002ULL, (u64bit) 0x0000020202000002ULL,
+(u64bit) 0x0000000002000200ULL, (u64bit) 0x0000000202000200ULL, (u64bit) 0x0000000002000202ULL, (u64bit) 0x0000000202000202ULL,
+(u64bit) 0x0000020002000200ULL, (u64bit) 0x0000020202000200ULL, (u64bit) 0x0000020002000202ULL, (u64bit) 0x0000020202000202ULL,
+(u64bit) 0x0002000002000000ULL, (u64bit) 0x0002000202000000ULL, (u64bit) 0x0002000002000002ULL, (u64bit) 0x0002000202000002ULL,
+(u64bit) 0x0002020002000000ULL, (u64bit) 0x0002020202000000ULL, (u64bit) 0x0002020002000002ULL, (u64bit) 0x0002020202000002ULL,
+(u64bit) 0x0002000002000200ULL, (u64bit) 0x0002000202000200ULL, (u64bit) 0x0002000002000202ULL, (u64bit) 0x0002000202000202ULL,
+(u64bit) 0x0002020002000200ULL, (u64bit) 0x0002020202000200ULL, (u64bit) 0x0002020002000202ULL, (u64bit) 0x0002020202000202ULL,
+(u64bit) 0x0000000002020000ULL, (u64bit) 0x0000000202020000ULL, (u64bit) 0x0000000002020002ULL, (u64bit) 0x0000000202020002ULL,
+(u64bit) 0x0000020002020000ULL, (u64bit) 0x0000020202020000ULL, (u64bit) 0x0000020002020002ULL, (u64bit) 0x0000020202020002ULL,
+(u64bit) 0x0000000002020200ULL, (u64bit) 0x0000000202020200ULL, (u64bit) 0x0000000002020202ULL, (u64bit) 0x0000000202020202ULL,
+(u64bit) 0x0000020002020200ULL, (u64bit) 0x0000020202020200ULL, (u64bit) 0x0000020002020202ULL, (u64bit) 0x0000020202020202ULL,
+(u64bit) 0x0002000002020000ULL, (u64bit) 0x0002000202020000ULL, (u64bit) 0x0002000002020002ULL, (u64bit) 0x0002000202020002ULL,
+(u64bit) 0x0002020002020000ULL, (u64bit) 0x0002020202020000ULL, (u64bit) 0x0002020002020002ULL, (u64bit) 0x0002020202020002ULL,
+(u64bit) 0x0002000002020200ULL, (u64bit) 0x0002000202020200ULL, (u64bit) 0x0002000002020202ULL, (u64bit) 0x0002000202020202ULL,
+(u64bit) 0x0002020002020200ULL, (u64bit) 0x0002020202020200ULL, (u64bit) 0x0002020002020202ULL, (u64bit) 0x0002020202020202ULL,
+(u64bit) 0x0200000002000000ULL, (u64bit) 0x0200000202000000ULL, (u64bit) 0x0200000002000002ULL, (u64bit) 0x0200000202000002ULL,
+(u64bit) 0x0200020002000000ULL, (u64bit) 0x0200020202000000ULL, (u64bit) 0x0200020002000002ULL, (u64bit) 0x0200020202000002ULL,
+(u64bit) 0x0200000002000200ULL, (u64bit) 0x0200000202000200ULL, (u64bit) 0x0200000002000202ULL, (u64bit) 0x0200000202000202ULL,
+(u64bit) 0x0200020002000200ULL, (u64bit) 0x0200020202000200ULL, (u64bit) 0x0200020002000202ULL, (u64bit) 0x0200020202000202ULL,
+(u64bit) 0x0202000002000000ULL, (u64bit) 0x0202000202000000ULL, (u64bit) 0x0202000002000002ULL, (u64bit) 0x0202000202000002ULL,
+(u64bit) 0x0202020002000000ULL, (u64bit) 0x0202020202000000ULL, (u64bit) 0x0202020002000002ULL, (u64bit) 0x0202020202000002ULL,
+(u64bit) 0x0202000002000200ULL, (u64bit) 0x0202000202000200ULL, (u64bit) 0x0202000002000202ULL, (u64bit) 0x0202000202000202ULL,
+(u64bit) 0x0202020002000200ULL, (u64bit) 0x0202020202000200ULL, (u64bit) 0x0202020002000202ULL, (u64bit) 0x0202020202000202ULL,
+(u64bit) 0x0200000002020000ULL, (u64bit) 0x0200000202020000ULL, (u64bit) 0x0200000002020002ULL, (u64bit) 0x0200000202020002ULL,
+(u64bit) 0x0200020002020000ULL, (u64bit) 0x0200020202020000ULL, (u64bit) 0x0200020002020002ULL, (u64bit) 0x0200020202020002ULL,
+(u64bit) 0x0200000002020200ULL, (u64bit) 0x0200000202020200ULL, (u64bit) 0x0200000002020202ULL, (u64bit) 0x0200000202020202ULL,
+(u64bit) 0x0200020002020200ULL, (u64bit) 0x0200020202020200ULL, (u64bit) 0x0200020002020202ULL, (u64bit) 0x0200020202020202ULL,
+(u64bit) 0x0202000002020000ULL, (u64bit) 0x0202000202020000ULL, (u64bit) 0x0202000002020002ULL, (u64bit) 0x0202000202020002ULL,
+(u64bit) 0x0202020002020000ULL, (u64bit) 0x0202020202020000ULL, (u64bit) 0x0202020002020002ULL, (u64bit) 0x0202020202020002ULL,
+(u64bit) 0x0202000002020200ULL, (u64bit) 0x0202000202020200ULL, (u64bit) 0x0202000002020202ULL, (u64bit) 0x0202000202020202ULL,
+(u64bit) 0x0202020002020200ULL, (u64bit) 0x0202020202020200ULL, (u64bit) 0x0202020002020202ULL, (u64bit) 0x0202020202020202ULL };
+
+const u64bit DES_IPTAB2[256] = {
+(u64bit) 0x0000000000000000ULL, (u64bit) 0x0000010000000000ULL, (u64bit) 0x0000000000000100ULL, (u64bit) 0x0000010000000100ULL,
+(u64bit) 0x0001000000000000ULL, (u64bit) 0x0001010000000000ULL, (u64bit) 0x0001000000000100ULL, (u64bit) 0x0001010000000100ULL,
+(u64bit) 0x0000000000010000ULL, (u64bit) 0x0000010000010000ULL, (u64bit) 0x0000000000010100ULL, (u64bit) 0x0000010000010100ULL,
+(u64bit) 0x0001000000010000ULL, (u64bit) 0x0001010000010000ULL, (u64bit) 0x0001000000010100ULL, (u64bit) 0x0001010000010100ULL,
+(u64bit) 0x0100000000000000ULL, (u64bit) 0x0100010000000000ULL, (u64bit) 0x0100000000000100ULL, (u64bit) 0x0100010000000100ULL,
+(u64bit) 0x0101000000000000ULL, (u64bit) 0x0101010000000000ULL, (u64bit) 0x0101000000000100ULL, (u64bit) 0x0101010000000100ULL,
+(u64bit) 0x0100000000010000ULL, (u64bit) 0x0100010000010000ULL, (u64bit) 0x0100000000010100ULL, (u64bit) 0x0100010000010100ULL,
+(u64bit) 0x0101000000010000ULL, (u64bit) 0x0101010000010000ULL, (u64bit) 0x0101000000010100ULL, (u64bit) 0x0101010000010100ULL,
+(u64bit) 0x0000000001000000ULL, (u64bit) 0x0000010001000000ULL, (u64bit) 0x0000000001000100ULL, (u64bit) 0x0000010001000100ULL,
+(u64bit) 0x0001000001000000ULL, (u64bit) 0x0001010001000000ULL, (u64bit) 0x0001000001000100ULL, (u64bit) 0x0001010001000100ULL,
+(u64bit) 0x0000000001010000ULL, (u64bit) 0x0000010001010000ULL, (u64bit) 0x0000000001010100ULL, (u64bit) 0x0000010001010100ULL,
+(u64bit) 0x0001000001010000ULL, (u64bit) 0x0001010001010000ULL, (u64bit) 0x0001000001010100ULL, (u64bit) 0x0001010001010100ULL,
+(u64bit) 0x0100000001000000ULL, (u64bit) 0x0100010001000000ULL, (u64bit) 0x0100000001000100ULL, (u64bit) 0x0100010001000100ULL,
+(u64bit) 0x0101000001000000ULL, (u64bit) 0x0101010001000000ULL, (u64bit) 0x0101000001000100ULL, (u64bit) 0x0101010001000100ULL,
+(u64bit) 0x0100000001010000ULL, (u64bit) 0x0100010001010000ULL, (u64bit) 0x0100000001010100ULL, (u64bit) 0x0100010001010100ULL,
+(u64bit) 0x0101000001010000ULL, (u64bit) 0x0101010001010000ULL, (u64bit) 0x0101000001010100ULL, (u64bit) 0x0101010001010100ULL,
+(u64bit) 0x0000000100000000ULL, (u64bit) 0x0000010100000000ULL, (u64bit) 0x0000000100000100ULL, (u64bit) 0x0000010100000100ULL,
+(u64bit) 0x0001000100000000ULL, (u64bit) 0x0001010100000000ULL, (u64bit) 0x0001000100000100ULL, (u64bit) 0x0001010100000100ULL,
+(u64bit) 0x0000000100010000ULL, (u64bit) 0x0000010100010000ULL, (u64bit) 0x0000000100010100ULL, (u64bit) 0x0000010100010100ULL,
+(u64bit) 0x0001000100010000ULL, (u64bit) 0x0001010100010000ULL, (u64bit) 0x0001000100010100ULL, (u64bit) 0x0001010100010100ULL,
+(u64bit) 0x0100000100000000ULL, (u64bit) 0x0100010100000000ULL, (u64bit) 0x0100000100000100ULL, (u64bit) 0x0100010100000100ULL,
+(u64bit) 0x0101000100000000ULL, (u64bit) 0x0101010100000000ULL, (u64bit) 0x0101000100000100ULL, (u64bit) 0x0101010100000100ULL,
+(u64bit) 0x0100000100010000ULL, (u64bit) 0x0100010100010000ULL, (u64bit) 0x0100000100010100ULL, (u64bit) 0x0100010100010100ULL,
+(u64bit) 0x0101000100010000ULL, (u64bit) 0x0101010100010000ULL, (u64bit) 0x0101000100010100ULL, (u64bit) 0x0101010100010100ULL,
+(u64bit) 0x0000000101000000ULL, (u64bit) 0x0000010101000000ULL, (u64bit) 0x0000000101000100ULL, (u64bit) 0x0000010101000100ULL,
+(u64bit) 0x0001000101000000ULL, (u64bit) 0x0001010101000000ULL, (u64bit) 0x0001000101000100ULL, (u64bit) 0x0001010101000100ULL,
+(u64bit) 0x0000000101010000ULL, (u64bit) 0x0000010101010000ULL, (u64bit) 0x0000000101010100ULL, (u64bit) 0x0000010101010100ULL,
+(u64bit) 0x0001000101010000ULL, (u64bit) 0x0001010101010000ULL, (u64bit) 0x0001000101010100ULL, (u64bit) 0x0001010101010100ULL,
+(u64bit) 0x0100000101000000ULL, (u64bit) 0x0100010101000000ULL, (u64bit) 0x0100000101000100ULL, (u64bit) 0x0100010101000100ULL,
+(u64bit) 0x0101000101000000ULL, (u64bit) 0x0101010101000000ULL, (u64bit) 0x0101000101000100ULL, (u64bit) 0x0101010101000100ULL,
+(u64bit) 0x0100000101010000ULL, (u64bit) 0x0100010101010000ULL, (u64bit) 0x0100000101010100ULL, (u64bit) 0x0100010101010100ULL,
+(u64bit) 0x0101000101010000ULL, (u64bit) 0x0101010101010000ULL, (u64bit) 0x0101000101010100ULL, (u64bit) 0x0101010101010100ULL,
+(u64bit) 0x0000000000000001ULL, (u64bit) 0x0000010000000001ULL, (u64bit) 0x0000000000000101ULL, (u64bit) 0x0000010000000101ULL,
+(u64bit) 0x0001000000000001ULL, (u64bit) 0x0001010000000001ULL, (u64bit) 0x0001000000000101ULL, (u64bit) 0x0001010000000101ULL,
+(u64bit) 0x0000000000010001ULL, (u64bit) 0x0000010000010001ULL, (u64bit) 0x0000000000010101ULL, (u64bit) 0x0000010000010101ULL,
+(u64bit) 0x0001000000010001ULL, (u64bit) 0x0001010000010001ULL, (u64bit) 0x0001000000010101ULL, (u64bit) 0x0001010000010101ULL,
+(u64bit) 0x0100000000000001ULL, (u64bit) 0x0100010000000001ULL, (u64bit) 0x0100000000000101ULL, (u64bit) 0x0100010000000101ULL,
+(u64bit) 0x0101000000000001ULL, (u64bit) 0x0101010000000001ULL, (u64bit) 0x0101000000000101ULL, (u64bit) 0x0101010000000101ULL,
+(u64bit) 0x0100000000010001ULL, (u64bit) 0x0100010000010001ULL, (u64bit) 0x0100000000010101ULL, (u64bit) 0x0100010000010101ULL,
+(u64bit) 0x0101000000010001ULL, (u64bit) 0x0101010000010001ULL, (u64bit) 0x0101000000010101ULL, (u64bit) 0x0101010000010101ULL,
+(u64bit) 0x0000000001000001ULL, (u64bit) 0x0000010001000001ULL, (u64bit) 0x0000000001000101ULL, (u64bit) 0x0000010001000101ULL,
+(u64bit) 0x0001000001000001ULL, (u64bit) 0x0001010001000001ULL, (u64bit) 0x0001000001000101ULL, (u64bit) 0x0001010001000101ULL,
+(u64bit) 0x0000000001010001ULL, (u64bit) 0x0000010001010001ULL, (u64bit) 0x0000000001010101ULL, (u64bit) 0x0000010001010101ULL,
+(u64bit) 0x0001000001010001ULL, (u64bit) 0x0001010001010001ULL, (u64bit) 0x0001000001010101ULL, (u64bit) 0x0001010001010101ULL,
+(u64bit) 0x0100000001000001ULL, (u64bit) 0x0100010001000001ULL, (u64bit) 0x0100000001000101ULL, (u64bit) 0x0100010001000101ULL,
+(u64bit) 0x0101000001000001ULL, (u64bit) 0x0101010001000001ULL, (u64bit) 0x0101000001000101ULL, (u64bit) 0x0101010001000101ULL,
+(u64bit) 0x0100000001010001ULL, (u64bit) 0x0100010001010001ULL, (u64bit) 0x0100000001010101ULL, (u64bit) 0x0100010001010101ULL,
+(u64bit) 0x0101000001010001ULL, (u64bit) 0x0101010001010001ULL, (u64bit) 0x0101000001010101ULL, (u64bit) 0x0101010001010101ULL,
+(u64bit) 0x0000000100000001ULL, (u64bit) 0x0000010100000001ULL, (u64bit) 0x0000000100000101ULL, (u64bit) 0x0000010100000101ULL,
+(u64bit) 0x0001000100000001ULL, (u64bit) 0x0001010100000001ULL, (u64bit) 0x0001000100000101ULL, (u64bit) 0x0001010100000101ULL,
+(u64bit) 0x0000000100010001ULL, (u64bit) 0x0000010100010001ULL, (u64bit) 0x0000000100010101ULL, (u64bit) 0x0000010100010101ULL,
+(u64bit) 0x0001000100010001ULL, (u64bit) 0x0001010100010001ULL, (u64bit) 0x0001000100010101ULL, (u64bit) 0x0001010100010101ULL,
+(u64bit) 0x0100000100000001ULL, (u64bit) 0x0100010100000001ULL, (u64bit) 0x0100000100000101ULL, (u64bit) 0x0100010100000101ULL,
+(u64bit) 0x0101000100000001ULL, (u64bit) 0x0101010100000001ULL, (u64bit) 0x0101000100000101ULL, (u64bit) 0x0101010100000101ULL,
+(u64bit) 0x0100000100010001ULL, (u64bit) 0x0100010100010001ULL, (u64bit) 0x0100000100010101ULL, (u64bit) 0x0100010100010101ULL,
+(u64bit) 0x0101000100010001ULL, (u64bit) 0x0101010100010001ULL, (u64bit) 0x0101000100010101ULL, (u64bit) 0x0101010100010101ULL,
+(u64bit) 0x0000000101000001ULL, (u64bit) 0x0000010101000001ULL, (u64bit) 0x0000000101000101ULL, (u64bit) 0x0000010101000101ULL,
+(u64bit) 0x0001000101000001ULL, (u64bit) 0x0001010101000001ULL, (u64bit) 0x0001000101000101ULL, (u64bit) 0x0001010101000101ULL,
+(u64bit) 0x0000000101010001ULL, (u64bit) 0x0000010101010001ULL, (u64bit) 0x0000000101010101ULL, (u64bit) 0x0000010101010101ULL,
+(u64bit) 0x0001000101010001ULL, (u64bit) 0x0001010101010001ULL, (u64bit) 0x0001000101010101ULL, (u64bit) 0x0001010101010101ULL,
+(u64bit) 0x0100000101000001ULL, (u64bit) 0x0100010101000001ULL, (u64bit) 0x0100000101000101ULL, (u64bit) 0x0100010101000101ULL,
+(u64bit) 0x0101000101000001ULL, (u64bit) 0x0101010101000001ULL, (u64bit) 0x0101000101000101ULL, (u64bit) 0x0101010101000101ULL,
+(u64bit) 0x0100000101010001ULL, (u64bit) 0x0100010101010001ULL, (u64bit) 0x0100000101010101ULL, (u64bit) 0x0100010101010101ULL,
+(u64bit) 0x0101000101010001ULL, (u64bit) 0x0101010101010001ULL, (u64bit) 0x0101000101010101ULL, (u64bit) 0x0101010101010101ULL };
+
+const u64bit DES_FPTAB1[256] = {
+(u64bit) 0x0000000000000000ULL, (u64bit) 0x0000000100000000ULL, (u64bit) 0x0000000004000000ULL, (u64bit) 0x0000000104000000ULL,
+(u64bit) 0x0000000000040000ULL, (u64bit) 0x0000000100040000ULL, (u64bit) 0x0000000004040000ULL, (u64bit) 0x0000000104040000ULL,
+(u64bit) 0x0000000000000400ULL, (u64bit) 0x0000000100000400ULL, (u64bit) 0x0000000004000400ULL, (u64bit) 0x0000000104000400ULL,
+(u64bit) 0x0000000000040400ULL, (u64bit) 0x0000000100040400ULL, (u64bit) 0x0000000004040400ULL, (u64bit) 0x0000000104040400ULL,
+(u64bit) 0x0000000000000004ULL, (u64bit) 0x0000000100000004ULL, (u64bit) 0x0000000004000004ULL, (u64bit) 0x0000000104000004ULL,
+(u64bit) 0x0000000000040004ULL, (u64bit) 0x0000000100040004ULL, (u64bit) 0x0000000004040004ULL, (u64bit) 0x0000000104040004ULL,
+(u64bit) 0x0000000000000404ULL, (u64bit) 0x0000000100000404ULL, (u64bit) 0x0000000004000404ULL, (u64bit) 0x0000000104000404ULL,
+(u64bit) 0x0000000000040404ULL, (u64bit) 0x0000000100040404ULL, (u64bit) 0x0000000004040404ULL, (u64bit) 0x0000000104040404ULL,
+(u64bit) 0x0400000000000000ULL, (u64bit) 0x0400000100000000ULL, (u64bit) 0x0400000004000000ULL, (u64bit) 0x0400000104000000ULL,
+(u64bit) 0x0400000000040000ULL, (u64bit) 0x0400000100040000ULL, (u64bit) 0x0400000004040000ULL, (u64bit) 0x0400000104040000ULL,
+(u64bit) 0x0400000000000400ULL, (u64bit) 0x0400000100000400ULL, (u64bit) 0x0400000004000400ULL, (u64bit) 0x0400000104000400ULL,
+(u64bit) 0x0400000000040400ULL, (u64bit) 0x0400000100040400ULL, (u64bit) 0x0400000004040400ULL, (u64bit) 0x0400000104040400ULL,
+(u64bit) 0x0400000000000004ULL, (u64bit) 0x0400000100000004ULL, (u64bit) 0x0400000004000004ULL, (u64bit) 0x0400000104000004ULL,
+(u64bit) 0x0400000000040004ULL, (u64bit) 0x0400000100040004ULL, (u64bit) 0x0400000004040004ULL, (u64bit) 0x0400000104040004ULL,
+(u64bit) 0x0400000000000404ULL, (u64bit) 0x0400000100000404ULL, (u64bit) 0x0400000004000404ULL, (u64bit) 0x0400000104000404ULL,
+(u64bit) 0x0400000000040404ULL, (u64bit) 0x0400000100040404ULL, (u64bit) 0x0400000004040404ULL, (u64bit) 0x0400000104040404ULL,
+(u64bit) 0x0004000000000000ULL, (u64bit) 0x0004000100000000ULL, (u64bit) 0x0004000004000000ULL, (u64bit) 0x0004000104000000ULL,
+(u64bit) 0x0004000000040000ULL, (u64bit) 0x0004000100040000ULL, (u64bit) 0x0004000004040000ULL, (u64bit) 0x0004000104040000ULL,
+(u64bit) 0x0004000000000400ULL, (u64bit) 0x0004000100000400ULL, (u64bit) 0x0004000004000400ULL, (u64bit) 0x0004000104000400ULL,
+(u64bit) 0x0004000000040400ULL, (u64bit) 0x0004000100040400ULL, (u64bit) 0x0004000004040400ULL, (u64bit) 0x0004000104040400ULL,
+(u64bit) 0x0004000000000004ULL, (u64bit) 0x0004000100000004ULL, (u64bit) 0x0004000004000004ULL, (u64bit) 0x0004000104000004ULL,
+(u64bit) 0x0004000000040004ULL, (u64bit) 0x0004000100040004ULL, (u64bit) 0x0004000004040004ULL, (u64bit) 0x0004000104040004ULL,
+(u64bit) 0x0004000000000404ULL, (u64bit) 0x0004000100000404ULL, (u64bit) 0x0004000004000404ULL, (u64bit) 0x0004000104000404ULL,
+(u64bit) 0x0004000000040404ULL, (u64bit) 0x0004000100040404ULL, (u64bit) 0x0004000004040404ULL, (u64bit) 0x0004000104040404ULL,
+(u64bit) 0x0404000000000000ULL, (u64bit) 0x0404000100000000ULL, (u64bit) 0x0404000004000000ULL, (u64bit) 0x0404000104000000ULL,
+(u64bit) 0x0404000000040000ULL, (u64bit) 0x0404000100040000ULL, (u64bit) 0x0404000004040000ULL, (u64bit) 0x0404000104040000ULL,
+(u64bit) 0x0404000000000400ULL, (u64bit) 0x0404000100000400ULL, (u64bit) 0x0404000004000400ULL, (u64bit) 0x0404000104000400ULL,
+(u64bit) 0x0404000000040400ULL, (u64bit) 0x0404000100040400ULL, (u64bit) 0x0404000004040400ULL, (u64bit) 0x0404000104040400ULL,
+(u64bit) 0x0404000000000004ULL, (u64bit) 0x0404000100000004ULL, (u64bit) 0x0404000004000004ULL, (u64bit) 0x0404000104000004ULL,
+(u64bit) 0x0404000000040004ULL, (u64bit) 0x0404000100040004ULL, (u64bit) 0x0404000004040004ULL, (u64bit) 0x0404000104040004ULL,
+(u64bit) 0x0404000000000404ULL, (u64bit) 0x0404000100000404ULL, (u64bit) 0x0404000004000404ULL, (u64bit) 0x0404000104000404ULL,
+(u64bit) 0x0404000000040404ULL, (u64bit) 0x0404000100040404ULL, (u64bit) 0x0404000004040404ULL, (u64bit) 0x0404000104040404ULL,
+(u64bit) 0x0000040000000000ULL, (u64bit) 0x0000040100000000ULL, (u64bit) 0x0000040004000000ULL, (u64bit) 0x0000040104000000ULL,
+(u64bit) 0x0000040000040000ULL, (u64bit) 0x0000040100040000ULL, (u64bit) 0x0000040004040000ULL, (u64bit) 0x0000040104040000ULL,
+(u64bit) 0x0000040000000400ULL, (u64bit) 0x0000040100000400ULL, (u64bit) 0x0000040004000400ULL, (u64bit) 0x0000040104000400ULL,
+(u64bit) 0x0000040000040400ULL, (u64bit) 0x0000040100040400ULL, (u64bit) 0x0000040004040400ULL, (u64bit) 0x0000040104040400ULL,
+(u64bit) 0x0000040000000004ULL, (u64bit) 0x0000040100000004ULL, (u64bit) 0x0000040004000004ULL, (u64bit) 0x0000040104000004ULL,
+(u64bit) 0x0000040000040004ULL, (u64bit) 0x0000040100040004ULL, (u64bit) 0x0000040004040004ULL, (u64bit) 0x0000040104040004ULL,
+(u64bit) 0x0000040000000404ULL, (u64bit) 0x0000040100000404ULL, (u64bit) 0x0000040004000404ULL, (u64bit) 0x0000040104000404ULL,
+(u64bit) 0x0000040000040404ULL, (u64bit) 0x0000040100040404ULL, (u64bit) 0x0000040004040404ULL, (u64bit) 0x0000040104040404ULL,
+(u64bit) 0x0400040000000000ULL, (u64bit) 0x0400040100000000ULL, (u64bit) 0x0400040004000000ULL, (u64bit) 0x0400040104000000ULL,
+(u64bit) 0x0400040000040000ULL, (u64bit) 0x0400040100040000ULL, (u64bit) 0x0400040004040000ULL, (u64bit) 0x0400040104040000ULL,
+(u64bit) 0x0400040000000400ULL, (u64bit) 0x0400040100000400ULL, (u64bit) 0x0400040004000400ULL, (u64bit) 0x0400040104000400ULL,
+(u64bit) 0x0400040000040400ULL, (u64bit) 0x0400040100040400ULL, (u64bit) 0x0400040004040400ULL, (u64bit) 0x0400040104040400ULL,
+(u64bit) 0x0400040000000004ULL, (u64bit) 0x0400040100000004ULL, (u64bit) 0x0400040004000004ULL, (u64bit) 0x0400040104000004ULL,
+(u64bit) 0x0400040000040004ULL, (u64bit) 0x0400040100040004ULL, (u64bit) 0x0400040004040004ULL, (u64bit) 0x0400040104040004ULL,
+(u64bit) 0x0400040000000404ULL, (u64bit) 0x0400040100000404ULL, (u64bit) 0x0400040004000404ULL, (u64bit) 0x0400040104000404ULL,
+(u64bit) 0x0400040000040404ULL, (u64bit) 0x0400040100040404ULL, (u64bit) 0x0400040004040404ULL, (u64bit) 0x0400040104040404ULL,
+(u64bit) 0x0004040000000000ULL, (u64bit) 0x0004040100000000ULL, (u64bit) 0x0004040004000000ULL, (u64bit) 0x0004040104000000ULL,
+(u64bit) 0x0004040000040000ULL, (u64bit) 0x0004040100040000ULL, (u64bit) 0x0004040004040000ULL, (u64bit) 0x0004040104040000ULL,
+(u64bit) 0x0004040000000400ULL, (u64bit) 0x0004040100000400ULL, (u64bit) 0x0004040004000400ULL, (u64bit) 0x0004040104000400ULL,
+(u64bit) 0x0004040000040400ULL, (u64bit) 0x0004040100040400ULL, (u64bit) 0x0004040004040400ULL, (u64bit) 0x0004040104040400ULL,
+(u64bit) 0x0004040000000004ULL, (u64bit) 0x0004040100000004ULL, (u64bit) 0x0004040004000004ULL, (u64bit) 0x0004040104000004ULL,
+(u64bit) 0x0004040000040004ULL, (u64bit) 0x0004040100040004ULL, (u64bit) 0x0004040004040004ULL, (u64bit) 0x0004040104040004ULL,
+(u64bit) 0x0004040000000404ULL, (u64bit) 0x0004040100000404ULL, (u64bit) 0x0004040004000404ULL, (u64bit) 0x0004040104000404ULL,
+(u64bit) 0x0004040000040404ULL, (u64bit) 0x0004040100040404ULL, (u64bit) 0x0004040004040404ULL, (u64bit) 0x0004040104040404ULL,
+(u64bit) 0x0404040000000000ULL, (u64bit) 0x0404040100000000ULL, (u64bit) 0x0404040004000000ULL, (u64bit) 0x0404040104000000ULL,
+(u64bit) 0x0404040000040000ULL, (u64bit) 0x0404040100040000ULL, (u64bit) 0x0404040004040000ULL, (u64bit) 0x0404040104040000ULL,
+(u64bit) 0x0404040000000400ULL, (u64bit) 0x0404040100000400ULL, (u64bit) 0x0404040004000400ULL, (u64bit) 0x0404040104000400ULL,
+(u64bit) 0x0404040000040400ULL, (u64bit) 0x0404040100040400ULL, (u64bit) 0x0404040004040400ULL, (u64bit) 0x0404040104040400ULL,
+(u64bit) 0x0404040000000004ULL, (u64bit) 0x0404040100000004ULL, (u64bit) 0x0404040004000004ULL, (u64bit) 0x0404040104000004ULL,
+(u64bit) 0x0404040000040004ULL, (u64bit) 0x0404040100040004ULL, (u64bit) 0x0404040004040004ULL, (u64bit) 0x0404040104040004ULL,
+(u64bit) 0x0404040000000404ULL, (u64bit) 0x0404040100000404ULL, (u64bit) 0x0404040004000404ULL, (u64bit) 0x0404040104000404ULL,
+(u64bit) 0x0404040000040404ULL, (u64bit) 0x0404040100040404ULL, (u64bit) 0x0404040004040404ULL, (u64bit) 0x0404040104040404ULL };
+
+const u64bit DES_FPTAB2[256] = {
+(u64bit) 0x0000000000000000ULL, (u64bit) 0x0000004000000000ULL, (u64bit) 0x0000000001000000ULL, (u64bit) 0x0000004001000000ULL,
+(u64bit) 0x0000000000010000ULL, (u64bit) 0x0000004000010000ULL, (u64bit) 0x0000000001010000ULL, (u64bit) 0x0000004001010000ULL,
+(u64bit) 0x0000000000000100ULL, (u64bit) 0x0000004000000100ULL, (u64bit) 0x0000000001000100ULL, (u64bit) 0x0000004001000100ULL,
+(u64bit) 0x0000000000010100ULL, (u64bit) 0x0000004000010100ULL, (u64bit) 0x0000000001010100ULL, (u64bit) 0x0000004001010100ULL,
+(u64bit) 0x0000000000000001ULL, (u64bit) 0x0000004000000001ULL, (u64bit) 0x0000000001000001ULL, (u64bit) 0x0000004001000001ULL,
+(u64bit) 0x0000000000010001ULL, (u64bit) 0x0000004000010001ULL, (u64bit) 0x0000000001010001ULL, (u64bit) 0x0000004001010001ULL,
+(u64bit) 0x0000000000000101ULL, (u64bit) 0x0000004000000101ULL, (u64bit) 0x0000000001000101ULL, (u64bit) 0x0000004001000101ULL,
+(u64bit) 0x0000000000010101ULL, (u64bit) 0x0000004000010101ULL, (u64bit) 0x0000000001010101ULL, (u64bit) 0x0000004001010101ULL,
+(u64bit) 0x0100000000000000ULL, (u64bit) 0x0100004000000000ULL, (u64bit) 0x0100000001000000ULL, (u64bit) 0x0100004001000000ULL,
+(u64bit) 0x0100000000010000ULL, (u64bit) 0x0100004000010000ULL, (u64bit) 0x0100000001010000ULL, (u64bit) 0x0100004001010000ULL,
+(u64bit) 0x0100000000000100ULL, (u64bit) 0x0100004000000100ULL, (u64bit) 0x0100000001000100ULL, (u64bit) 0x0100004001000100ULL,
+(u64bit) 0x0100000000010100ULL, (u64bit) 0x0100004000010100ULL, (u64bit) 0x0100000001010100ULL, (u64bit) 0x0100004001010100ULL,
+(u64bit) 0x0100000000000001ULL, (u64bit) 0x0100004000000001ULL, (u64bit) 0x0100000001000001ULL, (u64bit) 0x0100004001000001ULL,
+(u64bit) 0x0100000000010001ULL, (u64bit) 0x0100004000010001ULL, (u64bit) 0x0100000001010001ULL, (u64bit) 0x0100004001010001ULL,
+(u64bit) 0x0100000000000101ULL, (u64bit) 0x0100004000000101ULL, (u64bit) 0x0100000001000101ULL, (u64bit) 0x0100004001000101ULL,
+(u64bit) 0x0100000000010101ULL, (u64bit) 0x0100004000010101ULL, (u64bit) 0x0100000001010101ULL, (u64bit) 0x0100004001010101ULL,
+(u64bit) 0x0001000000000000ULL, (u64bit) 0x0001004000000000ULL, (u64bit) 0x0001000001000000ULL, (u64bit) 0x0001004001000000ULL,
+(u64bit) 0x0001000000010000ULL, (u64bit) 0x0001004000010000ULL, (u64bit) 0x0001000001010000ULL, (u64bit) 0x0001004001010000ULL,
+(u64bit) 0x0001000000000100ULL, (u64bit) 0x0001004000000100ULL, (u64bit) 0x0001000001000100ULL, (u64bit) 0x0001004001000100ULL,
+(u64bit) 0x0001000000010100ULL, (u64bit) 0x0001004000010100ULL, (u64bit) 0x0001000001010100ULL, (u64bit) 0x0001004001010100ULL,
+(u64bit) 0x0001000000000001ULL, (u64bit) 0x0001004000000001ULL, (u64bit) 0x0001000001000001ULL, (u64bit) 0x0001004001000001ULL,
+(u64bit) 0x0001000000010001ULL, (u64bit) 0x0001004000010001ULL, (u64bit) 0x0001000001010001ULL, (u64bit) 0x0001004001010001ULL,
+(u64bit) 0x0001000000000101ULL, (u64bit) 0x0001004000000101ULL, (u64bit) 0x0001000001000101ULL, (u64bit) 0x0001004001000101ULL,
+(u64bit) 0x0001000000010101ULL, (u64bit) 0x0001004000010101ULL, (u64bit) 0x0001000001010101ULL, (u64bit) 0x0001004001010101ULL,
+(u64bit) 0x0101000000000000ULL, (u64bit) 0x0101004000000000ULL, (u64bit) 0x0101000001000000ULL, (u64bit) 0x0101004001000000ULL,
+(u64bit) 0x0101000000010000ULL, (u64bit) 0x0101004000010000ULL, (u64bit) 0x0101000001010000ULL, (u64bit) 0x0101004001010000ULL,
+(u64bit) 0x0101000000000100ULL, (u64bit) 0x0101004000000100ULL, (u64bit) 0x0101000001000100ULL, (u64bit) 0x0101004001000100ULL,
+(u64bit) 0x0101000000010100ULL, (u64bit) 0x0101004000010100ULL, (u64bit) 0x0101000001010100ULL, (u64bit) 0x0101004001010100ULL,
+(u64bit) 0x0101000000000001ULL, (u64bit) 0x0101004000000001ULL, (u64bit) 0x0101000001000001ULL, (u64bit) 0x0101004001000001ULL,
+(u64bit) 0x0101000000010001ULL, (u64bit) 0x0101004000010001ULL, (u64bit) 0x0101000001010001ULL, (u64bit) 0x0101004001010001ULL,
+(u64bit) 0x0101000000000101ULL, (u64bit) 0x0101004000000101ULL, (u64bit) 0x0101000001000101ULL, (u64bit) 0x0101004001000101ULL,
+(u64bit) 0x0101000000010101ULL, (u64bit) 0x0101004000010101ULL, (u64bit) 0x0101000001010101ULL, (u64bit) 0x0101004001010101ULL,
+(u64bit) 0x0000010000000000ULL, (u64bit) 0x0000014000000000ULL, (u64bit) 0x0000010001000000ULL, (u64bit) 0x0000014001000000ULL,
+(u64bit) 0x0000010000010000ULL, (u64bit) 0x0000014000010000ULL, (u64bit) 0x0000010001010000ULL, (u64bit) 0x0000014001010000ULL,
+(u64bit) 0x0000010000000100ULL, (u64bit) 0x0000014000000100ULL, (u64bit) 0x0000010001000100ULL, (u64bit) 0x0000014001000100ULL,
+(u64bit) 0x0000010000010100ULL, (u64bit) 0x0000014000010100ULL, (u64bit) 0x0000010001010100ULL, (u64bit) 0x0000014001010100ULL,
+(u64bit) 0x0000010000000001ULL, (u64bit) 0x0000014000000001ULL, (u64bit) 0x0000010001000001ULL, (u64bit) 0x0000014001000001ULL,
+(u64bit) 0x0000010000010001ULL, (u64bit) 0x0000014000010001ULL, (u64bit) 0x0000010001010001ULL, (u64bit) 0x0000014001010001ULL,
+(u64bit) 0x0000010000000101ULL, (u64bit) 0x0000014000000101ULL, (u64bit) 0x0000010001000101ULL, (u64bit) 0x0000014001000101ULL,
+(u64bit) 0x0000010000010101ULL, (u64bit) 0x0000014000010101ULL, (u64bit) 0x0000010001010101ULL, (u64bit) 0x0000014001010101ULL,
+(u64bit) 0x0100010000000000ULL, (u64bit) 0x0100014000000000ULL, (u64bit) 0x0100010001000000ULL, (u64bit) 0x0100014001000000ULL,
+(u64bit) 0x0100010000010000ULL, (u64bit) 0x0100014000010000ULL, (u64bit) 0x0100010001010000ULL, (u64bit) 0x0100014001010000ULL,
+(u64bit) 0x0100010000000100ULL, (u64bit) 0x0100014000000100ULL, (u64bit) 0x0100010001000100ULL, (u64bit) 0x0100014001000100ULL,
+(u64bit) 0x0100010000010100ULL, (u64bit) 0x0100014000010100ULL, (u64bit) 0x0100010001010100ULL, (u64bit) 0x0100014001010100ULL,
+(u64bit) 0x0100010000000001ULL, (u64bit) 0x0100014000000001ULL, (u64bit) 0x0100010001000001ULL, (u64bit) 0x0100014001000001ULL,
+(u64bit) 0x0100010000010001ULL, (u64bit) 0x0100014000010001ULL, (u64bit) 0x0100010001010001ULL, (u64bit) 0x0100014001010001ULL,
+(u64bit) 0x0100010000000101ULL, (u64bit) 0x0100014000000101ULL, (u64bit) 0x0100010001000101ULL, (u64bit) 0x0100014001000101ULL,
+(u64bit) 0x0100010000010101ULL, (u64bit) 0x0100014000010101ULL, (u64bit) 0x0100010001010101ULL, (u64bit) 0x0100014001010101ULL,
+(u64bit) 0x0001010000000000ULL, (u64bit) 0x0001014000000000ULL, (u64bit) 0x0001010001000000ULL, (u64bit) 0x0001014001000000ULL,
+(u64bit) 0x0001010000010000ULL, (u64bit) 0x0001014000010000ULL, (u64bit) 0x0001010001010000ULL, (u64bit) 0x0001014001010000ULL,
+(u64bit) 0x0001010000000100ULL, (u64bit) 0x0001014000000100ULL, (u64bit) 0x0001010001000100ULL, (u64bit) 0x0001014001000100ULL,
+(u64bit) 0x0001010000010100ULL, (u64bit) 0x0001014000010100ULL, (u64bit) 0x0001010001010100ULL, (u64bit) 0x0001014001010100ULL,
+(u64bit) 0x0001010000000001ULL, (u64bit) 0x0001014000000001ULL, (u64bit) 0x0001010001000001ULL, (u64bit) 0x0001014001000001ULL,
+(u64bit) 0x0001010000010001ULL, (u64bit) 0x0001014000010001ULL, (u64bit) 0x0001010001010001ULL, (u64bit) 0x0001014001010001ULL,
+(u64bit) 0x0001010000000101ULL, (u64bit) 0x0001014000000101ULL, (u64bit) 0x0001010001000101ULL, (u64bit) 0x0001014001000101ULL,
+(u64bit) 0x0001010000010101ULL, (u64bit) 0x0001014000010101ULL, (u64bit) 0x0001010001010101ULL, (u64bit) 0x0001014001010101ULL,
+(u64bit) 0x0101010000000000ULL, (u64bit) 0x0101014000000000ULL, (u64bit) 0x0101010001000000ULL, (u64bit) 0x0101014001000000ULL,
+(u64bit) 0x0101010000010000ULL, (u64bit) 0x0101014000010000ULL, (u64bit) 0x0101010001010000ULL, (u64bit) 0x0101014001010000ULL,
+(u64bit) 0x0101010000000100ULL, (u64bit) 0x0101014000000100ULL, (u64bit) 0x0101010001000100ULL, (u64bit) 0x0101014001000100ULL,
+(u64bit) 0x0101010000010100ULL, (u64bit) 0x0101014000010100ULL, (u64bit) 0x0101010001010100ULL, (u64bit) 0x0101014001010100ULL,
+(u64bit) 0x0101010000000001ULL, (u64bit) 0x0101014000000001ULL, (u64bit) 0x0101010001000001ULL, (u64bit) 0x0101014001000001ULL,
+(u64bit) 0x0101010000010001ULL, (u64bit) 0x0101014000010001ULL, (u64bit) 0x0101010001010001ULL, (u64bit) 0x0101014001010001ULL,
+(u64bit) 0x0101010000000101ULL, (u64bit) 0x0101014000000101ULL, (u64bit) 0x0101010001000101ULL, (u64bit) 0x0101014001000101ULL,
+(u64bit) 0x0101010000010101ULL, (u64bit) 0x0101014000010101ULL, (u64bit) 0x0101010001010101ULL, (u64bit) 0x0101014001010101ULL };
+
+}
diff --git a/botan/src/block/des/desx.cpp b/botan/src/block/des/desx.cpp
new file mode 100644
index 0000000..e557901
--- /dev/null
+++ b/botan/src/block/des/desx.cpp
@@ -0,0 +1,43 @@
+/*
+* DES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/desx.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* DESX Encryption
+*/
+void DESX::enc(const byte in[], byte out[]) const
+ {
+ xor_buf(out, in, K1.begin(), BLOCK_SIZE);
+ des.encrypt(out);
+ xor_buf(out, K2.begin(), BLOCK_SIZE);
+ }
+
+/*
+* DESX Decryption
+*/
+void DESX::dec(const byte in[], byte out[]) const
+ {
+ xor_buf(out, in, K2.begin(), BLOCK_SIZE);
+ des.decrypt(out);
+ xor_buf(out, K1.begin(), BLOCK_SIZE);
+ }
+
+/*
+* DESX Key Schedule
+*/
+void DESX::key_schedule(const byte key[], u32bit)
+ {
+ K1.copy(key, 8);
+ des.set_key(key + 8, 8);
+ K2.copy(key + 16, 8);
+ }
+
+}
diff --git a/botan/src/block/des/desx.h b/botan/src/block/des/desx.h
new file mode 100644
index 0000000..49ecc24
--- /dev/null
+++ b/botan/src/block/des/desx.h
@@ -0,0 +1,35 @@
+/*
+* DESX
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DESX_H__
+#define BOTAN_DESX_H__
+
+#include <botan/des.h>
+
+namespace Botan {
+
+/*
+* DESX
+*/
+class BOTAN_DLL DESX : public BlockCipher
+ {
+ public:
+ void clear() throw() { des.clear(); K1.clear(); K2.clear(); }
+ std::string name() const { return "DESX"; }
+ BlockCipher* clone() const { return new DESX; }
+ DESX() : BlockCipher(8, 24) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<byte, 8> K1, K2;
+ DES des;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/des/info.txt b/botan/src/block/des/info.txt
new file mode 100644
index 0000000..ed05979
--- /dev/null
+++ b/botan/src/block/des/info.txt
@@ -0,0 +1,13 @@
+realname "DES"
+
+define DES
+
+load_on auto
+
+<add>
+des.cpp
+des.h
+des_tab.cpp
+desx.h
+desx.cpp
+</add>
diff --git a/botan/src/block/gost_28147/gost_28147.cpp b/botan/src/block/gost_28147/gost_28147.cpp
new file mode 100644
index 0000000..bfd092c
--- /dev/null
+++ b/botan/src/block/gost_28147/gost_28147.cpp
@@ -0,0 +1,139 @@
+/*
+* GOST 28147-89
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/gost_28147.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+byte GOST_28147_89_Params::sbox_entry(u32bit row, u32bit col) const
+ {
+ byte x = sboxes[4 * col + (row / 2)];
+
+ return (row % 2 == 0) ? (x >> 4) : (x & 0x0F);
+ }
+
+GOST_28147_89_Params::GOST_28147_89_Params(const std::string& n) : name(n)
+ {
+ // Encoded in the packed fromat from RFC 4357
+
+ // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0)
+ static const byte GOST_R_3411_TEST_PARAMS[64] = {
+ 0x4E, 0x57, 0x64, 0xD1, 0xAB, 0x8D, 0xCB, 0xBF, 0x94, 0x1A, 0x7A,
+ 0x4D, 0x2C, 0xD1, 0x10, 0x10, 0xD6, 0xA0, 0x57, 0x35, 0x8D, 0x38,
+ 0xF2, 0xF7, 0x0F, 0x49, 0xD1, 0x5A, 0xEA, 0x2F, 0x8D, 0x94, 0x62,
+ 0xEE, 0x43, 0x09, 0xB3, 0xF4, 0xA6, 0xA2, 0x18, 0xC6, 0x98, 0xE3,
+ 0xC1, 0x7C, 0xE5, 0x7E, 0x70, 0x6B, 0x09, 0x66, 0xF7, 0x02, 0x3C,
+ 0x8B, 0x55, 0x95, 0xBF, 0x28, 0x39, 0xB3, 0x2E, 0xCC };
+
+ // GostR3411-94-CryptoProParamSet (OID 1.2.643.2.2.31.1)
+ static const byte GOST_R_3411_CRYPTOPRO_PARAMS[64] = {
+ 0xA5, 0x74, 0x77, 0xD1, 0x4F, 0xFA, 0x66, 0xE3, 0x54, 0xC7, 0x42,
+ 0x4A, 0x60, 0xEC, 0xB4, 0x19, 0x82, 0x90, 0x9D, 0x75, 0x1D, 0x4F,
+ 0xC9, 0x0B, 0x3B, 0x12, 0x2F, 0x54, 0x79, 0x08, 0xA0, 0xAF, 0xD1,
+ 0x3E, 0x1A, 0x38, 0xC7, 0xB1, 0x81, 0xC6, 0xE6, 0x56, 0x05, 0x87,
+ 0x03, 0x25, 0xEB, 0xFE, 0x9C, 0x6D, 0xF8, 0x6D, 0x2E, 0xAB, 0xDE,
+ 0x20, 0xBA, 0x89, 0x3C, 0x92, 0xF8, 0xD3, 0x53, 0xBC };
+
+ if(name == "R3411_94_TestParam")
+ sboxes = GOST_R_3411_TEST_PARAMS;
+ else if(name == "R3411_CryptoPro")
+ sboxes = GOST_R_3411_CRYPTOPRO_PARAMS;
+ else
+ throw Invalid_Argument("GOST_28147_89_Params: Unknown " + name);
+ }
+
+/*
+* GOST Constructor
+*/
+GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) :
+ BlockCipher(8, 32)
+ {
+ // Convert the parallel 4x4 sboxes into larger word-based sboxes
+ for(size_t i = 0; i != 4; ++i)
+ for(size_t j = 0; j != 256; ++j)
+ {
+ u32bit T = (param.sbox_entry(2*i , j % 16)) |
+ (param.sbox_entry(2*i+1, j / 16) << 4);
+ SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32);
+ }
+ }
+
+/*
+* Two rounds of GOST
+*/
+#define GOST_2ROUND(N1, N2, R1, R2) \
+ do { \
+ u32bit T0 = N1 + EK[R1]; \
+ N2 ^= SBOX[get_byte(3, T0)] | \
+ SBOX[get_byte(2, T0)+256] | \
+ SBOX[get_byte(1, T0)+512] | \
+ SBOX[get_byte(0, T0)+768]; \
+ \
+ u32bit T1 = N2 + EK[R2]; \
+ N1 ^= SBOX[get_byte(3, T1)] | \
+ SBOX[get_byte(2, T1)+256] | \
+ SBOX[get_byte(1, T1)+512] | \
+ SBOX[get_byte(0, T1)+768]; \
+ } while(0)
+
+/*
+* GOST Encryption
+*/
+void GOST_28147_89::enc(const byte in[], byte out[]) const
+ {
+ u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
+
+ for(size_t i = 0; i != 3; ++i)
+ {
+ GOST_2ROUND(N1, N2, 0, 1);
+ GOST_2ROUND(N1, N2, 2, 3);
+ GOST_2ROUND(N1, N2, 4, 5);
+ GOST_2ROUND(N1, N2, 6, 7);
+ }
+
+ GOST_2ROUND(N1, N2, 7, 6);
+ GOST_2ROUND(N1, N2, 5, 4);
+ GOST_2ROUND(N1, N2, 3, 2);
+ GOST_2ROUND(N1, N2, 1, 0);
+
+ store_le(out, N2, N1);
+ }
+
+/*
+* GOST Decryption
+*/
+void GOST_28147_89::dec(const byte in[], byte out[]) const
+ {
+ u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
+
+ GOST_2ROUND(N1, N2, 0, 1);
+ GOST_2ROUND(N1, N2, 2, 3);
+ GOST_2ROUND(N1, N2, 4, 5);
+ GOST_2ROUND(N1, N2, 6, 7);
+
+ for(size_t i = 0; i != 3; ++i)
+ {
+ GOST_2ROUND(N1, N2, 7, 6);
+ GOST_2ROUND(N1, N2, 5, 4);
+ GOST_2ROUND(N1, N2, 3, 2);
+ GOST_2ROUND(N1, N2, 1, 0);
+ }
+
+ store_le(out, N2, N1);
+ }
+
+/*
+* GOST Key Schedule
+*/
+void GOST_28147_89::key_schedule(const byte key[], u32bit)
+ {
+ for(u32bit j = 0; j != 8; ++j)
+ EK[j] = load_le<u32bit>(key, j);
+ }
+
+}
diff --git a/botan/src/block/gost_28147/gost_28147.h b/botan/src/block/gost_28147/gost_28147.h
new file mode 100644
index 0000000..96d24c6
--- /dev/null
+++ b/botan/src/block/gost_28147/gost_28147.h
@@ -0,0 +1,67 @@
+/*
+* GOST 28147-89
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GOST_28147_89_H__
+#define BOTAN_GOST_28147_89_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+class GOST_28147_89_Params;
+
+/**
+* The GOST 28147-89 block cipher uses a set of 4 bit Sboxes, however
+* the standard does not actually define these Sboxes; they are
+* considered a local configuration issue. Several different sets are
+* used.
+*/
+class GOST_28147_89_Params
+ {
+ public:
+ byte sbox_entry(u32bit row, u32bit col) const;
+
+ std::string param_name() const { return name; }
+
+ /**
+ * Default GOST parameters are the ones given in GOST R 34.11 for
+ * testing purposes; these sboxes are also used by Crypto++, and,
+ * at least according to Wikipedia, the Central Bank of Russian Federation
+ */
+ GOST_28147_89_Params(const std::string& name = "R3411_94_TestParam");
+ private:
+ const byte* sboxes;
+ std::string name;
+ };
+
+/**
+* GOST 28147-89
+*/
+class BOTAN_DLL GOST_28147_89 : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+
+ std::string name() const { return "GOST-28147-89"; }
+ BlockCipher* clone() const { return new GOST_28147_89(SBOX); }
+
+ GOST_28147_89(const GOST_28147_89_Params& params);
+ private:
+ GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) :
+ BlockCipher(8, 32), SBOX(other_SBOX) {}
+
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 1024> SBOX;
+ SecureBuffer<u32bit, 8> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/gost_28147/info.txt b/botan/src/block/gost_28147/info.txt
new file mode 100644
index 0000000..6e187fd
--- /dev/null
+++ b/botan/src/block/gost_28147/info.txt
@@ -0,0 +1,10 @@
+realname "GOST 28147-89"
+
+define GOST_28147_89
+
+load_on auto
+
+<add>
+gost_28147.cpp
+gost_28147.h
+</add>
diff --git a/botan/src/block/idea/idea.cpp b/botan/src/block/idea/idea.cpp
new file mode 100644
index 0000000..5bbe470
--- /dev/null
+++ b/botan/src/block/idea/idea.cpp
@@ -0,0 +1,174 @@
+/*
+* IDEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/idea.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Multiplication modulo 65537
+*/
+inline u16bit mul(u16bit x, u16bit y)
+ {
+ if(x && y)
+ {
+ u32bit T = static_cast<u32bit>(x) * y;
+ x = static_cast<u16bit>(T >> 16);
+ y = static_cast<u16bit>(T & 0xFFFF);
+ return static_cast<u16bit>(y - x + ((y < x) ? 1 : 0));
+ }
+ else
+ return static_cast<u16bit>(1 - x - y);
+ }
+
+/*
+* Find multiplicative inverses modulo 65537
+*/
+u16bit mul_inv(u16bit x)
+ {
+ if(x <= 1)
+ return x;
+
+ u16bit t0 = static_cast<u16bit>(65537 / x), t1 = 1;
+ u16bit y = static_cast<u16bit>(65537 % x);
+
+ while(y != 1)
+ {
+ u16bit q = x / y;
+ x %= y;
+ t1 += q * t0;
+
+ if(x == 1)
+ return t1;
+
+ q = y / x;
+ y %= x;
+ t0 += q * t1;
+ }
+ return (1 - t0);
+ }
+
+}
+
+/*
+* IDEA Encryption
+*/
+void IDEA::enc(const byte in[], byte out[]) const
+ {
+ u16bit X1 = load_be<u16bit>(in, 0);
+ u16bit X2 = load_be<u16bit>(in, 1);
+ u16bit X3 = load_be<u16bit>(in, 2);
+ u16bit X4 = load_be<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ X1 = mul(X1, EK[6*j+0]);
+ X2 += EK[6*j+1];
+ X3 += EK[6*j+2];
+ X4 = mul(X4, EK[6*j+3]);
+
+ u16bit T0 = X3;
+ X3 = mul(X3 ^ X1, EK[6*j+4]);
+
+ u16bit T1 = X2;
+ X2 = mul((X2 ^ X4) + X3, EK[6*j+5]);
+ X3 += X2;
+
+ X1 ^= X2;
+ X4 ^= X3;
+ X2 ^= T0;
+ X3 ^= T1;
+ }
+
+ X1 = mul(X1, EK[48]);
+ X2 += EK[50];
+ X3 += EK[49];
+ X4 = mul(X4, EK[51]);
+
+ store_be(out, X1, X3, X2, X4);
+ }
+
+/*
+* IDEA Decryption
+*/
+void IDEA::dec(const byte in[], byte out[]) const
+ {
+ u16bit X1 = load_be<u16bit>(in, 0);
+ u16bit X2 = load_be<u16bit>(in, 1);
+ u16bit X3 = load_be<u16bit>(in, 2);
+ u16bit X4 = load_be<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ X1 = mul(X1, DK[6*j+0]);
+ X2 += DK[6*j+1];
+ X3 += DK[6*j+2];
+ X4 = mul(X4, DK[6*j+3]);
+
+ u16bit T0 = X3;
+ X3 = mul(X3 ^ X1, DK[6*j+4]);
+
+ u16bit T1 = X2;
+ X2 = mul((X2 ^ X4) + X3, DK[6*j+5]);
+ X3 += X2;
+
+ X1 ^= X2;
+ X4 ^= X3;
+ X2 ^= T0;
+ X3 ^= T1;
+ }
+
+ X1 = mul(X1, DK[48]);
+ X2 += DK[50];
+ X3 += DK[49];
+ X4 = mul(X4, DK[51]);
+
+ store_be(out, X1, X3, X2, X4);
+ }
+
+/*
+* IDEA Key Schedule
+*/
+void IDEA::key_schedule(const byte key[], u32bit)
+ {
+ for(u32bit j = 0; j != 8; ++j)
+ EK[j] = load_be<u16bit>(key, j);
+
+ for(u32bit j = 1, k = 8, offset = 0; k != 52; j %= 8, ++j, ++k)
+ {
+ EK[j+7+offset] = static_cast<u16bit>((EK[(j % 8) + offset] << 9) |
+ (EK[((j+1) % 8) + offset] >> 7));
+ offset += (j == 8) ? 8 : 0;
+ }
+
+ DK[51] = mul_inv(EK[3]);
+ DK[50] = -EK[2];
+ DK[49] = -EK[1];
+ DK[48] = mul_inv(EK[0]);
+
+ for(u32bit j = 1, k = 4, counter = 47; j != 8; ++j, k += 6)
+ {
+ DK[counter--] = EK[k+1];
+ DK[counter--] = EK[k];
+ DK[counter--] = mul_inv(EK[k+5]);
+ DK[counter--] = -EK[k+3];
+ DK[counter--] = -EK[k+4];
+ DK[counter--] = mul_inv(EK[k+2]);
+ }
+
+ DK[5] = EK[47];
+ DK[4] = EK[46];
+ DK[3] = mul_inv(EK[51]);
+ DK[2] = -EK[50];
+ DK[1] = -EK[49];
+ DK[0] = mul_inv(EK[48]);
+ }
+
+}
diff --git a/botan/src/block/idea/idea.h b/botan/src/block/idea/idea.h
new file mode 100644
index 0000000..2c53cd0
--- /dev/null
+++ b/botan/src/block/idea/idea.h
@@ -0,0 +1,34 @@
+/*
+* IDEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IDEA_H__
+#define BOTAN_IDEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* IDEA
+*/
+class BOTAN_DLL IDEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); DK.clear(); }
+ std::string name() const { return "IDEA"; }
+ BlockCipher* clone() const { return new IDEA; }
+ IDEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u16bit, 52> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/idea/info.txt b/botan/src/block/idea/info.txt
new file mode 100644
index 0000000..2da3ffb
--- /dev/null
+++ b/botan/src/block/idea/info.txt
@@ -0,0 +1,10 @@
+realname "IDEA"
+
+define IDEA
+
+load_on auto
+
+<add>
+idea.cpp
+idea.h
+</add>
diff --git a/botan/src/block/info.txt b/botan/src/block/info.txt
new file mode 100644
index 0000000..ff48fb0
--- /dev/null
+++ b/botan/src/block/info.txt
@@ -0,0 +1,13 @@
+realname "Block Ciphers"
+
+load_on auto
+
+define BLOCK_CIPHER
+
+<add>
+block_cipher.h
+</add>
+
+<requires>
+sym_algo
+</requires>
diff --git a/botan/src/block/kasumi/info.txt b/botan/src/block/kasumi/info.txt
new file mode 100644
index 0000000..8ea879b
--- /dev/null
+++ b/botan/src/block/kasumi/info.txt
@@ -0,0 +1,10 @@
+realname "Kasumi"
+
+define KASUMI
+
+load_on auto
+
+<add>
+kasumi.cpp
+kasumi.h
+</add>
diff --git a/botan/src/block/kasumi/kasumi.cpp b/botan/src/block/kasumi/kasumi.cpp
new file mode 100644
index 0000000..e051dde
--- /dev/null
+++ b/botan/src/block/kasumi/kasumi.cpp
@@ -0,0 +1,215 @@
+/*
+* KASUMI
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kasumi.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* KASUMI S-Boxes
+*/
+const byte KASUMI_SBOX_S7[128] = {
+ 0x36, 0x32, 0x3E, 0x38, 0x16, 0x22, 0x5E, 0x60, 0x26, 0x06, 0x3F, 0x5D,
+ 0x02, 0x12, 0x7B, 0x21, 0x37, 0x71, 0x27, 0x72, 0x15, 0x43, 0x41, 0x0C,
+ 0x2F, 0x49, 0x2E, 0x1B, 0x19, 0x6F, 0x7C, 0x51, 0x35, 0x09, 0x79, 0x4F,
+ 0x34, 0x3C, 0x3A, 0x30, 0x65, 0x7F, 0x28, 0x78, 0x68, 0x46, 0x47, 0x2B,
+ 0x14, 0x7A, 0x48, 0x3D, 0x17, 0x6D, 0x0D, 0x64, 0x4D, 0x01, 0x10, 0x07,
+ 0x52, 0x0A, 0x69, 0x62, 0x75, 0x74, 0x4C, 0x0B, 0x59, 0x6A, 0x00, 0x7D,
+ 0x76, 0x63, 0x56, 0x45, 0x1E, 0x39, 0x7E, 0x57, 0x70, 0x33, 0x11, 0x05,
+ 0x5F, 0x0E, 0x5A, 0x54, 0x5B, 0x08, 0x23, 0x67, 0x20, 0x61, 0x1C, 0x42,
+ 0x66, 0x1F, 0x1A, 0x2D, 0x4B, 0x04, 0x55, 0x5C, 0x25, 0x4A, 0x50, 0x31,
+ 0x44, 0x1D, 0x73, 0x2C, 0x40, 0x6B, 0x6C, 0x18, 0x6E, 0x53, 0x24, 0x4E,
+ 0x2A, 0x13, 0x0F, 0x29, 0x58, 0x77, 0x3B, 0x03 };
+
+const u16bit KASUMI_SBOX_S9[512] = {
+ 0x00A7, 0x00EF, 0x00A1, 0x017B, 0x0187, 0x014E, 0x0009, 0x0152, 0x0026,
+ 0x00E2, 0x0030, 0x0166, 0x01C4, 0x0181, 0x005A, 0x018D, 0x00B7, 0x00FD,
+ 0x0093, 0x014B, 0x019F, 0x0154, 0x0033, 0x016A, 0x0132, 0x01F4, 0x0106,
+ 0x0052, 0x00D8, 0x009F, 0x0164, 0x00B1, 0x00AF, 0x00F1, 0x01E9, 0x0025,
+ 0x00CE, 0x0011, 0x0000, 0x014D, 0x002C, 0x00FE, 0x017A, 0x003A, 0x008F,
+ 0x00DC, 0x0051, 0x0190, 0x005F, 0x0003, 0x013B, 0x00F5, 0x0036, 0x00EB,
+ 0x00DA, 0x0195, 0x01D8, 0x0108, 0x00AC, 0x01EE, 0x0173, 0x0122, 0x018F,
+ 0x004C, 0x00A5, 0x00C5, 0x018B, 0x0079, 0x0101, 0x01E0, 0x01A7, 0x00D4,
+ 0x00F0, 0x001C, 0x01CE, 0x00B0, 0x0196, 0x01FB, 0x0120, 0x00DF, 0x01F5,
+ 0x0197, 0x00F9, 0x0109, 0x0059, 0x00BA, 0x00DD, 0x01AC, 0x00A4, 0x004A,
+ 0x01B8, 0x00C4, 0x01CA, 0x01A5, 0x015E, 0x00A3, 0x00E8, 0x009E, 0x0086,
+ 0x0162, 0x000D, 0x00FA, 0x01EB, 0x008E, 0x00BF, 0x0045, 0x00C1, 0x01A9,
+ 0x0098, 0x00E3, 0x016E, 0x0087, 0x0158, 0x012C, 0x0114, 0x00F2, 0x01B5,
+ 0x0140, 0x0071, 0x0116, 0x000B, 0x00F3, 0x0057, 0x013D, 0x0024, 0x005D,
+ 0x01F0, 0x001B, 0x01E7, 0x01BE, 0x01E2, 0x0029, 0x0044, 0x009C, 0x01C9,
+ 0x0083, 0x0146, 0x0193, 0x0153, 0x0014, 0x0027, 0x0073, 0x01BA, 0x007C,
+ 0x01DB, 0x0180, 0x01FC, 0x0035, 0x0070, 0x00AA, 0x01DF, 0x0097, 0x007E,
+ 0x00A9, 0x0049, 0x010C, 0x0117, 0x0141, 0x00A8, 0x016C, 0x016B, 0x0124,
+ 0x002E, 0x01F3, 0x0189, 0x0147, 0x0144, 0x0018, 0x01C8, 0x010B, 0x009D,
+ 0x01CC, 0x01E8, 0x01AA, 0x0135, 0x00E5, 0x01B7, 0x01FA, 0x00D0, 0x010F,
+ 0x015D, 0x0191, 0x01B2, 0x00EC, 0x0010, 0x00D1, 0x0167, 0x0034, 0x0038,
+ 0x0078, 0x00C7, 0x0115, 0x01D1, 0x01A0, 0x00FC, 0x011F, 0x00F6, 0x0006,
+ 0x0053, 0x0131, 0x01A4, 0x0159, 0x0099, 0x01F6, 0x0041, 0x003D, 0x00F4,
+ 0x011A, 0x00AD, 0x00DE, 0x01A2, 0x0043, 0x0182, 0x0170, 0x0105, 0x0065,
+ 0x01DC, 0x0123, 0x00C3, 0x01AE, 0x0031, 0x004F, 0x00A6, 0x014A, 0x0118,
+ 0x017F, 0x0175, 0x0080, 0x017E, 0x0198, 0x009B, 0x01EF, 0x016F, 0x0184,
+ 0x0112, 0x006B, 0x01CB, 0x01A1, 0x003E, 0x01C6, 0x0084, 0x00E1, 0x00CB,
+ 0x013C, 0x00EA, 0x000E, 0x012D, 0x005B, 0x01F7, 0x011E, 0x01A8, 0x00D3,
+ 0x015B, 0x0133, 0x008C, 0x0176, 0x0023, 0x0067, 0x007D, 0x01AB, 0x0013,
+ 0x00D6, 0x01C5, 0x0092, 0x01F2, 0x013A, 0x01BC, 0x00E6, 0x0100, 0x0149,
+ 0x00C6, 0x011D, 0x0032, 0x0074, 0x004E, 0x019A, 0x000A, 0x00CD, 0x01FE,
+ 0x00AB, 0x00E7, 0x002D, 0x008B, 0x01D3, 0x001D, 0x0056, 0x01F9, 0x0020,
+ 0x0048, 0x001A, 0x0156, 0x0096, 0x0139, 0x01EA, 0x01AF, 0x00EE, 0x019B,
+ 0x0145, 0x0095, 0x01D9, 0x0028, 0x0077, 0x00AE, 0x0163, 0x00B9, 0x00E9,
+ 0x0185, 0x0047, 0x01C0, 0x0111, 0x0174, 0x0037, 0x006E, 0x00B2, 0x0142,
+ 0x000C, 0x01D5, 0x0188, 0x0171, 0x00BE, 0x0001, 0x006D, 0x0177, 0x0089,
+ 0x00B5, 0x0058, 0x004B, 0x0134, 0x0104, 0x01E4, 0x0062, 0x0110, 0x0172,
+ 0x0113, 0x019C, 0x006F, 0x0150, 0x013E, 0x0004, 0x01F8, 0x01EC, 0x0103,
+ 0x0130, 0x004D, 0x0151, 0x01B3, 0x0015, 0x0165, 0x012F, 0x014C, 0x01E3,
+ 0x0012, 0x002F, 0x0055, 0x0019, 0x01F1, 0x01DA, 0x0121, 0x0064, 0x010D,
+ 0x0128, 0x01DE, 0x010E, 0x006A, 0x001F, 0x0068, 0x01B1, 0x0054, 0x019E,
+ 0x01E6, 0x018A, 0x0060, 0x0063, 0x009A, 0x01FF, 0x0094, 0x019D, 0x0169,
+ 0x0199, 0x00FF, 0x00A2, 0x00D7, 0x012E, 0x00C9, 0x010A, 0x015F, 0x0157,
+ 0x0090, 0x01B9, 0x016D, 0x006C, 0x012A, 0x00FB, 0x0022, 0x00B6, 0x01FD,
+ 0x008A, 0x00D2, 0x014F, 0x0085, 0x0137, 0x0160, 0x0148, 0x008D, 0x018C,
+ 0x015A, 0x007B, 0x013F, 0x01C2, 0x0119, 0x01AD, 0x00E4, 0x01BB, 0x01E1,
+ 0x005C, 0x0194, 0x01E5, 0x01A6, 0x00F8, 0x0129, 0x0017, 0x00D5, 0x0082,
+ 0x01D2, 0x0016, 0x00D9, 0x011B, 0x0046, 0x0126, 0x0168, 0x01A3, 0x007F,
+ 0x0138, 0x0179, 0x0007, 0x01D4, 0x00C2, 0x0002, 0x0075, 0x0127, 0x01CF,
+ 0x0102, 0x00E0, 0x01BF, 0x00F7, 0x00BB, 0x0050, 0x018E, 0x011C, 0x0161,
+ 0x0069, 0x0186, 0x012B, 0x01D7, 0x01D6, 0x00B8, 0x0039, 0x00C8, 0x015C,
+ 0x003F, 0x00CC, 0x00BC, 0x0021, 0x01C3, 0x0061, 0x001E, 0x0136, 0x00DB,
+ 0x005E, 0x00A0, 0x0081, 0x01ED, 0x0040, 0x00B3, 0x0107, 0x0066, 0x00BD,
+ 0x00CF, 0x0072, 0x0192, 0x01B6, 0x01DD, 0x0183, 0x007A, 0x00C0, 0x002A,
+ 0x017D, 0x0005, 0x0091, 0x0076, 0x00B4, 0x01C1, 0x0125, 0x0143, 0x0088,
+ 0x017C, 0x002B, 0x0042, 0x003C, 0x01C7, 0x0155, 0x01BD, 0x00CA, 0x01B0,
+ 0x0008, 0x00ED, 0x000F, 0x0178, 0x01B4, 0x01D0, 0x003B, 0x01CD };
+
+/*
+* KASUMI FI Function
+*/
+u16bit FI(u16bit I, u16bit K)
+ {
+ u16bit D9 = (I >> 7);
+ byte D7 = (I & 0x7F);
+ D9 = KASUMI_SBOX_S9[D9] ^ D7;
+ D7 = KASUMI_SBOX_S7[D7] ^ (D9 & 0x7F);
+
+ D7 ^= (K >> 9);
+ D9 = KASUMI_SBOX_S9[D9 ^ (K & 0x1FF)] ^ D7;
+ D7 = KASUMI_SBOX_S7[D7] ^ (D9 & 0x7F);
+ return (D7 << 9) | D9;
+ }
+
+}
+
+/*
+* KASUMI Encryption
+*/
+void KASUMI::enc(const byte in[], byte out[]) const
+ {
+ u16bit B0 = load_be<u16bit>(in, 0);
+ u16bit B1 = load_be<u16bit>(in, 1);
+ u16bit B2 = load_be<u16bit>(in, 2);
+ u16bit B3 = load_be<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 8; j += 2)
+ {
+ const u16bit* K = EK + 8*j;
+
+ u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]);
+ u16bit L = B0 ^ (rotate_left(R, 1) | K[1]);
+
+ L = FI(L ^ K[ 2], K[ 3]) ^ R;
+ R = FI(R ^ K[ 4], K[ 5]) ^ L;
+ L = FI(L ^ K[ 6], K[ 7]) ^ R;
+
+ R = B2 ^= R;
+ L = B3 ^= L;
+
+ R = FI(R ^ K[10], K[11]) ^ L;
+ L = FI(L ^ K[12], K[13]) ^ R;
+ R = FI(R ^ K[14], K[15]) ^ L;
+
+ R ^= (rotate_left(L, 1) & K[8]);
+ L ^= (rotate_left(R, 1) | K[9]);
+
+ B0 ^= L;
+ B1 ^= R;
+ }
+
+ store_be(out, B0, B1, B2, B3);
+ }
+
+/*
+* KASUMI Decryption
+*/
+void KASUMI::dec(const byte in[], byte out[]) const
+ {
+ u16bit B0 = load_be<u16bit>(in, 0);
+ u16bit B1 = load_be<u16bit>(in, 1);
+ u16bit B2 = load_be<u16bit>(in, 2);
+ u16bit B3 = load_be<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 8; j += 2)
+ {
+ const u16bit* K = EK + 8*(6-j);
+
+ u16bit L = B2, R = B3;
+
+ L = FI(L ^ K[10], K[11]) ^ R;
+ R = FI(R ^ K[12], K[13]) ^ L;
+ L = FI(L ^ K[14], K[15]) ^ R;
+
+ L ^= (rotate_left(R, 1) & K[8]);
+ R ^= (rotate_left(L, 1) | K[9]);
+
+ R = B0 ^= R;
+ L = B1 ^= L;
+
+ L ^= (rotate_left(R, 1) & K[0]);
+ R ^= (rotate_left(L, 1) | K[1]);
+
+ R = FI(R ^ K[2], K[3]) ^ L;
+ L = FI(L ^ K[4], K[5]) ^ R;
+ R = FI(R ^ K[6], K[7]) ^ L;
+
+ B2 ^= L;
+ B3 ^= R;
+ }
+
+ store_be(out, B0, B1, B2, B3);
+ }
+
+/*
+* KASUMI Key Schedule
+*/
+void KASUMI::key_schedule(const byte key[], u32bit)
+ {
+ static const u16bit RC[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF,
+ 0xFEDC, 0xBA98, 0x7654, 0x3210 };
+
+ SecureBuffer<u16bit, 16> K;
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ K[j] = load_be<u16bit>(key, j);
+ K[j+8] = K[j] ^ RC[j];
+ }
+
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ EK[8*j ] = rotate_left(K[(j+0) % 8 ], 2);
+ EK[8*j+1] = rotate_left(K[(j+2) % 8 + 8], 1);
+ EK[8*j+2] = rotate_left(K[(j+1) % 8 ], 5);
+ EK[8*j+3] = K[(j+4) % 8 + 8];
+ EK[8*j+4] = rotate_left(K[(j+5) % 8 ], 8);
+ EK[8*j+5] = K[(j+3) % 8 + 8];
+ EK[8*j+6] = rotate_left(K[(j+6) % 8 ], 13);
+ EK[8*j+7] = K[(j+7) % 8 + 8];
+ }
+ }
+
+}
diff --git a/botan/src/block/kasumi/kasumi.h b/botan/src/block/kasumi/kasumi.h
new file mode 100644
index 0000000..df49fa9
--- /dev/null
+++ b/botan/src/block/kasumi/kasumi.h
@@ -0,0 +1,36 @@
+/*
+* KASUMI
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KASUMI_H__
+#define BOTAN_KASUMI_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* KASUMI
+*/
+class BOTAN_DLL KASUMI : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "KASUMI"; }
+ BlockCipher* clone() const { return new KASUMI; }
+
+ KASUMI() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 64> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/lion/info.txt b/botan/src/block/lion/info.txt
new file mode 100644
index 0000000..81ef585
--- /dev/null
+++ b/botan/src/block/lion/info.txt
@@ -0,0 +1,15 @@
+realname "Lion"
+
+define LION
+
+load_on auto
+
+<add>
+lion.cpp
+lion.h
+</add>
+
+<requires>
+hash
+stream
+</requires>
diff --git a/botan/src/block/lion/lion.cpp b/botan/src/block/lion/lion.cpp
new file mode 100644
index 0000000..c7cdf6d
--- /dev/null
+++ b/botan/src/block/lion/lion.cpp
@@ -0,0 +1,114 @@
+/*
+* Lion
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lion.h>
+#include <botan/xor_buf.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Lion Encryption
+*/
+void Lion::enc(const byte in[], byte out[]) const
+ {
+ SecureVector<byte> buffer(LEFT_SIZE);
+
+ xor_buf(buffer, in, key1, LEFT_SIZE);
+ cipher->set_key(buffer, LEFT_SIZE);
+ cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE);
+
+ hash->update(out + LEFT_SIZE, RIGHT_SIZE);
+ hash->final(buffer);
+ xor_buf(out, in, buffer, LEFT_SIZE);
+
+ xor_buf(buffer, out, key2, LEFT_SIZE);
+ cipher->set_key(buffer, LEFT_SIZE);
+ cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE);
+ }
+
+/*
+* Lion Decryption
+*/
+void Lion::dec(const byte in[], byte out[]) const
+ {
+ SecureVector<byte> buffer(LEFT_SIZE);
+
+ xor_buf(buffer, in, key2, LEFT_SIZE);
+ cipher->set_key(buffer, LEFT_SIZE);
+ cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE);
+
+ hash->update(out + LEFT_SIZE, RIGHT_SIZE);
+ hash->final(buffer);
+ xor_buf(out, in, buffer, LEFT_SIZE);
+
+ xor_buf(buffer, out, key1, LEFT_SIZE);
+ cipher->set_key(buffer, LEFT_SIZE);
+ cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE);
+ }
+
+/*
+* Lion Key Schedule
+*/
+void Lion::key_schedule(const byte key[], u32bit length)
+ {
+ clear();
+
+ key1.copy(key, length / 2);
+ key2.copy(key + length / 2, length / 2);
+ }
+
+/*
+* Return the name of this type
+*/
+std::string Lion::name() const
+ {
+ return "Lion(" + hash->name() + "," +
+ cipher->name() + "," +
+ to_string(BLOCK_SIZE) + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+BlockCipher* Lion::clone() const
+ {
+ return new Lion(hash->clone(), cipher->clone(), BLOCK_SIZE);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Lion::clear() throw()
+ {
+ hash->clear();
+ cipher->clear();
+ key1.clear();
+ key2.clear();
+ }
+
+/*
+* Lion Constructor
+*/
+Lion::Lion(HashFunction* hash_in, StreamCipher* sc_in, u32bit block_len) :
+ BlockCipher(std::max<u32bit>(2*hash_in->OUTPUT_LENGTH + 1, block_len),
+ 2, 2*hash_in->OUTPUT_LENGTH, 2),
+ LEFT_SIZE(hash_in->OUTPUT_LENGTH),
+ RIGHT_SIZE(BLOCK_SIZE - LEFT_SIZE),
+ hash(hash_in),
+ cipher(sc_in)
+ {
+ if(2*LEFT_SIZE + 1 > BLOCK_SIZE)
+ throw Invalid_Argument(name() + ": Chosen block size is too small");
+ if(!cipher->valid_keylength(LEFT_SIZE))
+ throw Exception(name() + ": This stream/hash combination is invalid");
+
+ key1.create(LEFT_SIZE);
+ key2.create(LEFT_SIZE);
+ }
+
+}
diff --git a/botan/src/block/lion/lion.h b/botan/src/block/lion/lion.h
new file mode 100644
index 0000000..5bc4e72
--- /dev/null
+++ b/botan/src/block/lion/lion.h
@@ -0,0 +1,43 @@
+/*
+* Lion
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LION_H__
+#define BOTAN_LION_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Lion
+*/
+class BOTAN_DLL Lion : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ BlockCipher* clone() const;
+
+ Lion(HashFunction*, StreamCipher*, u32bit);
+ ~Lion() { delete hash; delete cipher; }
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ const u32bit LEFT_SIZE, RIGHT_SIZE;
+
+ HashFunction* hash;
+ StreamCipher* cipher;
+ SecureVector<byte> key1, key2;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/lubyrack/info.txt b/botan/src/block/lubyrack/info.txt
new file mode 100644
index 0000000..a478526
--- /dev/null
+++ b/botan/src/block/lubyrack/info.txt
@@ -0,0 +1,14 @@
+realname "Luby-Rackoff"
+
+define LUBY_RACKOFF
+
+load_on auto
+
+<add>
+lubyrack.cpp
+lubyrack.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/block/lubyrack/lubyrack.cpp b/botan/src/block/lubyrack/lubyrack.cpp
new file mode 100644
index 0000000..a9d2b1d
--- /dev/null
+++ b/botan/src/block/lubyrack/lubyrack.cpp
@@ -0,0 +1,116 @@
+/*
+* Luby-Rackoff
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lubyrack.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Luby-Rackoff Encryption
+*/
+void LubyRackoff::enc(const byte in[], byte out[]) const
+ {
+ const u32bit len = hash->OUTPUT_LENGTH;
+
+ SecureVector<byte> buffer(len);
+ hash->update(K1);
+ hash->update(in, len);
+ hash->final(buffer);
+ xor_buf(out + len, in + len, buffer, len);
+
+ hash->update(K2);
+ hash->update(out + len, len);
+ hash->final(buffer);
+ xor_buf(out, in, buffer, len);
+
+ hash->update(K1);
+ hash->update(out, len);
+ hash->final(buffer);
+ xor_buf(out + len, buffer, len);
+
+ hash->update(K2);
+ hash->update(out + len, len);
+ hash->final(buffer);
+ xor_buf(out, buffer, len);
+ }
+
+/*
+* Luby-Rackoff Decryption
+*/
+void LubyRackoff::dec(const byte in[], byte out[]) const
+ {
+ const u32bit len = hash->OUTPUT_LENGTH;
+
+ SecureVector<byte> buffer(len);
+ hash->update(K2);
+ hash->update(in + len, len);
+ hash->final(buffer);
+ xor_buf(out, in, buffer, len);
+
+ hash->update(K1);
+ hash->update(out, len);
+ hash->final(buffer);
+ xor_buf(out + len, in + len, buffer, len);
+
+ hash->update(K2);
+ hash->update(out + len, len);
+ hash->final(buffer);
+ xor_buf(out, buffer, len);
+
+ hash->update(K1);
+ hash->update(out, len);
+ hash->final(buffer);
+ xor_buf(out + len, buffer, len);
+ }
+
+/*
+* Luby-Rackoff Key Schedule
+*/
+void LubyRackoff::key_schedule(const byte key[], u32bit length)
+ {
+ K1.set(key, length / 2);
+ K2.set(key + length / 2, length / 2);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void LubyRackoff::clear() throw()
+ {
+ K1.clear();
+ K2.clear();
+ hash->clear();
+ }
+
+/*
+* Return a clone of this object
+*/
+BlockCipher* LubyRackoff::clone() const
+ {
+ return new LubyRackoff(hash->clone());
+ }
+
+/*
+* Return the name of this type
+*/
+std::string LubyRackoff::name() const
+ {
+ return "Luby-Rackoff(" + hash->name() + ")";
+ }
+
+/*
+* Luby-Rackoff Constructor
+*/
+LubyRackoff::LubyRackoff(HashFunction* h) :
+ BlockCipher(2 * (h ? h->OUTPUT_LENGTH: 0),
+ 2, 32, 2),
+ hash(h)
+ {
+ }
+
+}
diff --git a/botan/src/block/lubyrack/lubyrack.h b/botan/src/block/lubyrack/lubyrack.h
new file mode 100644
index 0000000..ebde313
--- /dev/null
+++ b/botan/src/block/lubyrack/lubyrack.h
@@ -0,0 +1,38 @@
+/*
+* Luby-Rackoff
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LUBY_RACKOFF_H__
+#define BOTAN_LUBY_RACKOFF_H__
+
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Luby-Rackoff
+*/
+class BOTAN_DLL LubyRackoff : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ BlockCipher* clone() const;
+
+ LubyRackoff(HashFunction* hash);
+ ~LubyRackoff() { delete hash; }
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ HashFunction* hash;
+ SecureVector<byte> K1, K2;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/mars/info.txt b/botan/src/block/mars/info.txt
new file mode 100644
index 0000000..b0ad8af
--- /dev/null
+++ b/botan/src/block/mars/info.txt
@@ -0,0 +1,11 @@
+realname "MARS"
+
+define MARS
+
+load_on auto
+
+<add>
+mars.cpp
+mars.h
+mars_tab.cpp
+</add>
diff --git a/botan/src/block/mars/mars.cpp b/botan/src/block/mars/mars.cpp
new file mode 100644
index 0000000..08c8409
--- /dev/null
+++ b/botan/src/block/mars/mars.cpp
@@ -0,0 +1,276 @@
+/*
+* MARS
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mars.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Generate a mask for runs of bits
+*/
+u32bit gen_mask(u32bit input)
+ {
+ u32bit mask = 0;
+
+ for(u32bit j = 2; j != 31; ++j)
+ {
+ u32bit region = (input >> (j-1)) & 0x07;
+
+ if(region == 0x00 || region == 0x07)
+ {
+ u32bit low = (j < 9) ? 0 : (j - 9);
+ u32bit high = (j < 23) ? j : 23;
+
+ for(u32bit k = low; k != high; ++k)
+ {
+ u32bit value = (input >> k) & 0x3FF;
+
+ if(value == 0 || value == 0x3FF)
+ {
+ mask |= 1 << j;
+ break;
+ }
+ }
+ }
+ }
+
+ return mask;
+ }
+
+}
+
+/*
+* MARS Encryption
+*/
+void MARS::enc(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0) + EK[0];
+ u32bit B = load_le<u32bit>(in, 1) + EK[1];
+ u32bit C = load_le<u32bit>(in, 2) + EK[2];
+ u32bit D = load_le<u32bit>(in, 3) + EK[3];
+
+ forward_mix(A, B, C, D);
+
+ encrypt_round(A, B, C, D, 0);
+ encrypt_round(B, C, D, A, 1);
+ encrypt_round(C, D, A, B, 2);
+ encrypt_round(D, A, B, C, 3);
+ encrypt_round(A, B, C, D, 4);
+ encrypt_round(B, C, D, A, 5);
+ encrypt_round(C, D, A, B, 6);
+ encrypt_round(D, A, B, C, 7);
+
+ encrypt_round(A, D, C, B, 8);
+ encrypt_round(B, A, D, C, 9);
+ encrypt_round(C, B, A, D, 10);
+ encrypt_round(D, C, B, A, 11);
+ encrypt_round(A, D, C, B, 12);
+ encrypt_round(B, A, D, C, 13);
+ encrypt_round(C, B, A, D, 14);
+ encrypt_round(D, C, B, A, 15);
+
+ reverse_mix(A, B, C, D);
+
+ A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39];
+
+ store_le(out, A, B, C, D);
+ }
+
+/*
+* MARS Decryption
+*/
+void MARS::dec(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 3) + EK[39];
+ u32bit B = load_le<u32bit>(in, 2) + EK[38];
+ u32bit C = load_le<u32bit>(in, 1) + EK[37];
+ u32bit D = load_le<u32bit>(in, 0) + EK[36];
+
+ forward_mix(A, B, C, D);
+
+ decrypt_round(A, B, C, D, 15);
+ decrypt_round(B, C, D, A, 14);
+ decrypt_round(C, D, A, B, 13);
+ decrypt_round(D, A, B, C, 12);
+ decrypt_round(A, B, C, D, 11);
+ decrypt_round(B, C, D, A, 10);
+ decrypt_round(C, D, A, B, 9);
+ decrypt_round(D, A, B, C, 8);
+
+ decrypt_round(A, D, C, B, 7);
+ decrypt_round(B, A, D, C, 6);
+ decrypt_round(C, B, A, D, 5);
+ decrypt_round(D, C, B, A, 4);
+ decrypt_round(A, D, C, B, 3);
+ decrypt_round(B, A, D, C, 2);
+ decrypt_round(C, B, A, D, 1);
+ decrypt_round(D, C, B, A, 0);
+
+ reverse_mix(A, B, C, D);
+
+ A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0];
+
+ store_le(out, D, C, B, A);
+ }
+
+/*
+* MARS Forward Mixing Operation
+*/
+void MARS::forward_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D)
+ {
+ for(u32bit j = 0; j != 2; ++j)
+ {
+ B ^= SBOX[get_byte(3, A)]; B += SBOX[get_byte(2, A) + 256];
+ C += SBOX[get_byte(1, A)]; D ^= SBOX[get_byte(0, A) + 256];
+ A = rotate_right(A, 24) + D;
+
+ C ^= SBOX[get_byte(3, B)]; C += SBOX[get_byte(2, B) + 256];
+ D += SBOX[get_byte(1, B)]; A ^= SBOX[get_byte(0, B) + 256];
+ B = rotate_right(B, 24) + C;
+
+ D ^= SBOX[get_byte(3, C)]; D += SBOX[get_byte(2, C) + 256];
+ A += SBOX[get_byte(1, C)]; B ^= SBOX[get_byte(0, C) + 256];
+ C = rotate_right(C, 24);
+
+ A ^= SBOX[get_byte(3, D)]; A += SBOX[get_byte(2, D) + 256];
+ B += SBOX[get_byte(1, D)]; C ^= SBOX[get_byte(0, D) + 256];
+ D = rotate_right(D, 24);
+ }
+ }
+
+/*
+* MARS Reverse Mixing Operation
+*/
+void MARS::reverse_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D)
+ {
+ for(u32bit j = 0; j != 2; ++j)
+ {
+ B ^= SBOX[get_byte(3, A) + 256]; C -= SBOX[get_byte(0, A)];
+ D -= SBOX[get_byte(1, A) + 256]; D ^= SBOX[get_byte(2, A)];
+ A = rotate_left(A, 24);
+
+ C ^= SBOX[get_byte(3, B) + 256]; D -= SBOX[get_byte(0, B)];
+ A -= SBOX[get_byte(1, B) + 256]; A ^= SBOX[get_byte(2, B)];
+ C -= (B = rotate_left(B, 24));
+
+ D ^= SBOX[get_byte(3, C) + 256]; A -= SBOX[get_byte(0, C)];
+ B -= SBOX[get_byte(1, C) + 256]; B ^= SBOX[get_byte(2, C)];
+ C = rotate_left(C, 24);
+ D -= A;
+
+ A ^= SBOX[get_byte(3, D) + 256]; B -= SBOX[get_byte(0, D)];
+ C -= SBOX[get_byte(1, D) + 256]; C ^= SBOX[get_byte(2, D)];
+ D = rotate_left(D, 24);
+ }
+ }
+
+/*
+* MARS Encryption Round
+*/
+void MARS::encrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D,
+ u32bit round) const
+ {
+ u32bit X, Y, Z;
+ X = A + EK[2*round + 4];
+ A = rotate_left(A, 13);
+ Y = A * EK[2*round + 5];
+ Z = SBOX[X % 512];
+ Y = rotate_left(Y, 5);
+ Z ^= Y;
+ C += rotate_left(X, Y % 32);
+ Y = rotate_left(Y, 5);
+ Z ^= Y;
+ D ^= Y;
+ B += rotate_left(Z, Y % 32);
+ }
+
+/*
+* MARS Decryption Round
+*/
+void MARS::decrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D,
+ u32bit round) const
+ {
+ u32bit X, Y, Z;
+ Y = A * EK[2*round + 5];
+ A = rotate_right(A, 13);
+ X = A + EK[2*round + 4];
+ Z = SBOX[X % 512];
+ Y = rotate_left(Y, 5);
+ Z ^= Y;
+ C -= rotate_left(X, Y % 32);
+ Y = rotate_left(Y, 5);
+ Z ^= Y;
+ D ^= Y;
+ B -= rotate_left(Z, Y % 32);
+ }
+
+/*
+* MARS Key Schedule
+*/
+void MARS::key_schedule(const byte key[], u32bit length)
+ {
+ SecureBuffer<u32bit, 15> T;
+ for(u32bit j = 0; j != length / 4; ++j)
+ T[j] = load_le<u32bit>(key, j);
+ T[length / 4] = length / 4;
+
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ T[ 0] ^= rotate_left(T[ 8] ^ T[13], 3) ^ (j );
+ T[ 1] ^= rotate_left(T[ 9] ^ T[14], 3) ^ (j + 4);
+ T[ 2] ^= rotate_left(T[10] ^ T[ 0], 3) ^ (j + 8);
+ T[ 3] ^= rotate_left(T[11] ^ T[ 1], 3) ^ (j + 12);
+ T[ 4] ^= rotate_left(T[12] ^ T[ 2], 3) ^ (j + 16);
+ T[ 5] ^= rotate_left(T[13] ^ T[ 3], 3) ^ (j + 20);
+ T[ 6] ^= rotate_left(T[14] ^ T[ 4], 3) ^ (j + 24);
+ T[ 7] ^= rotate_left(T[ 0] ^ T[ 5], 3) ^ (j + 28);
+ T[ 8] ^= rotate_left(T[ 1] ^ T[ 6], 3) ^ (j + 32);
+ T[ 9] ^= rotate_left(T[ 2] ^ T[ 7], 3) ^ (j + 36);
+ T[10] ^= rotate_left(T[ 3] ^ T[ 8], 3) ^ (j + 40);
+ T[11] ^= rotate_left(T[ 4] ^ T[ 9], 3) ^ (j + 44);
+ T[12] ^= rotate_left(T[ 5] ^ T[10], 3) ^ (j + 48);
+ T[13] ^= rotate_left(T[ 6] ^ T[11], 3) ^ (j + 52);
+ T[14] ^= rotate_left(T[ 7] ^ T[12], 3) ^ (j + 56);
+
+ for(u32bit k = 0; k != 4; ++k)
+ {
+ T[ 0] = rotate_left(T[ 0] + SBOX[T[14] % 512], 9);
+ T[ 1] = rotate_left(T[ 1] + SBOX[T[ 0] % 512], 9);
+ T[ 2] = rotate_left(T[ 2] + SBOX[T[ 1] % 512], 9);
+ T[ 3] = rotate_left(T[ 3] + SBOX[T[ 2] % 512], 9);
+ T[ 4] = rotate_left(T[ 4] + SBOX[T[ 3] % 512], 9);
+ T[ 5] = rotate_left(T[ 5] + SBOX[T[ 4] % 512], 9);
+ T[ 6] = rotate_left(T[ 6] + SBOX[T[ 5] % 512], 9);
+ T[ 7] = rotate_left(T[ 7] + SBOX[T[ 6] % 512], 9);
+ T[ 8] = rotate_left(T[ 8] + SBOX[T[ 7] % 512], 9);
+ T[ 9] = rotate_left(T[ 9] + SBOX[T[ 8] % 512], 9);
+ T[10] = rotate_left(T[10] + SBOX[T[ 9] % 512], 9);
+ T[11] = rotate_left(T[11] + SBOX[T[10] % 512], 9);
+ T[12] = rotate_left(T[12] + SBOX[T[11] % 512], 9);
+ T[13] = rotate_left(T[13] + SBOX[T[12] % 512], 9);
+ T[14] = rotate_left(T[14] + SBOX[T[13] % 512], 9);
+ }
+
+ EK[10*j + 0] = T[ 0]; EK[10*j + 1] = T[ 4]; EK[10*j + 2] = T[ 8];
+ EK[10*j + 3] = T[12]; EK[10*j + 4] = T[ 1]; EK[10*j + 5] = T[ 5];
+ EK[10*j + 6] = T[ 9]; EK[10*j + 7] = T[13]; EK[10*j + 8] = T[ 2];
+ EK[10*j + 9] = T[ 6];
+ }
+
+ for(u32bit j = 5; j != 37; j += 2)
+ {
+ u32bit key3 = EK[j] & 3;
+ EK[j] |= 3;
+ EK[j] ^= rotate_left(SBOX[265 + key3], EK[j-1] % 32) & gen_mask(EK[j]);
+ }
+ }
+
+}
diff --git a/botan/src/block/mars/mars.h b/botan/src/block/mars/mars.h
new file mode 100644
index 0000000..ca49695
--- /dev/null
+++ b/botan/src/block/mars/mars.h
@@ -0,0 +1,38 @@
+/*
+* MARS
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MARS_H__
+#define BOTAN_MARS_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+class BOTAN_DLL MARS : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "MARS"; }
+ BlockCipher* clone() const { return new MARS; }
+ MARS() : BlockCipher(16, 16, 32, 4) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ void encrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const;
+ void decrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const;
+ static void forward_mix(u32bit&, u32bit&, u32bit&, u32bit&);
+ static void reverse_mix(u32bit&, u32bit&, u32bit&, u32bit&);
+
+ static const u32bit SBOX[512];
+ SecureBuffer<u32bit, 40> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/mars/mars_tab.cpp b/botan/src/block/mars/mars_tab.cpp
new file mode 100644
index 0000000..fb8f345
--- /dev/null
+++ b/botan/src/block/mars/mars_tab.cpp
@@ -0,0 +1,100 @@
+/*
+* S-Box Table for MARS
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mars.h>
+
+namespace Botan {
+
+const u32bit MARS::SBOX[512] = {
+ 0x09D0C479, 0x28C8FFE0, 0x84AA6C39, 0x9DAD7287, 0x7DFF9BE3, 0xD4268361,
+ 0xC96DA1D4, 0x7974CC93, 0x85D0582E, 0x2A4B5705, 0x1CA16A62, 0xC3BD279D,
+ 0x0F1F25E5, 0x5160372F, 0xC695C1FB, 0x4D7FF1E4, 0xAE5F6BF4, 0x0D72EE46,
+ 0xFF23DE8A, 0xB1CF8E83, 0xF14902E2, 0x3E981E42, 0x8BF53EB6, 0x7F4BF8AC,
+ 0x83631F83, 0x25970205, 0x76AFE784, 0x3A7931D4, 0x4F846450, 0x5C64C3F6,
+ 0x210A5F18, 0xC6986A26, 0x28F4E826, 0x3A60A81C, 0xD340A664, 0x7EA820C4,
+ 0x526687C5, 0x7EDDD12B, 0x32A11D1D, 0x9C9EF086, 0x80F6E831, 0xAB6F04AD,
+ 0x56FB9B53, 0x8B2E095C, 0xB68556AE, 0xD2250B0D, 0x294A7721, 0xE21FB253,
+ 0xAE136749, 0xE82AAE86, 0x93365104, 0x99404A66, 0x78A784DC, 0xB69BA84B,
+ 0x04046793, 0x23DB5C1E, 0x46CAE1D6, 0x2FE28134, 0x5A223942, 0x1863CD5B,
+ 0xC190C6E3, 0x07DFB846, 0x6EB88816, 0x2D0DCC4A, 0xA4CCAE59, 0x3798670D,
+ 0xCBFA9493, 0x4F481D45, 0xEAFC8CA8, 0xDB1129D6, 0xB0449E20, 0x0F5407FB,
+ 0x6167D9A8, 0xD1F45763, 0x4DAA96C3, 0x3BEC5958, 0xABABA014, 0xB6CCD201,
+ 0x38D6279F, 0x02682215, 0x8F376CD5, 0x092C237E, 0xBFC56593, 0x32889D2C,
+ 0x854B3E95, 0x05BB9B43, 0x7DCD5DCD, 0xA02E926C, 0xFAE527E5, 0x36A1C330,
+ 0x3412E1AE, 0xF257F462, 0x3C4F1D71, 0x30A2E809, 0x68E5F551, 0x9C61BA44,
+ 0x5DED0AB8, 0x75CE09C8, 0x9654F93E, 0x698C0CCA, 0x243CB3E4, 0x2B062B97,
+ 0x0F3B8D9E, 0x00E050DF, 0xFC5D6166, 0xE35F9288, 0xC079550D, 0x0591AEE8,
+ 0x8E531E74, 0x75FE3578, 0x2F6D829A, 0xF60B21AE, 0x95E8EB8D, 0x6699486B,
+ 0x901D7D9B, 0xFD6D6E31, 0x1090ACEF, 0xE0670DD8, 0xDAB2E692, 0xCD6D4365,
+ 0xE5393514, 0x3AF345F0, 0x6241FC4D, 0x460DA3A3, 0x7BCF3729, 0x8BF1D1E0,
+ 0x14AAC070, 0x1587ED55, 0x3AFD7D3E, 0xD2F29E01, 0x29A9D1F6, 0xEFB10C53,
+ 0xCF3B870F, 0xB414935C, 0x664465ED, 0x024ACAC7, 0x59A744C1, 0x1D2936A7,
+ 0xDC580AA6, 0xCF574CA8, 0x040A7A10, 0x6CD81807, 0x8A98BE4C, 0xACCEA063,
+ 0xC33E92B5, 0xD1E0E03D, 0xB322517E, 0x2092BD13, 0x386B2C4A, 0x52E8DD58,
+ 0x58656DFB, 0x50820371, 0x41811896, 0xE337EF7E, 0xD39FB119, 0xC97F0DF6,
+ 0x68FEA01B, 0xA150A6E5, 0x55258962, 0xEB6FF41B, 0xD7C9CD7A, 0xA619CD9E,
+ 0xBCF09576, 0x2672C073, 0xF003FB3C, 0x4AB7A50B, 0x1484126A, 0x487BA9B1,
+ 0xA64FC9C6, 0xF6957D49, 0x38B06A75, 0xDD805FCD, 0x63D094CF, 0xF51C999E,
+ 0x1AA4D343, 0xB8495294, 0xCE9F8E99, 0xBFFCD770, 0xC7C275CC, 0x378453A7,
+ 0x7B21BE33, 0x397F41BD, 0x4E94D131, 0x92CC1F98, 0x5915EA51, 0x99F861B7,
+ 0xC9980A88, 0x1D74FD5F, 0xB0A495F8, 0x614DEED0, 0xB5778EEA, 0x5941792D,
+ 0xFA90C1F8, 0x33F824B4, 0xC4965372, 0x3FF6D550, 0x4CA5FEC0, 0x8630E964,
+ 0x5B3FBBD6, 0x7DA26A48, 0xB203231A, 0x04297514, 0x2D639306, 0x2EB13149,
+ 0x16A45272, 0x532459A0, 0x8E5F4872, 0xF966C7D9, 0x07128DC0, 0x0D44DB62,
+ 0xAFC8D52D, 0x06316131, 0xD838E7CE, 0x1BC41D00, 0x3A2E8C0F, 0xEA83837E,
+ 0xB984737D, 0x13BA4891, 0xC4F8B949, 0xA6D6ACB3, 0xA215CDCE, 0x8359838B,
+ 0x6BD1AA31, 0xF579DD52, 0x21B93F93, 0xF5176781, 0x187DFDDE, 0xE94AEB76,
+ 0x2B38FD54, 0x431DE1DA, 0xAB394825, 0x9AD3048F, 0xDFEA32AA, 0x659473E3,
+ 0x623F7863, 0xF3346C59, 0xAB3AB685, 0x3346A90B, 0x6B56443E, 0xC6DE01F8,
+ 0x8D421FC0, 0x9B0ED10C, 0x88F1A1E9, 0x54C1F029, 0x7DEAD57B, 0x8D7BA426,
+ 0x4CF5178A, 0x551A7CCA, 0x1A9A5F08, 0xFCD651B9, 0x25605182, 0xE11FC6C3,
+ 0xB6FD9676, 0x337B3027, 0xB7C8EB14, 0x9E5FD030, 0x6B57E354, 0xAD913CF7,
+ 0x7E16688D, 0x58872A69, 0x2C2FC7DF, 0xE389CCC6, 0x30738DF1, 0x0824A734,
+ 0xE1797A8B, 0xA4A8D57B, 0x5B5D193B, 0xC8A8309B, 0x73F9A978, 0x73398D32,
+ 0x0F59573E, 0xE9DF2B03, 0xE8A5B6C8, 0x848D0704, 0x98DF93C2, 0x720A1DC3,
+ 0x684F259A, 0x943BA848, 0xA6370152, 0x863B5EA3, 0xD17B978B, 0x6D9B58EF,
+ 0x0A700DD4, 0xA73D36BF, 0x8E6A0829, 0x8695BC14, 0xE35B3447, 0x933AC568,
+ 0x8894B022, 0x2F511C27, 0xDDFBCC3C, 0x006662B6, 0x117C83FE, 0x4E12B414,
+ 0xC2BCA766, 0x3A2FEC10, 0xF4562420, 0x55792E2A, 0x46F5D857, 0xCEDA25CE,
+ 0xC3601D3B, 0x6C00AB46, 0xEFAC9C28, 0xB3C35047, 0x611DFEE3, 0x257C3207,
+ 0xFDD58482, 0x3B14D84F, 0x23BECB64, 0xA075F3A3, 0x088F8EAD, 0x07ADF158,
+ 0x7796943C, 0xFACABF3D, 0xC09730CD, 0xF7679969, 0xDA44E9ED, 0x2C854C12,
+ 0x35935FA3, 0x2F057D9F, 0x690624F8, 0x1CB0BAFD, 0x7B0DBDC6, 0x810F23BB,
+ 0xFA929A1A, 0x6D969A17, 0x6742979B, 0x74AC7D05, 0x010E65C4, 0x86A3D963,
+ 0xF907B5A0, 0xD0042BD3, 0x158D7D03, 0x287A8255, 0xBBA8366F, 0x096EDC33,
+ 0x21916A7B, 0x77B56B86, 0x951622F9, 0xA6C5E650, 0x8CEA17D1, 0xCD8C62BC,
+ 0xA3D63433, 0x358A68FD, 0x0F9B9D3C, 0xD6AA295B, 0xFE33384A, 0xC000738E,
+ 0xCD67EB2F, 0xE2EB6DC2, 0x97338B02, 0x06C9F246, 0x419CF1AD, 0x2B83C045,
+ 0x3723F18A, 0xCB5B3089, 0x160BEAD7, 0x5D494656, 0x35F8A74B, 0x1E4E6C9E,
+ 0x000399BD, 0x67466880, 0xB4174831, 0xACF423B2, 0xCA815AB3, 0x5A6395E7,
+ 0x302A67C5, 0x8BDB446B, 0x108F8FA4, 0x10223EDA, 0x92B8B48B, 0x7F38D0EE,
+ 0xAB2701D4, 0x0262D415, 0xAF224A30, 0xB3D88ABA, 0xF8B2C3AF, 0xDAF7EF70,
+ 0xCC97D3B7, 0xE9614B6C, 0x2BAEBFF4, 0x70F687CF, 0x386C9156, 0xCE092EE5,
+ 0x01E87DA6, 0x6CE91E6A, 0xBB7BCC84, 0xC7922C20, 0x9D3B71FD, 0x060E41C6,
+ 0xD7590F15, 0x4E03BB47, 0x183C198E, 0x63EEB240, 0x2DDBF49A, 0x6D5CBA54,
+ 0x923750AF, 0xF9E14236, 0x7838162B, 0x59726C72, 0x81B66760, 0xBB2926C1,
+ 0x48A0CE0D, 0xA6C0496D, 0xAD43507B, 0x718D496A, 0x9DF057AF, 0x44B1BDE6,
+ 0x054356DC, 0xDE7CED35, 0xD51A138B, 0x62088CC9, 0x35830311, 0xC96EFCA2,
+ 0x686F86EC, 0x8E77CB68, 0x63E1D6B8, 0xC80F9778, 0x79C491FD, 0x1B4C67F2,
+ 0x72698D7D, 0x5E368C31, 0xF7D95E2E, 0xA1D3493F, 0xDCD9433E, 0x896F1552,
+ 0x4BC4CA7A, 0xA6D1BAF4, 0xA5A96DCC, 0x0BEF8B46, 0xA169FDA7, 0x74DF40B7,
+ 0x4E208804, 0x9A756607, 0x038E87C8, 0x20211E44, 0x8B7AD4BF, 0xC6403F35,
+ 0x1848E36D, 0x80BDB038, 0x1E62891C, 0x643D2107, 0xBF04D6F8, 0x21092C8C,
+ 0xF644F389, 0x0778404E, 0x7B78ADB8, 0xA2C52D53, 0x42157ABE, 0xA2253E2E,
+ 0x7BF3F4AE, 0x80F594F9, 0x953194E7, 0x77EB92ED, 0xB3816930, 0xDA8D9336,
+ 0xBF447469, 0xF26D9483, 0xEE6FAED5, 0x71371235, 0xDE425F73, 0xB4E59F43,
+ 0x7DBE2D4E, 0x2D37B185, 0x49DC9A63, 0x98C39D98, 0x1301C9A2, 0x389B1BBF,
+ 0x0C18588D, 0xA421C1BA, 0x7AA3865C, 0x71E08558, 0x3C5CFCAA, 0x7D239CA4,
+ 0x0297D9DD, 0xD7DC2830, 0x4B37802B, 0x7428AB54, 0xAEEE0347, 0x4B3FBB85,
+ 0x692F2F08, 0x134E578E, 0x36D9E0BF, 0xAE8B5FCF, 0xEDB93ECF, 0x2B27248E,
+ 0x170EB1EF, 0x7DC57FD6, 0x1E760F16, 0xB1136601, 0x864E1B9B, 0xD7EA7319,
+ 0x3AB871BD, 0xCFA4D76F, 0xE31BD782, 0x0DBEB469, 0xABB96061, 0x5370F85D,
+ 0xFFB07E37, 0xDA30D0FB, 0xEBC977B6, 0x0B98B40F, 0x3A4D0FE6, 0xDF4FC26B,
+ 0x159CF22A, 0xC298D6E2, 0x2B78EF6A, 0x61A94AC0, 0xAB561187, 0x14EEA0F0,
+ 0xDF0D4164, 0x19AF70EE };
+
+}
diff --git a/botan/src/block/misty1/info.txt b/botan/src/block/misty1/info.txt
new file mode 100644
index 0000000..d45058b
--- /dev/null
+++ b/botan/src/block/misty1/info.txt
@@ -0,0 +1,10 @@
+realname "MISTY-1"
+
+define MISTY1
+
+load_on auto
+
+<add>
+misty1.cpp
+misty1.h
+</add>
diff --git a/botan/src/block/misty1/misty1.cpp b/botan/src/block/misty1/misty1.cpp
new file mode 100644
index 0000000..a35ff58
--- /dev/null
+++ b/botan/src/block/misty1/misty1.cpp
@@ -0,0 +1,249 @@
+/*
+* MISTY1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/misty1.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace {
+
+static const byte MISTY1_SBOX_S7[128] = {
+ 0x1B, 0x32, 0x33, 0x5A, 0x3B, 0x10, 0x17, 0x54, 0x5B, 0x1A, 0x72, 0x73,
+ 0x6B, 0x2C, 0x66, 0x49, 0x1F, 0x24, 0x13, 0x6C, 0x37, 0x2E, 0x3F, 0x4A,
+ 0x5D, 0x0F, 0x40, 0x56, 0x25, 0x51, 0x1C, 0x04, 0x0B, 0x46, 0x20, 0x0D,
+ 0x7B, 0x35, 0x44, 0x42, 0x2B, 0x1E, 0x41, 0x14, 0x4B, 0x79, 0x15, 0x6F,
+ 0x0E, 0x55, 0x09, 0x36, 0x74, 0x0C, 0x67, 0x53, 0x28, 0x0A, 0x7E, 0x38,
+ 0x02, 0x07, 0x60, 0x29, 0x19, 0x12, 0x65, 0x2F, 0x30, 0x39, 0x08, 0x68,
+ 0x5F, 0x78, 0x2A, 0x4C, 0x64, 0x45, 0x75, 0x3D, 0x59, 0x48, 0x03, 0x57,
+ 0x7C, 0x4F, 0x62, 0x3C, 0x1D, 0x21, 0x5E, 0x27, 0x6A, 0x70, 0x4D, 0x3A,
+ 0x01, 0x6D, 0x6E, 0x63, 0x18, 0x77, 0x23, 0x05, 0x26, 0x76, 0x00, 0x31,
+ 0x2D, 0x7A, 0x7F, 0x61, 0x50, 0x22, 0x11, 0x06, 0x47, 0x16, 0x52, 0x4E,
+ 0x71, 0x3E, 0x69, 0x43, 0x34, 0x5C, 0x58, 0x7D };
+
+static const u16bit MISTY1_SBOX_S9[512] = {
+ 0x01C3, 0x00CB, 0x0153, 0x019F, 0x01E3, 0x00E9, 0x00FB, 0x0035, 0x0181,
+ 0x00B9, 0x0117, 0x01EB, 0x0133, 0x0009, 0x002D, 0x00D3, 0x00C7, 0x014A,
+ 0x0037, 0x007E, 0x00EB, 0x0164, 0x0193, 0x01D8, 0x00A3, 0x011E, 0x0055,
+ 0x002C, 0x001D, 0x01A2, 0x0163, 0x0118, 0x014B, 0x0152, 0x01D2, 0x000F,
+ 0x002B, 0x0030, 0x013A, 0x00E5, 0x0111, 0x0138, 0x018E, 0x0063, 0x00E3,
+ 0x00C8, 0x01F4, 0x001B, 0x0001, 0x009D, 0x00F8, 0x01A0, 0x016D, 0x01F3,
+ 0x001C, 0x0146, 0x007D, 0x00D1, 0x0082, 0x01EA, 0x0183, 0x012D, 0x00F4,
+ 0x019E, 0x01D3, 0x00DD, 0x01E2, 0x0128, 0x01E0, 0x00EC, 0x0059, 0x0091,
+ 0x0011, 0x012F, 0x0026, 0x00DC, 0x00B0, 0x018C, 0x010F, 0x01F7, 0x00E7,
+ 0x016C, 0x00B6, 0x00F9, 0x00D8, 0x0151, 0x0101, 0x014C, 0x0103, 0x00B8,
+ 0x0154, 0x012B, 0x01AE, 0x0017, 0x0071, 0x000C, 0x0047, 0x0058, 0x007F,
+ 0x01A4, 0x0134, 0x0129, 0x0084, 0x015D, 0x019D, 0x01B2, 0x01A3, 0x0048,
+ 0x007C, 0x0051, 0x01CA, 0x0023, 0x013D, 0x01A7, 0x0165, 0x003B, 0x0042,
+ 0x00DA, 0x0192, 0x00CE, 0x00C1, 0x006B, 0x009F, 0x01F1, 0x012C, 0x0184,
+ 0x00FA, 0x0196, 0x01E1, 0x0169, 0x017D, 0x0031, 0x0180, 0x010A, 0x0094,
+ 0x01DA, 0x0186, 0x013E, 0x011C, 0x0060, 0x0175, 0x01CF, 0x0067, 0x0119,
+ 0x0065, 0x0068, 0x0099, 0x0150, 0x0008, 0x0007, 0x017C, 0x00B7, 0x0024,
+ 0x0019, 0x00DE, 0x0127, 0x00DB, 0x00E4, 0x01A9, 0x0052, 0x0109, 0x0090,
+ 0x019C, 0x01C1, 0x0028, 0x01B3, 0x0135, 0x016A, 0x0176, 0x00DF, 0x01E5,
+ 0x0188, 0x00C5, 0x016E, 0x01DE, 0x01B1, 0x00C3, 0x01DF, 0x0036, 0x00EE,
+ 0x01EE, 0x00F0, 0x0093, 0x0049, 0x009A, 0x01B6, 0x0069, 0x0081, 0x0125,
+ 0x000B, 0x005E, 0x00B4, 0x0149, 0x01C7, 0x0174, 0x003E, 0x013B, 0x01B7,
+ 0x008E, 0x01C6, 0x00AE, 0x0010, 0x0095, 0x01EF, 0x004E, 0x00F2, 0x01FD,
+ 0x0085, 0x00FD, 0x00F6, 0x00A0, 0x016F, 0x0083, 0x008A, 0x0156, 0x009B,
+ 0x013C, 0x0107, 0x0167, 0x0098, 0x01D0, 0x01E9, 0x0003, 0x01FE, 0x00BD,
+ 0x0122, 0x0089, 0x00D2, 0x018F, 0x0012, 0x0033, 0x006A, 0x0142, 0x00ED,
+ 0x0170, 0x011B, 0x00E2, 0x014F, 0x0158, 0x0131, 0x0147, 0x005D, 0x0113,
+ 0x01CD, 0x0079, 0x0161, 0x01A5, 0x0179, 0x009E, 0x01B4, 0x00CC, 0x0022,
+ 0x0132, 0x001A, 0x00E8, 0x0004, 0x0187, 0x01ED, 0x0197, 0x0039, 0x01BF,
+ 0x01D7, 0x0027, 0x018B, 0x00C6, 0x009C, 0x00D0, 0x014E, 0x006C, 0x0034,
+ 0x01F2, 0x006E, 0x00CA, 0x0025, 0x00BA, 0x0191, 0x00FE, 0x0013, 0x0106,
+ 0x002F, 0x01AD, 0x0172, 0x01DB, 0x00C0, 0x010B, 0x01D6, 0x00F5, 0x01EC,
+ 0x010D, 0x0076, 0x0114, 0x01AB, 0x0075, 0x010C, 0x01E4, 0x0159, 0x0054,
+ 0x011F, 0x004B, 0x00C4, 0x01BE, 0x00F7, 0x0029, 0x00A4, 0x000E, 0x01F0,
+ 0x0077, 0x004D, 0x017A, 0x0086, 0x008B, 0x00B3, 0x0171, 0x00BF, 0x010E,
+ 0x0104, 0x0097, 0x015B, 0x0160, 0x0168, 0x00D7, 0x00BB, 0x0066, 0x01CE,
+ 0x00FC, 0x0092, 0x01C5, 0x006F, 0x0016, 0x004A, 0x00A1, 0x0139, 0x00AF,
+ 0x00F1, 0x0190, 0x000A, 0x01AA, 0x0143, 0x017B, 0x0056, 0x018D, 0x0166,
+ 0x00D4, 0x01FB, 0x014D, 0x0194, 0x019A, 0x0087, 0x01F8, 0x0123, 0x00A7,
+ 0x01B8, 0x0141, 0x003C, 0x01F9, 0x0140, 0x002A, 0x0155, 0x011A, 0x01A1,
+ 0x0198, 0x00D5, 0x0126, 0x01AF, 0x0061, 0x012E, 0x0157, 0x01DC, 0x0072,
+ 0x018A, 0x00AA, 0x0096, 0x0115, 0x00EF, 0x0045, 0x007B, 0x008D, 0x0145,
+ 0x0053, 0x005F, 0x0178, 0x00B2, 0x002E, 0x0020, 0x01D5, 0x003F, 0x01C9,
+ 0x01E7, 0x01AC, 0x0044, 0x0038, 0x0014, 0x00B1, 0x016B, 0x00AB, 0x00B5,
+ 0x005A, 0x0182, 0x01C8, 0x01D4, 0x0018, 0x0177, 0x0064, 0x00CF, 0x006D,
+ 0x0100, 0x0199, 0x0130, 0x015A, 0x0005, 0x0120, 0x01BB, 0x01BD, 0x00E0,
+ 0x004F, 0x00D6, 0x013F, 0x01C4, 0x012A, 0x0015, 0x0006, 0x00FF, 0x019B,
+ 0x00A6, 0x0043, 0x0088, 0x0050, 0x015F, 0x01E8, 0x0121, 0x0073, 0x017E,
+ 0x00BC, 0x00C2, 0x00C9, 0x0173, 0x0189, 0x01F5, 0x0074, 0x01CC, 0x01E6,
+ 0x01A8, 0x0195, 0x001F, 0x0041, 0x000D, 0x01BA, 0x0032, 0x003D, 0x01D1,
+ 0x0080, 0x00A8, 0x0057, 0x01B9, 0x0162, 0x0148, 0x00D9, 0x0105, 0x0062,
+ 0x007A, 0x0021, 0x01FF, 0x0112, 0x0108, 0x01C0, 0x00A9, 0x011D, 0x01B0,
+ 0x01A6, 0x00CD, 0x00F3, 0x005C, 0x0102, 0x005B, 0x01D9, 0x0144, 0x01F6,
+ 0x00AD, 0x00A5, 0x003A, 0x01CB, 0x0136, 0x017F, 0x0046, 0x00E1, 0x001E,
+ 0x01DD, 0x00E6, 0x0137, 0x01FA, 0x0185, 0x008C, 0x008F, 0x0040, 0x01B5,
+ 0x00BE, 0x0078, 0x0000, 0x00AC, 0x0110, 0x015E, 0x0124, 0x0002, 0x01BC,
+ 0x00A2, 0x00EA, 0x0070, 0x01FC, 0x0116, 0x015C, 0x004C, 0x01C2 };
+
+/*
+* MISTY1 FI Function
+*/
+u16bit FI(u16bit input, u16bit key7, u16bit key9)
+ {
+ u16bit D9 = input >> 7, D7 = input & 0x7F;
+ D9 = MISTY1_SBOX_S9[D9] ^ D7;
+ D7 = (MISTY1_SBOX_S7[D7] ^ key7 ^ D9) & 0x7F;
+ D9 = MISTY1_SBOX_S9[D9 ^ key9] ^ D7;
+ return static_cast<u16bit>((D7 << 9) | D9);
+ }
+
+}
+
+/*
+* MISTY1 Encryption
+*/
+void MISTY1::enc(const byte in[], byte out[]) const
+ {
+ u16bit B0 = load_be<u16bit>(in, 0);
+ u16bit B1 = load_be<u16bit>(in, 1);
+ u16bit B2 = load_be<u16bit>(in, 2);
+ u16bit B3 = load_be<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 12; j += 3)
+ {
+ const u16bit* RK = EK + 8 * j;
+
+ B1 ^= B0 & RK[0];
+ B0 ^= B1 | RK[1];
+ B3 ^= B2 & RK[2];
+ B2 ^= B3 | RK[3];
+
+ u32bit T0, T1;
+
+ T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1;
+ T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0;
+ T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1;
+
+ B2 ^= T1 ^ RK[13];
+ B3 ^= T0;
+
+ T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3;
+ T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0;
+ T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1;
+
+ B0 ^= T1 ^ RK[23];
+ B1 ^= T0;
+ }
+
+ B1 ^= B0 & EK[96];
+ B0 ^= B1 | EK[97];
+ B3 ^= B2 & EK[98];
+ B2 ^= B3 | EK[99];
+
+ store_be(out, B2, B3, B0, B1);
+ }
+
+/*
+* MISTY1 Decryption
+*/
+void MISTY1::dec(const byte in[], byte out[]) const
+ {
+ u16bit B0 = load_be<u16bit>(in, 2);
+ u16bit B1 = load_be<u16bit>(in, 3);
+ u16bit B2 = load_be<u16bit>(in, 0);
+ u16bit B3 = load_be<u16bit>(in, 1);
+
+ for(u32bit j = 0; j != 12; j += 3)
+ {
+ const u16bit* RK = DK + 8 * j;
+
+ B2 ^= B3 | RK[0];
+ B3 ^= B2 & RK[1];
+ B0 ^= B1 | RK[2];
+ B1 ^= B0 & RK[3];
+
+ u32bit T0, T1;
+
+ T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3;
+ T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0;
+ T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1;
+
+ B0 ^= T1 ^ RK[13];
+ B1 ^= T0;
+
+ T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1;
+ T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0;
+ T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1;
+
+ B2 ^= T1 ^ RK[23];
+ B3 ^= T0;
+ }
+
+ B2 ^= B3 | DK[96];
+ B3 ^= B2 & DK[97];
+ B0 ^= B1 | DK[98];
+ B1 ^= B0 & DK[99];
+
+ store_be(out, B0, B1, B2, B3);
+ }
+
+/*
+* MISTY1 Key Schedule
+*/
+void MISTY1::key_schedule(const byte key[], u32bit length)
+ {
+ SecureBuffer<u16bit, 32> KS;
+ for(u32bit j = 0; j != length / 2; ++j)
+ KS[j] = load_be<u16bit>(key, j);
+
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ KS[j+ 8] = FI(KS[j], KS[(j+1) % 8] >> 9, KS[(j+1) % 8] & 0x1FF);
+ KS[j+16] = KS[j+8] >> 9;
+ KS[j+24] = KS[j+8] & 0x1FF;
+ }
+
+ /*
+ * Precomputed indexes for the orderings of the subkeys (MISTY1 reuses
+ * values)
+ */
+ static const byte EK_ORDER[100] = {
+ 0x00, 0x0E, 0x0A, 0x04, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13,
+ 0x1B, 0x04, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14, 0x1C, 0x05,
+ 0x01, 0x0F, 0x0B, 0x05, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15,
+ 0x1D, 0x06, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16, 0x1E, 0x07,
+ 0x02, 0x08, 0x0C, 0x06, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17,
+ 0x1F, 0x00, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10, 0x18, 0x01,
+ 0x03, 0x09, 0x0D, 0x07, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11,
+ 0x19, 0x02, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12, 0x1A, 0x03,
+ 0x04, 0x0A, 0x0E, 0x00 };
+
+ static const byte DK_ORDER[100] = {
+ 0x00, 0x0E, 0x0A, 0x04, 0x07, 0x14, 0x1C, 0x01, 0x10, 0x18, 0x06, 0x12,
+ 0x1A, 0x03, 0x06, 0x13, 0x1B, 0x00, 0x17, 0x1F, 0x05, 0x11, 0x19, 0x02,
+ 0x07, 0x0D, 0x09, 0x03, 0x05, 0x12, 0x1A, 0x07, 0x16, 0x1E, 0x04, 0x10,
+ 0x18, 0x01, 0x04, 0x11, 0x19, 0x06, 0x15, 0x1D, 0x03, 0x17, 0x1F, 0x00,
+ 0x06, 0x0C, 0x08, 0x02, 0x03, 0x10, 0x18, 0x05, 0x14, 0x1C, 0x02, 0x16,
+ 0x1E, 0x07, 0x02, 0x17, 0x1F, 0x04, 0x13, 0x1B, 0x01, 0x15, 0x1D, 0x06,
+ 0x05, 0x0B, 0x0F, 0x01, 0x01, 0x16, 0x1E, 0x03, 0x12, 0x1A, 0x00, 0x14,
+ 0x1C, 0x05, 0x00, 0x15, 0x1D, 0x02, 0x11, 0x19, 0x07, 0x13, 0x1B, 0x04,
+ 0x04, 0x0A, 0x0E, 0x00 };
+
+ for(u32bit j = 0; j != 100; ++j)
+ {
+ EK[j] = KS[EK_ORDER[j]];
+ DK[j] = KS[DK_ORDER[j]];
+ }
+ }
+
+/*
+* MISTY1 Constructor
+*/
+MISTY1::MISTY1(u32bit rounds) : BlockCipher(8, 16)
+ {
+ if(rounds != 8)
+ throw Invalid_Argument("MISTY1: Invalid number of rounds: "
+ + to_string(rounds));
+ }
+
+}
diff --git a/botan/src/block/misty1/misty1.h b/botan/src/block/misty1/misty1.h
new file mode 100644
index 0000000..62d4f85
--- /dev/null
+++ b/botan/src/block/misty1/misty1.h
@@ -0,0 +1,35 @@
+/**
+* MISTY1
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MISTY1_H__
+#define BOTAN_MISTY1_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* MISTY1
+*/
+class BOTAN_DLL MISTY1 : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); DK.clear(); }
+ std::string name() const { return "MISTY1"; }
+ BlockCipher* clone() const { return new MISTY1; }
+ MISTY1(u32bit = 8);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 100> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/noekeon/info.txt b/botan/src/block/noekeon/info.txt
new file mode 100644
index 0000000..8025c20
--- /dev/null
+++ b/botan/src/block/noekeon/info.txt
@@ -0,0 +1,10 @@
+realname "Noekeon"
+
+define NOEKEON
+
+load_on auto
+
+<add>
+noekeon.cpp
+noekeon.h
+</add>
diff --git a/botan/src/block/noekeon/noekeon.cpp b/botan/src/block/noekeon/noekeon.cpp
new file mode 100644
index 0000000..90eb9ad
--- /dev/null
+++ b/botan/src/block/noekeon/noekeon.cpp
@@ -0,0 +1,198 @@
+/*
+* Noekeon
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/noekeon.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Noekeon's Theta Operation
+*/
+inline void theta(u32bit& A0, u32bit& A1,
+ u32bit& A2, u32bit& A3,
+ const u32bit EK[4])
+ {
+ u32bit T = A0 ^ A2;
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
+ A1 ^= T;
+ A3 ^= T;
+
+ A0 ^= EK[0];
+ A1 ^= EK[1];
+ A2 ^= EK[2];
+ A3 ^= EK[3];
+
+ T = A1 ^ A3;
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
+ A0 ^= T;
+ A2 ^= T;
+ }
+
+/*
+* Theta With Null Key
+*/
+inline void theta(u32bit& A0, u32bit& A1,
+ u32bit& A2, u32bit& A3)
+ {
+ u32bit T = A0 ^ A2;
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
+ A1 ^= T;
+ A3 ^= T;
+
+ T = A1 ^ A3;
+ T ^= rotate_left(T, 8) ^ rotate_right(T, 8);
+ A0 ^= T;
+ A2 ^= T;
+ }
+
+/*
+* Noekeon's Gamma S-Box Layer
+*/
+inline void gamma(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3)
+ {
+ A1 ^= ~A3 & ~A2;
+ A0 ^= A2 & A1;
+
+ u32bit T = A3;
+ A3 = A0;
+ A0 = T;
+
+ A2 ^= A0 ^ A1 ^ A3;
+
+ A1 ^= ~A3 & ~A2;
+ A0 ^= A2 & A1;
+ }
+
+}
+
+/*
+* Noekeon Round Constants
+*/
+const byte Noekeon::RC[] = {
+ 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
+ 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
+ 0xD4 };
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon::enc(const byte in[], byte out[]) const
+ {
+ u32bit A0 = load_be<u32bit>(in, 0);
+ u32bit A1 = load_be<u32bit>(in, 1);
+ u32bit A2 = load_be<u32bit>(in, 2);
+ u32bit A3 = load_be<u32bit>(in, 3);
+
+ for(u32bit j = 0; j != 16; ++j)
+ {
+ A0 ^= RC[j];
+ theta(A0, A1, A2, A3, EK);
+
+ A1 = rotate_left(A1, 1);
+ A2 = rotate_left(A2, 5);
+ A3 = rotate_left(A3, 2);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotate_right(A1, 1);
+ A2 = rotate_right(A2, 5);
+ A3 = rotate_right(A3, 2);
+ }
+
+ A0 ^= RC[16];
+ theta(A0, A1, A2, A3, EK);
+
+ store_be(out, A0, A1, A2, A3);
+ }
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon::dec(const byte in[], byte out[]) const
+ {
+ u32bit A0 = load_be<u32bit>(in, 0);
+ u32bit A1 = load_be<u32bit>(in, 1);
+ u32bit A2 = load_be<u32bit>(in, 2);
+ u32bit A3 = load_be<u32bit>(in, 3);
+
+ for(u32bit j = 16; j != 0; --j)
+ {
+ theta(A0, A1, A2, A3, DK);
+ A0 ^= RC[j];
+
+ A1 = rotate_left(A1, 1);
+ A2 = rotate_left(A2, 5);
+ A3 = rotate_left(A3, 2);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotate_right(A1, 1);
+ A2 = rotate_right(A2, 5);
+ A3 = rotate_right(A3, 2);
+ }
+
+ theta(A0, A1, A2, A3, DK);
+ A0 ^= RC[0];
+
+ store_be(out, A0, A1, A2, A3);
+ }
+
+/*
+* Noekeon Key Schedule
+*/
+void Noekeon::key_schedule(const byte key[], u32bit)
+ {
+ u32bit A0 = load_be<u32bit>(key, 0);
+ u32bit A1 = load_be<u32bit>(key, 1);
+ u32bit A2 = load_be<u32bit>(key, 2);
+ u32bit A3 = load_be<u32bit>(key, 3);
+
+ for(u32bit j = 0; j != 16; ++j)
+ {
+ A0 ^= RC[j];
+ theta(A0, A1, A2, A3);
+
+ A1 = rotate_left(A1, 1);
+ A2 = rotate_left(A2, 5);
+ A3 = rotate_left(A3, 2);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotate_right(A1, 1);
+ A2 = rotate_right(A2, 5);
+ A3 = rotate_right(A3, 2);
+ }
+
+ A0 ^= RC[16];
+
+ DK[0] = A0;
+ DK[1] = A1;
+ DK[2] = A2;
+ DK[3] = A3;
+
+ theta(A0, A1, A2, A3);
+
+ EK[0] = A0;
+ EK[1] = A1;
+ EK[2] = A2;
+ EK[3] = A3;
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Noekeon::clear() throw()
+ {
+ EK.clear();
+ DK.clear();
+ }
+
+}
diff --git a/botan/src/block/noekeon/noekeon.h b/botan/src/block/noekeon/noekeon.h
new file mode 100644
index 0000000..8938924
--- /dev/null
+++ b/botan/src/block/noekeon/noekeon.h
@@ -0,0 +1,37 @@
+/*
+* Noekeon
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOEKEON_H__
+#define BOTAN_NOEKEON_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Noekeon
+*/
+class BOTAN_DLL Noekeon : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Noekeon"; }
+ BlockCipher* clone() const { return new Noekeon; }
+ Noekeon() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const byte RC[17];
+
+ SecureBuffer<u32bit, 4> EK, DK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/rc2/info.txt b/botan/src/block/rc2/info.txt
new file mode 100644
index 0000000..099141d
--- /dev/null
+++ b/botan/src/block/rc2/info.txt
@@ -0,0 +1,10 @@
+realname "RC2"
+
+define RC2
+
+load_on auto
+
+<add>
+rc2.cpp
+rc2.h
+</add>
diff --git a/botan/src/block/rc2/rc2.cpp b/botan/src/block/rc2/rc2.cpp
new file mode 100644
index 0000000..5827bdb
--- /dev/null
+++ b/botan/src/block/rc2/rc2.cpp
@@ -0,0 +1,163 @@
+/*
+* RC2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rc2.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* RC2 Encryption
+*/
+void RC2::enc(const byte in[], byte out[]) const
+ {
+ u16bit R0 = load_le<u16bit>(in, 0);
+ u16bit R1 = load_le<u16bit>(in, 1);
+ u16bit R2 = load_le<u16bit>(in, 2);
+ u16bit R3 = load_le<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 16; ++j)
+ {
+ R0 += (R1 & ~R3) + (R2 & R3) + K[4*j];
+ R0 = rotate_left(R0, 1);
+
+ R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1];
+ R1 = rotate_left(R1, 2);
+
+ R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2];
+ R2 = rotate_left(R2, 3);
+
+ R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3];
+ R3 = rotate_left(R3, 5);
+
+ if(j == 4 || j == 10)
+ {
+ R0 += K[R3 % 64];
+ R1 += K[R0 % 64];
+ R2 += K[R1 % 64];
+ R3 += K[R2 % 64];
+ }
+ }
+
+ store_le(out, R0, R1, R2, R3);
+ }
+
+/*
+* RC2 Decryption
+*/
+void RC2::dec(const byte in[], byte out[]) const
+ {
+ u16bit R0 = load_le<u16bit>(in, 0);
+ u16bit R1 = load_le<u16bit>(in, 1);
+ u16bit R2 = load_le<u16bit>(in, 2);
+ u16bit R3 = load_le<u16bit>(in, 3);
+
+ for(u32bit j = 0; j != 16; ++j)
+ {
+ R3 = rotate_right(R3, 5);
+ R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)];
+
+ R2 = rotate_right(R2, 3);
+ R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)];
+
+ R1 = rotate_right(R1, 2);
+ R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)];
+
+ R0 = rotate_right(R0, 1);
+ R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)];
+
+ if(j == 4 || j == 10)
+ {
+ R3 -= K[R2 % 64];
+ R2 -= K[R1 % 64];
+ R1 -= K[R0 % 64];
+ R0 -= K[R3 % 64];
+ }
+ }
+
+ store_le(out, R0, R1, R2, R3);
+ }
+
+/*
+* RC2 Key Schedule
+*/
+void RC2::key_schedule(const byte key[], u32bit length)
+ {
+ static const byte TABLE[256] = {
+ 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 };
+
+ SecureBuffer<byte, 128> L;
+ L.copy(key, length);
+
+ for(u32bit j = length; j != 128; ++j)
+ L[j] = TABLE[(L[j-1] + L[j-length]) % 256];
+ L[128-length] = TABLE[L[128-length]];
+ for(s32bit j = 127-length; j >= 0; --j)
+ L[j] = TABLE[L[j+1] ^ L[j+length]];
+
+ for(u32bit j = 0; j != 64; ++j)
+ K[j] = load_le<u16bit>(L, j);
+ }
+
+/*
+* Return the code of the effective key bits
+*/
+byte RC2::EKB_code(u32bit ekb)
+ {
+ const byte EKB[256] = {
+ 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 };
+
+ if(ekb < 256)
+ return EKB[ekb];
+ else
+ throw Encoding_Error("RC2::EKB_code: EKB is too large");
+ }
+
+}
diff --git a/botan/src/block/rc2/rc2.h b/botan/src/block/rc2/rc2.h
new file mode 100644
index 0000000..cb6f58f
--- /dev/null
+++ b/botan/src/block/rc2/rc2.h
@@ -0,0 +1,37 @@
+/*
+* RC2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC2_H__
+#define BOTAN_RC2_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC2
+*/
+class BOTAN_DLL RC2 : public BlockCipher
+ {
+ public:
+ static byte EKB_code(u32bit);
+
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "RC2"; }
+ BlockCipher* clone() const { return new RC2; }
+ RC2() : BlockCipher(8, 1, 32) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u16bit, 64> K;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/rc5/info.txt b/botan/src/block/rc5/info.txt
new file mode 100644
index 0000000..4a150c3
--- /dev/null
+++ b/botan/src/block/rc5/info.txt
@@ -0,0 +1,10 @@
+realname "RC5"
+
+define RC5
+
+load_on auto
+
+<add>
+rc5.cpp
+rc5.h
+</add>
diff --git a/botan/src/block/rc5/rc5.cpp b/botan/src/block/rc5/rc5.cpp
new file mode 100644
index 0000000..5d83d5a
--- /dev/null
+++ b/botan/src/block/rc5/rc5.cpp
@@ -0,0 +1,103 @@
+/*
+* RC5
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rc5.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* RC5 Encryption
+*/
+void RC5::enc(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1);
+
+ A += S[0]; B += S[1];
+ for(u32bit j = 0; j != ROUNDS; j += 4)
+ {
+ A = rotate_left(A ^ B, B % 32) + S[2*j+2];
+ B = rotate_left(B ^ A, A % 32) + S[2*j+3];
+ A = rotate_left(A ^ B, B % 32) + S[2*j+4];
+ B = rotate_left(B ^ A, A % 32) + S[2*j+5];
+ A = rotate_left(A ^ B, B % 32) + S[2*j+6];
+ B = rotate_left(B ^ A, A % 32) + S[2*j+7];
+ A = rotate_left(A ^ B, B % 32) + S[2*j+8];
+ B = rotate_left(B ^ A, A % 32) + S[2*j+9];
+ }
+
+ store_le(out, A, B);
+ }
+
+/*
+* RC5 Decryption
+*/
+void RC5::dec(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1);
+
+ for(u32bit j = ROUNDS; j != 0; j -= 4)
+ {
+ B = rotate_right(B - S[2*j+1], A % 32) ^ A;
+ A = rotate_right(A - S[2*j ], B % 32) ^ B;
+ B = rotate_right(B - S[2*j-1], A % 32) ^ A;
+ A = rotate_right(A - S[2*j-2], B % 32) ^ B;
+ B = rotate_right(B - S[2*j-3], A % 32) ^ A;
+ A = rotate_right(A - S[2*j-4], B % 32) ^ B;
+ B = rotate_right(B - S[2*j-5], A % 32) ^ A;
+ A = rotate_right(A - S[2*j-6], B % 32) ^ B;
+ }
+ B -= S[1]; A -= S[0];
+
+ store_le(out, A, B);
+ }
+
+/*
+* RC5 Key Schedule
+*/
+void RC5::key_schedule(const byte key[], u32bit length)
+ {
+ const u32bit WORD_KEYLENGTH = (((length - 1) / 4) + 1),
+ MIX_ROUNDS = 3*std::max(WORD_KEYLENGTH, S.size());
+ S[0] = 0xB7E15163;
+ for(u32bit j = 1; j != S.size(); ++j)
+ S[j] = S[j-1] + 0x9E3779B9;
+
+ SecureBuffer<u32bit, 8> K;
+ for(s32bit j = length-1; j >= 0; --j)
+ K[j/4] = (K[j/4] << 8) + key[j];
+ for(u32bit j = 0, A = 0, B = 0; j != MIX_ROUNDS; ++j)
+ {
+ A = rotate_left(S[j % S.size()] + A + B, 3);
+ B = rotate_left(K[j % WORD_KEYLENGTH] + A + B, (A + B) % 32);
+ S[j % S.size()] = A;
+ K[j % WORD_KEYLENGTH] = B;
+ }
+ }
+
+/*
+* Return the name of this type
+*/
+std::string RC5::name() const
+ {
+ return "RC5(" + to_string(ROUNDS) + ")";
+ }
+
+/*
+* RC5 Constructor
+*/
+RC5::RC5(u32bit r) : BlockCipher(8, 1, 32), ROUNDS(r)
+ {
+ if(ROUNDS < 8 || ROUNDS > 32 || (ROUNDS % 4 != 0))
+ throw Invalid_Argument(name() + ": Invalid number of rounds");
+ S.create(2*ROUNDS + 2);
+ }
+
+}
diff --git a/botan/src/block/rc5/rc5.h b/botan/src/block/rc5/rc5.h
new file mode 100644
index 0000000..0832247
--- /dev/null
+++ b/botan/src/block/rc5/rc5.h
@@ -0,0 +1,35 @@
+/*
+* RC5
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC5_H__
+#define BOTAN_RC5_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC5
+*/
+class BOTAN_DLL RC5 : public BlockCipher
+ {
+ public:
+ void clear() throw() { S.clear(); }
+ std::string name() const;
+ BlockCipher* clone() const { return new RC5(ROUNDS); }
+ RC5(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureVector<u32bit> S;
+ const u32bit ROUNDS;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/rc6/info.txt b/botan/src/block/rc6/info.txt
new file mode 100644
index 0000000..1457e78
--- /dev/null
+++ b/botan/src/block/rc6/info.txt
@@ -0,0 +1,10 @@
+realname "RC6"
+
+define RC6
+
+load_on auto
+
+<add>
+rc6.cpp
+rc6.h
+</add>
diff --git a/botan/src/block/rc6/rc6.cpp b/botan/src/block/rc6/rc6.cpp
new file mode 100644
index 0000000..3b30ea9
--- /dev/null
+++ b/botan/src/block/rc6/rc6.cpp
@@ -0,0 +1,122 @@
+/*
+* RC6
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rc6.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* RC6 Encryption
+*/
+void RC6::enc(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0);
+ u32bit B = load_le<u32bit>(in, 1);
+ u32bit C = load_le<u32bit>(in, 2);
+ u32bit D = load_le<u32bit>(in, 3);
+
+ B += S[0]; D += S[1];
+
+ for(u32bit j = 0; j != 20; j += 4)
+ {
+ u32bit T1, T2;
+
+ T1 = rotate_left(B*(2*B+1), 5);
+ T2 = rotate_left(D*(2*D+1), 5);
+ A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2];
+ C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3];
+
+ T1 = rotate_left(C*(2*C+1), 5);
+ T2 = rotate_left(A*(2*A+1), 5);
+ B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4];
+ D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5];
+
+ T1 = rotate_left(D*(2*D+1), 5);
+ T2 = rotate_left(B*(2*B+1), 5);
+ C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6];
+ A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7];
+
+ T1 = rotate_left(A*(2*A+1), 5);
+ T2 = rotate_left(C*(2*C+1), 5);
+ D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8];
+ B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9];
+ }
+
+ A += S[42]; C += S[43];
+
+ store_le(out, A, B, C, D);
+ }
+
+/*
+* RC6 Decryption
+*/
+void RC6::dec(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0);
+ u32bit B = load_le<u32bit>(in, 1);
+ u32bit C = load_le<u32bit>(in, 2);
+ u32bit D = load_le<u32bit>(in, 3);
+
+ C -= S[43]; A -= S[42];
+
+ for(u32bit j = 0; j != 20; j += 4)
+ {
+ u32bit T1, T2;
+
+ T1 = rotate_left(A*(2*A+1), 5);
+ T2 = rotate_left(C*(2*C+1), 5);
+ B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2;
+ D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1;
+
+ T1 = rotate_left(D*(2*D+1), 5);
+ T2 = rotate_left(B*(2*B+1), 5);
+ A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2;
+ C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1;
+
+ T1 = rotate_left(C*(2*C+1), 5);
+ T2 = rotate_left(A*(2*A+1), 5);
+ D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2;
+ B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1;
+
+ T1 = rotate_left(B*(2*B+1), 5);
+ T2 = rotate_left(D*(2*D+1), 5);
+ C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2;
+ A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1;
+ }
+
+ D -= S[1]; B -= S[0];
+
+ store_le(out, A, B, C, D);
+ }
+
+/*
+* RC6 Key Schedule
+*/
+void RC6::key_schedule(const byte key[], u32bit length)
+ {
+ const u32bit WORD_KEYLENGTH = (((length - 1) / 4) + 1),
+ MIX_ROUNDS = 3*std::max(WORD_KEYLENGTH, S.size());
+ S[0] = 0xB7E15163;
+ for(u32bit j = 1; j != S.size(); ++j)
+ S[j] = S[j-1] + 0x9E3779B9;
+
+ SecureBuffer<u32bit, 8> K;
+ for(s32bit j = length-1; j >= 0; --j)
+ K[j/4] = (K[j/4] << 8) + key[j];
+ for(u32bit j = 0, A = 0, B = 0; j != MIX_ROUNDS; ++j)
+ {
+ A = rotate_left(S[j % S.size()] + A + B, 3);
+ B = rotate_left(K[j % WORD_KEYLENGTH] + A + B, (A + B) % 32);
+ S[j % S.size()] = A;
+ K[j % WORD_KEYLENGTH] = B;
+ }
+ }
+
+}
diff --git a/botan/src/block/rc6/rc6.h b/botan/src/block/rc6/rc6.h
new file mode 100644
index 0000000..cb2800b
--- /dev/null
+++ b/botan/src/block/rc6/rc6.h
@@ -0,0 +1,35 @@
+/*
+* RC6
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RC6_H__
+#define BOTAN_RC6_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* RC6
+*/
+class BOTAN_DLL RC6 : public BlockCipher
+ {
+ public:
+ void clear() throw() { S.clear(); }
+ std::string name() const { return "RC6"; }
+ BlockCipher* clone() const { return new RC6; }
+ RC6() : BlockCipher(16, 1, 32) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 44> S;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/safer/info.txt b/botan/src/block/safer/info.txt
new file mode 100644
index 0000000..973cbff
--- /dev/null
+++ b/botan/src/block/safer/info.txt
@@ -0,0 +1,11 @@
+realname "SAFER"
+
+define SAFER
+
+load_on auto
+
+<add>
+safe_tab.cpp
+safer_sk.cpp
+safer_sk.h
+</add>
diff --git a/botan/src/block/safer/safe_tab.cpp b/botan/src/block/safer/safe_tab.cpp
new file mode 100644
index 0000000..e265a40
--- /dev/null
+++ b/botan/src/block/safer/safe_tab.cpp
@@ -0,0 +1,121 @@
+/*
+* S-Box Tables for SAFER-SK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/safer_sk.h>
+
+namespace Botan {
+
+const byte SAFER_SK::EXP[256] = {
+ 0x01, 0x2D, 0xE2, 0x93, 0xBE, 0x45, 0x15, 0xAE, 0x78, 0x03, 0x87, 0xA4,
+ 0xB8, 0x38, 0xCF, 0x3F, 0x08, 0x67, 0x09, 0x94, 0xEB, 0x26, 0xA8, 0x6B,
+ 0xBD, 0x18, 0x34, 0x1B, 0xBB, 0xBF, 0x72, 0xF7, 0x40, 0x35, 0x48, 0x9C,
+ 0x51, 0x2F, 0x3B, 0x55, 0xE3, 0xC0, 0x9F, 0xD8, 0xD3, 0xF3, 0x8D, 0xB1,
+ 0xFF, 0xA7, 0x3E, 0xDC, 0x86, 0x77, 0xD7, 0xA6, 0x11, 0xFB, 0xF4, 0xBA,
+ 0x92, 0x91, 0x64, 0x83, 0xF1, 0x33, 0xEF, 0xDA, 0x2C, 0xB5, 0xB2, 0x2B,
+ 0x88, 0xD1, 0x99, 0xCB, 0x8C, 0x84, 0x1D, 0x14, 0x81, 0x97, 0x71, 0xCA,
+ 0x5F, 0xA3, 0x8B, 0x57, 0x3C, 0x82, 0xC4, 0x52, 0x5C, 0x1C, 0xE8, 0xA0,
+ 0x04, 0xB4, 0x85, 0x4A, 0xF6, 0x13, 0x54, 0xB6, 0xDF, 0x0C, 0x1A, 0x8E,
+ 0xDE, 0xE0, 0x39, 0xFC, 0x20, 0x9B, 0x24, 0x4E, 0xA9, 0x98, 0x9E, 0xAB,
+ 0xF2, 0x60, 0xD0, 0x6C, 0xEA, 0xFA, 0xC7, 0xD9, 0x00, 0xD4, 0x1F, 0x6E,
+ 0x43, 0xBC, 0xEC, 0x53, 0x89, 0xFE, 0x7A, 0x5D, 0x49, 0xC9, 0x32, 0xC2,
+ 0xF9, 0x9A, 0xF8, 0x6D, 0x16, 0xDB, 0x59, 0x96, 0x44, 0xE9, 0xCD, 0xE6,
+ 0x46, 0x42, 0x8F, 0x0A, 0xC1, 0xCC, 0xB9, 0x65, 0xB0, 0xD2, 0xC6, 0xAC,
+ 0x1E, 0x41, 0x62, 0x29, 0x2E, 0x0E, 0x74, 0x50, 0x02, 0x5A, 0xC3, 0x25,
+ 0x7B, 0x8A, 0x2A, 0x5B, 0xF0, 0x06, 0x0D, 0x47, 0x6F, 0x70, 0x9D, 0x7E,
+ 0x10, 0xCE, 0x12, 0x27, 0xD5, 0x4C, 0x4F, 0xD6, 0x79, 0x30, 0x68, 0x36,
+ 0x75, 0x7D, 0xE4, 0xED, 0x80, 0x6A, 0x90, 0x37, 0xA2, 0x5E, 0x76, 0xAA,
+ 0xC5, 0x7F, 0x3D, 0xAF, 0xA5, 0xE5, 0x19, 0x61, 0xFD, 0x4D, 0x7C, 0xB7,
+ 0x0B, 0xEE, 0xAD, 0x4B, 0x22, 0xF5, 0xE7, 0x73, 0x23, 0x21, 0xC8, 0x05,
+ 0xE1, 0x66, 0xDD, 0xB3, 0x58, 0x69, 0x63, 0x56, 0x0F, 0xA1, 0x31, 0x95,
+ 0x17, 0x07, 0x3A, 0x28 };
+
+const byte SAFER_SK::LOG[512] = {
+ 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 0x10, 0x12, 0x9F, 0xE4,
+ 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 0x4F, 0x06, 0x94, 0xFC,
+ 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 0x70, 0xED, 0xE8, 0xEC,
+ 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 0x44, 0x01, 0xAC, 0x25,
+ 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 0x0D, 0x6E, 0xFE, 0x26,
+ 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 0x98, 0x05, 0x9C, 0xBB,
+ 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 0xAF, 0x24, 0x5B, 0x87,
+ 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 0x5C, 0x8B, 0xD5, 0x54,
+ 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 0xCA, 0xF5, 0xD1, 0x17,
+ 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 0xAE, 0xCC, 0xD6, 0x35,
+ 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 0xD0, 0x50, 0x59, 0x3F,
+ 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 0x4C, 0x2E, 0x6B, 0x9E,
+ 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 0x75, 0x4A, 0x91, 0x71,
+ 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 0x0B, 0xDC, 0x37, 0x31,
+ 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 0xA4, 0x2F, 0x46, 0xF3,
+ 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 0x85, 0x18, 0x04, 0x1D,
+ 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 0xEE, 0x8D, 0x53, 0x4B,
+ 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 0x81, 0xC4, 0xC7, 0x36,
+ 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 0x6D, 0xF0, 0x02, 0x28,
+ 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 0x86, 0xCF, 0xE5, 0x42,
+ 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 0x92, 0x90, 0x7D, 0x39,
+ 0x6F, 0xE0, 0x89, 0x30, 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD,
+ 0x10, 0x12, 0x9F, 0xE4, 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65,
+ 0x4F, 0x06, 0x94, 0xFC, 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82,
+ 0x70, 0xED, 0xE8, 0xEC, 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47,
+ 0x44, 0x01, 0xAC, 0x25, 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3,
+ 0x0D, 0x6E, 0xFE, 0x26, 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84,
+ 0x98, 0x05, 0x9C, 0xBB, 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6,
+ 0xAF, 0x24, 0x5B, 0x87, 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7,
+ 0x5C, 0x8B, 0xD5, 0x54, 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11,
+ 0xCA, 0xF5, 0xD1, 0x17, 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB,
+ 0xAE, 0xCC, 0xD6, 0x35, 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9,
+ 0xD0, 0x50, 0x59, 0x3F, 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56,
+ 0x4C, 0x2E, 0x6B, 0x9E, 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51,
+ 0x75, 0x4A, 0x91, 0x71, 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55,
+ 0x0B, 0xDC, 0x37, 0x31, 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB,
+ 0xA4, 0x2F, 0x46, 0xF3, 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C,
+ 0x85, 0x18, 0x04, 0x1D, 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E,
+ 0xEE, 0x8D, 0x53, 0x4B, 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C,
+ 0x81, 0xC4, 0xC7, 0x36, 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68,
+ 0x6D, 0xF0, 0x02, 0x28, 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14,
+ 0x86, 0xCF, 0xE5, 0x42, 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F,
+ 0x92, 0x90, 0x7D, 0x39, 0x6F, 0xE0, 0x89, 0x30 };
+
+const byte SAFER_SK::BIAS[208] = {
+ 0x16, 0x73, 0x3B, 0x1E, 0x8E, 0x70, 0xBD, 0x86, 0x47, 0x7E, 0x24, 0x56,
+ 0xF1, 0x77, 0x88, 0x46, 0xB1, 0xBA, 0xA3, 0xB7, 0x10, 0x0A, 0xC5, 0x37,
+ 0xC9, 0x5A, 0x28, 0xAC, 0x64, 0xA5, 0xEC, 0xAB, 0xC6, 0x67, 0x95, 0x58,
+ 0x0D, 0xF8, 0x9A, 0xF6, 0x66, 0xDC, 0x05, 0x3D, 0xD3, 0x8A, 0xC3, 0xD8,
+ 0x6A, 0xE9, 0x36, 0x49, 0x43, 0xBF, 0xEB, 0xD4, 0x9B, 0x68, 0xA0, 0x65,
+ 0x5D, 0x57, 0x92, 0x1F, 0x71, 0x5C, 0xBB, 0x22, 0xC1, 0xBE, 0x7B, 0xBC,
+ 0x63, 0x94, 0x5F, 0x2A, 0x61, 0xB8, 0x34, 0x32, 0xFD, 0xFB, 0x17, 0x40,
+ 0xE6, 0x51, 0x1D, 0x41, 0x8F, 0x29, 0xDD, 0x04, 0x80, 0xDE, 0xE7, 0x31,
+ 0x7F, 0x01, 0xA2, 0xF7, 0x39, 0xDA, 0x6F, 0x23, 0xFE, 0x3A, 0xD0, 0x1C,
+ 0xD1, 0x30, 0x3E, 0x12, 0xCD, 0x0F, 0xE0, 0xA8, 0xAF, 0x82, 0x59, 0x2C,
+ 0x7D, 0xAD, 0xB2, 0xEF, 0xC2, 0x87, 0xCE, 0x75, 0x13, 0x02, 0x90, 0x4F,
+ 0x2E, 0x72, 0x33, 0x85, 0x8D, 0xCF, 0xA9, 0x81, 0xE2, 0xC4, 0x27, 0x2F,
+ 0x7A, 0x9F, 0x52, 0xE1, 0x15, 0x38, 0x2B, 0xFC, 0x42, 0xC7, 0x08, 0xE4,
+ 0x09, 0x55, 0x5E, 0x8C, 0x76, 0x60, 0xFF, 0xDF, 0xD7, 0x98, 0xFA, 0x0B,
+ 0x00, 0x1A, 0xF9, 0xA6, 0xB9, 0xE8, 0x9E, 0x62, 0xD9, 0x91, 0x50, 0xD2,
+ 0xEE, 0x18, 0xB4, 0x07, 0xEA, 0x5B, 0xA4, 0xC8, 0x0E, 0xCB, 0x48, 0x69,
+ 0x4E, 0x9C, 0x35, 0x79, 0x45, 0x4D, 0x54, 0xE5, 0x3C, 0x0C, 0x4A, 0x8B,
+ 0x3F, 0xCC, 0xA7, 0xDB };
+
+const byte SAFER_SK::KEY_INDEX[208] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x0E, 0x0F, 0x10, 0x11,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x08, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F };
+
+}
diff --git a/botan/src/block/safer/safer_sk.cpp b/botan/src/block/safer/safer_sk.cpp
new file mode 100644
index 0000000..f72c477
--- /dev/null
+++ b/botan/src/block/safer/safer_sk.cpp
@@ -0,0 +1,115 @@
+/*
+* SAFER-SK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/safer_sk.h>
+#include <botan/rotate.h>
+#include <botan/parsing.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* SAFER-SK Encryption
+*/
+void SAFER_SK::enc(const byte in[], byte out[]) const
+ {
+ byte A = in[0], B = in[1], C = in[2], D = in[3],
+ E = in[4], F = in[5], G = in[6], H = in[7], X, Y;
+ for(u32bit j = 0; j != 16*ROUNDS; j += 16)
+ {
+ A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]];
+ C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]];
+ E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]];
+ G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]];
+ A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11];
+ E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15];
+ B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H;
+ C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H;
+ H += D; Y = D + H; D = B + F; X = B + D; B = A + E;
+ A += B; F = C + G; E = C + F; C = X; G = Y;
+ }
+ out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1];
+ out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3];
+ out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5];
+ out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7];
+ }
+
+/*
+* SAFER-SK Decryption
+*/
+void SAFER_SK::dec(const byte in[], byte out[]) const
+ {
+ byte A = in[0], B = in[1], C = in[2], D = in[3],
+ E = in[4], F = in[5], G = in[6], H = in[7];
+ A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2];
+ D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5];
+ G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7];
+ for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16)
+ {
+ byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T;
+ A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D;
+ A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F;
+ A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G;
+ A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]];
+ C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256];
+ E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]];
+ G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256];
+ A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3];
+ E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7];
+ }
+ out[0] = A; out[1] = B; out[2] = C; out[3] = D;
+ out[4] = E; out[5] = F; out[6] = G; out[7] = H;
+ }
+
+/*
+* SAFER-SK Key Schedule
+*/
+void SAFER_SK::key_schedule(const byte key[], u32bit)
+ {
+ SecureBuffer<byte, 18> KB;
+
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ KB[ 8] ^= KB[j] = rotate_left(key[j], 5);
+ KB[17] ^= KB[j+9] = EK[j] = key[j+8];
+ }
+ for(u32bit j = 0; j != ROUNDS; ++j)
+ {
+ for(u32bit k = 0; k != 18; ++k)
+ KB[k] = rotate_left(KB[k], 6);
+ for(u32bit k = 0; k != 16; ++k)
+ EK[16*j+k+8] = KB[KEY_INDEX[16*j+k]] + BIAS[16*j+k];
+ }
+ }
+
+/*
+* Return the name of this type
+*/
+std::string SAFER_SK::name() const
+ {
+ return "SAFER-SK(" + to_string(ROUNDS) + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+BlockCipher* SAFER_SK::clone() const
+ {
+ return new SAFER_SK(ROUNDS);
+ }
+
+/*
+* SAFER-SK Constructor
+*/
+SAFER_SK::SAFER_SK(u32bit rounds) : BlockCipher(8, 16),
+ EK(16 * rounds + 8), ROUNDS(rounds)
+ {
+ if(ROUNDS > 13 || ROUNDS == 0)
+ throw Invalid_Argument(name() + ": Invalid number of rounds");
+ }
+
+}
diff --git a/botan/src/block/safer/safer_sk.h b/botan/src/block/safer/safer_sk.h
new file mode 100644
index 0000000..e52c583
--- /dev/null
+++ b/botan/src/block/safer/safer_sk.h
@@ -0,0 +1,40 @@
+/*
+* SAFER-SK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SAFER_SK_H__
+#define BOTAN_SAFER_SK_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* SAFER-SK
+*/
+class BOTAN_DLL SAFER_SK : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const;
+ BlockCipher* clone() const;
+ SAFER_SK(u32bit);
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static const byte EXP[256];
+ static const byte LOG[512];
+ static const byte BIAS[208];
+ static const byte KEY_INDEX[208];
+ SecureVector<byte> EK;
+ const u32bit ROUNDS;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/seed/info.txt b/botan/src/block/seed/info.txt
new file mode 100644
index 0000000..d049793
--- /dev/null
+++ b/botan/src/block/seed/info.txt
@@ -0,0 +1,11 @@
+realname "SEED"
+
+define SEED
+
+load_on auto
+
+<add>
+seed.cpp
+seed.h
+seed_tab.cpp
+</add>
diff --git a/botan/src/block/seed/seed.cpp b/botan/src/block/seed/seed.cpp
new file mode 100644
index 0000000..b06a7cd
--- /dev/null
+++ b/botan/src/block/seed/seed.cpp
@@ -0,0 +1,127 @@
+/*
+* SEED
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/seed.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* SEED G Function
+*/
+u32bit SEED::G_FUNC::operator()(u32bit X) const
+ {
+ return (S0[get_byte(3, X)] ^ S1[get_byte(2, X)] ^
+ S2[get_byte(1, X)] ^ S3[get_byte(0, X)]);
+ }
+
+/*
+* SEED Encryption
+*/
+void SEED::enc(const byte in[], byte out[]) const
+ {
+ u32bit B0 = load_be<u32bit>(in, 0);
+ u32bit B1 = load_be<u32bit>(in, 1);
+ u32bit B2 = load_be<u32bit>(in, 2);
+ u32bit B3 = load_be<u32bit>(in, 3);
+
+ G_FUNC G;
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ u32bit T0, T1;
+
+ T0 = B2 ^ K[2*j];
+ T1 = G(B2 ^ B3 ^ K[2*j+1]);
+ T0 = G(T1 + T0);
+ T1 = G(T1 + T0);
+ B1 ^= T1;
+ B0 ^= T0 + T1;
+
+ T0 = B0 ^ K[2*j+2];
+ T1 = G(B0 ^ B1 ^ K[2*j+3]);
+ T0 = G(T1 + T0);
+ T1 = G(T1 + T0);
+ B3 ^= T1;
+ B2 ^= T0 + T1;
+ }
+
+ store_be(out, B2, B3, B0, B1);
+ }
+
+/*
+* SEED Decryption
+*/
+void SEED::dec(const byte in[], byte out[]) const
+ {
+ u32bit B0 = load_be<u32bit>(in, 0);
+ u32bit B1 = load_be<u32bit>(in, 1);
+ u32bit B2 = load_be<u32bit>(in, 2);
+ u32bit B3 = load_be<u32bit>(in, 3);
+
+ G_FUNC G;
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ u32bit T0, T1;
+
+ T0 = B2 ^ K[30-2*j];
+ T1 = G(B2 ^ B3 ^ K[31-2*j]);
+ T0 = G(T1 + T0);
+ T1 = G(T1 + T0);
+ B1 ^= T1;
+ B0 ^= T0 + T1;
+
+ T0 = B0 ^ K[28-2*j];
+ T1 = G(B0 ^ B1 ^ K[29-2*j]);
+ T0 = G(T1 + T0);
+ T1 = G(T1 + T0);
+ B3 ^= T1;
+ B2 ^= T0 + T1;
+ }
+
+ store_be(out, B2, B3, B0, B1);
+ }
+
+/*
+* SEED Key Schedule
+*/
+void SEED::key_schedule(const byte key[], u32bit)
+ {
+ const u32bit RC[16] = {
+ 0x9E3779B9, 0x3C6EF373, 0x78DDE6E6, 0xF1BBCDCC,
+ 0xE3779B99, 0xC6EF3733, 0x8DDE6E67, 0x1BBCDCCF,
+ 0x3779B99E, 0x6EF3733C, 0xDDE6E678, 0xBBCDCCF1,
+ 0x779B99E3, 0xEF3733C6, 0xDE6E678D, 0xBCDCCF1B
+ };
+
+ SecureBuffer<u32bit, 4> WK;
+
+ for(u32bit j = 0; j != 4; ++j)
+ WK[j] = load_be<u32bit>(key, j);
+
+ G_FUNC G;
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ K[2*j ] = G(WK[0] + WK[2] - RC[j]);
+ K[2*j+1] = G(WK[1] - WK[3] + RC[j]) ^ K[2*j];
+
+ byte T = get_byte(3, WK[0]);
+ WK[0] = (WK[0] >> 8) | (get_byte(3, WK[1]) << 24);
+ WK[1] = (WK[1] >> 8) | (T << 24);
+
+ K[2*j+2] = G(WK[0] + WK[2] - RC[j+1]);
+ K[2*j+3] = G(WK[1] - WK[3] + RC[j+1]) ^ K[2*j+2];
+
+ T = get_byte(0, WK[3]);
+ WK[3] = (WK[3] << 8) | get_byte(0, WK[2]);
+ WK[2] = (WK[2] << 8) | T;
+ }
+ }
+
+}
diff --git a/botan/src/block/seed/seed.h b/botan/src/block/seed/seed.h
new file mode 100644
index 0000000..54c25d5
--- /dev/null
+++ b/botan/src/block/seed/seed.h
@@ -0,0 +1,43 @@
+/*
+* SEED
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SEED_H__
+#define BOTAN_SEED_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* SEED
+*/
+class BOTAN_DLL SEED : public BlockCipher
+ {
+ public:
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "SEED"; }
+ BlockCipher* clone() const { return new SEED; }
+ SEED() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ class G_FUNC
+ {
+ public:
+ u32bit operator()(u32bit) const;
+ private:
+ static const u32bit S0[256], S1[256], S2[256], S3[256];
+ };
+
+ SecureBuffer<u32bit, 32> K;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/seed/seed_tab.cpp b/botan/src/block/seed/seed_tab.cpp
new file mode 100644
index 0000000..6ada36e
--- /dev/null
+++ b/botan/src/block/seed/seed_tab.cpp
@@ -0,0 +1,192 @@
+/*
+* S-Box Tables for SEED
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/seed.h>
+
+namespace Botan {
+
+const u32bit SEED::G_FUNC::S0[256] = {
+ 0x2989A1A8, 0x05858184, 0x16C6D2D4, 0x13C3D3D0, 0x14445054, 0x1D0D111C,
+ 0x2C8CA0AC, 0x25052124, 0x1D4D515C, 0x03434340, 0x18081018, 0x1E0E121C,
+ 0x11415150, 0x3CCCF0FC, 0x0ACAC2C8, 0x23436360, 0x28082028, 0x04444044,
+ 0x20002020, 0x1D8D919C, 0x20C0E0E0, 0x22C2E2E0, 0x08C8C0C8, 0x17071314,
+ 0x2585A1A4, 0x0F8F838C, 0x03030300, 0x3B4B7378, 0x3B8BB3B8, 0x13031310,
+ 0x12C2D2D0, 0x2ECEE2EC, 0x30407070, 0x0C8C808C, 0x3F0F333C, 0x2888A0A8,
+ 0x32023230, 0x1DCDD1DC, 0x36C6F2F4, 0x34447074, 0x2CCCE0EC, 0x15859194,
+ 0x0B0B0308, 0x17475354, 0x1C4C505C, 0x1B4B5358, 0x3D8DB1BC, 0x01010100,
+ 0x24042024, 0x1C0C101C, 0x33437370, 0x18889098, 0x10001010, 0x0CCCC0CC,
+ 0x32C2F2F0, 0x19C9D1D8, 0x2C0C202C, 0x27C7E3E4, 0x32427270, 0x03838380,
+ 0x1B8B9398, 0x11C1D1D0, 0x06868284, 0x09C9C1C8, 0x20406060, 0x10405050,
+ 0x2383A3A0, 0x2BCBE3E8, 0x0D0D010C, 0x3686B2B4, 0x1E8E929C, 0x0F4F434C,
+ 0x3787B3B4, 0x1A4A5258, 0x06C6C2C4, 0x38487078, 0x2686A2A4, 0x12021210,
+ 0x2F8FA3AC, 0x15C5D1D4, 0x21416160, 0x03C3C3C0, 0x3484B0B4, 0x01414140,
+ 0x12425250, 0x3D4D717C, 0x0D8D818C, 0x08080008, 0x1F0F131C, 0x19899198,
+ 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37C7F3F4, 0x21C1E1E0,
+ 0x3DCDF1FC, 0x36467274, 0x2F0F232C, 0x27072324, 0x3080B0B0, 0x0B8B8388,
+ 0x0E0E020C, 0x2B8BA3A8, 0x2282A2A0, 0x2E4E626C, 0x13839390, 0x0D4D414C,
+ 0x29496168, 0x3C4C707C, 0x09090108, 0x0A0A0208, 0x3F8FB3BC, 0x2FCFE3EC,
+ 0x33C3F3F0, 0x05C5C1C4, 0x07878384, 0x14041014, 0x3ECEF2FC, 0x24446064,
+ 0x1ECED2DC, 0x2E0E222C, 0x0B4B4348, 0x1A0A1218, 0x06060204, 0x21012120,
+ 0x2B4B6368, 0x26466264, 0x02020200, 0x35C5F1F4, 0x12829290, 0x0A8A8288,
+ 0x0C0C000C, 0x3383B3B0, 0x3E4E727C, 0x10C0D0D0, 0x3A4A7278, 0x07474344,
+ 0x16869294, 0x25C5E1E4, 0x26062224, 0x00808080, 0x2D8DA1AC, 0x1FCFD3DC,
+ 0x2181A1A0, 0x30003030, 0x37073334, 0x2E8EA2AC, 0x36063234, 0x15051114,
+ 0x22022220, 0x38083038, 0x34C4F0F4, 0x2787A3A4, 0x05454144, 0x0C4C404C,
+ 0x01818180, 0x29C9E1E8, 0x04848084, 0x17879394, 0x35053134, 0x0BCBC3C8,
+ 0x0ECEC2CC, 0x3C0C303C, 0x31417170, 0x11011110, 0x07C7C3C4, 0x09898188,
+ 0x35457174, 0x3BCBF3F8, 0x1ACAD2D8, 0x38C8F0F8, 0x14849094, 0x19495158,
+ 0x02828280, 0x04C4C0C4, 0x3FCFF3FC, 0x09494148, 0x39093138, 0x27476364,
+ 0x00C0C0C0, 0x0FCFC3CC, 0x17C7D3D4, 0x3888B0B8, 0x0F0F030C, 0x0E8E828C,
+ 0x02424240, 0x23032320, 0x11819190, 0x2C4C606C, 0x1BCBD3D8, 0x2484A0A4,
+ 0x34043034, 0x31C1F1F0, 0x08484048, 0x02C2C2C0, 0x2F4F636C, 0x3D0D313C,
+ 0x2D0D212C, 0x00404040, 0x3E8EB2BC, 0x3E0E323C, 0x3C8CB0BC, 0x01C1C1C0,
+ 0x2A8AA2A8, 0x3A8AB2B8, 0x0E4E424C, 0x15455154, 0x3B0B3338, 0x1CCCD0DC,
+ 0x28486068, 0x3F4F737C, 0x1C8C909C, 0x18C8D0D8, 0x0A4A4248, 0x16465254,
+ 0x37477374, 0x2080A0A0, 0x2DCDE1EC, 0x06464244, 0x3585B1B4, 0x2B0B2328,
+ 0x25456164, 0x3ACAF2F8, 0x23C3E3E0, 0x3989B1B8, 0x3181B1B0, 0x1F8F939C,
+ 0x1E4E525C, 0x39C9F1F8, 0x26C6E2E4, 0x3282B2B0, 0x31013130, 0x2ACAE2E8,
+ 0x2D4D616C, 0x1F4F535C, 0x24C4E0E4, 0x30C0F0F0, 0x0DCDC1CC, 0x08888088,
+ 0x16061214, 0x3A0A3238, 0x18485058, 0x14C4D0D4, 0x22426260, 0x29092128,
+ 0x07070304, 0x33033330, 0x28C8E0E8, 0x1B0B1318, 0x05050104, 0x39497178,
+ 0x10809090, 0x2A4A6268, 0x2A0A2228, 0x1A8A9298 };
+
+const u32bit SEED::G_FUNC::S1[256] = {
+ 0x38380830, 0xE828C8E0, 0x2C2D0D21, 0xA42686A2, 0xCC0FCFC3, 0xDC1ECED2,
+ 0xB03383B3, 0xB83888B0, 0xAC2F8FA3, 0x60204060, 0x54154551, 0xC407C7C3,
+ 0x44044440, 0x6C2F4F63, 0x682B4B63, 0x581B4B53, 0xC003C3C3, 0x60224262,
+ 0x30330333, 0xB43585B1, 0x28290921, 0xA02080A0, 0xE022C2E2, 0xA42787A3,
+ 0xD013C3D3, 0x90118191, 0x10110111, 0x04060602, 0x1C1C0C10, 0xBC3C8CB0,
+ 0x34360632, 0x480B4B43, 0xEC2FCFE3, 0x88088880, 0x6C2C4C60, 0xA82888A0,
+ 0x14170713, 0xC404C4C0, 0x14160612, 0xF434C4F0, 0xC002C2C2, 0x44054541,
+ 0xE021C1E1, 0xD416C6D2, 0x3C3F0F33, 0x3C3D0D31, 0x8C0E8E82, 0x98188890,
+ 0x28280820, 0x4C0E4E42, 0xF436C6F2, 0x3C3E0E32, 0xA42585A1, 0xF839C9F1,
+ 0x0C0D0D01, 0xDC1FCFD3, 0xD818C8D0, 0x282B0B23, 0x64264662, 0x783A4A72,
+ 0x24270723, 0x2C2F0F23, 0xF031C1F1, 0x70324272, 0x40024242, 0xD414C4D0,
+ 0x40014141, 0xC000C0C0, 0x70334373, 0x64274763, 0xAC2C8CA0, 0x880B8B83,
+ 0xF437C7F3, 0xAC2D8DA1, 0x80008080, 0x1C1F0F13, 0xC80ACAC2, 0x2C2C0C20,
+ 0xA82A8AA2, 0x34340430, 0xD012C2D2, 0x080B0B03, 0xEC2ECEE2, 0xE829C9E1,
+ 0x5C1D4D51, 0x94148490, 0x18180810, 0xF838C8F0, 0x54174753, 0xAC2E8EA2,
+ 0x08080800, 0xC405C5C1, 0x10130313, 0xCC0DCDC1, 0x84068682, 0xB83989B1,
+ 0xFC3FCFF3, 0x7C3D4D71, 0xC001C1C1, 0x30310131, 0xF435C5F1, 0x880A8A82,
+ 0x682A4A62, 0xB03181B1, 0xD011C1D1, 0x20200020, 0xD417C7D3, 0x00020202,
+ 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xD81BCBD3,
+ 0x9C1D8D91, 0x98198991, 0x60214161, 0xBC3E8EB2, 0xE426C6E2, 0x58194951,
+ 0xDC1DCDD1, 0x50114151, 0x90108090, 0xDC1CCCD0, 0x981A8A92, 0xA02383A3,
+ 0xA82B8BA3, 0xD010C0D0, 0x80018181, 0x0C0F0F03, 0x44074743, 0x181A0A12,
+ 0xE023C3E3, 0xEC2CCCE0, 0x8C0D8D81, 0xBC3F8FB3, 0x94168692, 0x783B4B73,
+ 0x5C1C4C50, 0xA02282A2, 0xA02181A1, 0x60234363, 0x20230323, 0x4C0D4D41,
+ 0xC808C8C0, 0x9C1E8E92, 0x9C1C8C90, 0x383A0A32, 0x0C0C0C00, 0x2C2E0E22,
+ 0xB83A8AB2, 0x6C2E4E62, 0x9C1F8F93, 0x581A4A52, 0xF032C2F2, 0x90128292,
+ 0xF033C3F3, 0x48094941, 0x78384870, 0xCC0CCCC0, 0x14150511, 0xF83BCBF3,
+ 0x70304070, 0x74354571, 0x7C3F4F73, 0x34350531, 0x10100010, 0x00030303,
+ 0x64244460, 0x6C2D4D61, 0xC406C6C2, 0x74344470, 0xD415C5D1, 0xB43484B0,
+ 0xE82ACAE2, 0x08090901, 0x74364672, 0x18190911, 0xFC3ECEF2, 0x40004040,
+ 0x10120212, 0xE020C0E0, 0xBC3D8DB1, 0x04050501, 0xF83ACAF2, 0x00010101,
+ 0xF030C0F0, 0x282A0A22, 0x5C1E4E52, 0xA82989A1, 0x54164652, 0x40034343,
+ 0x84058581, 0x14140410, 0x88098981, 0x981B8B93, 0xB03080B0, 0xE425C5E1,
+ 0x48084840, 0x78394971, 0x94178793, 0xFC3CCCF0, 0x1C1E0E12, 0x80028282,
+ 0x20210121, 0x8C0C8C80, 0x181B0B13, 0x5C1F4F53, 0x74374773, 0x54144450,
+ 0xB03282B2, 0x1C1D0D11, 0x24250521, 0x4C0F4F43, 0x00000000, 0x44064642,
+ 0xEC2DCDE1, 0x58184850, 0x50124252, 0xE82BCBE3, 0x7C3E4E72, 0xD81ACAD2,
+ 0xC809C9C1, 0xFC3DCDF1, 0x30300030, 0x94158591, 0x64254561, 0x3C3C0C30,
+ 0xB43686B2, 0xE424C4E0, 0xB83B8BB3, 0x7C3C4C70, 0x0C0E0E02, 0x50104050,
+ 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
+ 0x34370733, 0xE427C7E3, 0x24240420, 0xA42484A0, 0xC80BCBC3, 0x50134353,
+ 0x080A0A02, 0x84078783, 0xD819C9D1, 0x4C0C4C40, 0x80038383, 0x8C0F8F83,
+ 0xCC0ECEC2, 0x383B0B33, 0x480A4A42, 0xB43787B3 };
+
+const u32bit SEED::G_FUNC::S2[256] = {
+ 0xA1A82989, 0x81840585, 0xD2D416C6, 0xD3D013C3, 0x50541444, 0x111C1D0D,
+ 0xA0AC2C8C, 0x21242505, 0x515C1D4D, 0x43400343, 0x10181808, 0x121C1E0E,
+ 0x51501141, 0xF0FC3CCC, 0xC2C80ACA, 0x63602343, 0x20282808, 0x40440444,
+ 0x20202000, 0x919C1D8D, 0xE0E020C0, 0xE2E022C2, 0xC0C808C8, 0x13141707,
+ 0xA1A42585, 0x838C0F8F, 0x03000303, 0x73783B4B, 0xB3B83B8B, 0x13101303,
+ 0xD2D012C2, 0xE2EC2ECE, 0x70703040, 0x808C0C8C, 0x333C3F0F, 0xA0A82888,
+ 0x32303202, 0xD1DC1DCD, 0xF2F436C6, 0x70743444, 0xE0EC2CCC, 0x91941585,
+ 0x03080B0B, 0x53541747, 0x505C1C4C, 0x53581B4B, 0xB1BC3D8D, 0x01000101,
+ 0x20242404, 0x101C1C0C, 0x73703343, 0x90981888, 0x10101000, 0xC0CC0CCC,
+ 0xF2F032C2, 0xD1D819C9, 0x202C2C0C, 0xE3E427C7, 0x72703242, 0x83800383,
+ 0x93981B8B, 0xD1D011C1, 0x82840686, 0xC1C809C9, 0x60602040, 0x50501040,
+ 0xA3A02383, 0xE3E82BCB, 0x010C0D0D, 0xB2B43686, 0x929C1E8E, 0x434C0F4F,
+ 0xB3B43787, 0x52581A4A, 0xC2C406C6, 0x70783848, 0xA2A42686, 0x12101202,
+ 0xA3AC2F8F, 0xD1D415C5, 0x61602141, 0xC3C003C3, 0xB0B43484, 0x41400141,
+ 0x52501242, 0x717C3D4D, 0x818C0D8D, 0x00080808, 0x131C1F0F, 0x91981989,
+ 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xF3F437C7, 0xE1E021C1,
+ 0xF1FC3DCD, 0x72743646, 0x232C2F0F, 0x23242707, 0xB0B03080, 0x83880B8B,
+ 0x020C0E0E, 0xA3A82B8B, 0xA2A02282, 0x626C2E4E, 0x93901383, 0x414C0D4D,
+ 0x61682949, 0x707C3C4C, 0x01080909, 0x02080A0A, 0xB3BC3F8F, 0xE3EC2FCF,
+ 0xF3F033C3, 0xC1C405C5, 0x83840787, 0x10141404, 0xF2FC3ECE, 0x60642444,
+ 0xD2DC1ECE, 0x222C2E0E, 0x43480B4B, 0x12181A0A, 0x02040606, 0x21202101,
+ 0x63682B4B, 0x62642646, 0x02000202, 0xF1F435C5, 0x92901282, 0x82880A8A,
+ 0x000C0C0C, 0xB3B03383, 0x727C3E4E, 0xD0D010C0, 0x72783A4A, 0x43440747,
+ 0x92941686, 0xE1E425C5, 0x22242606, 0x80800080, 0xA1AC2D8D, 0xD3DC1FCF,
+ 0xA1A02181, 0x30303000, 0x33343707, 0xA2AC2E8E, 0x32343606, 0x11141505,
+ 0x22202202, 0x30383808, 0xF0F434C4, 0xA3A42787, 0x41440545, 0x404C0C4C,
+ 0x81800181, 0xE1E829C9, 0x80840484, 0x93941787, 0x31343505, 0xC3C80BCB,
+ 0xC2CC0ECE, 0x303C3C0C, 0x71703141, 0x11101101, 0xC3C407C7, 0x81880989,
+ 0x71743545, 0xF3F83BCB, 0xD2D81ACA, 0xF0F838C8, 0x90941484, 0x51581949,
+ 0x82800282, 0xC0C404C4, 0xF3FC3FCF, 0x41480949, 0x31383909, 0x63642747,
+ 0xC0C000C0, 0xC3CC0FCF, 0xD3D417C7, 0xB0B83888, 0x030C0F0F, 0x828C0E8E,
+ 0x42400242, 0x23202303, 0x91901181, 0x606C2C4C, 0xD3D81BCB, 0xA0A42484,
+ 0x30343404, 0xF1F031C1, 0x40480848, 0xC2C002C2, 0x636C2F4F, 0x313C3D0D,
+ 0x212C2D0D, 0x40400040, 0xB2BC3E8E, 0x323C3E0E, 0xB0BC3C8C, 0xC1C001C1,
+ 0xA2A82A8A, 0xB2B83A8A, 0x424C0E4E, 0x51541545, 0x33383B0B, 0xD0DC1CCC,
+ 0x60682848, 0x737C3F4F, 0x909C1C8C, 0xD0D818C8, 0x42480A4A, 0x52541646,
+ 0x73743747, 0xA0A02080, 0xE1EC2DCD, 0x42440646, 0xB1B43585, 0x23282B0B,
+ 0x61642545, 0xF2F83ACA, 0xE3E023C3, 0xB1B83989, 0xB1B03181, 0x939C1F8F,
+ 0x525C1E4E, 0xF1F839C9, 0xE2E426C6, 0xB2B03282, 0x31303101, 0xE2E82ACA,
+ 0x616C2D4D, 0x535C1F4F, 0xE0E424C4, 0xF0F030C0, 0xC1CC0DCD, 0x80880888,
+ 0x12141606, 0x32383A0A, 0x50581848, 0xD0D414C4, 0x62602242, 0x21282909,
+ 0x03040707, 0x33303303, 0xE0E828C8, 0x13181B0B, 0x01040505, 0x71783949,
+ 0x90901080, 0x62682A4A, 0x22282A0A, 0x92981A8A };
+
+const u32bit SEED::G_FUNC::S3[256] = {
+ 0x08303838, 0xC8E0E828, 0x0D212C2D, 0x86A2A426, 0xCFC3CC0F, 0xCED2DC1E,
+ 0x83B3B033, 0x88B0B838, 0x8FA3AC2F, 0x40606020, 0x45515415, 0xC7C3C407,
+ 0x44404404, 0x4F636C2F, 0x4B63682B, 0x4B53581B, 0xC3C3C003, 0x42626022,
+ 0x03333033, 0x85B1B435, 0x09212829, 0x80A0A020, 0xC2E2E022, 0x87A3A427,
+ 0xC3D3D013, 0x81919011, 0x01111011, 0x06020406, 0x0C101C1C, 0x8CB0BC3C,
+ 0x06323436, 0x4B43480B, 0xCFE3EC2F, 0x88808808, 0x4C606C2C, 0x88A0A828,
+ 0x07131417, 0xC4C0C404, 0x06121416, 0xC4F0F434, 0xC2C2C002, 0x45414405,
+ 0xC1E1E021, 0xC6D2D416, 0x0F333C3F, 0x0D313C3D, 0x8E828C0E, 0x88909818,
+ 0x08202828, 0x4E424C0E, 0xC6F2F436, 0x0E323C3E, 0x85A1A425, 0xC9F1F839,
+ 0x0D010C0D, 0xCFD3DC1F, 0xC8D0D818, 0x0B23282B, 0x46626426, 0x4A72783A,
+ 0x07232427, 0x0F232C2F, 0xC1F1F031, 0x42727032, 0x42424002, 0xC4D0D414,
+ 0x41414001, 0xC0C0C000, 0x43737033, 0x47636427, 0x8CA0AC2C, 0x8B83880B,
+ 0xC7F3F437, 0x8DA1AC2D, 0x80808000, 0x0F131C1F, 0xCAC2C80A, 0x0C202C2C,
+ 0x8AA2A82A, 0x04303434, 0xC2D2D012, 0x0B03080B, 0xCEE2EC2E, 0xC9E1E829,
+ 0x4D515C1D, 0x84909414, 0x08101818, 0xC8F0F838, 0x47535417, 0x8EA2AC2E,
+ 0x08000808, 0xC5C1C405, 0x03131013, 0xCDC1CC0D, 0x86828406, 0x89B1B839,
+ 0xCFF3FC3F, 0x4D717C3D, 0xC1C1C001, 0x01313031, 0xC5F1F435, 0x8A82880A,
+ 0x4A62682A, 0x81B1B031, 0xC1D1D011, 0x00202020, 0xC7D3D417, 0x02020002,
+ 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xCBD3D81B,
+ 0x8D919C1D, 0x89919819, 0x41616021, 0x8EB2BC3E, 0xC6E2E426, 0x49515819,
+ 0xCDD1DC1D, 0x41515011, 0x80909010, 0xCCD0DC1C, 0x8A92981A, 0x83A3A023,
+ 0x8BA3A82B, 0xC0D0D010, 0x81818001, 0x0F030C0F, 0x47434407, 0x0A12181A,
+ 0xC3E3E023, 0xCCE0EC2C, 0x8D818C0D, 0x8FB3BC3F, 0x86929416, 0x4B73783B,
+ 0x4C505C1C, 0x82A2A022, 0x81A1A021, 0x43636023, 0x03232023, 0x4D414C0D,
+ 0xC8C0C808, 0x8E929C1E, 0x8C909C1C, 0x0A32383A, 0x0C000C0C, 0x0E222C2E,
+ 0x8AB2B83A, 0x4E626C2E, 0x8F939C1F, 0x4A52581A, 0xC2F2F032, 0x82929012,
+ 0xC3F3F033, 0x49414809, 0x48707838, 0xCCC0CC0C, 0x05111415, 0xCBF3F83B,
+ 0x40707030, 0x45717435, 0x4F737C3F, 0x05313435, 0x00101010, 0x03030003,
+ 0x44606424, 0x4D616C2D, 0xC6C2C406, 0x44707434, 0xC5D1D415, 0x84B0B434,
+ 0xCAE2E82A, 0x09010809, 0x46727436, 0x09111819, 0xCEF2FC3E, 0x40404000,
+ 0x02121012, 0xC0E0E020, 0x8DB1BC3D, 0x05010405, 0xCAF2F83A, 0x01010001,
+ 0xC0F0F030, 0x0A22282A, 0x4E525C1E, 0x89A1A829, 0x46525416, 0x43434003,
+ 0x85818405, 0x04101414, 0x89818809, 0x8B93981B, 0x80B0B030, 0xC5E1E425,
+ 0x48404808, 0x49717839, 0x87939417, 0xCCF0FC3C, 0x0E121C1E, 0x82828002,
+ 0x01212021, 0x8C808C0C, 0x0B13181B, 0x4F535C1F, 0x47737437, 0x44505414,
+ 0x82B2B032, 0x0D111C1D, 0x05212425, 0x4F434C0F, 0x00000000, 0x46424406,
+ 0xCDE1EC2D, 0x48505818, 0x42525012, 0xCBE3E82B, 0x4E727C3E, 0xCAD2D81A,
+ 0xC9C1C809, 0xCDF1FC3D, 0x00303030, 0x85919415, 0x45616425, 0x0C303C3C,
+ 0x86B2B436, 0xC4E0E424, 0x8BB3B83B, 0x4C707C3C, 0x0E020C0E, 0x40505010,
+ 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
+ 0x07333437, 0xC7E3E427, 0x04202424, 0x84A0A424, 0xCBC3C80B, 0x43535013,
+ 0x0A02080A, 0x87838407, 0xC9D1D819, 0x4C404C0C, 0x83838003, 0x8F838C0F,
+ 0xCEC2CC0E, 0x0B33383B, 0x4A42480A, 0x87B3B437 };
+
+}
diff --git a/botan/src/block/serpent/info.txt b/botan/src/block/serpent/info.txt
new file mode 100644
index 0000000..baaccbf
--- /dev/null
+++ b/botan/src/block/serpent/info.txt
@@ -0,0 +1,10 @@
+realname "Serpent"
+
+define SERPENT
+
+load_on auto
+
+<add>
+serpent.cpp
+serpent.h
+</add>
diff --git a/botan/src/block/serpent/serpent.cpp b/botan/src/block/serpent/serpent.cpp
new file mode 100644
index 0000000..df7592f
--- /dev/null
+++ b/botan/src/block/serpent/serpent.cpp
@@ -0,0 +1,369 @@
+/*
+* Serpent
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/serpent.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Serpent Encryption S-Box 1
+*/
+inline void SBoxE1(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T3 ^= T0; T4 = T1; T1 &= T3; T4 ^= T2; T1 ^= T0; T0 |= T3; T0 ^= T4;
+ T4 ^= T3; T3 ^= T2; T2 |= T1; T2 ^= T4; T4 = ~T4; T4 |= T1; T1 ^= T3;
+ T1 ^= T4; T3 |= T0; T1 ^= T3; T4 ^= T3;
+ B0 = T1; B1 = T4; B2 = T2; B3 = T0;
+ }
+
+/*
+* Serpent Encryption S-Box 2
+*/
+inline void SBoxE2(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T0 = ~T0; T2 = ~T2; T4 = T0; T0 &= T1; T2 ^= T0; T0 |= T3; T3 ^= T2;
+ T1 ^= T0; T0 ^= T4; T4 |= T1; T1 ^= T3; T2 |= T0; T2 &= T4; T0 ^= T1;
+ T1 &= T2; T1 ^= T0; T0 &= T2; T0 ^= T4;
+ B0 = T2; B1 = T0; B2 = T3; B3 = T1;
+ }
+
+/*
+* Serpent Encryption S-Box 3
+*/
+inline void SBoxE3(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T0; T0 &= T2; T0 ^= T3; T2 ^= T1; T2 ^= T0; T3 |= T4; T3 ^= T1;
+ T4 ^= T2; T1 = T3; T3 |= T4; T3 ^= T0; T0 &= T1; T4 ^= T0; T1 ^= T3;
+ T1 ^= T4; T4 = ~T4;
+ B0 = T2; B1 = T3; B2 = T1; B3 = T4;
+ }
+
+/*
+* Serpent Encryption S-Box 4
+*/
+inline void SBoxE4(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T0; T0 |= T3; T3 ^= T1; T1 &= T4; T4 ^= T2; T2 ^= T3; T3 &= T0;
+ T4 |= T1; T3 ^= T4; T0 ^= T1; T4 &= T0; T1 ^= T3; T4 ^= T2; T1 |= T0;
+ T1 ^= T2; T0 ^= T3; T2 = T1; T1 |= T3; T1 ^= T0;
+ B0 = T1; B1 = T2; B2 = T3; B3 = T4;
+ }
+
+/*
+* Serpent Encryption S-Box 5
+*/
+inline void SBoxE5(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T1 ^= T3; T3 = ~T3; T2 ^= T3; T3 ^= T0; T4 = T1; T1 &= T3; T1 ^= T2;
+ T4 ^= T3; T0 ^= T4; T2 &= T4; T2 ^= T0; T0 &= T1; T3 ^= T0; T4 |= T1;
+ T4 ^= T0; T0 |= T3; T0 ^= T2; T2 &= T3; T0 = ~T0; T4 ^= T2;
+ B0 = T1; B1 = T4; B2 = T0; B3 = T3;
+ }
+
+/*
+* Serpent Encryption S-Box 6
+*/
+inline void SBoxE6(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T0 ^= T1; T1 ^= T3; T3 = ~T3; T4 = T1; T1 &= T0; T2 ^= T3; T1 ^= T2;
+ T2 |= T4; T4 ^= T3; T3 &= T1; T3 ^= T0; T4 ^= T1; T4 ^= T2; T2 ^= T0;
+ T0 &= T3; T2 = ~T2; T0 ^= T4; T4 |= T3; T2 ^= T4;
+ B0 = T1; B1 = T3; B2 = T0; B3 = T2;
+ }
+
+/*
+* Serpent Encryption S-Box 7
+*/
+inline void SBoxE7(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T2 = ~T2; T4 = T3; T3 &= T0; T0 ^= T4; T3 ^= T2; T2 |= T4; T1 ^= T3;
+ T2 ^= T0; T0 |= T1; T2 ^= T1; T4 ^= T0; T0 |= T3; T0 ^= T2; T4 ^= T3;
+ T4 ^= T0; T3 = ~T3; T2 &= T4; T2 ^= T3;
+ B0 = T0; B1 = T1; B2 = T4; B3 = T2;
+ }
+
+/*
+* Serpent Encryption S-Box 8
+*/
+inline void SBoxE8(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T1; T1 |= T2; T1 ^= T3; T4 ^= T2; T2 ^= T1; T3 |= T4; T3 &= T0;
+ T4 ^= T2; T3 ^= T1; T1 |= T4; T1 ^= T0; T0 |= T4; T0 ^= T2; T1 ^= T4;
+ T2 ^= T1; T1 &= T0; T1 ^= T4; T2 = ~T2; T2 |= T0; T4 ^= T2;
+ B0 = T4; B1 = T3; B2 = T1; B3 = T0;
+ }
+
+/*
+* Serpent Decryption S-Box 1
+*/
+inline void SBoxD1(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T2 = ~T2; T4 = T1; T1 |= T0; T4 = ~T4; T1 ^= T2; T2 |= T4; T1 ^= T3;
+ T0 ^= T4; T2 ^= T0; T0 &= T3; T4 ^= T0; T0 |= T1; T0 ^= T2; T3 ^= T4;
+ T2 ^= T1; T3 ^= T0; T3 ^= T1; T2 &= T3; T4 ^= T2;
+ B0 = T0; B1 = T4; B2 = T1; B3 = T3;
+ }
+
+/*
+* Serpent Decryption S-Box 2
+*/
+inline void SBoxD2(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T1; T1 ^= T3; T3 &= T1; T4 ^= T2; T3 ^= T0; T0 |= T1; T2 ^= T3;
+ T0 ^= T4; T0 |= T2; T1 ^= T3; T0 ^= T1; T1 |= T3; T1 ^= T0; T4 = ~T4;
+ T4 ^= T1; T1 |= T0; T1 ^= T0; T1 |= T4; T3 ^= T1;
+ B0 = T4; B1 = T0; B2 = T3; B3 = T2;
+ }
+
+/*
+* Serpent Decryption S-Box 3
+*/
+inline void SBoxD3(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T2 ^= T3; T3 ^= T0; T4 = T3; T3 &= T2; T3 ^= T1; T1 |= T2; T1 ^= T4;
+ T4 &= T3; T2 ^= T3; T4 &= T0; T4 ^= T2; T2 &= T1; T2 |= T0; T3 = ~T3;
+ T2 ^= T3; T0 ^= T3; T0 &= T1; T3 ^= T4; T3 ^= T0;
+ B0 = T1; B1 = T4; B2 = T2; B3 = T3;
+ }
+
+/*
+* Serpent Decryption S-Box 4
+*/
+inline void SBoxD4(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T2; T2 ^= T1; T0 ^= T2; T4 &= T2; T4 ^= T0; T0 &= T1; T1 ^= T3;
+ T3 |= T4; T2 ^= T3; T0 ^= T3; T1 ^= T4; T3 &= T2; T3 ^= T1; T1 ^= T0;
+ T1 |= T2; T0 ^= T3; T1 ^= T4; T0 ^= T1;
+ B0 = T2; B1 = T1; B2 = T3; B3 = T0;
+ }
+
+/*
+* Serpent Decryption S-Box 5
+*/
+inline void SBoxD5(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T2; T2 &= T3; T2 ^= T1; T1 |= T3; T1 &= T0; T4 ^= T2; T4 ^= T1;
+ T1 &= T2; T0 = ~T0; T3 ^= T4; T1 ^= T3; T3 &= T0; T3 ^= T2; T0 ^= T1;
+ T2 &= T0; T3 ^= T0; T2 ^= T4; T2 |= T3; T3 ^= T0; T2 ^= T1;
+ B0 = T0; B1 = T3; B2 = T2; B3 = T4;
+ }
+
+/*
+* Serpent Decryption S-Box 6
+*/
+inline void SBoxD6(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T1 = ~T1; T4 = T3; T2 ^= T1; T3 |= T0; T3 ^= T2; T2 |= T1; T2 &= T0;
+ T4 ^= T3; T2 ^= T4; T4 |= T0; T4 ^= T1; T1 &= T2; T1 ^= T3; T4 ^= T2;
+ T3 &= T4; T4 ^= T1; T3 ^= T4; T4 = ~T4; T3 ^= T0;
+ B0 = T1; B1 = T4; B2 = T3; B3 = T2;
+ }
+
+/*
+* Serpent Decryption S-Box 7
+*/
+inline void SBoxD7(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T0 ^= T2; T4 = T2; T2 &= T0; T4 ^= T3; T2 = ~T2; T3 ^= T1; T2 ^= T3;
+ T4 |= T0; T0 ^= T2; T3 ^= T4; T4 ^= T1; T1 &= T3; T1 ^= T0; T0 ^= T3;
+ T0 |= T2; T3 ^= T1; T4 ^= T0;
+ B0 = T1; B1 = T2; B2 = T4; B3 = T3;
+ }
+
+/*
+* Serpent Decryption S-Box 8
+*/
+inline void SBoxD8(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ u32bit T0 = B0, T1 = B1, T2 = B2, T3 = B3, T4;
+ T4 = T2; T2 ^= T0; T0 &= T3; T4 |= T3; T2 = ~T2; T3 ^= T1; T1 |= T0;
+ T0 ^= T2; T2 &= T4; T3 &= T4; T1 ^= T2; T2 ^= T0; T0 |= T2; T4 ^= T1;
+ T0 ^= T3; T3 ^= T4; T4 |= T0; T3 ^= T2; T4 ^= T2;
+ B0 = T3; B1 = T0; B2 = T1; B3 = T4;
+ }
+
+/*
+* Serpent's Linear Transformation
+*/
+inline void transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ B0 = rotate_left(B0, 13); B2 = rotate_left(B2, 3);
+ B1 ^= B0 ^ B2; B3 ^= B2 ^ (B0 << 3);
+ B1 = rotate_left(B1, 1); B3 = rotate_left(B3, 7);
+ B0 ^= B1 ^ B3; B2 ^= B3 ^ (B1 << 7);
+ B0 = rotate_left(B0, 5); B2 = rotate_left(B2, 22);
+ }
+
+/*
+* Serpent's Inverse Linear Transformation
+*/
+inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3)
+ {
+ B2 = rotate_right(B2, 22); B0 = rotate_right(B0, 5);
+ B2 ^= B3 ^ (B1 << 7); B0 ^= B1 ^ B3;
+ B3 = rotate_right(B3, 7); B1 = rotate_right(B1, 1);
+ B3 ^= B2 ^ (B0 << 3); B1 ^= B0 ^ B2;
+ B2 = rotate_right(B2, 3); B0 = rotate_right(B0, 13);
+ }
+
+}
+
+/*
+* XOR a key block with a data block
+*/
+#define key_xor(round, B0, B1, B2, B3) \
+ B0 ^= round_key[4*round ]; \
+ B1 ^= round_key[4*round+1]; \
+ B2 ^= round_key[4*round+2]; \
+ B3 ^= round_key[4*round+3];
+
+/*
+* Serpent Encryption
+*/
+void Serpent::enc(const byte in[], byte out[]) const
+ {
+ u32bit B0 = load_le<u32bit>(in, 0);
+ u32bit B1 = load_le<u32bit>(in, 1);
+ u32bit B2 = load_le<u32bit>(in, 2);
+ u32bit B3 = load_le<u32bit>(in, 3);
+
+ key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
+ key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3);
+
+ store_le(out, B0, B1, B2, B3);
+ }
+
+/*
+* Serpent Decryption
+*/
+void Serpent::dec(const byte in[], byte out[]) const
+ {
+ u32bit B0 = load_le<u32bit>(in, 0);
+ u32bit B1 = load_le<u32bit>(in, 1);
+ u32bit B2 = load_le<u32bit>(in, 2);
+ u32bit B3 = load_le<u32bit>(in, 3);
+
+ key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3);
+ i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3);
+
+ store_le(out, B0, B1, B2, B3);
+ }
+
+/*
+* Serpent Key Schedule
+*/
+void Serpent::key_schedule(const byte key[], u32bit length)
+ {
+ const u32bit PHI = 0x9E3779B9;
+
+ SecureBuffer<u32bit, 140> W;
+ for(u32bit j = 0; j != length / 4; ++j)
+ W[j] = load_le<u32bit>(key, j);
+
+ W[length / 4] |= u32bit(1) << ((length%4)*8);
+ for(u32bit j = 8; j != 140; ++j)
+ W[j] = rotate_left(W[j-8] ^ W[j-5] ^ W[j-3] ^ W[j-1] ^ PHI ^ (j-8), 11);
+ SBoxE4(W[ 8],W[ 9],W[ 10],W[ 11]); SBoxE3(W[ 12],W[ 13],W[ 14],W[ 15]);
+ SBoxE2(W[ 16],W[ 17],W[ 18],W[ 19]); SBoxE1(W[ 20],W[ 21],W[ 22],W[ 23]);
+ SBoxE8(W[ 24],W[ 25],W[ 26],W[ 27]); SBoxE7(W[ 28],W[ 29],W[ 30],W[ 31]);
+ SBoxE6(W[ 32],W[ 33],W[ 34],W[ 35]); SBoxE5(W[ 36],W[ 37],W[ 38],W[ 39]);
+ SBoxE4(W[ 40],W[ 41],W[ 42],W[ 43]); SBoxE3(W[ 44],W[ 45],W[ 46],W[ 47]);
+ SBoxE2(W[ 48],W[ 49],W[ 50],W[ 51]); SBoxE1(W[ 52],W[ 53],W[ 54],W[ 55]);
+ SBoxE8(W[ 56],W[ 57],W[ 58],W[ 59]); SBoxE7(W[ 60],W[ 61],W[ 62],W[ 63]);
+ SBoxE6(W[ 64],W[ 65],W[ 66],W[ 67]); SBoxE5(W[ 68],W[ 69],W[ 70],W[ 71]);
+ SBoxE4(W[ 72],W[ 73],W[ 74],W[ 75]); SBoxE3(W[ 76],W[ 77],W[ 78],W[ 79]);
+ SBoxE2(W[ 80],W[ 81],W[ 82],W[ 83]); SBoxE1(W[ 84],W[ 85],W[ 86],W[ 87]);
+ SBoxE8(W[ 88],W[ 89],W[ 90],W[ 91]); SBoxE7(W[ 92],W[ 93],W[ 94],W[ 95]);
+ SBoxE6(W[ 96],W[ 97],W[ 98],W[ 99]); SBoxE5(W[100],W[101],W[102],W[103]);
+ SBoxE4(W[104],W[105],W[106],W[107]); SBoxE3(W[108],W[109],W[110],W[111]);
+ SBoxE2(W[112],W[113],W[114],W[115]); SBoxE1(W[116],W[117],W[118],W[119]);
+ SBoxE8(W[120],W[121],W[122],W[123]); SBoxE7(W[124],W[125],W[126],W[127]);
+ SBoxE6(W[128],W[129],W[130],W[131]); SBoxE5(W[132],W[133],W[134],W[135]);
+ SBoxE4(W[136],W[137],W[138],W[139]);
+ round_key.copy(W + 8, 132);
+ }
+
+}
diff --git a/botan/src/block/serpent/serpent.h b/botan/src/block/serpent/serpent.h
new file mode 100644
index 0000000..5b9be25
--- /dev/null
+++ b/botan/src/block/serpent/serpent.h
@@ -0,0 +1,35 @@
+/*
+* Serpent
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SERPENT_H__
+#define BOTAN_SERPENT_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Serpent
+*/
+class BOTAN_DLL Serpent : public BlockCipher
+ {
+ public:
+ void clear() throw() { round_key.clear(); }
+ std::string name() const { return "Serpent"; }
+ BlockCipher* clone() const { return new Serpent; }
+ Serpent() : BlockCipher(16, 16, 32, 8) {}
+ protected:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 132> round_key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/serpent_ia32/info.txt b/botan/src/block/serpent_ia32/info.txt
new file mode 100644
index 0000000..ea05062
--- /dev/null
+++ b/botan/src/block/serpent_ia32/info.txt
@@ -0,0 +1,35 @@
+realname "Serpent (IA-32)"
+
+define SERPENT_IA32
+
+load_on asm_ok
+
+<add>
+serp_ia32_imp.S
+serp_ia32.cpp
+serp_ia32.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_ia32
+serpent
+</requires>
diff --git a/botan/src/block/serpent_ia32/serp_ia32.cpp b/botan/src/block/serpent_ia32/serp_ia32.cpp
new file mode 100644
index 0000000..37dd4e6
--- /dev/null
+++ b/botan/src/block/serpent_ia32/serp_ia32.cpp
@@ -0,0 +1,51 @@
+/*
+* IA-32 Serpent
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/serp_ia32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+extern "C" {
+
+void botan_serpent_ia32_encrypt(const byte[16], byte[16], const u32bit[132]);
+void botan_serpent_ia32_decrypt(const byte[16], byte[16], const u32bit[132]);
+void botan_serpent_ia32_key_schedule(u32bit[140]);
+
+}
+
+/*
+* Serpent Encryption
+*/
+void Serpent_IA32::enc(const byte in[], byte out[]) const
+ {
+ botan_serpent_ia32_encrypt(in, out, round_key);
+ }
+
+/*
+* Serpent Decryption
+*/
+void Serpent_IA32::dec(const byte in[], byte out[]) const
+ {
+ botan_serpent_ia32_decrypt(in, out, round_key);
+ }
+
+/*
+* Serpent Key Schedule
+*/
+void Serpent_IA32::key_schedule(const byte key[], u32bit length)
+ {
+ SecureBuffer<u32bit, 140> W;
+ for(u32bit j = 0; j != length / 4; ++j)
+ W[j] = make_u32bit(key[4*j+3], key[4*j+2], key[4*j+1], key[4*j]);
+ W[length / 4] |= u32bit(1) << ((length%4)*8);
+
+ botan_serpent_ia32_key_schedule(W);
+ round_key.copy(W + 8, 132);
+ }
+
+}
diff --git a/botan/src/block/serpent_ia32/serp_ia32.h b/botan/src/block/serpent_ia32/serp_ia32.h
new file mode 100644
index 0000000..565e988
--- /dev/null
+++ b/botan/src/block/serpent_ia32/serp_ia32.h
@@ -0,0 +1,30 @@
+/*
+* Serpent (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SERPENT_IA32_H__
+#define BOTAN_SERPENT_IA32_H__
+
+#include <botan/serpent.h>
+
+namespace Botan {
+
+/*
+* Serpent
+*/
+class BOTAN_DLL Serpent_IA32 : public Serpent
+ {
+ public:
+ BlockCipher* clone() const { return new Serpent_IA32; }
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/serpent_ia32/serp_ia32_imp.S b/botan/src/block/serpent_ia32/serp_ia32_imp.S
new file mode 100644
index 0000000..9e50f8c
--- /dev/null
+++ b/botan/src/block/serpent_ia32/serp_ia32_imp.S
@@ -0,0 +1,669 @@
+/*
+* Serpent Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(serp_ia32.S)
+
+#define SBOX_E1(A, B, C, D, T) \
+ XOR(D, A) ; \
+ ASSIGN(T, B) ; \
+ AND(B, D) ; \
+ XOR(T, C) ; \
+ XOR(B, A) ; \
+ OR(A, D) ; \
+ XOR(A, T) ; \
+ XOR(T, D) ; \
+ XOR(D, C) ; \
+ OR(C, B) ; \
+ XOR(C, T) ; \
+ NOT(T) ; \
+ OR(T, B) ; \
+ XOR(B, D) ; \
+ XOR(B, T) ; \
+ OR(D, A) ; \
+ XOR(B, D) ; \
+ XOR(T, D) ; \
+ ASSIGN(D, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, T) ;
+
+#define SBOX_E2(A, B, C, D, T) \
+ NOT(A) ; \
+ NOT(C) ; \
+ ASSIGN(T, A) ; \
+ AND(A, B) ; \
+ XOR(C, A) ; \
+ OR(A, D) ; \
+ XOR(D, C) ; \
+ XOR(B, A) ; \
+ XOR(A, T) ; \
+ OR(T, B) ; \
+ XOR(B, D) ; \
+ OR(C, A) ; \
+ AND(C, T) ; \
+ XOR(A, B) ; \
+ AND(B, C) ; \
+ XOR(B, A) ; \
+ AND(A, C) ; \
+ XOR(T, A) ; \
+ ASSIGN(A, C) ; \
+ ASSIGN(C, D) ; \
+ ASSIGN(D, B) ; \
+ ASSIGN(B, T) ;
+
+#define SBOX_E3(A, B, C, D, T) \
+ ASSIGN(T, A) ; \
+ AND(A, C) ; \
+ XOR(A, D) ; \
+ XOR(C, B) ; \
+ XOR(C, A) ; \
+ OR(D, T) ; \
+ XOR(D, B) ; \
+ XOR(T, C) ; \
+ ASSIGN(B, D) ; \
+ OR(D, T) ; \
+ XOR(D, A) ; \
+ AND(A, B) ; \
+ XOR(T, A) ; \
+ XOR(B, D) ; \
+ XOR(B, T) ; \
+ NOT(T) ; \
+ ASSIGN(A, C) ; \
+ ASSIGN(C, B) ; \
+ ASSIGN(B, D) ; \
+ ASSIGN(D, T) ;
+
+#define SBOX_E4(A, B, C, D, T) \
+ ASSIGN(T, A) ; \
+ OR(A, D) ; \
+ XOR(D, B) ; \
+ AND(B, T) ; \
+ XOR(T, C) ; \
+ XOR(C, D) ; \
+ AND(D, A) ; \
+ OR(T, B) ; \
+ XOR(D, T) ; \
+ XOR(A, B) ; \
+ AND(T, A) ; \
+ XOR(B, D) ; \
+ XOR(T, C) ; \
+ OR(B, A) ; \
+ XOR(B, C) ; \
+ XOR(A, D) ; \
+ ASSIGN(C, B) ; \
+ OR(B, D) ; \
+ XOR(B, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, C) ; \
+ ASSIGN(C, D) ; \
+ ASSIGN(D, T) ;
+
+#define SBOX_E5(A, B, C, D, T) \
+ XOR(B, D) ; \
+ NOT(D) ; \
+ XOR(C, D) ; \
+ XOR(D, A) ; \
+ ASSIGN(T, B) ; \
+ AND(B, D) ; \
+ XOR(B, C) ; \
+ XOR(T, D) ; \
+ XOR(A, T) ; \
+ AND(C, T) ; \
+ XOR(C, A) ; \
+ AND(A, B) ; \
+ XOR(D, A) ; \
+ OR(T, B) ; \
+ XOR(T, A) ; \
+ OR(A, D) ; \
+ XOR(A, C) ; \
+ AND(C, D) ; \
+ NOT(A) ; \
+ XOR(T, C) ; \
+ ASSIGN(C, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, T) ;
+
+#define SBOX_E6(A, B, C, D, T) \
+ XOR(A, B) ; \
+ XOR(B, D) ; \
+ NOT(D) ; \
+ ASSIGN(T, B) ; \
+ AND(B, A) ; \
+ XOR(C, D) ; \
+ XOR(B, C) ; \
+ OR(C, T) ; \
+ XOR(T, D) ; \
+ AND(D, B) ; \
+ XOR(D, A) ; \
+ XOR(T, B) ; \
+ XOR(T, C) ; \
+ XOR(C, A) ; \
+ AND(A, D) ; \
+ NOT(C) ; \
+ XOR(A, T) ; \
+ OR(T, D) ; \
+ XOR(T, C) ; \
+ ASSIGN(C, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, D) ; \
+ ASSIGN(D, T) ;
+
+#define SBOX_E7(A, B, C, D, T) \
+ NOT(C) ; \
+ ASSIGN(T, D) ; \
+ AND(D, A) ; \
+ XOR(A, T) ; \
+ XOR(D, C) ; \
+ OR(C, T) ; \
+ XOR(B, D) ; \
+ XOR(C, A) ; \
+ OR(A, B) ; \
+ XOR(C, B) ; \
+ XOR(T, A) ; \
+ OR(A, D) ; \
+ XOR(A, C) ; \
+ XOR(T, D) ; \
+ XOR(T, A) ; \
+ NOT(D) ; \
+ AND(C, T) ; \
+ XOR(C, D) ; \
+ ASSIGN(D, C) ; \
+ ASSIGN(C, T) ;
+
+#define SBOX_E8(A, B, C, D, T) \
+ ASSIGN(T, B) ; \
+ OR(B, C) ; \
+ XOR(B, D) ; \
+ XOR(T, C) ; \
+ XOR(C, B) ; \
+ OR(D, T) ; \
+ AND(D, A) ; \
+ XOR(T, C) ; \
+ XOR(D, B) ; \
+ OR(B, T) ; \
+ XOR(B, A) ; \
+ OR(A, T) ; \
+ XOR(A, C) ; \
+ XOR(B, T) ; \
+ XOR(C, B) ; \
+ AND(B, A) ; \
+ XOR(B, T) ; \
+ NOT(C) ; \
+ OR(C, A) ; \
+ XOR(T, C) ; \
+ ASSIGN(C, B) ; \
+ ASSIGN(B, D) ; \
+ ASSIGN(D, A) ; \
+ ASSIGN(A, T) ;
+
+#define SBOX_D1(A, B, C, D, T) \
+ NOT(C) ; \
+ ASSIGN(T, B) ; \
+ OR(B, A) ; \
+ NOT(T) ; \
+ XOR(B, C) ; \
+ OR(C, T) ; \
+ XOR(B, D) ; \
+ XOR(A, T) ; \
+ XOR(C, A) ; \
+ AND(A, D) ; \
+ XOR(T, A) ; \
+ OR(A, B) ; \
+ XOR(A, C) ; \
+ XOR(D, T) ; \
+ XOR(C, B) ; \
+ XOR(D, A) ; \
+ XOR(D, B) ; \
+ AND(C, D) ; \
+ XOR(T, C) ; \
+ ASSIGN(C, B) ; \
+ ASSIGN(B, T) ;
+
+#define SBOX_D2(A, B, C, D, T) \
+ ASSIGN(T, B) ; \
+ XOR(B, D) ; \
+ AND(D, B) ; \
+ XOR(T, C) ; \
+ XOR(D, A) ; \
+ OR(A, B) ; \
+ XOR(C, D) ; \
+ XOR(A, T) ; \
+ OR(A, C) ; \
+ XOR(B, D) ; \
+ XOR(A, B) ; \
+ OR(B, D) ; \
+ XOR(B, A) ; \
+ NOT(T) ; \
+ XOR(T, B) ; \
+ OR(B, A) ; \
+ XOR(B, A) ; \
+ OR(B, T) ; \
+ XOR(D, B) ; \
+ ASSIGN(B, A) ; \
+ ASSIGN(A, T) ; \
+ ASSIGN(T, D) ; \
+ ASSIGN(D, C) ; \
+ ASSIGN(C, T) ;
+
+#define SBOX_D3(A, B, C, D, T) \
+ XOR(C, D) ; \
+ XOR(D, A) ; \
+ ASSIGN(T, D) ; \
+ AND(D, C) ; \
+ XOR(D, B) ; \
+ OR(B, C) ; \
+ XOR(B, T) ; \
+ AND(T, D) ; \
+ XOR(C, D) ; \
+ AND(T, A) ; \
+ XOR(T, C) ; \
+ AND(C, B) ; \
+ OR(C, A) ; \
+ NOT(D) ; \
+ XOR(C, D) ; \
+ XOR(A, D) ; \
+ AND(A, B) ; \
+ XOR(D, T) ; \
+ XOR(D, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, T) ;
+
+#define SBOX_D4(A, B, C, D, T) \
+ ASSIGN(T, C) ; \
+ XOR(C, B) ; \
+ XOR(A, C) ; \
+ AND(T, C) ; \
+ XOR(T, A) ; \
+ AND(A, B) ; \
+ XOR(B, D) ; \
+ OR(D, T) ; \
+ XOR(C, D) ; \
+ XOR(A, D) ; \
+ XOR(B, T) ; \
+ AND(D, C) ; \
+ XOR(D, B) ; \
+ XOR(B, A) ; \
+ OR(B, C) ; \
+ XOR(A, D) ; \
+ XOR(B, T) ; \
+ XOR(A, B) ; \
+ ASSIGN(T, A) ; \
+ ASSIGN(A, C) ; \
+ ASSIGN(C, D) ; \
+ ASSIGN(D, T) ;
+
+#define SBOX_D5(A, B, C, D, T) \
+ ASSIGN(T, C) ; \
+ AND(C, D) ; \
+ XOR(C, B) ; \
+ OR(B, D) ; \
+ AND(B, A) ; \
+ XOR(T, C) ; \
+ XOR(T, B) ; \
+ AND(B, C) ; \
+ NOT(A) ; \
+ XOR(D, T) ; \
+ XOR(B, D) ; \
+ AND(D, A) ; \
+ XOR(D, C) ; \
+ XOR(A, B) ; \
+ AND(C, A) ; \
+ XOR(D, A) ; \
+ XOR(C, T) ; \
+ OR(C, D) ; \
+ XOR(D, A) ; \
+ XOR(C, B) ; \
+ ASSIGN(B, D) ; \
+ ASSIGN(D, T) ;
+
+#define SBOX_D6(A, B, C, D, T) \
+ NOT(B) ; \
+ ASSIGN(T, D) ; \
+ XOR(C, B) ; \
+ OR(D, A) ; \
+ XOR(D, C) ; \
+ OR(C, B) ; \
+ AND(C, A) ; \
+ XOR(T, D) ; \
+ XOR(C, T) ; \
+ OR(T, A) ; \
+ XOR(T, B) ; \
+ AND(B, C) ; \
+ XOR(B, D) ; \
+ XOR(T, C) ; \
+ AND(D, T) ; \
+ XOR(T, B) ; \
+ XOR(D, T) ; \
+ NOT(T) ; \
+ XOR(D, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, T) ; \
+ ASSIGN(T, D) ; \
+ ASSIGN(D, C) ; \
+ ASSIGN(C, T) ;
+
+#define SBOX_D7(A, B, C, D, T) \
+ XOR(A, C) ; \
+ ASSIGN(T, C) ; \
+ AND(C, A) ; \
+ XOR(T, D) ; \
+ NOT(C) ; \
+ XOR(D, B) ; \
+ XOR(C, D) ; \
+ OR(T, A) ; \
+ XOR(A, C) ; \
+ XOR(D, T) ; \
+ XOR(T, B) ; \
+ AND(B, D) ; \
+ XOR(B, A) ; \
+ XOR(A, D) ; \
+ OR(A, C) ; \
+ XOR(D, B) ; \
+ XOR(T, A) ; \
+ ASSIGN(A, B) ; \
+ ASSIGN(B, C) ; \
+ ASSIGN(C, T) ;
+
+#define SBOX_D8(A, B, C, D, T) \
+ ASSIGN(T, C) ; \
+ XOR(C, A) ; \
+ AND(A, D) ; \
+ OR(T, D) ; \
+ NOT(C) ; \
+ XOR(D, B) ; \
+ OR(B, A) ; \
+ XOR(A, C) ; \
+ AND(C, T) ; \
+ AND(D, T) ; \
+ XOR(B, C) ; \
+ XOR(C, A) ; \
+ OR(A, C) ; \
+ XOR(T, B) ; \
+ XOR(A, D) ; \
+ XOR(D, T) ; \
+ OR(T, A) ; \
+ XOR(D, C) ; \
+ XOR(T, C) ; \
+ ASSIGN(C, B) ; \
+ ASSIGN(B, A) ; \
+ ASSIGN(A, D) ; \
+ ASSIGN(D, T) ;
+
+#define TRANSFORM(A, B, C, D, T) \
+ ROTL_IMM(A, 13) ; \
+ ROTL_IMM(C, 3) ; \
+ SHL2_3(T, A) ; \
+ XOR(B, A) ; \
+ XOR(D, C) ; \
+ XOR(B, C) ; \
+ XOR(D, T) ; \
+ ROTL_IMM(B, 1) ; \
+ ROTL_IMM(D, 7) ; \
+ ASSIGN(T, B) ; \
+ SHL_IMM(T, 7) ; \
+ XOR(A, B) ; \
+ XOR(C, D) ; \
+ XOR(A, D) ; \
+ XOR(C, T) ; \
+ ROTL_IMM(A, 5) ; \
+ ROTL_IMM(C, 22) ;
+
+#define I_TRANSFORM(A, B, C, D, T) \
+ ROTR_IMM(C, 22) ; \
+ ROTR_IMM(A, 5) ; \
+ ASSIGN(T, B) ; \
+ SHL_IMM(T, 7) ; \
+ XOR(A, B) ; \
+ XOR(C, D) ; \
+ XOR(A, D) ; \
+ XOR(C, T) ; \
+ ROTR_IMM(D, 7) ; \
+ ROTR_IMM(B, 1) ; \
+ SHL2_3(T, A) ; \
+ XOR(B, C) ; \
+ XOR(D, C) ; \
+ XOR(B, A) ; \
+ XOR(D, T) ; \
+ ROTR_IMM(C, 3) ; \
+ ROTR_IMM(A, 13) ;
+
+#define KEY_XOR(A, B, C, D, N) \
+ XOR(A, ARRAY4(EDI, (4*N ))) ; \
+ XOR(B, ARRAY4(EDI, (4*N+1))) ; \
+ XOR(C, ARRAY4(EDI, (4*N+2))) ; \
+ XOR(D, ARRAY4(EDI, (4*N+3))) ;
+
+/*
+* Serpent Encryption
+*/
+START_FUNCTION(botan_serpent_ia32_encrypt)
+ SPILL_REGS()
+#define PUSHED 4
+
+ ASSIGN(EBP, ARG(1)) /* input block */
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+ ASSIGN(EDI, ARG(3)) /* round keys */
+ ZEROIZE(EBP)
+
+#define E_ROUND(A, B, C, D, T, N, SBOX) \
+ KEY_XOR(A, B, C, D, N) \
+ SBOX(A, B, C, D, T) \
+ TRANSFORM(A, B, C, D, T)
+
+
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 0, SBOX_E1)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 1, SBOX_E2)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 2, SBOX_E3)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 3, SBOX_E4)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 4, SBOX_E5)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 5, SBOX_E6)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 6, SBOX_E7)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 7, SBOX_E8)
+
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 8, SBOX_E1)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 9, SBOX_E2)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 10, SBOX_E3)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 11, SBOX_E4)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 12, SBOX_E5)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 13, SBOX_E6)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 14, SBOX_E7)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 15, SBOX_E8)
+
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 16, SBOX_E1)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 17, SBOX_E2)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 18, SBOX_E3)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 19, SBOX_E4)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 20, SBOX_E5)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 21, SBOX_E6)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 22, SBOX_E7)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 23, SBOX_E8)
+
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 24, SBOX_E1)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 25, SBOX_E2)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 26, SBOX_E3)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 27, SBOX_E4)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 28, SBOX_E5)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 29, SBOX_E6)
+ E_ROUND(EAX, EBX, ECX, EDX, EBP, 30, SBOX_E7)
+
+ KEY_XOR(EAX, EBX, ECX, EDX, 31)
+ SBOX_E8(EAX, EBX, ECX, EDX, EBP)
+ KEY_XOR(EAX, EBX, ECX, EDX, 32)
+
+ ASSIGN(EBP, ARG(2)) /* output block */
+ ASSIGN(ARRAY4(EBP, 0), EAX)
+ ASSIGN(ARRAY4(EBP, 1), EBX)
+ ASSIGN(ARRAY4(EBP, 2), ECX)
+ ASSIGN(ARRAY4(EBP, 3), EDX)
+
+ RESTORE_REGS()
+#undef PUSHED
+END_FUNCTION(botan_serpent_ia32_encrypt)
+
+/*
+* Serpent Decryption
+*/
+START_FUNCTION(botan_serpent_ia32_decrypt)
+ SPILL_REGS()
+#define PUSHED 4
+
+ ASSIGN(EBP, ARG(1)) /* input block */
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+ ASSIGN(EDI, ARG(3)) /* round keys */
+
+ ZEROIZE(EBP)
+
+#define D_ROUND(A, B, C, D, T, N, SBOX) \
+ I_TRANSFORM(A, B, C, D, T) \
+ SBOX(A, B, C, D, T) \
+ KEY_XOR(A, B, C, D, N) \
+
+ KEY_XOR(EAX, EBX, ECX, EDX, 32)
+ SBOX_D8(EAX, EBX, ECX, EDX, EBP)
+ KEY_XOR(EAX, EBX, ECX, EDX, 31)
+
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 30, SBOX_D7)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 29, SBOX_D6)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 28, SBOX_D5)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 27, SBOX_D4)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 26, SBOX_D3)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 25, SBOX_D2)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 24, SBOX_D1)
+
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 23, SBOX_D8)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 22, SBOX_D7)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 21, SBOX_D6)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 20, SBOX_D5)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 19, SBOX_D4)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 18, SBOX_D3)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 17, SBOX_D2)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 16, SBOX_D1)
+
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 15, SBOX_D8)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 14, SBOX_D7)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 13, SBOX_D6)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 12, SBOX_D5)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 11, SBOX_D4)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 10, SBOX_D3)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 9, SBOX_D2)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 8, SBOX_D1)
+
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 7, SBOX_D8)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 6, SBOX_D7)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 5, SBOX_D6)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 4, SBOX_D5)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 3, SBOX_D4)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 2, SBOX_D3)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 1, SBOX_D2)
+ D_ROUND(EAX, EBX, ECX, EDX, EBP, 0, SBOX_D1)
+
+ ASSIGN(EBP, ARG(2)) /* output block */
+ ASSIGN(ARRAY4(EBP, 0), EAX)
+ ASSIGN(ARRAY4(EBP, 1), EBX)
+ ASSIGN(ARRAY4(EBP, 2), ECX)
+ ASSIGN(ARRAY4(EBP, 3), EDX)
+
+ RESTORE_REGS()
+#undef PUSHED
+END_FUNCTION(botan_serpent_ia32_decrypt)
+
+/*
+* Serpent Key Schedule
+*/
+START_FUNCTION(botan_serpent_ia32_key_schedule)
+ SPILL_REGS()
+#define PUSHED 4
+
+ ASSIGN(EDI, ARG(1)) /* round keys */
+ ASSIGN(ESI, IMM(8))
+ ADD_IMM(EDI, 32)
+
+START_LOOP(.EXPANSION)
+ ASSIGN(EAX, ARRAY4(EDI, -1))
+ ASSIGN(EBX, ARRAY4(EDI, -3))
+ ASSIGN(ECX, ARRAY4(EDI, -5))
+ ASSIGN(EDX, ARRAY4(EDI, -8))
+
+ ASSIGN(EBP, ESI)
+ SUB_IMM(EBP, 8)
+ XOR(EBP, IMM(0x9E3779B9))
+ XOR(EAX, EBX)
+ XOR(ECX, EDX)
+ XOR(EAX, EBP)
+ XOR(EAX, ECX)
+
+ ROTL_IMM(EAX, 11)
+
+ ASSIGN(ARRAY4(EDI, 0), EAX)
+
+ ADD_IMM(ESI, 1)
+ ADD_IMM(EDI, 4)
+LOOP_UNTIL_EQ(ESI, 140, .EXPANSION)
+
+ ASSIGN(EDI, ARG(1)) /* round keys */
+
+#define LOAD_AND_SBOX(MSG, SBOX) \
+ ASSIGN(EAX, ARRAY4(EDI, (4*MSG+ 8))) ; \
+ ASSIGN(EBX, ARRAY4(EDI, (4*MSG+ 9))) ; \
+ ASSIGN(ECX, ARRAY4(EDI, (4*MSG+10))) ; \
+ ASSIGN(EDX, ARRAY4(EDI, (4*MSG+11))) ; \
+ SBOX(EAX, EBX, ECX, EDX, EBP) ; \
+ ASSIGN(ARRAY4(EDI, (4*MSG+ 8)), EAX) ; \
+ ASSIGN(ARRAY4(EDI, (4*MSG+ 9)), EBX) ; \
+ ASSIGN(ARRAY4(EDI, (4*MSG+10)), ECX) ; \
+ ASSIGN(ARRAY4(EDI, (4*MSG+11)), EDX)
+
+ LOAD_AND_SBOX( 0, SBOX_E4)
+ LOAD_AND_SBOX( 1, SBOX_E3)
+ LOAD_AND_SBOX( 2, SBOX_E2)
+ LOAD_AND_SBOX( 3, SBOX_E1)
+
+ LOAD_AND_SBOX( 4, SBOX_E8)
+ LOAD_AND_SBOX( 5, SBOX_E7)
+ LOAD_AND_SBOX( 6, SBOX_E6)
+ LOAD_AND_SBOX( 7, SBOX_E5)
+ LOAD_AND_SBOX( 8, SBOX_E4)
+ LOAD_AND_SBOX( 9, SBOX_E3)
+ LOAD_AND_SBOX(10, SBOX_E2)
+ LOAD_AND_SBOX(11, SBOX_E1)
+
+ LOAD_AND_SBOX(12, SBOX_E8)
+ LOAD_AND_SBOX(13, SBOX_E7)
+ LOAD_AND_SBOX(14, SBOX_E6)
+ LOAD_AND_SBOX(15, SBOX_E5)
+ LOAD_AND_SBOX(16, SBOX_E4)
+ LOAD_AND_SBOX(17, SBOX_E3)
+ LOAD_AND_SBOX(18, SBOX_E2)
+ LOAD_AND_SBOX(19, SBOX_E1)
+
+ LOAD_AND_SBOX(20, SBOX_E8)
+ LOAD_AND_SBOX(21, SBOX_E7)
+ LOAD_AND_SBOX(22, SBOX_E6)
+ LOAD_AND_SBOX(23, SBOX_E5)
+ LOAD_AND_SBOX(24, SBOX_E4)
+ LOAD_AND_SBOX(25, SBOX_E3)
+ LOAD_AND_SBOX(26, SBOX_E2)
+ LOAD_AND_SBOX(27, SBOX_E1)
+
+ LOAD_AND_SBOX(28, SBOX_E8)
+ LOAD_AND_SBOX(29, SBOX_E7)
+ LOAD_AND_SBOX(30, SBOX_E6)
+ LOAD_AND_SBOX(31, SBOX_E5)
+ LOAD_AND_SBOX(32, SBOX_E4)
+
+ RESTORE_REGS()
+#undef PUSHED
+END_FUNCTION(botan_serpent_ia32_key_schedule)
diff --git a/botan/src/block/skipjack/info.txt b/botan/src/block/skipjack/info.txt
new file mode 100644
index 0000000..4b38d6d
--- /dev/null
+++ b/botan/src/block/skipjack/info.txt
@@ -0,0 +1,10 @@
+realname "Skipjack"
+
+define SKIPJACK
+
+load_on auto
+
+<add>
+skipjack.cpp
+skipjack.h
+</add>
diff --git a/botan/src/block/skipjack/skipjack.cpp b/botan/src/block/skipjack/skipjack.cpp
new file mode 100644
index 0000000..f5ffc86
--- /dev/null
+++ b/botan/src/block/skipjack/skipjack.cpp
@@ -0,0 +1,162 @@
+/*
+* Skipjack
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/skipjack.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Skipjack Encryption
+*/
+void Skipjack::enc(const byte in[], byte out[]) const
+ {
+ u16bit W1 = load_le<u16bit>(in, 3);
+ u16bit W2 = load_le<u16bit>(in, 2);
+ u16bit W3 = load_le<u16bit>(in, 1);
+ u16bit W4 = load_le<u16bit>(in, 0);
+
+ step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4);
+ step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8);
+
+ step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12);
+ step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16);
+
+ step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20);
+ step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24);
+
+ step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28);
+ step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32);
+
+ store_le(out, W4, W3, W2, W1);
+ }
+
+/*
+* Skipjack Decryption
+*/
+void Skipjack::dec(const byte in[], byte out[]) const
+ {
+ u16bit W1 = load_le<u16bit>(in, 3);
+ u16bit W2 = load_le<u16bit>(in, 2);
+ u16bit W3 = load_le<u16bit>(in, 1);
+ u16bit W4 = load_le<u16bit>(in, 0);
+
+ step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29);
+ step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25);
+
+ step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21);
+ step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17);
+
+ step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13);
+ step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9);
+
+ step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5);
+ step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1);
+
+ store_le(out, W4, W3, W2, W1);
+ }
+
+/*
+* Skipjack Stepping Rule 'A'
+*/
+void Skipjack::step_A(u16bit& W1, u16bit& W4, u32bit round) const
+ {
+ byte G1 = get_byte(0, W1), G2 = get_byte(1, W1), G3;
+ G3 = FTABLE[(4 * round - 4) % 10][G2] ^ G1;
+ G1 = FTABLE[(4 * round - 3) % 10][G3] ^ G2;
+ G2 = FTABLE[(4 * round - 2) % 10][G1] ^ G3;
+ G3 = FTABLE[(4 * round - 1) % 10][G2] ^ G1;
+ W1 = make_u16bit(G2, G3);
+ W4 ^= W1 ^ round;
+ }
+
+/*
+* Skipjack Stepping Rule 'B'
+*/
+void Skipjack::step_B(u16bit& W1, u16bit& W2, u32bit round) const
+ {
+ W2 ^= W1 ^ round;
+ byte G1 = get_byte(0, W1), G2 = get_byte(1, W1), G3;
+ G3 = FTABLE[(4 * round - 4) % 10][G2] ^ G1;
+ G1 = FTABLE[(4 * round - 3) % 10][G3] ^ G2;
+ G2 = FTABLE[(4 * round - 2) % 10][G1] ^ G3;
+ G3 = FTABLE[(4 * round - 1) % 10][G2] ^ G1;
+ W1 = make_u16bit(G2, G3);
+ }
+
+/*
+* Skipjack Invserse Stepping Rule 'A'
+*/
+void Skipjack::step_Ai(u16bit& W1, u16bit& W2, u32bit round) const
+ {
+ W1 ^= W2 ^ round;
+ byte G1 = get_byte(1, W2), G2 = get_byte(0, W2), G3;
+ G3 = FTABLE[(4 * round - 1) % 10][G2] ^ G1;
+ G1 = FTABLE[(4 * round - 2) % 10][G3] ^ G2;
+ G2 = FTABLE[(4 * round - 3) % 10][G1] ^ G3;
+ G3 = FTABLE[(4 * round - 4) % 10][G2] ^ G1;
+ W2 = make_u16bit(G3, G2);
+ }
+
+/*
+* Skipjack Invserse Stepping Rule 'B'
+*/
+void Skipjack::step_Bi(u16bit& W2, u16bit& W3, u32bit round) const
+ {
+ byte G1 = get_byte(1, W2), G2 = get_byte(0, W2), G3;
+ G3 = FTABLE[(4 * round - 1) % 10][G2] ^ G1;
+ G1 = FTABLE[(4 * round - 2) % 10][G3] ^ G2;
+ G2 = FTABLE[(4 * round - 3) % 10][G1] ^ G3;
+ G3 = FTABLE[(4 * round - 4) % 10][G2] ^ G1;
+ W2 = make_u16bit(G3, G2);
+ W3 ^= W2 ^ round;
+ }
+
+/*
+* Skipjack Key Schedule
+*/
+void Skipjack::key_schedule(const byte key[], u32bit)
+ {
+ static const byte F[256] = {
+ 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 };
+
+ for(u32bit j = 0; j != 10; ++j)
+ for(u32bit k = 0; k != 256; ++k)
+ FTABLE[j][k] = F[k ^ key[9-j]];
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Skipjack::clear() throw()
+ {
+ for(u32bit j = 0; j != 10; ++j)
+ FTABLE[j].clear();
+ }
+
+}
diff --git a/botan/src/block/skipjack/skipjack.h b/botan/src/block/skipjack/skipjack.h
new file mode 100644
index 0000000..231cd9c
--- /dev/null
+++ b/botan/src/block/skipjack/skipjack.h
@@ -0,0 +1,38 @@
+/*
+* Skipjack
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SKIPJACK_H__
+#define BOTAN_SKIPJACK_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Skipjack
+*/
+class BOTAN_DLL Skipjack : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Skipjack"; }
+ BlockCipher* clone() const { return new Skipjack; }
+ Skipjack() : BlockCipher(8, 10) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ void step_A(u16bit&, u16bit&, u32bit) const;
+ void step_B(u16bit&, u16bit&, u32bit) const;
+ void step_Ai(u16bit&, u16bit&, u32bit) const;
+ void step_Bi(u16bit&, u16bit&, u32bit) const;
+ SecureBuffer<byte, 256> FTABLE[10];
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/square/info.txt b/botan/src/block/square/info.txt
new file mode 100644
index 0000000..a206979
--- /dev/null
+++ b/botan/src/block/square/info.txt
@@ -0,0 +1,11 @@
+realname "Square"
+
+define SQUARE
+
+load_on auto
+
+<add>
+sqr_tab.cpp
+square.cpp
+square.h
+</add>
diff --git a/botan/src/block/square/sqr_tab.cpp b/botan/src/block/square/sqr_tab.cpp
new file mode 100644
index 0000000..331bf3e
--- /dev/null
+++ b/botan/src/block/square/sqr_tab.cpp
@@ -0,0 +1,460 @@
+/*
+* S-Box and Diffusion Tables for Square
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/square.h>
+
+namespace Botan {
+
+const byte Square::SE[256] = {
+0xB1, 0xCE, 0xC3, 0x95, 0x5A, 0xAD, 0xE7, 0x02, 0x4D, 0x44, 0xFB, 0x91, 0x0C,
+0x87, 0xA1, 0x50, 0xCB, 0x67, 0x54, 0xDD, 0x46, 0x8F, 0xE1, 0x4E, 0xF0, 0xFD,
+0xFC, 0xEB, 0xF9, 0xC4, 0x1A, 0x6E, 0x5E, 0xF5, 0xCC, 0x8D, 0x1C, 0x56, 0x43,
+0xFE, 0x07, 0x61, 0xF8, 0x75, 0x59, 0xFF, 0x03, 0x22, 0x8A, 0xD1, 0x13, 0xEE,
+0x88, 0x00, 0x0E, 0x34, 0x15, 0x80, 0x94, 0xE3, 0xED, 0xB5, 0x53, 0x23, 0x4B,
+0x47, 0x17, 0xA7, 0x90, 0x35, 0xAB, 0xD8, 0xB8, 0xDF, 0x4F, 0x57, 0x9A, 0x92,
+0xDB, 0x1B, 0x3C, 0xC8, 0x99, 0x04, 0x8E, 0xE0, 0xD7, 0x7D, 0x85, 0xBB, 0x40,
+0x2C, 0x3A, 0x45, 0xF1, 0x42, 0x65, 0x20, 0x41, 0x18, 0x72, 0x25, 0x93, 0x70,
+0x36, 0x05, 0xF2, 0x0B, 0xA3, 0x79, 0xEC, 0x08, 0x27, 0x31, 0x32, 0xB6, 0x7C,
+0xB0, 0x0A, 0x73, 0x5B, 0x7B, 0xB7, 0x81, 0xD2, 0x0D, 0x6A, 0x26, 0x9E, 0x58,
+0x9C, 0x83, 0x74, 0xB3, 0xAC, 0x30, 0x7A, 0x69, 0x77, 0x0F, 0xAE, 0x21, 0xDE,
+0xD0, 0x2E, 0x97, 0x10, 0xA4, 0x98, 0xA8, 0xD4, 0x68, 0x2D, 0x62, 0x29, 0x6D,
+0x16, 0x49, 0x76, 0xC7, 0xE8, 0xC1, 0x96, 0x37, 0xE5, 0xCA, 0xF4, 0xE9, 0x63,
+0x12, 0xC2, 0xA6, 0x14, 0xBC, 0xD3, 0x28, 0xAF, 0x2F, 0xE6, 0x24, 0x52, 0xC6,
+0xA0, 0x09, 0xBD, 0x8C, 0xCF, 0x5D, 0x11, 0x5F, 0x01, 0xC5, 0x9F, 0x3D, 0xA2,
+0x9B, 0xC9, 0x3B, 0xBE, 0x51, 0x19, 0x1F, 0x3F, 0x5C, 0xB2, 0xEF, 0x4A, 0xCD,
+0xBF, 0xBA, 0x6F, 0x64, 0xD9, 0xF3, 0x3E, 0xB4, 0xAA, 0xDC, 0xD5, 0x06, 0xC0,
+0x7E, 0xF6, 0x66, 0x6C, 0x84, 0x71, 0x38, 0xB9, 0x1D, 0x7F, 0x9D, 0x48, 0x8B,
+0x2A, 0xDA, 0xA5, 0x33, 0x82, 0x39, 0xD6, 0x78, 0x86, 0xFA, 0xE4, 0x2B, 0xA9,
+0x1E, 0x89, 0x60, 0x6B, 0xEA, 0x55, 0x4C, 0xF7, 0xE2 };
+
+const byte Square::SD[256] = {
+0x35, 0xBE, 0x07, 0x2E, 0x53, 0x69, 0xDB, 0x28, 0x6F, 0xB7, 0x76, 0x6B, 0x0C,
+0x7D, 0x36, 0x8B, 0x92, 0xBC, 0xA9, 0x32, 0xAC, 0x38, 0x9C, 0x42, 0x63, 0xC8,
+0x1E, 0x4F, 0x24, 0xE5, 0xF7, 0xC9, 0x61, 0x8D, 0x2F, 0x3F, 0xB3, 0x65, 0x7F,
+0x70, 0xAF, 0x9A, 0xEA, 0xF5, 0x5B, 0x98, 0x90, 0xB1, 0x87, 0x71, 0x72, 0xED,
+0x37, 0x45, 0x68, 0xA3, 0xE3, 0xEF, 0x5C, 0xC5, 0x50, 0xC1, 0xD6, 0xCA, 0x5A,
+0x62, 0x5F, 0x26, 0x09, 0x5D, 0x14, 0x41, 0xE8, 0x9D, 0xCE, 0x40, 0xFD, 0x08,
+0x17, 0x4A, 0x0F, 0xC7, 0xB4, 0x3E, 0x12, 0xFC, 0x25, 0x4B, 0x81, 0x2C, 0x04,
+0x78, 0xCB, 0xBB, 0x20, 0xBD, 0xF9, 0x29, 0x99, 0xA8, 0xD3, 0x60, 0xDF, 0x11,
+0x97, 0x89, 0x7E, 0xFA, 0xE0, 0x9B, 0x1F, 0xD2, 0x67, 0xE2, 0x64, 0x77, 0x84,
+0x2B, 0x9E, 0x8A, 0xF1, 0x6D, 0x88, 0x79, 0x74, 0x57, 0xDD, 0xE6, 0x39, 0x7B,
+0xEE, 0x83, 0xE1, 0x58, 0xF2, 0x0D, 0x34, 0xF8, 0x30, 0xE9, 0xB9, 0x23, 0x54,
+0x15, 0x44, 0x0B, 0x4D, 0x66, 0x3A, 0x03, 0xA2, 0x91, 0x94, 0x52, 0x4C, 0xC3,
+0x82, 0xE7, 0x80, 0xC0, 0xB6, 0x0E, 0xC2, 0x6C, 0x93, 0xEC, 0xAB, 0x43, 0x95,
+0xF6, 0xD8, 0x46, 0x86, 0x05, 0x8C, 0xB0, 0x75, 0x00, 0xCC, 0x85, 0xD7, 0x3D,
+0x73, 0x7A, 0x48, 0xE4, 0xD1, 0x59, 0xAD, 0xB8, 0xC6, 0xD0, 0xDC, 0xA1, 0xAA,
+0x02, 0x1D, 0xBF, 0xB5, 0x9F, 0x51, 0xC4, 0xA5, 0x10, 0x22, 0xCF, 0x01, 0xBA,
+0x8F, 0x31, 0x7C, 0xAE, 0x96, 0xDA, 0xF0, 0x56, 0x47, 0xD4, 0xEB, 0x4E, 0xD9,
+0x13, 0x8E, 0x49, 0x55, 0x16, 0xFF, 0x3B, 0xF4, 0xA4, 0xB2, 0x06, 0xA0, 0xA7,
+0xFB, 0x1B, 0x6E, 0x3C, 0x33, 0xCD, 0x18, 0x5E, 0x6A, 0xD5, 0xA6, 0x21, 0xDE,
+0xFE, 0x2A, 0x1C, 0xF3, 0x0A, 0x1A, 0x19, 0x27, 0x2D };
+
+const byte Square::Log[256] = {
+0x00, 0x00, 0x01, 0x86, 0x02, 0x0D, 0x87, 0x4C, 0x03, 0xD2, 0x0E, 0xAE, 0x88,
+0x22, 0x4D, 0x93, 0x04, 0x1A, 0xD3, 0xCB, 0x0F, 0x98, 0xAF, 0xA8, 0x89, 0xF0,
+0x23, 0x59, 0x4E, 0x35, 0x94, 0x09, 0x05, 0x8F, 0x1B, 0x6E, 0xD4, 0x39, 0xCC,
+0xBB, 0x10, 0x68, 0x99, 0x77, 0xB0, 0xDF, 0xA9, 0x72, 0x8A, 0xFA, 0xF1, 0xA0,
+0x24, 0x52, 0x5A, 0x60, 0x4F, 0x2F, 0x36, 0xDC, 0x95, 0x32, 0x0A, 0x1F, 0x06,
+0xA5, 0x90, 0x49, 0x1C, 0x5D, 0x6F, 0xB8, 0xD5, 0xC1, 0x3A, 0xB5, 0xCD, 0x63,
+0xBC, 0x3D, 0x11, 0x44, 0x69, 0x81, 0x9A, 0x27, 0x78, 0xC4, 0xB1, 0xE6, 0xE0,
+0xEA, 0xAA, 0x55, 0x73, 0xD8, 0x8B, 0xF6, 0xFB, 0x16, 0xF2, 0xF4, 0xA1, 0x40,
+0x25, 0x42, 0x53, 0xE4, 0x5B, 0xA3, 0x61, 0xBF, 0x50, 0xF8, 0x30, 0x2D, 0x37,
+0x8D, 0xDD, 0x66, 0x96, 0x18, 0x33, 0xEE, 0x0B, 0xFD, 0x20, 0xD0, 0x07, 0x57,
+0xA6, 0xC9, 0x91, 0xAC, 0x4A, 0x84, 0x1D, 0xDA, 0x5E, 0x9E, 0x70, 0x75, 0xB9,
+0x6C, 0xD6, 0xE8, 0xC2, 0x7F, 0x3B, 0xB3, 0xB6, 0x47, 0xCE, 0xEC, 0x64, 0x2B,
+0xBD, 0xE2, 0x3E, 0x14, 0x12, 0x29, 0x45, 0x7D, 0x6A, 0x9C, 0x82, 0xC7, 0x9B,
+0xC6, 0x28, 0x7C, 0x79, 0x7A, 0xC5, 0x7B, 0xB2, 0x46, 0xE7, 0x7E, 0xE1, 0x13,
+0xEB, 0x2A, 0xAB, 0x83, 0x56, 0xC8, 0x74, 0x6B, 0xD9, 0x9D, 0x8C, 0x65, 0xF7,
+0x2C, 0xFC, 0xCF, 0x17, 0xED, 0xF3, 0x3F, 0xF5, 0x15, 0xA2, 0xBE, 0x41, 0xE3,
+0x26, 0xC3, 0x43, 0x80, 0x54, 0xD7, 0xE5, 0xE9, 0x5C, 0xB7, 0xA4, 0x48, 0x62,
+0x3C, 0xC0, 0xB4, 0x51, 0x5F, 0xF9, 0x9F, 0x31, 0x1E, 0x2E, 0xDB, 0x38, 0xBA,
+0x8E, 0x6D, 0xDE, 0x71, 0x67, 0x76, 0x97, 0xA7, 0x19, 0xCA, 0x34, 0x08, 0xEF,
+0x58, 0x0C, 0x4B, 0xFE, 0x85, 0x21, 0x92, 0xD1, 0xAD };
+
+const byte Square::ALog[255] = {
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF5, 0x1F, 0x3E, 0x7C, 0xF8,
+0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0xB5, 0x9F, 0xCB, 0x63, 0xC6, 0x79, 0xF2,
+0x11, 0x22, 0x44, 0x88, 0xE5, 0x3F, 0x7E, 0xFC, 0x0D, 0x1A, 0x34, 0x68, 0xD0,
+0x55, 0xAA, 0xA1, 0xB7, 0x9B, 0xC3, 0x73, 0xE6, 0x39, 0x72, 0xE4, 0x3D, 0x7A,
+0xF4, 0x1D, 0x3A, 0x74, 0xE8, 0x25, 0x4A, 0x94, 0xDD, 0x4F, 0x9E, 0xC9, 0x67,
+0xCE, 0x69, 0xD2, 0x51, 0xA2, 0xB1, 0x97, 0xDB, 0x43, 0x86, 0xF9, 0x07, 0x0E,
+0x1C, 0x38, 0x70, 0xE0, 0x35, 0x6A, 0xD4, 0x5D, 0xBA, 0x81, 0xF7, 0x1B, 0x36,
+0x6C, 0xD8, 0x45, 0x8A, 0xE1, 0x37, 0x6E, 0xDC, 0x4D, 0x9A, 0xC1, 0x77, 0xEE,
+0x29, 0x52, 0xA4, 0xBD, 0x8F, 0xEB, 0x23, 0x46, 0x8C, 0xED, 0x2F, 0x5E, 0xBC,
+0x8D, 0xEF, 0x2B, 0x56, 0xAC, 0xAD, 0xAF, 0xAB, 0xA3, 0xB3, 0x93, 0xD3, 0x53,
+0xA6, 0xB9, 0x87, 0xFB, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x75, 0xEA,
+0x21, 0x42, 0x84, 0xFD, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0x15, 0x2A, 0x54, 0xA8,
+0xA5, 0xBF, 0x8B, 0xE3, 0x33, 0x66, 0xCC, 0x6D, 0xDA, 0x41, 0x82, 0xF1, 0x17,
+0x2E, 0x5C, 0xB8, 0x85, 0xFF, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x95, 0xDF, 0x4B,
+0x96, 0xD9, 0x47, 0x8E, 0xE9, 0x27, 0x4E, 0x9C, 0xCD, 0x6F, 0xDE, 0x49, 0x92,
+0xD1, 0x57, 0xAE, 0xA9, 0xA7, 0xBB, 0x83, 0xF3, 0x13, 0x26, 0x4C, 0x98, 0xC5,
+0x7F, 0xFE, 0x09, 0x12, 0x24, 0x48, 0x90, 0xD5, 0x5F, 0xBE, 0x89, 0xE7, 0x3B,
+0x76, 0xEC, 0x2D, 0x5A, 0xB4, 0x9D, 0xCF, 0x6B, 0xD6, 0x59, 0xB2, 0x91, 0xD7,
+0x5B, 0xB6, 0x99, 0xC7, 0x7B, 0xF6, 0x19, 0x32, 0x64, 0xC8, 0x65, 0xCA, 0x61,
+0xC2, 0x71, 0xE2, 0x31, 0x62, 0xC4, 0x7D, 0xFA };
+
+const u32bit Square::TE0[256] = {
+0x97B1B126, 0x69CECEA7, 0x73C3C3B0, 0xDF95954A, 0xB45A5AEE, 0xAFADAD02,
+0x3BE7E7DC, 0x04020206, 0x9A4D4DD7, 0x884444CC, 0x03FBFBF8, 0xD7919146,
+0x180C0C14, 0xFB87877C, 0xB7A1A116, 0xA05050F0, 0x63CBCBA8, 0xCE6767A9,
+0xA85454FC, 0x4FDDDD92, 0x8C4646CA, 0xEB8F8F64, 0x37E1E1D6, 0x9C4E4ED2,
+0x15F0F0E5, 0x0FFDFDF2, 0x0DFCFCF1, 0x23EBEBC8, 0x07F9F9FE, 0x7DC4C4B9,
+0x341A1A2E, 0xDC6E6EB2, 0xBC5E5EE2, 0x1FF5F5EA, 0x6DCCCCA1, 0xEF8D8D62,
+0x381C1C24, 0xAC5656FA, 0x864343C5, 0x09FEFEF7, 0x0E070709, 0xC26161A3,
+0x05F8F8FD, 0xEA75759F, 0xB25959EB, 0x0BFFFFF4, 0x06030305, 0x44222266,
+0xE18A8A6B, 0x57D1D186, 0x26131335, 0x29EEEEC7, 0xE588886D, 0x00000000,
+0x1C0E0E12, 0x6834345C, 0x2A15153F, 0xF5808075, 0xDD949449, 0x33E3E3D0,
+0x2FEDEDC2, 0x9FB5B52A, 0xA65353F5, 0x46232365, 0x964B4BDD, 0x8E4747C9,
+0x2E171739, 0xBBA7A71C, 0xD5909045, 0x6A35355F, 0xA3ABAB08, 0x45D8D89D,
+0x85B8B83D, 0x4BDFDF94, 0x9E4F4FD1, 0xAE5757F9, 0xC19A9A5B, 0xD1929243,
+0x43DBDB98, 0x361B1B2D, 0x783C3C44, 0x65C8C8AD, 0xC799995E, 0x0804040C,
+0xE98E8E67, 0x35E0E0D5, 0x5BD7D78C, 0xFA7D7D87, 0xFF85857A, 0x83BBBB38,
+0x804040C0, 0x582C2C74, 0x743A3A4E, 0x8A4545CF, 0x17F1F1E6, 0x844242C6,
+0xCA6565AF, 0x40202060, 0x824141C3, 0x30181828, 0xE4727296, 0x4A25256F,
+0xD3939340, 0xE0707090, 0x6C36365A, 0x0A05050F, 0x11F2F2E3, 0x160B0B1D,
+0xB3A3A310, 0xF279798B, 0x2DECECC1, 0x10080818, 0x4E272769, 0x62313153,
+0x64323256, 0x99B6B62F, 0xF87C7C84, 0x95B0B025, 0x140A0A1E, 0xE6737395,
+0xB65B5BED, 0xF67B7B8D, 0x9BB7B72C, 0xF7818176, 0x51D2D283, 0x1A0D0D17,
+0xD46A6ABE, 0x4C26266A, 0xC99E9E57, 0xB05858E8, 0xCD9C9C51, 0xF3838370,
+0xE874749C, 0x93B3B320, 0xADACAC01, 0x60303050, 0xF47A7A8E, 0xD26969BB,
+0xEE777799, 0x1E0F0F11, 0xA9AEAE07, 0x42212163, 0x49DEDE97, 0x55D0D085,
+0x5C2E2E72, 0xDB97974C, 0x20101030, 0xBDA4A419, 0xC598985D, 0xA5A8A80D,
+0x5DD4D489, 0xD06868B8, 0x5A2D2D77, 0xC46262A6, 0x5229297B, 0xDA6D6DB7,
+0x2C16163A, 0x924949DB, 0xEC76769A, 0x7BC7C7BC, 0x25E8E8CD, 0x77C1C1B6,
+0xD996964F, 0x6E373759, 0x3FE5E5DA, 0x61CACAAB, 0x1DF4F4E9, 0x27E9E9CE,
+0xC66363A5, 0x24121236, 0x71C2C2B3, 0xB9A6A61F, 0x2814143C, 0x8DBCBC31,
+0x53D3D380, 0x50282878, 0xABAFAF04, 0x5E2F2F71, 0x39E6E6DF, 0x4824246C,
+0xA45252F6, 0x79C6C6BF, 0xB5A0A015, 0x1209091B, 0x8FBDBD32, 0xED8C8C61,
+0x6BCFCFA4, 0xBA5D5DE7, 0x22111133, 0xBE5F5FE1, 0x02010103, 0x7FC5C5BA,
+0xCB9F9F54, 0x7A3D3D47, 0xB1A2A213, 0xC39B9B58, 0x67C9C9AE, 0x763B3B4D,
+0x89BEBE37, 0xA25151F3, 0x3219192B, 0x3E1F1F21, 0x7E3F3F41, 0xB85C5CE4,
+0x91B2B223, 0x2BEFEFC4, 0x944A4ADE, 0x6FCDCDA2, 0x8BBFBF34, 0x81BABA3B,
+0xDE6F6FB1, 0xC86464AC, 0x47D9D99E, 0x13F3F3E0, 0x7C3E3E42, 0x9DB4B429,
+0xA1AAAA0B, 0x4DDCDC91, 0x5FD5D58A, 0x0C06060A, 0x75C0C0B5, 0xFC7E7E82,
+0x19F6F6EF, 0xCC6666AA, 0xD86C6CB4, 0xFD848479, 0xE2717193, 0x70383848,
+0x87B9B93E, 0x3A1D1D27, 0xFE7F7F81, 0xCF9D9D52, 0x904848D8, 0xE38B8B68,
+0x542A2A7E, 0x41DADA9B, 0xBFA5A51A, 0x66333355, 0xF1828273, 0x7239394B,
+0x59D6D68F, 0xF0787888, 0xF986867F, 0x01FAFAFB, 0x3DE4E4D9, 0x562B2B7D,
+0xA7A9A90E, 0x3C1E1E22, 0xE789896E, 0xC06060A0, 0xD66B6BBD, 0x21EAEACB,
+0xAA5555FF, 0x984C4CD4, 0x1BF7F7EC, 0x31E2E2D3 };
+
+const u32bit Square::TE1[256] = {
+0x2697B1B1, 0xA769CECE, 0xB073C3C3, 0x4ADF9595, 0xEEB45A5A, 0x02AFADAD,
+0xDC3BE7E7, 0x06040202, 0xD79A4D4D, 0xCC884444, 0xF803FBFB, 0x46D79191,
+0x14180C0C, 0x7CFB8787, 0x16B7A1A1, 0xF0A05050, 0xA863CBCB, 0xA9CE6767,
+0xFCA85454, 0x924FDDDD, 0xCA8C4646, 0x64EB8F8F, 0xD637E1E1, 0xD29C4E4E,
+0xE515F0F0, 0xF20FFDFD, 0xF10DFCFC, 0xC823EBEB, 0xFE07F9F9, 0xB97DC4C4,
+0x2E341A1A, 0xB2DC6E6E, 0xE2BC5E5E, 0xEA1FF5F5, 0xA16DCCCC, 0x62EF8D8D,
+0x24381C1C, 0xFAAC5656, 0xC5864343, 0xF709FEFE, 0x090E0707, 0xA3C26161,
+0xFD05F8F8, 0x9FEA7575, 0xEBB25959, 0xF40BFFFF, 0x05060303, 0x66442222,
+0x6BE18A8A, 0x8657D1D1, 0x35261313, 0xC729EEEE, 0x6DE58888, 0x00000000,
+0x121C0E0E, 0x5C683434, 0x3F2A1515, 0x75F58080, 0x49DD9494, 0xD033E3E3,
+0xC22FEDED, 0x2A9FB5B5, 0xF5A65353, 0x65462323, 0xDD964B4B, 0xC98E4747,
+0x392E1717, 0x1CBBA7A7, 0x45D59090, 0x5F6A3535, 0x08A3ABAB, 0x9D45D8D8,
+0x3D85B8B8, 0x944BDFDF, 0xD19E4F4F, 0xF9AE5757, 0x5BC19A9A, 0x43D19292,
+0x9843DBDB, 0x2D361B1B, 0x44783C3C, 0xAD65C8C8, 0x5EC79999, 0x0C080404,
+0x67E98E8E, 0xD535E0E0, 0x8C5BD7D7, 0x87FA7D7D, 0x7AFF8585, 0x3883BBBB,
+0xC0804040, 0x74582C2C, 0x4E743A3A, 0xCF8A4545, 0xE617F1F1, 0xC6844242,
+0xAFCA6565, 0x60402020, 0xC3824141, 0x28301818, 0x96E47272, 0x6F4A2525,
+0x40D39393, 0x90E07070, 0x5A6C3636, 0x0F0A0505, 0xE311F2F2, 0x1D160B0B,
+0x10B3A3A3, 0x8BF27979, 0xC12DECEC, 0x18100808, 0x694E2727, 0x53623131,
+0x56643232, 0x2F99B6B6, 0x84F87C7C, 0x2595B0B0, 0x1E140A0A, 0x95E67373,
+0xEDB65B5B, 0x8DF67B7B, 0x2C9BB7B7, 0x76F78181, 0x8351D2D2, 0x171A0D0D,
+0xBED46A6A, 0x6A4C2626, 0x57C99E9E, 0xE8B05858, 0x51CD9C9C, 0x70F38383,
+0x9CE87474, 0x2093B3B3, 0x01ADACAC, 0x50603030, 0x8EF47A7A, 0xBBD26969,
+0x99EE7777, 0x111E0F0F, 0x07A9AEAE, 0x63422121, 0x9749DEDE, 0x8555D0D0,
+0x725C2E2E, 0x4CDB9797, 0x30201010, 0x19BDA4A4, 0x5DC59898, 0x0DA5A8A8,
+0x895DD4D4, 0xB8D06868, 0x775A2D2D, 0xA6C46262, 0x7B522929, 0xB7DA6D6D,
+0x3A2C1616, 0xDB924949, 0x9AEC7676, 0xBC7BC7C7, 0xCD25E8E8, 0xB677C1C1,
+0x4FD99696, 0x596E3737, 0xDA3FE5E5, 0xAB61CACA, 0xE91DF4F4, 0xCE27E9E9,
+0xA5C66363, 0x36241212, 0xB371C2C2, 0x1FB9A6A6, 0x3C281414, 0x318DBCBC,
+0x8053D3D3, 0x78502828, 0x04ABAFAF, 0x715E2F2F, 0xDF39E6E6, 0x6C482424,
+0xF6A45252, 0xBF79C6C6, 0x15B5A0A0, 0x1B120909, 0x328FBDBD, 0x61ED8C8C,
+0xA46BCFCF, 0xE7BA5D5D, 0x33221111, 0xE1BE5F5F, 0x03020101, 0xBA7FC5C5,
+0x54CB9F9F, 0x477A3D3D, 0x13B1A2A2, 0x58C39B9B, 0xAE67C9C9, 0x4D763B3B,
+0x3789BEBE, 0xF3A25151, 0x2B321919, 0x213E1F1F, 0x417E3F3F, 0xE4B85C5C,
+0x2391B2B2, 0xC42BEFEF, 0xDE944A4A, 0xA26FCDCD, 0x348BBFBF, 0x3B81BABA,
+0xB1DE6F6F, 0xACC86464, 0x9E47D9D9, 0xE013F3F3, 0x427C3E3E, 0x299DB4B4,
+0x0BA1AAAA, 0x914DDCDC, 0x8A5FD5D5, 0x0A0C0606, 0xB575C0C0, 0x82FC7E7E,
+0xEF19F6F6, 0xAACC6666, 0xB4D86C6C, 0x79FD8484, 0x93E27171, 0x48703838,
+0x3E87B9B9, 0x273A1D1D, 0x81FE7F7F, 0x52CF9D9D, 0xD8904848, 0x68E38B8B,
+0x7E542A2A, 0x9B41DADA, 0x1ABFA5A5, 0x55663333, 0x73F18282, 0x4B723939,
+0x8F59D6D6, 0x88F07878, 0x7FF98686, 0xFB01FAFA, 0xD93DE4E4, 0x7D562B2B,
+0x0EA7A9A9, 0x223C1E1E, 0x6EE78989, 0xA0C06060, 0xBDD66B6B, 0xCB21EAEA,
+0xFFAA5555, 0xD4984C4C, 0xEC1BF7F7, 0xD331E2E2 };
+
+const u32bit Square::TE2[256] = {
+0xB12697B1, 0xCEA769CE, 0xC3B073C3, 0x954ADF95, 0x5AEEB45A, 0xAD02AFAD,
+0xE7DC3BE7, 0x02060402, 0x4DD79A4D, 0x44CC8844, 0xFBF803FB, 0x9146D791,
+0x0C14180C, 0x877CFB87, 0xA116B7A1, 0x50F0A050, 0xCBA863CB, 0x67A9CE67,
+0x54FCA854, 0xDD924FDD, 0x46CA8C46, 0x8F64EB8F, 0xE1D637E1, 0x4ED29C4E,
+0xF0E515F0, 0xFDF20FFD, 0xFCF10DFC, 0xEBC823EB, 0xF9FE07F9, 0xC4B97DC4,
+0x1A2E341A, 0x6EB2DC6E, 0x5EE2BC5E, 0xF5EA1FF5, 0xCCA16DCC, 0x8D62EF8D,
+0x1C24381C, 0x56FAAC56, 0x43C58643, 0xFEF709FE, 0x07090E07, 0x61A3C261,
+0xF8FD05F8, 0x759FEA75, 0x59EBB259, 0xFFF40BFF, 0x03050603, 0x22664422,
+0x8A6BE18A, 0xD18657D1, 0x13352613, 0xEEC729EE, 0x886DE588, 0x00000000,
+0x0E121C0E, 0x345C6834, 0x153F2A15, 0x8075F580, 0x9449DD94, 0xE3D033E3,
+0xEDC22FED, 0xB52A9FB5, 0x53F5A653, 0x23654623, 0x4BDD964B, 0x47C98E47,
+0x17392E17, 0xA71CBBA7, 0x9045D590, 0x355F6A35, 0xAB08A3AB, 0xD89D45D8,
+0xB83D85B8, 0xDF944BDF, 0x4FD19E4F, 0x57F9AE57, 0x9A5BC19A, 0x9243D192,
+0xDB9843DB, 0x1B2D361B, 0x3C44783C, 0xC8AD65C8, 0x995EC799, 0x040C0804,
+0x8E67E98E, 0xE0D535E0, 0xD78C5BD7, 0x7D87FA7D, 0x857AFF85, 0xBB3883BB,
+0x40C08040, 0x2C74582C, 0x3A4E743A, 0x45CF8A45, 0xF1E617F1, 0x42C68442,
+0x65AFCA65, 0x20604020, 0x41C38241, 0x18283018, 0x7296E472, 0x256F4A25,
+0x9340D393, 0x7090E070, 0x365A6C36, 0x050F0A05, 0xF2E311F2, 0x0B1D160B,
+0xA310B3A3, 0x798BF279, 0xECC12DEC, 0x08181008, 0x27694E27, 0x31536231,
+0x32566432, 0xB62F99B6, 0x7C84F87C, 0xB02595B0, 0x0A1E140A, 0x7395E673,
+0x5BEDB65B, 0x7B8DF67B, 0xB72C9BB7, 0x8176F781, 0xD28351D2, 0x0D171A0D,
+0x6ABED46A, 0x266A4C26, 0x9E57C99E, 0x58E8B058, 0x9C51CD9C, 0x8370F383,
+0x749CE874, 0xB32093B3, 0xAC01ADAC, 0x30506030, 0x7A8EF47A, 0x69BBD269,
+0x7799EE77, 0x0F111E0F, 0xAE07A9AE, 0x21634221, 0xDE9749DE, 0xD08555D0,
+0x2E725C2E, 0x974CDB97, 0x10302010, 0xA419BDA4, 0x985DC598, 0xA80DA5A8,
+0xD4895DD4, 0x68B8D068, 0x2D775A2D, 0x62A6C462, 0x297B5229, 0x6DB7DA6D,
+0x163A2C16, 0x49DB9249, 0x769AEC76, 0xC7BC7BC7, 0xE8CD25E8, 0xC1B677C1,
+0x964FD996, 0x37596E37, 0xE5DA3FE5, 0xCAAB61CA, 0xF4E91DF4, 0xE9CE27E9,
+0x63A5C663, 0x12362412, 0xC2B371C2, 0xA61FB9A6, 0x143C2814, 0xBC318DBC,
+0xD38053D3, 0x28785028, 0xAF04ABAF, 0x2F715E2F, 0xE6DF39E6, 0x246C4824,
+0x52F6A452, 0xC6BF79C6, 0xA015B5A0, 0x091B1209, 0xBD328FBD, 0x8C61ED8C,
+0xCFA46BCF, 0x5DE7BA5D, 0x11332211, 0x5FE1BE5F, 0x01030201, 0xC5BA7FC5,
+0x9F54CB9F, 0x3D477A3D, 0xA213B1A2, 0x9B58C39B, 0xC9AE67C9, 0x3B4D763B,
+0xBE3789BE, 0x51F3A251, 0x192B3219, 0x1F213E1F, 0x3F417E3F, 0x5CE4B85C,
+0xB22391B2, 0xEFC42BEF, 0x4ADE944A, 0xCDA26FCD, 0xBF348BBF, 0xBA3B81BA,
+0x6FB1DE6F, 0x64ACC864, 0xD99E47D9, 0xF3E013F3, 0x3E427C3E, 0xB4299DB4,
+0xAA0BA1AA, 0xDC914DDC, 0xD58A5FD5, 0x060A0C06, 0xC0B575C0, 0x7E82FC7E,
+0xF6EF19F6, 0x66AACC66, 0x6CB4D86C, 0x8479FD84, 0x7193E271, 0x38487038,
+0xB93E87B9, 0x1D273A1D, 0x7F81FE7F, 0x9D52CF9D, 0x48D89048, 0x8B68E38B,
+0x2A7E542A, 0xDA9B41DA, 0xA51ABFA5, 0x33556633, 0x8273F182, 0x394B7239,
+0xD68F59D6, 0x7888F078, 0x867FF986, 0xFAFB01FA, 0xE4D93DE4, 0x2B7D562B,
+0xA90EA7A9, 0x1E223C1E, 0x896EE789, 0x60A0C060, 0x6BBDD66B, 0xEACB21EA,
+0x55FFAA55, 0x4CD4984C, 0xF7EC1BF7, 0xE2D331E2 };
+
+const u32bit Square::TE3[256] = {
+0xB1B12697, 0xCECEA769, 0xC3C3B073, 0x95954ADF, 0x5A5AEEB4, 0xADAD02AF,
+0xE7E7DC3B, 0x02020604, 0x4D4DD79A, 0x4444CC88, 0xFBFBF803, 0x919146D7,
+0x0C0C1418, 0x87877CFB, 0xA1A116B7, 0x5050F0A0, 0xCBCBA863, 0x6767A9CE,
+0x5454FCA8, 0xDDDD924F, 0x4646CA8C, 0x8F8F64EB, 0xE1E1D637, 0x4E4ED29C,
+0xF0F0E515, 0xFDFDF20F, 0xFCFCF10D, 0xEBEBC823, 0xF9F9FE07, 0xC4C4B97D,
+0x1A1A2E34, 0x6E6EB2DC, 0x5E5EE2BC, 0xF5F5EA1F, 0xCCCCA16D, 0x8D8D62EF,
+0x1C1C2438, 0x5656FAAC, 0x4343C586, 0xFEFEF709, 0x0707090E, 0x6161A3C2,
+0xF8F8FD05, 0x75759FEA, 0x5959EBB2, 0xFFFFF40B, 0x03030506, 0x22226644,
+0x8A8A6BE1, 0xD1D18657, 0x13133526, 0xEEEEC729, 0x88886DE5, 0x00000000,
+0x0E0E121C, 0x34345C68, 0x15153F2A, 0x808075F5, 0x949449DD, 0xE3E3D033,
+0xEDEDC22F, 0xB5B52A9F, 0x5353F5A6, 0x23236546, 0x4B4BDD96, 0x4747C98E,
+0x1717392E, 0xA7A71CBB, 0x909045D5, 0x35355F6A, 0xABAB08A3, 0xD8D89D45,
+0xB8B83D85, 0xDFDF944B, 0x4F4FD19E, 0x5757F9AE, 0x9A9A5BC1, 0x929243D1,
+0xDBDB9843, 0x1B1B2D36, 0x3C3C4478, 0xC8C8AD65, 0x99995EC7, 0x04040C08,
+0x8E8E67E9, 0xE0E0D535, 0xD7D78C5B, 0x7D7D87FA, 0x85857AFF, 0xBBBB3883,
+0x4040C080, 0x2C2C7458, 0x3A3A4E74, 0x4545CF8A, 0xF1F1E617, 0x4242C684,
+0x6565AFCA, 0x20206040, 0x4141C382, 0x18182830, 0x727296E4, 0x25256F4A,
+0x939340D3, 0x707090E0, 0x36365A6C, 0x05050F0A, 0xF2F2E311, 0x0B0B1D16,
+0xA3A310B3, 0x79798BF2, 0xECECC12D, 0x08081810, 0x2727694E, 0x31315362,
+0x32325664, 0xB6B62F99, 0x7C7C84F8, 0xB0B02595, 0x0A0A1E14, 0x737395E6,
+0x5B5BEDB6, 0x7B7B8DF6, 0xB7B72C9B, 0x818176F7, 0xD2D28351, 0x0D0D171A,
+0x6A6ABED4, 0x26266A4C, 0x9E9E57C9, 0x5858E8B0, 0x9C9C51CD, 0x838370F3,
+0x74749CE8, 0xB3B32093, 0xACAC01AD, 0x30305060, 0x7A7A8EF4, 0x6969BBD2,
+0x777799EE, 0x0F0F111E, 0xAEAE07A9, 0x21216342, 0xDEDE9749, 0xD0D08555,
+0x2E2E725C, 0x97974CDB, 0x10103020, 0xA4A419BD, 0x98985DC5, 0xA8A80DA5,
+0xD4D4895D, 0x6868B8D0, 0x2D2D775A, 0x6262A6C4, 0x29297B52, 0x6D6DB7DA,
+0x16163A2C, 0x4949DB92, 0x76769AEC, 0xC7C7BC7B, 0xE8E8CD25, 0xC1C1B677,
+0x96964FD9, 0x3737596E, 0xE5E5DA3F, 0xCACAAB61, 0xF4F4E91D, 0xE9E9CE27,
+0x6363A5C6, 0x12123624, 0xC2C2B371, 0xA6A61FB9, 0x14143C28, 0xBCBC318D,
+0xD3D38053, 0x28287850, 0xAFAF04AB, 0x2F2F715E, 0xE6E6DF39, 0x24246C48,
+0x5252F6A4, 0xC6C6BF79, 0xA0A015B5, 0x09091B12, 0xBDBD328F, 0x8C8C61ED,
+0xCFCFA46B, 0x5D5DE7BA, 0x11113322, 0x5F5FE1BE, 0x01010302, 0xC5C5BA7F,
+0x9F9F54CB, 0x3D3D477A, 0xA2A213B1, 0x9B9B58C3, 0xC9C9AE67, 0x3B3B4D76,
+0xBEBE3789, 0x5151F3A2, 0x19192B32, 0x1F1F213E, 0x3F3F417E, 0x5C5CE4B8,
+0xB2B22391, 0xEFEFC42B, 0x4A4ADE94, 0xCDCDA26F, 0xBFBF348B, 0xBABA3B81,
+0x6F6FB1DE, 0x6464ACC8, 0xD9D99E47, 0xF3F3E013, 0x3E3E427C, 0xB4B4299D,
+0xAAAA0BA1, 0xDCDC914D, 0xD5D58A5F, 0x06060A0C, 0xC0C0B575, 0x7E7E82FC,
+0xF6F6EF19, 0x6666AACC, 0x6C6CB4D8, 0x848479FD, 0x717193E2, 0x38384870,
+0xB9B93E87, 0x1D1D273A, 0x7F7F81FE, 0x9D9D52CF, 0x4848D890, 0x8B8B68E3,
+0x2A2A7E54, 0xDADA9B41, 0xA5A51ABF, 0x33335566, 0x828273F1, 0x39394B72,
+0xD6D68F59, 0x787888F0, 0x86867FF9, 0xFAFAFB01, 0xE4E4D93D, 0x2B2B7D56,
+0xA9A90EA7, 0x1E1E223C, 0x89896EE7, 0x6060A0C0, 0x6B6BBDD6, 0xEAEACB21,
+0x5555FFAA, 0x4C4CD498, 0xF7F7EC1B, 0xE2E2D331 };
+
+const u32bit Square::TD0[256] = {
+0xE368BC02, 0x5585620C, 0x2A3F2331, 0x61AB13F7, 0x98D46D72, 0x21CB9A19,
+0x3C22A461, 0x459D3DCD, 0x05FDB423, 0x2BC4075F, 0x9B2C01C0, 0x3DD9800F,
+0x486C5C74, 0xF97F7E85, 0xF173AB1F, 0xB6EDDE0E, 0x283C6BED, 0x4997781A,
+0x9F2A918D, 0xC9579F33, 0xA907A8AA, 0xA50DED7D, 0x7C422D8F, 0x764DB0C9,
+0x4D91E857, 0xCEA963CC, 0xB4EE96D2, 0x3028E1B6, 0x0DF161B9, 0xBD196726,
+0x419BAD80, 0xC0A06EC7, 0x5183F241, 0x92DBF034, 0x6FA21EFC, 0x8F32CE4C,
+0x13E03373, 0x69A7C66D, 0xE56D6493, 0xBF1A2FFA, 0xBB1CBFB7, 0x587403B5,
+0xE76E2C4F, 0x5D89B796, 0xE89C052A, 0x446619A3, 0x342E71FB, 0x0FF22965,
+0xFE81827A, 0xB11322F1, 0xA30835EC, 0xCD510F7E, 0xFF7AA614, 0x5C7293F8,
+0x2FC29712, 0xF370E3C3, 0x992F491C, 0xD1431568, 0xC2A3261B, 0x88CC32B3,
+0x8ACF7A6F, 0xB0E8069F, 0x7A47F51E, 0xD2BB79DA, 0xE6950821, 0x4398E55C,
+0xD0B83106, 0x11E37BAF, 0x7E416553, 0xCCAA2B10, 0xD8B4E49C, 0x6456A7D4,
+0xFB7C3659, 0x724B2084, 0xEA9F4DF6, 0x6A5FAADF, 0x2DC1DFCE, 0x70486858,
+0xCAAFF381, 0x0605D891, 0x5A774B69, 0x94DE28A5, 0x39DF1042, 0x813BC347,
+0xFC82CAA6, 0x23C8D2C5, 0x03F86CB2, 0x080CD59A, 0xDAB7AC40, 0x7DB909E1,
+0x3824342C, 0xCF5247A2, 0xDCB274D1, 0x63A85B2B, 0x35D55595, 0x479E7511,
+0x15E5EBE2, 0x4B9430C6, 0x4A6F14A8, 0x91239C86, 0x4C6ACC39, 0x5F8AFF4A,
+0x0406904D, 0xEE99DDBB, 0x1E1152CA, 0xAAFFC418, 0xEB646998, 0x07FEFCFF,
+0x8B345E01, 0x567D0EBE, 0xBAE79BD9, 0x4263C132, 0x75B5DC7B, 0x97264417,
+0x67AECB66, 0x95250CCB, 0xEC9A9567, 0x57862AD0, 0x60503799, 0xB8E4D305,
+0x65AD83BA, 0x19EFAE35, 0xA4F6C913, 0xC15B4AA9, 0x873E1BD6, 0xA0F0595E,
+0x18148A5B, 0xAF02703B, 0xAB04E076, 0xDD4950BF, 0xDF4A1863, 0xC6A5B656,
+0x853D530A, 0xFA871237, 0x77B694A7, 0x4665517F, 0xED61B109, 0x1BECE6E9,
+0xD5458525, 0xF5753B52, 0x7FBA413D, 0x27CE4288, 0xB2EB4E43, 0xD6BDE997,
+0x527B9EF3, 0x62537F45, 0x2C3AFBA0, 0x7BBCD170, 0xB91FF76B, 0x121B171D,
+0xFD79EEC8, 0x3A277CF0, 0x0C0A45D7, 0x96DD6079, 0x2233F6AB, 0xACFA1C89,
+0xC8ACBB5D, 0xA10B7D30, 0xD4BEA14B, 0xBEE10B94, 0x25CD0A54, 0x547E4662,
+0xA2F31182, 0x17E6A33E, 0x263566E6, 0xC3580275, 0x83388B9B, 0x7844BDC2,
+0x020348DC, 0x4F92A08B, 0x2E39B37C, 0x4E6984E5, 0xF0888F71, 0x362D3927,
+0x9CD2FD3F, 0x01FB246E, 0x893716DD, 0x00000000, 0xF68D57E0, 0xE293986C,
+0x744EF815, 0x9320D45A, 0xAD0138E7, 0xD3405DB4, 0x1A17C287, 0xB3106A2D,
+0x5078D62F, 0xF48E1F3C, 0xA70EA5A1, 0x71B34C36, 0x9AD725AE, 0x5E71DB24,
+0x161D8750, 0xEF62F9D5, 0x8D318690, 0x1C121A16, 0xA6F581CF, 0x5B8C6F07,
+0x37D61D49, 0x6E593A92, 0x84C67764, 0x86C53FB8, 0xD746CDF9, 0xE090D0B0,
+0x29C74F83, 0xE49640FD, 0x0E090D0B, 0x6DA15620, 0x8EC9EA22, 0xDB4C882E,
+0xF776738E, 0xB515B2BC, 0x10185FC1, 0x322BA96A, 0x6BA48EB1, 0xAEF95455,
+0x406089EE, 0x6655EF08, 0xE9672144, 0x3E21ECBD, 0x2030BE77, 0xF28BC7AD,
+0x80C0E729, 0x141ECF8C, 0xBCE24348, 0xC4A6FE8A, 0x31D3C5D8, 0xB716FA60,
+0x5380BA9D, 0xD94FC0F2, 0x1DE93E78, 0x24362E3A, 0xE16BF4DE, 0xCB54D7EF,
+0x09F7F1F4, 0x82C3AFF5, 0x0BF4B928, 0x9D29D951, 0xC75E9238, 0xF8845AEB,
+0x90D8B8E8, 0xDEB13C0D, 0x33D08D04, 0x685CE203, 0xC55DDAE4, 0x3BDC589E,
+0x0A0F9D46, 0x3FDAC8D3, 0x598F27DB, 0xA8FC8CC4, 0x79BF99AC, 0x6C5A724E,
+0x8CCAA2FE, 0x9ED1B5E3, 0x1FEA76A4, 0x73B004EA };
+
+const u32bit Square::TD1[256] = {
+0x02E368BC, 0x0C558562, 0x312A3F23, 0xF761AB13, 0x7298D46D, 0x1921CB9A,
+0x613C22A4, 0xCD459D3D, 0x2305FDB4, 0x5F2BC407, 0xC09B2C01, 0x0F3DD980,
+0x74486C5C, 0x85F97F7E, 0x1FF173AB, 0x0EB6EDDE, 0xED283C6B, 0x1A499778,
+0x8D9F2A91, 0x33C9579F, 0xAAA907A8, 0x7DA50DED, 0x8F7C422D, 0xC9764DB0,
+0x574D91E8, 0xCCCEA963, 0xD2B4EE96, 0xB63028E1, 0xB90DF161, 0x26BD1967,
+0x80419BAD, 0xC7C0A06E, 0x415183F2, 0x3492DBF0, 0xFC6FA21E, 0x4C8F32CE,
+0x7313E033, 0x6D69A7C6, 0x93E56D64, 0xFABF1A2F, 0xB7BB1CBF, 0xB5587403,
+0x4FE76E2C, 0x965D89B7, 0x2AE89C05, 0xA3446619, 0xFB342E71, 0x650FF229,
+0x7AFE8182, 0xF1B11322, 0xECA30835, 0x7ECD510F, 0x14FF7AA6, 0xF85C7293,
+0x122FC297, 0xC3F370E3, 0x1C992F49, 0x68D14315, 0x1BC2A326, 0xB388CC32,
+0x6F8ACF7A, 0x9FB0E806, 0x1E7A47F5, 0xDAD2BB79, 0x21E69508, 0x5C4398E5,
+0x06D0B831, 0xAF11E37B, 0x537E4165, 0x10CCAA2B, 0x9CD8B4E4, 0xD46456A7,
+0x59FB7C36, 0x84724B20, 0xF6EA9F4D, 0xDF6A5FAA, 0xCE2DC1DF, 0x58704868,
+0x81CAAFF3, 0x910605D8, 0x695A774B, 0xA594DE28, 0x4239DF10, 0x47813BC3,
+0xA6FC82CA, 0xC523C8D2, 0xB203F86C, 0x9A080CD5, 0x40DAB7AC, 0xE17DB909,
+0x2C382434, 0xA2CF5247, 0xD1DCB274, 0x2B63A85B, 0x9535D555, 0x11479E75,
+0xE215E5EB, 0xC64B9430, 0xA84A6F14, 0x8691239C, 0x394C6ACC, 0x4A5F8AFF,
+0x4D040690, 0xBBEE99DD, 0xCA1E1152, 0x18AAFFC4, 0x98EB6469, 0xFF07FEFC,
+0x018B345E, 0xBE567D0E, 0xD9BAE79B, 0x324263C1, 0x7B75B5DC, 0x17972644,
+0x6667AECB, 0xCB95250C, 0x67EC9A95, 0xD057862A, 0x99605037, 0x05B8E4D3,
+0xBA65AD83, 0x3519EFAE, 0x13A4F6C9, 0xA9C15B4A, 0xD6873E1B, 0x5EA0F059,
+0x5B18148A, 0x3BAF0270, 0x76AB04E0, 0xBFDD4950, 0x63DF4A18, 0x56C6A5B6,
+0x0A853D53, 0x37FA8712, 0xA777B694, 0x7F466551, 0x09ED61B1, 0xE91BECE6,
+0x25D54585, 0x52F5753B, 0x3D7FBA41, 0x8827CE42, 0x43B2EB4E, 0x97D6BDE9,
+0xF3527B9E, 0x4562537F, 0xA02C3AFB, 0x707BBCD1, 0x6BB91FF7, 0x1D121B17,
+0xC8FD79EE, 0xF03A277C, 0xD70C0A45, 0x7996DD60, 0xAB2233F6, 0x89ACFA1C,
+0x5DC8ACBB, 0x30A10B7D, 0x4BD4BEA1, 0x94BEE10B, 0x5425CD0A, 0x62547E46,
+0x82A2F311, 0x3E17E6A3, 0xE6263566, 0x75C35802, 0x9B83388B, 0xC27844BD,
+0xDC020348, 0x8B4F92A0, 0x7C2E39B3, 0xE54E6984, 0x71F0888F, 0x27362D39,
+0x3F9CD2FD, 0x6E01FB24, 0xDD893716, 0x00000000, 0xE0F68D57, 0x6CE29398,
+0x15744EF8, 0x5A9320D4, 0xE7AD0138, 0xB4D3405D, 0x871A17C2, 0x2DB3106A,
+0x2F5078D6, 0x3CF48E1F, 0xA1A70EA5, 0x3671B34C, 0xAE9AD725, 0x245E71DB,
+0x50161D87, 0xD5EF62F9, 0x908D3186, 0x161C121A, 0xCFA6F581, 0x075B8C6F,
+0x4937D61D, 0x926E593A, 0x6484C677, 0xB886C53F, 0xF9D746CD, 0xB0E090D0,
+0x8329C74F, 0xFDE49640, 0x0B0E090D, 0x206DA156, 0x228EC9EA, 0x2EDB4C88,
+0x8EF77673, 0xBCB515B2, 0xC110185F, 0x6A322BA9, 0xB16BA48E, 0x55AEF954,
+0xEE406089, 0x086655EF, 0x44E96721, 0xBD3E21EC, 0x772030BE, 0xADF28BC7,
+0x2980C0E7, 0x8C141ECF, 0x48BCE243, 0x8AC4A6FE, 0xD831D3C5, 0x60B716FA,
+0x9D5380BA, 0xF2D94FC0, 0x781DE93E, 0x3A24362E, 0xDEE16BF4, 0xEFCB54D7,
+0xF409F7F1, 0xF582C3AF, 0x280BF4B9, 0x519D29D9, 0x38C75E92, 0xEBF8845A,
+0xE890D8B8, 0x0DDEB13C, 0x0433D08D, 0x03685CE2, 0xE4C55DDA, 0x9E3BDC58,
+0x460A0F9D, 0xD33FDAC8, 0xDB598F27, 0xC4A8FC8C, 0xAC79BF99, 0x4E6C5A72,
+0xFE8CCAA2, 0xE39ED1B5, 0xA41FEA76, 0xEA73B004 };
+
+const u32bit Square::TD2[256] = {
+0xBC02E368, 0x620C5585, 0x23312A3F, 0x13F761AB, 0x6D7298D4, 0x9A1921CB,
+0xA4613C22, 0x3DCD459D, 0xB42305FD, 0x075F2BC4, 0x01C09B2C, 0x800F3DD9,
+0x5C74486C, 0x7E85F97F, 0xAB1FF173, 0xDE0EB6ED, 0x6BED283C, 0x781A4997,
+0x918D9F2A, 0x9F33C957, 0xA8AAA907, 0xED7DA50D, 0x2D8F7C42, 0xB0C9764D,
+0xE8574D91, 0x63CCCEA9, 0x96D2B4EE, 0xE1B63028, 0x61B90DF1, 0x6726BD19,
+0xAD80419B, 0x6EC7C0A0, 0xF2415183, 0xF03492DB, 0x1EFC6FA2, 0xCE4C8F32,
+0x337313E0, 0xC66D69A7, 0x6493E56D, 0x2FFABF1A, 0xBFB7BB1C, 0x03B55874,
+0x2C4FE76E, 0xB7965D89, 0x052AE89C, 0x19A34466, 0x71FB342E, 0x29650FF2,
+0x827AFE81, 0x22F1B113, 0x35ECA308, 0x0F7ECD51, 0xA614FF7A, 0x93F85C72,
+0x97122FC2, 0xE3C3F370, 0x491C992F, 0x1568D143, 0x261BC2A3, 0x32B388CC,
+0x7A6F8ACF, 0x069FB0E8, 0xF51E7A47, 0x79DAD2BB, 0x0821E695, 0xE55C4398,
+0x3106D0B8, 0x7BAF11E3, 0x65537E41, 0x2B10CCAA, 0xE49CD8B4, 0xA7D46456,
+0x3659FB7C, 0x2084724B, 0x4DF6EA9F, 0xAADF6A5F, 0xDFCE2DC1, 0x68587048,
+0xF381CAAF, 0xD8910605, 0x4B695A77, 0x28A594DE, 0x104239DF, 0xC347813B,
+0xCAA6FC82, 0xD2C523C8, 0x6CB203F8, 0xD59A080C, 0xAC40DAB7, 0x09E17DB9,
+0x342C3824, 0x47A2CF52, 0x74D1DCB2, 0x5B2B63A8, 0x559535D5, 0x7511479E,
+0xEBE215E5, 0x30C64B94, 0x14A84A6F, 0x9C869123, 0xCC394C6A, 0xFF4A5F8A,
+0x904D0406, 0xDDBBEE99, 0x52CA1E11, 0xC418AAFF, 0x6998EB64, 0xFCFF07FE,
+0x5E018B34, 0x0EBE567D, 0x9BD9BAE7, 0xC1324263, 0xDC7B75B5, 0x44179726,
+0xCB6667AE, 0x0CCB9525, 0x9567EC9A, 0x2AD05786, 0x37996050, 0xD305B8E4,
+0x83BA65AD, 0xAE3519EF, 0xC913A4F6, 0x4AA9C15B, 0x1BD6873E, 0x595EA0F0,
+0x8A5B1814, 0x703BAF02, 0xE076AB04, 0x50BFDD49, 0x1863DF4A, 0xB656C6A5,
+0x530A853D, 0x1237FA87, 0x94A777B6, 0x517F4665, 0xB109ED61, 0xE6E91BEC,
+0x8525D545, 0x3B52F575, 0x413D7FBA, 0x428827CE, 0x4E43B2EB, 0xE997D6BD,
+0x9EF3527B, 0x7F456253, 0xFBA02C3A, 0xD1707BBC, 0xF76BB91F, 0x171D121B,
+0xEEC8FD79, 0x7CF03A27, 0x45D70C0A, 0x607996DD, 0xF6AB2233, 0x1C89ACFA,
+0xBB5DC8AC, 0x7D30A10B, 0xA14BD4BE, 0x0B94BEE1, 0x0A5425CD, 0x4662547E,
+0x1182A2F3, 0xA33E17E6, 0x66E62635, 0x0275C358, 0x8B9B8338, 0xBDC27844,
+0x48DC0203, 0xA08B4F92, 0xB37C2E39, 0x84E54E69, 0x8F71F088, 0x3927362D,
+0xFD3F9CD2, 0x246E01FB, 0x16DD8937, 0x00000000, 0x57E0F68D, 0x986CE293,
+0xF815744E, 0xD45A9320, 0x38E7AD01, 0x5DB4D340, 0xC2871A17, 0x6A2DB310,
+0xD62F5078, 0x1F3CF48E, 0xA5A1A70E, 0x4C3671B3, 0x25AE9AD7, 0xDB245E71,
+0x8750161D, 0xF9D5EF62, 0x86908D31, 0x1A161C12, 0x81CFA6F5, 0x6F075B8C,
+0x1D4937D6, 0x3A926E59, 0x776484C6, 0x3FB886C5, 0xCDF9D746, 0xD0B0E090,
+0x4F8329C7, 0x40FDE496, 0x0D0B0E09, 0x56206DA1, 0xEA228EC9, 0x882EDB4C,
+0x738EF776, 0xB2BCB515, 0x5FC11018, 0xA96A322B, 0x8EB16BA4, 0x5455AEF9,
+0x89EE4060, 0xEF086655, 0x2144E967, 0xECBD3E21, 0xBE772030, 0xC7ADF28B,
+0xE72980C0, 0xCF8C141E, 0x4348BCE2, 0xFE8AC4A6, 0xC5D831D3, 0xFA60B716,
+0xBA9D5380, 0xC0F2D94F, 0x3E781DE9, 0x2E3A2436, 0xF4DEE16B, 0xD7EFCB54,
+0xF1F409F7, 0xAFF582C3, 0xB9280BF4, 0xD9519D29, 0x9238C75E, 0x5AEBF884,
+0xB8E890D8, 0x3C0DDEB1, 0x8D0433D0, 0xE203685C, 0xDAE4C55D, 0x589E3BDC,
+0x9D460A0F, 0xC8D33FDA, 0x27DB598F, 0x8CC4A8FC, 0x99AC79BF, 0x724E6C5A,
+0xA2FE8CCA, 0xB5E39ED1, 0x76A41FEA, 0x04EA73B0 };
+
+const u32bit Square::TD3[256] = {
+0x68BC02E3, 0x85620C55, 0x3F23312A, 0xAB13F761, 0xD46D7298, 0xCB9A1921,
+0x22A4613C, 0x9D3DCD45, 0xFDB42305, 0xC4075F2B, 0x2C01C09B, 0xD9800F3D,
+0x6C5C7448, 0x7F7E85F9, 0x73AB1FF1, 0xEDDE0EB6, 0x3C6BED28, 0x97781A49,
+0x2A918D9F, 0x579F33C9, 0x07A8AAA9, 0x0DED7DA5, 0x422D8F7C, 0x4DB0C976,
+0x91E8574D, 0xA963CCCE, 0xEE96D2B4, 0x28E1B630, 0xF161B90D, 0x196726BD,
+0x9BAD8041, 0xA06EC7C0, 0x83F24151, 0xDBF03492, 0xA21EFC6F, 0x32CE4C8F,
+0xE0337313, 0xA7C66D69, 0x6D6493E5, 0x1A2FFABF, 0x1CBFB7BB, 0x7403B558,
+0x6E2C4FE7, 0x89B7965D, 0x9C052AE8, 0x6619A344, 0x2E71FB34, 0xF229650F,
+0x81827AFE, 0x1322F1B1, 0x0835ECA3, 0x510F7ECD, 0x7AA614FF, 0x7293F85C,
+0xC297122F, 0x70E3C3F3, 0x2F491C99, 0x431568D1, 0xA3261BC2, 0xCC32B388,
+0xCF7A6F8A, 0xE8069FB0, 0x47F51E7A, 0xBB79DAD2, 0x950821E6, 0x98E55C43,
+0xB83106D0, 0xE37BAF11, 0x4165537E, 0xAA2B10CC, 0xB4E49CD8, 0x56A7D464,
+0x7C3659FB, 0x4B208472, 0x9F4DF6EA, 0x5FAADF6A, 0xC1DFCE2D, 0x48685870,
+0xAFF381CA, 0x05D89106, 0x774B695A, 0xDE28A594, 0xDF104239, 0x3BC34781,
+0x82CAA6FC, 0xC8D2C523, 0xF86CB203, 0x0CD59A08, 0xB7AC40DA, 0xB909E17D,
+0x24342C38, 0x5247A2CF, 0xB274D1DC, 0xA85B2B63, 0xD5559535, 0x9E751147,
+0xE5EBE215, 0x9430C64B, 0x6F14A84A, 0x239C8691, 0x6ACC394C, 0x8AFF4A5F,
+0x06904D04, 0x99DDBBEE, 0x1152CA1E, 0xFFC418AA, 0x646998EB, 0xFEFCFF07,
+0x345E018B, 0x7D0EBE56, 0xE79BD9BA, 0x63C13242, 0xB5DC7B75, 0x26441797,
+0xAECB6667, 0x250CCB95, 0x9A9567EC, 0x862AD057, 0x50379960, 0xE4D305B8,
+0xAD83BA65, 0xEFAE3519, 0xF6C913A4, 0x5B4AA9C1, 0x3E1BD687, 0xF0595EA0,
+0x148A5B18, 0x02703BAF, 0x04E076AB, 0x4950BFDD, 0x4A1863DF, 0xA5B656C6,
+0x3D530A85, 0x871237FA, 0xB694A777, 0x65517F46, 0x61B109ED, 0xECE6E91B,
+0x458525D5, 0x753B52F5, 0xBA413D7F, 0xCE428827, 0xEB4E43B2, 0xBDE997D6,
+0x7B9EF352, 0x537F4562, 0x3AFBA02C, 0xBCD1707B, 0x1FF76BB9, 0x1B171D12,
+0x79EEC8FD, 0x277CF03A, 0x0A45D70C, 0xDD607996, 0x33F6AB22, 0xFA1C89AC,
+0xACBB5DC8, 0x0B7D30A1, 0xBEA14BD4, 0xE10B94BE, 0xCD0A5425, 0x7E466254,
+0xF31182A2, 0xE6A33E17, 0x3566E626, 0x580275C3, 0x388B9B83, 0x44BDC278,
+0x0348DC02, 0x92A08B4F, 0x39B37C2E, 0x6984E54E, 0x888F71F0, 0x2D392736,
+0xD2FD3F9C, 0xFB246E01, 0x3716DD89, 0x00000000, 0x8D57E0F6, 0x93986CE2,
+0x4EF81574, 0x20D45A93, 0x0138E7AD, 0x405DB4D3, 0x17C2871A, 0x106A2DB3,
+0x78D62F50, 0x8E1F3CF4, 0x0EA5A1A7, 0xB34C3671, 0xD725AE9A, 0x71DB245E,
+0x1D875016, 0x62F9D5EF, 0x3186908D, 0x121A161C, 0xF581CFA6, 0x8C6F075B,
+0xD61D4937, 0x593A926E, 0xC6776484, 0xC53FB886, 0x46CDF9D7, 0x90D0B0E0,
+0xC74F8329, 0x9640FDE4, 0x090D0B0E, 0xA156206D, 0xC9EA228E, 0x4C882EDB,
+0x76738EF7, 0x15B2BCB5, 0x185FC110, 0x2BA96A32, 0xA48EB16B, 0xF95455AE,
+0x6089EE40, 0x55EF0866, 0x672144E9, 0x21ECBD3E, 0x30BE7720, 0x8BC7ADF2,
+0xC0E72980, 0x1ECF8C14, 0xE24348BC, 0xA6FE8AC4, 0xD3C5D831, 0x16FA60B7,
+0x80BA9D53, 0x4FC0F2D9, 0xE93E781D, 0x362E3A24, 0x6BF4DEE1, 0x54D7EFCB,
+0xF7F1F409, 0xC3AFF582, 0xF4B9280B, 0x29D9519D, 0x5E9238C7, 0x845AEBF8,
+0xD8B8E890, 0xB13C0DDE, 0xD08D0433, 0x5CE20368, 0x5DDAE4C5, 0xDC589E3B,
+0x0F9D460A, 0xDAC8D33F, 0x8F27DB59, 0xFC8CC4A8, 0xBF99AC79, 0x5A724E6C,
+0xCAA2FE8C, 0xD1B5E39E, 0xEA76A41F, 0xB004EA73 };
+
+}
diff --git a/botan/src/block/square/square.cpp b/botan/src/block/square/square.cpp
new file mode 100644
index 0000000..cb22654
--- /dev/null
+++ b/botan/src/block/square/square.cpp
@@ -0,0 +1,187 @@
+/*
+* Square
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/square.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* Square Encryption
+*/
+void Square::enc(const byte in[], byte out[]) const
+ {
+ u32bit T0, T1, T2, T3, B0, B1, B2, B3;
+ B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^
+ TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0];
+ B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^
+ TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1];
+ B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^
+ TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2];
+ B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^
+ TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3];
+ for(u32bit j = 1; j != 7; j += 2)
+ {
+ T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^
+ TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0];
+ T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^
+ TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1];
+ T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^
+ TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2];
+ T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^
+ TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3];
+ B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^
+ TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4];
+ B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^
+ TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5];
+ B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^
+ TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6];
+ B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^
+ TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7];
+ }
+ out[ 0] = SE[get_byte(0, B0)] ^ ME[16];
+ out[ 1] = SE[get_byte(0, B1)] ^ ME[17];
+ out[ 2] = SE[get_byte(0, B2)] ^ ME[18];
+ out[ 3] = SE[get_byte(0, B3)] ^ ME[19];
+ out[ 4] = SE[get_byte(1, B0)] ^ ME[20];
+ out[ 5] = SE[get_byte(1, B1)] ^ ME[21];
+ out[ 6] = SE[get_byte(1, B2)] ^ ME[22];
+ out[ 7] = SE[get_byte(1, B3)] ^ ME[23];
+ out[ 8] = SE[get_byte(2, B0)] ^ ME[24];
+ out[ 9] = SE[get_byte(2, B1)] ^ ME[25];
+ out[10] = SE[get_byte(2, B2)] ^ ME[26];
+ out[11] = SE[get_byte(2, B3)] ^ ME[27];
+ out[12] = SE[get_byte(3, B0)] ^ ME[28];
+ out[13] = SE[get_byte(3, B1)] ^ ME[29];
+ out[14] = SE[get_byte(3, B2)] ^ ME[30];
+ out[15] = SE[get_byte(3, B3)] ^ ME[31];
+ }
+
+/*
+* Square Decryption
+*/
+void Square::dec(const byte in[], byte out[]) const
+ {
+ u32bit T0, T1, T2, T3, B0, B1, B2, B3;
+ B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^
+ TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0];
+ B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^
+ TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1];
+ B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^
+ TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2];
+ B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^
+ TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3];
+ for(u32bit j = 1; j != 7; j += 2)
+ {
+ T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^
+ TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0];
+ T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^
+ TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1];
+ T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^
+ TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2];
+ T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^
+ TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3];
+ B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^
+ TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4];
+ B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^
+ TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5];
+ B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^
+ TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6];
+ B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^
+ TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7];
+ }
+ out[ 0] = SD[get_byte(0, B0)] ^ MD[16];
+ out[ 1] = SD[get_byte(0, B1)] ^ MD[17];
+ out[ 2] = SD[get_byte(0, B2)] ^ MD[18];
+ out[ 3] = SD[get_byte(0, B3)] ^ MD[19];
+ out[ 4] = SD[get_byte(1, B0)] ^ MD[20];
+ out[ 5] = SD[get_byte(1, B1)] ^ MD[21];
+ out[ 6] = SD[get_byte(1, B2)] ^ MD[22];
+ out[ 7] = SD[get_byte(1, B3)] ^ MD[23];
+ out[ 8] = SD[get_byte(2, B0)] ^ MD[24];
+ out[ 9] = SD[get_byte(2, B1)] ^ MD[25];
+ out[10] = SD[get_byte(2, B2)] ^ MD[26];
+ out[11] = SD[get_byte(2, B3)] ^ MD[27];
+ out[12] = SD[get_byte(3, B0)] ^ MD[28];
+ out[13] = SD[get_byte(3, B1)] ^ MD[29];
+ out[14] = SD[get_byte(3, B2)] ^ MD[30];
+ out[15] = SD[get_byte(3, B3)] ^ MD[31];
+ }
+
+/*
+* Square Key Schedule
+*/
+void Square::key_schedule(const byte key[], u32bit)
+ {
+ SecureBuffer<u32bit, 36> XEK, XDK;
+ for(u32bit j = 0; j != 4; ++j)
+ XEK[j] = load_be<u32bit>(key, j);
+ for(u32bit j = 0; j != 8; ++j)
+ {
+ XEK[4*j+4] = XEK[4*j ] ^ rotate_left(XEK[4*j+3], 8) ^ (0x01000000 << j);
+ XEK[4*j+5] = XEK[4*j+1] ^ XEK[4*j+4];
+ XEK[4*j+6] = XEK[4*j+2] ^ XEK[4*j+5];
+ XEK[4*j+7] = XEK[4*j+3] ^ XEK[4*j+6];
+ XDK.copy(28 - 4*j, XEK + 4*(j+1), 4);
+ transform(XEK + 4*j);
+ }
+ for(u32bit j = 0; j != 4; ++j)
+ for(u32bit k = 0; k != 4; ++k)
+ {
+ ME[4*j+k ] = get_byte(k, XEK[j ]);
+ ME[4*j+k+16] = get_byte(k, XEK[j+32]);
+ MD[4*j+k ] = get_byte(k, XDK[j ]);
+ MD[4*j+k+16] = get_byte(k, XEK[j ]);
+ }
+ EK.copy(XEK + 4, 28);
+ DK.copy(XDK + 4, 28);
+ }
+
+/*
+* Square's Inverse Linear Transformation
+*/
+void Square::transform(u32bit round_key[4])
+ {
+ static const byte G[4][4] = {
+ { 0x02, 0x01, 0x01, 0x03 },
+ { 0x03, 0x02, 0x01, 0x01 },
+ { 0x01, 0x03, 0x02, 0x01 },
+ { 0x01, 0x01, 0x03, 0x02 } };
+
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ SecureBuffer<byte, 4> A, B;
+
+ store_be(round_key[j], A);
+
+ for(u32bit k = 0; k != 4; ++k)
+ for(u32bit l = 0; l != 4; ++l)
+ {
+ const byte a = A[l];
+ const byte b = G[l][k];
+
+ if(a && b)
+ B[k] ^= ALog[(Log[a] + Log[b]) % 255];
+ }
+
+ round_key[j] = load_be<u32bit>(B.begin(), 0);
+ }
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Square::clear() throw()
+ {
+ EK.clear();
+ DK.clear();
+ ME.clear();
+ MD.clear();
+ }
+
+}
diff --git a/botan/src/block/square/square.h b/botan/src/block/square/square.h
new file mode 100644
index 0000000..94a1fc3
--- /dev/null
+++ b/botan/src/block/square/square.h
@@ -0,0 +1,52 @@
+/*
+* Square
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SQUARE_H__
+#define BOTAN_SQUARE_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Square
+*/
+class BOTAN_DLL Square : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Square"; }
+ BlockCipher* clone() const { return new Square; }
+ Square() : BlockCipher(16, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void transform(u32bit[4]);
+
+ static const byte SE[256];
+ static const byte SD[256];
+ static const byte Log[256];
+ static const byte ALog[255];
+
+ static const u32bit TE0[256];
+ static const u32bit TE1[256];
+ static const u32bit TE2[256];
+ static const u32bit TE3[256];
+ static const u32bit TD0[256];
+ static const u32bit TD1[256];
+ static const u32bit TD2[256];
+ static const u32bit TD3[256];
+
+ SecureBuffer<u32bit, 28> EK, DK;
+ SecureBuffer<byte, 32> ME, MD;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/tea/info.txt b/botan/src/block/tea/info.txt
new file mode 100644
index 0000000..6a0e76b
--- /dev/null
+++ b/botan/src/block/tea/info.txt
@@ -0,0 +1,10 @@
+realname "TEA"
+
+define TEA
+
+load_on auto
+
+<add>
+tea.cpp
+tea.h
+</add>
diff --git a/botan/src/block/tea/tea.cpp b/botan/src/block/tea/tea.cpp
new file mode 100644
index 0000000..2b4212d
--- /dev/null
+++ b/botan/src/block/tea/tea.cpp
@@ -0,0 +1,58 @@
+/*
+* TEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tea.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* TEA Encryption
+*/
+void TEA::enc(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1);
+
+ u32bit S = 0;
+ for(u32bit j = 0; j != 32; ++j)
+ {
+ S += 0x9E3779B9;
+ L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]);
+ R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]);
+ }
+
+ store_be(out, L, R);
+ }
+
+/*
+* TEA Decryption
+*/
+void TEA::dec(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1);
+
+ u32bit S = 0xC6EF3720;
+ for(u32bit j = 0; j != 32; ++j)
+ {
+ R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]);
+ L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]);
+ S -= 0x9E3779B9;
+ }
+
+ store_be(out, L, R);
+ }
+
+/*
+* TEA Key Schedule
+*/
+void TEA::key_schedule(const byte key[], u32bit)
+ {
+ for(u32bit j = 0; j != 4; ++j)
+ K[j] = load_be<u32bit>(key, j);
+ }
+
+}
diff --git a/botan/src/block/tea/tea.h b/botan/src/block/tea/tea.h
new file mode 100644
index 0000000..8ddf3e3
--- /dev/null
+++ b/botan/src/block/tea/tea.h
@@ -0,0 +1,34 @@
+/*
+* TEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TEA_H__
+#define BOTAN_TEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* TEA
+*/
+class BOTAN_DLL TEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { K.clear(); }
+ std::string name() const { return "TEA"; }
+ BlockCipher* clone() const { return new TEA; }
+ TEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u32bit, 4> K;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/twofish/info.txt b/botan/src/block/twofish/info.txt
new file mode 100644
index 0000000..35639d8
--- /dev/null
+++ b/botan/src/block/twofish/info.txt
@@ -0,0 +1,11 @@
+realname "Twofish"
+
+define TWOFISH
+
+load_on auto
+
+<add>
+two_tab.cpp
+twofish.cpp
+twofish.h
+</add>
diff --git a/botan/src/block/twofish/two_tab.cpp b/botan/src/block/twofish/two_tab.cpp
new file mode 100644
index 0000000..19ba58d
--- /dev/null
+++ b/botan/src/block/twofish/two_tab.cpp
@@ -0,0 +1,293 @@
+/*
+* S-Box and MDS Tables for Twofish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/twofish.h>
+
+namespace Botan {
+
+const byte Twofish::Q0[256] = {
+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78,
+ 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30,
+ 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE,
+ 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45,
+ 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF,
+ 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED,
+ 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B,
+ 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F,
+ 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17,
+ 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68,
+ 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42,
+ 0x4A, 0x5E, 0xC1, 0xE0 };
+
+const byte Twofish::Q1[256] = {
+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B,
+ 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B,
+ 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54,
+ 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7,
+ 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF,
+ 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D,
+ 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21,
+ 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E,
+ 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44,
+ 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B,
+ 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56,
+ 0x55, 0x09, 0xBE, 0x91 };
+
+const byte Twofish::RS[32] = {
+ 0x01, 0xA4, 0x02, 0xA4, 0xA4, 0x56, 0xA1, 0x55, 0x55, 0x82, 0xFC, 0x87,
+ 0x87, 0xF3, 0xC1, 0x5A, 0x5A, 0x1E, 0x47, 0x58, 0x58, 0xC6, 0xAE, 0xDB,
+ 0xDB, 0x68, 0x3D, 0x9E, 0x9E, 0xE5, 0x19, 0x03 };
+
+const byte Twofish::EXP_TO_POLY[255] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2,
+ 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03,
+ 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6,
+ 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A,
+ 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63,
+ 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C,
+ 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07,
+ 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88,
+ 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12,
+ 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7,
+ 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C,
+ 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8,
+ 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25,
+ 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A,
+ 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE,
+ 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC,
+ 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E,
+ 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92,
+ 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89,
+ 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB,
+ 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1,
+ 0x8F, 0x53, 0xA6 };
+
+const byte Twofish::POLY_TO_EXP[255] = {
+ 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19,
+ 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A,
+ 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C,
+ 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B,
+ 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47,
+ 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D,
+ 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8,
+ 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C,
+ 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83,
+ 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48,
+ 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26,
+ 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E,
+ 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3,
+ 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9,
+ 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A,
+ 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D,
+ 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75,
+ 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84,
+ 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64,
+ 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49,
+ 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF,
+ 0x85, 0xC8, 0xA1 };
+
+const u32bit Twofish::MDS0[256] = {
+ 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B,
+ 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B,
+ 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32,
+ 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
+ 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA,
+ 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B,
+ 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1,
+ 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
+ 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490,
+ 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154,
+ 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0,
+ 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
+ 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228,
+ 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7,
+ 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3,
+ 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
+ 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477,
+ 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF,
+ 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C,
+ 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
+ 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA,
+ 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D,
+ 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72,
+ 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
+ 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76,
+ 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321,
+ 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39,
+ 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
+ 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D,
+ 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E,
+ 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5,
+ 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
+ 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7,
+ 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544,
+ 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E,
+ 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
+ 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A,
+ 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B,
+ 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2,
+ 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
+ 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504,
+ 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756,
+ 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 };
+
+const u32bit Twofish::MDS1[256] = {
+ 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252,
+ 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A,
+ 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020,
+ 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
+ 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444,
+ 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424,
+ 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A,
+ 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
+ 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383,
+ 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A,
+ 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9,
+ 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
+ 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1,
+ 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898,
+ 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414,
+ 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
+ 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1,
+ 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989,
+ 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5,
+ 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
+ 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E,
+ 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E,
+ 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202,
+ 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
+ 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565,
+ 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A,
+ 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808,
+ 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
+ 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A,
+ 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969,
+ 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505,
+ 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
+ 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D,
+ 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343,
+ 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF,
+ 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
+ 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F,
+ 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646,
+ 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6,
+ 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
+ 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A,
+ 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7,
+ 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 };
+
+const u32bit Twofish::MDS2[256] = {
+ 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B,
+ 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F,
+ 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A,
+ 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
+ 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70,
+ 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3,
+ 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB,
+ 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
+ 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4,
+ 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41,
+ 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C,
+ 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
+ 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622,
+ 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18,
+ 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035,
+ 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
+ 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84,
+ 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E,
+ 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F,
+ 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
+ 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558,
+ 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40,
+ 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA,
+ 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
+ 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF,
+ 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773,
+ 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D,
+ 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
+ 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C,
+ 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19,
+ 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086,
+ 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
+ 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74,
+ 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755,
+ 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691,
+ 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
+ 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4,
+ 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53,
+ 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E,
+ 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
+ 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705,
+ 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7,
+ 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF };
+
+const u32bit Twofish::MDS3[256] = {
+ 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98,
+ 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866,
+ 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643,
+ 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
+ 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9,
+ 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C,
+ 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3,
+ 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
+ 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F,
+ 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25,
+ 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF,
+ 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
+ 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4,
+ 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E,
+ 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA,
+ 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
+ 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12,
+ 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A,
+ 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D,
+ 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
+ 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A,
+ 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C,
+ 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B,
+ 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
+ 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B,
+ 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3,
+ 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE,
+ 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
+ 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85,
+ 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA,
+ 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E,
+ 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
+ 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33,
+ 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC,
+ 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718,
+ 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
+ 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8,
+ 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872,
+ 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882,
+ 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
+ 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10,
+ 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6,
+ 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 };
+
+}
diff --git a/botan/src/block/twofish/twofish.cpp b/botan/src/block/twofish/twofish.cpp
new file mode 100644
index 0000000..9784b00
--- /dev/null
+++ b/botan/src/block/twofish/twofish.cpp
@@ -0,0 +1,218 @@
+/*
+* Twofish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/twofish.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* Twofish Encryption
+*/
+void Twofish::enc(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0) ^ round_key[0];
+ u32bit B = load_le<u32bit>(in, 1) ^ round_key[1];
+ u32bit C = load_le<u32bit>(in, 2) ^ round_key[2];
+ u32bit D = load_le<u32bit>(in, 3) ^ round_key[3];
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ u32bit X, Y;
+
+ X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^
+ SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)];
+ Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^
+ SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)];
+ X += Y;
+ Y += X + round_key[2*j + 9];
+ X += round_key[2*j + 8];
+
+ C = rotate_right(C ^ X, 1);
+ D = rotate_left(D, 1) ^ Y;
+
+ X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^
+ SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)];
+ Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^
+ SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)];
+ X += Y;
+ Y += X + round_key[2*j + 11];
+ X += round_key[2*j + 10];
+
+ A = rotate_right(A ^ X, 1);
+ B = rotate_left(B, 1) ^ Y;
+ }
+
+ C ^= round_key[4];
+ D ^= round_key[5];
+ A ^= round_key[6];
+ B ^= round_key[7];
+
+ store_le(out, C, D, A, B);
+ }
+
+/*
+* Twofish Decryption
+*/
+void Twofish::dec(const byte in[], byte out[]) const
+ {
+ u32bit A = load_le<u32bit>(in, 0) ^ round_key[4];
+ u32bit B = load_le<u32bit>(in, 1) ^ round_key[5];
+ u32bit C = load_le<u32bit>(in, 2) ^ round_key[6];
+ u32bit D = load_le<u32bit>(in, 3) ^ round_key[7];
+
+ for(u32bit j = 0; j != 16; j += 2)
+ {
+ u32bit X, Y;
+
+ X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^
+ SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)];
+ Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^
+ SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)];
+ X += Y;
+ Y += X + round_key[39 - 2*j];
+ X += round_key[38 - 2*j];
+
+ C = rotate_left(C, 1) ^ X;
+ D = rotate_right(D ^ Y, 1);
+
+ X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^
+ SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)];
+ Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^
+ SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)];
+ X += Y;
+ Y += X + round_key[37 - 2*j];
+ X += round_key[36 - 2*j];
+
+ A = rotate_left(A, 1) ^ X;
+ B = rotate_right(B ^ Y, 1);
+ }
+
+ C ^= round_key[0];
+ D ^= round_key[1];
+ A ^= round_key[2];
+ B ^= round_key[3];
+
+ store_le(out, C, D, A, B);
+ }
+
+/*
+* Twofish Key Schedule
+*/
+void Twofish::key_schedule(const byte key[], u32bit length)
+ {
+ SecureBuffer<byte, 16> S;
+
+ for(u32bit j = 0; j != length; ++j)
+ rs_mul(S + 4*(j/8), key[j], j);
+
+ if(length == 16)
+ {
+ for(u32bit j = 0; j != 256; ++j)
+ {
+ SBox0[j] = MDS0[Q0[Q0[j]^S[ 0]]^S[ 4]];
+ SBox1[j] = MDS1[Q0[Q1[j]^S[ 1]]^S[ 5]];
+ SBox2[j] = MDS2[Q1[Q0[j]^S[ 2]]^S[ 6]];
+ SBox3[j] = MDS3[Q1[Q1[j]^S[ 3]]^S[ 7]];
+ }
+ for(u32bit j = 0; j != 40; j += 2)
+ {
+ u32bit X = MDS0[Q0[Q0[j ]^key[ 8]]^key[ 0]] ^
+ MDS1[Q0[Q1[j ]^key[ 9]]^key[ 1]] ^
+ MDS2[Q1[Q0[j ]^key[10]]^key[ 2]] ^
+ MDS3[Q1[Q1[j ]^key[11]]^key[ 3]];
+ u32bit Y = MDS0[Q0[Q0[j+1]^key[12]]^key[ 4]] ^
+ MDS1[Q0[Q1[j+1]^key[13]]^key[ 5]] ^
+ MDS2[Q1[Q0[j+1]^key[14]]^key[ 6]] ^
+ MDS3[Q1[Q1[j+1]^key[15]]^key[ 7]];
+ Y = rotate_left(Y, 8); X += Y; Y += X;
+ round_key[j] = X; round_key[j+1] = rotate_left(Y, 9);
+ }
+ }
+ else if(length == 24)
+ {
+ for(u32bit j = 0; j != 256; ++j)
+ {
+ SBox0[j] = MDS0[Q0[Q0[Q1[j]^S[ 0]]^S[ 4]]^S[ 8]];
+ SBox1[j] = MDS1[Q0[Q1[Q1[j]^S[ 1]]^S[ 5]]^S[ 9]];
+ SBox2[j] = MDS2[Q1[Q0[Q0[j]^S[ 2]]^S[ 6]]^S[10]];
+ SBox3[j] = MDS3[Q1[Q1[Q0[j]^S[ 3]]^S[ 7]]^S[11]];
+ }
+ for(u32bit j = 0; j != 40; j += 2)
+ {
+ u32bit X = MDS0[Q0[Q0[Q1[j ]^key[16]]^key[ 8]]^key[ 0]] ^
+ MDS1[Q0[Q1[Q1[j ]^key[17]]^key[ 9]]^key[ 1]] ^
+ MDS2[Q1[Q0[Q0[j ]^key[18]]^key[10]]^key[ 2]] ^
+ MDS3[Q1[Q1[Q0[j ]^key[19]]^key[11]]^key[ 3]];
+ u32bit Y = MDS0[Q0[Q0[Q1[j+1]^key[20]]^key[12]]^key[ 4]] ^
+ MDS1[Q0[Q1[Q1[j+1]^key[21]]^key[13]]^key[ 5]] ^
+ MDS2[Q1[Q0[Q0[j+1]^key[22]]^key[14]]^key[ 6]] ^
+ MDS3[Q1[Q1[Q0[j+1]^key[23]]^key[15]]^key[ 7]];
+ Y = rotate_left(Y, 8); X += Y; Y += X;
+ round_key[j] = X; round_key[j+1] = rotate_left(Y, 9);
+ }
+ }
+ else if(length == 32)
+ {
+ for(u32bit j = 0; j != 256; ++j)
+ {
+ SBox0[j] = MDS0[Q0[Q0[Q1[Q1[j]^S[ 0]]^S[ 4]]^S[ 8]]^S[12]];
+ SBox1[j] = MDS1[Q0[Q1[Q1[Q0[j]^S[ 1]]^S[ 5]]^S[ 9]]^S[13]];
+ SBox2[j] = MDS2[Q1[Q0[Q0[Q0[j]^S[ 2]]^S[ 6]]^S[10]]^S[14]];
+ SBox3[j] = MDS3[Q1[Q1[Q0[Q1[j]^S[ 3]]^S[ 7]]^S[11]]^S[15]];
+ }
+ for(u32bit j = 0; j != 40; j += 2)
+ {
+ u32bit X = MDS0[Q0[Q0[Q1[Q1[j ]^key[24]]^key[16]]^key[ 8]]^key[ 0]] ^
+ MDS1[Q0[Q1[Q1[Q0[j ]^key[25]]^key[17]]^key[ 9]]^key[ 1]] ^
+ MDS2[Q1[Q0[Q0[Q0[j ]^key[26]]^key[18]]^key[10]]^key[ 2]] ^
+ MDS3[Q1[Q1[Q0[Q1[j ]^key[27]]^key[19]]^key[11]]^key[ 3]];
+ u32bit Y = MDS0[Q0[Q0[Q1[Q1[j+1]^key[28]]^key[20]]^key[12]]^key[ 4]] ^
+ MDS1[Q0[Q1[Q1[Q0[j+1]^key[29]]^key[21]]^key[13]]^key[ 5]] ^
+ MDS2[Q1[Q0[Q0[Q0[j+1]^key[30]]^key[22]]^key[14]]^key[ 6]] ^
+ MDS3[Q1[Q1[Q0[Q1[j+1]^key[31]]^key[23]]^key[15]]^key[ 7]];
+ Y = rotate_left(Y, 8); X += Y; Y += X;
+ round_key[j] = X; round_key[j+1] = rotate_left(Y, 9);
+ }
+ }
+ }
+
+/*
+* Do one column of the RS matrix multiplcation
+*/
+void Twofish::rs_mul(byte S[4], byte key, u32bit offset)
+ {
+ if(key)
+ {
+ byte X = POLY_TO_EXP[key - 1];
+
+ byte RS1 = RS[(4*offset ) % 32];
+ byte RS2 = RS[(4*offset+1) % 32];
+ byte RS3 = RS[(4*offset+2) % 32];
+ byte RS4 = RS[(4*offset+3) % 32];
+
+ S[0] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS1 - 1]) % 255];
+ S[1] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS2 - 1]) % 255];
+ S[2] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS3 - 1]) % 255];
+ S[3] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS4 - 1]) % 255];
+ }
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Twofish::clear() throw()
+ {
+ SBox0.clear();
+ SBox1.clear();
+ SBox2.clear();
+ SBox3.clear();
+ round_key.clear();
+ }
+
+}
diff --git a/botan/src/block/twofish/twofish.h b/botan/src/block/twofish/twofish.h
new file mode 100644
index 0000000..0640e32
--- /dev/null
+++ b/botan/src/block/twofish/twofish.h
@@ -0,0 +1,48 @@
+/*
+* Twofish
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TWOFISH_H__
+#define BOTAN_TWOFISH_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* Twofish
+*/
+class BOTAN_DLL Twofish : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Twofish"; }
+ BlockCipher* clone() const { return new Twofish; }
+ Twofish() : BlockCipher(16, 16, 32, 8) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+
+ static void rs_mul(byte[4], byte, u32bit);
+
+ static const u32bit MDS0[256];
+ static const u32bit MDS1[256];
+ static const u32bit MDS2[256];
+ static const u32bit MDS3[256];
+ static const byte Q0[256];
+ static const byte Q1[256];
+ static const byte RS[32];
+ static const byte EXP_TO_POLY[255];
+ static const byte POLY_TO_EXP[255];
+
+ SecureBuffer<u32bit, 256> SBox0, SBox1, SBox2, SBox3;
+ SecureBuffer<u32bit, 40> round_key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/block/xtea/info.txt b/botan/src/block/xtea/info.txt
new file mode 100644
index 0000000..0120a3b
--- /dev/null
+++ b/botan/src/block/xtea/info.txt
@@ -0,0 +1,10 @@
+realname "XTEA"
+
+define XTEA
+
+load_on auto
+
+<add>
+xtea.cpp
+xtea.h
+</add>
diff --git a/botan/src/block/xtea/xtea.cpp b/botan/src/block/xtea/xtea.cpp
new file mode 100644
index 0000000..5047f65
--- /dev/null
+++ b/botan/src/block/xtea/xtea.cpp
@@ -0,0 +1,64 @@
+/*
+* XTEA
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/xtea.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* XTEA Encryption
+*/
+void XTEA::enc(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1);
+
+ for(u32bit j = 0; j != 32; ++j)
+ {
+ L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j];
+ R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1];
+ }
+
+ store_be(out, L, R);
+ }
+
+/*
+* XTEA Decryption
+*/
+void XTEA::dec(const byte in[], byte out[]) const
+ {
+ u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1);
+
+ for(u32bit j = 0; j != 32; ++j)
+ {
+ R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j];
+ L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j];
+ }
+
+ store_be(out, L, R);
+ }
+
+/*
+* XTEA Key Schedule
+*/
+void XTEA::key_schedule(const byte key[], u32bit)
+ {
+ SecureBuffer<u32bit, 4> UK;
+ for(u32bit i = 0; i != 4; ++i)
+ UK[i] = load_be<u32bit>(key, i);
+
+ u32bit D = 0;
+ for(u32bit i = 0; i != 64; i += 2)
+ {
+ EK[i ] = D + UK[D % 4];
+ D += 0x9E3779B9;
+ EK[i+1] = D + UK[(D >> 11) % 4];
+ }
+ }
+
+}
diff --git a/botan/src/block/xtea/xtea.h b/botan/src/block/xtea/xtea.h
new file mode 100644
index 0000000..d9c6066
--- /dev/null
+++ b/botan/src/block/xtea/xtea.h
@@ -0,0 +1,34 @@
+/*
+* XTEA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XTEA_H__
+#define BOTAN_XTEA_H__
+
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* XTEA
+*/
+class BOTAN_DLL XTEA : public BlockCipher
+ {
+ public:
+ void clear() throw() { EK.clear(); }
+ std::string name() const { return "XTEA"; }
+ BlockCipher* clone() const { return new XTEA; }
+ XTEA() : BlockCipher(8, 16) {}
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ SecureBuffer<u32bit, 64> EK;
+ };
+
+}
+
+#endif
diff --git a/botan/src/build-data/arch/alpha.txt b/botan/src/build-data/arch/alpha.txt
new file mode 100644
index 0000000..60b2643
--- /dev/null
+++ b/botan/src/build-data/arch/alpha.txt
@@ -0,0 +1,31 @@
+realname "DEC Alpha"
+
+default_submodel alpha-ev4
+endian little
+
+<aliases>
+axp
+alphaaxp
+</aliases>
+
+<submodels>
+alpha-ev4
+alpha-ev5
+alpha-ev56
+alpha-pca56
+alpha-ev6
+alpha-ev67
+alpha-ev68
+alpha-ev7
+</submodels>
+
+<submodel_aliases>
+alphaev4 -> alpha-ev4
+alphaev5 -> alpha-ev5
+alphaev56 -> alpha-ev56
+alphapca56 -> alpha-pca56
+alphaev6 -> alpha-ev6
+alphaev67 -> alpha-ev67
+alphaev68 -> alpha-ev68
+alphaev7 -> alpha-ev7
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/amd64.txt b/botan/src/build-data/arch/amd64.txt
new file mode 100644
index 0000000..216588e
--- /dev/null
+++ b/botan/src/build-data/arch/amd64.txt
@@ -0,0 +1,27 @@
+realname "x86-64"
+
+default_submodel opteron
+
+endian little
+unaligned ok
+
+<aliases>
+x86-64
+x86_64 # for RPM
+</aliases>
+
+<submodels>
+opteron
+em64t
+core2
+</submodels>
+
+<submodel_aliases>
+core2duo -> core2
+intelcore2 -> core2
+intelcore2duo -> core2
+
+amdopteron -> opteron
+athlon64 -> opteron
+k8 -> opteron
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/arm.txt b/botan/src/build-data/arch/arm.txt
new file mode 100644
index 0000000..c6be4ad
--- /dev/null
+++ b/botan/src/build-data/arch/arm.txt
@@ -0,0 +1,23 @@
+realname "ARM"
+
+default_submodel arm2
+
+<submodels>
+arm2
+arm3
+arm6
+arm7
+arm8
+arm9
+strongarm
+strongarm110
+strongarm1100
+xscale
+</submodels>
+
+<submodel_aliases>
+sa110 -> strongarm110
+sa1100 -> strongarm1100
+strongarm1110 -> strongarm1100
+armv5tel -> xscale
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/hitachi-sh.txt b/botan/src/build-data/arch/hitachi-sh.txt
new file mode 100644
index 0000000..8e9f7ee
--- /dev/null
+++ b/botan/src/build-data/arch/hitachi-sh.txt
@@ -0,0 +1,11 @@
+realname "Hitachi SH"
+
+default_submodel hitachi-sh1
+
+<submodels>
+hitachi-sh1
+hitachi-sh2
+hitachi-sh3
+hitachi-sh3e
+hitachi-sh4
+</submodels>
diff --git a/botan/src/build-data/arch/hppa.txt b/botan/src/build-data/arch/hppa.txt
new file mode 100644
index 0000000..4cdd408
--- /dev/null
+++ b/botan/src/build-data/arch/hppa.txt
@@ -0,0 +1,17 @@
+realname "HP-PA"
+
+default_submodel hppa1.0
+
+<aliases>
+hp-pa
+parisc
+pa-risc
+hp-parisc
+hp-pa-risc
+</aliases>
+
+<submodels>
+hppa1.0
+hppa1.1
+hppa2.0
+</submodels>
diff --git a/botan/src/build-data/arch/ia32.txt b/botan/src/build-data/arch/ia32.txt
new file mode 100644
index 0000000..aafcf9a
--- /dev/null
+++ b/botan/src/build-data/arch/ia32.txt
@@ -0,0 +1,60 @@
+realname "IA-32"
+
+default_submodel i386
+
+endian little
+unaligned ok
+
+<aliases>
+x86
+ix86
+80x86
+i86pc # for Solaris
+</aliases>
+
+<submodels>
+i386
+i486
+i586
+i686
+pentium2
+pentium3
+pentium4
+pentium-m
+prescott
+k6
+athlon
+</submodels>
+
+<submodel_aliases>
+pentium -> i586
+pentiumpro -> i686
+pentium_pro -> i686
+pentium2 -> pentium2
+pentiumii -> pentium2
+pentium3 -> pentium3
+pentiumiii -> pentium3
+
+x86family5 -> i586
+x86family6 -> i686
+
+pentiumm -> pentium-m
+intelpentiumm -> pentium-m
+
+intelpentium4 -> pentium4
+
+duron -> athlon
+athlon-xp -> athlon
+k7 -> athlon
+
+p2 -> i686
+p3 -> i686
+p4 -> pentium4
+
+intelcput2250 -> prescott
+intelcput2300 -> prescott
+intelcput2400 -> prescott
+intelcput2500 -> prescott
+intelcput2600 -> prescott
+intelcput2700 -> prescott
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/ia64.txt b/botan/src/build-data/arch/ia64.txt
new file mode 100644
index 0000000..7ca84c0
--- /dev/null
+++ b/botan/src/build-data/arch/ia64.txt
@@ -0,0 +1,15 @@
+realname "IA-64"
+
+# This is safe: only affects tuning, not ISA
+default_submodel itanium2
+
+<aliases>
+merced
+itanium
+</aliases>
+
+<submodels>
+itanium1
+itanium2
+mckinley
+</submodels>
diff --git a/botan/src/build-data/arch/m68k.txt b/botan/src/build-data/arch/m68k.txt
new file mode 100644
index 0000000..27f246a
--- /dev/null
+++ b/botan/src/build-data/arch/m68k.txt
@@ -0,0 +1,15 @@
+realname "Motorola 680x0"
+
+default_submodel 68020
+
+<aliases>
+680x0
+68k
+</aliases>
+
+<submodels>
+68020
+68030
+68040
+68060
+</submodels>
diff --git a/botan/src/build-data/arch/mips32.txt b/botan/src/build-data/arch/mips32.txt
new file mode 100644
index 0000000..9846c8f
--- /dev/null
+++ b/botan/src/build-data/arch/mips32.txt
@@ -0,0 +1,22 @@
+realname "MIPS"
+
+default_submodel r3000
+
+<aliases>
+mips
+mipsel # For Debian
+</aliases>
+
+<submodels>
+r3000
+r6000
+</submodels>
+
+<submodel_aliases>
+r3k -> r3000
+r6k -> r6000
+
+# These are for RPM
+mipsbe -> r3000
+mipsle -> r3000
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/mips64.txt b/botan/src/build-data/arch/mips64.txt
new file mode 100644
index 0000000..dbb49d0
--- /dev/null
+++ b/botan/src/build-data/arch/mips64.txt
@@ -0,0 +1,22 @@
+realname "MIPS64"
+
+default_submodel r4400
+
+<submodels>
+r4000
+r4100
+r4300
+r4400
+r4600
+r4560
+r5000
+r8000
+r10000
+</submodels>
+
+<submodel_aliases>
+r4k -> r4000
+r5k -> r5000
+r8k -> r8000
+r10k -> r10000
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/ppc.txt b/botan/src/build-data/arch/ppc.txt
new file mode 100644
index 0000000..16112f3
--- /dev/null
+++ b/botan/src/build-data/arch/ppc.txt
@@ -0,0 +1,24 @@
+realname "PowerPC"
+
+endian big
+
+default_submodel ppc604
+
+<aliases>
+powerpc
+</aliases>
+
+<submodel_aliases>
+g3 -> ppc740
+g4 -> ppc7450
+</submodel_aliases>
+
+<submodels>
+ppc601
+ppc603
+ppc604
+ppc740
+ppc750
+ppc7400
+ppc7450
+</submodels>
diff --git a/botan/src/build-data/arch/ppc64.txt b/botan/src/build-data/arch/ppc64.txt
new file mode 100644
index 0000000..7c8944f
--- /dev/null
+++ b/botan/src/build-data/arch/ppc64.txt
@@ -0,0 +1,26 @@
+realname "PowerPC 64"
+
+endian big
+
+default_submodel power4
+
+<aliases>
+powerpc64
+</aliases>
+
+<submodel_aliases>
+g5 -> ppc970
+</submodel_aliases>
+
+<submodels>
+rs64a
+ppc970
+power3
+power4
+power5
+cellppu
+</submodels>
+
+<submodel_aliases>
+cellbroadbandengine -> cellppu
+</submodel_aliases>
diff --git a/botan/src/build-data/arch/s390.txt b/botan/src/build-data/arch/s390.txt
new file mode 100644
index 0000000..392f513
--- /dev/null
+++ b/botan/src/build-data/arch/s390.txt
@@ -0,0 +1,7 @@
+realname "S/390 31-bit"
+
+default_submodel s390
+
+<submodels>
+s390
+</submodels>
diff --git a/botan/src/build-data/arch/s390x.txt b/botan/src/build-data/arch/s390x.txt
new file mode 100644
index 0000000..49fb0bd
--- /dev/null
+++ b/botan/src/build-data/arch/s390x.txt
@@ -0,0 +1,7 @@
+realname "S/390 64-bit"
+
+default_submodel s390x
+
+<submodels>
+s390x
+</submodels>
diff --git a/botan/src/build-data/arch/sparc32.txt b/botan/src/build-data/arch/sparc32.txt
new file mode 100644
index 0000000..6b752df
--- /dev/null
+++ b/botan/src/build-data/arch/sparc32.txt
@@ -0,0 +1,34 @@
+realname "SPARC"
+
+# V7 doesn't have integer multiply, so it will be bitterly slow for some things
+# (especially BigInt). Also, it's fairly rare nowadays, so we default to V8.
+default_submodel sparc32-v8
+
+endian big
+
+<aliases>
+sparc
+</aliases>
+
+<submodels>
+sparc32-v7
+sparc32-v8
+sparc32-v9
+</submodels>
+
+<submodel_aliases>
+cypress -> sparc32-v7
+supersparc -> sparc32-v8
+hypersparc -> sparc32-v8
+microsparc -> sparc32-v8
+sparclite -> sparc32-v8
+
+sparcv7 -> sparc32-v7
+sparcv8 -> sparc32-v8
+sparcv9 -> sparc32-v9
+
+sparc-v7 -> sparc32-v7
+sparc-v8 -> sparc32-v8
+sparc-v9 -> sparc32-v9
+</submodel_aliases>
+
diff --git a/botan/src/build-data/arch/sparc64.txt b/botan/src/build-data/arch/sparc64.txt
new file mode 100644
index 0000000..c0575ef
--- /dev/null
+++ b/botan/src/build-data/arch/sparc64.txt
@@ -0,0 +1,15 @@
+realname "SPARC64"
+
+default_submodel sparc64-ultra
+
+<submodels>
+sparc64-ultra
+sparc64-ultra2
+sparc64-ultra3
+</submodels>
+
+<submodel_aliases>
+ultrasparc -> sparc64-ultra
+ultrasparc2 -> sparc64-ultra2
+ultrasparc3 -> sparc64-ultra3
+</submodel_aliases>
diff --git a/botan/src/build-data/botan-config.in b/botan/src/build-data/botan-config.in
new file mode 100644
index 0000000..f3fa3db
--- /dev/null
+++ b/botan/src/build-data/botan-config.in
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# For normal builds:
+guess_prefix=`dirname \`dirname $0\``
+includedir=%{includedir}
+libdir=%{libdir}
+
+# For workspace builds:
+#guess_prefix=`dirname $0`
+#includedir=build/include
+#libdir=
+
+install_prefix=%{prefix}
+prefix=
+
+usage()
+{
+ echo "$0 [--prefix[=DIR]] [--version] [--libs] [--cflags]"
+ exit 1
+}
+
+if test $# -eq 0; then
+ usage
+fi
+
+if test `echo $guess_prefix | cut -c 1` = "/"; then
+ prefix=$guess_prefix
+else
+ prefix=$install_prefix
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+ case "$1" in
+ --prefix=*)
+ prefix=$optarg
+ ;;
+ --prefix)
+ echo $prefix
+ ;;
+ --version)
+ echo %{version}
+ exit 0
+ ;;
+ --cflags)
+ if [ $prefix != "/usr" -a $prefix != "/usr/local" ]
+ then
+ echo -I$prefix/$includedir
+ fi
+ ;;
+ --libs)
+ if [ $prefix != "/usr" -a $prefix != "/usr/local" ]
+ then
+ echo -L$prefix/$libdir -lbotan %{link_to}
+ else
+ echo -lbotan %{link_to}
+ fi
+ ;;
+ *)
+ usage
+ ;;
+ esac
+ shift
+done
+
+exit 0
diff --git a/botan/src/build-data/botan.doxy.in b/botan/src/build-data/botan.doxy.in
new file mode 100644
index 0000000..87d6e58
--- /dev/null
+++ b/botan/src/build-data/botan.doxy.in
@@ -0,0 +1,233 @@
+# Doxyfile 1.5.4
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = Botan
+PROJECT_NUMBER = %{version}
+OUTPUT_DIRECTORY = doc/doxygen
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = YES
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = YES
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = NO
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = src
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS =
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = YES
+STRIP_CODE_COMMENTS = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+HTML_DYNAMIC_SECTIONS = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/botan/src/build-data/botan.pc.in b/botan/src/build-data/botan.pc.in
new file mode 100644
index 0000000..70ed65d
--- /dev/null
+++ b/botan/src/build-data/botan.pc.in
@@ -0,0 +1,12 @@
+prefix=%{prefix}
+exec_prefix=${prefix}
+libdir=${prefix}/%{libdir}
+includedir=${prefix}/include
+
+Name: Botan
+Description: Multi-platform C++ crypto library
+Version: %{version}
+
+Libs: -L${libdir} -lbotan
+Libs.private: %{link_to}
+Cflags: -I${includedir}
diff --git a/botan/src/build-data/buildh.in b/botan/src/build-data/buildh.in
new file mode 100644
index 0000000..e4ab0f4
--- /dev/null
+++ b/botan/src/build-data/buildh.in
@@ -0,0 +1,66 @@
+
+#ifndef BOTAN_BUILD_CONFIG_H__
+#define BOTAN_BUILD_CONFIG_H__
+
+/* This file was automatically generated %{timestamp} UTC */
+
+#define BOTAN_VERSION_MAJOR %{version_major}
+#define BOTAN_VERSION_MINOR %{version_minor}
+#define BOTAN_VERSION_PATCH %{version_patch}
+
+#ifndef BOTAN_DLL
+ #define BOTAN_DLL %{dll_export_flags}
+#endif
+
+/* Chunk sizes */
+#define BOTAN_DEFAULT_BUFFER_SIZE 4096
+#define BOTAN_MEM_POOL_CHUNK_SIZE 64*1024
+
+/* BigInt toggles */
+#define BOTAN_MP_WORD_BITS %{mp_bits}
+#define BOTAN_KARAT_MUL_THRESHOLD 32
+#define BOTAN_KARAT_SQR_THRESHOLD 32
+#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64
+
+/* PK key consistency checking toggles */
+#define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD 1
+#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1
+
+/* Should we use GCC-style inline assembler? */
+#if !defined(BOTAN_USE_GCC_INLINE_ASM) && defined(__GNUG__)
+ #define BOTAN_USE_GCC_INLINE_ASM 1
+#endif
+
+#ifndef BOTAN_USE_GCC_INLINE_ASM
+ #define BOTAN_USE_GCC_INLINE_ASM 0
+#endif
+
+/* Target identification and feature test macros */
+%{target_os_defines}
+
+%{target_cpu_defines}
+
+%{target_compiler_defines}
+
+/* Module definitions */
+%{module_defines}
+
+/* Local configuration options */
+%{local_config}
+
+/*
+%{user}@%{hostname} ran '%{command_line}'
+
+Target
+-------
+Compiler: %{cc} %{lib_opt} %{mach_opt}
+Arch: %{submodel}/%{arch}
+OS: %{os}
+
+Modules
+-------
+%{mod_list}
+*/
+
+#endif
diff --git a/botan/src/build-data/cc/bcc.txt b/botan/src/build-data/cc/bcc.txt
new file mode 100644
index 0000000..df09daf
--- /dev/null
+++ b/botan/src/build-data/cc/bcc.txt
@@ -0,0 +1,31 @@
+realname "Borland C++"
+
+binary_name "bcc32"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O2"
+check_opt_flags "-O2"
+debug_flags ""
+no_debug_flags ""
+lang_flags "-tWR -tWM -tWC"
+warning_flags "-w"
+
+dll_import_flags ""
+dll_export_flags ""
+
+ar_command "tlib /C /P256"
+
+makefile_style nmake
+
+<mach_opt>
+i486 -> "/G4"
+i586 -> "/G5"
+i686 -> "/G6"
+athlon -> "/G6"
+pentium4 -> "/G6"
+</mach_opt>
diff --git a/botan/src/build-data/cc/compaq.txt b/botan/src/build-data/cc/compaq.txt
new file mode 100644
index 0000000..66d3a52
--- /dev/null
+++ b/botan/src/build-data/cc/compaq.txt
@@ -0,0 +1,29 @@
+realname "Compaq C++"
+
+binary_name "cxx"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+# -O3 and up seem to be unhappy with Botan
+lib_opt_flags "-O2"
+check_opt_flags "-O2"
+debug_flags "-g"
+no_debug_flags ""
+lang_flags "-std ansi -D__USE_STD_IOSTREAM"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -shared -soname $(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+alpha -> "-arch=SUBMODEL" alpha-
+</mach_opt>
diff --git a/botan/src/build-data/cc/ekopath.txt b/botan/src/build-data/cc/ekopath.txt
new file mode 100644
index 0000000..ca24710
--- /dev/null
+++ b/botan/src/build-data/cc/ekopath.txt
@@ -0,0 +1,40 @@
+realname "PathScale EKOPath C++"
+
+binary_name "pathCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O3 -OPT:Ofast:alias=disjoint"
+check_opt_flags "-O2"
+lang_flags "-D_REENTRANT -ansi -Wno-long-long"
+warning_flags "-W -Wall"
+
+ar_command "pathCC -ar -o"
+
+shared_flags "-fPIC"
+debug_flags "-g"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+athlon -> "-mcpu=athlon"
+pentium4 -> "-mcpu=pentium4"
+
+opteron -> "-mcpu=opteron"
+em64t -> "-mcpu=em64t"
+core2 -> "-mcpu=core"
+
+ia32 -> "-mcpu=anyx86"
+amd64 -> "-mcpu=athlon64"
+</mach_opt>
diff --git a/botan/src/build-data/cc/gcc.txt b/botan/src/build-data/cc/gcc.txt
new file mode 100644
index 0000000..978ed6d
--- /dev/null
+++ b/botan/src/build-data/cc/gcc.txt
@@ -0,0 +1,89 @@
+realname "GNU C++"
+
+binary_name "g++"
+
+compiler_has_tr1 yes
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lang_flags "-D_REENTRANT -ansi -Wno-long-long"
+warning_flags "-W -Wall"
+#warning_flags "-Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter"
+
+lib_opt_flags "-O2 -finline-functions"
+check_opt_flags "-O2"
+shared_flags "-fPIC"
+debug_flags "-g"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+# The default works for GNU ld and several other Unix linkers
+default -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)"
+
+# AIX doesn't seem to have soname support (weird...)
+aix -> "$(CXX) -shared -fPIC"
+
+darwin -> "$(CXX) -dynamiclib -fPIC -install_name $(SONAME)"
+hpux -> "$(CXX) -shared -fPIC -Wl,+h,$(SONAME)"
+solaris -> "$(CXX) -shared -fPIC -Wl,-h,$(SONAME)"
+# Gotta use ld directly on BeOS, their GCC is busted
+beos -> "ld -shared -h $(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+# Specializations first (they don't need to be, just clearer)
+i386 -> "-mtune=i686 -momit-leaf-frame-pointer"
+r10000 -> "-mips4"
+alpha-ev67 -> "-mcpu=ev6" # FIXME: GCC 3.1 and on has -march=ev67
+alpha-ev68 -> "-mcpu=ev6"
+alpha-ev7 -> "-mcpu=ev6"
+ppc601 -> "-mpowerpc -mcpu=601"
+sparc64-ultra3 -> "-mcpu=v9 -mtune=ultrasparc3"
+
+em64t -> "-march=nocona -momit-leaf-frame-pointer"
+cellppu -> ""
+
+# Default family options (SUBMODEL is substitued with the real submodel)
+# Anything after the quotes is what should be *removed* from the submodel name
+# before it's put into SUBMODEL.
+alpha -> "-mcpu=SUBMODEL" alpha-
+amd64 -> "-march=SUBMODEL -momit-leaf-frame-pointer"
+arm -> "-mcpu=SUBMODEL"
+ia32 -> "-march=SUBMODEL -momit-leaf-frame-pointer"
+ia64 -> "-mtune=SUBMODEL"
+hppa -> "-march=SUBMODEL" hppa
+m68k -> "-mSUBMODEL"
+hitachi-sh -> "-mSUBMODEL" hitachi-sh
+sparc32 -> "-mcpu=SUBMODEL -Wa,-xarch=v8plus" sparc32-
+sparc64 -> "-mcpu=v9 -mtune=ultrasparc"
+mips32 -> "-mips1 -mcpu=SUBMODEL" mips32-
+mips64 -> "-mips3 -mcpu=SUBMODEL" mips64-
+ppc -> "-mcpu=SUBMODEL" ppc
+ppc64 -> "-mcpu=SUBMODEL" ppc
+</mach_opt>
+
+# Note that the 'linking' bit means "use this for both compiling *and* linking"
+<mach_abi_linking>
+amd64 -> "-m64"
+mips64 -> "-mabi=64"
+s390 -> "-m31"
+s390x -> "-m64"
+sparc32 -> "-m32 -mno-app-regs"
+sparc64 -> "-m64 -mno-app-regs"
+ppc64 -> "-m64"
+
+# This should probably be used on most/all targets, but the docs are incomplete
+openbsd -> "-pthread"
+freebsd -> "-pthread"
+dragonfly -> "-pthread"
+netbsd -> "-pthread -D_NETBSD_SOURCE"
+qnx -> "-fexceptions -D_QNX_SOURCE"
+</mach_abi_linking>
diff --git a/botan/src/build-data/cc/hpcc.txt b/botan/src/build-data/cc/hpcc.txt
new file mode 100644
index 0000000..284e92c
--- /dev/null
+++ b/botan/src/build-data/cc/hpcc.txt
@@ -0,0 +1,32 @@
+realname "HP-UX C++"
+
+binary_name "aCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "+O2"
+check_opt_flags "+O2"
+debug_flags "-g"
+no_debug_flags ""
+lang_flags "-AA -ext +eh -z"
+warning_flags "" # +w
+shared_flags "+Z"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<mach_abi_linking>
+hppa1.0 -> "+DAportable"
+hppa1.1 -> "+DA1.1"
+hppa2.0 -> "+DA2.0W"
+</mach_abi_linking>
+
+<so_link_flags>
+default -> "$(CXX) +Z -b -Wl,+h,$(SONAME)" # Documented in cc(1), but not CC(1) (?)
+</so_link_flags>
diff --git a/botan/src/build-data/cc/icc.txt b/botan/src/build-data/cc/icc.txt
new file mode 100644
index 0000000..7d8e968
--- /dev/null
+++ b/botan/src/build-data/cc/icc.txt
@@ -0,0 +1,35 @@
+realname "Intel C++"
+
+binary_name "icpc"
+
+compiler_has_tr1 yes
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O2 -ip -unroll"
+check_opt_flags "-O2"
+debug_flags "-g"
+no_debug_flags "-fomit-frame-pointer"
+lang_flags ""
+warning_flags "-w1"
+shared_flags "-fPIC"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<mach_opt>
+pentium3 -> "-march=pentium3"
+pentium4 -> "-march=pentium4"
+pentium-m -> "-march=pentium3"
+core2 -> "-march=core2"
+</mach_opt>
+
+<so_link_flags>
+default -> "$(CXX) -fPIC -shared"
+</so_link_flags>
diff --git a/botan/src/build-data/cc/kai.txt b/botan/src/build-data/cc/kai.txt
new file mode 100644
index 0000000..8585e54
--- /dev/null
+++ b/botan/src/build-data/cc/kai.txt
@@ -0,0 +1,30 @@
+realname "KAI C++"
+
+binary_name "KCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+ar_command "KCC -o"
+
+lib_opt_flags "+K3 --inline_auto_space_time=65 --abstract_pointer"
+check_opt_flags "+K3"
+lang_flags "-D__KAI_STRICT"
+debug_flags "-g"
+no_debug_flags ""
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) --soname $(SONAME)"
+</so_link_flags>
+
+<mach_abi_linking>
+all -> "--one_per"
+</mach_abi_linking>
diff --git a/botan/src/build-data/cc/mipspro.txt b/botan/src/build-data/cc/mipspro.txt
new file mode 100644
index 0000000..b75fc4f
--- /dev/null
+++ b/botan/src/build-data/cc/mipspro.txt
@@ -0,0 +1,42 @@
+realname "SGI MIPSPro C++"
+
+binary_name "CC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O3 -OPT:alias=TYPED"
+check_opt_flags "-O3 -OPT:alias=TYPED"
+debug_flags "-g3"
+no_debug_flags ""
+shared_flags "-KPIC"
+lang_flags "-ansi -LANG:ansi-for-init-scope=ON"
+# Disabled, because, while my code is fine, it warns about a lot of it's own
+# headers <g>
+#warning_flags "-fullwarn"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+mips32 -> "-mips1"
+mips64 -> "-mips3"
+
+mips64-r5000 -> "-mips4 -r5000"
+mips64-r8000 -> "-mips4 -r8000"
+mips64-r10000 -> "-mips4 -r10000"
+</mach_opt>
+
+<mach_abi_linking>
+mips32 -> "-n32"
+mips64 -> "-64"
+</mach_abi_linking>
diff --git a/botan/src/build-data/cc/msvc.txt b/botan/src/build-data/cc/msvc.txt
new file mode 100644
index 0000000..68e4517
--- /dev/null
+++ b/botan/src/build-data/cc/msvc.txt
@@ -0,0 +1,27 @@
+realname "Visual C++"
+
+binary_name "cl.exe"
+
+compile_option "/nologo /c "
+output_to_option "/Fo"
+add_include_dir_option "/I"
+add_lib_dir_option "-L"
+add_lib_option ""
+
+lib_opt_flags "/O2"
+check_opt_flags "/O2"
+debug_flags "/Zi"
+no_debug_flags ""
+lang_flags "/EHsc /GR /D_CONSOLE"
+warning_flags ""
+
+dll_import_flags "__declspec(dllimport)"
+dll_export_flags "__declspec(dllexport)"
+
+ar_command "lib"
+
+makefile_style nmake
+
+<so_link_flags>
+default -> "link /DLL"
+</so_link_flags>
diff --git a/botan/src/build-data/cc/open64.txt b/botan/src/build-data/cc/open64.txt
new file mode 100644
index 0000000..b7c1e9e
--- /dev/null
+++ b/botan/src/build-data/cc/open64.txt
@@ -0,0 +1,30 @@
+realname "Open64"
+
+binary_name "openCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O3 -OPT:alias=TYPED"
+check_opt_flags "-O3 -OPT:alias=TYPED"
+debug_flags "-g3"
+no_debug_flags "-fomit-frame-pointer"
+shared_flags "-fPIC"
+lang_flags "-ansi -LANG:ansi-for-init-scope=ON"
+warning_flags "-Wall -W"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
+</so_link_flags>
+
+<mach_abi_linking>
+amd64 -> "-m64"
+</mach_abi_linking>
diff --git a/botan/src/build-data/cc/pgi.txt b/botan/src/build-data/cc/pgi.txt
new file mode 100644
index 0000000..35f4664
--- /dev/null
+++ b/botan/src/build-data/cc/pgi.txt
@@ -0,0 +1,31 @@
+realname "Portland Group C++"
+
+binary_name "pgCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-fast -Minline"
+check_opt_flags "-fast"
+shared_flags "-fPIC"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+linux -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)"
+solaris -> "$(CXX) -G -fPIC -Wl,-h,$(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+i586 -> "-tp p5"
+i686 -> "-tp p6"
+athlon -> "-tp k7"
+pentium4 -> "-tp p6"
+ia32 -> "-tp px"
+</mach_opt>
diff --git a/botan/src/build-data/cc/sgipro64.txt b/botan/src/build-data/cc/sgipro64.txt
new file mode 100644
index 0000000..28132ff
--- /dev/null
+++ b/botan/src/build-data/cc/sgipro64.txt
@@ -0,0 +1,30 @@
+realname "SGI Pro64"
+
+binary_name "sgiCC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O3 -OPT:alias=TYPED"
+check_opt_flags "-O3 -OPT:alias=TYPED"
+debug_flags "-g3"
+no_debug_flags ""
+shared_flags "-KPIC"
+lang_flags "-ansi -LANG:ansi-for-init-scope=ON"
+warning_flags "-Wall -W"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+
+</mach_opt>
diff --git a/botan/src/build-data/cc/sunwspro.txt b/botan/src/build-data/cc/sunwspro.txt
new file mode 100644
index 0000000..e1bc0b2
--- /dev/null
+++ b/botan/src/build-data/cc/sunwspro.txt
@@ -0,0 +1,47 @@
+realname "Sun Workshop Pro C++"
+
+binary_name "CC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+# The compiler supports up to -xO5, but anything higher than -xO2 causes
+# incorrect results, infinite loops, other badness. :(
+lib_opt_flags "-xO2"
+check_opt_flags "-xO2"
+debug_flags "-g"
+no_debug_flags ""
+shared_flags "-KPIC"
+warning_flags "+w"
+lang_flags "+p -D__EXTENSIONS__"
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<so_link_flags>
+default -> "$(CXX) -G -h$(SONAME)"
+</so_link_flags>
+
+<mach_opt>
+i386 -> "-xtarget=486"
+i486 -> "-xtarget=486"
+i586 -> "-xtarget=pentium"
+i686 -> "-xtarget=pentium_pro"
+pentium4 -> "-xtarget=pentium_pro"
+k6 -> "-xtarget=pentium"
+
+sparc32-v9 -> "-xchip=ultra -xarch=v8"
+
+sparc32 -> "-xchip=ultra -xarch=SUBMODEL" sparc32-
+sparc64 -> "-xchip=SUBMODEL" sparc64-
+</mach_opt>
+
+<mach_abi_linking>
+sparc64 -> "-xarch=v9"
+amd64 -> "-m64"
+</mach_abi_linking>
diff --git a/botan/src/build-data/cc/xlc.txt b/botan/src/build-data/cc/xlc.txt
new file mode 100644
index 0000000..64b8884
--- /dev/null
+++ b/botan/src/build-data/cc/xlc.txt
@@ -0,0 +1,29 @@
+realname "IBM XL C/C++"
+
+binary_name "xlC"
+
+compile_option "-c "
+output_to_option "-o "
+add_include_dir_option "-I"
+add_lib_dir_option "-L"
+add_lib_option "-l"
+
+lib_opt_flags "-O2"
+check_opt_flags "-O2"
+lang_flags ""
+debug_flags "-g"
+no_debug_flags ""
+
+dll_import_flags ""
+dll_export_flags ""
+
+makefile_style unix
+
+<mach_opt>
+cellppu -> "-qarch=cell"
+ppc970 -> "-qarch=ppc970"
+power4 -> "-qarch=pwr4"
+power5 -> "-qarch=pwr5"
+
+cellppu -> "-qarch=cell"
+</mach_opt>
diff --git a/botan/src/build-data/makefile/nmake.in b/botan/src/build-data/makefile/nmake.in
new file mode 100644
index 0000000..34c864e
--- /dev/null
+++ b/botan/src/build-data/makefile/nmake.in
@@ -0,0 +1,107 @@
+##################################################
+# Compiler Options #
+##################################################
+CXX = %{cc}
+LIB_OPT = %{lib_opt}
+CHECK_OPT = %{check_opt}
+MACH_OPT = %{mach_opt}
+LANG_FLAGS = %{lang_flags}
+WARN_FLAGS = %{warn_flags}
+LINK_TO = %{link_to}
+
+##################################################
+# Version Numbers #
+##################################################
+VERSION = %{version}
+
+##################################################
+# Installation Settings #
+##################################################
+DESTDIR = %{prefix}
+
+LIBDIR = $(DESTDIR)\%{libdir}
+HEADERDIR = $(DESTDIR)\%{includedir}\botan
+DOCDIR = $(DESTDIR)\%{docdir}\Botan-$(VERSION)
+
+##################################################
+# Aliases for Common Programs #
+##################################################
+AR = %{ar_command}
+CD = @cd
+ECHO = @echo
+INSTALL = %{install_cmd_exec}
+INSTALL_CMD = %{install_cmd_exec}
+MKDIR = @md
+MKDIR_INSTALL = @md
+RM = @del /Q
+RMDIR = @rmdir
+
+##################################################
+# File Lists #
+##################################################
+CHECK = check
+
+DOCS = %{doc_files}
+
+HEADERS = %{include_files}
+
+LIBOBJS = %{lib_objs}
+
+CHECKOBJS = %{check_objs}
+
+LIB_FLAGS = $(LIB_OPT) $(MACH_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+
+LIBRARIES = $(STATIC_LIB)
+
+LIBNAME = libbotan
+STATIC_LIB = $(LIBNAME).%{static_suffix}
+
+all: $(LIBRARIES)
+
+##################################################
+# Build Commands #
+##################################################
+%{lib_build_cmds}
+
+%{check_build_cmds}
+
+##################################################
+# Link Commands #
+##################################################
+
+# Link for Borland?
+#ilink32 -L$(BCB)\lib -w -c -x -Gn -ap -Tpe c0x32.obj \
+# $(CHECKOBJS),check.exe,,$(LINK_TO) $(STATIC_LIB)
+
+$(CHECK): $(LIBRARIES) $(CHECKOBJS)
+ link /OUT:$@.exe $(CHECKOBJS) $(STATIC_LIB) $(LINK_TO)
+
+$(STATIC_LIB): $(LIBOBJS)
+ $(AR) /OUT:$@ /NAME:BOTAN-$(VERSION) $(LIBOBJS)
+
+##################################################
+# Misc Targets #
+##################################################
+static: $(STATIC_LIB)
+
+##################################################
+# Fake Targets #
+##################################################
+clean:
+ $(RM) %{build_dir}\lib\* %{build_dir}\checks\*
+ $(RM) $(LIBRARIES) $(CHECK)
+
+distclean: clean
+ $(RM) %{build_dir}\build.h
+ $(RM) %{build_dir}\include\botan\*
+ $(RMDIR) %{build_dir}\include\botan %{build_dir}\include
+ $(RMDIR) %{build_dir}\lib %{build_dir}\checks
+ $(RMDIR) %{build_dir}
+ $(RM) Makefile
+
+##################################################
+# Install Commands #
+##################################################
+install: $(LIBRARIES)
+ $(ECHO) "Install command not implemented"
diff --git a/botan/src/build-data/makefile/unix.in b/botan/src/build-data/makefile/unix.in
new file mode 100644
index 0000000..a48a5a1
--- /dev/null
+++ b/botan/src/build-data/makefile/unix.in
@@ -0,0 +1,121 @@
+##################################################
+# Compiler Options #
+##################################################
+CXX = %{cc}
+LIB_OPT = %{lib_opt}
+CHECK_OPT = %{check_opt}
+MACH_OPT = %{mach_opt}
+LANG_FLAGS = %{lang_flags}
+WARN_FLAGS = %{warn_flags}
+LINK_TO = %{link_to}
+
+##################################################
+# Version Numbers #
+##################################################
+VERSION = %{version}
+
+##################################################
+# Installation Settings #
+##################################################
+DESTDIR = %{prefix}
+
+BINDIR = $(DESTDIR)/bin
+LIBDIR = $(DESTDIR)/%{libdir}
+HEADERDIR = $(DESTDIR)/%{includedir}/botan
+DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+PKGCONF_DIR = $(LIBDIR)/pkgconfig
+
+CONFIG_SCRIPT = %{botan_config}
+PKGCONFIG = %{botan_pkgconfig}
+
+##################################################
+# Aliases for Common Programs #
+##################################################
+AR = %{ar_command}
+CD = @cd
+ECHO = @echo
+INSTALL_CMD_EXEC = %{install_cmd_exec}
+INSTALL_CMD_DATA = %{install_cmd_data}
+LN = ln -fs
+MKDIR = @mkdir
+MKDIR_INSTALL = @umask 022; mkdir -p -m 755
+RANLIB = %{ranlib_command}
+RM = @rm -f
+RM_R = @rm -rf
+
+##################################################
+# File Lists #
+##################################################
+CHECK = %{check_prefix}check
+
+DOCS = %{doc_files}
+
+HEADERS = %{include_files}
+
+LIBOBJS = %{lib_objs}
+
+CHECKOBJS = %{check_objs}
+
+LIB_FLAGS = $(LIB_OPT) $(MACH_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+
+LIBRARIES = $(STATIC_LIB)
+
+LIBNAME = %{lib_prefix}libbotan
+STATIC_LIB = $(LIBNAME).a
+
+all: $(LIBRARIES)
+
+##################################################
+# Build Commands #
+##################################################
+%{lib_build_cmds}
+
+%{check_build_cmds}
+
+##################################################
+# Link Commands #
+##################################################
+$(CHECK): $(LIBRARIES) $(CHECKOBJS)
+ $(CXX) $(CHECKOBJS) -L. libbotan.a $(LINK_TO) -o $(CHECK)
+
+$(STATIC_LIB): $(LIBOBJS)
+ $(RM) $(STATIC_LIB)
+ $(AR) $(STATIC_LIB) $(LIBOBJS)
+ $(RANLIB) $(STATIC_LIB)
+
+##################################################
+# Fake Targets #
+##################################################
+.PHONY = doxygen clean distclean install static
+
+static: $(STATIC_LIB)
+
+doxygen:
+ doxygen %{doc_src_dir}/botan.doxy
+
+clean:
+ $(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
+ $(RM) $(LIBRARIES) $(SYMLINK) $(CHECK)
+
+distclean: clean
+ $(RM_R) %{build_dir}
+ $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy
+ $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG)
+
+install: $(LIBRARIES)
+ $(ECHO) "Installing Botan into $(DESTDIR)... "
+ $(MKDIR_INSTALL) $(DOCDIR)
+ $(MKDIR_INSTALL) $(HEADERDIR)
+ $(MKDIR_INSTALL) $(LIBDIR)
+ $(MKDIR_INSTALL) $(BINDIR)
+ $(MKDIR_INSTALL) $(PKGCONF_DIR)
+ for i in $(DOCS); do \
+ $(INSTALL_CMD_DATA) $$i $(DOCDIR); \
+ done
+ for i in $(HEADERS); do \
+ $(INSTALL_CMD_DATA) $$i $(HEADERDIR); \
+ done
+ $(INSTALL_CMD_DATA) $(STATIC_LIB) $(LIBDIR)
+ $(INSTALL_CMD_EXEC) $(CONFIG_SCRIPT) $(BINDIR)
+ $(INSTALL_CMD_DATA) $(PKGCONFIG) $(PKGCONF_DIR)
diff --git a/botan/src/build-data/makefile/unix_shr.in b/botan/src/build-data/makefile/unix_shr.in
new file mode 100644
index 0000000..f718d11
--- /dev/null
+++ b/botan/src/build-data/makefile/unix_shr.in
@@ -0,0 +1,137 @@
+##################################################
+# Compiler Options #
+##################################################
+CXX = %{cc}
+LIB_OPT = %{lib_opt}
+CHECK_OPT = %{check_opt}
+MACH_OPT = %{mach_opt}
+LANG_FLAGS = %{lang_flags}
+WARN_FLAGS = %{warn_flags}
+SO_OBJ_FLAGS = %{shared_flags}
+SO_LINK_CMD = %{so_link}
+LINK_TO = %{link_to}
+
+##################################################
+# Version Numbers #
+##################################################
+VERSION = %{version}
+SO_VERSION = %{so_version}
+
+##################################################
+# Installation Settings #
+##################################################
+DESTDIR = %{prefix}
+
+BINDIR = $(DESTDIR)/bin
+LIBDIR = $(DESTDIR)/%{libdir}
+HEADERDIR = $(DESTDIR)/%{includedir}/botan
+DOCDIR = $(DESTDIR)/%{docdir}/Botan-$(VERSION)
+PKGCONF_DIR = $(LIBDIR)/pkgconfig
+
+CONFIG_SCRIPT = %{botan_config}
+PKGCONFIG = %{botan_pkgconfig}
+
+##################################################
+# Aliases for Common Programs #
+##################################################
+AR = %{ar_command}
+CD = @cd
+ECHO = @echo
+INSTALL_CMD_EXEC = %{install_cmd_exec}
+INSTALL_CMD_DATA = %{install_cmd_data}
+LN = ln -fs
+MKDIR = @mkdir
+MKDIR_INSTALL = @umask 022; mkdir -p -m 755
+RANLIB = %{ranlib_command}
+RM = @rm -f
+RM_R = @rm -rf
+
+##################################################
+# File Lists #
+##################################################
+CHECK = %{check_prefix}check
+
+DOCS = %{doc_files}
+
+HEADERS = %{include_files}
+
+LIBOBJS = %{lib_objs}
+
+CHECKOBJS = %{check_objs}
+
+LIB_FLAGS = $(LIB_OPT) $(MACH_OPT) $(LANG_FLAGS) $(WARN_FLAGS) $(SO_OBJ_FLAGS)
+CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
+
+LIBRARIES = $(STATIC_LIB) $(SHARED_LIB)
+
+LIBNAME = %{lib_prefix}libbotan
+STATIC_LIB = $(LIBNAME).a
+
+SHARED_LIB = $(LIBNAME)-$(SO_VERSION).%{so_suffix}
+SONAME = $(LIBNAME)-$(SO_VERSION).%{so_suffix}
+
+SYMLINK = libbotan.%{so_suffix}
+
+all: $(LIBRARIES)
+
+##################################################
+# Build Commands #
+##################################################
+%{lib_build_cmds}
+
+%{check_build_cmds}
+
+##################################################
+# Link Commands #
+##################################################
+$(CHECK): $(LIBRARIES) $(CHECKOBJS)
+ $(CXX) $(LDFLAGS) $(CHECKOBJS) -o $(CHECK) -L. -lbotan-%{so_version} $(LINK_TO)
+
+$(STATIC_LIB): $(LIBOBJS)
+ $(RM) $(STATIC_LIB)
+ $(AR) $(STATIC_LIB) $(LIBOBJS)
+ $(RANLIB) $(STATIC_LIB)
+
+$(SHARED_LIB): $(LIBOBJS)
+ $(SO_LINK_CMD) $(LDFLAGS) $(LIBOBJS) -o $(SHARED_LIB) $(LINK_TO)
+ $(LN) $(SHARED_LIB) $(SYMLINK)
+
+##################################################
+# Fake Targets #
+##################################################
+.PHONY = doxygen clean distclean install static shared
+
+static: $(STATIC_LIB)
+
+shared: $(SHARED_LIB)
+
+doxygen:
+ doxygen %{doc_src_dir}/botan.doxy
+
+clean:
+ $(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
+ $(RM) $(LIBRARIES) $(SYMLINK) $(CHECK)
+
+distclean: clean
+ $(RM_R) %{build_dir}
+ $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy
+ $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG)
+
+install: $(LIBRARIES)
+ $(ECHO) "Installing Botan into $(DESTDIR)... "
+ $(MKDIR_INSTALL) $(DOCDIR)
+ $(MKDIR_INSTALL) $(HEADERDIR)
+ $(MKDIR_INSTALL) $(LIBDIR)
+ $(MKDIR_INSTALL) $(BINDIR)
+ $(MKDIR_INSTALL) $(PKGCONF_DIR)
+ for i in $(DOCS); do \
+ $(INSTALL_CMD_DATA) $$i $(DOCDIR); \
+ done
+ for i in $(HEADERS); do \
+ $(INSTALL_CMD_DATA) $$i $(HEADERDIR); \
+ done
+ $(INSTALL_CMD_DATA) $(STATIC_LIB) $(LIBDIR)
+ $(INSTALL_CMD_EXEC) $(CONFIG_SCRIPT) $(BINDIR)
+ $(INSTALL_CMD_EXEC) $(SHARED_LIB) $(LIBDIR)
+ $(INSTALL_CMD_DATA) $(PKGCONFIG) $(PKGCONF_DIR)
+ $(CD) $(LIBDIR); $(LN) $(SHARED_LIB) $(SYMLINK)
diff --git a/botan/src/build-data/os/aix.txt b/botan/src/build-data/os/aix.txt
new file mode 100644
index 0000000..cec8185
--- /dev/null
+++ b/botan/src/build-data/os/aix.txt
@@ -0,0 +1,7 @@
+realname "AIX"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/beos.txt b/botan/src/build-data/os/beos.txt
new file mode 100644
index 0000000..2b12792
--- /dev/null
+++ b/botan/src/build-data/os/beos.txt
@@ -0,0 +1,16 @@
+realname "BeOS"
+
+os_type beos
+
+install_root /boot/beos
+header_dir ../develop/headers
+lib_dir system/lib
+doc_dir documentation
+
+<supports_shared>
+all
+</supports_shared>
+
+<aliases>
+haiku
+</aliases>
diff --git a/botan/src/build-data/os/cygwin.txt b/botan/src/build-data/os/cygwin.txt
new file mode 100644
index 0000000..c2aadea
--- /dev/null
+++ b/botan/src/build-data/os/cygwin.txt
@@ -0,0 +1,13 @@
+realname "Cygwin"
+
+os_type unix
+
+install_root c:\Botan
+doc_dir docs
+
+# Cygwin supports shared libs fine, but there are problems with making a Botan
+# shared library when libraries it depends on are static-only (such as libz).
+# So until I can figure out a work-around, it's disabled.
+<supports_shared>
+#all
+</supports_shared>
diff --git a/botan/src/build-data/os/darwin.txt b/botan/src/build-data/os/darwin.txt
new file mode 100644
index 0000000..2986212
--- /dev/null
+++ b/botan/src/build-data/os/darwin.txt
@@ -0,0 +1,19 @@
+realname "Darwin / MacOS X"
+
+os_type unix
+
+so_suffix dylib
+
+# It doesn't have the 's' option; you need to use needs ranlib
+ar_command "ar cr"
+ar_needs_ranlib yes
+
+doc_dir doc
+
+<supports_shared>
+all
+</supports_shared>
+
+<aliases>
+macosx
+</aliases>
diff --git a/botan/src/build-data/os/defaults.txt b/botan/src/build-data/os/defaults.txt
new file mode 100644
index 0000000..5648643
--- /dev/null
+++ b/botan/src/build-data/os/defaults.txt
@@ -0,0 +1,19 @@
+# Defaults are for a Unix box, since that's what most of OS variants are. It
+# would be nice to have generic 'windows', 'beos', 'unix', etc targets to
+# handle defaults for those classes of OSes, though Unix is by far the most
+# varied/fragmented
+
+obj_suffix o
+so_suffix so
+static_suffix a
+
+ar_command "ar crs"
+ar_needs_ranlib no
+
+install_root /usr/local
+header_dir include
+lib_dir lib
+doc_dir share/doc
+
+install_cmd_data "install -m 644"
+install_cmd_exec "install -m 755"
diff --git a/botan/src/build-data/os/dragonfly.txt b/botan/src/build-data/os/dragonfly.txt
new file mode 100644
index 0000000..7e36634
--- /dev/null
+++ b/botan/src/build-data/os/dragonfly.txt
@@ -0,0 +1,11 @@
+realname "DragonFly"
+
+os_type unix
+
+<target_features>
+posix_mlock
+</target_features>
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/freebsd.txt b/botan/src/build-data/os/freebsd.txt
new file mode 100644
index 0000000..ea96b0c
--- /dev/null
+++ b/botan/src/build-data/os/freebsd.txt
@@ -0,0 +1,11 @@
+realname "FreeBSD"
+
+os_type unix
+
+<target_features>
+posix_mlock
+</target_features>
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/hpux.txt b/botan/src/build-data/os/hpux.txt
new file mode 100644
index 0000000..6e17d3b
--- /dev/null
+++ b/botan/src/build-data/os/hpux.txt
@@ -0,0 +1,13 @@
+realname "HP-UX"
+
+os_type unix
+
+so_suffix sl
+
+<supports_shared>
+all
+</supports_shared>
+
+<aliases>
+hp-ux
+</aliases>
diff --git a/botan/src/build-data/os/irix.txt b/botan/src/build-data/os/irix.txt
new file mode 100644
index 0000000..fd8b432
--- /dev/null
+++ b/botan/src/build-data/os/irix.txt
@@ -0,0 +1,7 @@
+realname "IRIX"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/linux.txt b/botan/src/build-data/os/linux.txt
new file mode 100644
index 0000000..5352851
--- /dev/null
+++ b/botan/src/build-data/os/linux.txt
@@ -0,0 +1,12 @@
+realname "Linux"
+
+os_type unix
+
+<target_features>
+posix_mlock
+</target_features>
+
+# Is this correct?
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/mingw.txt b/botan/src/build-data/os/mingw.txt
new file mode 100644
index 0000000..eb25017
--- /dev/null
+++ b/botan/src/build-data/os/mingw.txt
@@ -0,0 +1,22 @@
+realname "MS Windows (MinGW)"
+os_type windows
+
+obj_suffix o
+so_suffix dll
+static_suffix a
+
+ar_command "ar crs"
+ar_needs_ranlib yes
+
+install_root /mingw
+header_dir include
+lib_dir lib
+doc_dir share/doc
+
+install_cmd_data "install -m 644"
+install_cmd_exec "install -m 755"
+
+<aliases>
+msys
+mingw32
+</aliases>
diff --git a/botan/src/build-data/os/netbsd.txt b/botan/src/build-data/os/netbsd.txt
new file mode 100644
index 0000000..435d8f5
--- /dev/null
+++ b/botan/src/build-data/os/netbsd.txt
@@ -0,0 +1,7 @@
+realname "NetBSD"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/openbsd.txt b/botan/src/build-data/os/openbsd.txt
new file mode 100644
index 0000000..cb44bd1
--- /dev/null
+++ b/botan/src/build-data/os/openbsd.txt
@@ -0,0 +1,7 @@
+realname "OpenBSD"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/qnx.txt b/botan/src/build-data/os/qnx.txt
new file mode 100644
index 0000000..28bc8de
--- /dev/null
+++ b/botan/src/build-data/os/qnx.txt
@@ -0,0 +1,7 @@
+realname "QNX"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
diff --git a/botan/src/build-data/os/solaris.txt b/botan/src/build-data/os/solaris.txt
new file mode 100644
index 0000000..8610b48
--- /dev/null
+++ b/botan/src/build-data/os/solaris.txt
@@ -0,0 +1,15 @@
+realname "Solaris"
+
+os_type unix
+
+<target_features>
+posix_mlock
+</target_features>
+
+<supports_shared>
+all
+</supports_shared>
+
+<aliases>
+sunos
+</aliases>
diff --git a/botan/src/build-data/os/tru64.txt b/botan/src/build-data/os/tru64.txt
new file mode 100644
index 0000000..e320c1d
--- /dev/null
+++ b/botan/src/build-data/os/tru64.txt
@@ -0,0 +1,11 @@
+realname "Tru64"
+
+os_type unix
+
+<supports_shared>
+all
+</supports_shared>
+
+<aliases>
+osf1
+</aliases>
diff --git a/botan/src/build-data/os/windows.txt b/botan/src/build-data/os/windows.txt
new file mode 100644
index 0000000..a04d609
--- /dev/null
+++ b/botan/src/build-data/os/windows.txt
@@ -0,0 +1,26 @@
+realname "MS Windows"
+
+os_type windows
+
+obj_suffix obj
+so_suffix dll
+static_suffix lib
+
+install_root c:\Botan
+doc_dir docs
+
+install_cmd_data "copy"
+install_cmd_exec "copy"
+
+<target_features>
+win32_virtual_lock
+</target_features>
+
+<supports_shared>
+msvc
+</supports_shared>
+
+<aliases>
+win32
+MSWin32
+</aliases>
diff --git a/botan/src/cert/cvc/asn1_eac_str.cpp b/botan/src/cert/cvc/asn1_eac_str.cpp
new file mode 100644
index 0000000..a306ffb
--- /dev/null
+++ b/botan/src/cert/cvc/asn1_eac_str.cpp
@@ -0,0 +1,130 @@
+/*
+* Simple ASN.1 String Types
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eac_asn_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <sstream>
+
+namespace Botan {
+
+/*
+* Create an ASN1_EAC_String
+*/
+ASN1_EAC_String::ASN1_EAC_String(const std::string& str, ASN1_Tag t) : tag(t)
+ {
+ iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET);
+ if (!sanity_check())
+ {
+ throw Invalid_Argument("attempted to construct ASN1_EAC_String with illegal characters");
+ }
+ }
+
+/*
+* Return this string in ISO 8859-1 encoding
+*/
+std::string ASN1_EAC_String::iso_8859() const
+ {
+ return iso_8859_str;
+ }
+
+/*
+* Return this string in local encoding
+*/
+std::string ASN1_EAC_String::value() const
+ {
+ return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET);
+ }
+
+/*
+* Return the type of this string object
+*/
+ASN1_Tag ASN1_EAC_String::tagging() const
+ {
+ return tag;
+ }
+
+/*
+* DER encode an ASN1_EAC_String
+*/
+void ASN1_EAC_String::encode_into(DER_Encoder& encoder) const
+ {
+ std::string value = iso_8859();
+ encoder.add_object(tagging(), APPLICATION, value);
+ }
+
+/*
+* Decode a BER encoded ASN1_EAC_String
+*/
+void ASN1_EAC_String::decode_from(BER_Decoder& source)
+ {
+ BER_Object obj = source.get_next_object();
+ if (obj.type_tag != this->tag)
+ {
+
+ std::string message("decoding type mismatch for ASN1_EAC_String, tag is ");
+ std::stringstream ss;
+ std::string str_is;
+ ss << std::hex << obj.type_tag;
+ ss >> str_is;
+ message.append(str_is);
+ message.append(", while it should be ");
+ std::stringstream ss2;
+ std::string str_should;
+ ss2 << std::hex << this->tag;
+ ss2 >> str_should;
+ message.append(str_should);
+ throw Decoding_Error(message);
+ }
+ Character_Set charset_is;
+ charset_is = LATIN1_CHARSET;
+
+ try
+ {
+ *this = ASN1_EAC_String(
+ Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET),
+ obj.type_tag);
+ }
+ catch (Invalid_Argument inv_arg)
+ {
+ throw Decoding_Error(std::string("error while decoding ASN1_EAC_String: ") + std::string(inv_arg.what()));
+ }
+ }
+
+// checks for compliance to the alphabet defined in TR-03110 v1.10, 2007-08-20
+// p. 43
+bool ASN1_EAC_String::sanity_check() const
+ {
+ const byte* rep = reinterpret_cast<const byte*>(iso_8859_str.data());
+ const u32bit rep_len = iso_8859_str.size();
+ for (u32bit i=0; i<rep_len; i++)
+ {
+ if ((rep[i] < 0x20) || ((rep[i] >= 0x7F) && (rep[i] < 0xA0)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+bool operator==(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs)
+ {
+ return (lhs.iso_8859() == rhs.iso_8859());
+ }
+
+ASN1_Car::ASN1_Car(std::string const& str)
+ : ASN1_EAC_String(str, ASN1_Tag(2))
+ {}
+
+ASN1_Chr::ASN1_Chr(std::string const& str)
+ : ASN1_EAC_String(str, ASN1_Tag(32))
+ {}
+
+}
diff --git a/botan/src/cert/cvc/asn1_eac_tm.cpp b/botan/src/cert/cvc/asn1_eac_tm.cpp
new file mode 100644
index 0000000..05533b5
--- /dev/null
+++ b/botan/src/cert/cvc/asn1_eac_tm.cpp
@@ -0,0 +1,361 @@
+/*
+* EAC Time Types
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eac_asn_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <ctime>
+#include <sstream>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Convert a time_t to a struct tm
+*/
+std::tm get_tm(u64bit timer)
+ {
+ std::time_t time_val = static_cast<std::time_t>(timer);
+
+ std::tm* tm_p = std::gmtime(&time_val);
+ if (tm_p == 0)
+ throw Encoding_Error("EAC_Time: gmtime could not encode " +
+ to_string(timer));
+ return (*tm_p);
+ }
+SecureVector<byte> enc_two_digit(u32bit in)
+ {
+ SecureVector<byte> result;
+ in %= 100;
+ if (in < 10)
+ {
+ result.append(0x00);
+ }
+ else
+ {
+ u32bit y_first_pos = (in - (in%10))/10;
+ result.append(static_cast<byte>(y_first_pos));
+ }
+ u32bit y_sec_pos = in%10;
+ result.append(static_cast<byte>(y_sec_pos));
+ return result;
+ }
+u32bit dec_two_digit(byte b1, byte b2)
+ {
+ u32bit upper = (u32bit)b1;
+ u32bit lower = (u32bit)b2;
+ if (upper > 9 || lower > 9)
+ {
+ throw Invalid_Argument("u32bit dec_two_digit(byte b1, byte b2): value too large");
+ }
+ return upper*10 + lower;
+
+ }
+}
+
+/*
+* Create an EAC_Time
+*/
+EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t)
+ :tag(t)
+ {
+ std::tm time_info = get_tm(timer);
+
+ year = time_info.tm_year + 1900;
+ month = time_info.tm_mon + 1;
+ day = time_info.tm_mday;
+
+ }
+
+/*
+* Create an EAC_Time
+*/
+EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t)
+ :tag(t)
+ {
+ set_to(t_spec);
+ }
+/*
+* Create an EAC_Time
+*/
+EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t)
+ : year(y),
+ month(m),
+ day(d),
+ tag(t)
+ {
+ }
+
+/*
+* Set the time with a human readable string
+*/
+void EAC_Time::set_to(const std::string& time_str)
+ {
+ if (time_str == "")
+ {
+ year = month = day = 0;
+ return;
+ }
+
+ std::vector<std::string> params;
+ std::string current;
+
+ for (u32bit j = 0; j != time_str.size(); ++j)
+ {
+ if (Charset::is_digit(time_str[j]))
+ current += time_str[j];
+ else
+ {
+ if (current != "")
+ params.push_back(current);
+ current.clear();
+ }
+ }
+ if (current != "")
+ params.push_back(current);
+
+ if (params.size() != 3)
+ throw Invalid_Argument("Invalid time specification " + time_str);
+
+ year = to_u32bit(params[0]);
+ month = to_u32bit(params[1]);
+ day = to_u32bit(params[2]);
+
+ if (!passes_sanity_check())
+ throw Invalid_Argument("Invalid time specification " + time_str);
+ }
+
+
+/*
+* DER encode a EAC_Time
+*/
+void EAC_Time::encode_into(DER_Encoder& der) const
+ {
+ der.add_object(tag, APPLICATION,
+ encoded_eac_time());
+ }
+
+/*
+* Return a string representation of the time
+*/
+std::string EAC_Time::as_string() const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::as_string: No time set");
+
+ std::string asn1rep;
+ asn1rep = to_string(year, 2);
+
+ asn1rep += to_string(month, 2) + to_string(day, 2);
+
+ return asn1rep;
+ }
+
+/*
+* Return if the time has been set somehow
+*/
+bool EAC_Time::time_is_set() const
+ {
+ return (year != 0);
+ }
+
+/*
+* Return a human readable string representation
+*/
+std::string EAC_Time::readable_string() const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::readable_string: No time set");
+
+ std::string readable;
+ readable += to_string(year, 2) + "/";
+ readable += to_string(month, 2) + "/";
+ readable += to_string(day, 2) + " ";
+
+ return readable;
+ }
+
+/*
+* Do a general sanity check on the time
+*/
+bool EAC_Time::passes_sanity_check() const
+ {
+ if (year < 2000 || year > 2099)
+ return false;
+ if (month == 0 || month > 12)
+ return false;
+ if (day == 0 || day > 31)
+ return false;
+
+ return true;
+ }
+
+/******************************************
+* modification functions
+******************************************/
+
+void EAC_Time::add_years(u32bit years)
+ {
+ year += years;
+ }
+void EAC_Time::add_months(u32bit months)
+ {
+ year += months/12;
+ month += months % 12;
+ if(month > 12)
+ {
+ year += 1;
+ month -= 12;
+ }
+ }
+
+
+/*
+* Compare this time against another
+*/
+s32bit EAC_Time::cmp(const EAC_Time& other) const
+ {
+ if (time_is_set() == false)
+ throw Invalid_State("EAC_Time::cmp: No time set");
+
+ const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0;
+
+ if (year < other.year) return EARLIER;
+ if (year > other.year) return LATER;
+ if (month < other.month) return EARLIER;
+ if (month > other.month) return LATER;
+ if (day < other.day) return EARLIER;
+ if (day > other.day) return LATER;
+
+ return SAME_TIME;
+ }
+
+/*
+* Compare two EAC_Times for in various ways
+*/
+bool operator==(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) == 0);
+ }
+bool operator!=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) != 0);
+ }
+bool operator<=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) <= 0);
+ }
+bool operator>=(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) >= 0);
+ }
+bool operator>(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) > 0);
+ }
+bool operator<(const EAC_Time& t1, const EAC_Time& t2)
+ {
+ return (t1.cmp(t2) < 0);
+ }
+
+/*
+* Decode a BER encoded EAC_Time
+*/
+void EAC_Time::decode_from(BER_Decoder& source)
+ {
+ BER_Object obj = source.get_next_object();
+ if (obj.type_tag != this->tag)
+ {
+ std::string message("decoding type mismatch for EAC_Time, tag is ");
+ std::stringstream ss;
+ std::string str_is;
+ ss << std::hex << obj.type_tag;
+ ss >> str_is;
+ message.append(str_is);
+ message.append(", while it should be ");
+ std::stringstream ss2;
+ std::string str_should;
+ ss2 << std::hex << this->tag;
+ ss2 >> str_should;
+ message.append(str_should);
+ throw Decoding_Error(message);
+
+ }
+ if (obj.value.size() != 6)
+ {
+ throw Decoding_Error("EAC_Time decoding failed");
+ }
+ try
+ {
+ u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]);
+ u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]);
+ u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]);
+ year = tmp_year + 2000;
+ month = tmp_mon;
+ day = tmp_day;
+ }
+ catch (Invalid_Argument)
+ {
+ throw Decoding_Error("EAC_Time decoding failed");
+ }
+
+ }
+
+u32bit EAC_Time::get_year() const
+ {
+ return year;
+ }
+u32bit EAC_Time::get_month() const
+ {
+ return month;
+ }
+u32bit EAC_Time::get_day() const
+ {
+ return day;
+ }
+
+/*
+* make the value an octet string for encoding
+*/
+SecureVector<byte> EAC_Time::encoded_eac_time() const
+ {
+ SecureVector<byte> result;
+ result.append(enc_two_digit(year));
+ result.append(enc_two_digit(month));
+ result.append(enc_two_digit(day));
+ return result;
+ }
+
+ASN1_Ced::ASN1_Ced(std::string const& str)
+ : EAC_Time(str, ASN1_Tag(37))
+ {}
+
+ASN1_Ced::ASN1_Ced(u64bit val)
+ : EAC_Time(val, ASN1_Tag(37))
+ {}
+
+ASN1_Ced::ASN1_Ced(EAC_Time const& other)
+ : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(37))
+ {}
+
+ASN1_Cex::ASN1_Cex(std::string const& str)
+ : EAC_Time(str, ASN1_Tag(36))
+ {}
+
+ASN1_Cex::ASN1_Cex(u64bit val)
+ : EAC_Time(val, ASN1_Tag(36))
+ {}
+
+ASN1_Cex::ASN1_Cex(EAC_Time const& other)
+ : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(36))
+ {}
+
+}
diff --git a/botan/src/cert/cvc/cvc_ado.cpp b/botan/src/cert/cvc/cvc_ado.cpp
new file mode 100644
index 0000000..6e1484e
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_ado.cpp
@@ -0,0 +1,135 @@
+/*
+* CVC Certificate Constructor
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cvc_ado.h>
+#include <fstream>
+#include <assert.h>
+
+namespace Botan {
+
+EAC1_1_ADO::EAC1_1_ADO(std::tr1::shared_ptr<DataSource> in)
+ {
+ init(in);
+ do_decode();
+ }
+
+EAC1_1_ADO::EAC1_1_ADO(const std::string& in)
+ {
+ std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ init(stream);
+ do_decode();
+ }
+
+void EAC1_1_ADO::force_decode()
+ {
+ SecureVector<byte> inner_cert;
+ BER_Decoder(tbs_bits)
+ .start_cons(ASN1_Tag(33))
+ .raw_bytes(inner_cert)
+ .end_cons()
+ .decode(m_car)
+ .verify_end();
+
+ SecureVector<byte> req_bits = DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .raw_bytes(inner_cert)
+ .end_cons()
+ .get_contents();
+
+ std::tr1::shared_ptr<DataSource> req_source(new DataSource_Memory(req_bits));
+ m_req = EAC1_1_Req(req_source);
+ sig_algo = m_req.sig_algo;
+ }
+
+MemoryVector<byte> EAC1_1_ADO::make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> concat_sig =
+ EAC1_1_obj<EAC1_1_ADO>::make_signature(signer.get(), tbs_bits, rng);
+ assert(concat_sig.size() % 2 == 0);
+ MemoryVector<byte> result = DER_Encoder()
+ .start_cons(ASN1_Tag(7), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+ return result;
+ }
+
+ASN1_Car EAC1_1_ADO::get_car() const
+ {
+ return m_car;
+ }
+
+void EAC1_1_ADO::decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig)
+ {
+ SecureVector<byte> concat_sig;
+ SecureVector<byte> cert_inner_bits;
+ ASN1_Car car;
+ BER_Decoder(*source.get_ptr().get())
+ .start_cons(ASN1_Tag(7))
+ .start_cons(ASN1_Tag(33))
+ .raw_bytes(cert_inner_bits)
+ .end_cons()
+ .decode(car)
+ .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons();
+
+ SecureVector<byte> enc_cert = DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .raw_bytes(cert_inner_bits)
+ .end_cons()
+ .get_contents();
+ SecureVector<byte> enc_car = DER_Encoder()
+ .encode(car)
+ .get_contents();
+ res_tbs_bits = enc_cert;
+ res_tbs_bits.append(enc_car);
+ res_sig = decode_concatenation(concat_sig);
+
+
+ }
+void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const
+ {
+ SecureVector<byte> concat_sig(EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation());
+ SecureVector<byte> der = DER_Encoder()
+ .start_cons(ASN1_Tag(7), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+ if(encoding == PEM)
+ throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object");
+ else
+ out.write(der);
+ }
+
+SecureVector<byte> EAC1_1_ADO::tbs_data() const
+ {
+ return tbs_bits;
+ }
+
+bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const
+ {
+ assert(((this->m_req == rhs.m_req) && (this->tbs_data() == rhs.tbs_data())) ||
+ ((this->m_req != rhs.m_req) && (this->tbs_data() != rhs.tbs_data())));
+ return (this->get_concat_sig() == rhs.get_concat_sig()
+ && this->tbs_data() == rhs.tbs_data()
+ && this->get_car() == rhs.get_car());
+ }
+
+EAC1_1_Req EAC1_1_ADO::get_request() const
+ {
+ return m_req;
+ }
+
+}
diff --git a/botan/src/cert/cvc/cvc_ado.h b/botan/src/cert/cvc/cvc_ado.h
new file mode 100644
index 0000000..2c4f3ce
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_ado.h
@@ -0,0 +1,101 @@
+/*
+* EAC1_1 CVC ADO
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_ADO_H__
+#define BOTAN_EAC_CVC_ADO_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_req.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a TR03110 (EAC) v1.1 CVC ADO request
+*/
+
+ // CRTP continuation from EAC1_1_obj
+class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
+ {
+ public:
+ friend class EAC1_1_obj<EAC1_1_ADO>;
+
+ /**
+ * Construct a CVC ADO request from a DER encoded CVC ADO request file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_ADO(const std::string& str);
+
+ /**
+ * Construct a CVC ADO request from a data source
+ * @param source the data source
+ */
+ EAC1_1_ADO(std::tr1::shared_ptr<DataSource> source);
+
+ /**
+ * Create a signed CVC ADO request from to be signed (TBS) data
+ * @param signer the signer used to sign the CVC ADO request
+ * @param tbs_bits the TBS data to sign
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Get the CAR of this CVC ADO request
+ * @result the CAR of this CVC ADO request
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CVC request contained in this object.
+ * @result the CVC request inside this CVC ADO request
+ */
+ EAC1_1_Req get_request() const;
+
+ /**
+ * Encode this object into a pipe. Only DER is supported.
+ * @param out the pipe to encode this object into
+ * @param encoding the encoding type to use, must be DER
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ bool operator==(EAC1_1_ADO const& rhs) const;
+
+ /**
+ * Get the TBS data of this CVC ADO request.
+ * @result the TBS data
+ */
+ SecureVector<byte> tbs_data() const;
+
+ virtual ~EAC1_1_ADO() {}
+ private:
+ ASN1_Car m_car;
+ EAC1_1_Req m_req;
+
+ void force_decode();
+ static void decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig);
+ };
+
+inline bool operator!=(EAC1_1_ADO const& lhs, EAC1_1_ADO const& rhs)
+ {
+ return (!(lhs == rhs));
+ }
+
+}
+
+#endif
+
+
diff --git a/botan/src/cert/cvc/cvc_ca.cpp b/botan/src/cert/cvc/cvc_ca.cpp
new file mode 100644
index 0000000..638d3f9
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_ca.cpp
@@ -0,0 +1,46 @@
+#include <botan/cvc_ca.h>
+#include <botan/cvc_cert.h>
+#include <botan/der_enc.h>
+#include <botan/util.h>
+#include <botan/oids.h>
+namespace Botan {
+
+EAC1_1_CVC EAC1_1_CVC_CA::make_cert(std::auto_ptr<PK_Signer> signer,
+ MemoryRegion<byte> const& public_key,
+ ASN1_Car const& car,
+ ASN1_Chr const& chr,
+ byte holder_auth_templ,
+ ASN1_Ced ced,
+ ASN1_Cex cex,
+ RandomNumberGenerator& rng)
+ {
+ OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate"));
+ MemoryVector<byte> enc_chat_val;
+ enc_chat_val.append(holder_auth_templ);
+
+ MemoryVector<byte> enc_cpi;
+ enc_cpi.append(0x00);
+ MemoryVector<byte> tbs = DER_Encoder()
+ .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi
+ .encode(car)
+ .raw_bytes(public_key)
+ .encode(chr)
+ .start_cons(ASN1_Tag(76), APPLICATION)
+ .encode(chat_oid)
+ .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION)
+ .end_cons()
+ .encode(ced)
+ .encode(cex)
+ .get_contents();
+
+ MemoryVector<byte> signed_cert =
+ EAC1_1_CVC::make_signed(signer,
+ EAC1_1_CVC::build_cert_body(tbs),
+ rng);
+
+ std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
+
+ return EAC1_1_CVC(source);
+ }
+
+}
diff --git a/botan/src/cert/cvc/cvc_ca.h b/botan/src/cert/cvc/cvc_ca.h
new file mode 100644
index 0000000..3ec307b
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_ca.h
@@ -0,0 +1,51 @@
+/*
+* EAC1.1 CVC Certificate Authority
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_CA_H__
+#define BOTAN_CVC_CA_H__
+
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/pubkey.h>
+#include <botan/cvc_cert.h>
+
+namespace Botan {
+
+/**
+* This class represents a CVC CA.
+*/
+class BOTAN_DLL EAC1_1_CVC_CA
+ {
+ public:
+
+ /**
+ * Create an arbitrary EAC 1.1 CVC.
+ * The desired key encoding must be set within the key (if applicable).
+ * @param signer the signer used to sign the certificate
+ * @param public_key the DER encoded public key to appear in
+ * the certificate
+ * @param car the CAR of the certificate
+ * @param chr the CHR of the certificate
+ * @param holder_auth_templ the holder authorization value byte to
+ * appear in the CHAT of the certificate
+ * @param ced the CED to appear in the certificate
+ * @param ced the CEX to appear in the certificate
+ */
+ static EAC1_1_CVC make_cert(std::auto_ptr<PK_Signer> signer,
+ MemoryRegion<byte> const& public_key,
+ ASN1_Car const& car,
+ ASN1_Chr const& chr,
+ byte holder_auth_templ,
+ ASN1_Ced ced,
+ ASN1_Cex cex,
+ RandomNumberGenerator& rng);
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/cvc_cert.cpp b/botan/src/cert/cvc/cvc_cert.cpp
new file mode 100644
index 0000000..d2be12d
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_cert.cpp
@@ -0,0 +1,102 @@
+/*
+ (C) 2007 FlexSecure GmbH
+ 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cvc_cert.h>
+#include <botan/cvc_key.h>
+#include <botan/ecdsa.h>
+
+namespace Botan {
+
+ASN1_Car EAC1_1_CVC::get_car() const
+ {
+ return m_car;
+ }
+
+ASN1_Ced EAC1_1_CVC::get_ced() const
+ {
+ return m_ced;
+ }
+ASN1_Cex EAC1_1_CVC::get_cex() const
+ {
+ return m_cex;
+ }
+u32bit EAC1_1_CVC::get_chat_value() const
+ {
+ return m_chat_val;
+ }
+
+/*
+* Decode the TBSCertificate data
+*/
+void EAC1_1_CVC::force_decode()
+ {
+ SecureVector<byte> enc_pk;
+ SecureVector<byte> enc_chat_val;
+ u32bit cpi;
+ BER_Decoder tbs_cert(tbs_bits);
+ tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION)
+ .decode(m_car)
+ .start_cons(ASN1_Tag(73))
+ .raw_bytes(enc_pk)
+ .end_cons()
+ .decode(m_chr)
+ .start_cons(ASN1_Tag(76))
+ .decode(m_chat_oid)
+ .decode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION)
+ .end_cons()
+ .decode(m_ced)
+ .decode(m_cex)
+ .verify_end();
+
+ if(enc_chat_val.size() != 1)
+ throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1");
+
+ if(cpi != 0)
+ throw Decoding_Error("EAC1_1 certificate´s cpi was not 0");
+
+ // FIXME: PK algos have no notion of EAC encoder/decoder currently
+#if 0
+ ECDSA_PublicKey tmp_pk;
+ std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder();
+ sig_algo = dec->public_key(enc_pk);
+
+
+ m_pk = tmp_pk;
+ m_chat_val = enc_chat_val[0];
+ self_signed = false;
+ if(m_car.iso_8859() == m_chr.iso_8859())
+ {
+ self_signed= true;
+ }
+#endif
+ }
+
+/*
+* CVC Certificate Constructor
+*/
+EAC1_1_CVC::EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& in)
+ {
+ init(in);
+ self_signed = false;
+ do_decode();
+ }
+
+EAC1_1_CVC::EAC1_1_CVC(const std::string& in)
+ {
+ std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ init(stream);
+ self_signed = false;
+ do_decode();
+ }
+
+bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const
+ {
+ return (tbs_data() == rhs.tbs_data()
+ && get_concat_sig() == rhs.get_concat_sig());
+ }
+
+}
diff --git a/botan/src/cert/cvc/cvc_cert.h b/botan/src/cert/cvc/cvc_cert.h
new file mode 100644
index 0000000..17671d3
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_cert.h
@@ -0,0 +1,94 @@
+/*
+* EAC1_1 CVC
+* (C) 2008 Falko Strenzke
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_EAC_H__
+#define BOTAN_CVC_EAC_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/signed_obj.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/ecdsa_sig.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_gen_cert.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 (EAC) v1.1 CV Certificates
+*/
+class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object
+ {
+ public:
+ friend class EAC1_1_obj<EAC1_1_CVC>;
+
+ /**
+ * Get the CAR of the certificate.
+ * @result the CAR of the certificate
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CED of this certificate.
+ * @result the CED this certificate
+ */
+ ASN1_Ced get_ced() const;
+
+ /**
+ * Get the CEX of this certificate.
+ * @result the CEX this certificate
+ */
+ ASN1_Cex get_cex() const;
+
+ /**
+ * Get the CHAT value.
+ * @result the CHAT value
+ */
+ u32bit get_chat_value() const;
+
+ bool operator==(const EAC1_1_CVC&) const;
+
+ /**
+ * Construct a CVC from a data source
+ * @param source the data source
+ */
+ EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& source);
+
+ /**
+ * Construct a CVC from a file
+ * @param str the path to the certificate file
+ */
+ EAC1_1_CVC(const std::string& str);
+
+ virtual ~EAC1_1_CVC() {}
+ private:
+ void force_decode();
+ friend class EAC1_1_CVC_CA;
+ EAC1_1_CVC() {}
+
+ ASN1_Car m_car;
+ ASN1_Ced m_ced;
+ ASN1_Cex m_cex;
+ byte m_chat_val;
+ OID m_chat_oid;
+ };
+
+/*
+* Comparison
+*/
+inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
+
diff --git a/botan/src/cert/cvc/cvc_gen_cert.h b/botan/src/cert/cvc/cvc_gen_cert.h
new file mode 100644
index 0000000..4a78802
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_gen_cert.h
@@ -0,0 +1,177 @@
+/*
+* EAC1_1 general CVC
+* (C) 2008 Falko Strenzke
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_GEN_CERT_H__
+#define BOTAN_EAC_CVC_GEN_CERT_H__
+
+#include <botan/x509_key.h>
+#include <botan/eac_asn_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa_sig.h>
+#include <string>
+#include <assert.h>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 (EAC) v1.1 generalized CV Certificates
+*/
+template<typename Derived>
+class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj
+ {
+ friend class EAC1_1_obj<EAC1_1_gen_CVC>;
+
+ public:
+
+ /**
+ * Get this certificates public key.
+ * @result this certificates public key
+ */
+ std::auto_ptr<Public_Key> subject_public_key() const;
+
+ /**
+ * Find out whether this object is self signed.
+ * @result true if this object is self signed
+ */
+ bool is_self_signed() const;
+
+ /**
+ * Get the CHR of the certificate.
+ * @result the CHR of the certificate
+ */
+ ASN1_Chr get_chr() const;
+
+ /**
+ * Put the DER encoded version of this object into a pipe. PEM
+ * is not supported.
+ * @param out the pipe to push the DER encoded version into
+ * @param encoding the encoding to use. Must be DER.
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ /**
+ * Get the to-be-signed (TBS) data of this object.
+ * @result the TBS data of this object
+ */
+ SecureVector<byte> tbs_data() const;
+
+ /**
+ * Build the DER encoded certifcate body of an object
+ * @param tbs the data to be signed
+ * @result the correctly encoded body of the object
+ */
+ static SecureVector<byte> build_cert_body(MemoryRegion<byte> const& tbs);
+
+ /**
+ * Create a signed generalized CVC object.
+ * @param signer the signer used to sign this object
+ * @param tbs_bits the body the generalized CVC object to be signed
+ * @result the DER encoded signed generalized CVC object
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+ virtual ~EAC1_1_gen_CVC<Derived>()
+ {}
+
+ protected:
+ ECDSA_PublicKey m_pk; // public key
+ ASN1_Chr m_chr;
+ bool self_signed;
+
+ static void decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig);
+
+ };
+
+template<typename Derived> ASN1_Chr EAC1_1_gen_CVC<Derived>::get_chr() const
+ {
+ return m_chr;
+ }
+
+template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const
+ {
+ return self_signed;
+ }
+
+template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng) // static
+ {
+ SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer.get(), tbs_bits, rng);
+ assert(concat_sig.size() % 2 == 0);
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+ }
+
+template<typename Derived> std::auto_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const
+ {
+ return std::auto_ptr<Public_Key>(new ECDSA_PublicKey(m_pk));
+ }
+
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs)
+ {
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(tbs)
+ .end_cons().get_contents();
+ }
+
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const
+ {
+ return build_cert_body(EAC1_1_obj<Derived>::tbs_bits);
+ }
+
+template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const
+ {
+ SecureVector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation());
+ SecureVector<byte> der = DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(EAC1_1_obj<Derived>::tbs_bits)
+ .end_cons()
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+
+ if (encoding == PEM)
+ throw Invalid_Argument("EAC1_1_gen_CVC::encode() cannot PEM encode an EAC object");
+ else
+ out.write(der);
+ }
+
+template<typename Derived>
+void EAC1_1_gen_CVC<Derived>::decode_info(
+ SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig)
+ {
+ SecureVector<byte> concat_sig;
+ BER_Decoder(*source.get_shared().get())
+ .start_cons(ASN1_Tag(33))
+ .start_cons(ASN1_Tag(78))
+ .raw_bytes(res_tbs_bits)
+ .end_cons()
+ .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons();
+ res_sig = decode_concatenation(concat_sig);
+ }
+
+}
+
+#endif
+
+
diff --git a/botan/src/cert/cvc/cvc_key.h b/botan/src/cert/cvc/cvc_key.h
new file mode 100644
index 0000000..67b6cef
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_key.h
@@ -0,0 +1,54 @@
+/*
+* EAC CVC Public Key
+* (C) 2008 FlexSecure Gmbh
+* Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+#define BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+
+namespace Botan {
+
+/**
+* This class represents EAC 1.1 CVC public key encoders.
+*/
+class BOTAN_DLL EAC1_1_CVC_Encoder
+ {
+ public:
+ /**
+ * Get the DER encoded CVC public key.
+ * @param alg_id the algorithm identifier to use in the encoding
+ * @return the DER encoded public key
+ */
+ virtual MemoryVector<byte>
+ public_key(const AlgorithmIdentifier& enc) const = 0;
+
+ virtual ~EAC1_1_CVC_Encoder() {}
+ };
+
+/**
+* This class represents EAC 1.1 CVC public key decoders.
+*/
+class BOTAN_DLL EAC1_1_CVC_Decoder
+ {
+ public:
+ /**
+ * Decode a CVC public key.
+ * @param enc the DER encoded public key to decode
+ * @return the algorithm identifier found in the encoded public key
+ */
+ virtual AlgorithmIdentifier const
+ public_key(const MemoryRegion<byte>& enc) = 0;
+
+ virtual ~EAC1_1_CVC_Decoder() {}
+ };
+}
+
+#endif
diff --git a/botan/src/cert/cvc/cvc_req.cpp b/botan/src/cert/cvc/cvc_req.cpp
new file mode 100644
index 0000000..70a44ba
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_req.cpp
@@ -0,0 +1,68 @@
+/*
+ (C) 2007 FlexSecure GmbH
+ 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cvc_cert.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pem.h>
+#include <botan/parsing.h>
+#include <assert.h>
+#include <botan/cvc_key.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/cvc_req.h>
+#include <botan/freestore.h>
+
+namespace Botan {
+
+bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const
+ {
+ return (this->tbs_data() == rhs.tbs_data()
+ && this->get_concat_sig() == rhs.get_concat_sig());
+ }
+
+void EAC1_1_Req::force_decode()
+ {
+ SecureVector<byte> enc_pk;
+ BER_Decoder tbs_cert(tbs_bits);
+ u32bit cpi;
+ tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION)
+ .start_cons(ASN1_Tag(73))
+ .raw_bytes(enc_pk)
+ .end_cons()
+ .decode(m_chr)
+ .verify_end();
+ if(cpi != 0)
+ {
+ throw Decoding_Error("EAC1_1 request´s cpi was not 0");
+ }
+
+ // FIXME: No EAC support in ECDSA
+#if 0
+ ECDSA_PublicKey tmp_pk;
+ std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder();
+ sig_algo = dec->public_key(enc_pk);
+ m_pk = tmp_pk;
+#endif
+ }
+
+EAC1_1_Req::EAC1_1_Req(std::tr1::shared_ptr<DataSource> in)
+ {
+ init(in);
+ self_signed = true;
+ do_decode();
+ }
+
+EAC1_1_Req::EAC1_1_Req(const std::string& in)
+ {
+ std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true));
+ init(stream);
+ self_signed = true;
+ do_decode();
+ }
+
+}
diff --git a/botan/src/cert/cvc/cvc_req.h b/botan/src/cert/cvc/cvc_req.h
new file mode 100644
index 0000000..96b6a44
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_req.h
@@ -0,0 +1,62 @@
+/*
+* EAC1_1 CVC Request
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_CVC_REQ_H__
+#define BOTAN_EAC_CVC_REQ_H__
+
+#include <botan/x509_key.h>
+#include <botan/pubkey_enums.h>
+#include <botan/cvc_gen_cert.h>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 v1.1 EAC CV Certificate Requests.
+*/
+class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req>
+ {
+ public:
+ friend class EAC1_1_Req_CA;
+ friend class EAC1_1_ADO;
+ friend class EAC1_1_obj<EAC1_1_Req>;
+
+ /**
+ * Compare for equality with other
+ * @param other compare for equality with this object
+ */
+ bool operator==(const EAC1_1_Req& other) const;
+
+ /**
+ * Construct a CVC request from a data source.
+ * @param source the data source
+ */
+ EAC1_1_Req(std::tr1::shared_ptr<DataSource> source);
+
+ /**
+ * Construct a CVC request from a DER encoded CVC reqeust file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_Req(const std::string& str);
+
+ virtual ~EAC1_1_Req(){}
+ private:
+ void force_decode();
+ EAC1_1_Req() {}
+ };
+
+/*
+* Comparison Operator
+*/
+inline bool operator!=(EAC1_1_Req const& lhs, EAC1_1_Req const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/cvc_self.cpp b/botan/src/cert/cvc/cvc_self.cpp
new file mode 100644
index 0000000..91ea387
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_self.cpp
@@ -0,0 +1,327 @@
+/*
+ (C) 2007 FlexSecure GmbH
+ 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cvc_self.h>
+#include <botan/cvc_cert.h>
+#include <botan/cvc_ca.h>
+#include <botan/alg_id.h>
+#include <botan/cvc_key.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/cvc_req.h>
+#include <botan/cvc_ado.h>
+#include <botan/util.h>
+#include <sstream>
+
+namespace Botan {
+
+namespace {
+
+/*******************************
+* cvc CHAT values
+*******************************/
+enum CHAT_values{
+ CVCA = 0xC0,
+ DVCA_domestic = 0x80,
+ DVCA_foreign = 0x40,
+ IS = 0x00,
+
+ IRIS = 0x02,
+ FINGERPRINT = 0x01
+};
+
+std::string padding_and_hash_from_oid(OID const& oid)
+ {
+ std::string padding_and_hash = OIDS::lookup(oid); // use the hash
+ assert(padding_and_hash.substr(0,6) == "ECDSA/"); // can only be ECDSA for now
+ assert(padding_and_hash.find("/",0) == 5);
+ padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1);
+ return padding_and_hash;
+ }
+std::string fixed_len_seqnr(u32bit seqnr, u32bit len)
+ {
+ std::stringstream ss;
+ std::string result;
+ ss << seqnr;
+ ss >> result;
+ if (result.size() > len)
+ {
+ throw Invalid_Argument("fixed_len_seqnr(): number too high to be encoded in provided length");
+ }
+ while (result.size() < len)
+ {
+ result.insert(0,"0");
+ }
+ return result;
+ }
+
+}
+namespace CVC_EAC
+{
+
+EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
+ EAC1_1_CVC_Options const& opt,
+ RandomNumberGenerator& rng)
+ {
+ // NOTE: we ignore
+ // the value
+ // of opt.chr
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+
+ ASN1_Chr chr(opt.car.value());
+
+ AlgorithmIdentifier sig_algo;
+ std::string padding_and_hash(eac_cvc_emsa + "(" + opt.hash_alg + ")");
+ sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
+ sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
+
+ std::auto_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash));
+
+#if 0 // FIXME
+ std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder());
+ MemoryVector<byte> enc_public_key = enc->public_key(sig_algo);
+#else
+ MemoryVector<byte> enc_public_key;
+#endif
+
+ return EAC1_1_CVC_CA::make_cert(signer, enc_public_key, opt.car, chr, opt.holder_auth_templ, opt.ced, opt.cex, rng);
+
+ }
+
+EAC1_1_Req create_cvc_req(Private_Key const& key,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng)
+ {
+
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ AlgorithmIdentifier sig_algo;
+ std::string padding_and_hash(eac_cvc_emsa + "(" + hash_alg + ")");
+ sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
+ sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
+
+ std::auto_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash));
+
+#if 0 // FIXME
+ std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder());
+ MemoryVector<byte> enc_public_key = enc->public_key(sig_algo);
+#else
+ MemoryVector<byte> enc_public_key;
+#endif
+
+ MemoryVector<byte> enc_cpi;
+ enc_cpi.append(0x00);
+ MemoryVector<byte> tbs = DER_Encoder()
+ .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION)
+ .raw_bytes(enc_public_key)
+ .encode(chr)
+ .get_contents();
+
+ MemoryVector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), rng);
+ std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
+ return EAC1_1_Req(source);
+ }
+
+EAC1_1_ADO create_ado_req(Private_Key const& key,
+ EAC1_1_Req const& req,
+ ASN1_Car const& car,
+ RandomNumberGenerator& rng)
+ {
+
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid);
+ std::auto_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash));
+ SecureVector<byte> tbs_bits = req.BER_encode();
+ tbs_bits.append(DER_Encoder().encode(car).get_contents());
+ MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(signer, tbs_bits, rng);
+ std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert));
+ return EAC1_1_ADO(source);
+ }
+
+} // namespace CVC_EAC
+namespace DE_EAC
+{
+
+EAC1_1_CVC create_cvca(Private_Key const& key,
+ std::string const& hash,
+ ASN1_Car const& car, bool iris, bool fingerpr,
+ u32bit cvca_validity_months,
+ RandomNumberGenerator& rng)
+ {
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ EAC1_1_CVC_Options opts;
+ opts.car = car;
+ const u64bit current_time = system_time();
+
+ opts.ced = ASN1_Ced(current_time);
+ opts.cex = ASN1_Cex(opts.ced);
+ opts.cex.add_months(cvca_validity_months);
+ opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT));
+ opts.hash_alg = hash;
+ return Botan::CVC_EAC::create_self_signed_cert(*priv_key, opts, rng);
+ }
+
+
+
+EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
+ Private_Key const& key,
+ EAC1_1_CVC const& signee,
+ RandomNumberGenerator& rng)
+ {
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ ASN1_Ced ced(system_time());
+ ASN1_Cex cex(signee.get_cex());
+ if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex))
+ {
+ std::string detail("link_cvca(): validity periods of provided certificates don't overlap: currend time = ced = ");
+ detail += ced.as_string();
+ detail += ", signee.cex = ";
+ detail += cex.as_string();
+ throw Invalid_Argument(detail);
+ }
+ if (signer.signature_algorithm() != signee.signature_algorithm())
+ {
+ throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don´t match");
+ }
+ AlgorithmIdentifier sig_algo = signer.signature_algorithm();
+ std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid);
+ std::auto_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash));
+ std::auto_ptr<Public_Key> pk = signee.subject_public_key();
+ ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
+ subj_pk->set_parameter_encoding(ENC_EXPLICIT);
+
+#if 0 // FIXME
+ std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder());
+ MemoryVector<byte> enc_public_key = enc->public_key(sig_algo);
+#else
+ MemoryVector<byte> enc_public_key;
+#endif
+
+ return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key,
+ signer.get_car(),
+ signee.get_chr(),
+ signer.get_chat_value(),
+ ced,
+ cex,
+ rng);
+ }
+
+EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
+ Private_Key const& key,
+ EAC1_1_Req const& signee,
+ u32bit seqnr,
+ u32bit seqnr_len,
+ bool domestic,
+ u32bit dvca_validity_months,
+ u32bit ca_is_validity_months,
+ RandomNumberGenerator& rng)
+ {
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ std::string chr_str = signee.get_chr().value();
+ chr_str.append(fixed_len_seqnr(seqnr, seqnr_len));
+ ASN1_Chr chr(chr_str);
+ std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid);
+ std::auto_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash));
+ std::auto_ptr<Public_Key> pk = signee.subject_public_key();
+ ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
+ std::auto_ptr<Public_Key> signer_pk = signer_cert.subject_public_key();
+
+ // for the case that the domain parameters are not set...
+ // (we use those from the signer because they must fit)
+ subj_pk->set_domain_parameters(priv_key->domain_parameters());
+
+ subj_pk->set_parameter_encoding(ENC_IMPLICITCA);
+
+#if 0 // FIXME
+ std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder());
+ MemoryVector<byte> enc_public_key = enc->public_key(sig_algo);
+#else
+ MemoryVector<byte> enc_public_key;
+#endif
+
+ AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm());
+ const u64bit current_time = system_time();
+ ASN1_Ced ced(current_time);
+ u32bit chat_val;
+ u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer
+ ASN1_Cex cex(ced);
+ if ((signer_cert.get_chat_value() & CVCA) == CVCA)
+ {
+ // we sign a dvca
+ cex.add_months(dvca_validity_months);
+ if (domestic)
+ {
+ chat_val = DVCA_domestic | chat_low;
+ }
+ else
+ {
+ chat_val = DVCA_foreign | chat_low;
+ }
+ }
+ else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic ||
+ (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign)
+ {
+ cex.add_months(ca_is_validity_months);
+ chat_val = IS | chat_low;
+ }
+ else
+ {
+ throw Invalid_Argument("sign_request(): encountered illegal value for CHAT");
+ // (IS cannot sign certificates)
+ }
+ return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key,
+ ASN1_Car(signer_cert.get_chr().iso_8859()),
+ chr,
+ chat_val,
+ ced,
+ cex,
+ rng);
+ }
+
+EAC1_1_Req create_cvc_req(Private_Key const& prkey,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng)
+ {
+ ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&prkey);
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+ ECDSA_PrivateKey key(*priv_key);
+ key.set_parameter_encoding(ENC_IMPLICITCA);
+ return Botan::CVC_EAC::create_cvc_req(key, chr, hash_alg, rng);
+ }
+
+} // namespace DE_EAC
+
+}
diff --git a/botan/src/cert/cvc/cvc_self.h b/botan/src/cert/cvc/cvc_self.h
new file mode 100644
index 0000000..db23547
--- /dev/null
+++ b/botan/src/cert/cvc/cvc_self.h
@@ -0,0 +1,167 @@
+/*
+* CVC Self-Signed Certificate
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CVC_EAC_SELF_H__
+#define BOTAN_CVC_EAC_SELF_H__
+
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/cvc_cert.h>
+#include <botan/ecdsa.h>
+#include <botan/asn1_obj.h>
+#include <botan/cvc_req.h>
+#include <botan/cvc_ado.h>
+
+namespace Botan {
+
+/**
+* This class represents a set of options used for the creation of CVC certificates
+*/
+class BOTAN_DLL EAC1_1_CVC_Options
+ {
+ public:
+
+ ASN1_Car car;
+ ASN1_Chr chr;
+ byte holder_auth_templ;
+ ASN1_Ced ced;
+ ASN1_Cex cex;
+ std::string hash_alg;
+ };
+
+/**
+* This namespace represents general EAC 1.1 convenience functions.
+*/
+namespace CVC_EAC {
+
+/**
+* Create a selfsigned CVCA
+* @param rng the rng to use
+* @param key the ECDSA private key to be used to sign the certificate
+* @param opts used to set several parameters. Necessary are:
+* car, holder_auth_templ, hash_alg, ced, cex and hash_alg
+* @result the self signed certificate
+*/
+
+EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
+ EAC1_1_CVC_Options const& opts,
+ RandomNumberGenerator& rng);
+/**
+* Create a CVC request. The key encoding will be according to the provided private key.
+* @param priv_key the private key associated with the requesting entity
+* @param chr the chr to appear in the certificate (to be provided without
+* sequence number)
+* @param hash_alg the string defining the hash algorithm to be used for the creation
+* of the signature
+* @param rng the rng to use
+* @result the new request
+*/
+EAC1_1_Req create_cvc_req(Private_Key const& priv_key,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng);
+
+/**
+* Create an ADO from a request object.
+* @param priv_key the private key used to sign the ADO
+* @param req the request forming the body of the ADO
+* @param car the CAR forming the body of the ADO, i.e. the
+* CHR of the entity associated with the provided private key
+* @param rng the rng to use
+*/
+EAC1_1_ADO create_ado_req(Private_Key const& priv_key,
+ EAC1_1_Req const& req,
+ ASN1_Car const& car,
+ RandomNumberGenerator& rng);
+}
+/**
+* This namespace represents EAC 1.1 CVC convenience functions following the specific german
+* requirements.
+*/
+namespace DE_EAC {
+
+/**
+* Create a CVCA certificate.
+* @param priv_key the private key associated with the CVCA certificate
+* to be created
+* @param hash the string identifying the hash algorithm to be used
+* for signing the certificate to be created
+* @param car the CAR of the certificate to be created
+* @param iris indicates whether the entity associated with the certificate
+* shall be entitled to read the biometrical iris image
+* @param fingerpr indicates whether the entity associated with the certificate
+* shall be entitled to read the biometrical fingerprint image
+* @param rng the rng to use
+* @result the CVCA certificate created
+*/
+EAC1_1_CVC create_cvca(Private_Key const& priv_key,
+ std::string const& hash,
+ ASN1_Car const& car,
+ bool iris,
+ bool fingerpr,
+ u32bit cvca_validity_months,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a link certificate between two CVCA certificates. The key
+* encoding will be implicitCA.
+* @param signer the cvca certificate associated with the signing
+* entity
+* @param priv_key the private key associated with the signer
+* @param to_be_signed the certificate which whose CAR/CHR will be
+* the holder of the link certificate
+* @param rng a random number generator
+*/
+EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
+ Private_Key const& priv_key,
+ EAC1_1_CVC const& to_be_signed,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a CVC request. The key encoding will be implicitCA.
+* @param priv_key the private key associated with the requesting entity
+* @param chr the chr to appear in the certificate (to be provided without
+* sequence number)
+* @param hash_alg the string defining the hash algorithm to be used for the creation
+* of the signature
+* @param rng a random number generator
+* @result the new request
+*/
+EAC1_1_Req create_cvc_req(Private_Key const& priv_key,
+ ASN1_Chr const& chr,
+ std::string const& hash_alg,
+ RandomNumberGenerator& rng);
+
+/**
+* Sign a CVC request.
+* @param signer_cert the certificate of the signing entity
+* @param priv_key the private key of the signing entity
+* @param req the request to be signed
+* @param seqnr the sequence number of the certificate to be created
+* @param seqnr_len the number of digits the sequence number will be
+* encoded in
+* @param domestic indicates whether to sign a domestic or a foreign certificate:
+* set to true for domestic
+* @param rng a random number generator
+* @result the new certificate
+*
+**/
+EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
+ Private_Key const& priv_key,
+ EAC1_1_Req const& req,
+ u32bit seqnr,
+ u32bit seqnr_len,
+ bool domestic,
+ u32bit dvca_validity_months,
+ u32bit ca_is_validity_months,
+ RandomNumberGenerator& rng);
+}
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/eac_asn_obj.h b/botan/src/cert/cvc/eac_asn_obj.h
new file mode 100644
index 0000000..3e70f6b
--- /dev/null
+++ b/botan/src/cert/cvc/eac_asn_obj.h
@@ -0,0 +1,244 @@
+/*
+* EAC ASN.1 Objects
+* (C) 2007-2008 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_ASN1_OBJ_H__
+#define BOTAN_EAC_ASN1_OBJ_H__
+
+#include <botan/asn1_obj.h>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* This class represents CVC EAC Time objects.
+* It only models year, month and day. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL EAC_Time : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get a this objects value as a string.
+ * @return the date string
+ */
+ std::string as_string() const;
+
+ /**
+ * Get a this objects value as a readable formatted string.
+ * @return the date string
+ */
+ std::string readable_string() const;
+
+ /**
+ * Find out whether this object's values have been set.
+ * @return true if this object's internal values are set
+ */
+ bool time_is_set() const;
+
+ /**
+ * Compare this to another EAC_Time object.
+ * @return -1 if this object's date is earlier than
+ * other, +1 in the opposite case, and 0 if both dates are
+ * equal.
+ */
+ s32bit cmp(const EAC_Time& other) const;
+
+ /**
+ * Set this' value by a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ void set_to(const std::string& str);
+ //void set_to(const std::string&, ASN1_Tag);
+
+ /**
+ * Add the specified number of years to this.
+ * @param years the number of years to add
+ */
+ void add_years(u32bit years);
+
+ /**
+ * Add the specified number of months to this.
+ * @param months the number of months to add
+ */
+ void add_months(u32bit months);
+
+ /**
+ * Get the year value of this objects.
+ * @return the year value
+ */
+ u32bit get_year() const;
+
+ /**
+ * Get the month value of this objects.
+ * @return the month value
+ */
+ u32bit get_month() const;
+
+ /**
+ * Get the day value of this objects.
+ * @return the day value
+ */
+ u32bit get_day() const;
+
+ EAC_Time(u64bit, ASN1_Tag t = ASN1_Tag(0));
+ //EAC_Time(const std::string& = "");
+ EAC_Time(const std::string&, ASN1_Tag = ASN1_Tag(0));
+ EAC_Time(u32bit year, u32bit month, u32bit day, ASN1_Tag = ASN1_Tag(0));
+
+ virtual ~EAC_Time() {}
+ private:
+ SecureVector<byte> encoded_eac_time() const;
+ bool passes_sanity_check() const;
+ u32bit year, month, day;
+ ASN1_Tag tag;
+ };
+
+/**
+* This class represents CVC CEDs. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL ASN1_Ced : public EAC_Time
+ {
+ public:
+ /**
+ * Construct a CED from a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ ASN1_Ced(std::string const& str = "");
+
+ /**
+ * Construct a CED from a timer value.
+ * @param time the number of seconds elapsed midnight, 1st
+ * January 1970 GMT (or 7pm, 31st December 1969 EST) up to the
+ * desired date
+ */
+ ASN1_Ced(u64bit time);
+
+ /**
+ * Copy constructor (for general EAC_Time objects).
+ * @param other the object to copy from
+ */
+ ASN1_Ced(EAC_Time const& other);
+ //ASN1_Ced(ASN1_Cex const& cex);
+ };
+
+
+/**
+* This class represents CVC CEXs. Only limited sanity checks of
+* the inputted date value are performed.
+*/
+class BOTAN_DLL ASN1_Cex : public EAC_Time
+ {
+ public:
+ /**
+ * Construct a CED from a string value.
+ * @param str a string in the format "yyyy mm dd",
+ * e.g. "2007 08 01"
+ */
+ ASN1_Cex(std::string const& str="");
+
+ /**
+ * Construct a CED from a timer value.
+ * @param time the number of seconds elapsed
+ * midnight, 1st
+ * January 1970 GMT (or 7pm, 31st December 1969 EST)
+ * up to the desired date
+ */
+ ASN1_Cex(u64bit time);
+
+ /**
+ * Copy constructor (for general EAC_Time objects).
+ * @param other the object to copy from
+ */
+ ASN1_Cex(EAC_Time const& other);
+ //ASN1_Cex(ASN1_Ced const& ced);
+ };
+
+/**
+* Base class for car/chr of cv certificates.
+*/
+class BOTAN_DLL ASN1_EAC_String: public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get this objects string value.
+ * @return the string value
+ */
+ std::string value() const;
+
+ /**
+ * Get this objects string value.
+ * @return the string value in iso8859 encoding
+ */
+ std::string iso_8859() const;
+
+ ASN1_Tag tagging() const;
+ ASN1_EAC_String(const std::string& str, ASN1_Tag the_tag);
+
+ virtual ~ASN1_EAC_String() {}
+ protected:
+ bool sanity_check() const;
+ private:
+ std::string iso_8859_str;
+ ASN1_Tag tag;
+ };
+
+/**
+* This class represents CARs of CVCs. (String tagged with 2)
+*/
+class BOTAN_DLL ASN1_Car : public ASN1_EAC_String
+ {
+ public:
+ /**
+ * Create a CAR with the specified content.
+ * @param str the CAR value
+ */
+ ASN1_Car(std::string const& str = "");
+ };
+
+/**
+* This class represents CHRs of CVCs (tag 32)
+*/
+class BOTAN_DLL ASN1_Chr : public ASN1_EAC_String
+ {
+ public:
+ /**
+ * Create a CHR with the specified content.
+ * @param str the CHR value
+ */
+ ASN1_Chr(std::string const& str = "");
+ };
+
+/*
+* Comparison Operations
+*/
+bool operator==(const EAC_Time&, const EAC_Time&);
+bool operator!=(const EAC_Time&, const EAC_Time&);
+bool operator<=(const EAC_Time&, const EAC_Time&);
+bool operator>=(const EAC_Time&, const EAC_Time&);
+bool operator>(const EAC_Time&, const EAC_Time&);
+bool operator<(const EAC_Time&, const EAC_Time&);
+
+bool operator==(const ASN1_EAC_String&, const ASN1_EAC_String&);
+inline bool operator!=(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/eac_obj.h b/botan/src/cert/cvc/eac_obj.h
new file mode 100644
index 0000000..04afd7e
--- /dev/null
+++ b/botan/src/cert/cvc/eac_obj.h
@@ -0,0 +1,131 @@
+/*
+* EAC1_1 objects
+* (C) 2008 Falko Strenzke
+* strenzke@flexsecure.de
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_OBJ_H__
+#define BOTAN_EAC_OBJ_H__
+
+#include <botan/pubkey.h>
+#include <botan/x509_key.h>
+#include <botan/signed_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/pubkey.h>
+#include <botan/parsing.h>
+#include <botan/pem.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/ecdsa_sig.h>
+#include <string>
+
+namespace Botan {
+
+const std::string eac_cvc_emsa("EMSA1_BSI");
+
+/*
+* TR03110 v1.1 EAC CV Certificate
+*/
+template<typename Derived> // CRTP is used enable the call sequence:
+class BOTAN_DLL EAC1_1_obj : public EAC_Signed_Object
+ {
+ // data members first:
+ protected:
+
+ ECDSA_Signature m_sig;
+
+ // member functions here:
+ public:
+ /**
+ * Return the signature as a concatenation of the encoded parts.
+ * @result the concatenated signature
+ */
+ SecureVector<byte> get_concat_sig() const;
+
+ /**
+ * Verify the signature of this objects.
+ * @param pub_key the public key to verify the signature with
+ * @result true if the verification succeeded
+ */
+ virtual bool check_signature(Public_Key& pub_key) const;
+
+ protected:
+ void init(SharedPtrConverter<DataSource> in);
+
+ static SecureVector<byte> make_signature(PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+
+ virtual ~EAC1_1_obj<Derived>(){}
+
+ };
+
+template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_sig() const
+ {
+ return m_sig.get_concatenation();
+ }
+
+template<typename Derived> SecureVector<byte>
+EAC1_1_obj<Derived>::make_signature(PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng)
+ {
+ // this is the signature as a der sequence
+ SecureVector<byte> seq_sig = signer->sign_message(tbs_bits, rng);
+
+ ECDSA_Signature sig(decode_seq(seq_sig));
+ SecureVector<byte> concat_sig(sig.get_concatenation());
+ return concat_sig;
+ }
+
+template<typename Derived> void EAC1_1_obj<Derived>::init(SharedPtrConverter<DataSource> in)
+ {
+ try
+ {
+ Derived::decode_info(in.get_shared(), tbs_bits, m_sig);
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error(PEM_label_pref + " decoding failed");
+ }
+ }
+
+template<typename Derived>
+bool EAC1_1_obj<Derived>::check_signature(Public_Key& pub_key) const
+ {
+ try
+ {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ {
+ return false;
+ }
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ if(!dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key))
+ return false;
+
+ std::auto_ptr<ECDSA_Signature_Encoder> enc(new ECDSA_Signature_Encoder(&m_sig));
+ SecureVector<byte> seq_sig = enc->signature_bits();
+ SecureVector<byte> to_sign = tbs_data();
+
+ PK_Verifying_wo_MR_Key& sig_key = dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key);
+ std::auto_ptr<PK_Verifier> verifier(get_pk_verifier(sig_key, padding, format));
+ return verifier->verify_message(to_sign, seq_sig);
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/ecdsa_sig.cpp b/botan/src/cert/cvc/ecdsa_sig.cpp
new file mode 100644
index 0000000..c33a455
--- /dev/null
+++ b/botan/src/cert/cvc/ecdsa_sig.cpp
@@ -0,0 +1,64 @@
+
+#include <botan/ecdsa_sig.h>
+#include <memory>
+
+namespace Botan {
+
+ECDSA_Signature::ECDSA_Signature(const BigInt& r, const BigInt& s)
+ : m_r(r),
+ m_s(s)
+ {}
+
+ECDSA_Signature::ECDSA_Signature(const ECDSA_Signature& other)
+ : m_r(other.m_r), m_s(other.m_s)
+ {}
+
+ECDSA_Signature const& ECDSA_Signature::operator=(const ECDSA_Signature& other)
+ {
+ m_r = other.m_r;
+ m_s = other.m_s;
+ return *this;
+ }
+
+bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs)
+ {
+ return (lhs.get_r() == rhs.get_r() && lhs.get_s() == rhs.get_s());
+ }
+
+SecureVector<byte> const ECDSA_Signature::get_concatenation() const
+ {
+ u32bit enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); // use the larger
+
+ SecureVector<byte> sv_r = BigInt::encode_1363(m_r, enc_len);
+ SecureVector<byte> sv_s = BigInt::encode_1363(m_s, enc_len);
+
+ SecureVector<byte> result(sv_r);
+ result.append(sv_s);
+ return result;
+ }
+
+ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq)
+ {
+ ECDSA_Signature sig;
+
+ std::auto_ptr<ECDSA_Signature_Decoder> dec(new ECDSA_Signature_Decoder(&sig));
+ dec->signature_bits(seq);
+ return sig;
+ }
+
+ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concat)
+ {
+ if(concat.size() % 2 != 0)
+ throw Invalid_Argument("Erroneous length of signature");
+
+ u32bit rs_len = concat.size()/2;
+ SecureVector<byte> sv_r;
+ SecureVector<byte> sv_s;
+ sv_r.set(concat.begin(), rs_len);
+ sv_s.set(&concat[rs_len], rs_len);
+ BigInt r = BigInt::decode(sv_r, sv_r.size());
+ BigInt s = BigInt::decode(sv_s, sv_s.size());
+ return ECDSA_Signature(r, s);
+ }
+
+}
diff --git a/botan/src/cert/cvc/ecdsa_sig.h b/botan/src/cert/cvc/ecdsa_sig.h
new file mode 100644
index 0000000..15015c7
--- /dev/null
+++ b/botan/src/cert/cvc/ecdsa_sig.h
@@ -0,0 +1,88 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_SIGNATURE_H__
+#define BOTAN_ECDSA_SIGNATURE_H__
+
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+class BOTAN_DLL ECDSA_Signature
+ {
+ public:
+ friend class ECDSA_Signature_Decoder;
+
+ ECDSA_Signature() {}
+ ECDSA_Signature(const BigInt& r, const BigInt& s);
+ ECDSA_Signature(ECDSA_Signature const& other);
+ ECDSA_Signature const& operator=(ECDSA_Signature const& other);
+
+ const BigInt& get_r() const { return m_r; }
+ const BigInt& get_s() const { return m_s; }
+
+ /**
+ * return the r||s
+ */
+ SecureVector<byte> const get_concatenation() const;
+ private:
+ BigInt m_r;
+ BigInt m_s;
+ };
+
+/* Equality of ECDSA_Signature */
+bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs);
+inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+class BOTAN_DLL ECDSA_Signature_Decoder
+ {
+ public:
+ void signature_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(m_signature->m_r)
+ .decode(m_signature->m_s)
+ .verify_end()
+ .end_cons();
+ }
+ ECDSA_Signature_Decoder(ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ ECDSA_Signature* m_signature;
+ };
+
+class BOTAN_DLL ECDSA_Signature_Encoder
+ {
+ public:
+ MemoryVector<byte> signature_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(m_signature->get_r())
+ .encode(m_signature->get_s())
+ .end_cons()
+ .get_contents();
+ }
+ ECDSA_Signature_Encoder(const ECDSA_Signature* signature) : m_signature(signature)
+ {}
+ private:
+ const ECDSA_Signature* m_signature;
+ };
+
+ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq);
+ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation);
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/freestore.h b/botan/src/cert/cvc/freestore.h
new file mode 100644
index 0000000..f95afa8
--- /dev/null
+++ b/botan/src/cert/cvc/freestore.h
@@ -0,0 +1,85 @@
+/**
+* (C) 2007 Christoph Ludwig
+* ludwig@fh-worms.de
+**/
+
+#ifndef BOTAN_FREESTORE_H__
+#define BOTAN_FREESTORE_H__
+
+#include <botan/build.h>
+
+#if defined(BOTAN_USE_STD_TR1)
+ #include <tr1/memory>
+#elif defined(BOTAN_USE_BOOST_TR1)
+ #include <boost/tr1/memory.hpp>
+#else
+ #error "Please choose a TR1 implementation in build.h"
+#endif
+
+namespace Botan {
+
+/**
+* This class is intended as an function call parameter type and
+* enables convenient automatic conversions between plain and smart
+* pointer types. It internally stores a SharedPointer which can be
+* accessed.
+*
+* Distributed under the terms of the Botan license
+*/
+template<typename T>
+class BOTAN_DLL SharedPtrConverter
+ {
+ public:
+ typedef std::tr1::shared_ptr<T> SharedPtr;
+
+ /**
+ * Construct a null pointer equivalent object.
+ */
+ SharedPtrConverter() : ptr() {}
+
+ /**
+ * Copy constructor.
+ */
+ SharedPtrConverter(SharedPtrConverter const& other) :
+ ptr(other.ptr) {}
+
+ /**
+ * Construct a converter object from another pointer type.
+ * @param p the pointer which shall be set as the internally stored
+ * pointer value of this converter.
+ */
+ template<typename Ptr>
+ SharedPtrConverter(Ptr p)
+ : ptr(p) {}
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr const& get_ptr() const { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr get_ptr() { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr const& get_shared() const { return this->ptr; }
+
+ /**
+ * Get the internally stored shared pointer.
+ * @return the internally stored shared pointer
+ */
+ SharedPtr get_shared() { return this->ptr; }
+
+ private:
+ SharedPtr ptr;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/cvc/info.txt b/botan/src/cert/cvc/info.txt
new file mode 100644
index 0000000..e3e11f5
--- /dev/null
+++ b/botan/src/cert/cvc/info.txt
@@ -0,0 +1,44 @@
+realname "Card Verifiable Certificates"
+
+define CARD_VERIFIABLE_CERTIFICATES
+
+uses_tr1 yes
+
+load_on auto
+
+<add>
+asn1_eac_str.cpp
+asn1_eac_tm.cpp
+ecdsa_sig.cpp
+ecdsa_sig.h
+cvc_ado.cpp
+cvc_ado.h
+cvc_ca.cpp
+cvc_ca.h
+cvc_cert.cpp
+cvc_cert.h
+cvc_gen_cert.h
+cvc_key.h
+cvc_req.cpp
+cvc_req.h
+cvc_self.cpp
+cvc_self.h
+eac_asn_obj.h
+eac_obj.h
+signed_obj.cpp
+signed_obj.h
+freestore.h
+</add>
+
+<requires>
+asn1
+bigint
+ecdsa
+filters
+libstate
+oid_lookup
+pem
+pk_codecs
+pubkey
+x509
+</requires>
diff --git a/botan/src/cert/cvc/signed_obj.cpp b/botan/src/cert/cvc/signed_obj.cpp
new file mode 100644
index 0000000..4a08ed0
--- /dev/null
+++ b/botan/src/cert/cvc/signed_obj.cpp
@@ -0,0 +1,67 @@
+/*
+* X.509 SIGNED Object
+* (C) 1999-2007 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/signed_obj.h>
+
+namespace Botan {
+
+/*
+* Return a BER encoded X.509 object
+*/
+SecureVector<byte> EAC_Signed_Object::BER_encode() const
+ {
+ Pipe ber;
+ ber.start_msg();
+ encode(ber, RAW_BER);
+ ber.end_msg();
+ return ber.read_all();
+ }
+
+/*
+* Return a PEM encoded X.509 object
+*/
+std::string EAC_Signed_Object::PEM_encode() const
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*
+* Return the algorithm used to sign this object
+*/
+AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const
+ {
+ return sig_algo;
+ }
+
+/*
+* Try to decode the actual information
+*/
+void EAC_Signed_Object::do_decode()
+ {
+ try {
+ force_decode();
+ }
+ catch(Decoding_Error& e)
+ {
+ const std::string what = e.what();
+ throw Decoding_Error(PEM_label_pref + " decoding failed (" +
+ what.substr(23, std::string::npos) + ")");
+ }
+ catch(Invalid_Argument& e)
+ {
+ const std::string what = e.what();
+ throw Decoding_Error(PEM_label_pref + " decoding failed (" +
+ what.substr(7, std::string::npos) + ")");
+ }
+ }
+
+}
diff --git a/botan/src/cert/cvc/signed_obj.h b/botan/src/cert/cvc/signed_obj.h
new file mode 100644
index 0000000..3c233d2
--- /dev/null
+++ b/botan/src/cert/cvc/signed_obj.h
@@ -0,0 +1,93 @@
+/*
+* EAC SIGNED Object
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAC_SIGNED_OBJECT_H__
+#define BOTAN_EAC_SIGNED_OBJECT_H__
+
+#include <botan/asn1_obj.h>
+#include <botan/pubkey_enums.h>
+#include <botan/freestore.h>
+#include <botan/pipe.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents abstract signed EAC object
+*/
+class BOTAN_DLL EAC_Signed_Object
+ {
+ public:
+ /**
+ * Get the TBS (to-be-signed) data in this object.
+ * @return the DER encoded TBS data of this object
+ */
+ virtual SecureVector<byte> tbs_data() const = 0;
+
+ /**
+ * Get the signature of this object as a concatenation, i.e. if the
+ * signature consists of multiple parts (like in the case of ECDSA)
+ * these will be concatenated.
+ * @return the signature as a concatenation of its parts
+ */
+
+ /*
+ NOTE: this is here only because abstract signature objects have
+ not yet been introduced
+ */
+ virtual SecureVector<byte> get_concat_sig() const = 0;
+
+ /**
+ * Get the signature algorithm identifier used to sign this object.
+ * @result the signature algorithm identifier
+ */
+ AlgorithmIdentifier signature_algorithm() const;
+
+ /**
+ * Check the signature of this object.
+ * @param key the public key associated with this signed object
+ * @return true if the signature was created by the private key
+ * associated with this public key
+ */
+ virtual bool check_signature(class Public_Key&) const = 0;
+
+ /**
+ * Write this object DER encoded into a specified pipe.
+ * @param pipe the pipe to write the encoded object to
+ * @param enc the encoding type to use
+ */
+ virtual void encode(Pipe&, X509_Encoding = PEM) const = 0;
+
+ /**
+ * BER encode this object.
+ * @return the result containing the BER representation of this object.
+ */
+ SecureVector<byte> BER_encode() const;
+
+ /**
+ * PEM encode this object.
+ * @return the result containing the PEM representation of this object.
+ */
+ std::string PEM_encode() const;
+
+ virtual ~EAC_Signed_Object() {}
+ protected:
+ void do_decode();
+ EAC_Signed_Object() {}
+
+ AlgorithmIdentifier sig_algo;
+ SecureVector<byte> tbs_bits;
+ std::string PEM_label_pref;
+ std::vector<std::string> PEM_labels_allowed;
+ private:
+ virtual void force_decode() = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/certstor.cpp b/botan/src/cert/x509/certstor.cpp
new file mode 100644
index 0000000..96f2699
--- /dev/null
+++ b/botan/src/cert/x509/certstor.cpp
@@ -0,0 +1,48 @@
+/*
+* Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/certstor.h>
+
+namespace Botan {
+
+/*
+* Search by name
+*/
+std::vector<X509_Certificate>
+Certificate_Store::by_name(const std::string&) const
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+/*
+* Search by email
+*/
+std::vector<X509_Certificate>
+Certificate_Store::by_email(const std::string&) const
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+/*
+* Search by X.500 distinguished name
+*/
+std::vector<X509_Certificate>
+Certificate_Store::by_dn(const X509_DN&) const
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+/*
+* Find any CRLs that might be useful
+*/
+std::vector<X509_CRL>
+Certificate_Store::get_crls_for(const X509_Certificate&) const
+ {
+ return std::vector<X509_CRL>();
+ }
+
+}
diff --git a/botan/src/cert/x509/certstor.h b/botan/src/cert/x509/certstor.h
new file mode 100644
index 0000000..d5004e3
--- /dev/null
+++ b/botan/src/cert/x509/certstor.h
@@ -0,0 +1,39 @@
+/*
+* Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CERT_STORE_H__
+#define BOTAN_CERT_STORE_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+
+namespace Botan {
+
+/*
+* Certificate Store Interface
+*/
+class BOTAN_DLL Certificate_Store
+ {
+ public:
+ virtual std::vector<X509_Certificate>
+ by_SKID(const MemoryRegion<byte>&) const = 0;
+
+ virtual std::vector<X509_Certificate> by_name(const std::string&) const;
+ virtual std::vector<X509_Certificate> by_email(const std::string&) const;
+ virtual std::vector<X509_Certificate> by_dn(const X509_DN&) const;
+
+ virtual std::vector<X509_CRL>
+ get_crls_for(const X509_Certificate&) const;
+
+ virtual Certificate_Store* clone() const = 0;
+
+ virtual ~Certificate_Store() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/crl_ent.cpp b/botan/src/cert/x509/crl_ent.cpp
new file mode 100644
index 0000000..afea8cf
--- /dev/null
+++ b/botan/src/cert/x509/crl_ent.cpp
@@ -0,0 +1,107 @@
+/*
+* CRL Entry
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/crl_ent.h>
+#include <botan/x509_ext.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/oids.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*
+* Create a CRL_Entry
+*/
+CRL_Entry::CRL_Entry(bool t_on_unknown_crit) :
+ throw_on_unknown_critical(t_on_unknown_crit)
+ {
+ reason = UNSPECIFIED;
+ }
+
+/*
+* Create a CRL_Entry
+*/
+CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) :
+ throw_on_unknown_critical(false)
+ {
+ serial = cert.serial_number();
+ time = X509_Time(system_time());
+ reason = why;
+ }
+
+/*
+* Compare two CRL_Entrys for equality
+*/
+bool operator==(const CRL_Entry& a1, const CRL_Entry& a2)
+ {
+ if(a1.serial_number() != a2.serial_number())
+ return false;
+ if(a1.expire_time() != a2.expire_time())
+ return false;
+ if(a1.reason_code() != a2.reason_code())
+ return false;
+ return true;
+ }
+
+/*
+* Compare two CRL_Entrys for inequality
+*/
+bool operator!=(const CRL_Entry& a1, const CRL_Entry& a2)
+ {
+ return !(a1 == a2);
+ }
+
+/*
+* Compare two CRL_Entrys
+*/
+bool operator<(const CRL_Entry& a1, const CRL_Entry& a2)
+ {
+ return (a1.expire_time().cmp(a2.expire_time()) < 0);
+ }
+
+/*
+* DER encode a CRL_Entry
+*/
+void CRL_Entry::encode_into(DER_Encoder& der) const
+ {
+ Extensions extensions;
+
+ extensions.add(new Cert_Extension::CRL_ReasonCode(reason));
+
+ der.start_cons(SEQUENCE)
+ .encode(BigInt::decode(serial, serial.size()))
+ .encode(time)
+ .encode(extensions)
+ .end_cons();
+ }
+
+/*
+* Decode a BER encoded CRL_Entry
+*/
+void CRL_Entry::decode_from(BER_Decoder& source)
+ {
+ BigInt serial_number_bn;
+
+ source.start_cons(SEQUENCE)
+ .decode(serial_number_bn)
+ .decode(time);
+
+ if(source.more_items())
+ {
+ Extensions extensions(throw_on_unknown_critical);
+ source.decode(extensions);
+ Data_Store info;
+ extensions.contents_to(info, info);
+ reason = CRL_Code(info.get1_u32bit("X509v3.CRLReasonCode"));
+ }
+
+ serial = BigInt::encode(serial_number_bn);
+ }
+
+}
diff --git a/botan/src/cert/x509/crl_ent.h b/botan/src/cert/x509/crl_ent.h
new file mode 100644
index 0000000..050356c
--- /dev/null
+++ b/botan/src/cert/x509/crl_ent.h
@@ -0,0 +1,78 @@
+/*
+* CRL Entry
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRL_ENTRY_H__
+#define BOTAN_CRL_ENTRY_H__
+
+#include <botan/x509cert.h>
+
+namespace Botan {
+
+/**
+* This class represents CRL entries
+*/
+class BOTAN_DLL CRL_Entry : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ /**
+ * Get the serial number of the certificate associated with this entry.
+ * @return the certificate's serial number
+ */
+ MemoryVector<byte> serial_number() const { return serial; }
+
+ /**
+ * Get the revocation date of the certificate associated with this entry
+ * @return the certificate's revocation date
+ */
+ X509_Time expire_time() const { return time; }
+
+ /**
+ * Get the entries reason code
+ * @return the reason code
+ */
+ CRL_Code reason_code() const { return reason; }
+
+ /**
+ * Construct an empty CRL entry.
+ */
+ CRL_Entry(bool throw_on_unknown_critical_extension = false);
+
+ /**
+ * Construct an CRL entry.
+ * @param cert the certificate to revoke
+ * @param reason the reason code to set in the entry
+ */
+ CRL_Entry(const X509_Certificate&, CRL_Code = UNSPECIFIED);
+
+ private:
+ bool throw_on_unknown_critical;
+ MemoryVector<byte> serial;
+ X509_Time time;
+ CRL_Code reason;
+ };
+
+/**
+* Test two CRL entries for equality in all fields.
+*/
+BOTAN_DLL bool operator==(const CRL_Entry&, const CRL_Entry&);
+
+/**
+* Test two CRL entries for inequality in at least one field.
+*/
+BOTAN_DLL bool operator!=(const CRL_Entry&, const CRL_Entry&);
+
+/**
+* Order two entries based on the revocation date.
+*/
+BOTAN_DLL bool operator<(const CRL_Entry&, const CRL_Entry&);
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/info.txt b/botan/src/cert/x509/info.txt
new file mode 100644
index 0000000..552e2aa
--- /dev/null
+++ b/botan/src/cert/x509/info.txt
@@ -0,0 +1,45 @@
+realname "X.509"
+
+define X509
+
+load_on auto
+
+<add>
+certstor.h
+certstor.cpp
+crl_ent.cpp
+crl_ent.h
+pkcs10.h
+pkcs10.cpp
+x509_ca.cpp
+x509_ca.h
+x509_crl.cpp
+x509_crl.h
+x509_ext.cpp
+x509_ext.h
+x509_obj.cpp
+x509_obj.h
+x509cert.cpp
+x509cert.h
+x509find.cpp
+x509find.h
+x509opt.cpp
+x509self.cpp
+x509self.h
+x509stor.cpp
+x509stor.h
+</add>
+
+<requires>
+asn1
+bigint
+datastor
+filters
+libstate
+oid_lookup
+pem
+pk_codecs
+pubkey
+rng
+sha1
+</requires>
diff --git a/botan/src/cert/x509/pkcs10.cpp b/botan/src/cert/x509/pkcs10.cpp
new file mode 100644
index 0000000..5617cec
--- /dev/null
+++ b/botan/src/cert/x509/pkcs10.cpp
@@ -0,0 +1,200 @@
+/*
+* PKCS #10
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pkcs10.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/x509stor.h>
+#include <botan/x509_ext.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+/*
+* PKCS10_Request Constructor
+*/
+PKCS10_Request::PKCS10_Request(DataSource& in) :
+ X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST")
+ {
+ do_decode();
+ }
+
+/*
+* PKCS10_Request Constructor
+*/
+PKCS10_Request::PKCS10_Request(const std::string& in) :
+ X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST")
+ {
+ do_decode();
+ }
+
+/*
+* Deocde the CertificateRequestInfo
+*/
+void PKCS10_Request::force_decode()
+ {
+ BER_Decoder cert_req_info(tbs_bits);
+
+ u32bit version;
+ cert_req_info.decode(version);
+ if(version != 0)
+ throw Decoding_Error("Unknown version code in PKCS #10 request: " +
+ to_string(version));
+
+ X509_DN dn_subject;
+ cert_req_info.decode(dn_subject);
+
+ info.add(dn_subject.contents());
+
+ BER_Object public_key = cert_req_info.get_next_object();
+ if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
+ throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key",
+ public_key.type_tag, public_key.class_tag);
+
+ info.add("X509.Certificate.public_key",
+ PEM_Code::encode(
+ ASN1::put_in_sequence(public_key.value),
+ "PUBLIC KEY"
+ )
+ );
+
+ BER_Object attr_bits = cert_req_info.get_next_object();
+
+ if(attr_bits.type_tag == 0 &&
+ attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ BER_Decoder attributes(attr_bits.value);
+ while(attributes.more_items())
+ {
+ Attribute attr;
+ attributes.decode(attr);
+ handle_attribute(attr);
+ }
+ attributes.verify_end();
+ }
+ else if(attr_bits.type_tag != NO_OBJECT)
+ throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes",
+ attr_bits.type_tag, attr_bits.class_tag);
+
+ cert_req_info.verify_end();
+
+ X509_Code sig_check = X509_Store::check_sig(*this, subject_public_key());
+ if(sig_check != VERIFIED)
+ throw Decoding_Error("PKCS #10 request: Bad signature detected");
+ }
+
+/*
+* Handle attributes in a PKCS #10 request
+*/
+void PKCS10_Request::handle_attribute(const Attribute& attr)
+ {
+ BER_Decoder value(attr.parameters);
+
+ if(attr.oid == OIDS::lookup("PKCS9.EmailAddress"))
+ {
+ ASN1_String email;
+ value.decode(email);
+ info.add("RFC822", email.value());
+ }
+ else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword"))
+ {
+ ASN1_String challenge_password;
+ value.decode(challenge_password);
+ info.add("PKCS9.ChallengePassword", challenge_password.value());
+ }
+ else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest"))
+ {
+ Extensions extensions;
+ value.decode(extensions).verify_end();
+
+ Data_Store issuer_info;
+ extensions.contents_to(info, issuer_info);
+ }
+ }
+
+/*
+* Return the challenge password (if any)
+*/
+std::string PKCS10_Request::challenge_password() const
+ {
+ return info.get1("PKCS9.ChallengePassword");
+ }
+
+/*
+* Return the name of the requestor
+*/
+X509_DN PKCS10_Request::subject_dn() const
+ {
+ return create_dn(info);
+ }
+
+/*
+* Return the public key of the requestor
+*/
+MemoryVector<byte> PKCS10_Request::raw_public_key() const
+ {
+ DataSource_Memory source(info.get1("X509.Certificate.public_key"));
+ return PEM_Code::decode_check_label(source, "PUBLIC KEY");
+ }
+
+/*
+* Return the public key of the requestor
+*/
+Public_Key* PKCS10_Request::subject_public_key() const
+ {
+ DataSource_Memory source(info.get1("X509.Certificate.public_key"));
+ return X509::load_key(source);
+ }
+
+/*
+* Return the alternative names of the requestor
+*/
+AlternativeName PKCS10_Request::subject_alt_name() const
+ {
+ return create_alt_name(info);
+ }
+
+/*
+* Return the key constraints (if any)
+*/
+Key_Constraints PKCS10_Request::constraints() const
+ {
+ return Key_Constraints(info.get1_u32bit("X509v3.KeyUsage", NO_CONSTRAINTS));
+ }
+
+/*
+* Return the extendend key constraints (if any)
+*/
+std::vector<OID> PKCS10_Request::ex_constraints() const
+ {
+ std::vector<std::string> oids = info.get("X509v3.ExtendedKeyUsage");
+
+ std::vector<OID> result;
+ for(u32bit j = 0; j != oids.size(); ++j)
+ result.push_back(OID(oids[j]));
+ return result;
+ }
+
+/*
+* Return is a CA certificate is requested
+*/
+bool PKCS10_Request::is_CA() const
+ {
+ return info.get1_u32bit("X509v3.BasicConstraints.is_ca");
+ }
+
+/*
+* Return the desired path limit (if any)
+*/
+u32bit PKCS10_Request::path_limit() const
+ {
+ return info.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0);
+ }
+
+}
diff --git a/botan/src/cert/x509/pkcs10.h b/botan/src/cert/x509/pkcs10.h
new file mode 100644
index 0000000..9b435de
--- /dev/null
+++ b/botan/src/cert/x509/pkcs10.h
@@ -0,0 +1,101 @@
+/*
+* PKCS #10
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS10_H__
+#define BOTAN_PKCS10_H__
+
+#include <botan/x509_obj.h>
+#include <botan/pkcs8.h>
+#include <botan/datastor.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* PKCS #10 Certificate Request.
+*/
+class BOTAN_DLL PKCS10_Request : public X509_Object
+ {
+ public:
+ /**
+ * Get the subject public key.
+ * @return the subject public key
+ */
+ Public_Key* subject_public_key() const;
+
+ /**
+ * Get the raw DER encoded public key.
+ * @return the raw DER encoded public key
+ */
+ MemoryVector<byte> raw_public_key() const;
+
+ /**
+ * Get the subject DN.
+ * @return the subject DN
+ */
+ X509_DN subject_dn() const;
+
+ /**
+ * Get the subject alternative name.
+ * @return the subject alternative name.
+ */
+ AlternativeName subject_alt_name() const;
+
+ /**
+ * Get the key constraints for the key associated with this
+ * PKCS#10 object.
+ * @return the key constraints
+ */
+ Key_Constraints constraints() const;
+
+ /**
+ * Get the extendend key constraints (if any).
+ * @return the extended key constraints
+ */
+ std::vector<OID> ex_constraints() const;
+
+ /**
+ * Find out whether this is a CA request.
+ * @result true if it is a CA request, false otherwise.
+ */
+ bool is_CA() const;
+
+ /**
+ * Return the constraint on the path length defined
+ * in the BasicConstraints extension.
+ * @return the path limit
+ */
+ u32bit path_limit() const;
+
+ /**
+ * Get the challenge password for this request
+ * @return the challenge password for this request
+ */
+ std::string challenge_password() const;
+
+ /**
+ * Create a PKCS#10 Request from a data source.
+ * @param source the data source providing the DER encoded request
+ */
+ PKCS10_Request(DataSource& source);
+
+ /**
+ * Create a PKCS#10 Request from a file.
+ * @param filename the name of the file containing the DER or PEM
+ * encoded request file
+ */
+ PKCS10_Request(const std::string& filename);
+ private:
+ void force_decode();
+ void handle_attribute(const Attribute&);
+
+ Data_Store info;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509_ca.cpp b/botan/src/cert/x509/x509_ca.cpp
new file mode 100644
index 0000000..41e3147
--- /dev/null
+++ b/botan/src/cert/x509/x509_ca.cpp
@@ -0,0 +1,284 @@
+/*
+* X.509 Certificate Authority
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_ca.h>
+#include <botan/x509stor.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/look_pk.h>
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+#include <botan/oids.h>
+#include <botan/util.h>
+#include <algorithm>
+#include <typeinfo>
+#include <iterator>
+#include <memory>
+#include <set>
+
+namespace Botan {
+
+/*
+* Load the certificate and private key
+*/
+X509_CA::X509_CA(const X509_Certificate& c,
+ const Private_Key& key) : cert(c)
+ {
+ const Private_Key* key_pointer = &key;
+ if(!dynamic_cast<const PK_Signing_Key*>(key_pointer))
+ throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign");
+
+ if(!cert.is_CA_cert())
+ throw Invalid_Argument("X509_CA: This certificate is not for a CA");
+
+ signer = choose_sig_format(key, ca_sig_algo);
+ }
+
+/*
+* Sign a PKCS #10 certificate request
+*/
+X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
+ RandomNumberGenerator& rng,
+ const X509_Time& not_before,
+ const X509_Time& not_after)
+ {
+ Key_Constraints constraints;
+ if(req.is_CA())
+ constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
+ else
+ {
+ std::auto_ptr<Public_Key> key(req.subject_public_key());
+ constraints = X509::find_constraints(*key, req.constraints());
+ }
+
+ Extensions extensions;
+
+ extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
+ extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key()));
+
+ extensions.add(
+ new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()));
+
+ extensions.add(new Cert_Extension::Key_Usage(constraints));
+ extensions.add(
+ new Cert_Extension::Extended_Key_Usage(req.ex_constraints()));
+
+ extensions.add(
+ new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name()));
+
+ return make_cert(signer, rng, ca_sig_algo, req.raw_public_key(),
+ not_before, not_after,
+ cert.subject_dn(), req.subject_dn(),
+ extensions);
+ }
+
+/*
+* Create a new certificate
+*/
+X509_Certificate X509_CA::make_cert(PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& sig_algo,
+ const MemoryRegion<byte>& pub_key,
+ const X509_Time& not_before,
+ const X509_Time& not_after,
+ const X509_DN& issuer_dn,
+ const X509_DN& subject_dn,
+ const Extensions& extensions)
+ {
+ const u32bit X509_CERT_VERSION = 3;
+ const u32bit SERIAL_BITS = 128;
+
+ BigInt serial_no(rng, SERIAL_BITS);
+
+ DataSource_Memory source(X509_Object::make_signed(signer, rng, sig_algo,
+ DER_Encoder().start_cons(SEQUENCE)
+ .start_explicit(0)
+ .encode(X509_CERT_VERSION-1)
+ .end_explicit()
+
+ .encode(serial_no)
+
+ .encode(sig_algo)
+ .encode(issuer_dn)
+
+ .start_cons(SEQUENCE)
+ .encode(not_before)
+ .encode(not_after)
+ .end_cons()
+
+ .encode(subject_dn)
+ .raw_bytes(pub_key)
+
+ .start_explicit(3)
+ .start_cons(SEQUENCE)
+ .encode(extensions)
+ .end_cons()
+ .end_explicit()
+ .end_cons()
+ .get_contents()
+ ));
+
+ return X509_Certificate(source);
+ }
+
+/*
+* Create a new, empty CRL
+*/
+X509_CRL X509_CA::new_crl(RandomNumberGenerator& rng,
+ u32bit next_update) const
+ {
+ std::vector<CRL_Entry> empty;
+ return make_crl(empty, 1, next_update, rng);
+ }
+
+/*
+* Update a CRL with new entries
+*/
+X509_CRL X509_CA::update_crl(const X509_CRL& crl,
+ const std::vector<CRL_Entry>& new_revoked,
+ RandomNumberGenerator& rng,
+ u32bit next_update) const
+ {
+ std::vector<CRL_Entry> already_revoked = crl.get_revoked();
+ std::vector<CRL_Entry> all_revoked;
+
+ X509_Store store;
+ store.add_cert(cert, true);
+ if(store.add_crl(crl) != VERIFIED)
+ throw Invalid_Argument("X509_CA::update_crl: Invalid CRL provided");
+
+ std::set<SecureVector<byte> > removed_from_crl;
+ for(u32bit j = 0; j != new_revoked.size(); ++j)
+ {
+ if(new_revoked[j].reason_code() == DELETE_CRL_ENTRY)
+ removed_from_crl.insert(new_revoked[j].serial_number());
+ else
+ all_revoked.push_back(new_revoked[j]);
+ }
+
+ for(u32bit j = 0; j != already_revoked.size(); ++j)
+ {
+ std::set<SecureVector<byte> >::const_iterator i;
+ i = removed_from_crl.find(already_revoked[j].serial_number());
+
+ if(i == removed_from_crl.end())
+ all_revoked.push_back(already_revoked[j]);
+ }
+ std::sort(all_revoked.begin(), all_revoked.end());
+
+ std::vector<CRL_Entry> cert_list;
+ std::unique_copy(all_revoked.begin(), all_revoked.end(),
+ std::back_inserter(cert_list));
+
+ return make_crl(cert_list, crl.crl_number() + 1, next_update, rng);
+ }
+
+/*
+* Create a CRL
+*/
+X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
+ u32bit crl_number, u32bit next_update,
+ RandomNumberGenerator& rng) const
+ {
+ const u32bit X509_CRL_VERSION = 2;
+
+ if(next_update == 0)
+ next_update = timespec_to_u32bit("7d");
+
+ // Totally stupid: ties encoding logic to the return of std::time!!
+ const u64bit current_time = system_time();
+
+ Extensions extensions;
+ extensions.add(
+ new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
+ extensions.add(new Cert_Extension::CRL_Number(crl_number));
+
+ DataSource_Memory source(X509_Object::make_signed(signer, rng, ca_sig_algo,
+ DER_Encoder().start_cons(SEQUENCE)
+ .encode(X509_CRL_VERSION-1)
+ .encode(ca_sig_algo)
+ .encode(cert.issuer_dn())
+ .encode(X509_Time(current_time))
+ .encode(X509_Time(current_time + next_update))
+ .encode_if(revoked.size() > 0,
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(revoked)
+ .end_cons()
+ )
+ .start_explicit(0)
+ .start_cons(SEQUENCE)
+ .encode(extensions)
+ .end_cons()
+ .end_explicit()
+ .end_cons()
+ .get_contents()
+ ));
+
+ return X509_CRL(source);
+ }
+
+/*
+* Return the CA's certificate
+*/
+X509_Certificate X509_CA::ca_certificate() const
+ {
+ return cert;
+ }
+
+/*
+* X509_CA Destructor
+*/
+X509_CA::~X509_CA()
+ {
+ delete signer;
+ }
+
+/*
+* Choose a signing format for the key
+*/
+PK_Signer* choose_sig_format(const Private_Key& key,
+ AlgorithmIdentifier& sig_algo)
+ {
+ std::string padding;
+ Signature_Format format;
+
+ const std::string algo_name = key.algo_name();
+
+ if(algo_name == "RSA")
+ {
+ padding = "EMSA3(SHA-160)";
+ format = IEEE_1363;
+ }
+ else if(algo_name == "DSA")
+ {
+ padding = "EMSA1(SHA-160)";
+ format = DER_SEQUENCE;
+ }
+ else if(algo_name == "ECDSA")
+ {
+ padding = "EMSA1_BSI(SHA-160)";
+ format = IEEE_1363;
+ }
+ else
+ throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
+
+ sig_algo.oid = OIDS::lookup(algo_name + "/" + padding);
+
+ std::auto_ptr<X509_Encoder> encoding(key.x509_encoder());
+ if(!encoding.get())
+ throw Encoding_Error("Key " + algo_name + " does not support "
+ "X.509 encoding");
+
+ sig_algo.parameters = encoding->alg_id().parameters;
+
+ const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key);
+
+ return get_pk_signer(sig_key, padding, format);
+ }
+
+}
diff --git a/botan/src/cert/x509/x509_ca.h b/botan/src/cert/x509/x509_ca.h
new file mode 100644
index 0000000..ef2a8d1
--- /dev/null
+++ b/botan/src/cert/x509/x509_ca.h
@@ -0,0 +1,108 @@
+/*
+* X.509 Certificate Authority
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CA_H__
+#define BOTAN_X509_CA_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/x509_ext.h>
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate Authorities (CAs).
+*/
+class BOTAN_DLL X509_CA
+ {
+ public:
+
+ /**
+ * Sign a PKCS#10 Request.
+ * @param req the request to sign
+ * @param rng the rng to use
+ * @param not_before the starting time for the certificate
+ * @param not_after the expiration time for the certificate
+ * @return the resulting certificate
+ */
+ X509_Certificate sign_request(const PKCS10_Request& req,
+ RandomNumberGenerator& rng,
+ const X509_Time& not_before,
+ const X509_Time& not_after);
+
+ /**
+ * Get the certificate of this CA.
+ * @return the CA certificate
+ */
+ X509_Certificate ca_certificate() const;
+
+ /**
+ * Create a new and empty CRL for this CA.
+ * @param rng the random number generator to use
+ * @param next_update the time to set in next update in seconds
+ * as the offset from the current time
+ * @return the new CRL
+ */
+ X509_CRL new_crl(RandomNumberGenerator& rng, u32bit = 0) const;
+
+ /**
+ * Create a new CRL by with additional entries.
+ * @param last_crl the last CRL of this CA to add the new entries to
+ * @param new_entries contains the new CRL entries to be added to the CRL
+ * @param rng the random number generator to use
+ * @param next_update the time to set in next update in seconds
+ * as the offset from the current time
+ */
+ X509_CRL update_crl(const X509_CRL& last_crl,
+ const std::vector<CRL_Entry>& new_entries,
+ RandomNumberGenerator& rng,
+ u32bit next_update = 0) const;
+
+ static X509_Certificate make_cert(PK_Signer*,
+ RandomNumberGenerator&,
+ const AlgorithmIdentifier&,
+ const MemoryRegion<byte>&,
+ const X509_Time&, const X509_Time&,
+ const X509_DN&, const X509_DN&,
+ const Extensions&);
+
+ /**
+ * Create a new CA object.
+ * @param ca_certificate the certificate of the CA
+ * @param key the private key of the CA
+ */
+ X509_CA(const X509_Certificate& ca_certificate, const Private_Key& key);
+ ~X509_CA();
+ private:
+ X509_CA(const X509_CA&) {}
+ X509_CA& operator=(const X509_CA&) { return (*this); }
+
+ X509_CRL make_crl(const std::vector<CRL_Entry>&,
+ u32bit, u32bit, RandomNumberGenerator&) const;
+
+ AlgorithmIdentifier ca_sig_algo;
+ X509_Certificate cert;
+ PK_Signer* signer;
+ };
+
+/**
+* Choose the default signature format for a certain public key signature
+* scheme.
+* @param key will be the key to choose a padding scheme for
+* @param alg_id will be set to the chosen scheme
+* @return A PK_Signer object for generating signatures
+*/
+BOTAN_DLL PK_Signer* choose_sig_format(const Private_Key& key,
+ AlgorithmIdentifier& alg_id);
+
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509_crl.cpp b/botan/src/cert/x509/x509_crl.cpp
new file mode 100644
index 0000000..f6a344d
--- /dev/null
+++ b/botan/src/cert/x509/x509_crl.cpp
@@ -0,0 +1,147 @@
+/*
+* X.509 CRL
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_crl.h>
+#include <botan/x509_ext.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/bigint.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* Load a X.509 CRL
+*/
+X509_CRL::X509_CRL(DataSource& in, bool touc) :
+ X509_Object(in, "X509 CRL/CRL"), throw_on_unknown_critical(touc)
+ {
+ do_decode();
+ }
+
+/*
+* Load a X.509 CRL
+*/
+X509_CRL::X509_CRL(const std::string& in, bool touc) :
+ X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(touc)
+ {
+ do_decode();
+ }
+
+/*
+* Decode the TBSCertList data
+*/
+void X509_CRL::force_decode()
+ {
+ BER_Decoder tbs_crl(tbs_bits);
+
+ u32bit version;
+ tbs_crl.decode_optional(version, INTEGER, UNIVERSAL);
+
+ if(version != 0 && version != 1)
+ throw X509_CRL_Error("Unknown X.509 CRL version " +
+ to_string(version+1));
+
+ AlgorithmIdentifier sig_algo_inner;
+ tbs_crl.decode(sig_algo_inner);
+
+ if(sig_algo != sig_algo_inner)
+ throw X509_CRL_Error("Algorithm identifier mismatch");
+
+ X509_DN dn_issuer;
+ tbs_crl.decode(dn_issuer);
+ info.add(dn_issuer.contents());
+
+ X509_Time start, end;
+ tbs_crl.decode(start).decode(end);
+ info.add("X509.CRL.start", start.readable_string());
+ info.add("X509.CRL.end", end.readable_string());
+
+ BER_Object next = tbs_crl.get_next_object();
+
+ if(next.type_tag == SEQUENCE && next.class_tag == CONSTRUCTED)
+ {
+ BER_Decoder cert_list(next.value);
+
+ while(cert_list.more_items())
+ {
+ CRL_Entry entry(throw_on_unknown_critical);
+ cert_list.decode(entry);
+ revoked.push_back(entry);
+ }
+ next = tbs_crl.get_next_object();
+ }
+
+ if(next.type_tag == 0 &&
+ next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ BER_Decoder crl_options(next.value);
+
+ Extensions extensions(throw_on_unknown_critical);
+
+ crl_options.decode(extensions).verify_end();
+
+ extensions.contents_to(info, info);
+
+ next = tbs_crl.get_next_object();
+ }
+
+ if(next.type_tag != NO_OBJECT)
+ throw X509_CRL_Error("Unknown tag in CRL");
+
+ tbs_crl.verify_end();
+ }
+
+/*
+* Return the list of revoked certificates
+*/
+std::vector<CRL_Entry> X509_CRL::get_revoked() const
+ {
+ return revoked;
+ }
+
+/*
+* Return the distinguished name of the issuer
+*/
+X509_DN X509_CRL::issuer_dn() const
+ {
+ return create_dn(info);
+ }
+
+/*
+* Return the key identifier of the issuer
+*/
+MemoryVector<byte> X509_CRL::authority_key_id() const
+ {
+ return info.get1_memvec("X509v3.AuthorityKeyIdentifier");
+ }
+
+/*
+* Return the CRL number of this CRL
+*/
+u32bit X509_CRL::crl_number() const
+ {
+ return info.get1_u32bit("X509v3.CRLNumber");
+ }
+
+/*
+* Return the issue data of the CRL
+*/
+X509_Time X509_CRL::this_update() const
+ {
+ return info.get1("X509.CRL.start");
+ }
+
+/*
+* Return the date when a new CRL will be issued
+*/
+X509_Time X509_CRL::next_update() const
+ {
+ return info.get1("X509.CRL.end");
+ }
+
+}
diff --git a/botan/src/cert/x509/x509_crl.h b/botan/src/cert/x509/x509_crl.h
new file mode 100644
index 0000000..6caef42
--- /dev/null
+++ b/botan/src/cert/x509/x509_crl.h
@@ -0,0 +1,90 @@
+/*
+* X.509 CRL
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CRL_H__
+#define BOTAN_X509_CRL_H__
+
+#include <botan/x509_obj.h>
+#include <botan/crl_ent.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate Revocation Lists (CRLs).
+*/
+class BOTAN_DLL X509_CRL : public X509_Object
+ {
+ public:
+ /**
+ * This class represents CRL related errors.
+ */
+ struct X509_CRL_Error : public Exception
+ {
+ X509_CRL_Error(const std::string& error) :
+ Exception("X509_CRL: " + error) {}
+ };
+
+ /**
+ * Get the entries of this CRL in the form of a vector.
+ * @return a vector containing the entries of this CRL.
+ */
+ std::vector<CRL_Entry> get_revoked() const;
+
+ /**
+ * Get the issuer DN of this CRL.
+ * @return the CRLs issuer DN
+ */
+ X509_DN issuer_dn() const;
+
+ /**
+ * Get the AuthorityKeyIdentifier of this CRL.
+ * @return this CRLs AuthorityKeyIdentifier
+ */
+ MemoryVector<byte> authority_key_id() const;
+
+ /**
+ * Get the serial number of this CRL.
+ * @return the CRLs serial number
+ */
+ u32bit crl_number() const;
+
+ /**
+ * Get the CRL's thisUpdate value.
+ * @return the CRLs thisUpdate
+ */
+ X509_Time this_update() const;
+
+ /**
+ * Get the CRL's nextUpdate value.
+ * @return the CRLs nextdUpdate
+ */
+ X509_Time next_update() const;
+
+ /**
+ * Construct a CRL from a data source.
+ * @param source the data source providing the DER or PEM encoded CRL.
+ */
+ X509_CRL(DataSource&, bool throw_on_unknown_critical = false);
+
+ /**
+ * Construct a CRL from a file containing the DER or PEM encoded CRL.
+ * @param filename the name of the CRL file
+ */
+ X509_CRL(const std::string& filename,
+ bool throw_on_unknown_critical = false);
+ private:
+ void force_decode();
+
+ bool throw_on_unknown_critical;
+ std::vector<CRL_Entry> revoked;
+ Data_Store info;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509_ext.cpp b/botan/src/cert/x509/x509_ext.cpp
new file mode 100644
index 0000000..5e07cbd
--- /dev/null
+++ b/botan/src/cert/x509/x509_ext.cpp
@@ -0,0 +1,581 @@
+/*
+* X.509 Certificate Extensions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_ext.h>
+#include <botan/sha160.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+#include <botan/libstate.h>
+#include <botan/bit_ops.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*
+* List of X.509 Certificate Extensions
+*/
+Certificate_Extension* Extensions::get_extension(const OID& oid)
+ {
+#define X509_EXTENSION(NAME, TYPE) \
+ if(OIDS::name_of(oid, NAME)) \
+ return new Cert_Extension::TYPE();
+
+ X509_EXTENSION("X509v3.KeyUsage", Key_Usage);
+ X509_EXTENSION("X509v3.BasicConstraints", Basic_Constraints);
+ X509_EXTENSION("X509v3.SubjectKeyIdentifier", Subject_Key_ID);
+ X509_EXTENSION("X509v3.AuthorityKeyIdentifier", Authority_Key_ID);
+ X509_EXTENSION("X509v3.ExtendedKeyUsage", Extended_Key_Usage);
+ X509_EXTENSION("X509v3.IssuerAlternativeName", Issuer_Alternative_Name);
+ X509_EXTENSION("X509v3.SubjectAlternativeName", Subject_Alternative_Name);
+ X509_EXTENSION("X509v3.CRLNumber", CRL_Number);
+ X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies);
+
+ return 0;
+ }
+
+/*
+* Extensions Copy Constructor
+*/
+Extensions::Extensions(const Extensions& extensions) : ASN1_Object()
+ {
+ *this = extensions;
+ }
+
+/*
+* Extensions Assignment Operator
+*/
+Extensions& Extensions::operator=(const Extensions& other)
+ {
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+ extensions.clear();
+
+ for(u32bit j = 0; j != other.extensions.size(); ++j)
+ extensions.push_back(other.extensions[j]->copy());
+
+ return (*this);
+ }
+
+/*
+* Return the OID of this extension
+*/
+OID Certificate_Extension::oid_of() const
+ {
+ return OIDS::lookup(oid_name());
+ }
+
+/*
+* Encode an Extensions list
+*/
+void Extensions::encode_into(DER_Encoder& to_object) const
+ {
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ {
+ const Certificate_Extension* ext = extensions[j];
+
+ std::string setting;
+
+ if(ext->config_id() != "")
+ setting = global_state().option("x509/exts/" + ext->config_id());
+
+ if(setting == "")
+ setting = "yes";
+
+ if(setting != "yes" && setting != "no" && setting != "critical")
+ throw Invalid_Argument("X509_CA:: Invalid value for option "
+ "x509/exts/" + ext->config_id() + " of " +
+ setting);
+
+ bool is_critical = (setting == "critical");
+ bool should_encode = ext->should_encode() && (setting != "no");
+
+ if(should_encode)
+ {
+ to_object.start_cons(SEQUENCE)
+ .encode(ext->oid_of())
+ .encode_optional(is_critical, false)
+ .encode(ext->encode_inner(), OCTET_STRING)
+ .end_cons();
+ }
+ }
+ }
+
+/*
+* Decode a list of Extensions
+*/
+void Extensions::decode_from(BER_Decoder& from_source)
+ {
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+ extensions.clear();
+
+ BER_Decoder sequence = from_source.start_cons(SEQUENCE);
+ while(sequence.more_items())
+ {
+ OID oid;
+ MemoryVector<byte> value;
+ bool critical;
+
+ sequence.start_cons(SEQUENCE)
+ .decode(oid)
+ .decode_optional(critical, BOOLEAN, UNIVERSAL, false)
+ .decode(value, OCTET_STRING)
+ .verify_end()
+ .end_cons();
+
+ Certificate_Extension* ext = get_extension(oid);
+
+ if(!ext)
+ {
+ if(!critical || !should_throw)
+ continue;
+
+ throw Decoding_Error("Encountered unknown X.509 extension marked "
+ "as critical; OID = " + oid.as_string());
+ }
+
+ ext->decode_inner(value);
+
+ extensions.push_back(ext);
+ }
+ sequence.verify_end();
+ }
+
+/*
+* Write the extensions to an info store
+*/
+void Extensions::contents_to(Data_Store& subject_info,
+ Data_Store& issuer_info) const
+ {
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ extensions[j]->contents_to(subject_info, issuer_info);
+ }
+
+/*
+* Delete an Extensions list
+*/
+Extensions::~Extensions()
+ {
+ for(u32bit j = 0; j != extensions.size(); ++j)
+ delete extensions[j];
+ }
+
+namespace Cert_Extension {
+
+/*
+* Checked accessor for the path_limit member
+*/
+u32bit Basic_Constraints::get_path_limit() const
+ {
+ if(!is_ca)
+ throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
+ return path_limit;
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Basic_Constraints::encode_inner() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_if(is_ca,
+ DER_Encoder()
+ .encode(is_ca)
+ .encode_optional(path_limit, NO_CERT_PATH_LIMIT)
+ )
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in)
+ .start_cons(SEQUENCE)
+ .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false)
+ .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT)
+ .verify_end()
+ .end_cons();
+
+ if(is_ca == false)
+ path_limit = 0;
+ }
+
+/*
+* Return a textual representation
+*/
+void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const
+ {
+ subject.add("X509v3.BasicConstraints.is_ca", (is_ca ? 1 : 0));
+ subject.add("X509v3.BasicConstraints.path_constraint", path_limit);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Key_Usage::encode_inner() const
+ {
+ if(constraints == NO_CONSTRAINTS)
+ throw Encoding_Error("Cannot encode zero usage constraints");
+
+ const u32bit unused_bits = low_bit(constraints) - 1;
+
+ SecureVector<byte> der;
+ der.append(BIT_STRING);
+ der.append(2 + ((unused_bits < 8) ? 1 : 0));
+ der.append(unused_bits % 8);
+ der.append((constraints >> 8) & 0xFF);
+ if(constraints & 0xFF)
+ der.append(constraints & 0xFF);
+
+ return der;
+ }
+
+/*
+* Decode the extension
+*/
+void Key_Usage::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder ber(in);
+
+ BER_Object obj = ber.get_next_object();
+
+ if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL)
+ throw BER_Bad_Tag("Bad tag for usage constraint",
+ obj.type_tag, obj.class_tag);
+
+ if(obj.value.size() != 2 && obj.value.size() != 3)
+ throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");
+
+ if(obj.value[0] >= 8)
+ throw BER_Decoding_Error("Invalid unused bits in usage constraint");
+
+ obj.value[obj.value.size()-1] &= (0xFF << obj.value[0]);
+
+ u16bit usage = 0;
+ for(u32bit j = 1; j != obj.value.size(); ++j)
+ usage = (obj.value[j] << 8) | usage;
+
+ constraints = Key_Constraints(usage);
+ }
+
+/*
+* Return a textual representation
+*/
+void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
+ {
+ subject.add("X509v3.KeyUsage", constraints);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Subject_Key_ID::encode_inner() const
+ {
+ return DER_Encoder().encode(key_id, OCTET_STRING).get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end();
+ }
+
+/*
+* Return a textual representation
+*/
+void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const
+ {
+ subject.add("X509v3.SubjectKeyIdentifier", key_id);
+ }
+
+/*
+* Subject_Key_ID Constructor
+*/
+Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key)
+ {
+ SHA_160 hash;
+ key_id = hash.process(pub_key);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Authority_Key_ID::encode_inner() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in)
+ .start_cons(SEQUENCE)
+ .decode_optional_string(key_id, OCTET_STRING, 0);
+ }
+
+/*
+* Return a textual representation
+*/
+void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const
+ {
+ if(key_id.size())
+ issuer.add("X509v3.AuthorityKeyIdentifier", key_id);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Alternative_Name::encode_inner() const
+ {
+ return DER_Encoder().encode(alt_name).get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Alternative_Name::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in).decode(alt_name);
+ }
+
+/*
+* Return a textual representation
+*/
+void Alternative_Name::contents_to(Data_Store& subject_info,
+ Data_Store& issuer_info) const
+ {
+ std::multimap<std::string, std::string> contents =
+ get_alt_name().contents();
+
+ if(oid_name_str == "X509v3.SubjectAlternativeName")
+ subject_info.add(contents);
+ else if(oid_name_str == "X509v3.IssuerAlternativeName")
+ issuer_info.add(contents);
+ else
+ throw Internal_Error("In Alternative_Name, unknown type " +
+ oid_name_str);
+ }
+
+/*
+* Alternative_Name Constructor
+*/
+Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
+ const std::string& oid_name_str,
+ const std::string& config_name_str)
+ {
+ this->alt_name = alt_name;
+ this->oid_name_str = oid_name_str;
+ this->config_name_str = config_name_str;
+ }
+
+/*
+* Subject_Alternative_Name Constructor
+*/
+Subject_Alternative_Name::Subject_Alternative_Name(
+ const AlternativeName& name) :
+
+ Alternative_Name(name, "X509v3.SubjectAlternativeName",
+ "subject_alternative_name")
+ {
+ }
+
+/*
+* Issuer_Alternative_Name Constructor
+*/
+Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
+ Alternative_Name(name, "X509v3.IssuerAlternativeName",
+ "issuer_alternative_name")
+ {
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Extended_Key_Usage::encode_inner() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(oids)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in)
+ .start_cons(SEQUENCE)
+ .decode_list(oids)
+ .end_cons();
+ }
+
+/*
+* Return a textual representation
+*/
+void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
+ {
+ for(u32bit j = 0; j != oids.size(); ++j)
+ subject.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
+ }
+
+namespace {
+
+/*
+* A policy specifier
+*/
+class Policy_Information : public ASN1_Object
+ {
+ public:
+ OID oid;
+
+ void encode_into(DER_Encoder& codec) const
+ {
+ codec.start_cons(SEQUENCE)
+ .encode(oid)
+ .end_cons();
+ }
+
+ void decode_from(BER_Decoder& codec)
+ {
+ codec.start_cons(SEQUENCE)
+ .decode(oid)
+ .discard_remaining()
+ .end_cons();
+ }
+ };
+
+}
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> Certificate_Policies::encode_inner() const
+ {
+ throw Exception("Certificate_Policies::encode_inner: Bugged");
+
+ std::vector<Policy_Information> policies;
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(policies)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in)
+ {
+ std::vector<Policy_Information> policies;
+
+ BER_Decoder(in)
+ .start_cons(SEQUENCE)
+ .decode_list(policies)
+ .end_cons();
+ }
+
+/*
+* Return a textual representation
+*/
+void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const
+ {
+ for(u32bit j = 0; j != oids.size(); ++j)
+ info.add("X509v3.ExtendedKeyUsage", oids[j].as_string());
+ }
+
+/*
+* Checked accessor for the crl_number member
+*/
+u32bit CRL_Number::get_crl_number() const
+ {
+ if(!has_value)
+ throw Invalid_State("CRL_Number::get_crl_number: Not set");
+ return crl_number;
+ }
+
+/*
+* Copy a CRL_Number extension
+*/
+CRL_Number* CRL_Number::copy() const
+ {
+ if(!has_value)
+ throw Invalid_State("CRL_Number::copy: Not set");
+ return new CRL_Number(crl_number);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> CRL_Number::encode_inner() const
+ {
+ return DER_Encoder().encode(crl_number).get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void CRL_Number::decode_inner(const MemoryRegion<byte>& in)
+ {
+ BER_Decoder(in).decode(crl_number);
+ }
+
+/*
+* Return a textual representation
+*/
+void CRL_Number::contents_to(Data_Store& info, Data_Store&) const
+ {
+ info.add("X509v3.CRLNumber", crl_number);
+ }
+
+/*
+* Encode the extension
+*/
+MemoryVector<byte> CRL_ReasonCode::encode_inner() const
+ {
+ return DER_Encoder()
+ .encode(static_cast<u32bit>(reason), ENUMERATED, UNIVERSAL)
+ .get_contents();
+ }
+
+/*
+* Decode the extension
+*/
+void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in)
+ {
+ u32bit reason_code = 0;
+ BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL);
+ reason = static_cast<CRL_Code>(reason_code);
+ }
+
+/*
+* Return a textual representation
+*/
+void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const
+ {
+ info.add("X509v3.CRLReasonCode", reason);
+ }
+
+}
+
+}
diff --git a/botan/src/cert/x509/x509_ext.h b/botan/src/cert/x509/x509_ext.h
new file mode 100644
index 0000000..108215e
--- /dev/null
+++ b/botan/src/cert/x509/x509_ext.h
@@ -0,0 +1,317 @@
+/*
+* X.509 Certificate Extensions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_EXTENSIONS_H__
+#define BOTAN_X509_EXTENSIONS_H__
+
+#include <botan/asn1_int.h>
+#include <botan/asn1_oid.h>
+#include <botan/asn1_obj.h>
+#include <botan/datastor.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/*
+* X.509 Certificate Extension
+*/
+class BOTAN_DLL Certificate_Extension
+ {
+ public:
+ OID oid_of() const;
+
+ virtual Certificate_Extension* copy() const = 0;
+
+ virtual void contents_to(Data_Store&, Data_Store&) const = 0;
+ virtual std::string config_id() const = 0;
+ virtual std::string oid_name() const = 0;
+
+ virtual ~Certificate_Extension() {}
+ protected:
+ friend class Extensions;
+ virtual bool should_encode() const { return true; }
+ virtual MemoryVector<byte> encode_inner() const = 0;
+ virtual void decode_inner(const MemoryRegion<byte>&) = 0;
+ };
+
+/*
+* X.509 Certificate Extension List
+*/
+class BOTAN_DLL Extensions : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ void add(Certificate_Extension* extn)
+ { extensions.push_back(extn); }
+
+ Extensions& operator=(const Extensions&);
+
+ Extensions(const Extensions&);
+ Extensions(bool st = true) : should_throw(st) {}
+ ~Extensions();
+ private:
+ static Certificate_Extension* get_extension(const OID&);
+
+ std::vector<Certificate_Extension*> extensions;
+ bool should_throw;
+ };
+
+namespace Cert_Extension {
+
+/*
+* Basic Constraints Extension
+*/
+class BOTAN_DLL Basic_Constraints : public Certificate_Extension
+ {
+ public:
+ Basic_Constraints* copy() const
+ { return new Basic_Constraints(is_ca, path_limit); }
+
+ Basic_Constraints(bool ca = false, u32bit limit = 0) :
+ is_ca(ca), path_limit(limit) {}
+
+ bool get_is_ca() const { return is_ca; }
+ u32bit get_path_limit() const;
+ private:
+ std::string config_id() const { return "basic_constraints"; }
+ std::string oid_name() const { return "X509v3.BasicConstraints"; }
+
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ bool is_ca;
+ u32bit path_limit;
+ };
+
+/*
+* Key Usage Constraints Extension
+*/
+class BOTAN_DLL Key_Usage : public Certificate_Extension
+ {
+ public:
+ Key_Usage* copy() const { return new Key_Usage(constraints); }
+
+ Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : constraints(c) {}
+
+ Key_Constraints get_constraints() const { return constraints; }
+ private:
+ std::string config_id() const { return "key_usage"; }
+ std::string oid_name() const { return "X509v3.KeyUsage"; }
+
+ bool should_encode() const { return (constraints != NO_CONSTRAINTS); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ Key_Constraints constraints;
+ };
+
+/*
+* Subject Key Identifier Extension
+*/
+class BOTAN_DLL Subject_Key_ID : public Certificate_Extension
+ {
+ public:
+ Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); }
+
+ Subject_Key_ID() {}
+ Subject_Key_ID(const MemoryRegion<byte>&);
+
+ MemoryVector<byte> get_key_id() const { return key_id; }
+ private:
+ std::string config_id() const { return "subject_key_id"; }
+ std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; }
+
+ bool should_encode() const { return (key_id.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ MemoryVector<byte> key_id;
+ };
+
+/*
+* Authority Key Identifier Extension
+*/
+class BOTAN_DLL Authority_Key_ID : public Certificate_Extension
+ {
+ public:
+ Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); }
+
+ Authority_Key_ID() {}
+ Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {}
+
+ MemoryVector<byte> get_key_id() const { return key_id; }
+ private:
+ std::string config_id() const { return "authority_key_id"; }
+ std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; }
+
+ bool should_encode() const { return (key_id.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ MemoryVector<byte> key_id;
+ };
+
+/*
+* Alternative Name Extension Base Class
+*/
+class BOTAN_DLL Alternative_Name : public Certificate_Extension
+ {
+ public:
+ AlternativeName get_alt_name() const { return alt_name; }
+
+ protected:
+ Alternative_Name(const AlternativeName&,
+ const std::string&, const std::string&);
+
+ Alternative_Name(const std::string&, const std::string&);
+ private:
+ std::string config_id() const { return config_name_str; }
+ std::string oid_name() const { return oid_name_str; }
+
+ bool should_encode() const { return alt_name.has_items(); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::string config_name_str, oid_name_str;
+ AlternativeName alt_name;
+ };
+
+/*
+* Subject Alternative Name Extension
+*/
+class BOTAN_DLL Subject_Alternative_Name : public Alternative_Name
+ {
+ public:
+ Subject_Alternative_Name* copy() const
+ { return new Subject_Alternative_Name(get_alt_name()); }
+
+ Subject_Alternative_Name(const AlternativeName& = AlternativeName());
+ };
+
+/*
+* Issuer Alternative Name Extension
+*/
+class BOTAN_DLL Issuer_Alternative_Name : public Alternative_Name
+ {
+ public:
+ Issuer_Alternative_Name* copy() const
+ { return new Issuer_Alternative_Name(get_alt_name()); }
+
+ Issuer_Alternative_Name(const AlternativeName& = AlternativeName());
+ };
+
+/*
+* Extended Key Usage Extension
+*/
+class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension
+ {
+ public:
+ Extended_Key_Usage* copy() const { return new Extended_Key_Usage(oids); }
+
+ Extended_Key_Usage() {}
+ Extended_Key_Usage(const std::vector<OID>& o) : oids(o) {}
+
+ std::vector<OID> get_oids() const { return oids; }
+ private:
+ std::string config_id() const { return "extended_key_usage"; }
+ std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; }
+
+ bool should_encode() const { return (oids.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<OID> oids;
+ };
+
+/*
+* Certificate Policies Extension
+*/
+class BOTAN_DLL Certificate_Policies : public Certificate_Extension
+ {
+ public:
+ Certificate_Policies* copy() const
+ { return new Certificate_Policies(oids); }
+
+ Certificate_Policies() {}
+ Certificate_Policies(const std::vector<OID>& o) : oids(o) {}
+
+ std::vector<OID> get_oids() const { return oids; }
+ private:
+ std::string config_id() const { return "policy_info"; }
+ std::string oid_name() const { return "X509v3.CertificatePolicies"; }
+
+ bool should_encode() const { return (oids.size() > 0); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<OID> oids;
+ };
+
+/*
+* CRL Number Extension
+*/
+class BOTAN_DLL CRL_Number : public Certificate_Extension
+ {
+ public:
+ CRL_Number* copy() const;
+
+ CRL_Number() : has_value(false), crl_number(0) {}
+ CRL_Number(u32bit n) : has_value(true), crl_number(n) {}
+
+ u32bit get_crl_number() const;
+ private:
+ std::string config_id() const { return "crl_number"; }
+ std::string oid_name() const { return "X509v3.CRLNumber"; }
+
+ bool should_encode() const { return has_value; }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ bool has_value;
+ u32bit crl_number;
+ };
+
+/*
+* CRL Entry Reason Code Extension
+*/
+class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
+ {
+ public:
+ CRL_ReasonCode* copy() const { return new CRL_ReasonCode(reason); }
+
+ CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : reason(r) {}
+
+ CRL_Code get_reason() const { return reason; }
+ private:
+ std::string config_id() const { return "crl_reason"; }
+ std::string oid_name() const { return "X509v3.ReasonCode"; }
+
+ bool should_encode() const { return (reason != UNSPECIFIED); }
+ MemoryVector<byte> encode_inner() const;
+ void decode_inner(const MemoryRegion<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ CRL_Code reason;
+ };
+
+}
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509_obj.cpp b/botan/src/cert/x509/x509_obj.cpp
new file mode 100644
index 0000000..31b4a30
--- /dev/null
+++ b/botan/src/cert/x509/x509_obj.cpp
@@ -0,0 +1,235 @@
+/*
+* X.509 SIGNED Object
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_obj.h>
+#include <botan/x509_key.h>
+#include <botan/look_pk.h>
+#include <botan/oids.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/pem.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*
+* Create a generic X.509 object
+*/
+X509_Object::X509_Object(DataSource& stream, const std::string& labels)
+ {
+ init(stream, labels);
+ }
+
+/*
+* Createa a generic X.509 object
+*/
+X509_Object::X509_Object(const std::string& file, const std::string& labels)
+ {
+ DataSource_Stream stream(file, true);
+ init(stream, labels);
+ }
+
+/*
+* Read a PEM or BER X.509 object
+*/
+void X509_Object::init(DataSource& in, const std::string& labels)
+ {
+ PEM_labels_allowed = split_on(labels, '/');
+ if(PEM_labels_allowed.size() < 1)
+ throw Invalid_Argument("Bad labels argument to X509_Object");
+
+ PEM_label_pref = PEM_labels_allowed[0];
+ std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end());
+
+ try {
+ if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
+ decode_info(in);
+ else
+ {
+ std::string got_label;
+ DataSource_Memory ber(PEM_Code::decode(in, got_label));
+
+ if(!std::binary_search(PEM_labels_allowed.begin(),
+ PEM_labels_allowed.end(), got_label))
+ throw Decoding_Error("Invalid PEM label: " + got_label);
+ decode_info(ber);
+ }
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error(PEM_label_pref + " decoding failed");
+ }
+ }
+
+/*
+* Read a BER encoded X.509 object
+*/
+void X509_Object::decode_info(DataSource& source)
+ {
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .start_cons(SEQUENCE)
+ .raw_bytes(tbs_bits)
+ .end_cons()
+ .decode(sig_algo)
+ .decode(sig, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+
+/*
+* Return a BER or PEM encoded X.509 object
+*/
+void X509_Object::encode(Pipe& out, X509_Encoding encoding) const
+ {
+ SecureVector<byte> der = DER_Encoder()
+ .start_cons(SEQUENCE)
+ .start_cons(SEQUENCE)
+ .raw_bytes(tbs_bits)
+ .end_cons()
+ .encode(sig_algo)
+ .encode(sig, BIT_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ out.write(PEM_Code::encode(der, PEM_label_pref));
+ else
+ out.write(der);
+ }
+
+/*
+* Return a BER encoded X.509 object
+*/
+SecureVector<byte> X509_Object::BER_encode() const
+ {
+ Pipe ber;
+ ber.start_msg();
+ encode(ber, RAW_BER);
+ ber.end_msg();
+ return ber.read_all();
+ }
+
+/*
+* Return a PEM encoded X.509 object
+*/
+std::string X509_Object::PEM_encode() const
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*
+* Return the TBS data
+*/
+SecureVector<byte> X509_Object::tbs_data() const
+ {
+ return ASN1::put_in_sequence(tbs_bits);
+ }
+
+/*
+* Return the signature of this object
+*/
+SecureVector<byte> X509_Object::signature() const
+ {
+ return sig;
+ }
+
+/*
+* Return the algorithm used to sign this object
+*/
+AlgorithmIdentifier X509_Object::signature_algorithm() const
+ {
+ return sig_algo;
+ }
+
+/*
+* Check the signature on an object
+*/
+bool X509_Object::check_signature(Public_Key& pub_key) const
+ {
+ try {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ return false;
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ std::auto_ptr<PK_Verifier> verifier;
+
+ if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key))
+ {
+ PK_Verifying_with_MR_Key& sig_key =
+ dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key);
+ verifier.reset(get_pk_verifier(sig_key, padding, format));
+ }
+ else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key))
+ {
+ PK_Verifying_wo_MR_Key& sig_key =
+ dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key);
+ verifier.reset(get_pk_verifier(sig_key, padding, format));
+ }
+ else
+ return false;
+
+ return verifier->verify_message(tbs_data(), signature());
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+/*
+* Apply the X.509 SIGNED macro
+*/
+MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& algo,
+ const MemoryRegion<byte>& tbs_bits)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .raw_bytes(tbs_bits)
+ .encode(algo)
+ .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Try to decode the actual information
+*/
+void X509_Object::do_decode()
+ {
+ try {
+ force_decode();
+ }
+ catch(Decoding_Error& e)
+ {
+ const std::string what = e.what();
+ throw Decoding_Error(PEM_label_pref + " decoding failed (" +
+ what.substr(23, std::string::npos) + ")");
+ }
+ catch(Invalid_Argument& e)
+ {
+ const std::string what = e.what();
+ throw Decoding_Error(PEM_label_pref + " decoding failed (" +
+ what.substr(7, std::string::npos) + ")");
+ }
+ }
+
+}
diff --git a/botan/src/cert/x509/x509_obj.h b/botan/src/cert/x509/x509_obj.h
new file mode 100644
index 0000000..c7f92fa
--- /dev/null
+++ b/botan/src/cert/x509/x509_obj.h
@@ -0,0 +1,67 @@
+/*
+* X.509 SIGNED Object
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_OBJECT_H__
+#define BOTAN_X509_OBJECT_H__
+
+#include <botan/asn1_obj.h>
+#include <botan/pipe.h>
+#include <botan/pubkey_enums.h>
+#include <botan/rng.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents abstract X.509 signed objects as
+* in the X.500 SIGNED macro
+*/
+class BOTAN_DLL X509_Object
+ {
+ public:
+ SecureVector<byte> tbs_data() const;
+ SecureVector<byte> signature() const;
+ AlgorithmIdentifier signature_algorithm() const;
+
+ /**
+ * Create a signed X509 object.
+ * @param signer the signer used to sign the object
+ * @param rng the random number generator to use
+ * @param alg_id the algorithm identifier of the signature scheme
+ * @param tbs the tbs bits to be signed
+ * @return the signed X509 object
+ */
+ static MemoryVector<byte> make_signed(class PK_Signer* signer,
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& alg_id,
+ const MemoryRegion<byte>& tbs);
+
+ bool check_signature(class Public_Key&) const;
+
+ void encode(Pipe&, X509_Encoding = PEM) const;
+ SecureVector<byte> BER_encode() const;
+ std::string PEM_encode() const;
+
+ X509_Object(DataSource&, const std::string&);
+ X509_Object(const std::string&, const std::string&);
+ virtual ~X509_Object() {}
+ protected:
+ void do_decode();
+ X509_Object() {}
+ AlgorithmIdentifier sig_algo;
+ SecureVector<byte> tbs_bits, sig;
+ private:
+ virtual void force_decode() = 0;
+ void init(DataSource&, const std::string&);
+ void decode_info(DataSource&);
+ std::vector<std::string> PEM_labels_allowed;
+ std::string PEM_label_pref;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509cert.cpp b/botan/src/cert/x509/x509cert.cpp
new file mode 100644
index 0000000..ac5839f
--- /dev/null
+++ b/botan/src/cert/x509/x509cert.cpp
@@ -0,0 +1,366 @@
+/*
+* X.509 Certificates
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509cert.h>
+#include <botan/x509_ext.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/stl_util.h>
+#include <botan/parsing.h>
+#include <botan/bigint.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Lookup each OID in the vector
+*/
+std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
+ {
+ std::vector<std::string> out;
+
+ std::vector<std::string>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ out.push_back(OIDS::lookup(OID(*i)));
+ ++i;
+ }
+ return out;
+ }
+
+}
+
+/*
+* X509_Certificate Constructor
+*/
+X509_Certificate::X509_Certificate(DataSource& in) :
+ X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
+ {
+ self_signed = false;
+ do_decode();
+ }
+
+/*
+* X509_Certificate Constructor
+*/
+X509_Certificate::X509_Certificate(const std::string& in) :
+ X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
+ {
+ self_signed = false;
+ do_decode();
+ }
+
+/*
+* Decode the TBSCertificate data
+*/
+void X509_Certificate::force_decode()
+ {
+ u32bit version;
+ BigInt serial_bn;
+ AlgorithmIdentifier sig_algo_inner;
+ X509_DN dn_issuer, dn_subject;
+ X509_Time start, end;
+
+ BER_Decoder tbs_cert(tbs_bits);
+
+ tbs_cert.decode_optional(version, ASN1_Tag(0),
+ ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ .decode(serial_bn)
+ .decode(sig_algo_inner)
+ .decode(dn_issuer)
+ .start_cons(SEQUENCE)
+ .decode(start)
+ .decode(end)
+ .verify_end()
+ .end_cons()
+ .decode(dn_subject);
+
+ if(version > 2)
+ throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
+ if(sig_algo != sig_algo_inner)
+ throw Decoding_Error("Algorithm identifier mismatch");
+
+ self_signed = (dn_subject == dn_issuer);
+
+ subject.add(dn_subject.contents());
+ issuer.add(dn_issuer.contents());
+
+ BER_Object public_key = tbs_cert.get_next_object();
+ if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
+ throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
+ public_key.type_tag, public_key.class_tag);
+
+ MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id;
+
+ tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
+ tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
+
+ BER_Object v3_exts_data = tbs_cert.get_next_object();
+ if(v3_exts_data.type_tag == 3 &&
+ v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ Extensions extensions;
+
+ BER_Decoder(v3_exts_data.value).decode(extensions).verify_end();
+
+ extensions.contents_to(subject, issuer);
+ }
+ else if(v3_exts_data.type_tag != NO_OBJECT)
+ throw BER_Bad_Tag("Unknown tag in X.509 cert",
+ v3_exts_data.type_tag, v3_exts_data.class_tag);
+
+ if(tbs_cert.more_items())
+ throw Decoding_Error("TBSCertificate has more items that expected");
+
+ subject.add("X509.Certificate.version", version);
+ subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
+ subject.add("X509.Certificate.start", start.readable_string());
+ subject.add("X509.Certificate.end", end.readable_string());
+
+ issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
+ subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
+
+ subject.add("X509.Certificate.public_key",
+ PEM_Code::encode(
+ ASN1::put_in_sequence(public_key.value),
+ "PUBLIC KEY"
+ )
+ );
+
+ if(is_CA_cert() &&
+ !subject.has_value("X509v3.BasicConstraints.path_constraint"))
+ {
+ u32bit limit = (x509_version() < 3) ? NO_CERT_PATH_LIMIT : 0;
+ subject.add("X509v3.BasicConstraints.path_constraint", limit);
+ }
+ }
+
+/*
+* Return the X.509 version in use
+*/
+u32bit X509_Certificate::x509_version() const
+ {
+ return (subject.get1_u32bit("X509.Certificate.version") + 1);
+ }
+
+/*
+* Return the time this cert becomes valid
+*/
+std::string X509_Certificate::start_time() const
+ {
+ return subject.get1("X509.Certificate.start");
+ }
+
+/*
+* Return the time this cert becomes invalid
+*/
+std::string X509_Certificate::end_time() const
+ {
+ return subject.get1("X509.Certificate.end");
+ }
+
+/*
+* Return information about the subject
+*/
+std::vector<std::string>
+X509_Certificate::subject_info(const std::string& what) const
+ {
+ return subject.get(X509_DN::deref_info_field(what));
+ }
+
+/*
+* Return information about the issuer
+*/
+std::vector<std::string>
+X509_Certificate::issuer_info(const std::string& what) const
+ {
+ return issuer.get(X509_DN::deref_info_field(what));
+ }
+
+/*
+* Return the public key in this certificate
+*/
+Public_Key* X509_Certificate::subject_public_key() const
+ {
+ DataSource_Memory source(subject.get1("X509.Certificate.public_key"));
+ return X509::load_key(source);
+ }
+
+/*
+* Check if the certificate is for a CA
+*/
+bool X509_Certificate::is_CA_cert() const
+ {
+ if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca"))
+ return false;
+ if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS))
+ return true;
+ return false;
+ }
+
+/*
+* Return the path length constraint
+*/
+u32bit X509_Certificate::path_limit() const
+ {
+ return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0);
+ }
+
+/*
+* Return the key usage constraints
+*/
+Key_Constraints X509_Certificate::constraints() const
+ {
+ return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage",
+ NO_CONSTRAINTS));
+ }
+
+/*
+* Return the list of extended key usage OIDs
+*/
+std::vector<std::string> X509_Certificate::ex_constraints() const
+ {
+ return lookup_oids(subject.get("X509v3.ExtendedKeyUsage"));
+ }
+
+/*
+* Return the list of certificate policies
+*/
+std::vector<std::string> X509_Certificate::policies() const
+ {
+ return lookup_oids(subject.get("X509v3.CertificatePolicies"));
+ }
+
+/*
+* Return the authority key id
+*/
+MemoryVector<byte> X509_Certificate::authority_key_id() const
+ {
+ return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
+ }
+
+/*
+* Return the subject key id
+*/
+MemoryVector<byte> X509_Certificate::subject_key_id() const
+ {
+ return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
+ }
+
+/*
+* Return the certificate serial number
+*/
+MemoryVector<byte> X509_Certificate::serial_number() const
+ {
+ return subject.get1_memvec("X509.Certificate.serial");
+ }
+
+/*
+* Return the distinguished name of the issuer
+*/
+X509_DN X509_Certificate::issuer_dn() const
+ {
+ return create_dn(issuer);
+ }
+
+/*
+* Return the distinguished name of the subject
+*/
+X509_DN X509_Certificate::subject_dn() const
+ {
+ return create_dn(subject);
+ }
+
+/*
+* Compare two certificates for equality
+*/
+bool X509_Certificate::operator==(const X509_Certificate& other) const
+ {
+ return (sig == other.sig &&
+ sig_algo == other.sig_algo &&
+ self_signed == other.self_signed &&
+ issuer == other.issuer &&
+ subject == other.subject);
+ }
+
+/*
+* X.509 Certificate Comparison
+*/
+bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
+ {
+ return !(cert1 == cert2);
+ }
+
+/*
+* Create and populate a X509_DN
+*/
+X509_DN create_dn(const Data_Store& info)
+ {
+ class DN_Matcher : public Data_Store::Matcher
+ {
+ public:
+ bool operator()(const std::string& key, const std::string&) const
+ {
+ if(key.find("X520.") != std::string::npos)
+ return true;
+ return false;
+ }
+ };
+
+ std::multimap<std::string, std::string> names =
+ info.search_with(DN_Matcher());
+
+ X509_DN dn;
+
+ std::multimap<std::string, std::string>::iterator j;
+ for(j = names.begin(); j != names.end(); ++j)
+ dn.add_attribute(j->first, j->second);
+
+ return dn;
+ }
+
+/*
+* Create and populate an AlternativeName
+*/
+AlternativeName create_alt_name(const Data_Store& info)
+ {
+ class AltName_Matcher : public Data_Store::Matcher
+ {
+ public:
+ bool operator()(const std::string& key, const std::string&) const
+ {
+ for(u32bit j = 0; j != matches.size(); ++j)
+ if(key.compare(matches[j]) == 0)
+ return true;
+ return false;
+ }
+
+ AltName_Matcher(const std::string& match_any_of)
+ {
+ matches = split_on(match_any_of, '/');
+ }
+ private:
+ std::vector<std::string> matches;
+ };
+
+ std::multimap<std::string, std::string> names =
+ info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
+
+ AlternativeName alt_name;
+
+ std::multimap<std::string, std::string>::iterator j;
+ for(j = names.begin(); j != names.end(); ++j)
+ alt_name.add_attribute(j->first, j->second);
+
+ return alt_name;
+ }
+
+}
diff --git a/botan/src/cert/x509/x509cert.h b/botan/src/cert/x509/x509cert.h
new file mode 100644
index 0000000..4a9d11f
--- /dev/null
+++ b/botan/src/cert/x509/x509cert.h
@@ -0,0 +1,185 @@
+/*
+* X.509 Certificates
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERTS_H__
+#define BOTAN_X509_CERTS_H__
+
+#include <botan/x509_obj.h>
+#include <botan/x509_key.h>
+#include <botan/datastor.h>
+#include <botan/pubkey_enums.h>
+#include <map>
+
+namespace Botan {
+
+/**
+* This class represents X.509 Certificate
+*/
+class BOTAN_DLL X509_Certificate : public X509_Object
+ {
+ public:
+ /**
+ * Get the public key associated with this certificate.
+ * @return the subject public key of this certificate
+ */
+ Public_Key* subject_public_key() const;
+
+ /**
+ * Get the issuer certificate DN.
+ * @return the issuer DN of this certificate
+ */
+ X509_DN issuer_dn() const;
+
+ /**
+ * Get the subject certificate DN.
+ * @return the subject DN of this certificate
+ */
+ X509_DN subject_dn() const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.version", "X509.Certificate.serial",
+ * "X509.Certificate.start", "X509.Certificate.end",
+ * "X509.Certificate.v2.key_id", "X509.Certificate.public_key",
+ * "X509v3.BasicConstraints.path_constraint",
+ * "X509v3.BasicConstraints.is_ca", "X509v3.ExtendedKeyUsage",
+ * "X509v3.CertificatePolicies", "X509v3.SubjectKeyIdentifier" or
+ * "X509.Certificate.serial".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> subject_info(const std::string& name) const;
+
+ /**
+ * Get a value for a specific subject_info parameter name.
+ * @param name the name of the paramter to look up. Possible names are
+ * "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier".
+ * @return the value(s) of the specified parameter
+ */
+ std::vector<std::string> issuer_info(const std::string& name) const;
+
+ /**
+ * Get the notBefore of the certificate.
+ * @return the notBefore of the certificate
+ */
+ std::string start_time() const;
+
+ /**
+ * Get the notAfter of the certificate.
+ * @return the notAfter of the certificate
+ */
+ std::string end_time() const;
+
+ /**
+ * Get the X509 version of this certificate object.
+ * @return the X509 version
+ */
+ u32bit x509_version() const;
+
+ /**
+ * Get the serial number of this certificate.
+ * @return the certificates serial number
+ */
+ MemoryVector<byte> serial_number() const;
+
+ /**
+ * Get the DER encoded AuthorityKeyIdentifier of this certificate.
+ * @return the DER encoded AuthorityKeyIdentifier
+ */
+ MemoryVector<byte> authority_key_id() const;
+
+ /**
+ * Get the DER encoded SubjectKeyIdentifier of this certificate.
+ * @return the DER encoded SubjectKeyIdentifier
+ */
+ MemoryVector<byte> subject_key_id() const;
+
+ /**
+ * Check whether this certificate is self signed.
+ * @return true if this certificate is self signed
+ */
+ bool is_self_signed() const { return self_signed; }
+
+ /**
+ * Check whether this certificate is a CA certificate.
+ * @return true if this certificate is a CA certificate
+ */
+ bool is_CA_cert() const;
+
+ /**
+ * Get the path limit as defined in the BasicConstraints extension of
+ * this certificate.
+ * @return the path limit
+ */
+ u32bit path_limit() const;
+
+ /**
+ * Get the key constraints as defined in the KeyUsage extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ Key_Constraints constraints() const;
+
+ /**
+ * Get the key constraints as defined in the ExtendedKeyUsage
+ * extension of this
+ * certificate.
+ * @return the key constraints
+ */
+ std::vector<std::string> ex_constraints() const;
+
+ /**
+ * Get the policies as defined in the CertificatePolicies extension
+ * of this certificate.
+ * @return the certificate policies
+ */
+ std::vector<std::string> policies() const;
+
+ /**
+ * Check to certificates for equality.
+ * @return true both certificates are (binary) equal
+ */
+ bool operator==(const X509_Certificate& other) const;
+
+ /**
+ * Create a certificate from a data source providing the DER or
+ * PEM encoded certificate.
+ * @param source the data source
+ */
+ X509_Certificate(DataSource& source);
+
+ /**
+ * Create a certificate from a file containing the DER or PEM
+ * encoded certificate.
+ * @param filename the name of the certificate file
+ */
+ X509_Certificate(const std::string& filename);
+ private:
+ void force_decode();
+ friend class X509_CA;
+ X509_Certificate() {}
+
+ Data_Store subject, issuer;
+ bool self_signed;
+ };
+
+/**
+* Check two certificates for inequality
+* @return true if the arguments represent different certificates,
+* false if they are binary identical
+*/
+BOTAN_DLL bool operator!=(const X509_Certificate&, const X509_Certificate&);
+
+/*
+* Data Store Extraction Operations
+*/
+BOTAN_DLL X509_DN create_dn(const Data_Store&);
+BOTAN_DLL AlternativeName create_alt_name(const Data_Store&);
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509find.cpp b/botan/src/cert/x509/x509find.cpp
new file mode 100644
index 0000000..257367d
--- /dev/null
+++ b/botan/src/cert/x509/x509find.cpp
@@ -0,0 +1,111 @@
+/*
+* X.509 Certificate Store Searching
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509find.h>
+#include <botan/charset.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Compare based on case-insensive substrings
+*/
+bool substring_match(const std::string& searching_for,
+ const std::string& found)
+ {
+ if(std::search(found.begin(), found.end(), searching_for.begin(),
+ searching_for.end(), Charset::caseless_cmp) != found.end())
+ return true;
+ return false;
+ }
+
+/*
+* Compare based on case-insensive match
+*/
+bool ignore_case(const std::string& searching_for, const std::string& found)
+ {
+ if(searching_for.size() != found.size())
+ return false;
+
+ return std::equal(found.begin(), found.end(),
+ searching_for.begin(), Charset::caseless_cmp);
+ }
+
+}
+
+/*
+* Search based on the contents of a DN entry
+*/
+bool DN_Check::match(const X509_Certificate& cert) const
+ {
+ std::vector<std::string> info = cert.subject_info(dn_entry);
+
+ for(u32bit j = 0; j != info.size(); ++j)
+ if(compare(info[j], looking_for))
+ return true;
+ return false;
+ }
+
+/*
+* DN_Check Constructor
+*/
+DN_Check::DN_Check(const std::string& dn_entry, const std::string& looking_for,
+ compare_fn func)
+ {
+ this->dn_entry = dn_entry;
+ this->looking_for = looking_for;
+ compare = func;
+ }
+
+/*
+* DN_Check Constructor
+*/
+DN_Check::DN_Check(const std::string& dn_entry, const std::string& looking_for,
+ Search_Type method)
+ {
+ this->dn_entry = dn_entry;
+ this->looking_for = looking_for;
+
+ if(method == SUBSTRING_MATCHING)
+ compare = &substring_match;
+ else if(method == IGNORE_CASE)
+ compare = &ignore_case;
+ else
+ throw Invalid_Argument("Unknown method argument to DN_Check()");
+ }
+
+/*
+* Match by issuer and serial number
+*/
+bool IandS_Match::match(const X509_Certificate& cert) const
+ {
+ if(cert.serial_number() != serial)
+ return false;
+ return (cert.issuer_dn() == issuer);
+ }
+
+/*
+* IandS_Match Constructor
+*/
+IandS_Match::IandS_Match(const X509_DN& issuer,
+ const MemoryRegion<byte>& serial)
+ {
+ this->issuer = issuer;
+ this->serial = serial;
+ }
+
+/*
+* Match by subject key identifier
+*/
+bool SKID_Match::match(const X509_Certificate& cert) const
+ {
+ return (cert.subject_key_id() == skid);
+ }
+
+}
diff --git a/botan/src/cert/x509/x509find.h b/botan/src/cert/x509/x509find.h
new file mode 100644
index 0000000..a7a84c7
--- /dev/null
+++ b/botan/src/cert/x509/x509find.h
@@ -0,0 +1,60 @@
+/*
+* X.509 Certificate Store Searching
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERT_STORE_SEARCH_H__
+#define BOTAN_X509_CERT_STORE_SEARCH_H__
+
+#include <botan/x509stor.h>
+
+namespace Botan {
+
+/*
+* Search based on the contents of a DN entry
+*/
+class BOTAN_DLL DN_Check : public X509_Store::Search_Func
+ {
+ public:
+ typedef bool (*compare_fn)(const std::string&, const std::string&);
+ enum Search_Type { SUBSTRING_MATCHING, IGNORE_CASE };
+
+ bool match(const X509_Certificate& cert) const;
+
+ DN_Check(const std::string&, const std::string&, compare_fn);
+ DN_Check(const std::string&, const std::string&, Search_Type);
+ private:
+ std::string dn_entry, looking_for;
+ compare_fn compare;
+ };
+
+/*
+* Search for a certificate by issuer/serial
+*/
+class BOTAN_DLL IandS_Match : public X509_Store::Search_Func
+ {
+ public:
+ bool match(const X509_Certificate& cert) const;
+ IandS_Match(const X509_DN&, const MemoryRegion<byte>&);
+ private:
+ X509_DN issuer;
+ MemoryVector<byte> serial;
+ };
+
+/*
+* Search for a certificate by subject keyid
+*/
+class BOTAN_DLL SKID_Match : public X509_Store::Search_Func
+ {
+ public:
+ bool match(const X509_Certificate& cert) const;
+ SKID_Match(const MemoryRegion<byte>& s) : skid(s) {}
+ private:
+ MemoryVector<byte> skid;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509opt.cpp b/botan/src/cert/x509/x509opt.cpp
new file mode 100644
index 0000000..de9d589
--- /dev/null
+++ b/botan/src/cert/x509/x509opt.cpp
@@ -0,0 +1,108 @@
+/*
+* X.509 Certificate Options
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509self.h>
+#include <botan/util.h>
+#include <botan/parsing.h>
+#include <botan/oids.h>
+#include <ctime>
+
+namespace Botan {
+
+/*
+* Set when the certificate should become valid
+*/
+void X509_Cert_Options::not_before(const std::string& time_string)
+ {
+ start = X509_Time(time_string);
+ }
+
+/*
+* Set when the certificate should expire
+*/
+void X509_Cert_Options::not_after(const std::string& time_string)
+ {
+ end = X509_Time(time_string);
+ }
+
+/*
+* Set key constraint information
+*/
+void X509_Cert_Options::add_constraints(Key_Constraints usage)
+ {
+ constraints = usage;
+ }
+
+/*
+* Set key constraint information
+*/
+void X509_Cert_Options::add_ex_constraint(const OID& oid)
+ {
+ ex_constraints.push_back(oid);
+ }
+
+/*
+* Set key constraint information
+*/
+void X509_Cert_Options::add_ex_constraint(const std::string& oid_str)
+ {
+ ex_constraints.push_back(OIDS::lookup(oid_str));
+ }
+
+/*
+* Mark this certificate for CA usage
+*/
+void X509_Cert_Options::CA_key(u32bit limit)
+ {
+ is_CA = true;
+ path_limit = limit;
+ }
+
+/*
+* Do basic sanity checks
+*/
+void X509_Cert_Options::sanity_check() const
+ {
+ if(common_name == "" || country == "")
+ throw Encoding_Error("X.509 certificate: name and country MUST be set");
+ if(country.size() != 2)
+ throw Encoding_Error("Invalid ISO country code: " + country);
+ if(start >= end)
+ throw Encoding_Error("X509_Cert_Options: invalid time constraints");
+ }
+
+/*
+* Initialize the certificate options
+*/
+X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts,
+ u32bit expiration_time_in_seconds)
+ {
+ is_CA = false;
+ path_limit = 0;
+ constraints = NO_CONSTRAINTS;
+
+ const u32bit now = system_time();
+
+ start = X509_Time(now);
+ end = X509_Time(now + expiration_time_in_seconds);
+
+ if(initial_opts == "")
+ return;
+
+ std::vector<std::string> parsed = split_on(initial_opts, '/');
+
+ if(parsed.size() > 4)
+ throw Invalid_Argument("X.509 cert options: Too many names: "
+ + initial_opts);
+
+ if(parsed.size() >= 1) common_name = parsed[0];
+ if(parsed.size() >= 2) country = parsed[1];
+ if(parsed.size() >= 3) organization = parsed[2];
+ if(parsed.size() == 4) org_unit = parsed[3];
+ }
+
+}
diff --git a/botan/src/cert/x509/x509self.cpp b/botan/src/cert/x509/x509self.cpp
new file mode 100644
index 0000000..8afb22a
--- /dev/null
+++ b/botan/src/cert/x509/x509self.cpp
@@ -0,0 +1,176 @@
+/*
+* PKCS #10/Self Signed Cert Creation
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509self.h>
+#include <botan/x509_ext.h>
+#include <botan/x509_ca.h>
+#include <botan/der_enc.h>
+#include <botan/look_pk.h>
+#include <botan/oids.h>
+#include <botan/pipe.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Shared setup for self-signed items
+*/
+MemoryVector<byte> shared_setup(const X509_Cert_Options& opts,
+ const Private_Key& key)
+ {
+ const Private_Key* key_pointer = &key;
+ if(!dynamic_cast<const PK_Signing_Key*>(key_pointer))
+ throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign");
+
+ opts.sanity_check();
+
+ Pipe key_encoder;
+ key_encoder.start_msg();
+ X509::encode(key, key_encoder, RAW_BER);
+ key_encoder.end_msg();
+
+ return key_encoder.read_all();
+ }
+
+/*
+* Load information from the X509_Cert_Options
+*/
+void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn,
+ AlternativeName& subject_alt)
+ {
+ subject_dn.add_attribute("X520.CommonName", opts.common_name);
+ subject_dn.add_attribute("X520.Country", opts.country);
+ subject_dn.add_attribute("X520.State", opts.state);
+ subject_dn.add_attribute("X520.Locality", opts.locality);
+ subject_dn.add_attribute("X520.Organization", opts.organization);
+ subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
+ subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
+ subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip);
+ subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"),
+ opts.xmpp, UTF8_STRING);
+ }
+
+}
+
+namespace X509 {
+
+/*
+* Create a new self-signed X.509 certificate
+*/
+X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ AlgorithmIdentifier sig_algo;
+ X509_DN subject_dn;
+ AlternativeName subject_alt;
+
+ MemoryVector<byte> pub_key = shared_setup(opts, key);
+ std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+ load_info(opts, subject_dn, subject_alt);
+
+ Key_Constraints constraints;
+ if(opts.is_CA)
+ constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
+ else
+ constraints = find_constraints(key, opts.constraints);
+
+ Extensions extensions;
+
+ extensions.add(new Cert_Extension::Subject_Key_ID(pub_key));
+ extensions.add(new Cert_Extension::Key_Usage(constraints));
+ extensions.add(
+ new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
+ extensions.add(
+ new Cert_Extension::Subject_Alternative_Name(subject_alt));
+ extensions.add(
+ new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit));
+
+ return X509_CA::make_cert(signer.get(), rng, sig_algo, pub_key,
+ opts.start, opts.end,
+ subject_dn, subject_dn,
+ extensions);
+ }
+
+/*
+* Create a PKCS #10 certificate request
+*/
+PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ AlgorithmIdentifier sig_algo;
+ X509_DN subject_dn;
+ AlternativeName subject_alt;
+
+ MemoryVector<byte> pub_key = shared_setup(opts, key);
+ std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+ load_info(opts, subject_dn, subject_alt);
+
+ const u32bit PKCS10_VERSION = 0;
+
+ Extensions extensions;
+
+ extensions.add(
+ new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit));
+ extensions.add(
+ new Cert_Extension::Key_Usage(
+ opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) :
+ find_constraints(key, opts.constraints)
+ )
+ );
+ extensions.add(
+ new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
+ extensions.add(
+ new Cert_Extension::Subject_Alternative_Name(subject_alt));
+
+ DER_Encoder tbs_req;
+
+ tbs_req.start_cons(SEQUENCE)
+ .encode(PKCS10_VERSION)
+ .encode(subject_dn)
+ .raw_bytes(pub_key)
+ .start_explicit(0);
+
+ if(opts.challenge != "")
+ {
+ ASN1_String challenge(opts.challenge, DIRECTORY_STRING);
+
+ tbs_req.encode(
+ Attribute("PKCS9.ChallengePassword",
+ DER_Encoder().encode(challenge).get_contents()
+ )
+ );
+ }
+
+ tbs_req.encode(
+ Attribute("PKCS9.ExtensionRequest",
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(extensions)
+ .end_cons()
+ .get_contents()
+ )
+ )
+ .end_explicit()
+ .end_cons();
+
+ DataSource_Memory source(
+ X509_Object::make_signed(signer.get(),
+ rng,
+ sig_algo,
+ tbs_req.get_contents())
+ );
+
+ return PKCS10_Request(source);
+ }
+
+}
+
+}
diff --git a/botan/src/cert/x509/x509self.h b/botan/src/cert/x509/x509self.h
new file mode 100644
index 0000000..bd3e291
--- /dev/null
+++ b/botan/src/cert/x509/x509self.h
@@ -0,0 +1,198 @@
+/*
+* X.509 Self-Signed Certificate
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_SELF_H__
+#define BOTAN_X509_SELF_H__
+
+#include <botan/x509cert.h>
+#include <botan/pkcs8.h>
+#include <botan/pkcs10.h>
+
+namespace Botan {
+
+/**
+* Options for X.509 certificates.
+*/
+class BOTAN_DLL X509_Cert_Options
+ {
+ public:
+ /**
+ * the subject common name
+ */
+ std::string common_name;
+
+ /**
+ * the subject counry
+ */
+ std::string country;
+
+ /**
+ * the subject organization
+ */
+ std::string organization;
+
+ /**
+ * the subject organizational unit
+ */
+ std::string org_unit;
+
+ /**
+ * the subject locality
+ */
+ std::string locality;
+
+ /**
+ * the subject state
+ */
+ std::string state;
+
+ /**
+ * the subject serial number
+ */
+ std::string serial_number;
+
+ /**
+ * the subject email adress
+ */
+ std::string email;
+
+ /**
+ * the subject URI
+ */
+ std::string uri;
+
+ /**
+ * the subject IPv4 address
+ */
+ std::string ip;
+
+ /**
+ * the subject DNS
+ */
+ std::string dns;
+
+ /**
+ * the subject XMPP
+ */
+ std::string xmpp;
+
+ /**
+ * the subject challenge password
+ */
+ std::string challenge;
+
+ /**
+ * the subject notBefore
+ */
+ X509_Time start;
+ /**
+ * the subject notAfter
+ */
+ X509_Time end;
+
+ /**
+ * Indicates whether the certificate request
+ */
+ bool is_CA;
+
+ /**
+ * Indicates the BasicConstraints path limit
+ */
+ u32bit path_limit;
+
+ /**
+ * The key constraints for the subject public key
+ */
+ Key_Constraints constraints;
+
+ /**
+ * The key extended constraints for the subject public key
+ */
+ std::vector<OID> ex_constraints;
+
+ /**
+ * Check the options set in this object for validity.
+ */
+ void sanity_check() const;
+
+ /**
+ * Mark the certificate as a CA certificate and set the path limit.
+ * @param limit the path limit to be set in the BasicConstraints extension.
+ */
+ void CA_key(u32bit limit = 1);
+
+ /**
+ * Set the notBefore of the certificate.
+ * @param time the notBefore value of the certificate
+ */
+ void not_before(const std::string& time);
+
+ /**
+ * Set the notAfter of the certificate.
+ * @param time the notAfter value of the certificate
+ */
+ void not_after(const std::string& time);
+
+ /**
+ * Add the key constraints of the KeyUsage extension.
+ * @param constr the constraints to set
+ */
+ void add_constraints(Key_Constraints constr);
+
+ /**
+ * Add constraints to the ExtendedKeyUsage extension.
+ * @param oid the oid to add
+ */
+ void add_ex_constraint(const OID& oid);
+
+ /**
+ * Add constraints to the ExtendedKeyUsage extension.
+ * @param name the name to look up the oid to add
+ */
+ void add_ex_constraint(const std::string& name);
+
+ /**
+ * Construct a new options object
+ * @param opts define the common name of this object. An example for this
+ * parameter would be "common_name/country/organization/organizational_unit".
+ * @param expire_time the expiration time (from the current clock in seconds)
+ */
+ X509_Cert_Options(const std::string& opts = "",
+ u32bit expire_time = 365 * 24 * 60 * 60);
+ };
+
+namespace X509 {
+
+/**
+* Create a self-signed X.509 certificate.
+* @param opts the options defining the certificate to create
+* @param key the private key used for signing, i.e. the key
+* associated with this self-signed certificate
+* @param rng the rng to use
+* @return the newly created self-signed certificate
+*/
+BOTAN_DLL X509_Certificate
+create_self_signed_cert(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+/**
+* Create a PKCS#10 certificate request.
+* @param opts the options defining the request to create
+* @param key the key used to sign this request
+* @param rng the rng to use
+* @return the newly created PKCS#10 request
+*/
+BOTAN_DLL PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
+ const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/cert/x509/x509stor.cpp b/botan/src/cert/x509/x509stor.cpp
new file mode 100644
index 0000000..cb61bc2
--- /dev/null
+++ b/botan/src/cert/x509/x509stor.cpp
@@ -0,0 +1,695 @@
+/*
+* X.509 Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509stor.h>
+#include <botan/parsing.h>
+#include <botan/pubkey.h>
+#include <botan/look_pk.h>
+#include <botan/oids.h>
+#include <botan/util.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Do a validity check
+*/
+s32bit validity_check(const X509_Time& start, const X509_Time& end,
+ u64bit current_time, u32bit slack)
+ {
+ const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1;
+
+ if(start.cmp(current_time + slack) > 0)
+ return NOT_YET_VALID;
+ if(end.cmp(current_time - slack) < 0)
+ return EXPIRED;
+ return VALID_TIME;
+ }
+
+/*
+* Compare the value of unique ID fields
+*/
+bool compare_ids(const MemoryVector<byte>& id1,
+ const MemoryVector<byte>& id2)
+ {
+ if(!id1.size() || !id2.size())
+ return true;
+ return (id1 == id2);
+ }
+
+/*
+* Check a particular usage restriction
+*/
+bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage,
+ X509_Store::Cert_Usage check_for, Key_Constraints constraints)
+ {
+ if((usage & check_for) == 0)
+ return true;
+ if(cert.constraints() == NO_CONSTRAINTS)
+ return true;
+ if(cert.constraints() & constraints)
+ return true;
+ return false;
+ }
+
+/*
+* Check a particular usage restriction
+*/
+bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage,
+ X509_Store::Cert_Usage check_for,
+ const std::string& usage_oid)
+ {
+ if((usage & check_for) == 0)
+ return true;
+
+ const std::vector<std::string> constraints = cert.ex_constraints();
+
+ if(constraints.empty())
+ return true;
+
+ return std::binary_search(constraints.begin(), constraints.end(),
+ usage_oid);
+ }
+
+/*
+* Check the usage restrictions
+*/
+X509_Code usage_check(const X509_Certificate& cert,
+ X509_Store::Cert_Usage usage)
+ {
+ if(usage == X509_Store::ANY)
+ return VERIFIED;
+
+ if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN))
+ return CA_CERT_NOT_FOR_CRL_ISSUER;
+
+ if(!check_usage(cert, usage, X509_Store::TLS_SERVER, "PKIX.ServerAuth"))
+ return INVALID_USAGE;
+ if(!check_usage(cert, usage, X509_Store::TLS_CLIENT, "PKIX.ClientAuth"))
+ return INVALID_USAGE;
+ if(!check_usage(cert, usage, X509_Store::CODE_SIGNING, "PKIX.CodeSigning"))
+ return INVALID_USAGE;
+ if(!check_usage(cert, usage, X509_Store::EMAIL_PROTECTION,
+ "PKIX.EmailProtection"))
+ return INVALID_USAGE;
+ if(!check_usage(cert, usage, X509_Store::TIME_STAMPING,
+ "PKIX.TimeStamping"))
+ return INVALID_USAGE;
+
+ return VERIFIED;
+ }
+
+}
+
+/*
+* Define equality for revocation data
+*/
+bool X509_Store::CRL_Data::operator==(const CRL_Data& other) const
+ {
+ if(issuer != other.issuer)
+ return false;
+ if(serial != other.serial)
+ return false;
+ return compare_ids(auth_key_id, other.auth_key_id);
+ }
+
+/*
+* Define inequality for revocation data
+*/
+bool X509_Store::CRL_Data::operator!=(const CRL_Data& other) const
+ {
+ return !((*this) == other);
+ }
+
+/*
+* Define an ordering for revocation data
+*/
+bool X509_Store::CRL_Data::operator<(const X509_Store::CRL_Data& other) const
+ {
+ if(*this == other)
+ return false;
+
+ const MemoryVector<byte>& serial1 = serial;
+ const MemoryVector<byte>& key_id1 = auth_key_id;
+ const MemoryVector<byte>& serial2 = other.serial;
+ const MemoryVector<byte>& key_id2 = other.auth_key_id;
+
+ if(compare_ids(key_id1, key_id2) == false)
+ {
+ if(std::lexicographical_compare(key_id1.begin(), key_id1.end(),
+ key_id2.begin(), key_id2.end()))
+ return true;
+
+ if(std::lexicographical_compare(key_id2.begin(), key_id2.end(),
+ key_id1.begin(), key_id1.end()))
+ return false;
+ }
+
+ if(compare_ids(serial1, serial2) == false)
+ {
+ if(std::lexicographical_compare(serial1.begin(), serial1.end(),
+ serial2.begin(), serial2.end()))
+ return true;
+
+ if(std::lexicographical_compare(serial2.begin(), serial2.end(),
+ serial1.begin(), serial1.end()))
+ return false;
+ }
+
+ return (issuer < other.issuer);
+ }
+
+/*
+* X509_Store Constructor
+*/
+X509_Store::X509_Store(u32bit slack, u32bit cache_timeout)
+ {
+ revoked_info_valid = true;
+
+ validation_cache_timeout = cache_timeout;
+ time_slack = slack;
+ }
+
+/*
+* X509_Store Copy Constructor
+*/
+X509_Store::X509_Store(const X509_Store& other)
+ {
+ certs = other.certs;
+ revoked = other.revoked;
+ revoked_info_valid = other.revoked_info_valid;
+ for(u32bit j = 0; j != other.stores.size(); ++j)
+ stores[j] = other.stores[j]->clone();
+ time_slack = other.time_slack;
+ }
+
+/*
+* X509_Store Destructor
+*/
+X509_Store::~X509_Store()
+ {
+ for(u32bit j = 0; j != stores.size(); ++j)
+ delete stores[j];
+ }
+
+/*
+* Verify a certificate's authenticity
+*/
+X509_Code X509_Store::validate_cert(const X509_Certificate& cert,
+ Cert_Usage cert_usage)
+ {
+ recompute_revoked_info();
+
+ std::vector<u32bit> indexes;
+ X509_Code chaining_result = construct_cert_chain(cert, indexes);
+ if(chaining_result != VERIFIED)
+ return chaining_result;
+
+ const u64bit current_time = system_time();
+
+ s32bit time_check = validity_check(cert.start_time(), cert.end_time(),
+ current_time, time_slack);
+ if(time_check < 0) return CERT_NOT_YET_VALID;
+ else if(time_check > 0) return CERT_HAS_EXPIRED;
+
+ X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]);
+ if(sig_check_result != VERIFIED)
+ return sig_check_result;
+
+ if(is_revoked(cert))
+ return CERT_IS_REVOKED;
+
+ for(u32bit j = 0; j != indexes.size() - 1; ++j)
+ {
+ const X509_Certificate& current_cert = certs[indexes[j]].cert;
+
+ time_check = validity_check(current_cert.start_time(),
+ current_cert.end_time(),
+ current_time,
+ time_slack);
+
+ if(time_check < 0) return CERT_NOT_YET_VALID;
+ else if(time_check > 0) return CERT_HAS_EXPIRED;
+
+ sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]);
+ if(sig_check_result != VERIFIED)
+ return sig_check_result;
+ }
+
+ return usage_check(cert, cert_usage);
+ }
+
+/*
+* Find this certificate
+*/
+u32bit X509_Store::find_cert(const X509_DN& subject_dn,
+ const MemoryRegion<byte>& subject_key_id) const
+ {
+ for(u32bit j = 0; j != certs.size(); ++j)
+ {
+ const X509_Certificate& this_cert = certs[j].cert;
+ if(compare_ids(this_cert.subject_key_id(), subject_key_id) &&
+ this_cert.subject_dn() == subject_dn)
+ return j;
+ }
+ return NO_CERT_FOUND;
+ }
+
+/*
+* Find the parent of this certificate
+*/
+u32bit X509_Store::find_parent_of(const X509_Certificate& cert)
+ {
+ const X509_DN issuer_dn = cert.issuer_dn();
+ const MemoryVector<byte> auth_key_id = cert.authority_key_id();
+
+ u32bit index = find_cert(issuer_dn, auth_key_id);
+
+ if(index != NO_CERT_FOUND)
+ return index;
+
+ if(auth_key_id.size())
+ {
+ for(u32bit j = 0; j != stores.size(); ++j)
+ {
+ std::vector<X509_Certificate> got = stores[j]->by_SKID(auth_key_id);
+
+ if(got.empty())
+ continue;
+
+ for(u32bit k = 0; k != got.size(); ++k)
+ add_cert(got[k]);
+ return find_cert(issuer_dn, auth_key_id);
+ }
+ }
+
+ return NO_CERT_FOUND;
+ }
+
+/*
+* Construct a chain of certificate relationships
+*/
+X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert,
+ std::vector<u32bit>& indexes,
+ bool need_full_chain)
+ {
+ u32bit parent = find_parent_of(end_cert);
+
+ while(true)
+ {
+ if(parent == NO_CERT_FOUND)
+ return CERT_ISSUER_NOT_FOUND;
+ indexes.push_back(parent);
+
+ if(certs[parent].is_verified(validation_cache_timeout))
+ if(certs[parent].verify_result() != VERIFIED)
+ return certs[parent].verify_result();
+
+ const X509_Certificate& parent_cert = certs[parent].cert;
+ if(!parent_cert.is_CA_cert())
+ return CA_CERT_NOT_FOR_CERT_ISSUER;
+
+ if(certs[parent].is_trusted())
+ break;
+ if(parent_cert.is_self_signed())
+ return CANNOT_ESTABLISH_TRUST;
+
+ if(parent_cert.path_limit() < indexes.size() - 1)
+ return CERT_CHAIN_TOO_LONG;
+
+ parent = find_parent_of(parent_cert);
+ }
+
+ if(need_full_chain)
+ return VERIFIED;
+
+ while(true)
+ {
+ if(indexes.size() < 2)
+ break;
+
+ const u32bit cert = indexes.back();
+
+ if(certs[cert].is_verified(validation_cache_timeout))
+ {
+ if(certs[cert].verify_result() != VERIFIED)
+ throw Internal_Error("X509_Store::construct_cert_chain");
+ indexes.pop_back();
+ }
+ else
+ break;
+ }
+
+ const u32bit last_cert = indexes.back();
+ const u32bit parent_of_last_cert = find_parent_of(certs[last_cert].cert);
+ if(parent_of_last_cert == NO_CERT_FOUND)
+ return CERT_ISSUER_NOT_FOUND;
+ indexes.push_back(parent_of_last_cert);
+
+ return VERIFIED;
+ }
+
+/*
+* Check the CAs signature on a certificate
+*/
+X509_Code X509_Store::check_sig(const Cert_Info& cert_info,
+ const Cert_Info& ca_cert_info) const
+ {
+ if(cert_info.is_verified(validation_cache_timeout))
+ return cert_info.verify_result();
+
+ const X509_Certificate& cert = cert_info.cert;
+ const X509_Certificate& ca_cert = ca_cert_info.cert;
+
+ X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key());
+
+ cert_info.set_result(verify_code);
+
+ return verify_code;
+ }
+
+/*
+* Check a CA's signature
+*/
+X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key)
+ {
+ std::auto_ptr<Public_Key> pub_key(key);
+ std::auto_ptr<PK_Verifier> verifier;
+
+ try {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(object.signature_algorithm().oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
+ return SIGNATURE_ERROR;
+
+ std::string padding = sig_info[1];
+ Signature_Format format;
+ if(key->message_parts() >= 2) format = DER_SEQUENCE;
+ else format = IEEE_1363;
+
+ if(dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get()))
+ {
+ PK_Verifying_with_MR_Key* sig_key =
+ dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get());
+ verifier.reset(get_pk_verifier(*sig_key, padding, format));
+ }
+ else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get()))
+ {
+ PK_Verifying_wo_MR_Key* sig_key =
+ dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get());
+ verifier.reset(get_pk_verifier(*sig_key, padding, format));
+ }
+ else
+ return CA_CERT_CANNOT_SIGN;
+
+ bool valid = verifier->verify_message(object.tbs_data(),
+ object.signature());
+
+ if(valid)
+ return VERIFIED;
+ else
+ return SIGNATURE_ERROR;
+ }
+ catch(Decoding_Error) { return CERT_FORMAT_ERROR; }
+ catch(Exception) {}
+
+ return UNKNOWN_X509_ERROR;
+ }
+
+/*
+* Recompute the revocation status of the certs
+*/
+void X509_Store::recompute_revoked_info() const
+ {
+ if(revoked_info_valid)
+ return;
+
+ for(u32bit j = 0; j != certs.size(); ++j)
+ {
+ if((certs[j].is_verified(validation_cache_timeout)) &&
+ (certs[j].verify_result() != VERIFIED))
+ continue;
+
+ if(is_revoked(certs[j].cert))
+ certs[j].set_result(CERT_IS_REVOKED);
+ }
+
+ revoked_info_valid = true;
+ }
+
+/*
+* Check if a certificate is revoked
+*/
+bool X509_Store::is_revoked(const X509_Certificate& cert) const
+ {
+ CRL_Data revoked_info;
+ revoked_info.issuer = cert.issuer_dn();
+ revoked_info.serial = cert.serial_number();
+ revoked_info.auth_key_id = cert.authority_key_id();
+
+ if(std::binary_search(revoked.begin(), revoked.end(), revoked_info))
+ return true;
+ return false;
+ }
+
+/*
+* Retrieve all the certificates in the store
+*/
+std::vector<X509_Certificate>
+X509_Store::get_certs(const Search_Func& search) const
+ {
+ std::vector<X509_Certificate> found_certs;
+ for(u32bit j = 0; j != certs.size(); ++j)
+ {
+ if(search.match(certs[j].cert))
+ found_certs.push_back(certs[j].cert);
+ }
+ return found_certs;
+ }
+
+/*
+* Construct a path back to a root for this cert
+*/
+std::vector<X509_Certificate>
+X509_Store::get_cert_chain(const X509_Certificate& cert)
+ {
+ std::vector<X509_Certificate> result;
+ std::vector<u32bit> indexes;
+ X509_Code chaining_result = construct_cert_chain(cert, indexes, true);
+
+ if(chaining_result != VERIFIED)
+ throw Invalid_State("X509_Store::get_cert_chain: Can't construct chain");
+
+ for(u32bit j = 0; j != indexes.size(); ++j)
+ result.push_back(certs[indexes[j]].cert);
+ return result;
+ }
+
+/*
+* Add a certificate store to the list of stores
+*/
+void X509_Store::add_new_certstore(Certificate_Store* certstore)
+ {
+ stores.push_back(certstore);
+ }
+
+/*
+* Add a certificate to the store
+*/
+void X509_Store::add_cert(const X509_Certificate& cert, bool trusted)
+ {
+ if(trusted && !cert.is_self_signed())
+ throw Invalid_Argument("X509_Store: Trusted certs must be self-signed");
+
+ if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND)
+ {
+ revoked_info_valid = false;
+ Cert_Info info(cert, trusted);
+ certs.push_back(info);
+ }
+ else if(trusted)
+ {
+ for(u32bit j = 0; j != certs.size(); ++j)
+ {
+ const X509_Certificate& this_cert = certs[j].cert;
+ if(this_cert == cert)
+ certs[j].trusted = trusted;
+ }
+ }
+ }
+
+/*
+* Add one or more certificates to the store
+*/
+void X509_Store::do_add_certs(DataSource& source, bool trusted)
+ {
+ while(!source.end_of_data())
+ {
+ try {
+ X509_Certificate cert(source);
+ add_cert(cert, trusted);
+ }
+ catch(Decoding_Error) {}
+ catch(Invalid_Argument) {}
+ }
+ }
+
+/*
+* Add one or more certificates to the store
+*/
+void X509_Store::add_certs(DataSource& source)
+ {
+ do_add_certs(source, false);
+ }
+
+/*
+* Add one or more certificates to the store
+*/
+void X509_Store::add_trusted_certs(DataSource& source)
+ {
+ do_add_certs(source, true);
+ }
+
+/*
+* Add one or more certificates to the store
+*/
+X509_Code X509_Store::add_crl(const X509_CRL& crl)
+ {
+ s32bit time_check = validity_check(crl.this_update(), crl.next_update(),
+ system_time(), time_slack);
+
+ if(time_check < 0) return CRL_NOT_YET_VALID;
+ else if(time_check > 0) return CRL_HAS_EXPIRED;
+
+ u32bit cert_index = NO_CERT_FOUND;
+
+ for(u32bit j = 0; j != certs.size(); ++j)
+ {
+ const X509_Certificate& this_cert = certs[j].cert;
+ if(compare_ids(this_cert.subject_key_id(), crl.authority_key_id()))
+ {
+ if(this_cert.subject_dn() == crl.issuer_dn())
+ cert_index = j;
+ }
+ }
+
+ if(cert_index == NO_CERT_FOUND)
+ return CRL_ISSUER_NOT_FOUND;
+
+ const X509_Certificate& ca_cert = certs[cert_index].cert;
+
+ X509_Code verify_result = validate_cert(ca_cert, CRL_SIGNING);
+ if(verify_result != VERIFIED)
+ return verify_result;
+
+ verify_result = check_sig(crl, ca_cert.subject_public_key());
+ if(verify_result != VERIFIED)
+ return verify_result;
+
+ std::vector<CRL_Entry> revoked_certs = crl.get_revoked();
+
+ for(u32bit j = 0; j != revoked_certs.size(); ++j)
+ {
+ CRL_Data revoked_info;
+ revoked_info.issuer = crl.issuer_dn();
+ revoked_info.serial = revoked_certs[j].serial_number();
+ revoked_info.auth_key_id = crl.authority_key_id();
+
+ std::vector<CRL_Data>::iterator p =
+ std::find(revoked.begin(), revoked.end(), revoked_info);
+
+ if(revoked_certs[j].reason_code() == REMOVE_FROM_CRL)
+ {
+ if(p == revoked.end()) continue;
+ revoked.erase(p);
+ }
+ else
+ {
+ if(p != revoked.end()) continue;
+ revoked.push_back(revoked_info);
+ }
+ }
+
+ std::sort(revoked.begin(), revoked.end());
+ revoked_info_valid = false;
+
+ return VERIFIED;
+ }
+
+/*
+* PEM encode the set of certificates
+*/
+std::string X509_Store::PEM_encode() const
+ {
+ std::string cert_store;
+ for(u32bit j = 0; j != certs.size(); ++j)
+ cert_store += certs[j].cert.PEM_encode();
+ return cert_store;
+ }
+
+/*
+* Create a Cert_Info structure
+*/
+X509_Store::Cert_Info::Cert_Info(const X509_Certificate& c,
+ bool t) : cert(c), trusted(t)
+ {
+ checked = false;
+ result = UNKNOWN_X509_ERROR;
+ last_checked = 0;
+ }
+
+/*
+* Return the verification results
+*/
+X509_Code X509_Store::Cert_Info::verify_result() const
+ {
+ if(!checked)
+ throw Invalid_State("Cert_Info::verify_result() called; not checked");
+ return result;
+ }
+
+/*
+* Set the verification results
+*/
+void X509_Store::Cert_Info::set_result(X509_Code code) const
+ {
+ result = code;
+ last_checked = system_time();
+ checked = true;
+ }
+
+/*
+* Check if this certificate can be trusted
+*/
+bool X509_Store::Cert_Info::is_trusted() const
+ {
+ return trusted;
+ }
+
+/*
+* Check if this certificate has been verified
+*/
+bool X509_Store::Cert_Info::is_verified(u32bit timeout) const
+ {
+ if(!checked)
+ return false;
+ if(result != VERIFIED && result != CERT_NOT_YET_VALID)
+ return true;
+
+ const u64bit current_time = system_time();
+
+ if(current_time > last_checked + timeout)
+ checked = false;
+
+ return checked;
+ }
+
+}
diff --git a/botan/src/cert/x509/x509stor.h b/botan/src/cert/x509/x509stor.h
new file mode 100644
index 0000000..4e60378
--- /dev/null
+++ b/botan/src/cert/x509/x509stor.h
@@ -0,0 +1,143 @@
+/*
+* X.509 Certificate Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_CERT_STORE_H__
+#define BOTAN_X509_CERT_STORE_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/certstor.h>
+
+namespace Botan {
+
+/*
+* X.509 Certificate Validation Result
+*/
+enum X509_Code {
+ VERIFIED,
+ UNKNOWN_X509_ERROR,
+ CANNOT_ESTABLISH_TRUST,
+ CERT_CHAIN_TOO_LONG,
+ SIGNATURE_ERROR,
+ POLICY_ERROR,
+ INVALID_USAGE,
+
+ CERT_FORMAT_ERROR,
+ CERT_ISSUER_NOT_FOUND,
+ CERT_NOT_YET_VALID,
+ CERT_HAS_EXPIRED,
+ CERT_IS_REVOKED,
+
+ CRL_FORMAT_ERROR,
+ CRL_ISSUER_NOT_FOUND,
+ CRL_NOT_YET_VALID,
+ CRL_HAS_EXPIRED,
+
+ CA_CERT_CANNOT_SIGN,
+ CA_CERT_NOT_FOR_CERT_ISSUER,
+ CA_CERT_NOT_FOR_CRL_ISSUER
+};
+
+/*
+* X.509 Certificate Store
+*/
+class BOTAN_DLL X509_Store
+ {
+ public:
+ class BOTAN_DLL Search_Func
+ {
+ public:
+ virtual bool match(const X509_Certificate&) const = 0;
+ virtual ~Search_Func() {}
+ };
+
+ enum Cert_Usage {
+ ANY = 0x00,
+ TLS_SERVER = 0x01,
+ TLS_CLIENT = 0x02,
+ CODE_SIGNING = 0x04,
+ EMAIL_PROTECTION = 0x08,
+ TIME_STAMPING = 0x10,
+ CRL_SIGNING = 0x20
+ };
+
+ X509_Code validate_cert(const X509_Certificate&, Cert_Usage = ANY);
+
+ std::vector<X509_Certificate> get_certs(const Search_Func&) const;
+ std::vector<X509_Certificate> get_cert_chain(const X509_Certificate&);
+ std::string PEM_encode() const;
+
+ /*
+ * Made CRL_Data public for XLC for Cell 0.9, otherwise cannot
+ * instantiate member variable std::vector<CRL_Data> revoked
+ */
+ class BOTAN_DLL CRL_Data
+ {
+ public:
+ X509_DN issuer;
+ MemoryVector<byte> serial, auth_key_id;
+ bool operator==(const CRL_Data&) const;
+ bool operator!=(const CRL_Data&) const;
+ bool operator<(const CRL_Data&) const;
+ };
+
+ X509_Code add_crl(const X509_CRL&);
+ void add_cert(const X509_Certificate&, bool = false);
+ void add_certs(DataSource&);
+ void add_trusted_certs(DataSource&);
+
+ void add_new_certstore(Certificate_Store*);
+
+ static X509_Code check_sig(const X509_Object&, Public_Key*);
+
+ X509_Store(u32bit time_slack = 24*60*60,
+ u32bit cache_results = 30*60);
+
+ X509_Store(const X509_Store&);
+ ~X509_Store();
+ private:
+ X509_Store& operator=(const X509_Store&) { return (*this); }
+
+ class BOTAN_DLL Cert_Info
+ {
+ public:
+ bool is_verified(u32bit timeout) const;
+ bool is_trusted() const;
+ X509_Code verify_result() const;
+ void set_result(X509_Code) const;
+ Cert_Info(const X509_Certificate&, bool = false);
+
+ X509_Certificate cert;
+ bool trusted;
+ private:
+ mutable bool checked;
+ mutable X509_Code result;
+ mutable u64bit last_checked;
+ };
+
+ u32bit find_cert(const X509_DN&, const MemoryRegion<byte>&) const;
+ X509_Code check_sig(const Cert_Info&, const Cert_Info&) const;
+ void recompute_revoked_info() const;
+
+ void do_add_certs(DataSource&, bool);
+ X509_Code construct_cert_chain(const X509_Certificate&,
+ std::vector<u32bit>&, bool = false);
+
+ u32bit find_parent_of(const X509_Certificate&);
+ bool is_revoked(const X509_Certificate&) const;
+
+ static const u32bit NO_CERT_FOUND = 0xFFFFFFFF;
+ std::vector<Cert_Info> certs;
+ std::vector<CRL_Data> revoked;
+ std::vector<Certificate_Store*> stores;
+ u32bit time_slack, validation_cache_timeout;
+ mutable bool revoked_info_valid;
+ };
+
+}
+
+#endif
diff --git a/botan/src/checksum/adler32/adler32.cpp b/botan/src/checksum/adler32/adler32.cpp
new file mode 100644
index 0000000..c66943b
--- /dev/null
+++ b/botan/src/checksum/adler32/adler32.cpp
@@ -0,0 +1,74 @@
+/*
+* Adler32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/adler32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Adler32 Checksum
+*/
+void Adler32::hash(const byte input[], u32bit length)
+ {
+ u32bit S1x = S1, S2x = S2;
+ while(length >= 16)
+ {
+ S1x += input[ 0]; S2x += S1x;
+ S1x += input[ 1]; S2x += S1x;
+ S1x += input[ 2]; S2x += S1x;
+ S1x += input[ 3]; S2x += S1x;
+ S1x += input[ 4]; S2x += S1x;
+ S1x += input[ 5]; S2x += S1x;
+ S1x += input[ 6]; S2x += S1x;
+ S1x += input[ 7]; S2x += S1x;
+ S1x += input[ 8]; S2x += S1x;
+ S1x += input[ 9]; S2x += S1x;
+ S1x += input[10]; S2x += S1x;
+ S1x += input[11]; S2x += S1x;
+ S1x += input[12]; S2x += S1x;
+ S1x += input[13]; S2x += S1x;
+ S1x += input[14]; S2x += S1x;
+ S1x += input[15]; S2x += S1x;
+ input += 16;
+ length -= 16;
+ }
+ for(u32bit j = 0; j != length; ++j)
+ {
+ S1x += input[j]; S2x += S1x;
+ }
+ S1x %= 65521;
+ S2x %= 65521;
+ S1 = S1x;
+ S2 = S2x;
+ }
+
+/*
+* Update an Adler32 Checksum
+*/
+void Adler32::add_data(const byte input[], u32bit length)
+ {
+ const u32bit PROCESS_AMOUNT = 5552;
+ while(length >= PROCESS_AMOUNT)
+ {
+ hash(input, PROCESS_AMOUNT);
+ input += PROCESS_AMOUNT;
+ length -= PROCESS_AMOUNT;
+ }
+ hash(input, length);
+ }
+
+/*
+* Finalize an Adler32 Checksum
+*/
+void Adler32::final_result(byte output[])
+ {
+ store_be(output, S2, S1);
+ clear();
+ }
+
+}
diff --git a/botan/src/checksum/adler32/adler32.h b/botan/src/checksum/adler32/adler32.h
new file mode 100644
index 0000000..98a28bc
--- /dev/null
+++ b/botan/src/checksum/adler32/adler32.h
@@ -0,0 +1,35 @@
+/*
+* Adler32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ADLER32_H__
+#define BOTAN_ADLER32_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* Adler32
+*/
+class BOTAN_DLL Adler32 : public HashFunction
+ {
+ public:
+ void clear() throw() { S1 = 1; S2 = 0; }
+ std::string name() const { return "Adler32"; }
+ HashFunction* clone() const { return new Adler32; }
+ Adler32() : HashFunction(4) { clear(); }
+ ~Adler32() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void hash(const byte[], u32bit);
+ u16bit S1, S2;
+ };
+
+}
+
+#endif
diff --git a/botan/src/checksum/adler32/info.txt b/botan/src/checksum/adler32/info.txt
new file mode 100644
index 0000000..76662cd
--- /dev/null
+++ b/botan/src/checksum/adler32/info.txt
@@ -0,0 +1,14 @@
+realname "Adler32"
+
+define ADLER32
+
+load_on auto
+
+<add>
+adler32.cpp
+adler32.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/checksum/crc24/crc24.cpp b/botan/src/checksum/crc24/crc24.cpp
new file mode 100644
index 0000000..e50b4d3
--- /dev/null
+++ b/botan/src/checksum/crc24/crc24.cpp
@@ -0,0 +1,100 @@
+/*
+* CRC24
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/crc24.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Update a CRC24 Checksum
+*/
+void CRC24::add_data(const byte input[], u32bit length)
+ {
+ const u32bit TABLE[256] = {
+ 0x00000000, 0x00864CFB, 0x008AD50D, 0x000C99F6, 0x0093E6E1, 0x0015AA1A,
+ 0x001933EC, 0x009F7F17, 0x00A18139, 0x0027CDC2, 0x002B5434, 0x00AD18CF,
+ 0x003267D8, 0x00B42B23, 0x00B8B2D5, 0x003EFE2E, 0x00C54E89, 0x00430272,
+ 0x004F9B84, 0x00C9D77F, 0x0056A868, 0x00D0E493, 0x00DC7D65, 0x005A319E,
+ 0x0064CFB0, 0x00E2834B, 0x00EE1ABD, 0x00685646, 0x00F72951, 0x007165AA,
+ 0x007DFC5C, 0x00FBB0A7, 0x000CD1E9, 0x008A9D12, 0x008604E4, 0x0000481F,
+ 0x009F3708, 0x00197BF3, 0x0015E205, 0x0093AEFE, 0x00AD50D0, 0x002B1C2B,
+ 0x002785DD, 0x00A1C926, 0x003EB631, 0x00B8FACA, 0x00B4633C, 0x00322FC7,
+ 0x00C99F60, 0x004FD39B, 0x00434A6D, 0x00C50696, 0x005A7981, 0x00DC357A,
+ 0x00D0AC8C, 0x0056E077, 0x00681E59, 0x00EE52A2, 0x00E2CB54, 0x006487AF,
+ 0x00FBF8B8, 0x007DB443, 0x00712DB5, 0x00F7614E, 0x0019A3D2, 0x009FEF29,
+ 0x009376DF, 0x00153A24, 0x008A4533, 0x000C09C8, 0x0000903E, 0x0086DCC5,
+ 0x00B822EB, 0x003E6E10, 0x0032F7E6, 0x00B4BB1D, 0x002BC40A, 0x00AD88F1,
+ 0x00A11107, 0x00275DFC, 0x00DCED5B, 0x005AA1A0, 0x00563856, 0x00D074AD,
+ 0x004F0BBA, 0x00C94741, 0x00C5DEB7, 0x0043924C, 0x007D6C62, 0x00FB2099,
+ 0x00F7B96F, 0x0071F594, 0x00EE8A83, 0x0068C678, 0x00645F8E, 0x00E21375,
+ 0x0015723B, 0x00933EC0, 0x009FA736, 0x0019EBCD, 0x008694DA, 0x0000D821,
+ 0x000C41D7, 0x008A0D2C, 0x00B4F302, 0x0032BFF9, 0x003E260F, 0x00B86AF4,
+ 0x002715E3, 0x00A15918, 0x00ADC0EE, 0x002B8C15, 0x00D03CB2, 0x00567049,
+ 0x005AE9BF, 0x00DCA544, 0x0043DA53, 0x00C596A8, 0x00C90F5E, 0x004F43A5,
+ 0x0071BD8B, 0x00F7F170, 0x00FB6886, 0x007D247D, 0x00E25B6A, 0x00641791,
+ 0x00688E67, 0x00EEC29C, 0x003347A4, 0x00B50B5F, 0x00B992A9, 0x003FDE52,
+ 0x00A0A145, 0x0026EDBE, 0x002A7448, 0x00AC38B3, 0x0092C69D, 0x00148A66,
+ 0x00181390, 0x009E5F6B, 0x0001207C, 0x00876C87, 0x008BF571, 0x000DB98A,
+ 0x00F6092D, 0x007045D6, 0x007CDC20, 0x00FA90DB, 0x0065EFCC, 0x00E3A337,
+ 0x00EF3AC1, 0x0069763A, 0x00578814, 0x00D1C4EF, 0x00DD5D19, 0x005B11E2,
+ 0x00C46EF5, 0x0042220E, 0x004EBBF8, 0x00C8F703, 0x003F964D, 0x00B9DAB6,
+ 0x00B54340, 0x00330FBB, 0x00AC70AC, 0x002A3C57, 0x0026A5A1, 0x00A0E95A,
+ 0x009E1774, 0x00185B8F, 0x0014C279, 0x00928E82, 0x000DF195, 0x008BBD6E,
+ 0x00872498, 0x00016863, 0x00FAD8C4, 0x007C943F, 0x00700DC9, 0x00F64132,
+ 0x00693E25, 0x00EF72DE, 0x00E3EB28, 0x0065A7D3, 0x005B59FD, 0x00DD1506,
+ 0x00D18CF0, 0x0057C00B, 0x00C8BF1C, 0x004EF3E7, 0x00426A11, 0x00C426EA,
+ 0x002AE476, 0x00ACA88D, 0x00A0317B, 0x00267D80, 0x00B90297, 0x003F4E6C,
+ 0x0033D79A, 0x00B59B61, 0x008B654F, 0x000D29B4, 0x0001B042, 0x0087FCB9,
+ 0x001883AE, 0x009ECF55, 0x009256A3, 0x00141A58, 0x00EFAAFF, 0x0069E604,
+ 0x00657FF2, 0x00E33309, 0x007C4C1E, 0x00FA00E5, 0x00F69913, 0x0070D5E8,
+ 0x004E2BC6, 0x00C8673D, 0x00C4FECB, 0x0042B230, 0x00DDCD27, 0x005B81DC,
+ 0x0057182A, 0x00D154D1, 0x0026359F, 0x00A07964, 0x00ACE092, 0x002AAC69,
+ 0x00B5D37E, 0x00339F85, 0x003F0673, 0x00B94A88, 0x0087B4A6, 0x0001F85D,
+ 0x000D61AB, 0x008B2D50, 0x00145247, 0x00921EBC, 0x009E874A, 0x0018CBB1,
+ 0x00E37B16, 0x006537ED, 0x0069AE1B, 0x00EFE2E0, 0x00709DF7, 0x00F6D10C,
+ 0x00FA48FA, 0x007C0401, 0x0042FA2F, 0x00C4B6D4, 0x00C82F22, 0x004E63D9,
+ 0x00D11CCE, 0x00575035, 0x005BC9C3, 0x00DD8538 };
+
+ u32bit tmp = crc;
+ while(length >= 16)
+ {
+ tmp = TABLE[((tmp >> 16) ^ input[ 0]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 1]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 2]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 3]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 4]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 5]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 6]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 7]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 8]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[ 9]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[10]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[11]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[12]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[13]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[14]) & 0xFF] ^ (tmp << 8);
+ tmp = TABLE[((tmp >> 16) ^ input[15]) & 0xFF] ^ (tmp << 8);
+ input += 16;
+ length -= 16;
+ }
+ for(u32bit j = 0; j != length; ++j)
+ tmp = TABLE[((tmp >> 16) ^ input[j]) & 0xFF] ^ (tmp << 8);
+ crc = tmp;
+ }
+
+/*
+* Finalize a CRC24 Checksum
+*/
+void CRC24::final_result(byte output[])
+ {
+ for(u32bit j = 0; j != 3; ++j)
+ output[j] = get_byte(j+1, crc);
+ clear();
+ }
+
+}
diff --git a/botan/src/checksum/crc24/crc24.h b/botan/src/checksum/crc24/crc24.h
new file mode 100644
index 0000000..bca4d0e
--- /dev/null
+++ b/botan/src/checksum/crc24/crc24.h
@@ -0,0 +1,34 @@
+/*
+* CRC24
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRC24_H__
+#define BOTAN_CRC24_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* CRC24
+*/
+class BOTAN_DLL CRC24 : public HashFunction
+ {
+ public:
+ void clear() throw() { crc = 0xB704CE; }
+ std::string name() const { return "CRC24"; }
+ HashFunction* clone() const { return new CRC24; }
+ CRC24() : HashFunction(3) { clear(); }
+ ~CRC24() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ u32bit crc;
+ };
+
+}
+
+#endif
diff --git a/botan/src/checksum/crc24/info.txt b/botan/src/checksum/crc24/info.txt
new file mode 100644
index 0000000..33b86a9
--- /dev/null
+++ b/botan/src/checksum/crc24/info.txt
@@ -0,0 +1,14 @@
+realname "CRC-24"
+
+define CRC24
+
+load_on auto
+
+<add>
+crc24.cpp
+crc24.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/checksum/crc32/crc32.cpp b/botan/src/checksum/crc32/crc32.cpp
new file mode 100644
index 0000000..4246209
--- /dev/null
+++ b/botan/src/checksum/crc32/crc32.cpp
@@ -0,0 +1,102 @@
+/*
+* CRC32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/crc32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Update a CRC32 Checksum
+*/
+void CRC32::add_data(const byte input[], u32bit length)
+ {
+ const u32bit TABLE[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
+ 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+ 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+ 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
+ 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+ 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
+ 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
+ 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+ 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
+ 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
+ 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+ 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
+ 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+ 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+ 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
+ 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
+ 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
+ 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
+ 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+ 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+ 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
+ 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };
+
+ u32bit tmp = crc;
+ while(length >= 16)
+ {
+ tmp = TABLE[(tmp ^ input[ 0]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 1]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 2]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 3]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 4]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 5]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 6]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 7]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 8]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[ 9]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[10]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[11]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[12]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[13]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[14]) & 0xFF] ^ (tmp >> 8);
+ tmp = TABLE[(tmp ^ input[15]) & 0xFF] ^ (tmp >> 8);
+ input += 16;
+ length -= 16;
+ }
+
+ for(u32bit j = 0; j != length; ++j)
+ tmp = TABLE[(tmp ^ input[j]) & 0xFF] ^ (tmp >> 8);
+
+ crc = tmp;
+ }
+
+/*
+* Finalize a CRC32 Checksum
+*/
+void CRC32::final_result(byte output[])
+ {
+ crc ^= 0xFFFFFFFF;
+ store_be(crc, output);
+ clear();
+ }
+
+}
diff --git a/botan/src/checksum/crc32/crc32.h b/botan/src/checksum/crc32/crc32.h
new file mode 100644
index 0000000..390fb10
--- /dev/null
+++ b/botan/src/checksum/crc32/crc32.h
@@ -0,0 +1,34 @@
+/*
+* CRC32
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRC32_H__
+#define BOTAN_CRC32_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* CRC32
+*/
+class BOTAN_DLL CRC32 : public HashFunction
+ {
+ public:
+ void clear() throw() { crc = 0xFFFFFFFF; }
+ std::string name() const { return "CRC32"; }
+ HashFunction* clone() const { return new CRC32; }
+ CRC32() : HashFunction(4) { clear(); }
+ ~CRC32() { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ u32bit crc;
+ };
+
+}
+
+#endif
diff --git a/botan/src/checksum/crc32/info.txt b/botan/src/checksum/crc32/info.txt
new file mode 100644
index 0000000..15933b3
--- /dev/null
+++ b/botan/src/checksum/crc32/info.txt
@@ -0,0 +1,14 @@
+realname "CRC-32"
+
+define CRC32
+
+load_on auto
+
+<add>
+crc32.cpp
+crc32.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/cms/cms_algo.cpp b/botan/src/cms/cms_algo.cpp
new file mode 100644
index 0000000..748aa73
--- /dev/null
+++ b/botan/src/cms/cms_algo.cpp
@@ -0,0 +1,164 @@
+/*
+* CMS Algorithm Specific Code
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_enc.h>
+#include <botan/der_enc.h>
+#include <botan/sha160.h>
+#include <botan/cbc.h>
+#include <botan/filters.h>
+#include <botan/libstate.h>
+
+#if defined(BOTAN_HAS_RC2)
+ #include <botan/rc2.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/*
+* Wrap a key as specified in RFC 3217
+*/
+SecureVector<byte> do_rfc3217_wrap(RandomNumberGenerator& rng,
+ const std::string& cipher_name,
+ const SymmetricKey& kek,
+ const SecureVector<byte>& input)
+ {
+ class Flip_Bytes : public Filter
+ {
+ public:
+ void write(const byte data[], u32bit length)
+ {
+ buf.append(data, length);
+ }
+ void end_msg()
+ {
+ for(u32bit j = 0; j != buf.size(); j++)
+ send(buf[buf.size()-j-1]);
+ buf.destroy();
+ }
+ Flip_Bytes(const SecureVector<byte>& prefix) { buf.append(prefix); }
+ private:
+ SecureVector<byte> buf;
+ };
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* cipher = af.prototype_block_cipher(cipher_name);
+
+ if(!cipher || cipher->BLOCK_SIZE != 8)
+ throw Encoding_Error("do_rfc3217_wrap: Bad cipher: " + cipher_name);
+
+ Pipe icv(new Hash_Filter(new SHA_160, 8));
+ icv.process_msg(input);
+
+ InitializationVector iv(rng, 8);
+ InitializationVector fixed("4ADDA22C79E82105");
+
+ Pipe pipe(new CBC_Encryption(cipher->clone(), new Null_Padding, kek, iv),
+ new Flip_Bytes(iv.bits_of()),
+ new CBC_Encryption(cipher->clone(), new Null_Padding, kek, iv));
+
+ pipe.start_msg();
+ pipe.write(input);
+ pipe.write(icv.read_all());
+ pipe.end_msg();
+ return pipe.read_all();
+ }
+
+}
+
+/*
+* Wrap a CEK with a KEK
+*/
+SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
+ const std::string& cipher,
+ const SymmetricKey& cek,
+ const SymmetricKey& kek)
+ {
+#if defined(BOTAN_HAS_DES)
+ if(cipher == "TripleDES")
+ {
+ SymmetricKey cek_parity = cek;
+ cek_parity.set_odd_parity();
+ return do_rfc3217_wrap(rng, cipher, kek, cek_parity.bits_of());
+ }
+#endif
+
+#if defined(BOTAN_HAS_RC2) || defined(BOTAN_HAS_CAST)
+ if(cipher == "RC2" || cipher == "CAST-128")
+ {
+ if(kek.length() != 16)
+ throw Encoding_Error("CMS: 128-bit KEKs must be used with " + cipher);
+
+ SecureVector<byte> lcekpad;
+ lcekpad.append((byte)cek.length());
+ lcekpad.append(cek.bits_of());
+ while(lcekpad.size() % 8)
+ lcekpad.append(rng.next_byte());
+ return do_rfc3217_wrap(rng, cipher, kek, lcekpad);
+ }
+#endif
+
+ throw Invalid_Argument("CMS_Encoder::wrap: Unknown cipher " + cipher);
+ }
+
+/*
+* Encode the parameters for an encryption algo
+*/
+SecureVector<byte> CMS_Encoder::encode_params(const std::string& cipher,
+ const SymmetricKey& key,
+ const InitializationVector& iv)
+ {
+ DER_Encoder encoder;
+
+#if defined(BOTAN_HAS_RC2)
+ if(cipher == "RC2")
+ {
+ encoder.start_cons(SEQUENCE).
+ encode((u32bit)RC2::EKB_code(8*key.length())).
+ encode(iv.bits_of(), OCTET_STRING).
+ end_cons();
+ return encoder.get_contents();
+ }
+#endif
+
+ if(cipher == "CAST-128")
+ {
+ encoder.start_cons(SEQUENCE).
+ encode(iv.bits_of(), OCTET_STRING).
+ encode(8*key.length()).
+ end_cons();
+ }
+ else
+ encoder.encode(iv.bits_of(), OCTET_STRING);
+
+ return encoder.get_contents();
+ }
+
+/*
+* Generate a CEK or KEK for the cipher
+*/
+SymmetricKey CMS_Encoder::setup_key(RandomNumberGenerator& rng,
+ const std::string& cipher)
+ {
+ u32bit keysize = 0;
+
+ if(cipher == "TripleDES") keysize = 24;
+ if(cipher == "RC2") keysize = 16;
+ if(cipher == "CAST-128") keysize = 16;
+
+ if(keysize == 0)
+ throw Invalid_Argument("CMS: Cannot encrypt with cipher " + cipher);
+
+ SymmetricKey key(rng, keysize);
+ if(cipher == "DES" || cipher == "TripleDES")
+ key.set_odd_parity();
+ return key;
+ }
+
+}
diff --git a/botan/src/cms/cms_comp.cpp b/botan/src/cms/cms_comp.cpp
new file mode 100644
index 0000000..b11cf90
--- /dev/null
+++ b/botan/src/cms/cms_comp.cpp
@@ -0,0 +1,107 @@
+/*
+* CMS Compression
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_enc.h>
+#include <botan/cms_dec.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+#include <botan/pipe.h>
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ #include <botan/zlib.h>
+#endif
+
+namespace Botan {
+
+/*
+* Compress a message
+*/
+void CMS_Encoder::compress(const std::string& algo)
+ {
+ if(!CMS_Encoder::can_compress_with(algo))
+ throw Invalid_Argument("CMS_Encoder: Cannot compress with " + algo);
+
+ Filter* compressor = 0;
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ if(algo == "Zlib") compressor = new Zlib_Compression;
+#endif
+
+ if(compressor == 0)
+ throw Internal_Error("CMS: Couldn't get ahold of a compressor");
+
+ Pipe pipe(compressor);
+ pipe.process_msg(data);
+ SecureVector<byte> compressed = pipe.read_all();
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE).
+ encode((u32bit)0).
+ encode(AlgorithmIdentifier("Compression." + algo,
+ MemoryVector<byte>())).
+ raw_bytes(make_econtent(compressed, type)).
+ end_cons();
+
+ add_layer("CMS.CompressedData", encoder);
+ }
+
+/*
+* See if the named compression algo is available
+*/
+bool CMS_Encoder::can_compress_with(const std::string& algo)
+ {
+ if(algo == "")
+ throw Invalid_Algorithm_Name("Empty string to can_compress_with");
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ if(algo == "Zlib")
+ return true;
+#endif
+
+ return false;
+ }
+
+/*
+* Decompress a message
+*/
+void CMS_Decoder::decompress(BER_Decoder& decoder)
+ {
+ u32bit version;
+ AlgorithmIdentifier comp_algo;
+
+ BER_Decoder comp_info = decoder.start_cons(SEQUENCE);
+
+ comp_info.decode(version);
+ if(version != 0)
+ throw Decoding_Error("CMS: Unknown version for CompressedData");
+
+ comp_info.decode(comp_algo);
+ read_econtent(comp_info);
+ comp_info.end_cons();
+
+ Filter* decompressor = 0;
+
+ info = comp_algo.oid.as_string();
+
+#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
+ if(comp_algo.oid == OIDS::lookup("Compression.Zlib"))
+ {
+ decompressor = new Zlib_Decompression;
+ info = "Zlib";
+ }
+#endif
+
+ if(!decompressor)
+ status = FAILURE;
+
+ Pipe pipe(decompressor);
+ pipe.process_msg(data);
+ data = pipe.read_all();
+ }
+
+}
diff --git a/botan/src/cms/cms_dalg.cpp b/botan/src/cms/cms_dalg.cpp
new file mode 100644
index 0000000..7ed793f
--- /dev/null
+++ b/botan/src/cms/cms_dalg.cpp
@@ -0,0 +1,276 @@
+/*
+* CMS Decoding Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_dec.h>
+#include <botan/x509find.h>
+#include <botan/ber_dec.h>
+#include <botan/oids.h>
+#include <botan/hash.h>
+#include <botan/look_pk.h>
+#include <botan/bigint.h>
+#include <botan/libstate.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Compute the hash of some content
+*/
+SecureVector<byte> hash_of(const SecureVector<byte>& content,
+ const AlgorithmIdentifier& hash_algo,
+ std::string& hash_name)
+ {
+ hash_name = OIDS::lookup(hash_algo.oid);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
+ return hash_fn->process(content);
+ }
+
+/*
+* Find a cert based on SignerIdentifier
+*/
+std::vector<X509_Certificate> get_cert(BER_Decoder& signer_info,
+ X509_Store& store)
+ {
+ BER_Object id = signer_info.get_next_object();
+
+ std::vector<X509_Certificate> found;
+
+ if(id.type_tag == SEQUENCE && id.class_tag == CONSTRUCTED)
+ {
+ X509_DN issuer;
+ BigInt serial;
+ BER_Decoder iands(id.value);
+ iands.decode(issuer);
+ iands.decode(serial);
+
+ found = store.get_certs(IandS_Match(issuer, BigInt::encode(serial)));
+ }
+ else if(id.type_tag == 0 && id.class_tag == CONSTRUCTED)
+ found = store.get_certs(SKID_Match(id.value));
+ else
+ throw Decoding_Error("CMS: Unknown tag for cert identifier");
+
+ // verify cert if found
+
+ if(found.size() > 1)
+ throw Internal_Error("CMS: Found more than one match in get_cert");
+ return found;
+ }
+
+/*
+* Read OriginatorInfo
+*/
+void read_orig_info(BER_Decoder& info, X509_Store& store)
+ {
+ BER_Object next = info.get_next_object();
+
+ if(next.type_tag == 0 &&
+ next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ DataSource_Memory certs(next.value);
+ while(!certs.end_of_data())
+ {
+ // FIXME: can be attribute certs too
+ // FIXME: DoS?
+ X509_Certificate cert(certs);
+ store.add_cert(cert);
+ }
+ next = info.get_next_object();
+ }
+ if(next.type_tag == 1 &&
+ next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ {
+ DataSource_Memory crls(next.value);
+ while(!crls.end_of_data())
+ {
+ // FIXME: DoS?
+ X509_CRL crl(crls);
+ store.add_crl(crl);
+ }
+ next = info.get_next_object();
+ }
+ info.push_back(next);
+ }
+
+/*
+* Decode any Attributes, and check type
+*/
+SecureVector<byte> decode_attributes(BER_Decoder& ber, const OID& type,
+ bool& bad_attributes)
+ {
+ BER_Object obj = ber.get_next_object();
+ SecureVector<byte> digest;
+
+ bool got_digest = false;
+ bool got_content_type = false;
+
+ if(obj.type_tag == 0 &&
+ obj.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
+ ber.push_back(obj);
+ else
+ {
+ BER_Decoder attributes(obj.value);
+ while(attributes.more_items())
+ {
+ Attribute attr;
+ attributes.decode(attr);
+ BER_Decoder attr_value(attr.parameters);
+
+ if(attr.oid == OIDS::lookup("PKCS9.MessageDigest"))
+ {
+ got_digest = true;
+ attr_value.decode(digest, OCTET_STRING);
+ }
+ else if(attr.oid == OIDS::lookup("PKCS9.ContentType"))
+ {
+ got_content_type = true;
+ OID inner_type;
+ attr_value.decode(inner_type);
+ if(inner_type != type)
+ bad_attributes = true;
+ }
+ else
+ throw Decoding_Error("Unknown/unhandled CMS attribute found: " +
+ OIDS::lookup(attr.oid));
+ }
+
+ if(!got_digest || !got_content_type)
+ bad_attributes = true;
+ }
+
+ return digest;
+ }
+
+}
+
+/*
+* Decode this layer of CMS encoding
+*/
+void CMS_Decoder::decode_layer()
+ {
+ try {
+ if(status == FAILURE)
+ throw Invalid_State("CMS: Decoder is in FAILURE state");
+
+ status = GOOD;
+ info = "";
+
+ type = next_type;
+
+ if(type == OIDS::lookup("CMS.DataContent"))
+ return;
+
+ BER_Decoder decoder(data);
+ if(type == OIDS::lookup("CMS.CompressedData"))
+ decompress(decoder);
+ else if(type == OIDS::lookup("CMS.DigestedData"))
+ {
+ u32bit version;
+ AlgorithmIdentifier hash_algo;
+ SecureVector<byte> digest;
+
+ BER_Decoder hash_info = decoder.start_cons(SEQUENCE);
+
+ hash_info.decode(version);
+ if(version != 0 && version != 2)
+ throw Decoding_Error("CMS: Unknown version for DigestedData");
+
+ hash_info.decode(hash_algo);
+ read_econtent(hash_info);
+ hash_info.decode(digest, OCTET_STRING);
+ hash_info.end_cons();
+
+ if(digest != hash_of(data, hash_algo, info))
+ status = BAD;
+ }
+ else if(type == OIDS::lookup("CMS.SignedData"))
+ {
+#if 1
+ throw Exception("FIXME: not implemented");
+#else
+ u32bit version;
+
+ BER_Decoder sig_info = BER::get_subsequence(decoder);
+ BER::decode(sig_info, version);
+ if(version != 1 && version != 3)
+ throw Decoding_Error("CMS: Unknown version for SignedData");
+ BER::get_subset(sig_info); // hash algos (do something with these?)
+ read_econtent(sig_info);
+ read_orig_info(sig_info, store);
+
+ BER_Decoder signer_infos = BER::get_subset(sig_info);
+ while(signer_infos.more_items())
+ {
+ AlgorithmIdentifier sig_algo, hash_algo;
+ SecureVector<byte> signature, digest;
+ u32bit version;
+
+ BER_Decoder signer_info = BER::get_subsequence(signer_infos);
+ BER::decode(signer_info, version);
+ if(version != 1 && version != 3)
+ throw Decoding_Error("CMS: Unknown version for SignerInfo");
+
+ std::vector<X509_Certificate> certs = get_cert(signer_info, store);
+ if(certs.size() == 0) { status = NO_KEY; continue; }
+
+ BER::decode(signer_info, hash_algo);
+ bool bad_attr = false;
+ digest = decode_attributes(signer_info, next_type, bad_attr);
+ if(bad_attr) { status = BAD; continue; }
+ BER::decode(signer_info, sig_algo);
+ BER::decode(signer_info, signature, OCTET_STRING);
+ // unsigned attributes
+ signer_info.verify_end();
+
+ if(digest.has_items())
+ {
+ std::string hash;
+ if(digest != hash_of(data, hash_algo, hash))
+ {
+ status = BAD;
+ continue;
+ }
+ status = check_sig(signed_attr, sig_algo, signature, certs[0]);
+ }
+ else
+ status = check_sig(data, sig_algo, signature, certs[0]);
+
+ if(status == BAD)
+ continue;
+
+ // fix this (gets only last signer, for one thing)
+ // maybe some way for the user to get all certs that signed the
+ // message? that would be useful
+ info = "CN=" + cert.subject_info("CommonName") +
+ ",O=" + cert.subject_info("Organization") +
+ ",OU=" + cert.subject_info("Organizational Unit");
+ }
+#endif
+ }
+ else if(type == OIDS::lookup("CMS.EnvelopedData"))
+ {
+ throw Exception("FIXME: not implemented");
+ }
+ else if(type == OIDS::lookup("CMS.AuthenticatedData"))
+ {
+ throw Exception("FIXME: not implemented");
+ }
+ else
+ throw Decoding_Error("CMS: Unknown content ID " + type.as_string());
+ }
+ catch(std::exception)
+ {
+ status = FAILURE;
+ }
+ }
+
+}
diff --git a/botan/src/cms/cms_dec.cpp b/botan/src/cms/cms_dec.cpp
new file mode 100644
index 0000000..222399f
--- /dev/null
+++ b/botan/src/cms/cms_dec.cpp
@@ -0,0 +1,127 @@
+/*
+* CMS Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_dec.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_int.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+/*
+* CMS_Decoder Constructor
+*/
+CMS_Decoder::CMS_Decoder(DataSource& in, const X509_Store& x509store,
+ User_Interface& ui_ref, PKCS8_PrivateKey* key) :
+ ui(ui_ref), store(x509store)
+ {
+ status = GOOD;
+
+ add_key(key);
+
+ if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
+ initial_read(in);
+ else
+ {
+ DataSource_Memory ber(PEM_Code::decode_check_label(in, "PKCS7"));
+ initial_read(ber);
+ }
+ }
+
+/*
+* Read the outermost ContentInfo
+*/
+void CMS_Decoder::initial_read(DataSource&)
+ {
+ // FIXME...
+
+ /*
+ BER_Decoder decoder(in);
+ BER_Decoder content_info = decoder.start_cons(SEQUENCE);
+
+ content_info.decode(next_type);
+
+
+ BER_Decoder content_type = BER::get_subsequence(content_info, ASN1_Tag(0));
+ data = content_type.get_remaining();
+ */
+
+ decode_layer();
+ }
+
+/*
+* Add another private key to use
+*/
+void CMS_Decoder::add_key(PKCS8_PrivateKey* key)
+ {
+ if(!key)
+ return;
+
+#if 0
+ for(u32bit j = 0; j != keys.size(); j++)
+ if(keys[j]->key_id() == key->key_id())
+ return;
+#endif
+
+ keys.push_back(key);
+ }
+
+/*
+* Return the status information
+*/
+CMS_Decoder::Status CMS_Decoder::layer_status() const
+ {
+ return status;
+ }
+
+/*
+* Return the final data content
+*/
+std::string CMS_Decoder::get_data() const
+ {
+ if(layer_type() != DATA)
+ throw Invalid_State("CMS: Cannot retrieve data from non-DATA layer");
+ return std::string((const char*)data.begin(), data.size());
+ }
+
+/*
+* Return the content type of this layer
+*/
+CMS_Decoder::Content_Type CMS_Decoder::layer_type() const
+ {
+ if(type == OIDS::lookup("CMS.DataContent")) return DATA;
+ if(type == OIDS::lookup("CMS.EnvelopedData")) return ENVELOPED;
+ if(type == OIDS::lookup("CMS.CompressedData")) return COMPRESSED;
+ if(type == OIDS::lookup("CMS.SignedData")) return SIGNED;
+ if(type == OIDS::lookup("CMS.AuthenticatedData")) return AUTHENTICATED;
+ if(type == OIDS::lookup("CMS.DigestedData")) return DIGESTED;
+ return UNKNOWN;
+ }
+
+/*
+* Return some information about this layer
+*/
+std::string CMS_Decoder::layer_info() const
+ {
+ return info;
+ }
+
+/*
+* Return some information about this layer
+*/
+void CMS_Decoder::read_econtent(BER_Decoder& decoder)
+ {
+ BER_Decoder econtent_info = decoder.start_cons(SEQUENCE);
+ econtent_info.decode(next_type);
+
+ // FIXME
+ //BER_Decoder econtent = BER::get_subsequence(econtent_info, ASN1_Tag(0));
+ //econtent.decode(data, OCTET_STRING);
+ }
+
+}
diff --git a/botan/src/cms/cms_dec.h b/botan/src/cms/cms_dec.h
new file mode 100644
index 0000000..75b61c9
--- /dev/null
+++ b/botan/src/cms/cms_dec.h
@@ -0,0 +1,65 @@
+/*
+* CMS Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMS_DECODER_H__
+#define BOTAN_CMS_DECODER_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509stor.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/ui.h>
+
+namespace Botan {
+
+/*
+* CMS Decoding Operation
+*/
+class BOTAN_DLL CMS_Decoder
+ {
+ public:
+ enum Status { GOOD, BAD, NO_KEY, FAILURE };
+
+ enum Content_Type { DATA, UNKNOWN, COMPRESSED, ENVELOPED, SIGNED,
+ AUTHENTICATED, DIGESTED };
+
+ Status layer_status() const;
+ Content_Type layer_type() const;
+ std::string layer_info() const;
+ std::string layer_algo() const;
+ std::string get_data() const;
+ std::vector<X509_Certificate> get_certs() const;
+ std::vector<X509_CRL> get_crls() const;
+
+ void next_layer() { decode_layer(); }
+
+ void add_key(PKCS8_PrivateKey*);
+
+ CMS_Decoder(DataSource&, const X509_Store&, User_Interface&,
+ PKCS8_PrivateKey* = 0);
+ private:
+ std::string get_passphrase(const std::string&);
+ void read_econtent(BER_Decoder&);
+ void initial_read(DataSource&);
+ void decode_layer();
+ void decompress(BER_Decoder&);
+
+ User_Interface& ui;
+
+ X509_Store store;
+ std::vector<std::string> passphrases;
+ std::vector<PKCS8_PrivateKey*> keys;
+
+ OID type, next_type;
+ SecureVector<byte> data;
+ Status status;
+ std::string info;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cms/cms_ealg.cpp b/botan/src/cms/cms_ealg.cpp
new file mode 100644
index 0000000..2970e8e
--- /dev/null
+++ b/botan/src/cms/cms_ealg.cpp
@@ -0,0 +1,401 @@
+/*
+* CMS Encoding Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_enc.h>
+#include <botan/der_enc.h>
+#include <botan/x509find.h>
+#include <botan/bigint.h>
+#include <botan/oids.h>
+#include <botan/cbc.h>
+#include <botan/hash.h>
+#include <botan/look_pk.h>
+#include <botan/libstate.h>
+#include <botan/pipe.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Choose an algorithm
+*/
+std::string choose_algo(const std::string& user_algo,
+ const std::string& default_algo)
+ {
+ if(user_algo == "")
+ return global_state().deref_alias(default_algo);
+ return global_state().deref_alias(user_algo);
+ }
+
+/*
+* Encode a SignerIdentifier/RecipientIdentifier
+*/
+DER_Encoder& encode_si(DER_Encoder& der, const X509_Certificate& cert,
+ bool use_skid_encoding = false)
+ {
+ if(cert.subject_key_id().size() && use_skid_encoding)
+ der.encode(cert.subject_key_id(), OCTET_STRING, ASN1_Tag(0));
+ else
+ {
+ der.start_cons(SEQUENCE).
+ encode(cert.issuer_dn()).
+ encode(BigInt::decode(cert.serial_number())).
+ end_cons();
+ }
+
+ return der;
+ }
+
+/*
+* Compute the hash of some content
+*/
+SecureVector<byte> hash_of(const SecureVector<byte>& content,
+ const std::string& hash_name)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ std::auto_ptr<HashFunction> hash_fn(af.make_hash_function(hash_name));
+ return hash_fn->process(content);
+ }
+
+/*
+* Encode Attributes containing info on content
+*/
+SecureVector<byte> encode_attr(const SecureVector<byte>& data,
+ const std::string& type,
+ const std::string& hash)
+ {
+ SecureVector<byte> digest = hash_of(data, hash);
+
+ DER_Encoder encoder;
+ encoder.encode(OIDS::lookup(type));
+ Attribute content_type("PKCS9.ContentType", encoder.get_contents());
+
+ encoder.encode(digest, OCTET_STRING);
+ Attribute message_digest("PKCS9.MessageDigest", encoder.get_contents());
+
+ encoder.start_cons(SET)
+ .encode(content_type)
+ .encode(message_digest)
+ .end_cons();
+
+ return encoder.get_contents();
+ }
+
+}
+
+/*
+* Encrypt a message
+*/
+void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
+ const X509_Certificate& to,
+ const std::string user_cipher)
+ {
+ const std::string cipher = choose_algo(user_cipher, "TripleDES");
+
+ std::auto_ptr<X509_PublicKey> key(to.subject_public_key());
+ const std::string algo = key->algo_name();
+
+ Key_Constraints constraints = to.constraints();
+
+ if(algo == "RSA")
+ {
+ if(constraints != NO_CONSTRAINTS && !(constraints & KEY_ENCIPHERMENT))
+ throw Invalid_Argument("CMS: Constraints not set for encryption");
+
+ PK_Encrypting_Key* enc_key = dynamic_cast<PK_Encrypting_Key*>(key.get());
+ if(enc_key == 0)
+ throw Internal_Error("CMS_Encoder::encrypt: " + algo +
+ " can't encrypt");
+
+ encrypt_ktri(rng, to, enc_key, cipher);
+ }
+ else if(algo == "DH")
+ {
+ if(constraints != NO_CONSTRAINTS && !(constraints & KEY_AGREEMENT))
+ throw Invalid_Argument("CMS: Constraints not set for key agreement");
+
+ encrypt_kari(rng, to, key.get(), cipher);
+ }
+ else
+ throw Invalid_Argument("Unknown CMS PK encryption algorithm " + algo);
+ }
+
+/*
+* Encrypt a message with a key transport algo
+*/
+void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng,
+ const X509_Certificate& to,
+ PK_Encrypting_Key* pub_key,
+ const std::string& cipher)
+ {
+ const std::string padding = "EME-PKCS1-v1_5";
+ const std::string pk_algo = pub_key->algo_name();
+ std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*pub_key, padding));
+
+ SymmetricKey cek = setup_key(rng, cipher);
+
+ AlgorithmIdentifier alg_id(OIDS::lookup(pk_algo + '/' + padding),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+
+ DER_Encoder encoder;
+
+ encoder.start_cons(SEQUENCE)
+ .encode((u32bit)0)
+ .start_cons(SET)
+ .start_cons(SEQUENCE)
+ .encode((u32bit)0);
+ encode_si(encoder, to)
+ .encode(alg_id)
+ .encode(enc->encrypt(cek.bits_of(), rng), OCTET_STRING)
+ .end_cons()
+ .end_cons()
+ .raw_bytes(do_encrypt(rng, cek, cipher))
+ .end_cons();
+
+ add_layer("CMS.EnvelopedData", encoder);
+ }
+
+/*
+* Encrypt a message with a key agreement algo
+*/
+void CMS_Encoder::encrypt_kari(RandomNumberGenerator&,
+ const X509_Certificate&,
+ X509_PublicKey*,
+ const std::string&)
+ {
+ throw Exception("FIXME: unimplemented");
+
+#if 0
+ SymmetricKey cek = setup_key(rng, cipher);
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE);
+ encoder.encode(2);
+ encoder.start_cons(SET);
+ encoder.start_sequence(ASN1_Tag(1));
+ encoder.encode(3);
+ encode_si(encoder, to);
+ encoder.encode(AlgorithmIdentifier(pk_algo + "/" + padding));
+ encoder.encode(encrypted_cek, OCTET_STRING);
+ encoder.end_cons();
+ encoder.end_cons();
+ encoder.raw_bytes(do_encrypt(rng, cek, cipher));
+ encoder.end_cons();
+
+ add_layer("CMS.EnvelopedData", encoder);
+#endif
+ }
+
+/*
+* Encrypt a message with a shared key
+*/
+void CMS_Encoder::encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey& kek,
+ const std::string& user_cipher)
+ {
+ throw Exception("FIXME: untested");
+
+ const std::string cipher = choose_algo(user_cipher, "TripleDES");
+ SymmetricKey cek = setup_key(rng, cipher);
+
+ SecureVector<byte> kek_id; // FIXME: ?
+
+ DER_Encoder encoder;
+
+ encoder.start_cons(SEQUENCE)
+ .encode((u32bit)2)
+ .start_explicit(ASN1_Tag(2))
+ .encode((u32bit)4)
+ .start_cons(SEQUENCE)
+ .encode(kek_id, OCTET_STRING)
+ .end_cons()
+ .encode(AlgorithmIdentifier(OIDS::lookup("KeyWrap." + cipher),
+ AlgorithmIdentifier::USE_NULL_PARAM))
+ .encode(wrap_key(rng, cipher, cek, kek), OCTET_STRING)
+ .end_cons()
+ .raw_bytes(do_encrypt(rng, cek, cipher))
+ .end_cons();
+
+ add_layer("CMS.EnvelopedData", encoder);
+ }
+
+/*
+* Encrypt a message with a passphrase
+*/
+void CMS_Encoder::encrypt(RandomNumberGenerator&,
+ const std::string&,
+ const std::string& user_cipher)
+ {
+ const std::string cipher = choose_algo(user_cipher, "TripleDES");
+ throw Exception("FIXME: unimplemented");
+ /*
+ SymmetricKey cek = setup_key(key);
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE);
+ encoder.encode(0);
+ encoder.raw_bytes(do_encrypt(rng, cek, cipher));
+ encoder.end_cons();
+
+ add_layer("CMS.EnvelopedData", encoder);
+ */
+ }
+
+/*
+* Encrypt the content with the chosen key/cipher
+*/
+SecureVector<byte> CMS_Encoder::do_encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey& key,
+ const std::string& cipher_name)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* cipher = af.prototype_block_cipher(cipher_name);
+
+ if(!cipher)
+ throw Invalid_Argument("CMS: Can't encrypt with non-existent cipher " + cipher_name);
+
+ if(!OIDS::have_oid(cipher->name() + "/CBC"))
+ throw Encoding_Error("CMS: No OID assigned for " + cipher_name + "/CBC");
+
+ InitializationVector iv(rng, cipher->BLOCK_SIZE);
+
+ AlgorithmIdentifier content_cipher;
+ content_cipher.oid = OIDS::lookup(cipher->name() + "/CBC");
+ content_cipher.parameters = encode_params(cipher->name(), key, iv);
+
+ Pipe pipe(new CBC_Encryption(cipher->clone(), new PKCS7_Padding, key, iv));
+
+ pipe.process_msg(data);
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE);
+ encoder.encode(OIDS::lookup(type));
+ encoder.encode(content_cipher);
+ encoder.encode(pipe.read_all(), OCTET_STRING, ASN1_Tag(0));
+ encoder.end_cons();
+
+ return encoder.get_contents();
+ }
+
+/*
+* Sign a message
+*/
+void CMS_Encoder::sign(const X509_Certificate& cert,
+ const PKCS8_PrivateKey& key,
+ RandomNumberGenerator& rng,
+ const std::vector<X509_Certificate>& chain,
+ const std::string& hash,
+ const std::string& pad_algo)
+ {
+ std::string padding = pad_algo + "(" + hash + ")";
+
+ // FIXME: Add new get_format() func to PK_Signing_Key, PK_Verifying_*_Key
+ Signature_Format format = IEEE_1363;
+
+ const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key);
+ std::auto_ptr<PK_Signer> signer(get_pk_signer(sig_key, padding, format));
+
+ AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+
+ SecureVector<byte> signed_attr = encode_attr(data, type, hash);
+ signer->update(signed_attr);
+ SecureVector<byte> signature = signer->signature(rng);
+ signed_attr[0] = 0xA0;
+
+ const u32bit SI_VERSION = cert.subject_key_id().size() ? 3 : 1;
+ const u32bit CMS_VERSION = (type != "CMS.DataContent") ? 3 : SI_VERSION;
+
+ DER_Encoder encoder;
+
+ encoder.start_cons(SEQUENCE)
+ .encode(CMS_VERSION)
+ .start_cons(SET)
+ .encode(AlgorithmIdentifier(OIDS::lookup(hash),
+ AlgorithmIdentifier::USE_NULL_PARAM))
+ .end_cons()
+ .raw_bytes(make_econtent(data, type));
+
+ encoder.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC);
+ for(u32bit j = 0; j != chain.size(); j++)
+ encoder.raw_bytes(chain[j].BER_encode());
+ encoder.raw_bytes(cert.BER_encode()).end_cons();
+
+ encoder.start_cons(SET)
+ .start_cons(SEQUENCE)
+ .encode(SI_VERSION);
+ encode_si(encoder, cert, ((SI_VERSION == 3) ? true : false))
+ .encode(
+ AlgorithmIdentifier(OIDS::lookup(hash),
+ AlgorithmIdentifier::USE_NULL_PARAM)
+ )
+ .raw_bytes(signed_attr)
+ .encode(sig_algo)
+ .encode(signature, OCTET_STRING)
+ .end_cons()
+ .end_cons()
+ .end_cons();
+
+ add_layer("CMS.SignedData", encoder);
+ }
+
+/*
+* Digest a message
+*/
+void CMS_Encoder::digest(const std::string& user_hash)
+ {
+ const std::string hash = choose_algo(user_hash, "SHA-1");
+ if(!OIDS::have_oid(hash))
+ throw Encoding_Error("CMS: No OID assigned for " + hash);
+
+ const u32bit VERSION = (type != "CMS.DataContent") ? 2 : 0;
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE)
+ .encode(VERSION)
+ .encode(AlgorithmIdentifier(OIDS::lookup(hash),
+ AlgorithmIdentifier::USE_NULL_PARAM))
+ .raw_bytes(make_econtent(data, type))
+ .encode(hash_of(data, hash), OCTET_STRING)
+ .end_cons();
+
+ add_layer("CMS.DigestedData", encoder);
+ }
+
+/*
+* MAC a message with an encrypted key
+*/
+void CMS_Encoder::authenticate(const X509_Certificate&,
+ const std::string& mac_algo)
+ {
+ const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
+ throw Exception("FIXME: unimplemented");
+ }
+
+/*
+* MAC a message with a shared key
+*/
+void CMS_Encoder::authenticate(const SymmetricKey&,
+ const std::string& mac_algo)
+ {
+ const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
+ throw Exception("FIXME: unimplemented");
+ }
+
+/*
+* MAC a message with a passphrase
+*/
+void CMS_Encoder::authenticate(const std::string&,
+ const std::string& mac_algo)
+ {
+ const std::string mac = choose_algo(mac_algo, "HMAC(SHA-1)");
+ throw Exception("FIXME: unimplemented");
+ }
+
+}
diff --git a/botan/src/cms/cms_enc.cpp b/botan/src/cms/cms_enc.cpp
new file mode 100644
index 0000000..2413676
--- /dev/null
+++ b/botan/src/cms/cms_enc.cpp
@@ -0,0 +1,86 @@
+/*
+* CMS Encoding Base
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cms_enc.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+/*
+* Setup the intitial layer of CMS data
+*/
+void CMS_Encoder::set_data(const byte buf[], u32bit length)
+ {
+ if(data.has_items())
+ throw Invalid_State("Cannot call CMS_Encoder::set_data here");
+
+ data.set(buf, length);
+ type = "CMS.DataContent";
+ }
+
+/*
+* Setup the intitial layer of CMS data
+*/
+void CMS_Encoder::set_data(const std::string& str)
+ {
+ set_data((const byte*)str.c_str(), str.length());
+ }
+
+/*
+* Finalize and return the CMS encoded data
+*/
+SecureVector<byte> CMS_Encoder::get_contents()
+ {
+ DER_Encoder encoder;
+
+ encoder.start_cons(SEQUENCE).
+ encode(OIDS::lookup(type)).
+ start_explicit(0).
+ raw_bytes(data).
+ end_explicit().
+ end_cons();
+
+ data.clear();
+
+ return encoder.get_contents();
+ }
+
+/*
+* Add a new layer of encapsulation
+*/
+void CMS_Encoder::add_layer(const std::string& oid, DER_Encoder& new_layer)
+ {
+ data = new_layer.get_contents();
+ type = oid;
+ }
+
+/*
+* Return the PEM-encoded data
+*/
+std::string CMS_Encoder::PEM_contents()
+ {
+ return PEM_Code::encode(get_contents(), "PKCS7");
+ }
+
+/*
+* Make an EncapsulatedContentInfo
+*/
+SecureVector<byte> CMS_Encoder::make_econtent(const SecureVector<byte>& data,
+ const std::string& type)
+ {
+ return DER_Encoder().start_cons(SEQUENCE).
+ encode(OIDS::lookup(type)).
+ start_explicit(0).
+ encode(data, OCTET_STRING).
+ end_explicit().
+ end_cons().
+ get_contents();
+ }
+
+}
diff --git a/botan/src/cms/cms_enc.h b/botan/src/cms/cms_enc.h
new file mode 100644
index 0000000..6fdd2b7
--- /dev/null
+++ b/botan/src/cms/cms_enc.h
@@ -0,0 +1,92 @@
+/*
+* CMS Encoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMS_ENCODER_H__
+#define BOTAN_CMS_ENCODER_H__
+
+#include <botan/x509cert.h>
+#include <botan/x509stor.h>
+#include <botan/pkcs8.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+/*
+* CMS Encoding Operation
+*/
+class BOTAN_DLL CMS_Encoder
+ {
+ public:
+
+ void encrypt(RandomNumberGenerator&,
+ const X509_Certificate&, const std::string = "");
+
+ void encrypt(RandomNumberGenerator& rng,
+ const std::string&, const std::string& = "");
+
+ void encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey&, const std::string& = "");
+
+ void authenticate(const X509_Certificate&, const std::string& = "");
+ void authenticate(const std::string&, const std::string& = "");
+ void authenticate(const SymmetricKey&, const std::string& = "");
+
+ void sign(const X509_Certificate& cert,
+ const PKCS8_PrivateKey& key,
+ RandomNumberGenerator& rng,
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::string& hash,
+ const std::string& padding);
+
+ void digest(const std::string& = "");
+
+ void compress(const std::string&);
+ static bool can_compress_with(const std::string&);
+
+ SecureVector<byte> get_contents();
+ std::string PEM_contents();
+
+ void set_data(const std::string&);
+ void set_data(const byte[], u32bit);
+
+ CMS_Encoder(const std::string& str) { set_data(str); }
+ CMS_Encoder(const byte buf[], u32bit length) { set_data(buf, length); }
+ private:
+ void add_layer(const std::string&, DER_Encoder&);
+
+ void encrypt_ktri(RandomNumberGenerator&,
+ const X509_Certificate&, PK_Encrypting_Key*,
+ const std::string&);
+ void encrypt_kari(RandomNumberGenerator&,
+ const X509_Certificate&, X509_PublicKey*,
+ const std::string&);
+
+ SecureVector<byte> do_encrypt(RandomNumberGenerator& rng,
+ const SymmetricKey&, const std::string&);
+
+ static SecureVector<byte> make_econtent(const SecureVector<byte>&,
+ const std::string&);
+
+ static SymmetricKey setup_key(RandomNumberGenerator& rng,
+ const std::string&);
+
+ static SecureVector<byte> wrap_key(RandomNumberGenerator& rng,
+ const std::string&,
+ const SymmetricKey&,
+ const SymmetricKey&);
+
+ static SecureVector<byte> encode_params(const std::string&,
+ const SymmetricKey&,
+ const InitializationVector&);
+
+ SecureVector<byte> data;
+ std::string type;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cms/info.txt b/botan/src/cms/info.txt
new file mode 100644
index 0000000..82c31b5
--- /dev/null
+++ b/botan/src/cms/info.txt
@@ -0,0 +1,31 @@
+realname "CMS"
+
+define CMS
+
+load_on auto
+
+<add>
+cms_algo.cpp
+cms_comp.cpp
+cms_dalg.cpp
+cms_dec.cpp
+cms_dec.h
+cms_ealg.cpp
+cms_enc.cpp
+cms_enc.h
+</add>
+
+<requires>
+asn1
+bigint
+cbc
+filters
+hash
+libstate
+oid_lookup
+pem
+pk_codecs
+sha1
+sym_algo
+x509
+</requires>
diff --git a/botan/src/codec/base64/b64_char.cpp b/botan/src/codec/base64/b64_char.cpp
new file mode 100644
index 0000000..e5722a0
--- /dev/null
+++ b/botan/src/codec/base64/b64_char.cpp
@@ -0,0 +1,47 @@
+/*
+* Base64 Codec Character Tables
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/base64.h>
+
+namespace Botan {
+
+/*
+* Base64 Encoder Lookup Table
+*/
+const byte Base64_Encoder::BIN_TO_BASE64[64] = {
+0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
+0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F };
+
+/*
+* Base64 Decoder Lookup Table
+*/
+const byte Base64_Decoder::BASE64_TO_BIN[256] = {
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, 0x34, 0x35, 0x36, 0x37,
+0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+}
diff --git a/botan/src/codec/base64/base64.cpp b/botan/src/codec/base64/base64.cpp
new file mode 100644
index 0000000..dfcc1ca
--- /dev/null
+++ b/botan/src/codec/base64/base64.cpp
@@ -0,0 +1,228 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/base64.h>
+#include <botan/charset.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Base64_Encoder Constructor
+*/
+Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) :
+ line_length(breaks ? length : 0), trailing_newline(t_n)
+ {
+ in.create(48);
+ out.create(4);
+
+ counter = position = 0;
+ }
+
+/*
+* Base64 Encoding Operation
+*/
+void Base64_Encoder::encode(const byte in[3], byte out[4])
+ {
+ out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)];
+ out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
+ out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
+ out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )];
+ }
+
+/*
+* Encode and send a block
+*/
+void Base64_Encoder::encode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j += 3)
+ {
+ encode(block + j, out);
+ do_output(out, 4);
+ }
+ }
+
+/*
+* Handle the output
+*/
+void Base64_Encoder::do_output(const byte input[], u32bit length)
+ {
+ if(line_length == 0)
+ send(input, length);
+ else
+ {
+ u32bit remaining = length, offset = 0;
+ while(remaining)
+ {
+ u32bit sent = std::min(line_length - counter, remaining);
+ send(input + offset, sent);
+ counter += sent;
+ remaining -= sent;
+ offset += sent;
+ if(counter == line_length)
+ {
+ send('\n');
+ counter = 0;
+ }
+ }
+ }
+ }
+
+/*
+* Convert some data into Base64
+*/
+void Base64_Encoder::write(const byte input[], u32bit length)
+ {
+ in.copy(position, input, length);
+ if(position + length >= in.size())
+ {
+ encode_and_send(in, in.size());
+ input += (in.size() - position);
+ length -= (in.size() - position);
+ while(length >= in.size())
+ {
+ encode_and_send(input, in.size());
+ input += in.size();
+ length -= in.size();
+ }
+ in.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Flush buffers
+*/
+void Base64_Encoder::end_msg()
+ {
+ u32bit start_of_last_block = 3 * (position / 3),
+ left_over = position % 3;
+ encode_and_send(in, start_of_last_block);
+
+ if(left_over)
+ {
+ SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over);
+
+ encode(remainder, out);
+
+ u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1;
+ while(empty_bits >= 8)
+ {
+ out[index--] = '=';
+ empty_bits -= 6;
+ }
+
+ do_output(out, 4);
+ }
+
+ if(trailing_newline || (counter && line_length))
+ send('\n');
+
+ counter = position = 0;
+ }
+
+/*
+* Base64_Decoder Constructor
+*/
+Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
+ {
+ in.create(48);
+ out.create(3);
+ position = 0;
+ }
+
+/*
+* Check if a character is a valid Base64 char
+*/
+bool Base64_Decoder::is_valid(byte in)
+ {
+ return (BASE64_TO_BIN[in] != 0x80);
+ }
+
+/*
+* Base64 Decoding Operation
+*/
+void Base64_Decoder::decode(const byte in[4], byte out[3])
+ {
+ out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4));
+ out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2));
+ out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]]));
+ }
+
+/*
+* Decode and send a block
+*/
+void Base64_Decoder::decode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; j += 4)
+ {
+ decode(block + j, out);
+ send(out, 3);
+ }
+ }
+
+/*
+* Handle processing an invalid character
+*/
+void Base64_Decoder::handle_bad_char(byte c)
+ {
+ if(c == '=' || checking == NONE)
+ return;
+
+ if((checking == IGNORE_WS) && Charset::is_space(c))
+ return;
+
+ throw Decoding_Error(
+ std::string("Base64_Decoder: Invalid base64 character '") +
+ static_cast<char>(c) + "'"
+ );
+ }
+
+/*
+* Convert some data from Base64
+*/
+void Base64_Decoder::write(const byte input[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ {
+ if(is_valid(input[j]))
+ in[position++] = input[j];
+ else
+ handle_bad_char(input[j]);
+
+ if(position == in.size())
+ {
+ decode_and_send(in, in.size());
+ position = 0;
+ }
+ }
+ }
+
+/*
+* Flush buffers
+*/
+void Base64_Decoder::end_msg()
+ {
+ if(position != 0)
+ {
+ u32bit start_of_last_block = 4 * (position / 4),
+ left_over = position % 4;
+ decode_and_send(in, start_of_last_block);
+
+ if(left_over)
+ {
+ SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over);
+ decode(remainder, out);
+ send(out, ((left_over == 1) ? (1) : (left_over - 1)));
+ }
+ }
+ position = 0;
+ }
+
+}
diff --git a/botan/src/codec/base64/base64.h b/botan/src/codec/base64/base64.h
new file mode 100644
index 0000000..aca02da
--- /dev/null
+++ b/botan/src/codec/base64/base64.h
@@ -0,0 +1,94 @@
+/*
+* Base64 Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASE64_H__
+#define BOTAN_BASE64_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a Base64 encoder.
+*/
+class BOTAN_DLL Base64_Encoder : public Filter
+ {
+ public:
+ static void encode(const byte in[3], byte out[4]);
+
+ /**
+ * Input a part of a message to the encoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param breaks whether to use line breaks in the Streamcipheroutput
+ * @param length the length of the lines of the output
+ * @param t_n whether to use a trailing newline
+ */
+ Base64_Encoder(bool breaks = false, u32bit length = 72,
+ bool t_n = false);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ void do_output(const byte[], u32bit);
+ static const byte BIN_TO_BASE64[64];
+
+ const u32bit line_length;
+ const bool trailing_newline;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This object represents a Base64 decoder.
+*/
+class BOTAN_DLL Base64_Decoder : public Filter
+ {
+ public:
+ static void decode(const byte input[4], byte output[3]);
+
+ static bool is_valid(byte);
+
+ /**
+ * Input a part of a message to the decoder.
+ * @param input the message to input as a byte array
+ * @param length the length of the byte array input
+ */
+ void write(const byte input[], u32bit length);
+
+ /**
+ * Inform the Encoder that the current message shall be closed.
+ */
+ void end_msg();
+
+ /**
+ * Create a base64 encoder.
+ * @param checking the type of checking that shall be performed by
+ * the decoder
+ */
+ Base64_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte BASE64_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/base64/info.txt b/botan/src/codec/base64/info.txt
new file mode 100644
index 0000000..d4ed809
--- /dev/null
+++ b/botan/src/codec/base64/info.txt
@@ -0,0 +1,15 @@
+realname "Base64 Codec"
+
+define BASE64_CODEC
+
+load_on auto
+
+<add>
+base64.cpp
+b64_char.cpp
+base64.h
+</add>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/bzip2/bzip2.cpp b/botan/src/codec/bzip2/bzip2.cpp
new file mode 100644
index 0000000..4cdca53
--- /dev/null
+++ b/botan/src/codec/bzip2/bzip2.cpp
@@ -0,0 +1,275 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bzip2.h>
+#include <botan/exceptn.h>
+
+#include <map>
+#include <cstring>
+#define BZ_NO_STDIO
+#include <bzlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Allocation Information for Bzip
+*/
+class Bzip_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Bzip_Alloc_Info() { alloc = Allocator::get(false); }
+ };
+
+/*
+* Allocation Function for Bzip
+*/
+void* bzip_malloc(void* info_ptr, int n, int size)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*
+* Allocation Function for Bzip
+*/
+void bzip_free(void* info_ptr, void* ptr)
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("bzip_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*
+* Wrapper Type for Bzip2 Stream
+*/
+class Bzip_Stream
+ {
+ public:
+ bz_stream stream;
+
+ Bzip_Stream()
+ {
+ std::memset(&stream, 0, sizeof(bz_stream));
+ stream.bzalloc = bzip_malloc;
+ stream.bzfree = bzip_free;
+ stream.opaque = new Bzip_Alloc_Info;
+ }
+ ~Bzip_Stream()
+ {
+ Bzip_Alloc_Info* info = static_cast<Bzip_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(bz_stream));
+ }
+ };
+
+/*
+* Bzip_Compression Constructor
+*/
+Bzip_Compression::Bzip_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ bz = 0;
+ }
+
+/*
+* Start Compressing with Bzip
+*/
+void Bzip_Compression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+ if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK)
+ throw Exception("Bzip_Compression: Memory allocation error");
+ }
+
+/*
+* Compress Input with Bzip
+*/
+void Bzip_Compression::write(const byte input[], u32bit length)
+ {
+ bz->stream.next_in = reinterpret_cast<char*>(const_cast<byte*>(input));
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ BZ2_bzCompress(&(bz->stream), BZ_RUN);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*
+* Finish Compressing with Bzip
+*/
+void Bzip_Compression::end_msg()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ clear();
+ }
+
+/*
+* Flush the Bzip Compressor
+*/
+void Bzip_Compression::flush()
+ {
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_RUN_OK)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH);
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+ }
+
+/*
+* Clean up Compression Context
+*/
+void Bzip_Compression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzCompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+/*
+* Bzip_Decompression Constructor
+*/
+Bzip_Decompression::Bzip_Decompression(bool s) :
+ small_mem(s), buffer(DEFAULT_BUFFERSIZE)
+ {
+ no_writes = true;
+ bz = 0;
+ }
+
+/*
+* Decompress Input with Bzip
+*/
+void Bzip_Decompression::write(const byte input_arr[], u32bit length)
+ {
+ if(length) no_writes = false;
+
+ char* input = reinterpret_cast<char*>(const_cast<byte*>(input_arr));
+
+ bz->stream.next_in = input;
+ bz->stream.avail_in = length;
+
+ while(bz->stream.avail_in != 0)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+
+ int rc = BZ2_bzDecompress(&(bz->stream));
+
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ if(rc == BZ_DATA_ERROR)
+ throw Decoding_Error("Bzip_Decompression: Data integrity error");
+ if(rc == BZ_DATA_ERROR_MAGIC)
+ throw Decoding_Error("Bzip_Decompression: Invalid input");
+ if(rc == BZ_MEM_ERROR)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+ throw Exception("Bzip_Decompression: Unknown decompress error");
+ }
+
+ send(buffer, buffer.size() - bz->stream.avail_out);
+
+ if(rc == BZ_STREAM_END)
+ {
+ u32bit read_from_block = length - bz->stream.avail_in;
+ start_msg();
+ bz->stream.next_in = input + read_from_block;
+ bz->stream.avail_in = length - read_from_block;
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*
+* Start Decompressing with Bzip
+*/
+void Bzip_Decompression::start_msg()
+ {
+ clear();
+ bz = new Bzip_Stream;
+
+ if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK)
+ throw Exception("Bzip_Decompression: Memory allocation error");
+
+ no_writes = true;
+ }
+
+/*
+* Finish Decompressing with Bzip
+*/
+void Bzip_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ bz->stream.next_in = 0;
+ bz->stream.avail_in = 0;
+
+ int rc = BZ_OK;
+ while(rc != BZ_STREAM_END)
+ {
+ bz->stream.next_out = reinterpret_cast<char*>(buffer.begin());
+ bz->stream.avail_out = buffer.size();
+ rc = BZ2_bzDecompress(&(bz->stream));
+
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ {
+ clear();
+ throw Exception("Bzip_Decompression: Error finalizing decompression");
+ }
+
+ send(buffer, buffer.size() - bz->stream.avail_out);
+ }
+
+ clear();
+ }
+
+/*
+* Clean up Decompression Context
+*/
+void Bzip_Decompression::clear()
+ {
+ if(!bz) return;
+ BZ2_bzDecompressEnd(&(bz->stream));
+ delete bz;
+ bz = 0;
+ }
+
+}
diff --git a/botan/src/codec/bzip2/bzip2.h b/botan/src/codec/bzip2/bzip2.h
new file mode 100644
index 0000000..f422635
--- /dev/null
+++ b/botan/src/codec/bzip2/bzip2.h
@@ -0,0 +1,61 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BZIP2_H__
+#define BOTAN_BZIP2_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* Bzip Compression Filter
+*/
+class BOTAN_DLL Bzip_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Bzip_Compression(u32bit = 9);
+ ~Bzip_Compression() { clear(); }
+ private:
+ void clear();
+
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ };
+
+/*
+* Bzip Decompression Filter
+*/
+class BOTAN_DLL Bzip_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Bzip_Decompression(bool = false);
+ ~Bzip_Decompression() { clear(); }
+ private:
+ void clear();
+
+ const bool small_mem;
+ SecureVector<byte> buffer;
+ class Bzip_Stream* bz;
+ bool no_writes;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/bzip2/info.txt b/botan/src/codec/bzip2/info.txt
new file mode 100644
index 0000000..1be84e4
--- /dev/null
+++ b/botan/src/codec/bzip2/info.txt
@@ -0,0 +1,21 @@
+# This module was written by Peter J. Jones
+
+realname "Bzip2 Compressor"
+
+define COMPRESSOR_BZIP2
+modset compression
+
+load_on request
+
+<add>
+bzip2.h
+bzip2.cpp
+</add>
+
+<libs>
+all -> bz2
+</libs>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/hex/hex.cpp b/botan/src/codec/hex/hex.cpp
new file mode 100644
index 0000000..fbacc27
--- /dev/null
+++ b/botan/src/codec/hex/hex.cpp
@@ -0,0 +1,191 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hex.h>
+#include <botan/parsing.h>
+#include <botan/charset.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Hex_Encoder Constructor
+*/
+Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) :
+ casing(c), line_length(breaks ? length : 0)
+ {
+ in.create(64);
+ out.create(2*in.size());
+ counter = position = 0;
+ }
+
+/*
+* Hex_Encoder Constructor
+*/
+Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0)
+ {
+ in.create(64);
+ out.create(2*in.size());
+ counter = position = 0;
+ }
+
+/*
+* Hex Encoding Operation
+*/
+void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing)
+ {
+ const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER :
+ BIN_TO_HEX_LOWER);
+
+ out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)];
+ out[1] = BIN_TO_HEX[((in ) & 0x0F)];
+ }
+
+/*
+* Encode and send a block
+*/
+void Hex_Encoder::encode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ encode(block[j], out + 2*j, casing);
+
+ if(line_length == 0)
+ send(out, 2*length);
+ else
+ {
+ u32bit remaining = 2*length, offset = 0;
+ while(remaining)
+ {
+ u32bit sent = std::min(line_length - counter, remaining);
+ send(out + offset, sent);
+ counter += sent;
+ remaining -= sent;
+ offset += sent;
+ if(counter == line_length)
+ {
+ send('\n');
+ counter = 0;
+ }
+ }
+ }
+ }
+
+/*
+* Convert some data into hex format
+*/
+void Hex_Encoder::write(const byte input[], u32bit length)
+ {
+ in.copy(position, input, length);
+ if(position + length >= in.size())
+ {
+ encode_and_send(in, in.size());
+ input += (in.size() - position);
+ length -= (in.size() - position);
+ while(length >= in.size())
+ {
+ encode_and_send(input, in.size());
+ input += in.size();
+ length -= in.size();
+ }
+ in.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Flush buffers
+*/
+void Hex_Encoder::end_msg()
+ {
+ encode_and_send(in, position);
+ if(counter && line_length)
+ send('\n');
+ counter = position = 0;
+ }
+
+/*
+* Hex_Decoder Constructor
+*/
+Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c)
+ {
+ in.create(64);
+ out.create(in.size() / 2);
+ position = 0;
+ }
+
+/*
+* Check if a character is a valid hex char
+*/
+bool Hex_Decoder::is_valid(byte in)
+ {
+ return (HEX_TO_BIN[in] != 0x80);
+ }
+
+/*
+* Handle processing an invalid character
+*/
+void Hex_Decoder::handle_bad_char(byte c)
+ {
+ if(checking == NONE)
+ return;
+
+ if((checking == IGNORE_WS) && Charset::is_space(c))
+ return;
+
+ throw Decoding_Error("Hex_Decoder: Invalid hex character: " +
+ to_string(c));
+ }
+
+/*
+* Hex Decoding Operation
+*/
+byte Hex_Decoder::decode(const byte hex[2])
+ {
+ return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]);
+ }
+
+/*
+* Decode and send a block
+*/
+void Hex_Decoder::decode_and_send(const byte block[], u32bit length)
+ {
+ for(u32bit j = 0; j != length / 2; ++j)
+ out[j] = decode(block + 2*j);
+ send(out, length / 2);
+ }
+
+/*
+* Convert some data from hex format
+*/
+void Hex_Decoder::write(const byte input[], u32bit length)
+ {
+ for(u32bit j = 0; j != length; ++j)
+ {
+ if(is_valid(input[j]))
+ in[position++] = input[j];
+ else
+ handle_bad_char(input[j]);
+ if(position == in.size())
+ {
+ decode_and_send(in, in.size());
+ position = 0;
+ }
+ }
+ }
+
+/*
+* Flush buffers
+*/
+void Hex_Decoder::end_msg()
+ {
+ decode_and_send(in, position);
+ position = 0;
+ }
+
+}
diff --git a/botan/src/codec/hex/hex.h b/botan/src/codec/hex/hex.h
new file mode 100644
index 0000000..035bf4e
--- /dev/null
+++ b/botan/src/codec/hex/hex.h
@@ -0,0 +1,90 @@
+/*
+* Hex Encoder/Decoder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HEX_H__
+#define BOTAN_HEX_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* This class represents a hex encoder. It encodes byte arrays to hex strings.
+*/
+class BOTAN_DLL Hex_Encoder : public Filter
+ {
+ public:
+ /**
+ * Whether to use uppercase or lowercase letters for the encoded string.
+ */
+ enum Case { Uppercase, Lowercase };
+
+ /**
+ Encode a single byte into two hex characters
+ */
+ static void encode(byte in, byte out[2], Case the_case = Uppercase);
+
+ void write(const byte in[], u32bit length);
+ void end_msg();
+
+ /**
+ * Create a hex encoder.
+ * @param the_case the case to use in the encoded strings.
+ */
+ Hex_Encoder(Case the_case);
+
+ /**
+ * Create a hex encoder.
+ * @param newlines should newlines be used
+ * @param line_length if newlines are used, how long are lines
+ * @param the_case the case to use in the encoded strings
+ */
+ Hex_Encoder(bool newlines = false,
+ u32bit line_length = 72,
+ Case the_case = Uppercase);
+ private:
+ void encode_and_send(const byte[], u32bit);
+ static const byte BIN_TO_HEX_UPPER[16];
+ static const byte BIN_TO_HEX_LOWER[16];
+
+ const Case casing;
+ const u32bit line_length;
+ SecureVector<byte> in, out;
+ u32bit position, counter;
+ };
+
+/**
+* This class represents a hex decoder. It converts hex strings to byte arrays.
+*/
+class BOTAN_DLL Hex_Decoder : public Filter
+ {
+ public:
+ static byte decode(const byte[2]);
+ static bool is_valid(byte);
+
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ /**
+ * Construct a Hex Decoder using the specified
+ * character checking.
+ * @param checking the checking to use during decoding.
+ */
+ Hex_Decoder(Decoder_Checking checking = NONE);
+ private:
+ void decode_and_send(const byte[], u32bit);
+ void handle_bad_char(byte);
+ static const byte HEX_TO_BIN[256];
+
+ const Decoder_Checking checking;
+ SecureVector<byte> in, out;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/codec/hex/hex_char.cpp b/botan/src/codec/hex/hex_char.cpp
new file mode 100644
index 0000000..c28efc5
--- /dev/null
+++ b/botan/src/codec/hex/hex_char.cpp
@@ -0,0 +1,48 @@
+/*
+* Hex Character Table
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hex.h>
+
+namespace Botan {
+
+/*
+* Hex Encoder Lookup Tables
+*/
+const byte Hex_Encoder::BIN_TO_HEX_UPPER[16] = {
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
+0x44, 0x45, 0x46 };
+
+const byte Hex_Encoder::BIN_TO_HEX_LOWER[16] = {
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63,
+0x64, 0x65, 0x66 };
+
+/*
+* Hex Decoder Lookup Table
+*/
+const byte Hex_Decoder::HEX_TO_BIN[256] = {
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03,
+0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+}
diff --git a/botan/src/codec/hex/info.txt b/botan/src/codec/hex/info.txt
new file mode 100644
index 0000000..512a5de
--- /dev/null
+++ b/botan/src/codec/hex/info.txt
@@ -0,0 +1,15 @@
+realname "Hex Codec"
+
+define HEX_CODEC
+
+load_on auto
+
+<add>
+hex.cpp
+hex_char.cpp
+hex.h
+</add>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/openpgp/info.txt b/botan/src/codec/openpgp/info.txt
new file mode 100644
index 0000000..6b30850
--- /dev/null
+++ b/botan/src/codec/openpgp/info.txt
@@ -0,0 +1,15 @@
+realname "OpenPGP Codec"
+
+define OPENPGP_CODEC
+
+load_on auto
+
+<add>
+openpgp.cpp
+openpgp.h
+</add>
+
+<requires>
+crc24
+filters
+</requires>
diff --git a/botan/src/codec/openpgp/openpgp.cpp b/botan/src/codec/openpgp/openpgp.cpp
new file mode 100644
index 0000000..7f9cf5f
--- /dev/null
+++ b/botan/src/codec/openpgp/openpgp.cpp
@@ -0,0 +1,197 @@
+/*
+* OpenPGP
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/openpgp.h>
+#include <botan/filters.h>
+#include <botan/charset.h>
+#include <botan/crc24.h>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*
+* OpenPGP Base64 encoding
+*/
+std::string encode(const byte input[], u32bit length,
+ const std::string& label,
+ const std::map<std::string, std::string>& headers)
+ {
+ const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
+ const u32bit PGP_WIDTH = 64;
+
+ std::string pgp_encoded = PGP_HEADER;
+
+ if(headers.find("Version") != headers.end())
+ pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
+
+ std::map<std::string, std::string>::const_iterator i = headers.begin();
+ while(i != headers.end())
+ {
+ if(i->first != "Version")
+ pgp_encoded += i->first + ": " + i->second + '\n';
+ ++i;
+ }
+ pgp_encoded += '\n';
+
+ Pipe pipe(new Fork(
+ new Base64_Encoder(true, PGP_WIDTH),
+ new Chain(new Hash_Filter(new CRC24), new Base64_Encoder)
+ )
+ );
+
+ pipe.process_msg(input, length);
+
+ pgp_encoded += pipe.read_all_as_string(0);
+ pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
+ pgp_encoded += PGP_TRAILER;
+
+ return pgp_encoded;
+ }
+
+/*
+* OpenPGP Base64 encoding
+*/
+std::string encode(const byte input[], u32bit length,
+ const std::string& type)
+ {
+ std::map<std::string, std::string> empty;
+ return encode(input, length, type, empty);
+ }
+
+/*
+* OpenPGP Base64 decoding
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label,
+ std::map<std::string, std::string>& headers)
+ {
+ const u32bit RANDOM_CHAR_LIMIT = 5;
+
+ const std::string PGP_HEADER1 = "-----BEGIN PGP ";
+ const std::string PGP_HEADER2 = "-----";
+ u32bit position = 0;
+
+ while(position != PGP_HEADER1.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PGP: Malformed PGP header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PGP_HEADER2.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ headers.clear();
+ bool end_of_headers = false;
+ while(!end_of_headers)
+ {
+ std::string this_header;
+ byte b = 0;
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad armor header");
+ if(b != '\n')
+ this_header += static_cast<char>(b);
+ }
+
+ end_of_headers = true;
+ for(u32bit j = 0; j != this_header.length(); ++j)
+ if(!Charset::is_space(this_header[j]))
+ end_of_headers = false;
+
+ if(!end_of_headers)
+ {
+ std::string::size_type pos = this_header.find(": ");
+ if(pos == std::string::npos)
+ throw Decoding_Error("OpenPGP: Bad headers");
+
+ std::string key = this_header.substr(0, pos);
+ std::string value = this_header.substr(pos + 2, std::string::npos);
+ headers[key] = value;
+ }
+ }
+
+ Pipe base64(new Base64_Decoder,
+ new Fork(0,
+ new Chain(new Hash_Filter(new CRC24),
+ new Base64_Encoder)
+ )
+ );
+ base64.start_msg();
+
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
+ position = 0;
+ bool newline_seen = 0;
+ std::string crc;
+ while(position != PGP_TRAILER.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP trailer found");
+ if(b == PGP_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP trailer");
+
+ if(b == '=' && newline_seen)
+ {
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad CRC tail");
+ if(b != '\n')
+ crc += static_cast<char>(b);
+ }
+ }
+ else if(b == '\n')
+ newline_seen = true;
+ else if(position == 0)
+ {
+ base64.write(b);
+ newline_seen = false;
+ }
+ }
+ base64.end_msg();
+
+ if(crc != "" && crc != base64.read_all_as_string(1))
+ throw Decoding_Error("PGP: Corrupt CRC");
+
+ return base64.read_all();
+ }
+
+/*
+* OpenPGP Base64 decoding
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label)
+ {
+ std::map<std::string, std::string> ignored;
+ return decode(source, label, ignored);
+ }
+
+}
+
+}
+
diff --git a/botan/src/codec/openpgp/openpgp.h b/botan/src/codec/openpgp/openpgp.h
new file mode 100644
index 0000000..890fcf0
--- /dev/null
+++ b/botan/src/codec/openpgp/openpgp.h
@@ -0,0 +1,34 @@
+/*
+* OpenPGP
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENPGP_H__
+#define BOTAN_OPENPGP_H__
+
+#include <botan/data_src.h>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*
+* OpenPGP Base64 encoding/decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&,
+ const std::map<std::string, std::string>&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&,
+ std::map<std::string, std::string>&);
+
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/codec/pem/info.txt b/botan/src/codec/pem/info.txt
new file mode 100644
index 0000000..bbe8d4c
--- /dev/null
+++ b/botan/src/codec/pem/info.txt
@@ -0,0 +1,15 @@
+realname "PEM Codec"
+
+define PEM_CODEC
+
+load_on auto
+
+<add>
+pem.cpp
+pem.h
+</add>
+
+<requires>
+base64
+filters
+</requires>
diff --git a/botan/src/codec/pem/pem.cpp b/botan/src/codec/pem/pem.cpp
new file mode 100644
index 0000000..5141bee
--- /dev/null
+++ b/botan/src/codec/pem/pem.cpp
@@ -0,0 +1,143 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pem.h>
+#include <botan/filters.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+/*
+* PEM encode BER/DER-encoded objects
+*/
+std::string encode(const byte der[], u32bit length, const std::string& label,
+ u32bit width)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n";
+ const std::string PEM_TRAILER = "-----END " + label + "-----\n";
+
+ Pipe pipe(new Base64_Encoder(true, width));
+ pipe.process_msg(der, length);
+ return (PEM_HEADER + pipe.read_all_as_string() + PEM_TRAILER);
+ }
+
+/*
+* PEM encode BER/DER-encoded objects
+*/
+std::string encode(const MemoryRegion<byte>& data, const std::string& label,
+ u32bit width)
+ {
+ return encode(data, data.size(), label, width);
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+SecureVector<byte> decode_check_label(DataSource& source,
+ const std::string& label_want)
+ {
+ std::string label_got;
+ SecureVector<byte> ber = decode(source, label_got);
+ if(label_got != label_want)
+ throw Decoding_Error("PEM: Label mismatch, wanted " + label_want +
+ ", got " + label_got);
+ return ber;
+ }
+
+/*
+* Decode PEM down to raw BER/DER
+*/
+SecureVector<byte> decode(DataSource& source, std::string& label)
+ {
+ const u32bit RANDOM_CHAR_LIMIT = 8;
+
+ const std::string PEM_HEADER1 = "-----BEGIN ";
+ const std::string PEM_HEADER2 = "-----";
+ u32bit position = 0;
+
+ while(position != PEM_HEADER1.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PEM: Malformed PEM header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PEM_HEADER2.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM header found");
+ if(b == PEM_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ Pipe base64(new Base64_Decoder);
+ base64.start_msg();
+
+ const std::string PEM_TRAILER = "-----END " + label + "-----";
+ position = 0;
+ while(position != PEM_TRAILER.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PEM: No PEM trailer found");
+ if(b == PEM_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PEM: Malformed PEM trailer");
+
+ if(position == 0)
+ base64.write(b);
+ }
+ base64.end_msg();
+ return base64.read_all();
+ }
+
+/*
+* Search for a PEM signature
+*/
+bool matches(DataSource& source, const std::string& extra,
+ u32bit search_range)
+ {
+ const std::string PEM_HEADER = "-----BEGIN " + extra;
+
+ SecureVector<byte> search_buf(search_range);
+ u32bit got = source.peek(search_buf, search_buf.size(), 0);
+
+ if(got < PEM_HEADER.length())
+ return false;
+
+ u32bit index = 0;
+
+ for(u32bit j = 0; j != got; ++j)
+ {
+ if(search_buf[j] == PEM_HEADER[index])
+ ++index;
+ else
+ index = 0;
+ if(index == PEM_HEADER.size())
+ return true;
+ }
+ return false;
+ }
+
+}
+
+}
diff --git a/botan/src/codec/pem/pem.h b/botan/src/codec/pem/pem.h
new file mode 100644
index 0000000..9fe8acb
--- /dev/null
+++ b/botan/src/codec/pem/pem.h
@@ -0,0 +1,35 @@
+/*
+* PEM Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PEM_H__
+#define BOTAN_PEM_H__
+
+#include <botan/data_src.h>
+
+namespace Botan {
+
+namespace PEM_Code {
+
+/*
+* PEM Encoding/Decoding
+*/
+BOTAN_DLL std::string encode(const byte[], u32bit,
+ const std::string&, u32bit = 64);
+BOTAN_DLL std::string encode(const MemoryRegion<byte>&,
+ const std::string&, u32bit = 64);
+
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+BOTAN_DLL SecureVector<byte> decode_check_label(DataSource&,
+ const std::string&);
+BOTAN_DLL bool matches(DataSource&, const std::string& = "",
+ u32bit search_range = 4096);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/codec/zlib/info.txt b/botan/src/codec/zlib/info.txt
new file mode 100644
index 0000000..9b1c35d
--- /dev/null
+++ b/botan/src/codec/zlib/info.txt
@@ -0,0 +1,23 @@
+realname "Zlib Compressor"
+#realname "Zlib/Gzip Compressor"
+
+define COMPRESSOR_ZLIB
+#define COMPRESSOR_ZLIB,COMPRESSOR_GZIP
+
+load_on request
+modset compression
+
+<add>
+zlib.h
+zlib.cpp
+#gzip.h
+#gzip.cpp
+</add>
+
+<libs>
+all -> z
+</libs>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/codec/zlib/zlib.cpp b/botan/src/codec/zlib/zlib.cpp
new file mode 100644
index 0000000..246e329
--- /dev/null
+++ b/botan/src/codec/zlib/zlib.cpp
@@ -0,0 +1,287 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/zlib.h>
+#include <botan/exceptn.h>
+
+#include <cstring>
+#include <map>
+#include <zlib.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Allocation Information for Zlib
+*/
+class Zlib_Alloc_Info
+ {
+ public:
+ std::map<void*, u32bit> current_allocs;
+ Allocator* alloc;
+
+ Zlib_Alloc_Info() { alloc = Allocator::get(false); }
+ };
+
+/*
+* Allocation Function for Zlib
+*/
+void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ void* ptr = info->alloc->allocate(n * size);
+ info->current_allocs[ptr] = n * size;
+ return ptr;
+ }
+
+/*
+* Allocation Function for Zlib
+*/
+void zlib_free(void* info_ptr, void* ptr)
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+ std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+ if(i == info->current_allocs.end())
+ throw Invalid_Argument("zlib_free: Got pointer not allocated by us");
+ info->alloc->deallocate(ptr, i->second);
+ }
+
+}
+
+/*
+* Wrapper Type for Zlib z_stream
+*/
+class Zlib_Stream
+ {
+ public:
+ z_stream stream;
+
+ Zlib_Stream()
+ {
+ std::memset(&stream, 0, sizeof(z_stream));
+ stream.zalloc = zlib_malloc;
+ stream.zfree = zlib_free;
+ stream.opaque = new Zlib_Alloc_Info;
+ }
+ ~Zlib_Stream()
+ {
+ Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(stream.opaque);
+ delete info;
+ std::memset(&stream, 0, sizeof(z_stream));
+ }
+ };
+
+/*
+* Zlib_Compression Constructor
+*/
+Zlib_Compression::Zlib_Compression(u32bit l) :
+ level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ }
+
+/*
+* Start Compressing with Zlib
+*/
+void Zlib_Compression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(deflateInit(&(zlib->stream), level) != Z_OK)
+ throw Exception("Zlib_Compression: Memory allocation error");
+ }
+
+/*
+* Compress Input with Zlib
+*/
+void Zlib_Compression::write(const byte input[], u32bit length)
+ {
+ zlib->stream.next_in = static_cast<Bytef*>(const_cast<byte*>(input));
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = static_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ deflate(&(zlib->stream), Z_NO_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ }
+
+/*
+* Finish Compressing with Zlib
+*/
+void Zlib_Compression::end_msg()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ rc = deflate(&(zlib->stream), Z_FINISH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+ clear();
+ }
+
+/*
+* Flush the Zlib Compressor
+*/
+void Zlib_Compression::flush()
+ {
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ while(true)
+ {
+ zlib->stream.avail_out = buffer.size();
+
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+
+
+ deflate(&(zlib->stream), Z_FULL_FLUSH);
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ if(zlib->stream.avail_out == buffer.size()) break;
+ }
+ }
+
+/*
+* Clean up Compression Context
+*/
+void Zlib_Compression::clear()
+ {
+ if(zlib)
+ {
+ deflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+/*
+* Zlib_Decompression Constructor
+*/
+Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE)
+ {
+ zlib = 0;
+ no_writes = true;
+ }
+
+/*
+* Start Decompressing with Zlib
+*/
+void Zlib_Decompression::start_msg()
+ {
+ clear();
+ zlib = new Zlib_Stream;
+ if(inflateInit(&(zlib->stream)) != Z_OK)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ }
+
+/*
+* Decompress Input with Zlib
+*/
+void Zlib_Decompression::write(const byte input_arr[], u32bit length)
+ {
+ if(length) no_writes = false;
+
+ // non-const needed by zlib api :(
+ Bytef* input = reinterpret_cast<Bytef*>(const_cast<byte*>(input_arr));
+
+ zlib->stream.next_in = input;
+ zlib->stream.avail_in = length;
+
+ while(zlib->stream.avail_in != 0)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+
+ int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ if(rc == Z_DATA_ERROR)
+ throw Decoding_Error("Zlib_Decompression: Data integrity error");
+ if(rc == Z_NEED_DICT)
+ throw Decoding_Error("Zlib_Decompression: Need preset dictionary");
+ if(rc == Z_MEM_ERROR)
+ throw Exception("Zlib_Decompression: Memory allocation error");
+ throw Exception("Zlib_Decompression: Unknown decompress error");
+ }
+
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+
+ if(rc == Z_STREAM_END)
+ {
+ u32bit read_from_block = length - zlib->stream.avail_in;
+ start_msg();
+
+ zlib->stream.next_in = input + read_from_block;
+ zlib->stream.avail_in = length - read_from_block;
+
+ input += read_from_block;
+ length -= read_from_block;
+ }
+ }
+ }
+
+/*
+* Finish Decompressing with Zlib
+*/
+void Zlib_Decompression::end_msg()
+ {
+ if(no_writes) return;
+ zlib->stream.next_in = 0;
+ zlib->stream.avail_in = 0;
+
+ int rc = Z_OK;
+
+ while(rc != Z_STREAM_END)
+ {
+ zlib->stream.next_out = reinterpret_cast<Bytef*>(buffer.begin());
+ zlib->stream.avail_out = buffer.size();
+ rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+
+ if(rc != Z_OK && rc != Z_STREAM_END)
+ {
+ clear();
+ throw Exception("Zlib_Decompression: Error finalizing decompression");
+ }
+
+ send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+ }
+
+ clear();
+ }
+
+/*
+* Clean up Decompression Context
+*/
+void Zlib_Decompression::clear()
+ {
+ no_writes = true;
+
+ if(zlib)
+ {
+ inflateEnd(&(zlib->stream));
+ delete zlib;
+ zlib = 0;
+ }
+
+ buffer.clear();
+ }
+
+}
diff --git a/botan/src/codec/zlib/zlib.h b/botan/src/codec/zlib/zlib.h
new file mode 100644
index 0000000..4a7f3bc
--- /dev/null
+++ b/botan/src/codec/zlib/zlib.h
@@ -0,0 +1,58 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ZLIB_H__
+#define BOTAN_ZLIB_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* Zlib Compression Filter
+*/
+class BOTAN_DLL Zlib_Compression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ void flush();
+
+ Zlib_Compression(u32bit = 6);
+ ~Zlib_Compression() { clear(); }
+ private:
+ void clear();
+ const u32bit level;
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ };
+
+/*
+* Zlib Decompression Filter
+*/
+class BOTAN_DLL Zlib_Decompression : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length);
+ void start_msg();
+ void end_msg();
+
+ Zlib_Decompression();
+ ~Zlib_Decompression() { clear(); }
+ private:
+ void clear();
+ SecureVector<byte> buffer;
+ class Zlib_Stream* zlib;
+ bool no_writes;
+ };
+
+}
+
+#endif
diff --git a/botan/src/cryptobox/cryptobox.cpp b/botan/src/cryptobox/cryptobox.cpp
new file mode 100644
index 0000000..c27bbaf
--- /dev/null
+++ b/botan/src/cryptobox/cryptobox.cpp
@@ -0,0 +1,146 @@
+/*
+* Cryptobox Message Routines
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cryptobox.h>
+#include <botan/filters.h>
+#include <botan/pipe.h>
+#include <botan/serpent.h>
+#include <botan/sha2_64.h>
+#include <botan/ctr.h>
+#include <botan/hmac.h>
+#include <botan/pbkdf2.h>
+#include <botan/pem.h>
+#include <botan/loadstor.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+namespace CryptoBox {
+
+namespace {
+
+/*
+First 24 bits of SHA-256("Botan Cryptobox"), followed by 8 0 bits
+for later use as flags, etc if needed
+*/
+const u32bit CRYPTOBOX_VERSION_CODE = 0xEFC22400;
+
+const u32bit VERSION_CODE_LEN = 4;
+const u32bit CIPHER_KEY_LEN = 32;
+const u32bit CIPHER_IV_LEN = 16;
+const u32bit MAC_KEY_LEN = 32;
+const u32bit MAC_OUTPUT_LEN = 20;
+const u32bit PBKDF_SALT_LEN = 10;
+const u32bit PBKDF_ITERATIONS = 8 * 1024;
+
+const u32bit PBKDF_OUTPUT_LEN = CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN;
+
+}
+
+std::string encrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase,
+ RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> pbkdf_salt(PBKDF_SALT_LEN);
+ rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size());
+
+ PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
+ pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
+ pbkdf.set_iterations(PBKDF_ITERATIONS);
+
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+
+ SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
+ SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
+ InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN,
+ CIPHER_IV_LEN);
+
+ Pipe pipe(new CTR_BE(new Serpent, cipher_key, iv),
+ new Fork(
+ 0,
+ new MAC_Filter(new HMAC(new SHA_512),
+ mac_key, MAC_OUTPUT_LEN)));
+
+ pipe.process_msg(input, input_len);
+
+ /*
+ Output format is:
+ version # (4 bytes)
+ salt (10 bytes)
+ mac (20 bytes)
+ ciphertext
+ */
+ u32bit ciphertext_len = pipe.remaining(0);
+
+ SecureVector<byte> out_buf;
+
+ for(u32bit i = 0; i != VERSION_CODE_LEN; ++i)
+ out_buf.append(get_byte(i, CRYPTOBOX_VERSION_CODE));
+
+ out_buf.append(pbkdf_salt.begin(), pbkdf_salt.size());
+
+ out_buf.grow_to(out_buf.size() + MAC_OUTPUT_LEN + ciphertext_len);
+ pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN, MAC_OUTPUT_LEN, 1);
+ pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN,
+ ciphertext_len, 0);
+
+ return PEM_Code::encode(out_buf.begin(), out_buf.size(),
+ "BOTAN CRYPTOBOX MESSAGE");
+ }
+
+std::string decrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase)
+ {
+ DataSource_Memory input_src(input, input_len);
+ SecureVector<byte> ciphertext =
+ PEM_Code::decode_check_label(input_src,
+ "BOTAN CRYPTOBOX MESSAGE");
+
+ if(ciphertext.size() < (VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN))
+ throw Decoding_Error("Invalid CryptoBox input");
+
+ for(u32bit i = 0; i != VERSION_CODE_LEN; ++i)
+ if(ciphertext[i] != get_byte(i, CRYPTOBOX_VERSION_CODE))
+ throw Decoding_Error("Bad CryptoBox version");
+
+ SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN);
+
+ PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
+ pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
+ pbkdf.set_iterations(PBKDF_ITERATIONS);
+
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+
+ SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
+ SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
+ InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN,
+ CIPHER_IV_LEN);
+
+ Pipe pipe(new Fork(
+ new CTR_BE(new Serpent, cipher_key, iv),
+ new MAC_Filter(new HMAC(new SHA_512),
+ mac_key, MAC_OUTPUT_LEN)));
+
+ const u32bit ciphertext_offset =
+ VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN;
+
+ pipe.process_msg(ciphertext + ciphertext_offset,
+ ciphertext.size() - ciphertext_offset);
+
+ byte computed_mac[MAC_OUTPUT_LEN];
+ pipe.read(computed_mac, MAC_OUTPUT_LEN, 1);
+
+ if(!same_mem(computed_mac, ciphertext + VERSION_CODE_LEN + PBKDF_SALT_LEN,
+ MAC_OUTPUT_LEN))
+ throw Integrity_Failure("CryptoBox integrity failure");
+
+ return pipe.read_all_as_string(0);
+ }
+
+}
+
+}
diff --git a/botan/src/cryptobox/cryptobox.h b/botan/src/cryptobox/cryptobox.h
new file mode 100644
index 0000000..a30cb24
--- /dev/null
+++ b/botan/src/cryptobox/cryptobox.h
@@ -0,0 +1,42 @@
+/*
+* Cryptobox Message Routines
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CRYPTOBOX_H__
+#define BOTAN_CRYPTOBOX_H__
+
+#include <string>
+#include <botan/rng.h>
+
+namespace Botan {
+
+namespace CryptoBox {
+
+/**
+* Encrypt a message
+* @param input the input data
+* @param input_len the length of input in bytes
+* @param passphrase the passphrase used to encrypt the message
+* @param rng a ref to a random number generator, such as AutoSeeded_RNG
+*/
+BOTAN_DLL std::string encrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase,
+ RandomNumberGenerator& rng);
+
+/**
+* Decrypt a message encrypted with CryptoBox::encrypt
+* @param input the input data
+* @param input_len the length of input in bytes
+* @param passphrase the passphrase used to encrypt the message
+*/
+BOTAN_DLL std::string decrypt(const byte input[], u32bit input_len,
+ const std::string& passphrase);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/cryptobox/info.txt b/botan/src/cryptobox/info.txt
new file mode 100644
index 0000000..b9b9806
--- /dev/null
+++ b/botan/src/cryptobox/info.txt
@@ -0,0 +1,22 @@
+realname "Crypto Box"
+
+load_on auto
+
+define CRYPTO_BOX
+
+<add>
+cryptobox.h
+cryptobox.cpp
+</add>
+
+<requires>
+filters
+ctr
+hmac
+rng
+serpent
+sha2
+base64
+pbkdf2
+pem
+</requires>
diff --git a/botan/src/engine/amd64_eng/eng_amd64.cpp b/botan/src/engine/amd64_eng/eng_amd64.cpp
new file mode 100644
index 0000000..eed2cf3
--- /dev/null
+++ b/botan/src/engine/amd64_eng/eng_amd64.cpp
@@ -0,0 +1,27 @@
+/**
+* AMD64 Assembly Implementation Engine
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_amd64.h>
+
+#if defined(BOTAN_HAS_SHA1_AMD64)
+ #include <botan/sha1_amd64.h>
+#endif
+
+namespace Botan {
+
+HashFunction* AMD64_Assembler_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_SHA1_AMD64)
+ if(request.algo_name() == "SHA-160")
+ return new SHA_160_AMD64;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/amd64_eng/eng_amd64.h b/botan/src/engine/amd64_eng/eng_amd64.h
new file mode 100644
index 0000000..528291f
--- /dev/null
+++ b/botan/src/engine/amd64_eng/eng_amd64.h
@@ -0,0 +1,26 @@
+/**
+* x86-64 Assembly Implementation Engines
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AMD64_ASM_ENGINE_H__
+#define BOTAN_AMD64_ASM_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+class BOTAN_DLL AMD64_Assembler_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "amd64"; }
+ private:
+ HashFunction* find_hash(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/amd64_eng/info.txt b/botan/src/engine/amd64_eng/info.txt
new file mode 100644
index 0000000..47f8914
--- /dev/null
+++ b/botan/src/engine/amd64_eng/info.txt
@@ -0,0 +1,10 @@
+realname "AMD64 Assembler Engine"
+
+define ENGINE_AMD64_ASSEMBLER
+
+load_on dep
+
+<add>
+eng_amd64.cpp
+eng_amd64.h
+</add>
diff --git a/botan/src/engine/def_engine/def_eng.h b/botan/src/engine/def_engine/def_eng.h
new file mode 100644
index 0000000..2d71454
--- /dev/null
+++ b/botan/src/engine/def_engine/def_eng.h
@@ -0,0 +1,83 @@
+/*
+* Default Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DEFAULT_ENGINE_H__
+#define BOTAN_DEFAULT_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*
+* Default Engine
+*/
+class BOTAN_DLL Default_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "core"; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ virtual bool can_add_algorithms() { return true; }
+
+ Keyed_Filter* get_cipher(const std::string&, Cipher_Dir,
+ Algorithm_Factory&);
+
+ private:
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ StreamCipher* find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+
+ MessageAuthenticationCode* find_mac(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/def_engine/def_mode.cpp b/botan/src/engine/def_engine/def_mode.cpp
new file mode 100644
index 0000000..2b093a0
--- /dev/null
+++ b/botan/src/engine/def_engine/def_mode.cpp
@@ -0,0 +1,209 @@
+/*
+* Default Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/parsing.h>
+#include <botan/filters.h>
+#include <botan/algo_factory.h>
+#include <botan/mode_pad.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_ECB)
+ #include <botan/ecb.h>
+#endif
+
+#if defined(BOTAN_HAS_CBC)
+ #include <botan/cbc.h>
+#endif
+
+#if defined(BOTAN_HAS_CTS)
+ #include <botan/cts.h>
+#endif
+
+#if defined(BOTAN_HAS_CFB)
+ #include <botan/cfb.h>
+#endif
+
+#if defined(BOTAN_HAS_OFB)
+ #include <botan/ofb.h>
+#endif
+
+#if defined(BOTAN_HAS_CTR)
+ #include <botan/ctr.h>
+#endif
+
+#if defined(BOTAN_HAS_EAX)
+ #include <botan/eax.h>
+#endif
+
+#if defined(BOTAN_HAS_XTS)
+ #include <botan/xts.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/**
+* Get a block cipher padding method by name
+*/
+BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ if(request.algo_name() == "PKCS7")
+ return new PKCS7_Padding;
+
+ if(request.algo_name() == "OneAndZeros")
+ return new OneAndZeros_Padding;
+
+ if(request.algo_name() == "X9.23")
+ return new ANSI_X923_Padding;
+
+ if(request.algo_name() == "NoPadding")
+ return new Null_Padding;
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+}
+
+/*
+* Get a cipher object
+*/
+Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction,
+ Algorithm_Factory& af)
+ {
+ std::vector<std::string> algo_parts = split_on(algo_spec, '/');
+ if(algo_parts.empty())
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ const std::string cipher_name = algo_parts[0];
+
+ // check if it is a stream cipher first (easy case)
+ const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
+ if(stream_cipher)
+ return new StreamCipher_Filter(stream_cipher->clone());
+
+ const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
+ if(!block_cipher)
+ return 0;
+
+ if(algo_parts.size() != 2 && algo_parts.size() != 3)
+ return 0;
+
+ std::string mode = algo_parts[1];
+ u32bit bits = 0;
+
+ if(mode.find("CFB") != std::string::npos ||
+ mode.find("EAX") != std::string::npos)
+ {
+ std::vector<std::string> algo_info = parse_algorithm_name(mode);
+ mode = algo_info[0];
+ if(algo_info.size() == 1)
+ bits = 8*block_cipher->BLOCK_SIZE;
+ else if(algo_info.size() == 2)
+ bits = to_u32bit(algo_info[1]);
+ else
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+
+ std::string padding;
+ if(algo_parts.size() == 3)
+ padding = algo_parts[2];
+ else
+ padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
+
+ if(mode == "ECB" && padding == "CTS")
+ return 0;
+ else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
+ throw Invalid_Algorithm_Name(algo_spec);
+
+#if defined(BOTAN_HAS_OFB)
+ if(mode == "OFB")
+ return new OFB(block_cipher->clone());
+#endif
+
+#if defined(BOTAN_HAS_CTR)
+ if(mode == "CTR-BE")
+ return new CTR_BE(block_cipher->clone());
+#endif
+
+#if defined(BOTAN_HAS_ECB)
+ if(mode == "ECB")
+ {
+ if(direction == ENCRYPTION)
+ return new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding));
+ else
+ return new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding));
+ }
+#endif
+
+#if defined(BOTAN_HAS_CFB)
+ if(mode == "CFB")
+ {
+ if(direction == ENCRYPTION)
+ return new CFB_Encryption(block_cipher->clone(), bits);
+ else
+ return new CFB_Decryption(block_cipher->clone(), bits);
+ }
+#endif
+
+ if(mode == "CBC")
+ {
+ if(padding == "CTS")
+ {
+#if defined(BOTAN_HAS_CTS)
+ if(direction == ENCRYPTION)
+ return new CTS_Encryption(block_cipher->clone());
+ else
+ return new CTS_Decryption(block_cipher->clone());
+#else
+ return 0;
+#endif
+ }
+
+#if defined(BOTAN_HAS_CBC)
+ if(direction == ENCRYPTION)
+ return new CBC_Encryption(block_cipher->clone(),
+ get_bc_pad(padding));
+ else
+ return new CBC_Decryption(block_cipher->clone(),
+ get_bc_pad(padding));
+#else
+ return 0;
+#endif
+ }
+
+#if defined(BOTAN_HAS_EAX)
+ if(mode == "EAX")
+ {
+ if(direction == ENCRYPTION)
+ return new EAX_Encryption(block_cipher->clone(), bits);
+ else
+ return new EAX_Decryption(block_cipher->clone(), bits);
+ }
+#endif
+
+#if defined(BOTAN_HAS_XTS)
+ if(mode == "XTS")
+ {
+ if(direction == ENCRYPTION)
+ return new XTS_Encryption(block_cipher->clone());
+ else
+ return new XTS_Decryption(block_cipher->clone());
+ }
+#endif
+
+ throw Algorithm_Not_Found("get_mode: " + cipher_name + "/" +
+ mode + "/" + padding);
+ }
+
+}
diff --git a/botan/src/engine/def_engine/def_pk_ops.cpp b/botan/src/engine/def_engine/def_pk_ops.cpp
new file mode 100644
index 0000000..31dce7a
--- /dev/null
+++ b/botan/src/engine/def_engine/def_pk_ops.cpp
@@ -0,0 +1,121 @@
+/*
+* PK Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+/*
+* Acquire an IF op
+*/
+IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new Default_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+/*
+* Acquire a DSA op
+*/
+DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_DSA_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+/*
+* Acquire a NR op
+*/
+NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_NR_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+/*
+* Acquire an ElGamal op
+*/
+ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_ELG_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+/*
+* Acquire a DH op
+*/
+DH_Operation* Default_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new Default_DH_Op(group, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+/*
+* Acquire a ECDSA op
+*/
+ECDSA_Operation* Default_Engine::ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key) const
+ {
+ return new Default_ECDSA_Op(dom_pars, priv_key, pub_key);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+/*
+* Acquire a ECKAEG op
+*/
+ECKAEG_Operation* Default_Engine::eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key) const
+ {
+ return new Default_ECKAEG_Op(dom_pars, priv_key, pub_key);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/def_engine/def_powm.cpp b/botan/src/engine/def_engine/def_powm.cpp
new file mode 100644
index 0000000..9e7a88a
--- /dev/null
+++ b/botan/src/engine/def_engine/def_powm.cpp
@@ -0,0 +1,24 @@
+/*
+* Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/def_powm.h>
+
+namespace Botan {
+
+/*
+* Choose a modular exponentation algorithm
+*/
+Modular_Exponentiator*
+Default_Engine::mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints) const
+ {
+ if(n.is_odd())
+ return new Montgomery_Exponentiator(n, hints);
+ return new Fixed_Window_Exponentiator(n, hints);
+ }
+
+}
diff --git a/botan/src/engine/def_engine/info.txt b/botan/src/engine/def_engine/info.txt
new file mode 100644
index 0000000..fd31ee2
--- /dev/null
+++ b/botan/src/engine/def_engine/info.txt
@@ -0,0 +1,24 @@
+realname "Default Engine"
+
+define DEFAULT_ENGINE
+
+load_on auto
+
+<add>
+def_eng.h
+def_mode.cpp
+def_pk_ops.cpp
+def_powm.cpp
+lookup_block.cpp
+lookup_hash.cpp
+lookup_mac.cpp
+lookup_stream.cpp
+</add>
+
+<requires>
+algo_factory
+filters
+libstate
+mode_pad
+numbertheory
+</requires>
diff --git a/botan/src/engine/def_engine/lookup_block.cpp b/botan/src/engine/def_engine/lookup_block.cpp
new file mode 100644
index 0000000..7ee5f58
--- /dev/null
+++ b/botan/src/engine/def_engine/lookup_block.cpp
@@ -0,0 +1,264 @@
+/*
+* Block Cipher Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.h>
+
+#if defined(BOTAN_HAS_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ #include <botan/blowfish.h>
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ #include <botan/cast128.h>
+ #include <botan/cast256.h>
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ #include <botan/des.h>
+ #include <botan/desx.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_28147_89)
+ #include <botan/gost_28147.h>
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ #include <botan/idea.h>
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ #include <botan/kasumi.h>
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ #include <botan/lion.h>
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ #include <botan/lubyrack.h>
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ #include <botan/mars.h>
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ #include <botan/misty1.h>
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ #include <botan/noekeon.h>
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ #include <botan/rc2.h>
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ #include <botan/rc5.h>
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ #include <botan/rc6.h>
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ #include <botan/safer_sk.h>
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ #include <botan/seed.h>
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ #include <botan/serpent.h>
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ #include <botan/skipjack.h>
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ #include <botan/square.h>
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ #include <botan/tea.h>
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ #include <botan/twofish.h>
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ #include <botan/xtea.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+BlockCipher*
+Default_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+
+#if defined(BOTAN_HAS_AES)
+ if(request.algo_name() == "AES")
+ return new AES;
+ if(request.algo_name() == "AES-128")
+ return new AES_128;
+ if(request.algo_name() == "AES-192")
+ return new AES_192;
+ if(request.algo_name() == "AES-256")
+ return new AES_256;
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ if(request.algo_name() == "Blowfish")
+ return new Blowfish;
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ if(request.algo_name() == "CAST-128")
+ return new CAST_128;
+ if(request.algo_name() == "CAST-256")
+ return new CAST_256;
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ if(request.algo_name() == "DES")
+ return new DES;
+ if(request.algo_name() == "DESX")
+ return new DESX;
+ if(request.algo_name() == "TripleDES")
+ return new TripleDES;
+#endif
+
+#if defined(BOTAN_HAS_GOST_28147_89)
+ if(request.algo_name() == "GOST-28147-89")
+ return new GOST_28147_89(request.arg(0, "R3411_94_TestParam"));
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ if(request.algo_name() == "IDEA")
+ return new IDEA;
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ if(request.algo_name() == "KASUMI")
+ return new KASUMI;
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ if(request.algo_name() == "MARS")
+ return new MARS;
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ if(request.algo_name() == "MISTY1")
+ return new MISTY1(request.arg_as_u32bit(0, 8));
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ if(request.algo_name() == "Noekeon")
+ return new Noekeon;
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ if(request.algo_name() == "RC2")
+ return new RC2;
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ if(request.algo_name() == "RC5")
+ return new RC5(request.arg_as_u32bit(0, 12));
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ if(request.algo_name() == "RC6")
+ return new RC6;
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ if(request.algo_name() == "SAFER-SK")
+ return new SAFER_SK(request.arg_as_u32bit(0, 10));
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ if(request.algo_name() == "SEED")
+ return new SEED;
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ if(request.algo_name() == "Serpent")
+ return new Serpent;
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ if(request.algo_name() == "Skipjack")
+ return new Skipjack;
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ if(request.algo_name() == "Square")
+ return new Square;
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ if(request.algo_name() == "TEA")
+ return new TEA;
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ if(request.algo_name() == "Twofish")
+ return new Twofish;
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ if(request.algo_name() == "XTEA")
+ return new XTEA;
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ if(request.algo_name() == "Luby-Rackoff" && request.arg_count() == 1)
+ {
+ const HashFunction* hash = af.prototype_hash_function(request.arg(0));
+
+ if(hash)
+ return new LubyRackoff(hash->clone());
+ }
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ if(request.algo_name() == "Lion" && request.arg_count_between(2, 3))
+ {
+ const u32bit block_size = request.arg_as_u32bit(2, 1024);
+
+ const HashFunction* hash =
+ af.prototype_hash_function(request.arg(0));
+
+ const StreamCipher* stream_cipher =
+ af.prototype_stream_cipher(request.arg(1));
+
+ if(!hash || !stream_cipher)
+ return 0;
+
+ return new Lion(hash->clone(), stream_cipher->clone(), block_size);
+ }
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/def_engine/lookup_hash.cpp b/botan/src/engine/def_engine/lookup_hash.cpp
new file mode 100644
index 0000000..58136fc
--- /dev/null
+++ b/botan/src/engine/def_engine/lookup_hash.cpp
@@ -0,0 +1,209 @@
+/*
+* Hash Algorithms Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_ADLER32)
+ #include <botan/adler32.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ #include <botan/crc24.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ #include <botan/crc32.h>
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ #include <botan/fork256.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_11)
+ #include <botan/gost_3411.h>
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ #include <botan/has160.h>
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ #include <botan/md2.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ #include <botan/md4.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ #include <botan/md5.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ #include <botan/rmd128.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ #include <botan/rmd160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ #include <botan/sha160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ #include <botan/sha2_32.h>
+ #include <botan/sha2_64.h>
+#endif
+
+#if defined(BOTAN_HAS_SKEIN_512)
+ #include <botan/skein_512.h>
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ #include <botan/tiger.h>
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ #include <botan/whrlpool.h>
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+ #include <botan/par_hash.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+HashFunction*
+Default_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+#if defined(BOTAN_HAS_ADLER32)
+ if(request.algo_name() == "Adler32")
+ return new Adler32;
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ if(request.algo_name() == "CRC24")
+ return new CRC24;
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ if(request.algo_name() == "CRC32")
+ return new CRC32;
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ if(request.algo_name() == "FORK-256")
+ return new FORK_256;
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_11)
+ if(request.algo_name() == "GOST-34.11")
+ return new GOST_34_11;
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ if(request.algo_name() == "HAS-160")
+ return new HAS_160;
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ if(request.algo_name() == "MD2")
+ return new MD2;
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ if(request.algo_name() == "MD4")
+ return new MD4;
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ if(request.algo_name() == "MD5")
+ return new MD5;
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ if(request.algo_name() == "RIPEMD-128")
+ return new RIPEMD_128;
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ if(request.algo_name() == "RIPEMD-160")
+ return new RIPEMD_160;
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ if(request.algo_name() == "SHA-160")
+ return new SHA_160;
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ if(request.algo_name() == "SHA-224")
+ return new SHA_224;
+ if(request.algo_name() == "SHA-256")
+ return new SHA_256;
+ if(request.algo_name() == "SHA-384")
+ return new SHA_384;
+ if(request.algo_name() == "SHA-512")
+ return new SHA_512;
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ if(request.algo_name() == "Tiger")
+ return new Tiger(request.arg_as_u32bit(0, 24), // hash output
+ request.arg_as_u32bit(1, 3)); // # passes
+#endif
+
+#if defined(BOTAN_HAS_SKEIN_512)
+ if(request.algo_name() == "Skein-512")
+ return new Skein_512(request.arg_as_u32bit(0, 512),
+ request.arg(1, ""));
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ if(request.algo_name() == "Whirlpool")
+ return new Whirlpool;
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+
+ if(request.algo_name() == "Parallel")
+ {
+ std::vector<const HashFunction*> hash_prototypes;
+
+ /* First pass, just get the prototypes (no memory allocation). Then
+ if all were found, replace each prototype with a newly created clone
+ */
+ for(size_t i = 0; i != request.arg_count(); ++i)
+ {
+ const HashFunction* hash = af.prototype_hash_function(request.arg(i));
+ if(!hash)
+ return 0;
+
+ hash_prototypes.push_back(hash);
+ }
+
+ std::vector<HashFunction*> hashes;
+ for(size_t i = 0; i != hash_prototypes.size(); ++i)
+ hashes.push_back(hash_prototypes[i]->clone());
+
+ return new Parallel(hashes);
+ }
+
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/def_engine/lookup_mac.cpp b/botan/src/engine/def_engine/lookup_mac.cpp
new file mode 100644
index 0000000..3fef12b
--- /dev/null
+++ b/botan/src/engine/def_engine/lookup_mac.cpp
@@ -0,0 +1,70 @@
+/*
+* MAC Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.h>
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ #include <botan/cbc_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ #include <botan/cmac.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ #include <botan/hmac.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ #include <botan/ssl3_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ #include <botan/x919_mac.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+MessageAuthenticationCode*
+Default_Engine::find_mac(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ if(request.algo_name() == "CBC-MAC" && request.arg_count() == 1)
+ return new CBC_MAC(af.make_block_cipher(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ if(request.algo_name() == "CMAC" && request.arg_count() == 1)
+ return new CMAC(af.make_block_cipher(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ if(request.algo_name() == "HMAC" && request.arg_count() == 1)
+ return new HMAC(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ if(request.algo_name() == "SSL3-MAC" && request.arg_count() == 1)
+ return new SSL3_MAC(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ if(request.algo_name() == "X9.19-MAC" && request.arg_count() == 0)
+ return new ANSI_X919_MAC(af.make_block_cipher("DES"));
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/def_engine/lookup_stream.cpp b/botan/src/engine/def_engine/lookup_stream.cpp
new file mode 100644
index 0000000..e2f1b32
--- /dev/null
+++ b/botan/src/engine/def_engine/lookup_stream.cpp
@@ -0,0 +1,61 @@
+/*
+* Stream Cipher Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_eng.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_ARC4)
+ #include <botan/arc4.h>
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ #include <botan/salsa20.h>
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ #include <botan/turing.h>
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ #include <botan/wid_wake.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+StreamCipher*
+Default_Engine::find_stream_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_ARC4)
+ if(request.algo_name() == "ARC4")
+ return new ARC4(request.arg_as_u32bit(0, 0));
+ if(request.algo_name() == "RC4_drop")
+ return new ARC4(768);
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ if(request.algo_name() == "Salsa20")
+ return new Salsa20;
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ if(request.algo_name() == "Turing")
+ return new Turing;
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ if(request.algo_name() == "WiderWake4+1-BE")
+ return new WiderWake_41_BE;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/engine.h b/botan/src/engine/engine.h
new file mode 100644
index 0000000..66a159e
--- /dev/null
+++ b/botan/src/engine/engine.h
@@ -0,0 +1,140 @@
+/*
+* Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_H__
+#define BOTAN_ENGINE_H__
+
+#include <botan/scan_name.h>
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/pow_mod.h>
+
+#include <utility>
+#include <map>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+namespace Botan {
+
+class Algorithm_Factory;
+class Keyed_Filter;
+
+/*
+* Engine Base Class
+*/
+class BOTAN_DLL Engine
+ {
+ public:
+ virtual ~Engine() {}
+
+ virtual std::string provider_name() const = 0;
+
+ // Lookup functions
+ virtual BlockCipher*
+ find_block_cipher(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual StreamCipher*
+ find_stream_cipher(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual HashFunction*
+ find_hash(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual MessageAuthenticationCode*
+ find_mac(const SCAN_Name&, Algorithm_Factory&) const
+ { return 0; }
+
+ virtual Modular_Exponentiator*
+ mod_exp(const BigInt&, Power_Mod::Usage_Hints) const
+ { return 0; }
+
+ virtual Keyed_Filter* get_cipher(const std::string&,
+ Cipher_Dir,
+ Algorithm_Factory&)
+ { return 0; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ virtual NR_Operation* nr_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/gnump/eng_gmp.h b/botan/src/engine/gnump/eng_gmp.h
new file mode 100644
index 0000000..6a52b7e
--- /dev/null
+++ b/botan/src/engine/gnump/eng_gmp.h
@@ -0,0 +1,57 @@
+/*
+* GMP Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_GMP_H__
+#define BOTAN_ENGINE_GMP_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*
+* GMP Engine
+*/
+class BOTAN_DLL GMP_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "gmp"; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ GMP_Engine();
+ private:
+ static void set_memory_hooks();
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/gnump/gmp_dh.cpp b/botan/src/engine/gnump/gmp_dh.cpp
new file mode 100644
index 0000000..b332402
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_dh.cpp
@@ -0,0 +1,53 @@
+/*
+* GMP Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+namespace {
+
+/*
+* GMP DH Operation
+*/
+class GMP_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new GMP_DH_Op(*this); }
+
+ GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, p;
+ };
+
+/*
+* GMP DH Key Agreement Operation
+*/
+BigInt GMP_DH_Op::agree(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, x.value, p.value);
+ return i.to_bigint();
+ }
+
+}
+
+/*
+* Acquire a DH op
+*/
+DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
+ {
+ return new GMP_DH_Op(group, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/gnump/gmp_dsa.cpp b/botan/src/engine/gnump/gmp_dsa.cpp
new file mode 100644
index 0000000..69a9c3e
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_dsa.cpp
@@ -0,0 +1,124 @@
+/*
+* GMP DSA Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DSA)
+
+namespace {
+
+/*
+* GMP DSA Operation
+*/
+class GMP_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new GMP_DSA_Op(*this); }
+
+ GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*
+* GMP DSA Verify Operation
+*/
+bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ GMP_MPZ r(sig, q_bytes);
+ GMP_MPZ s(sig + q_bytes, q_bytes);
+ GMP_MPZ i(msg, msg_len);
+
+ if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
+ return false;
+ if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(mpz_invert(s.value, s.value, q.value) == 0)
+ return false;
+
+ GMP_MPZ si;
+ mpz_mul(si.value, s.value, i.value);
+ mpz_mod(si.value, si.value, q.value);
+ mpz_powm(si.value, g.value, si.value, p.value);
+
+ GMP_MPZ sr;
+ mpz_mul(sr.value, s.value, r.value);
+ mpz_mod(sr.value, sr.value, q.value);
+ mpz_powm(sr.value, y.value, sr.value, p.value);
+
+ mpz_mul(si.value, si.value, sr.value);
+ mpz_mod(si.value, si.value, p.value);
+ mpz_mod(si.value, si.value, q.value);
+
+ if(mpz_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*
+* GMP DSA Sign Operation
+*/
+SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: No private key");
+
+ GMP_MPZ i(in, length);
+ GMP_MPZ k(k_bn);
+
+ GMP_MPZ r;
+ mpz_powm(r.value, g.value, k.value, p.value);
+ mpz_mod(r.value, r.value, q.value);
+
+ mpz_invert(k.value, k.value, q.value);
+
+ GMP_MPZ s;
+ mpz_mul(s.value, x.value, r.value);
+ mpz_add(s.value, s.value, i.value);
+ mpz_mul(s.value, s.value, k.value);
+ mpz_mod(s.value, s.value, q.value);
+
+ if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*
+* Acquire a DSA op
+*/
+DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_DSA_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/gnump/gmp_elg.cpp b/botan/src/engine/gnump/gmp_elg.cpp
new file mode 100644
index 0000000..ee109f1
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_elg.cpp
@@ -0,0 +1,92 @@
+/*
+* GMP ElGamal Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*
+* GMP ElGamal Operation
+*/
+class GMP_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
+
+ GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, y, g, p;
+ };
+
+/*
+* GMP ElGamal Encrypt Operation
+*/
+SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ GMP_MPZ i(in, length);
+
+ if(mpz_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Input is too large");
+
+ GMP_MPZ a, b, k(k_bn);
+
+ mpz_powm(a.value, g.value, k.value, p.value);
+ mpz_powm(b.value, y.value, k.value, p.value);
+ mpz_mul(b.value, b.value, i.value);
+ mpz_mod(b.value, b.value, p.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*
+* GMP ElGamal Decrypt Operation
+*/
+BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
+
+ GMP_MPZ a(a_bn), b(b_bn);
+
+ if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Invalid message");
+
+ mpz_powm(a.value, a.value, x.value, p.value);
+ mpz_invert(a.value, a.value, p.value);
+ mpz_mul(a.value, a.value, b.value);
+ mpz_mod(a.value, a.value, p.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*
+* Acquire an ElGamal op
+*/
+ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_ELG_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/gnump/gmp_if.cpp b/botan/src/engine/gnump/gmp_if.cpp
new file mode 100644
index 0000000..b96f2dd
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_if.cpp
@@ -0,0 +1,81 @@
+/*
+* GMP IF Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+
+namespace {
+
+/*
+* GMP IF Operation
+*/
+class GMP_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new GMP_IF_Op(*this); }
+
+ GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const GMP_MPZ e, n, p, q, d1, d2, c;
+ };
+
+/*
+* GMP IF Public Operation
+*/
+BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, e.value, n.value);
+ return i.to_bigint();
+ }
+
+/*
+* GMP IF Private Operation
+*/
+BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(mpz_cmp_ui(p.value, 0) == 0)
+ throw Internal_Error("GMP_IF_Op::private_op: No private key");
+
+ GMP_MPZ j1, j2, h(i_bn);
+
+ mpz_powm(j1.value, h.value, d1.value, p.value);
+ mpz_powm(j2.value, h.value, d2.value, q.value);
+ mpz_sub(h.value, j1.value, j2.value);
+ mpz_mul(h.value, h.value, c.value);
+ mpz_mod(h.value, h.value, p.value);
+ mpz_mul(h.value, h.value, q.value);
+ mpz_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+}
+
+/*
+* Acquire an IF op
+*/
+IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new GMP_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/gnump/gmp_mem.cpp b/botan/src/engine/gnump/gmp_mem.cpp
new file mode 100644
index 0000000..89a1ed2
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_mem.cpp
@@ -0,0 +1,70 @@
+/*
+* GNU MP Memory Handlers
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <cstring>
+#include <gmp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Allocator used by GNU MP
+*/
+Allocator* gmp_alloc = 0;
+
+/*
+* Allocation Function for GNU MP
+*/
+void* gmp_malloc(size_t n)
+ {
+ return gmp_alloc->allocate(n);
+ }
+
+/*
+* Reallocation Function for GNU MP
+*/
+void* gmp_realloc(void* ptr, size_t old_n, size_t new_n)
+ {
+ void* new_buf = gmp_alloc->allocate(new_n);
+ std::memcpy(new_buf, ptr, std::min(old_n, new_n));
+ gmp_alloc->deallocate(ptr, old_n);
+ return new_buf;
+ }
+
+/*
+* Deallocation Function for GNU MP
+*/
+void gmp_free(void* ptr, size_t n)
+ {
+ gmp_alloc->deallocate(ptr, n);
+ }
+
+}
+
+/*
+* Set the GNU MP memory functions
+*/
+void GMP_Engine::set_memory_hooks()
+ {
+ if(gmp_alloc == 0)
+ {
+ gmp_alloc = Allocator::get(true);
+ mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
+ }
+ }
+
+/*
+* GMP_Engine Constructor
+*/
+GMP_Engine::GMP_Engine()
+ {
+ set_memory_hooks();
+ }
+
+}
diff --git a/botan/src/engine/gnump/gmp_nr.cpp b/botan/src/engine/gnump/gmp_nr.cpp
new file mode 100644
index 0000000..4aeb09f
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_nr.cpp
@@ -0,0 +1,107 @@
+/*
+* GMP NR Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+
+namespace {
+
+/*
+* GMP NR Operation
+*/
+class GMP_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new GMP_NR_Op(*this); }
+
+ GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*
+* GMP NR Verify Operation
+*/
+SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ GMP_MPZ c(sig, q_bytes);
+ GMP_MPZ d(sig + q_bytes, q_bytes);
+
+ if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 ||
+ mpz_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature");
+
+ GMP_MPZ i1, i2;
+ mpz_powm(i1.value, g.value, d.value, p.value);
+ mpz_powm(i2.value, y.value, c.value, p.value);
+ mpz_mul(i1.value, i1.value, i2.value);
+ mpz_mod(i1.value, i1.value, p.value);
+ mpz_sub(i1.value, c.value, i1.value);
+ mpz_mod(i1.value, i1.value, q.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*
+* GMP NR Sign Operation
+*/
+SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_NR_Op::sign: No private key");
+
+ GMP_MPZ f(in, length);
+ GMP_MPZ k(k_bn);
+
+ if(mpz_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range");
+
+ GMP_MPZ c, d;
+ mpz_powm(c.value, g.value, k.value, p.value);
+ mpz_add(c.value, c.value, f.value);
+ mpz_mod(c.value, c.value, q.value);
+ mpz_mul(d.value, x.value, c.value);
+ mpz_sub(d.value, k.value, d.value);
+ mpz_mod(d.value, d.value, q.value);
+
+ if(mpz_cmp_ui(c.value, 0) == 0)
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*
+* Acquire a NR op
+*/
+NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_NR_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/gnump/gmp_powm.cpp b/botan/src/engine/gnump/gmp_powm.cpp
new file mode 100644
index 0000000..687aed8
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_powm.cpp
@@ -0,0 +1,53 @@
+/*
+* GMP Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* GMP Modular Exponentiator
+*/
+class GMP_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new GMP_Modular_Exponentiator(*this); }
+
+ GMP_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ GMP_MPZ base, exp, mod;
+ };
+
+/*
+* Compute the result
+*/
+BigInt GMP_Modular_Exponentiator::execute() const
+ {
+ GMP_MPZ r;
+ mpz_powm(r.value, base.value, exp.value, mod.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*
+* Return the GMP-based modular exponentiator
+*/
+Modular_Exponentiator* GMP_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new GMP_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/botan/src/engine/gnump/gmp_wrap.cpp b/botan/src/engine/gnump/gmp_wrap.cpp
new file mode 100644
index 0000000..735fc70
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_wrap.cpp
@@ -0,0 +1,98 @@
+/*
+* GMP Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/gmp_wrap.h>
+
+#define GNU_MP_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+#define GNU_MP_VERSION_CODE \
+ GNU_MP_VERSION_CODE_FOR(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, \
+ __GNU_MP_VERSION_PATCHLEVEL)
+
+#if GNU_MP_VERSION_CODE < GNU_MP_VERSION_CODE_FOR(4,1,0)
+ #error Your GNU MP install is too old, upgrade to 4.1 or later
+#endif
+
+namespace Botan {
+
+/*
+* GMP_MPZ Constructor
+*/
+GMP_MPZ::GMP_MPZ(const BigInt& in)
+ {
+ mpz_init(value);
+ if(in != 0)
+ mpz_import(value, in.sig_words(), -1, sizeof(word), 0, 0, in.data());
+ }
+
+/*
+* GMP_MPZ Constructor
+*/
+GMP_MPZ::GMP_MPZ(const byte in[], u32bit length)
+ {
+ mpz_init(value);
+ mpz_import(value, length, 1, 1, 0, 0, in);
+ }
+
+/*
+* GMP_MPZ Copy Constructor
+*/
+GMP_MPZ::GMP_MPZ(const GMP_MPZ& other)
+ {
+ mpz_init_set(value, other.value);
+ }
+
+/*
+* GMP_MPZ Destructor
+*/
+GMP_MPZ::~GMP_MPZ()
+ {
+ mpz_clear(value);
+ }
+
+/*
+* GMP_MPZ Assignment Operator
+*/
+GMP_MPZ& GMP_MPZ::operator=(const GMP_MPZ& other)
+ {
+ mpz_set(value, other.value);
+ return (*this);
+ }
+
+/*
+* Export the mpz_t as a bytestring
+*/
+void GMP_MPZ::encode(byte out[], u32bit length) const
+ {
+ size_t dummy = 0;
+ mpz_export(out + (length - bytes()), &dummy, 1, 1, 0, 0, value);
+ }
+
+/*
+* Return the number of significant bytes
+*/
+u32bit GMP_MPZ::bytes() const
+ {
+ return ((mpz_sizeinbase(value, 2) + 7) / 8);
+ }
+
+/*
+* GMP to BigInt Conversions
+*/
+BigInt GMP_MPZ::to_bigint() const
+ {
+ BigInt out(BigInt::Positive, (bytes() + sizeof(word) - 1) / sizeof(word));
+ size_t dummy = 0;
+ mpz_export(out.get_reg(), &dummy, -1, sizeof(word), 0, 0, value);
+
+ if(mpz_sgn(value) < 0)
+ out.flip_sign();
+
+ return out;
+ }
+
+}
diff --git a/botan/src/engine/gnump/gmp_wrap.h b/botan/src/engine/gnump/gmp_wrap.h
new file mode 100644
index 0000000..11a51c8
--- /dev/null
+++ b/botan/src/engine/gnump/gmp_wrap.h
@@ -0,0 +1,38 @@
+/*
+* GMP MPZ Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GMP_MPZ_WRAP_H__
+#define BOTAN_GMP_MPZ_WRAP_H__
+
+#include <botan/bigint.h>
+#include <gmp.h>
+
+namespace Botan {
+
+/*
+* Lightweight GMP mpz_t Wrapper
+*/
+class BOTAN_DLL GMP_MPZ
+ {
+ public:
+ mpz_t value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ GMP_MPZ& operator=(const GMP_MPZ&);
+
+ GMP_MPZ(const GMP_MPZ&);
+ GMP_MPZ(const BigInt& = 0);
+ GMP_MPZ(const byte[], u32bit);
+ ~GMP_MPZ();
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/gnump/info.txt b/botan/src/engine/gnump/info.txt
new file mode 100644
index 0000000..67a9bcd
--- /dev/null
+++ b/botan/src/engine/gnump/info.txt
@@ -0,0 +1,26 @@
+realname "GMP Engine"
+
+define ENGINE_GNU_MP
+
+load_on request
+
+<libs>
+all -> gmp
+</libs>
+
+<add>
+eng_gmp.h
+gmp_dh.cpp
+gmp_dsa.cpp
+gmp_elg.cpp
+gmp_if.cpp
+gmp_mem.cpp
+gmp_nr.cpp
+gmp_powm.cpp
+gmp_wrap.cpp
+gmp_wrap.h
+</add>
+
+<requires>
+bigint
+</requires>
diff --git a/botan/src/engine/ia32_eng/eng_ia32.cpp b/botan/src/engine/ia32_eng/eng_ia32.cpp
new file mode 100644
index 0000000..6ff2a4b
--- /dev/null
+++ b/botan/src/engine/ia32_eng/eng_ia32.cpp
@@ -0,0 +1,62 @@
+/*
+* Assembly Implementation Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ia32.h>
+
+#if defined(BOTAN_HAS_SERPENT_IA32)
+ #include <botan/serp_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4_IA32)
+ #include <botan/md4_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5_IA32)
+ #include <botan/md5_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_IA32)
+ #include <botan/sha1_ia32.h>
+#endif
+
+namespace Botan {
+
+BlockCipher*
+IA32_Assembler_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_SERPENT_IA32)
+ if(request.algo_name() == "Serpent")
+ return new Serpent_IA32;
+#endif
+
+ return 0;
+ }
+
+HashFunction*
+IA32_Assembler_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_MD4_IA32)
+ if(request.algo_name() == "MD4")
+ return new MD4_IA32;
+#endif
+
+#if defined(BOTAN_HAS_MD5_IA32)
+ if(request.algo_name() == "MD5")
+ return new MD5_IA32;
+#endif
+
+#if defined(BOTAN_HAS_SHA1_IA32)
+ if(request.algo_name() == "SHA-160")
+ return new SHA_160_IA32;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/ia32_eng/eng_ia32.h b/botan/src/engine/ia32_eng/eng_ia32.h
new file mode 100644
index 0000000..b7cb482
--- /dev/null
+++ b/botan/src/engine/ia32_eng/eng_ia32.h
@@ -0,0 +1,29 @@
+/**
+* IA-32 Assembly Implementation Engines
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IA32_ASM_ENGINE_H__
+#define BOTAN_IA32_ASM_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+class BOTAN_DLL IA32_Assembler_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "ia32"; }
+ private:
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/ia32_eng/info.txt b/botan/src/engine/ia32_eng/info.txt
new file mode 100644
index 0000000..3bf2a7f
--- /dev/null
+++ b/botan/src/engine/ia32_eng/info.txt
@@ -0,0 +1,10 @@
+realname "IA32 Assembler Engine"
+
+define ENGINE_IA32_ASSEMBLER
+
+load_on dep
+
+<add>
+eng_ia32.cpp
+eng_ia32.h
+</add>
diff --git a/botan/src/engine/info.txt b/botan/src/engine/info.txt
new file mode 100644
index 0000000..eef3c03
--- /dev/null
+++ b/botan/src/engine/info.txt
@@ -0,0 +1,18 @@
+realname "Engines"
+
+define ENGINES
+
+load_on auto
+
+<add>
+engine.h
+</add>
+
+<requires>
+block
+hash
+libstate
+mac
+numbertheory
+stream
+</requires>
diff --git a/botan/src/engine/openssl/arc4_openssl.cpp b/botan/src/engine/openssl/arc4_openssl.cpp
new file mode 100644
index 0000000..08ed3eb
--- /dev/null
+++ b/botan/src/engine/openssl/arc4_openssl.cpp
@@ -0,0 +1,82 @@
+/*
+* OpenSSL ARC4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <openssl/rc4.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* ARC4 as implemented by OpenSSL
+*/
+class ARC4_OpenSSL : public StreamCipher
+ {
+ public:
+ void clear() throw() { std::memset(&state, 0, sizeof(state)); }
+ std::string name() const;
+ StreamCipher* clone() const { return new ARC4_OpenSSL(SKIP); }
+
+ ARC4_OpenSSL(u32bit s = 0) : StreamCipher(1, 32), SKIP(s) { clear(); }
+ ~ARC4_OpenSSL() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ const u32bit SKIP;
+ RC4_KEY state;
+ };
+
+/*
+* Return the name of this type
+*/
+std::string ARC4_OpenSSL::name() const
+ {
+ if(SKIP == 0) return "ARC4";
+ if(SKIP == 256) return "MARK-4";
+ else return "RC4_skip(" + to_string(SKIP) + ")";
+ }
+
+/*
+* ARC4 Key Schedule
+*/
+void ARC4_OpenSSL::key_schedule(const byte key[], u32bit length)
+ {
+ RC4_set_key(&state, length, key);
+ byte dummy = 0;
+ for(u32bit j = 0; j != SKIP; j++)
+ RC4(&state, 1, &dummy, &dummy);
+ }
+
+/*
+* ARC4 Encryption
+*/
+void ARC4_OpenSSL::cipher(const byte in[], byte out[], u32bit length)
+ {
+ RC4(&state, length, in, out);
+ }
+
+}
+
+/**
+* Look for an OpenSSL-suported stream cipher (ARC4)
+*/
+StreamCipher*
+OpenSSL_Engine::find_stream_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+ if(request.algo_name() == "ARC4")
+ return new ARC4_OpenSSL(request.arg_as_u32bit(0, 0));
+ if(request.algo_name() == "RC4_drop")
+ return new ARC4_OpenSSL(768);
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/openssl/bn_powm.cpp b/botan/src/engine/openssl/bn_powm.cpp
new file mode 100644
index 0000000..7b836d1
--- /dev/null
+++ b/botan/src/engine/openssl/bn_powm.cpp
@@ -0,0 +1,54 @@
+/*
+* OpenSSL Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* OpenSSL Modular Exponentiator
+*/
+class OpenSSL_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new OpenSSL_Modular_Exponentiator(*this); }
+
+ OpenSSL_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ OSSL_BN base, exp, mod;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* Compute the result
+*/
+BigInt OpenSSL_Modular_Exponentiator::execute() const
+ {
+ OSSL_BN r;
+ BN_mod_exp(r.value, base.value, exp.value, mod.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*
+* Return the OpenSSL-based modular exponentiator
+*/
+Modular_Exponentiator* OpenSSL_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new OpenSSL_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/botan/src/engine/openssl/bn_wrap.cpp b/botan/src/engine/openssl/bn_wrap.cpp
new file mode 100644
index 0000000..e1cfe3f
--- /dev/null
+++ b/botan/src/engine/openssl/bn_wrap.cpp
@@ -0,0 +1,116 @@
+/*
+* OpenSSL BN Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+/*
+* OSSL_BN Constructor
+*/
+OSSL_BN::OSSL_BN(const BigInt& in)
+ {
+ value = BN_new();
+ SecureVector<byte> encoding = BigInt::encode(in);
+ if(in != 0)
+ BN_bin2bn(encoding, encoding.size(), value);
+ }
+
+/*
+* OSSL_BN Constructor
+*/
+OSSL_BN::OSSL_BN(const byte in[], u32bit length)
+ {
+ value = BN_new();
+ BN_bin2bn(in, length, value);
+ }
+
+/*
+* OSSL_BN Copy Constructor
+*/
+OSSL_BN::OSSL_BN(const OSSL_BN& other)
+ {
+ value = BN_dup(other.value);
+ }
+
+/*
+* OSSL_BN Destructor
+*/
+OSSL_BN::~OSSL_BN()
+ {
+ BN_clear_free(value);
+ }
+
+/*
+* OSSL_BN Assignment Operator
+*/
+OSSL_BN& OSSL_BN::operator=(const OSSL_BN& other)
+ {
+ BN_copy(value, other.value);
+ return (*this);
+ }
+
+/*
+* Export the BIGNUM as a bytestring
+*/
+void OSSL_BN::encode(byte out[], u32bit length) const
+ {
+ BN_bn2bin(value, out + (length - bytes()));
+ }
+
+/*
+* Return the number of significant bytes
+*/
+u32bit OSSL_BN::bytes() const
+ {
+ return BN_num_bytes(value);
+ }
+
+/*
+* OpenSSL to BigInt Conversions
+*/
+BigInt OSSL_BN::to_bigint() const
+ {
+ SecureVector<byte> out(bytes());
+ BN_bn2bin(value, out);
+ return BigInt::decode(out);
+ }
+
+/*
+* OSSL_BN_CTX Constructor
+*/
+OSSL_BN_CTX::OSSL_BN_CTX()
+ {
+ value = BN_CTX_new();
+ }
+
+/*
+* OSSL_BN_CTX Copy Constructor
+*/
+OSSL_BN_CTX::OSSL_BN_CTX(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ }
+
+/*
+* OSSL_BN_CTX Destructor
+*/
+OSSL_BN_CTX::~OSSL_BN_CTX()
+ {
+ BN_CTX_free(value);
+ }
+
+/*
+* OSSL_BN_CTX Assignment Operator
+*/
+OSSL_BN_CTX& OSSL_BN_CTX::operator=(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ return (*this);
+ }
+
+}
diff --git a/botan/src/engine/openssl/bn_wrap.h b/botan/src/engine/openssl/bn_wrap.h
new file mode 100644
index 0000000..4d18be1
--- /dev/null
+++ b/botan/src/engine/openssl/bn_wrap.h
@@ -0,0 +1,53 @@
+/*
+* OpenSSL BN Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENSSL_BN_WRAP_H__
+#define BOTAN_OPENSSL_BN_WRAP_H__
+
+#include <botan/bigint.h>
+#include <openssl/bn.h>
+
+namespace Botan {
+
+/*
+* Lightweight OpenSSL BN Wrapper
+*/
+class BOTAN_DLL OSSL_BN
+ {
+ public:
+ BIGNUM* value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ OSSL_BN& operator=(const OSSL_BN&);
+
+ OSSL_BN(const OSSL_BN&);
+ OSSL_BN(const BigInt& = 0);
+ OSSL_BN(const byte[], u32bit);
+ ~OSSL_BN();
+ };
+
+/*
+* Lightweight OpenSSL BN_CTX Wrapper
+*/
+class BOTAN_DLL OSSL_BN_CTX
+ {
+ public:
+ BN_CTX* value;
+
+ OSSL_BN_CTX& operator=(const OSSL_BN_CTX&);
+
+ OSSL_BN_CTX();
+ OSSL_BN_CTX(const OSSL_BN_CTX&);
+ ~OSSL_BN_CTX();
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/openssl/eng_ossl.h b/botan/src/engine/openssl/eng_ossl.h
new file mode 100644
index 0000000..7105546
--- /dev/null
+++ b/botan/src/engine/openssl/eng_ossl.h
@@ -0,0 +1,64 @@
+/*
+* OpenSSL Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_OPENSSL_H__
+#define BOTAN_ENGINE_OPENSSL_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*
+* OpenSSL Engine
+*/
+class BOTAN_DLL OpenSSL_Engine : public Engine
+ {
+ public:
+ /**
+ * Return the provider name ("openssl")
+ */
+ std::string provider_name() const { return "openssl"; }
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+ private:
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ StreamCipher* find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name&, Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/openssl/info.txt b/botan/src/engine/openssl/info.txt
new file mode 100644
index 0000000..3f2f1ab
--- /dev/null
+++ b/botan/src/engine/openssl/info.txt
@@ -0,0 +1,28 @@
+realname "OpenSSL Engine"
+
+define ENGINE_OPENSSL
+
+load_on request
+
+<libs>
+all -> crypto
+</libs>
+
+<add>
+arc4_openssl.cpp
+bn_powm.cpp
+bn_wrap.cpp
+bn_wrap.h
+eng_ossl.h
+ossl_bc.cpp
+ossl_dh.cpp
+ossl_dsa.cpp
+ossl_elg.cpp
+ossl_if.cpp
+ossl_md.cpp
+ossl_nr.cpp
+</add>
+
+<requires>
+bigint
+</requires>
diff --git a/botan/src/engine/openssl/ossl_bc.cpp b/botan/src/engine/openssl/ossl_bc.cpp
new file mode 100644
index 0000000..4d3761a
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_bc.cpp
@@ -0,0 +1,200 @@
+/*
+* OpenSSL Block Cipher
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EVP Block Cipher
+*/
+class EVP_BlockCipher : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return cipher_name; }
+ BlockCipher* clone() const;
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&);
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&,
+ u32bit, u32bit, u32bit);
+
+ ~EVP_BlockCipher();
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ std::string cipher_name;
+ mutable EVP_CIPHER_CTX encrypt, decrypt;
+ };
+
+/*
+* EVP Block Cipher Constructor
+*/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name) :
+ BlockCipher(EVP_CIPHER_block_size(algo), EVP_CIPHER_key_length(algo)),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*
+* EVP Block Cipher Constructor
+*/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name,
+ u32bit key_min, u32bit key_max,
+ u32bit key_mod) :
+ BlockCipher(EVP_CIPHER_block_size(algo), key_min, key_max, key_mod),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*
+* EVP Block Cipher Destructor
+*/
+EVP_BlockCipher::~EVP_BlockCipher()
+ {
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ }
+
+/*
+* Encrypt a block
+*/
+void EVP_BlockCipher::enc(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_EncryptUpdate(&encrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*
+* Decrypt a block
+*/
+void EVP_BlockCipher::dec(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_DecryptUpdate(&decrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*
+* Set the key
+*/
+void EVP_BlockCipher::key_schedule(const byte key[], u32bit length)
+ {
+ SecureVector<byte> full_key(key, length);
+
+ if(cipher_name == "TripleDES" && length == 16)
+ full_key.append(key, 8);
+ else
+ if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
+ EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
+ throw Invalid_Argument("EVP_BlockCipher: Bad key length for " +
+ cipher_name);
+
+ if(cipher_name == "RC2")
+ {
+ EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ }
+
+ EVP_EncryptInit_ex(&encrypt, 0, 0, full_key.begin(), 0);
+ EVP_DecryptInit_ex(&decrypt, 0, 0, full_key.begin(), 0);
+ }
+
+/*
+* Return a clone of this object
+*/
+BlockCipher* EVP_BlockCipher::clone() const
+ {
+ return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
+ cipher_name, MINIMUM_KEYLENGTH,
+ MAXIMUM_KEYLENGTH, KEYLENGTH_MULTIPLE);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void EVP_BlockCipher::clear() throw()
+ {
+ const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
+
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+}
+
+/*
+* Look for an algorithm with this name
+*/
+BlockCipher*
+OpenSSL_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#define HANDLE_EVP_CIPHER(NAME, EVP) \
+ if(request.algo_name() == NAME && request.arg_count() == 0) \
+ return new EVP_BlockCipher(EVP, NAME);
+
+#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \
+ if(request.algo_name() == NAME && request.arg_count() == 0) \
+ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD);
+
+#if 0
+ /*
+ Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g
+ cause is unknown
+ */
+ HANDLE_EVP_CIPHER("AES-128", EVP_aes_128_ecb());
+ HANDLE_EVP_CIPHER("AES-192", EVP_aes_192_ecb());
+ HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb());
+#endif
+
+ HANDLE_EVP_CIPHER("DES", EVP_des_ecb());
+ HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8);
+
+ HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1);
+
+#undef HANDLE_EVP_CIPHER
+#undef HANDLE_EVP_CIPHER_KEYLEN
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/openssl/ossl_dh.cpp b/botan/src/engine/openssl/ossl_dh.cpp
new file mode 100644
index 0000000..72eab8a
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_dh.cpp
@@ -0,0 +1,60 @@
+/*
+* OpenSSL Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+
+namespace {
+
+/*
+* OpenSSL DH Operation
+*/
+class OpenSSL_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new OpenSSL_DH_Op(*this); }
+
+ OpenSSL_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ OSSL_BN x, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* OpenSSL DH Key Agreement Operation
+*/
+BigInt OpenSSL_DH_Op::agree(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*
+* Acquire a DH op
+*/
+DH_Operation* OpenSSL_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DH_Op(group, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/openssl/ossl_dsa.cpp b/botan/src/engine/openssl/ossl_dsa.cpp
new file mode 100644
index 0000000..bfffb87
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_dsa.cpp
@@ -0,0 +1,126 @@
+/*
+* OpenSSL DSA Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DSA)
+
+namespace {
+
+/*
+* OpenSSL DSA Operation
+*/
+class OpenSSL_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new OpenSSL_DSA_Op(*this); }
+
+ OpenSSL_DSA_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* OpenSSL DSA Verify Operation
+*/
+bool OpenSSL_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ OSSL_BN r(sig, q_bytes);
+ OSSL_BN s(sig + q_bytes, q_bytes);
+ OSSL_BN i(msg, msg_len);
+
+ if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0)
+ return false;
+ if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0)
+ return false;
+
+ OSSL_BN si;
+ BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value);
+ BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value);
+
+ OSSL_BN sr;
+ BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value);
+ BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value);
+
+ BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value);
+ BN_nnmod(si.value, si.value, q.value, ctx.value);
+
+ if(BN_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*
+* OpenSSL DSA Sign Operation
+*/
+SecureVector<byte> OpenSSL_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: No private key");
+
+ OSSL_BN i(in, length);
+ OSSL_BN k(k_bn);
+
+ OSSL_BN r;
+ BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value);
+ BN_nnmod(r.value, r.value, q.value, ctx.value);
+
+ BN_mod_inverse(k.value, k.value, q.value, ctx.value);
+
+ OSSL_BN s;
+ BN_mul(s.value, x.value, r.value, ctx.value);
+ BN_add(s.value, s.value, i.value);
+ BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value);
+
+ if(BN_is_zero(r.value) || BN_is_zero(s.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*
+* Acquire a DSA op
+*/
+DSA_Operation* OpenSSL_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DSA_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/openssl/ossl_elg.cpp b/botan/src/engine/openssl/ossl_elg.cpp
new file mode 100644
index 0000000..aefda9a
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_elg.cpp
@@ -0,0 +1,95 @@
+/*
+* OpenSSL Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*
+* OpenSSL ElGamal Operation
+*/
+class OpenSSL_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); }
+ OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ OSSL_BN x, y, g, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* OpenSSL ElGamal Encrypt Operation
+*/
+SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ OSSL_BN i(in, length);
+
+ if(BN_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large");
+
+ OSSL_BN a, b, k(k_bn);
+
+ BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value);
+ BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value);
+ BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*
+* OpenSSL ElGamal Decrypt Operation
+*/
+BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key");
+
+ OSSL_BN a(a_bn), b(b_bn), t;
+
+ if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message");
+
+ BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value);
+ BN_mod_inverse(a.value, t.value, p.value, ctx.value);
+ BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*
+* Acquire an ElGamal op
+*/
+ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_ELG_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/openssl/ossl_if.cpp b/botan/src/engine/openssl/ossl_if.cpp
new file mode 100644
index 0000000..bbc10d5
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_if.cpp
@@ -0,0 +1,85 @@
+/*
+* OpenSSL IF Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+
+namespace {
+
+/*
+* OpenSSL IF Operation
+*/
+class OpenSSL_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new OpenSSL_IF_Op(*this); }
+
+ OpenSSL_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const OSSL_BN e, n, p, q, d1, d2, c;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* OpenSSL IF Public Operation
+*/
+BigInt OpenSSL_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, e.value, n.value, ctx.value);
+ return r.to_bigint();
+ }
+
+/*
+* OpenSSL IF Private Operation
+*/
+BigInt OpenSSL_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(BN_is_zero(p.value))
+ throw Internal_Error("OpenSSL_IF_Op::private_op: No private key");
+
+ OSSL_BN j1, j2, h(i_bn);
+
+ BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value);
+ BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value);
+ BN_sub(h.value, j1.value, j2.value);
+ BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value);
+ BN_mul(h.value, h.value, q.value, ctx.value);
+ BN_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+}
+
+/*
+* Acquire an IF op
+*/
+IF_Operation* OpenSSL_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new OpenSSL_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/openssl/ossl_md.cpp b/botan/src/engine/openssl/ossl_md.cpp
new file mode 100644
index 0000000..7c8fb67
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_md.cpp
@@ -0,0 +1,126 @@
+/*
+* OpenSSL Hash Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EVP Hash Function
+*/
+class EVP_HashFunction : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return algo_name; }
+ HashFunction* clone() const;
+ EVP_HashFunction(const EVP_MD*, const std::string&);
+ ~EVP_HashFunction();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+
+ std::string algo_name;
+ EVP_MD_CTX md;
+ };
+
+/*
+* Update an EVP Hash Calculation
+*/
+void EVP_HashFunction::add_data(const byte input[], u32bit length)
+ {
+ EVP_DigestUpdate(&md, input, length);
+ }
+
+/*
+* Finalize an EVP Hash Calculation
+*/
+void EVP_HashFunction::final_result(byte output[])
+ {
+ EVP_DigestFinal_ex(&md, output, 0);
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void EVP_HashFunction::clear() throw()
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*
+* Return a clone of this object
+*/
+HashFunction* EVP_HashFunction::clone() const
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ return new EVP_HashFunction(algo, name());
+ }
+
+/*
+* Create an EVP hash function
+*/
+EVP_HashFunction::EVP_HashFunction(const EVP_MD* algo,
+ const std::string& name) :
+ HashFunction(EVP_MD_size(algo), EVP_MD_block_size(algo)),
+ algo_name(name)
+ {
+ EVP_MD_CTX_init(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*
+* Destroy an EVP hash function
+*/
+EVP_HashFunction::~EVP_HashFunction()
+ {
+ EVP_MD_CTX_cleanup(&md);
+ }
+
+}
+
+/*
+* Look for an algorithm with this name
+*/
+HashFunction* OpenSSL_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#ifndef OPENSSL_NO_SHA
+ if(request.algo_name() == "SHA-160")
+ return new EVP_HashFunction(EVP_sha1(), "SHA-160");
+#endif
+
+#ifndef OPENSSL_NO_MD2
+ if(request.algo_name() == "MD2")
+ return new EVP_HashFunction(EVP_md2(), "MD2");
+#endif
+
+#ifndef OPENSSL_NO_MD4
+ if(request.algo_name() == "MD4")
+ return new EVP_HashFunction(EVP_md4(), "MD4");
+#endif
+
+#ifndef OPENSSL_NO_MD5
+ if(request.algo_name() == "MD5")
+ return new EVP_HashFunction(EVP_md5(), "MD5");
+#endif
+
+#ifndef OPENSSL_NO_RIPEMD
+ if(request.algo_name() == "RIPEMD-160")
+ return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160");
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/openssl/ossl_nr.cpp b/botan/src/engine/openssl/ossl_nr.cpp
new file mode 100644
index 0000000..532e4b8
--- /dev/null
+++ b/botan/src/engine/openssl/ossl_nr.cpp
@@ -0,0 +1,113 @@
+/*
+* OpenSSL NR Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+
+namespace {
+
+/*
+* OpenSSL NR Operation
+*/
+class OpenSSL_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new OpenSSL_NR_Op(*this); }
+
+ OpenSSL_NR_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*
+* OpenSSL NR Verify Operation
+*/
+SecureVector<byte> OpenSSL_NR_Op::verify(const byte sig[],
+ u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ OSSL_BN c(sig, q_bytes);
+ OSSL_BN d(sig + q_bytes, q_bytes);
+
+ if(BN_is_zero(c.value) || BN_cmp(c.value, q.value) >= 0 ||
+ BN_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::verify: Invalid signature");
+
+ OSSL_BN i1, i2;
+ BN_mod_exp(i1.value, g.value, d.value, p.value, ctx.value);
+ BN_mod_exp(i2.value, y.value, c.value, p.value, ctx.value);
+ BN_mod_mul(i1.value, i1.value, i2.value, p.value, ctx.value);
+ BN_sub(i1.value, c.value, i1.value);
+ BN_nnmod(i1.value, i1.value, q.value, ctx.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*
+* OpenSSL NR Sign Operation
+*/
+SecureVector<byte> OpenSSL_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_NR_Op::sign: No private key");
+
+ OSSL_BN f(in, length);
+ OSSL_BN k(k_bn);
+
+ if(BN_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::sign: Input is out of range");
+
+ OSSL_BN c, d;
+ BN_mod_exp(c.value, g.value, k.value, p.value, ctx.value);
+ BN_add(c.value, c.value, f.value);
+ BN_nnmod(c.value, c.value, q.value, ctx.value);
+ BN_mul(d.value, x.value, c.value, ctx.value);
+ BN_sub(d.value, k.value, d.value);
+ BN_nnmod(d.value, d.value, q.value, ctx.value);
+
+ if(BN_is_zero(c.value))
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*
+* Acquire a NR op
+*/
+NR_Operation* OpenSSL_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_NR_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/botan/src/engine/sse2_eng/eng_sse2.cpp b/botan/src/engine/sse2_eng/eng_sse2.cpp
new file mode 100644
index 0000000..c738b3d
--- /dev/null
+++ b/botan/src/engine/sse2_eng/eng_sse2.cpp
@@ -0,0 +1,27 @@
+/**
+* SSE2 Assembly Engine
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eng_sse2.h>
+
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ #include <botan/sha1_sse2.h>
+#endif
+
+namespace Botan {
+
+HashFunction* SSE2_Assembler_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ if(request.algo_name() == "SHA-160")
+ return new SHA_160_SSE2;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/engine/sse2_eng/eng_sse2.h b/botan/src/engine/sse2_eng/eng_sse2.h
new file mode 100644
index 0000000..129697e
--- /dev/null
+++ b/botan/src/engine/sse2_eng/eng_sse2.h
@@ -0,0 +1,26 @@
+/**
+* SSE2 Assembly Engine
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSE2_ASM_ENGINE_H__
+#define BOTAN_SSE2_ASM_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+class BOTAN_DLL SSE2_Assembler_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "sse2"; }
+ private:
+ HashFunction* find_hash(const SCAN_Name& reqeust,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/engine/sse2_eng/info.txt b/botan/src/engine/sse2_eng/info.txt
new file mode 100644
index 0000000..6242c7f
--- /dev/null
+++ b/botan/src/engine/sse2_eng/info.txt
@@ -0,0 +1,15 @@
+realname "SSE2 Assembler Engine"
+
+define ENGINE_SSE2_ASSEMBLER
+
+load_on dep
+
+<add>
+eng_sse2.cpp
+eng_sse2.h
+</add>
+
+<arch>
+ia32
+amd64
+</arch>
diff --git a/botan/src/entropy/beos_stats/es_beos.cpp b/botan/src/entropy/beos_stats/es_beos.cpp
new file mode 100644
index 0000000..18eca55
--- /dev/null
+++ b/botan/src/entropy/beos_stats/es_beos.cpp
@@ -0,0 +1,65 @@
+/**
+* BeOS EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_beos.h>
+
+#include <kernel/OS.h>
+#include <kernel/image.h>
+#include <interface/InterfaceDefs.h>
+
+namespace Botan {
+
+/**
+* BeOS entropy poll
+*/
+void BeOS_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ system_info info_sys;
+ get_system_info(&info_sys);
+ accum.add(info_sys, 2);
+
+ key_info info_key; // current state of the keyboard
+ get_key_info(&info_key);
+ accum.add(info_key, 0);
+
+ accum.add(idle_time(), 0);
+
+ team_info info_team;
+ int32 cookie_team = 0;
+
+ while(get_next_team_info(&cookie_team, &info_team) == B_OK)
+ {
+ accum.add(info_team, 2);
+
+ team_id id = info_team.team;
+ int32 cookie = 0;
+
+ thread_info info_thr;
+ while(get_next_thread_info(id, &cookie, &info_thr) == B_OK)
+ accum.add(info_thr, 1);
+
+ cookie = 0;
+ image_info info_img;
+ while(get_next_image_info(id, &cookie, &info_img) == B_OK)
+ accum.add(info_img, 1);
+
+ cookie = 0;
+ sem_info info_sem;
+ while(get_next_sem_info(id, &cookie, &info_sem) == B_OK)
+ accum.add(info_sem, 1);
+
+ cookie = 0;
+ area_info info_area;
+ while(get_next_area_info(id, &cookie, &info_area) == B_OK)
+ accum.add(info_area, 2);
+
+ if(accum.polling_goal_achieved())
+ break;
+ }
+ }
+
+}
diff --git a/botan/src/entropy/beos_stats/es_beos.h b/botan/src/entropy/beos_stats/es_beos.h
new file mode 100644
index 0000000..be80ad3
--- /dev/null
+++ b/botan/src/entropy/beos_stats/es_beos.h
@@ -0,0 +1,28 @@
+/**
+* BeOS EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_BEOS_H__
+#define BOTAN_ENTROPY_SRC_BEOS_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* BeOS Entropy Source
+*/
+class BOTAN_DLL BeOS_EntropySource : public EntropySource
+ {
+ private:
+ std::string name() const { return "BeOS Statistics"; }
+
+ void poll(Entropy_Accumulator& accum);
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/beos_stats/info.txt b/botan/src/entropy/beos_stats/info.txt
new file mode 100644
index 0000000..a7e62cf
--- /dev/null
+++ b/botan/src/entropy/beos_stats/info.txt
@@ -0,0 +1,19 @@
+realname "BeOS Entropy Source"
+
+define ENTROPY_SRC_BEOS
+modset beos
+
+load_on auto
+
+<add>
+es_beos.h
+es_beos.cpp
+</add>
+
+<os>
+beos
+</os>
+
+<libs>
+beos -> root,be
+</libs>
diff --git a/botan/src/entropy/cryptoapi_rng/es_capi.cpp b/botan/src/entropy/cryptoapi_rng/es_capi.cpp
new file mode 100644
index 0000000..a70b520
--- /dev/null
+++ b/botan/src/entropy/cryptoapi_rng/es_capi.cpp
@@ -0,0 +1,93 @@
+/*
+* Win32 CryptoAPI EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_capi.h>
+#include <botan/parsing.h>
+#include <windows.h>
+#include <wincrypt.h>
+
+namespace Botan {
+
+namespace {
+
+class CSP_Handle
+ {
+ public:
+ CSP_Handle(u64bit capi_provider)
+ {
+ valid = false;
+ DWORD prov_type = (DWORD)capi_provider;
+
+ if(CryptAcquireContext(&handle, 0, 0,
+ prov_type, CRYPT_VERIFYCONTEXT))
+ valid = true;
+ }
+
+ ~CSP_Handle()
+ {
+ if(is_valid())
+ CryptReleaseContext(handle, 0);
+ }
+
+ u32bit gen_random(byte out[], u32bit n) const
+ {
+ if(is_valid() && CryptGenRandom(handle, n, out))
+ return n;
+ return 0;
+ }
+
+ bool is_valid() const { return valid; }
+
+ HCRYPTPROV get_handle() const { return handle; }
+ private:
+ HCRYPTPROV handle;
+ bool valid;
+ };
+
+}
+
+/**
+* Gather Entropy from Win32 CAPI
+*/
+void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(32);
+
+ for(u32bit j = 0; j != prov_types.size(); ++j)
+ {
+ CSP_Handle csp(prov_types[j]);
+
+ u32bit got = csp.gen_random(io_buffer.begin(), io_buffer.size());
+
+ if(got)
+ {
+ accum.add(io_buffer.begin(), io_buffer.size(), 8);
+ break;
+ }
+ }
+ }
+
+/**
+* Win32_Capi_Entropysource Constructor
+*/
+Win32_CAPI_EntropySource::Win32_CAPI_EntropySource(const std::string& provs)
+ {
+ std::vector<std::string> capi_provs = split_on(provs, ':');
+
+ for(u32bit j = 0; j != capi_provs.size(); ++j)
+ {
+ if(capi_provs[j] == "RSA_FULL") prov_types.push_back(PROV_RSA_FULL);
+ if(capi_provs[j] == "INTEL_SEC") prov_types.push_back(PROV_INTEL_SEC);
+ if(capi_provs[j] == "FORTEZZA") prov_types.push_back(PROV_FORTEZZA);
+ if(capi_provs[j] == "RNG") prov_types.push_back(PROV_RNG);
+ }
+
+ if(prov_types.size() == 0)
+ prov_types.push_back(PROV_RSA_FULL);
+ }
+
+}
diff --git a/botan/src/entropy/cryptoapi_rng/es_capi.h b/botan/src/entropy/cryptoapi_rng/es_capi.h
new file mode 100644
index 0000000..55966d7
--- /dev/null
+++ b/botan/src/entropy/cryptoapi_rng/es_capi.h
@@ -0,0 +1,33 @@
+/*
+* Win32 CAPI EntropySource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_WIN32_CAPI_H__
+#define BOTAN_ENTROPY_SRC_WIN32_CAPI_H__
+
+#include <botan/entropy_src.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Win32 CAPI Entropy Source
+*/
+class BOTAN_DLL Win32_CAPI_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Win32 CryptoGenRandom"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ Win32_CAPI_EntropySource(const std::string& = "");
+ private:
+ std::vector<u64bit> prov_types;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/cryptoapi_rng/info.txt b/botan/src/entropy/cryptoapi_rng/info.txt
new file mode 100644
index 0000000..643c67d
--- /dev/null
+++ b/botan/src/entropy/cryptoapi_rng/info.txt
@@ -0,0 +1,21 @@
+realname "Win32 CryptoAPI Entropy Source"
+
+define ENTROPY_SRC_CAPI
+load_on auto
+modset win32
+
+<add>
+es_capi.h
+es_capi.cpp
+</add>
+
+# We'll just assume CAPI is there; this is OK except for 3.x, early versions
+# of 95, and maybe NT 3.5
+<os>
+windows
+cygwin
+</os>
+
+<libs>
+windows -> advapi32.lib
+</libs>
diff --git a/botan/src/entropy/dev_random/es_dev.cpp b/botan/src/entropy/dev_random/es_dev.cpp
new file mode 100644
index 0000000..ef30741
--- /dev/null
+++ b/botan/src/entropy/dev_random/es_dev.cpp
@@ -0,0 +1,125 @@
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_dev.h>
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+namespace Botan {
+
+/**
+Close the device, if open
+*/
+void Device_EntropySource::Device_Reader::close()
+ {
+ if(fd > 0) { ::close(fd); fd = -1; }
+ }
+
+/**
+Read bytes from a device file
+*/
+u32bit Device_EntropySource::Device_Reader::get(byte out[], u32bit length,
+ u32bit ms_wait_time)
+ {
+ if(fd < 0)
+ return 0;
+
+ if(fd >= FD_SETSIZE)
+ return 0;
+
+ fd_set read_set;
+ FD_ZERO(&read_set);
+ FD_SET(fd, &read_set);
+
+ struct ::timeval timeout;
+
+ timeout.tv_sec = (ms_wait_time / 1000);
+ timeout.tv_usec = (ms_wait_time % 1000) * 1000;
+
+ if(::select(fd + 1, &read_set, 0, 0, &timeout) < 0)
+ return 0;
+
+ if(!(FD_ISSET(fd, &read_set)))
+ return 0;
+
+ const ssize_t got = ::read(fd, out, length);
+ if(got <= 0)
+ return 0;
+
+ return static_cast<u32bit>(got);
+ }
+
+/**
+Attempt to open a device
+*/
+Device_EntropySource::Device_Reader::fd_type
+Device_EntropySource::Device_Reader::open(const std::string& pathname)
+ {
+#ifndef O_NONBLOCK
+ #define O_NONBLOCK 0
+#endif
+
+#ifndef O_NOCTTY
+ #define O_NOCTTY 0
+#endif
+
+ const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY;
+ return ::open(pathname.c_str(), flags);
+ }
+
+/**
+Device_EntropySource constructor
+Open a file descriptor to each (available) device in fsnames
+*/
+Device_EntropySource::Device_EntropySource(
+ const std::vector<std::string>& fsnames)
+ {
+ for(u32bit i = 0; i != fsnames.size(); ++i)
+ {
+ Device_Reader::fd_type fd = Device_Reader::open(fsnames[i]);
+ if(fd > 0)
+ devices.push_back(Device_Reader(fd));
+ }
+ }
+
+/**
+Device_EntropySource destructor: close all open devices
+*/
+Device_EntropySource::~Device_EntropySource()
+ {
+ for(size_t i = 0; i != devices.size(); ++i)
+ devices[i].close();
+ }
+
+/**
+* Gather entropy from a RNG device
+*/
+void Device_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 48);
+
+ u32bit read_wait_ms = std::max<u32bit>(go_get, 1000);
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
+
+ for(size_t i = 0; i != devices.size(); ++i)
+ {
+ u32bit got = devices[i].get(io_buffer.begin(), io_buffer.size(),
+ read_wait_ms);
+
+ if(got)
+ {
+ accum.add(io_buffer.begin(), got, 8);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/botan/src/entropy/dev_random/es_dev.h b/botan/src/entropy/dev_random/es_dev.h
new file mode 100644
index 0000000..df9dbe1
--- /dev/null
+++ b/botan/src/entropy/dev_random/es_dev.h
@@ -0,0 +1,53 @@
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_DEVICE_H__
+#define BOTAN_ENTROPY_SRC_DEVICE_H__
+
+#include <botan/entropy_src.h>
+#include <vector>
+#include <string>
+
+namespace Botan {
+
+class BOTAN_DLL Device_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "RNG Device Reader"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ Device_EntropySource(const std::vector<std::string>& fsnames);
+ ~Device_EntropySource();
+ private:
+
+ /**
+ A class handling reading from a Unix character device
+ */
+ class Device_Reader
+ {
+ public:
+ typedef int fd_type;
+
+ // Does not own fd, a transient class
+ Device_Reader(fd_type device_fd) : fd(device_fd) {}
+
+ void close();
+
+ u32bit get(byte out[], u32bit length, u32bit ms_wait_time);
+
+ static fd_type open(const std::string& pathname);
+ private:
+ fd_type fd;
+ };
+
+ std::vector<Device_Reader> devices;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/dev_random/info.txt b/botan/src/entropy/dev_random/info.txt
new file mode 100644
index 0000000..fddb7ac
--- /dev/null
+++ b/botan/src/entropy/dev_random/info.txt
@@ -0,0 +1,28 @@
+realname "RNG Device Reader"
+
+define ENTROPY_SRC_DEVICE
+
+load_on auto
+modset unix
+
+<add>
+es_dev.h
+es_dev.cpp
+</add>
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/botan/src/entropy/egd/es_egd.cpp b/botan/src/entropy/egd/es_egd.cpp
new file mode 100644
index 0000000..9e37f8f
--- /dev/null
+++ b/botan/src/entropy/egd/es_egd.cpp
@@ -0,0 +1,156 @@
+/*
+* EGD EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_egd.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <cstring>
+#include <stdexcept>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef PF_LOCAL
+ #define PF_LOCAL PF_UNIX
+#endif
+
+namespace Botan {
+
+EGD_EntropySource::EGD_Socket::EGD_Socket(const std::string& path) :
+ socket_path(path), m_fd(-1)
+ {
+ }
+
+/**
+* Attempt a connection to an EGD/PRNGD socket
+*/
+int EGD_EntropySource::EGD_Socket::open_socket(const std::string& path)
+ {
+ int fd = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+
+ if(fd >= 0)
+ {
+ sockaddr_un addr;
+ std::memset(&addr, 0, sizeof(addr));
+ addr.sun_family = PF_LOCAL;
+
+ if(sizeof(addr.sun_path) < path.length() + 1)
+ throw std::invalid_argument("EGD socket path is too long");
+
+ std::strcpy(addr.sun_path, path.c_str());
+
+ int len = sizeof(addr.sun_family) + std::strlen(addr.sun_path) + 1;
+
+ if(::connect(fd, reinterpret_cast<struct ::sockaddr*>(&addr), len) < 0)
+ {
+ ::close(fd);
+ fd = -1;
+ }
+ }
+
+ return fd;
+ }
+
+/**
+* Attempt to read entropy from EGD
+*/
+u32bit EGD_EntropySource::EGD_Socket::read(byte outbuf[], u32bit length)
+ {
+ if(length == 0)
+ return 0;
+
+ if(m_fd < 0)
+ {
+ m_fd = open_socket(socket_path);
+ if(m_fd < 0)
+ return 0;
+ }
+
+ try
+ {
+ // 1 == EGD command for non-blocking read
+ byte egd_read_command[2] = {
+ 1, static_cast<byte>(std::min<u32bit>(length, 255)) };
+
+ if(::write(m_fd, egd_read_command, 2) != 2)
+ throw std::runtime_error("Writing entropy read command to EGD failed");
+
+ byte out_len = 0;
+ if(::read(m_fd, &out_len, 1) != 1)
+ throw std::runtime_error("Reading response length from EGD failed");
+
+ if(out_len > egd_read_command[1])
+ throw std::runtime_error("Bogus length field recieved from EGD");
+
+ ssize_t count = ::read(m_fd, outbuf, out_len);
+
+ if(count != out_len)
+ throw std::runtime_error("Reading entropy result from EGD failed");
+
+ return static_cast<u32bit>(count);
+ }
+ catch(std::exception)
+ {
+ this->close();
+ // Will attempt to reopen next poll
+ }
+
+ return 0;
+ }
+
+void EGD_EntropySource::EGD_Socket::close()
+ {
+ if(m_fd > 0)
+ {
+ ::close(m_fd);
+ m_fd = -1;
+ }
+ }
+
+/**
+* EGD_EntropySource constructor
+*/
+EGD_EntropySource::EGD_EntropySource(const std::vector<std::string>& paths)
+ {
+ for(size_t i = 0; i != paths.size(); ++i)
+ sockets.push_back(EGD_Socket(paths[i]));
+ }
+
+EGD_EntropySource::~EGD_EntropySource()
+ {
+ for(size_t i = 0; i != sockets.size(); ++i)
+ sockets[i].close();
+ sockets.clear();
+ }
+
+/**
+* Gather Entropy from EGD
+*/
+void EGD_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 32);
+
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get);
+
+ for(size_t i = 0; i != sockets.size(); ++i)
+ {
+ u32bit got = sockets[i].read(io_buffer.begin(), io_buffer.size());
+
+ if(got)
+ {
+ accum.add(io_buffer.begin(), got, 8);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/botan/src/entropy/egd/es_egd.h b/botan/src/entropy/egd/es_egd.h
new file mode 100644
index 0000000..5db6565
--- /dev/null
+++ b/botan/src/entropy/egd/es_egd.h
@@ -0,0 +1,49 @@
+/**
+* EGD EntropySource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_EGD_H__
+#define BOTAN_ENTROPY_SRC_EGD_H__
+
+#include <botan/entropy_src.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* EGD Entropy Source
+*/
+class BOTAN_DLL EGD_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "EGD/PRNGD"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ EGD_EntropySource(const std::vector<std::string>&);
+ ~EGD_EntropySource();
+ private:
+ class EGD_Socket
+ {
+ public:
+ EGD_Socket(const std::string& path);
+
+ void close();
+ u32bit read(byte outbuf[], u32bit length);
+ private:
+ static int open_socket(const std::string& path);
+
+ std::string socket_path;
+ int m_fd; // cached fd
+ };
+
+ std::vector<EGD_Socket> sockets;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/egd/info.txt b/botan/src/entropy/egd/info.txt
new file mode 100644
index 0000000..85ba86c
--- /dev/null
+++ b/botan/src/entropy/egd/info.txt
@@ -0,0 +1,32 @@
+realname "EGD Entropy Source"
+
+define ENTROPY_SRC_EGD
+
+load_on auto
+modset unix
+
+<add>
+es_egd.h
+es_egd.cpp
+</add>
+
+<libs>
+solaris -> socket
+qnx -> socket
+</libs>
+
+<os>
+aix
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/botan/src/entropy/entropy_src.h b/botan/src/entropy/entropy_src.h
new file mode 100644
index 0000000..a1a53fa
--- /dev/null
+++ b/botan/src/entropy/entropy_src.h
@@ -0,0 +1,95 @@
+/**
+* EntropySource
+* (C) 2008-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SOURCE_BASE_H__
+#define BOTAN_ENTROPY_SOURCE_BASE_H__
+
+#include <botan/buf_comp.h>
+#include <string>
+#include <utility>
+
+namespace Botan {
+
+/**
+* Class used to accumulate the poll results of EntropySources
+*/
+class Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator(u32bit goal) :
+ entropy_goal(goal), collected_bits(0) {}
+
+ virtual ~Entropy_Accumulator() {}
+
+ /**
+ @return cached I/O buffer for repeated polls
+ */
+ MemoryRegion<byte>& get_io_buffer(u32bit size)
+ { io_buffer.create(size); return io_buffer; }
+
+ u32bit bits_collected() const
+ { return static_cast<u32bit>(collected_bits); }
+
+ bool polling_goal_achieved() const
+ { return (collected_bits >= entropy_goal); }
+
+ u32bit desired_remaining_bits() const
+ {
+ if(collected_bits >= entropy_goal)
+ return 0;
+ return static_cast<u32bit>(entropy_goal - collected_bits);
+ }
+
+ void add(const void* bytes, u32bit length, double entropy_bits_per_byte)
+ {
+ add_bytes(reinterpret_cast<const byte*>(bytes), length);
+ collected_bits += entropy_bits_per_byte * length;
+ }
+
+ template<typename T>
+ void add(const T& v, double entropy_bits_per_byte)
+ {
+ add(&v, sizeof(T), entropy_bits_per_byte);
+ }
+ private:
+ virtual void add_bytes(const byte bytes[], u32bit length) = 0;
+
+ SecureVector<byte> io_buffer;
+ u32bit entropy_goal;
+ double collected_bits;
+ };
+
+class Entropy_Accumulator_BufferedComputation : public Entropy_Accumulator
+ {
+ public:
+ Entropy_Accumulator_BufferedComputation(BufferedComputation& sink,
+ u32bit goal) :
+ Entropy_Accumulator(goal), entropy_sink(sink) {}
+
+ private:
+ virtual void add_bytes(const byte bytes[], u32bit length)
+ {
+ entropy_sink.update(bytes, length);
+ }
+
+ BufferedComputation& entropy_sink;
+ };
+
+/**
+* Abstract interface to a source of (hopefully unpredictable) system entropy
+*/
+class BOTAN_DLL EntropySource
+ {
+ public:
+ virtual std::string name() const = 0;
+ virtual void poll(Entropy_Accumulator& accum) = 0;
+ virtual ~EntropySource() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/info.txt b/botan/src/entropy/info.txt
new file mode 100644
index 0000000..ec3be5f
--- /dev/null
+++ b/botan/src/entropy/info.txt
@@ -0,0 +1,11 @@
+realname "Entropy Sources"
+
+load_on auto
+
+<add>
+entropy_src.h
+</add>
+
+<requires>
+buf_comp
+</requires>
diff --git a/botan/src/entropy/proc_walk/es_ftw.cpp b/botan/src/entropy/proc_walk/es_ftw.cpp
new file mode 100644
index 0000000..2016f09
--- /dev/null
+++ b/botan/src/entropy/proc_walk/es_ftw.cpp
@@ -0,0 +1,146 @@
+/*
+* FTW EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_ftw.h>
+#include <botan/secmem.h>
+#include <cstring>
+#include <deque>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+namespace Botan {
+
+namespace {
+
+class Directory_Walker : public FTW_EntropySource::File_Descriptor_Source
+ {
+ public:
+ Directory_Walker(const std::string& root) { add_directory(root); }
+ ~Directory_Walker();
+
+ int next_fd();
+ private:
+ void add_directory(const std::string&);
+
+ std::deque<std::pair<DIR*, std::string> > dirs;
+ };
+
+void Directory_Walker::add_directory(const std::string& dirname)
+ {
+ DIR* dir = ::opendir(dirname.c_str());
+ if(dir)
+ dirs.push_back(std::make_pair(dir, dirname));
+ }
+
+Directory_Walker::~Directory_Walker()
+ {
+ while(dirs.size())
+ {
+ ::closedir(dirs[0].first);
+ dirs.pop_front();
+ }
+ }
+
+int Directory_Walker::next_fd()
+ {
+ while(dirs.size())
+ {
+ std::pair<DIR*, std::string> dirinfo = dirs[0];
+
+ struct dirent* entry = ::readdir(dirinfo.first);
+
+ if(!entry)
+ {
+ ::closedir(dirinfo.first);
+ dirs.pop_front();
+ continue;
+ }
+
+ const std::string filename = entry->d_name;
+
+ if(filename == "." || filename == "..")
+ continue;
+
+ const std::string full_path = dirinfo.second + '/' + filename;
+
+ struct stat stat_buf;
+ if(::lstat(full_path.c_str(), &stat_buf) == -1)
+ continue;
+
+ if(S_ISDIR(stat_buf.st_mode))
+ add_directory(full_path);
+ else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH))
+ {
+ int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY);
+
+ if(fd > 0)
+ return fd;
+ }
+ }
+
+ return -1;
+ }
+
+}
+
+/**
+* FTW_EntropySource Constructor
+*/
+FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
+ {
+ dir = 0;
+ }
+
+/**
+* FTW_EntropySource Destructor
+*/
+FTW_EntropySource::~FTW_EntropySource()
+ {
+ delete dir;
+ }
+
+void FTW_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ const u32bit MAX_FILES_READ_PER_POLL = 1024;
+
+ if(!dir)
+ dir = new Directory_Walker(path);
+
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(128);
+
+ for(u32bit i = 0; i != MAX_FILES_READ_PER_POLL; ++i)
+ {
+ int fd = dir->next_fd();
+
+ // If we've exhaused this walk of the directory, halt the poll
+ if(fd == -1)
+ {
+ delete dir;
+ dir = 0;
+ break;
+ }
+
+ ssize_t got = ::read(fd, io_buffer.begin(), io_buffer.size());
+ ::close(fd);
+
+ if(got > 0)
+ accum.add(io_buffer.begin(), got, .01);
+
+ if(accum.polling_goal_achieved())
+ break;
+ }
+ }
+
+}
diff --git a/botan/src/entropy/proc_walk/es_ftw.h b/botan/src/entropy/proc_walk/es_ftw.h
new file mode 100644
index 0000000..928a7b1
--- /dev/null
+++ b/botan/src/entropy/proc_walk/es_ftw.h
@@ -0,0 +1,42 @@
+/*
+* File Tree Walking EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_FTW_H__
+#define BOTAN_ENTROPY_SRC_FTW_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* File Tree Walking Entropy Source
+*/
+class BOTAN_DLL FTW_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Proc Walker"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ FTW_EntropySource(const std::string& root_dir);
+ ~FTW_EntropySource();
+
+ class File_Descriptor_Source
+ {
+ public:
+ virtual int next_fd() = 0;
+ virtual ~File_Descriptor_Source() {}
+ };
+ private:
+
+ std::string path;
+ File_Descriptor_Source* dir;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/proc_walk/info.txt b/botan/src/entropy/proc_walk/info.txt
new file mode 100644
index 0000000..db96ccd
--- /dev/null
+++ b/botan/src/entropy/proc_walk/info.txt
@@ -0,0 +1,34 @@
+realname "File Tree Walking Entropy Source"
+
+define ENTROPY_SRC_FTW
+
+load_on auto
+modset unix
+
+<add>
+es_ftw.h
+es_ftw.cpp
+</add>
+
+<os>
+aix
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+openbsd
+qnx
+solaris
+tru64
+
+# Doesn't build on 2.0.2/x86 due to libc/libstdc++ header issues; no
+# big deal since it has /dev/*random
+#netbsd
+</os>
+
+<requires>
+alloc
+</requires>
diff --git a/botan/src/entropy/unix_procs/es_unix.cpp b/botan/src/entropy/unix_procs/es_unix.cpp
new file mode 100644
index 0000000..fc5b026
--- /dev/null
+++ b/botan/src/entropy/unix_procs/es_unix.cpp
@@ -0,0 +1,114 @@
+/*
+* Unix EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_unix.h>
+#include <botan/unix_cmd.h>
+#include <botan/parsing.h>
+#include <algorithm>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* Sort ordering by priority
+*/
+bool Unix_Program_Cmp(const Unix_Program& a, const Unix_Program& b)
+ { return (a.priority < b.priority); }
+
+}
+
+/**
+* Unix_EntropySource Constructor
+*/
+Unix_EntropySource::Unix_EntropySource(const std::vector<std::string>& path) :
+ PATH(path)
+ {
+ add_default_sources(sources);
+ }
+
+/**
+* Add sources to the list
+*/
+void Unix_EntropySource::add_sources(const Unix_Program srcs[], u32bit count)
+ {
+ sources.insert(sources.end(), srcs, srcs + count);
+ std::sort(sources.begin(), sources.end(), Unix_Program_Cmp);
+ }
+
+/**
+* Poll for entropy on a generic Unix system, first by grabbing various
+* statistics (stat on common files, getrusage, etc), and then, if more
+* is required, by exec'ing various programs like uname and rpcinfo and
+* reading the output.
+*/
+void Unix_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ const char* stat_targets[] = {
+ "/",
+ "/tmp",
+ "/var/tmp",
+ "/usr",
+ "/home",
+ "/etc/passwd",
+ ".",
+ "..",
+ 0 };
+
+ for(u32bit j = 0; stat_targets[j]; j++)
+ {
+ struct stat statbuf;
+ clear_mem(&statbuf, 1);
+ ::stat(stat_targets[j], &statbuf);
+ accum.add(&statbuf, sizeof(statbuf), .005);
+ }
+
+ accum.add(::getpid(), 0);
+ accum.add(::getppid(), 0);
+ accum.add(::getuid(), 0);
+ accum.add(::geteuid(), 0);
+ accum.add(::getegid(), 0);
+ accum.add(::getpgrp(), 0);
+ accum.add(::getsid(0), 0);
+
+ struct ::rusage usage;
+ ::getrusage(RUSAGE_SELF, &usage);
+ accum.add(usage, .005);
+
+ ::getrusage(RUSAGE_CHILDREN, &usage);
+ accum.add(usage, .005);
+
+ const u32bit MINIMAL_WORKING = 16;
+
+ MemoryRegion<byte>& io_buffer = accum.get_io_buffer(DEFAULT_BUFFERSIZE);
+
+ for(u32bit j = 0; j != sources.size(); j++)
+ {
+ DataSource_Command pipe(sources[j].name_and_args, PATH);
+
+ u32bit got_from_src = 0;
+
+ while(!pipe.end_of_data())
+ {
+ u32bit got_this_loop = pipe.read(io_buffer, io_buffer.size());
+ got_from_src += got_this_loop;
+
+ accum.add(io_buffer.begin(), got_this_loop, .005);
+ }
+
+ sources[j].working = (got_from_src >= MINIMAL_WORKING) ? true : false;
+
+ if(accum.polling_goal_achieved())
+ break;
+ }
+ }
+
+}
diff --git a/botan/src/entropy/unix_procs/es_unix.h b/botan/src/entropy/unix_procs/es_unix.h
new file mode 100644
index 0000000..1f8abb7
--- /dev/null
+++ b/botan/src/entropy/unix_procs/es_unix.h
@@ -0,0 +1,39 @@
+/*
+* Unix EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_UNIX_H__
+#define BOTAN_ENTROPY_SRC_UNIX_H__
+
+#include <botan/entropy_src.h>
+#include <botan/unix_cmd.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Unix Entropy Source
+*/
+class BOTAN_DLL Unix_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Unix Entropy Source"; }
+
+ void poll(Entropy_Accumulator& accum);
+
+ void add_sources(const Unix_Program[], u32bit);
+ Unix_EntropySource(const std::vector<std::string>& path);
+ private:
+ static void add_default_sources(std::vector<Unix_Program>&);
+ void fast_poll(Entropy_Accumulator& accum);
+
+ const std::vector<std::string> PATH;
+ std::vector<Unix_Program> sources;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/unix_procs/info.txt b/botan/src/entropy/unix_procs/info.txt
new file mode 100644
index 0000000..928ec13
--- /dev/null
+++ b/botan/src/entropy/unix_procs/info.txt
@@ -0,0 +1,33 @@
+realname "Generic Unix Entropy Source"
+
+define ENTROPY_SRC_UNIX
+modset unix,beos
+
+load_on auto
+
+<add>
+es_unix.cpp
+unix_src.cpp
+unix_cmd.cpp
+es_unix.h
+unix_cmd.h
+</add>
+
+<os>
+aix
+beos
+cygwin
+darwin
+#freebsd
+hpux
+irix
+linux
+netbsd
+qnx
+solaris
+tru64
+</os>
+
+<requires>
+filters
+</requires>
diff --git a/botan/src/entropy/unix_procs/unix_cmd.cpp b/botan/src/entropy/unix_procs/unix_cmd.cpp
new file mode 100644
index 0000000..1cae07e
--- /dev/null
+++ b/botan/src/entropy/unix_procs/unix_cmd.cpp
@@ -0,0 +1,236 @@
+/*
+* Unix Command Execution
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/unix_cmd.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* Attempt to execute the command
+*/
+void do_exec(const std::vector<std::string>& arg_list,
+ const std::vector<std::string>& paths)
+ {
+ const u32bit args = arg_list.size() - 1;
+
+ const char* arg1 = (args >= 1) ? arg_list[1].c_str() : 0;
+ const char* arg2 = (args >= 2) ? arg_list[2].c_str() : 0;
+ const char* arg3 = (args >= 3) ? arg_list[3].c_str() : 0;
+ const char* arg4 = (args >= 4) ? arg_list[4].c_str() : 0;
+
+ for(u32bit j = 0; j != paths.size(); j++)
+ {
+ const std::string full_path = paths[j] + "/" + arg_list[0];
+ const char* fsname = full_path.c_str();
+ ::execl(fsname, fsname, arg1, arg2, arg3, arg4, NULL);
+ }
+ }
+
+}
+
+/**
+* Local information about the pipe
+*/
+struct pipe_wrapper
+ {
+ int fd;
+ pid_t pid;
+ pipe_wrapper() { fd = -1; pid = 0; }
+ };
+
+/**
+* Read from the pipe
+*/
+u32bit DataSource_Command::read(byte buf[], u32bit length)
+ {
+ if(end_of_data())
+ return 0;
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(pipe->fd, &set);
+
+ struct ::timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = MAX_BLOCK_USECS;
+
+ ssize_t got = 0;
+ if(::select(pipe->fd + 1, &set, 0, 0, &tv) == 1)
+ {
+ if(FD_ISSET(pipe->fd, &set))
+ got = ::read(pipe->fd, buf, length);
+ }
+
+ if(got <= 0)
+ {
+ shutdown_pipe();
+ return 0;
+ }
+
+ return static_cast<u32bit>(got);
+ }
+
+/**
+* Peek at the pipe contents
+*/
+u32bit DataSource_Command::peek(byte[], u32bit, u32bit) const
+ {
+ if(end_of_data())
+ throw Invalid_State("DataSource_Command: Cannot peek when out of data");
+ throw Stream_IO_Error("Cannot peek/seek on a command pipe");
+ }
+
+/**
+* Check if we reached EOF
+*/
+bool DataSource_Command::end_of_data() const
+ {
+ return (pipe) ? false : true;
+ }
+
+/**
+* Return the Unix file descriptor of the pipe
+*/
+int DataSource_Command::fd() const
+ {
+ if(!pipe)
+ return -1;
+ return pipe->fd;
+ }
+
+/**
+* Return a human-readable ID for this stream
+*/
+std::string DataSource_Command::id() const
+ {
+ return "Unix command: " + arg_list[0];
+ }
+
+/**
+* Create the pipe
+*/
+void DataSource_Command::create_pipe(const std::vector<std::string>& paths)
+ {
+ bool found_something = false;
+ for(u32bit j = 0; j != paths.size(); j++)
+ {
+ const std::string full_path = paths[j] + "/" + arg_list[0];
+ if(::access(full_path.c_str(), X_OK) == 0)
+ {
+ found_something = true;
+ break;
+ }
+ }
+ if(!found_something)
+ return;
+
+ int pipe_fd[2];
+ if(::pipe(pipe_fd) != 0)
+ return;
+
+ pid_t pid = ::fork();
+
+ if(pid == -1)
+ {
+ ::close(pipe_fd[0]);
+ ::close(pipe_fd[1]);
+ }
+ else if(pid > 0)
+ {
+ pipe = new pipe_wrapper;
+ pipe->fd = pipe_fd[0];
+ pipe->pid = pid;
+ ::close(pipe_fd[1]);
+ }
+ else
+ {
+ if(dup2(pipe_fd[1], STDOUT_FILENO) == -1)
+ ::exit(127);
+ if(close(pipe_fd[0]) != 0 || close(pipe_fd[1]) != 0)
+ ::exit(127);
+ if(close(STDERR_FILENO) != 0)
+ ::exit(127);
+
+ do_exec(arg_list, paths);
+ ::exit(127);
+ }
+ }
+
+/**
+* Shutdown the pipe
+*/
+void DataSource_Command::shutdown_pipe()
+ {
+ if(pipe)
+ {
+ pid_t reaped = waitpid(pipe->pid, 0, WNOHANG);
+
+ if(reaped == 0)
+ {
+ kill(pipe->pid, SIGTERM);
+
+ struct ::timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = KILL_WAIT;
+ select(0, 0, 0, 0, &tv);
+
+ reaped = ::waitpid(pipe->pid, 0, WNOHANG);
+
+ if(reaped == 0)
+ {
+ ::kill(pipe->pid, SIGKILL);
+ do
+ reaped = ::waitpid(pipe->pid, 0, 0);
+ while(reaped == -1);
+ }
+ }
+
+ ::close(pipe->fd);
+ delete pipe;
+ pipe = 0;
+ }
+ }
+
+/**
+* DataSource_Command Constructor
+*/
+DataSource_Command::DataSource_Command(const std::string& prog_and_args,
+ const std::vector<std::string>& paths) :
+ MAX_BLOCK_USECS(100000), KILL_WAIT(10000)
+ {
+ arg_list = split_on(prog_and_args, ' ');
+
+ if(arg_list.size() == 0)
+ throw Invalid_Argument("DataSource_Command: No command given");
+ if(arg_list.size() > 5)
+ throw Invalid_Argument("DataSource_Command: Too many args");
+
+ pipe = 0;
+ create_pipe(paths);
+ }
+
+/**
+* DataSource_Command Destructor
+*/
+DataSource_Command::~DataSource_Command()
+ {
+ if(!end_of_data())
+ shutdown_pipe();
+ }
+
+}
diff --git a/botan/src/entropy/unix_procs/unix_cmd.h b/botan/src/entropy/unix_procs/unix_cmd.h
new file mode 100644
index 0000000..aec1891
--- /dev/null
+++ b/botan/src/entropy/unix_procs/unix_cmd.h
@@ -0,0 +1,59 @@
+/**
+* Unix Command Execution
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UNIX_CMD_H__
+#define BOTAN_UNIX_CMD_H__
+
+#include <botan/types.h>
+#include <botan/data_src.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Unix Program Info
+*/
+struct Unix_Program
+ {
+ Unix_Program(const char* n, u32bit p)
+ { name_and_args = n; priority = p; working = true; }
+
+ std::string name_and_args;
+ u32bit priority;
+ bool working;
+ };
+
+/**
+* Command Output DataSource
+*/
+class BOTAN_DLL DataSource_Command : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+ std::string id() const;
+
+ int fd() const;
+
+ DataSource_Command(const std::string&,
+ const std::vector<std::string>& paths);
+ ~DataSource_Command();
+ private:
+ void create_pipe(const std::vector<std::string>&);
+ void shutdown_pipe();
+
+ const u32bit MAX_BLOCK_USECS, KILL_WAIT;
+
+ std::vector<std::string> arg_list;
+ struct pipe_wrapper* pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/unix_procs/unix_src.cpp b/botan/src/entropy/unix_procs/unix_src.cpp
new file mode 100644
index 0000000..c843af6
--- /dev/null
+++ b/botan/src/entropy/unix_procs/unix_src.cpp
@@ -0,0 +1,61 @@
+/*
+* Program List for Unix_EntropySource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_unix.h>
+
+namespace Botan {
+
+/**
+* Default Commands for Entropy Gathering
+*/
+void Unix_EntropySource::add_default_sources(std::vector<Unix_Program>& srcs)
+ {
+ srcs.push_back(Unix_Program("vmstat", 1));
+ srcs.push_back(Unix_Program("vmstat -s", 1));
+ srcs.push_back(Unix_Program("pfstat", 1));
+ srcs.push_back(Unix_Program("netstat -in", 1));
+
+ srcs.push_back(Unix_Program("iostat", 2));
+ srcs.push_back(Unix_Program("mpstat", 2));
+ srcs.push_back(Unix_Program("nfsstat", 2));
+ srcs.push_back(Unix_Program("portstat", 2));
+ srcs.push_back(Unix_Program("arp -a -n", 2));
+ srcs.push_back(Unix_Program("ifconfig -a", 2));
+ srcs.push_back(Unix_Program("pstat -T", 2));
+ srcs.push_back(Unix_Program("pstat -s", 2));
+ srcs.push_back(Unix_Program("uname -a", 2));
+ srcs.push_back(Unix_Program("uptime", 2));
+ srcs.push_back(Unix_Program("ipcs -a", 2));
+ srcs.push_back(Unix_Program("procinfo -a", 2));
+
+ srcs.push_back(Unix_Program("sysinfo", 3));
+ srcs.push_back(Unix_Program("listarea", 3));
+ srcs.push_back(Unix_Program("listdev", 3));
+
+ srcs.push_back(Unix_Program("who", 3));
+ srcs.push_back(Unix_Program("finger", 3));
+ srcs.push_back(Unix_Program("netstat -s", 3));
+ srcs.push_back(Unix_Program("netstat -an", 3));
+ srcs.push_back(Unix_Program("ps -A", 3));
+ srcs.push_back(Unix_Program("mailstats", 3));
+ srcs.push_back(Unix_Program("rpcinfo -p localhost", 3));
+
+ srcs.push_back(Unix_Program("dmesg", 4));
+ srcs.push_back(Unix_Program("ls -alni /tmp", 4));
+ srcs.push_back(Unix_Program("ls -alni /proc", 4));
+ srcs.push_back(Unix_Program("df -l", 4));
+ srcs.push_back(Unix_Program("last -5", 4));
+ srcs.push_back(Unix_Program("pstat -f", 4));
+
+ srcs.push_back(Unix_Program("ps aux", 5));
+ srcs.push_back(Unix_Program("ps -elf", 5));
+
+ srcs.push_back(Unix_Program("sar -A", 6));
+ srcs.push_back(Unix_Program("lsof", 6));
+ }
+
+}
diff --git a/botan/src/entropy/win32_stats/es_win32.cpp b/botan/src/entropy/win32_stats/es_win32.cpp
new file mode 100644
index 0000000..a8e9e40
--- /dev/null
+++ b/botan/src/entropy/win32_stats/es_win32.cpp
@@ -0,0 +1,118 @@
+/**
+* Win32 EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/es_win32.h>
+#include <windows.h>
+#include <tlhelp32.h>
+
+namespace Botan {
+
+/**
+* Win32 poll using stats functions including Tooltip32
+*/
+void Win32_EntropySource::poll(Entropy_Accumulator& accum)
+ {
+ /*
+ First query a bunch of basic statistical stuff, though
+ don't count it for much in terms of contributed entropy.
+ */
+ accum.add(GetTickCount(), 0);
+ accum.add(GetMessagePos(), 0);
+ accum.add(GetMessageTime(), 0);
+ accum.add(GetInputState(), 0);
+ accum.add(GetCurrentProcessId(), 0);
+ accum.add(GetCurrentThreadId(), 0);
+
+ SYSTEM_INFO sys_info;
+ GetSystemInfo(&sys_info);
+ accum.add(sys_info, 1);
+
+ MEMORYSTATUS mem_info;
+ GlobalMemoryStatus(&mem_info);
+ accum.add(mem_info, 1);
+
+ POINT point;
+ GetCursorPos(&point);
+ accum.add(point, 1);
+
+ GetCaretPos(&point);
+ accum.add(point, 1);
+
+ LARGE_INTEGER perf_counter;
+ QueryPerformanceCounter(&perf_counter);
+ accum.add(perf_counter, 0);
+
+ /*
+ Now use the Tooltip library to iterate throug various objects on
+ the system, including processes, threads, and heap objects.
+ */
+
+ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
+
+#define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \
+ if(!accum.polling_goal_achieved()) \
+ { \
+ DATA_TYPE info; \
+ info.dwSize = sizeof(DATA_TYPE); \
+ if(FUNC_FIRST(snapshot, &info)) \
+ { \
+ do \
+ { \
+ accum.add(info, 1); \
+ } while(FUNC_NEXT(snapshot, &info)); \
+ } \
+ }
+
+ TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next);
+ TOOLHELP32_ITER(PROCESSENTRY32, Process32First, Process32Next);
+ TOOLHELP32_ITER(THREADENTRY32, Thread32First, Thread32Next);
+
+#undef TOOLHELP32_ITER
+
+ if(!accum.polling_goal_achieved())
+ {
+ u32bit heap_lists_found = 0;
+ HEAPLIST32 heap_list;
+ heap_list.dwSize = sizeof(HEAPLIST32);
+
+ const u32bit HEAP_LISTS_MAX = 32;
+ const u32bit HEAP_OBJS_PER_LIST = 128;
+
+ if(Heap32ListFirst(snapshot, &heap_list))
+ {
+ do
+ {
+ accum.add(heap_list, 1);
+
+ if(++heap_lists_found > HEAP_LISTS_MAX)
+ break;
+
+ u32bit heap_objs_found = 0;
+ HEAPENTRY32 heap_entry;
+ heap_entry.dwSize = sizeof(HEAPENTRY32);
+ if(Heap32First(&heap_entry, heap_list.th32ProcessID,
+ heap_list.th32HeapID))
+ {
+ do
+ {
+ if(heap_objs_found++ > HEAP_OBJS_PER_LIST)
+ break;
+ accum.add(heap_entry, 1);
+ } while(Heap32Next(&heap_entry));
+ }
+
+ if(accum.polling_goal_achieved())
+ break;
+
+ } while(Heap32ListNext(snapshot, &heap_list));
+ }
+ }
+
+ CloseHandle(snapshot);
+ }
+
+}
diff --git a/botan/src/entropy/win32_stats/es_win32.h b/botan/src/entropy/win32_stats/es_win32.h
new file mode 100644
index 0000000..0aa9054
--- /dev/null
+++ b/botan/src/entropy/win32_stats/es_win32.h
@@ -0,0 +1,27 @@
+/**
+* Win32 EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_WIN32_H__
+#define BOTAN_ENTROPY_SRC_WIN32_H__
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Win32 Entropy Source
+*/
+class BOTAN_DLL Win32_EntropySource : public EntropySource
+ {
+ public:
+ std::string name() const { return "Win32 Statistics"; }
+ void poll(Entropy_Accumulator& accum);
+ };
+
+}
+
+#endif
diff --git a/botan/src/entropy/win32_stats/info.txt b/botan/src/entropy/win32_stats/info.txt
new file mode 100644
index 0000000..ca71009
--- /dev/null
+++ b/botan/src/entropy/win32_stats/info.txt
@@ -0,0 +1,24 @@
+realname "Win32 Entropy Source"
+
+# Probably not much of an issue anymore
+#note "This module will not run under NT4"
+
+define ENTROPY_SRC_WIN32
+modset win32
+
+load_on auto
+
+<add>
+es_win32.h
+es_win32.cpp
+</add>
+
+<os>
+windows
+cygwin
+mingw
+</os>
+
+<libs>
+windows -> user32.lib
+</libs>
diff --git a/botan/src/filters/algo_filt.cpp b/botan/src/filters/algo_filt.cpp
new file mode 100644
index 0000000..23f7a20
--- /dev/null
+++ b/botan/src/filters/algo_filt.cpp
@@ -0,0 +1,124 @@
+/*
+* Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/filters.h>
+#include <botan/libstate.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = cipher = af.make_stream_cipher(sc_name);
+ }
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ base_ptr = cipher = stream_cipher;
+ }
+
+/*
+* StreamCipher_Filter Constructor
+*/
+StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name,
+ const SymmetricKey& key) :
+ buffer(DEFAULT_BUFFERSIZE)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = cipher = af.make_stream_cipher(sc_name);
+ cipher->set_key(key);
+ }
+
+/*
+* Set the IV of a stream cipher
+*/
+void StreamCipher_Filter::set_iv(const InitializationVector& iv)
+ {
+ cipher->resync(iv.begin(), iv.length());
+ }
+
+/*
+* Write data into a StreamCipher_Filter
+*/
+void StreamCipher_Filter::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit copied = std::min(length, buffer.size());
+ cipher->encrypt(input, buffer, copied);
+ send(buffer, copied);
+ input += copied;
+ length -= copied;
+ }
+ }
+
+/*
+* Hash_Filter Constructor
+*/
+Hash_Filter::Hash_Filter(const std::string& algo_spec,
+ u32bit len) :
+ OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ hash = af.make_hash_function(algo_spec);
+ }
+
+/*
+* Complete a calculation by a Hash_Filter
+*/
+void Hash_Filter::end_msg()
+ {
+ SecureVector<byte> output = hash->final();
+ if(OUTPUT_LENGTH)
+ send(output, std::min(OUTPUT_LENGTH, output.size()));
+ else
+ send(output);
+ }
+
+/*
+* MAC_Filter Constructor
+*/
+MAC_Filter::MAC_Filter(const std::string& mac_name, u32bit len) :
+ OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = mac = af.make_mac(mac_name);
+ }
+
+/*
+* MAC_Filter Constructor
+*/
+MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key,
+ u32bit len) : OUTPUT_LENGTH(len)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ base_ptr = mac = af.make_mac(mac_name);
+ mac->set_key(key);
+ }
+
+/*
+* Complete a calculation by a MAC_Filter
+*/
+void MAC_Filter::end_msg()
+ {
+ SecureVector<byte> output = mac->final();
+ if(OUTPUT_LENGTH)
+ send(output, std::min(OUTPUT_LENGTH, output.size()));
+ else
+ send(output);
+ }
+
+}
diff --git a/botan/src/filters/basefilt.cpp b/botan/src/filters/basefilt.cpp
new file mode 100644
index 0000000..02dbd8a
--- /dev/null
+++ b/botan/src/filters/basefilt.cpp
@@ -0,0 +1,74 @@
+/*
+* Basic Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/basefilt.h>
+
+namespace Botan {
+
+/*
+* Chain Constructor
+*/
+Chain::Chain(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ if(f1) { attach(f1); incr_owns(); }
+ if(f2) { attach(f2); incr_owns(); }
+ if(f3) { attach(f3); incr_owns(); }
+ if(f4) { attach(f4); incr_owns(); }
+ }
+
+/*
+* Chain Constructor
+*/
+Chain::Chain(Filter* filters[], u32bit count)
+ {
+ for(u32bit j = 0; j != count; ++j)
+ if(filters[j])
+ {
+ attach(filters[j]);
+ incr_owns();
+ }
+ }
+
+/*
+* Fork Constructor
+*/
+Fork::Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ Filter* filters[4] = { f1, f2, f3, f4 };
+ set_next(filters, 4);
+ }
+
+/*
+* Fork Constructor
+*/
+Fork::Fork(Filter* filters[], u32bit count)
+ {
+ set_next(filters, count);
+ }
+
+/*
+* Set the algorithm key
+*/
+void Keyed_Filter::set_key(const SymmetricKey& key)
+ {
+ if(base_ptr)
+ base_ptr->set_key(key);
+ else
+ throw Invalid_State("Keyed_Filter::set_key: No base algorithm set");
+ }
+
+/*
+* Check if a keylength is valid
+*/
+bool Keyed_Filter::valid_keylength(u32bit n) const
+ {
+ if(base_ptr)
+ return base_ptr->valid_keylength(n);
+ throw Invalid_State("Keyed_Filter::valid_keylength: No base algorithm set");
+ }
+
+}
diff --git a/botan/src/filters/basefilt.h b/botan/src/filters/basefilt.h
new file mode 100644
index 0000000..75625ab
--- /dev/null
+++ b/botan/src/filters/basefilt.h
@@ -0,0 +1,99 @@
+/*
+* Basic Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BASEFILT_H__
+#define BOTAN_BASEFILT_H__
+
+#include <botan/filter.h>
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/**
+* This class represents Filter chains. A Filter chain is an ordered
+* concatenation of Filters, the input to a Chain sequentially passes
+* through all the Filters contained in the Chain.
+*/
+
+class BOTAN_DLL Chain : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+
+ /**
+ * Construct a chain of up to four filters. The filters are set
+ * up in the same order as the arguments.
+ */
+ Chain(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a chain from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Chain(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents a fork filter, whose purpose is to fork the
+* flow of data. It causes an input message to result in n messages at
+* the end of the filter, where n is the number of forks.
+*/
+class BOTAN_DLL Fork : public Fanout_Filter
+ {
+ public:
+ void write(const byte input[], u32bit length) { send(input, length); }
+ void set_port(u32bit n) { Fanout_Filter::set_port(n); }
+
+ /**
+ * Construct a Fork filter with up to four forks.
+ */
+ Fork(Filter*, Filter*, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Fork from range of filters
+ * @param filter_arr the list of filters
+ * @param length how many filters
+ */
+ Fork(Filter* filter_arr[], u32bit length);
+ };
+
+/**
+* This class represents keyed filters, i.e. filters that have to be
+* fed with a key in order to function.
+*/
+class BOTAN_DLL Keyed_Filter : public Filter
+ {
+ public:
+
+ /**
+ * Set the key of this filter.
+ * @param key the key to set
+ */
+ virtual void set_key(const SymmetricKey& key);
+
+ /**
+ * Set the initialization vector of this filter.
+ * @param iv the initialization vector to set
+ */
+ virtual void set_iv(const InitializationVector&) {}
+
+ /**
+ * Check whether a key length is valid for this filter.
+ * @param length the key length to be checked for validity
+ * @return true if the key length is valid, false otherwise
+ */
+ virtual bool valid_keylength(u32bit length) const;
+
+ Keyed_Filter() { base_ptr = 0; }
+ protected:
+ SymmetricAlgorithm* base_ptr;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/buf_filt.cpp b/botan/src/filters/buf_filt.cpp
new file mode 100644
index 0000000..53352b5
--- /dev/null
+++ b/botan/src/filters/buf_filt.cpp
@@ -0,0 +1,71 @@
+/*
+* Buffering Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/buf_filt.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Buffering_Filter Constructor
+*/
+Buffering_Filter::Buffering_Filter(u32bit b, u32bit i) : INITIAL_BLOCK_SIZE(i),
+ BLOCK_SIZE(b)
+ {
+ initial_block_pos = block_pos = 0;
+ initial.create(INITIAL_BLOCK_SIZE);
+ block.create(BLOCK_SIZE);
+ }
+
+/*
+* Reset the Buffering Filter
+*/
+void Buffering_Filter::end_msg()
+ {
+ if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ throw Exception("Buffering_Filter: Not enough data for first block");
+ final_block(block, block_pos);
+ initial_block_pos = block_pos = 0;
+ initial.clear();
+ block.clear();
+ }
+
+/*
+* Buffer input into blocks
+*/
+void Buffering_Filter::write(const byte input[], u32bit length)
+ {
+ if(initial_block_pos != INITIAL_BLOCK_SIZE)
+ {
+ u32bit copied = std::min(INITIAL_BLOCK_SIZE - initial_block_pos, length);
+ initial.copy(initial_block_pos, input, copied);
+ input += copied;
+ length -= copied;
+ initial_block_pos += copied;
+ if(initial_block_pos == INITIAL_BLOCK_SIZE)
+ initial_block(initial);
+ }
+ block.copy(block_pos, input, length);
+ if(block_pos + length >= BLOCK_SIZE)
+ {
+ main_block(block);
+ input += (BLOCK_SIZE - block_pos);
+ length -= (BLOCK_SIZE - block_pos);
+ while(length >= BLOCK_SIZE)
+ {
+ main_block(input);
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ }
+ block.copy(input, length);
+ block_pos = 0;
+ }
+ block_pos += length;
+ }
+
+}
diff --git a/botan/src/filters/buf_filt.h b/botan/src/filters/buf_filt.h
new file mode 100644
index 0000000..ce3dbc9
--- /dev/null
+++ b/botan/src/filters/buf_filt.h
@@ -0,0 +1,39 @@
+/*
+* Buffering Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BUFFERING_FILTER_H__
+#define BOTAN_BUFFERING_FILTER_H__
+
+#include <botan/filter.h>
+
+namespace Botan {
+
+/**
+* Buffering_Filter: This class represents filters for operations that
+* maintain an internal state.
+*/
+
+class BOTAN_DLL Buffering_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ virtual void end_msg();
+ Buffering_Filter(u32bit, u32bit = 0);
+ virtual ~Buffering_Filter() {}
+ protected:
+ virtual void initial_block(const byte[]) {}
+ virtual void main_block(const byte[]) = 0;
+ virtual void final_block(const byte[], u32bit) = 0;
+ private:
+ const u32bit INITIAL_BLOCK_SIZE, BLOCK_SIZE;
+ SecureVector<byte> initial, block;
+ u32bit initial_block_pos, block_pos;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/data_snk.cpp b/botan/src/filters/data_snk.cpp
new file mode 100644
index 0000000..f8ee9f8
--- /dev/null
+++ b/botan/src/filters/data_snk.cpp
@@ -0,0 +1,62 @@
+/*
+* DataSink
+* (C) 1999-2007 Jack Lloyd
+* 2005 Matthew Gregan
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/data_snk.h>
+#include <botan/exceptn.h>
+#include <fstream>
+
+namespace Botan {
+
+/*
+* Write to a stream
+*/
+void DataSink_Stream::write(const byte out[], u32bit length)
+ {
+ sink->write(reinterpret_cast<const char*>(out), length);
+ if(!sink->good())
+ throw Stream_IO_Error("DataSink_Stream: Failure writing to " +
+ identifier);
+ }
+
+/*
+* DataSink_Stream Constructor
+*/
+DataSink_Stream::DataSink_Stream(std::ostream& out,
+ const std::string& name) :
+ identifier(name != "" ? name : "<std::ostream>"), owner(false)
+ {
+ sink = &out;
+ }
+
+/*
+* DataSink_Stream Constructor
+*/
+DataSink_Stream::DataSink_Stream(const std::string& path,
+ bool use_binary) :
+ identifier(path), owner(true)
+ {
+ if(use_binary)
+ sink = new std::ofstream(path.c_str(), std::ios::binary);
+ else
+ sink = new std::ofstream(path.c_str());
+
+ if(!sink->good())
+ throw Stream_IO_Error("DataSink_Stream: Failure opening " + path);
+ }
+
+/*
+* DataSink_Stream Destructor
+*/
+DataSink_Stream::~DataSink_Stream()
+ {
+ if(owner)
+ delete sink;
+ sink = 0;
+ }
+
+}
diff --git a/botan/src/filters/data_snk.h b/botan/src/filters/data_snk.h
new file mode 100644
index 0000000..61ddf6e
--- /dev/null
+++ b/botan/src/filters/data_snk.h
@@ -0,0 +1,65 @@
+/*
+* DataSink
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_SINK_H__
+#define BOTAN_DATA_SINK_H__
+
+#include <botan/filter.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents abstract data sink objects.
+*/
+class BOTAN_DLL DataSink : public Filter
+ {
+ public:
+ bool attachable() { return false; }
+ DataSink() {}
+ virtual ~DataSink() {}
+ private:
+ DataSink& operator=(const DataSink&) { return (*this); }
+ DataSink(const DataSink&);
+ };
+
+/**
+* This class represents a data sink which writes its output to a stream.
+*/
+class BOTAN_DLL DataSink_Stream : public DataSink
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param stream the stream to write to
+ * @param name identifier
+ */
+ DataSink_Stream(std::ostream& stream,
+ const std::string& name = "");
+
+ /**
+ * Construct a DataSink_Stream from a stream.
+ * @param file the name of the file to open a stream to
+ * @param use_binary indicates whether to treat the file
+ * as a binary file or not
+ */
+ DataSink_Stream(const std::string& filename,
+ bool use_binary = false);
+
+ ~DataSink_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::ostream* sink;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/data_src.cpp b/botan/src/filters/data_src.cpp
new file mode 100644
index 0000000..e6387c4
--- /dev/null
+++ b/botan/src/filters/data_src.cpp
@@ -0,0 +1,207 @@
+/*
+* DataSource
+* (C) 1999-2007 Jack Lloyd
+* 2005 Matthew Gregan
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/data_src.h>
+#include <botan/exceptn.h>
+
+#include <fstream>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Read a single byte from the DataSource
+*/
+u32bit DataSource::read_byte(byte& out)
+ {
+ return read(&out, 1);
+ }
+
+/*
+* Peek a single byte from the DataSource
+*/
+u32bit DataSource::peek_byte(byte& out) const
+ {
+ return peek(&out, 1, 0);
+ }
+
+/*
+* Discard the next N bytes of the data
+*/
+u32bit DataSource::discard_next(u32bit n)
+ {
+ u32bit discarded = 0;
+ byte dummy;
+ for(u32bit j = 0; j != n; ++j)
+ discarded += read_byte(dummy);
+ return discarded;
+ }
+
+/*
+* Read from a memory buffer
+*/
+u32bit DataSource_Memory::read(byte out[], u32bit length)
+ {
+ u32bit got = std::min(source.size() - offset, length);
+ copy_mem(out, source + offset, got);
+ offset += got;
+ return got;
+ }
+
+/*
+* Peek into a memory buffer
+*/
+u32bit DataSource_Memory::peek(byte out[], u32bit length,
+ u32bit peek_offset) const
+ {
+ const u32bit bytes_left = source.size() - offset;
+ if(peek_offset >= bytes_left) return 0;
+
+ u32bit got = std::min(bytes_left - peek_offset, length);
+ copy_mem(out, source + offset + peek_offset, got);
+ return got;
+ }
+
+/*
+* Check if the memory buffer is empty
+*/
+bool DataSource_Memory::end_of_data() const
+ {
+ return (offset == source.size());
+ }
+
+/*
+* DataSource_Memory Constructor
+*/
+DataSource_Memory::DataSource_Memory(const byte in[], u32bit length)
+ {
+ source.set(in, length);
+ offset = 0;
+ }
+
+/*
+* DataSource_Memory Constructor
+*/
+DataSource_Memory::DataSource_Memory(const MemoryRegion<byte>& in)
+ {
+ source = in;
+ offset = 0;
+ }
+
+/*
+* DataSource_Memory Constructor
+*/
+DataSource_Memory::DataSource_Memory(const std::string& in)
+ {
+ source.set(reinterpret_cast<const byte*>(in.data()), in.length());
+ offset = 0;
+ }
+
+/*
+* Read from a stream
+*/
+u32bit DataSource_Stream::read(byte out[], u32bit length)
+ {
+ source->read(reinterpret_cast<char*>(out), length);
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::read: Source failure");
+
+ u32bit got = source->gcount();
+ total_read += got;
+ return got;
+ }
+
+/*
+* Peek into a stream
+*/
+u32bit DataSource_Stream::peek(byte out[], u32bit length, u32bit offset) const
+ {
+ if(end_of_data())
+ throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
+
+ u32bit got = 0;
+
+ if(offset)
+ {
+ SecureVector<byte> buf(offset);
+ source->read(reinterpret_cast<char*>(buf.begin()), buf.size());
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
+ got = source->gcount();
+ }
+
+ if(got == offset)
+ {
+ source->read(reinterpret_cast<char*>(out), length);
+ if(source->bad())
+ throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
+ got = source->gcount();
+ }
+
+ if(source->eof())
+ source->clear();
+ source->seekg(total_read, std::ios::beg);
+
+ return got;
+ }
+
+/*
+* Check if the stream is empty or in error
+*/
+bool DataSource_Stream::end_of_data() const
+ {
+ return (!source->good());
+ }
+
+/*
+* Return a human-readable ID for this stream
+*/
+std::string DataSource_Stream::id() const
+ {
+ return identifier;
+ }
+
+/*
+* DataSource_Stream Constructor
+*/
+DataSource_Stream::DataSource_Stream(const std::string& path,
+ bool use_binary) :
+ identifier(path), owner(true)
+ {
+ if(use_binary)
+ source = new std::ifstream(path.c_str(), std::ios::binary);
+ else
+ source = new std::ifstream(path.c_str());
+
+ if(!source->good())
+ throw Stream_IO_Error("DataSource: Failure opening file " + path);
+
+ total_read = 0;
+ }
+
+/*
+* DataSource_Stream Constructor
+*/
+DataSource_Stream::DataSource_Stream(std::istream& in,
+ const std::string& name) :
+ identifier(name), owner(false)
+ {
+ source = &in;
+ total_read = 0;
+ }
+
+/*
+* DataSource_Stream Destructor
+*/
+DataSource_Stream::~DataSource_Stream()
+ {
+ if(owner)
+ delete source;
+ }
+
+}
diff --git a/botan/src/filters/data_src.h b/botan/src/filters/data_src.h
new file mode 100644
index 0000000..e16217e
--- /dev/null
+++ b/botan/src/filters/data_src.h
@@ -0,0 +1,150 @@
+/*
+* DataSource
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_SRC_H__
+#define BOTAN_DATA_SRC_H__
+
+#include <botan/secmem.h>
+#include <string>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents an abstract data source object.
+*/
+class BOTAN_DLL DataSource
+ {
+ public:
+ /**
+ * Read from the source. Moves the internal offset so that
+ * every call to read will return a new portion of the source.
+ * @param out the byte array to write the result to
+ * @param length the length of the byte array out
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ virtual u32bit read(byte out[], u32bit length) = 0;
+
+ /**
+ * Read from the source but do not modify the internal offset. Consecutive
+ * calls to peek() will return portions of the source starting at the same
+ * position.
+ * @param out the byte array to write the output to
+ * @param length the length of the byte array out
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ virtual u32bit peek(byte out[], u32bit length,
+ u32bit peek_offset) const = 0;
+
+ /**
+ * Test whether the source still has data that can be read.
+ * @return true if there is still data to read, false otherwise
+ */
+ virtual bool end_of_data() const = 0;
+ /**
+ * return the id of this data source
+ * @return the std::string representing the id of this data source
+ */
+ virtual std::string id() const { return ""; }
+
+ /**
+ * Read one byte.
+ * @param the byte to read to
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ u32bit read_byte(byte& out);
+
+ /**
+ * Peek at one byte.
+ * @param the byte to read to
+ * @return the length in bytes that was actually read and put
+ * into out
+ */
+ u32bit peek_byte(byte& out) const;
+
+ /**
+ * Discard the next N bytes of the data
+ * @param N the number of bytes to discard
+ * @return the number of bytes actually discarded
+ */
+ u32bit discard_next(u32bit N);
+
+ DataSource() {}
+ virtual ~DataSource() {}
+ private:
+ DataSource& operator=(const DataSource&) { return (*this); }
+ DataSource(const DataSource&);
+ };
+
+/**
+* This class represents a Memory-Based DataSource
+*/
+class BOTAN_DLL DataSource_Memory : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+
+ /**
+ * Construct a memory source that reads from a string
+ * @param in the string to read from
+ */
+ DataSource_Memory(const std::string& in);
+
+ /**
+ * Construct a memory source that reads from a byte array
+ * @param in the byte array to read from
+ * @param length the length of the byte array
+ */
+ DataSource_Memory(const byte in[], u32bit length);
+
+ /**
+ * Construct a memory source that reads from a MemoryRegion
+ * @param in the MemoryRegion to read from
+ */
+ DataSource_Memory(const MemoryRegion<byte>& in);
+ private:
+ SecureVector<byte> source;
+ u32bit offset;
+ };
+
+/**
+* This class represents a Stream-Based DataSource.
+*/
+class BOTAN_DLL DataSource_Stream : public DataSource
+ {
+ public:
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit) const;
+ bool end_of_data() const;
+ std::string id() const;
+
+ DataSource_Stream(std::istream&, const std::string& id = "");
+
+ /**
+ * Construct a Stream-Based DataSource from file
+ * @param file the name of the file
+ * @param use_binary whether to treat the file as binary or not
+ */
+ DataSource_Stream(const std::string& file, bool use_binary = false);
+
+ ~DataSource_Stream();
+ private:
+ const std::string identifier;
+ const bool owner;
+
+ std::istream* source;
+ u32bit total_read;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/fd_unix/fd_unix.cpp b/botan/src/filters/fd_unix/fd_unix.cpp
new file mode 100644
index 0000000..7f19b0a
--- /dev/null
+++ b/botan/src/filters/fd_unix/fd_unix.cpp
@@ -0,0 +1,53 @@
+/*
+* Pipe I/O for Unix
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/exceptn.h>
+#include <unistd.h>
+
+namespace Botan {
+
+/*
+* Write data from a pipe into a Unix fd
+*/
+int operator<<(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ u32bit position = 0;
+ while(got)
+ {
+ ssize_t ret = write(fd, buffer + position, got);
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe output operator (unixfd) has failed");
+ position += ret;
+ got -= ret;
+ }
+ }
+ return fd;
+ }
+
+/*
+* Read data from a Unix fd into a pipe
+*/
+int operator>>(int fd, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(true)
+ {
+ ssize_t ret = read(fd, buffer, buffer.size());
+ if(ret == 0) break;
+ if(ret == -1)
+ throw Stream_IO_Error("Pipe input operator (unixfd) has failed");
+ pipe.write(buffer, ret);
+ }
+ return fd;
+ }
+
+}
diff --git a/botan/src/filters/fd_unix/fd_unix.h b/botan/src/filters/fd_unix/fd_unix.h
new file mode 100644
index 0000000..0aed009
--- /dev/null
+++ b/botan/src/filters/fd_unix/fd_unix.h
@@ -0,0 +1,23 @@
+/*
+* Pipe I/O for Unix
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_UNIXFD_H__
+#define BOTAN_PIPE_UNIXFD_H__
+
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* Unix I/O Operators for Pipe
+*/
+int operator<<(int, Pipe&);
+int operator>>(int, Pipe&);
+
+}
+
+#endif
diff --git a/botan/src/filters/fd_unix/info.txt b/botan/src/filters/fd_unix/info.txt
new file mode 100644
index 0000000..d87978c
--- /dev/null
+++ b/botan/src/filters/fd_unix/info.txt
@@ -0,0 +1,28 @@
+realname "Unix I/O support for Pipe"
+
+define PIPE_UNIXFD_IO
+modset unix,beos
+
+load_on auto
+
+<add>
+fd_unix.h
+fd_unix.cpp
+</add>
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/botan/src/filters/filter.cpp b/botan/src/filters/filter.cpp
new file mode 100644
index 0000000..4bf0ef9
--- /dev/null
+++ b/botan/src/filters/filter.cpp
@@ -0,0 +1,127 @@
+/*
+* Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/filter.h>
+#include <botan/secqueue.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* Filter Constructor
+*/
+Filter::Filter()
+ {
+ next.resize(1);
+ port_num = 0;
+ filter_owns = 0;
+ owned = false;
+ }
+
+/*
+* Send data to all ports
+*/
+void Filter::send(const byte input[], u32bit length)
+ {
+ bool nothing_attached = true;
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ {
+ if(write_queue.has_items())
+ next[j]->write(write_queue, write_queue.size());
+ next[j]->write(input, length);
+ nothing_attached = false;
+ }
+ if(nothing_attached)
+ write_queue.append(input, length);
+ else if(write_queue.has_items())
+ write_queue.destroy();
+ }
+
+/*
+* Start a new message
+*/
+void Filter::new_msg()
+ {
+ start_msg();
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ next[j]->new_msg();
+ }
+
+/*
+* End the current message
+*/
+void Filter::finish_msg()
+ {
+ end_msg();
+ for(u32bit j = 0; j != total_ports(); ++j)
+ if(next[j])
+ next[j]->finish_msg();
+ }
+
+/*
+* Attach a filter to the current port
+*/
+void Filter::attach(Filter* new_filter)
+ {
+ if(new_filter)
+ {
+ Filter* last = this;
+ while(last->get_next())
+ last = last->get_next();
+ last->next[last->current_port()] = new_filter;
+ }
+ }
+
+/*
+* Set the active port on a filter
+*/
+void Filter::set_port(u32bit new_port)
+ {
+ if(new_port >= total_ports())
+ throw Invalid_Argument("Filter: Invalid port number");
+ port_num = new_port;
+ }
+
+/*
+* Return the next Filter in the logical chain
+*/
+Filter* Filter::get_next() const
+ {
+ if(port_num < next.size())
+ return next[port_num];
+ return 0;
+ }
+
+/*
+* Set the next Filters
+*/
+void Filter::set_next(Filter* filters[], u32bit size)
+ {
+ while(size && filters && filters[size-1] == 0)
+ --size;
+
+ next.clear();
+ next.resize(size);
+
+ port_num = 0;
+ filter_owns = 0;
+
+ for(u32bit j = 0; j != size; ++j)
+ next[j] = filters[j];
+ }
+
+/*
+* Return the total number of ports
+*/
+u32bit Filter::total_ports() const
+ {
+ return next.size();
+ }
+
+}
diff --git a/botan/src/filters/filter.h b/botan/src/filters/filter.h
new file mode 100644
index 0000000..b13a366
--- /dev/null
+++ b/botan/src/filters/filter.h
@@ -0,0 +1,113 @@
+/*
+* Filter
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTER_H__
+#define BOTAN_FILTER_H__
+
+#include <botan/secmem.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* This class represents general abstract filter objects.
+*/
+class BOTAN_DLL Filter
+ {
+ public:
+
+ /**
+ * Write a portion of a message to this filter.
+ * @param input the input as a byte array
+ * @param length the length of the byte array input
+ */
+ virtual void write(const byte input[], u32bit length) = 0;
+
+ /**
+ * Start a new message. Must be closed by end_msg() before another
+ * message can be startet.
+ */
+ virtual void start_msg() {}
+
+ /**
+ * Tell the Filter that the current message shall be ended.
+ */
+ virtual void end_msg() {}
+
+ /**
+ * Check whether this filter is an attachable filter.
+ * @return true if this filter is attachable, false otherwise
+ */
+ virtual bool attachable() { return true; }
+
+ /**
+ * Start a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void new_msg();
+
+ /**
+ * End a new message in *this and all following filters. Only for
+ * internal use, not intended for use in client applications.
+ */
+ void finish_msg();
+
+ virtual ~Filter() {}
+ protected:
+ void send(const byte[], u32bit);
+ void send(byte input) { send(&input, 1); }
+ void send(const MemoryRegion<byte>& in) { send(in.begin(), in.size()); }
+ Filter();
+ private:
+ Filter(const Filter&) {}
+ Filter& operator=(const Filter&) { return (*this); }
+
+ friend class Pipe;
+ friend class Fanout_Filter;
+
+ u32bit total_ports() const;
+ u32bit current_port() const { return port_num; }
+ void set_port(u32bit);
+
+ u32bit owns() const { return filter_owns; }
+
+ void attach(Filter*);
+ void set_next(Filter*[], u32bit);
+ Filter* get_next() const;
+
+ SecureVector<byte> write_queue;
+ std::vector<Filter*> next;
+ u32bit port_num, filter_owns;
+
+ // true if filter belongs to a pipe --> prohibit filter sharing!
+ bool owned;
+ };
+
+/**
+* This is the abstract Fanout_Filter base class.
+**/
+class BOTAN_DLL Fanout_Filter : public Filter
+ {
+ protected:
+ void incr_owns() { ++filter_owns; }
+
+ void set_port(u32bit n) { Filter::set_port(n); }
+ void set_next(Filter* f[], u32bit n) { Filter::set_next(f, n); }
+ void attach(Filter* f) { Filter::attach(f); }
+ };
+
+/**
+* The type of checking to be performed by decoders:
+* NONE - no checks, IGNORE_WS - perform checks, but ignore
+* whitespaces, FULL_CHECK - perform checks, also complain
+* about white spaces.
+*/
+enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
+
+}
+
+#endif
diff --git a/botan/src/filters/filters.h b/botan/src/filters/filters.h
new file mode 100644
index 0000000..725651f
--- /dev/null
+++ b/botan/src/filters/filters.h
@@ -0,0 +1,189 @@
+/*
+* Filters
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FILTERS_H__
+#define BOTAN_FILTERS_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+#include <botan/pipe.h>
+#include <botan/basefilt.h>
+#include <botan/data_snk.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_BASE64_CODEC)
+ #include <botan/base64.h>
+#endif
+
+#if defined(BOTAN_HAS_HEX_CODEC)
+ #include <botan/hex.h>
+#endif
+
+namespace Botan {
+
+/**
+* Stream Cipher Filter.
+*/
+class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter
+ {
+ public:
+
+ /**
+ * Seek in the stream.
+ * @param position the position to seek ahead
+ */
+ void seek(u32bit position) { cipher->seek(position); }
+
+ /**
+ * Find out whether the cipher underlying this filter supports
+ * resyncing.
+ * @return true if the cipher supports resyncing
+ */
+ bool supports_resync() const { return (cipher->IV_LENGTH != 0); }
+
+ /**
+ * Set the initialization vector for this filter.
+ * @param iv the initialization vector to set
+ */
+ void set_iv(const InitializationVector& iv);
+ void write(const byte[], u32bit);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher_obj a cipher object to use
+ */
+ StreamCipher_Filter(StreamCipher* cipher_obj);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ */
+ StreamCipher_Filter(const std::string& cipher);
+
+ /**
+ * Construct a stream cipher filter.
+ * @param cipher the name of the desired cipher
+ * @param key the key to use inside this filter
+ */
+ StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key);
+
+ ~StreamCipher_Filter() { delete cipher; }
+ private:
+ SecureVector<byte> buffer;
+ StreamCipher* cipher;
+ };
+
+/**
+* Hash Filter.
+*/
+class BOTAN_DLL Hash_Filter : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { hash->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a hash filter.
+ * @param hash_fun the hash function to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(HashFunction* hash_fun, u32bit len = 0) :
+ OUTPUT_LENGTH(len), hash(hash_fun) {}
+
+ /**
+ * Construct a hash filter.
+ * @param request the name of the hash algorithm to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the hashfunction
+ * hash. Otherwise, specify a smaller value here so that the
+ * output of the hash algorithm will be cut off.
+ */
+ Hash_Filter(const std::string& request, u32bit len = 0);
+
+ ~Hash_Filter() { delete hash; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ HashFunction* hash;
+ };
+
+/**
+* MessageAuthenticationCode Filter.
+*/
+class BOTAN_DLL MAC_Filter : public Keyed_Filter
+ {
+ public:
+ void write(const byte input[], u32bit len) { mac->update(input, len); }
+ void end_msg();
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ }
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(MessageAuthenticationCode* mac_obj,
+ const SymmetricKey& key,
+ u32bit out_len = 0) : OUTPUT_LENGTH(out_len)
+ {
+ base_ptr = mac = mac_obj;
+ mac->set_key(key);
+ }
+
+ /**
+ * Construct a MAC filter. The MAC key will be left empty.
+ * @param mac the name of the MAC to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, u32bit len = 0);
+
+ /**
+ * Construct a MAC filter.
+ * @param mac the name of the MAC to use
+ * @param key the MAC key to use
+ * @param len the output length of this filter. Leave the default
+ * value 0 if you want to use the full output of the
+ * MAC. Otherwise, specify a smaller value here so that the
+ * output of the MAC will be cut off.
+ */
+ MAC_Filter(const std::string& mac, const SymmetricKey& key,
+ u32bit len = 0);
+
+ ~MAC_Filter() { delete mac; }
+ private:
+ const u32bit OUTPUT_LENGTH;
+ MessageAuthenticationCode* mac;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/info.txt b/botan/src/filters/info.txt
new file mode 100644
index 0000000..79a92a9
--- /dev/null
+++ b/botan/src/filters/info.txt
@@ -0,0 +1,41 @@
+realname "Pipe/Filter"
+
+load_on auto
+
+define FILTERS
+
+<add>
+algo_filt.cpp
+basefilt.cpp
+basefilt.h
+buf_filt.cpp
+buf_filt.h
+data_snk.cpp
+data_snk.h
+data_src.cpp
+data_src.h
+filter.cpp
+filter.h
+filters.h
+out_buf.cpp
+out_buf.h
+pbe.h
+pipe.cpp
+pipe.h
+pipe_io.cpp
+pipe_rw.cpp
+secqueue.cpp
+secqueue.h
+</add>
+
+<requires>
+alloc
+asn1
+block
+hash
+libstate
+mac
+rng
+stream
+sym_algo
+</requires>
diff --git a/botan/src/filters/out_buf.cpp b/botan/src/filters/out_buf.cpp
new file mode 100644
index 0000000..6002f4f
--- /dev/null
+++ b/botan/src/filters/out_buf.cpp
@@ -0,0 +1,119 @@
+/*
+* Pipe Output Buffer Source file
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+
+namespace Botan {
+
+/*
+* Read data from a message
+*/
+u32bit Output_Buffers::read(byte output[], u32bit length,
+ Pipe::message_id msg)
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->read(output, length);
+ return 0;
+ }
+
+/*
+* Peek at data in a message
+*/
+u32bit Output_Buffers::peek(byte output[], u32bit length,
+ u32bit stream_offset,
+ Pipe::message_id msg) const
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->peek(output, length, stream_offset);
+ return 0;
+ }
+
+/*
+* Check available bytes in a message
+*/
+u32bit Output_Buffers::remaining(Pipe::message_id msg) const
+ {
+ SecureQueue* q = get(msg);
+ if(q)
+ return q->size();
+ return 0;
+ }
+
+/*
+* Add a new output queue
+*/
+void Output_Buffers::add(SecureQueue* queue)
+ {
+ if(!queue)
+ throw Internal_Error("Output_Buffers::add: Argument was NULL");
+
+ if(buffers.size() == buffers.max_size())
+ throw Internal_Error("Output_Buffers::add: No more room in container");
+
+ buffers.push_back(queue);
+ }
+
+/*
+* Retire old output queues
+*/
+void Output_Buffers::retire()
+ {
+ while(buffers.size())
+ {
+ if(buffers[0] == 0 || buffers[0]->size() == 0)
+ {
+ delete buffers[0];
+ buffers.pop_front();
+ offset = offset + Pipe::message_id(1);
+ }
+ else
+ break;
+ }
+ }
+
+/*
+* Get a particular output queue
+*/
+SecureQueue* Output_Buffers::get(Pipe::message_id msg) const
+ {
+ if(msg < offset)
+ return 0;
+ if(msg > message_count())
+ throw Internal_Error("Output_Buffers::get: msg > size");
+
+ return buffers[msg-offset];
+ }
+
+/*
+* Return the total number of messages
+*/
+Pipe::message_id Output_Buffers::message_count() const
+ {
+ return (offset + buffers.size());
+ }
+
+/*
+* Output_Buffers Constructor
+*/
+Output_Buffers::Output_Buffers()
+ {
+ offset = 0;
+ }
+
+/*
+* Output_Buffers Destructor
+*/
+Output_Buffers::~Output_Buffers()
+ {
+ for(u32bit j = 0; j != buffers.size(); ++j)
+ delete buffers[j];
+ }
+
+}
diff --git a/botan/src/filters/out_buf.h b/botan/src/filters/out_buf.h
new file mode 100644
index 0000000..0baacda
--- /dev/null
+++ b/botan/src/filters/out_buf.h
@@ -0,0 +1,43 @@
+/*
+* Output Buffer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OUTPUT_BUFFER_H__
+#define BOTAN_OUTPUT_BUFFER_H__
+
+#include <botan/types.h>
+#include <botan/pipe.h>
+#include <deque>
+
+namespace Botan {
+
+/*
+* Container of output buffers for Pipe
+*/
+class BOTAN_DLL Output_Buffers
+ {
+ public:
+ u32bit read(byte[], u32bit, Pipe::message_id);
+ u32bit peek(byte[], u32bit, u32bit, Pipe::message_id) const;
+ u32bit remaining(Pipe::message_id) const;
+
+ void add(class SecureQueue*);
+ void retire();
+
+ Pipe::message_id message_count() const;
+
+ Output_Buffers();
+ ~Output_Buffers();
+ private:
+ class SecureQueue* get(Pipe::message_id) const;
+
+ std::deque<SecureQueue*> buffers;
+ Pipe::message_id offset;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/pbe.h b/botan/src/filters/pbe.h
new file mode 100644
index 0000000..f06d593
--- /dev/null
+++ b/botan/src/filters/pbe.h
@@ -0,0 +1,56 @@
+/*
+* PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_BASE_H__
+#define BOTAN_PBE_BASE_H__
+
+#include <botan/asn1_oid.h>
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Password Based Encryption (PBE) Filter.
+*/
+class BOTAN_DLL PBE : public Filter
+ {
+ public:
+ /**
+ * Set this filter's key.
+ * @param pw the password to be used for the encryption
+ */
+ virtual void set_key(const std::string&) = 0;
+
+ /**
+ * Create a new random salt value and set the default iterations value.
+ */
+ virtual void new_params(RandomNumberGenerator& rng) = 0;
+
+ /**
+ * DER encode the params (the number of iterations and the salt value)
+ * @return the encoded params
+ */
+ virtual MemoryVector<byte> encode_params() const = 0;
+
+ /**
+ * Decode params and use them inside this Filter.
+ * @param src a data source to read the encoded params from
+ */
+ virtual void decode_params(DataSource&) = 0;
+
+ /**
+ * Get this PBE's OID.
+ * @return the OID
+ */
+ virtual OID get_oid() const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/filters/pipe.cpp b/botan/src/filters/pipe.cpp
new file mode 100644
index 0000000..33824be
--- /dev/null
+++ b/botan/src/filters/pipe.cpp
@@ -0,0 +1,306 @@
+/*
+* Pipe
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Constructor for Invalid_Message_Number
+*/
+Pipe::Invalid_Message_Number::Invalid_Message_Number(const std::string& where,
+ message_id msg)
+ {
+ set_msg("Pipe::" + where + ": Invalid message number " +
+ to_string(msg));
+ }
+
+namespace {
+
+/*
+* A Filter that does nothing
+*/
+class Null_Filter : public Filter
+ {
+ public:
+ void write(const byte input[], u32bit length)
+ { send(input, length); }
+ };
+
+}
+
+/*
+* Pipe Constructor
+*/
+Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ init();
+ append(f1);
+ append(f2);
+ append(f3);
+ append(f4);
+ }
+
+/*
+* Pipe Constructor
+*/
+Pipe::Pipe(Filter* filter_array[], u32bit count)
+ {
+ init();
+ for(u32bit j = 0; j != count; ++j)
+ append(filter_array[j]);
+ }
+
+/*
+* Pipe Destructor
+*/
+Pipe::~Pipe()
+ {
+ destruct(pipe);
+ delete outputs;
+ }
+
+/*
+* Initialize the Pipe
+*/
+void Pipe::init()
+ {
+ outputs = new Output_Buffers;
+ pipe = 0;
+ default_read = 0;
+ inside_msg = false;
+ }
+
+/*
+* Reset the Pipe
+*/
+void Pipe::reset()
+ {
+ if(inside_msg)
+ throw Invalid_State("Pipe cannot be reset while it is processing");
+ destruct(pipe);
+ pipe = 0;
+ inside_msg = false;
+ }
+
+/*
+* Destroy the Pipe
+*/
+void Pipe::destruct(Filter* to_kill)
+ {
+ if(!to_kill || dynamic_cast<SecureQueue*>(to_kill))
+ return;
+ for(u32bit j = 0; j != to_kill->total_ports(); ++j)
+ destruct(to_kill->next[j]);
+ delete to_kill;
+ }
+
+/*
+* Test if the Pipe has any data in it
+*/
+bool Pipe::end_of_data() const
+ {
+ return (remaining() == 0);
+ }
+
+/*
+* Set the default read message
+*/
+void Pipe::set_default_msg(message_id msg)
+ {
+ if(msg >= message_count())
+ throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
+ default_read = msg;
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const byte input[], u32bit length)
+ {
+ start_msg();
+ write(input, length);
+ end_msg();
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const MemoryRegion<byte>& input)
+ {
+ process_msg(input.begin(), input.size());
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(const std::string& input)
+ {
+ process_msg(reinterpret_cast<const byte*>(input.data()), input.length());
+ }
+
+/*
+* Process a full message at once
+*/
+void Pipe::process_msg(DataSource& input)
+ {
+ start_msg();
+ write(input);
+ end_msg();
+ }
+
+/*
+* Start a new message
+*/
+void Pipe::start_msg()
+ {
+ if(inside_msg)
+ throw Invalid_State("Pipe::start_msg: Message was already started");
+ if(pipe == 0)
+ pipe = new Null_Filter;
+ find_endpoints(pipe);
+ pipe->new_msg();
+ inside_msg = true;
+ }
+
+/*
+* End the current message
+*/
+void Pipe::end_msg()
+ {
+ if(!inside_msg)
+ throw Invalid_State("Pipe::end_msg: Message was already ended");
+ pipe->finish_msg();
+ clear_endpoints(pipe);
+ if(dynamic_cast<Null_Filter*>(pipe))
+ {
+ delete pipe;
+ pipe = 0;
+ }
+ inside_msg = false;
+
+ outputs->retire();
+ }
+
+/*
+* Find the endpoints of the Pipe
+*/
+void Pipe::find_endpoints(Filter* f)
+ {
+ for(u32bit j = 0; j != f->total_ports(); ++j)
+ if(f->next[j] && !dynamic_cast<SecureQueue*>(f->next[j]))
+ find_endpoints(f->next[j]);
+ else
+ {
+ SecureQueue* q = new SecureQueue;
+ f->next[j] = q;
+ outputs->add(q);
+ }
+ }
+
+/*
+* Remove the SecureQueues attached to the Filter
+*/
+void Pipe::clear_endpoints(Filter* f)
+ {
+ if(!f) return;
+ for(u32bit j = 0; j != f->total_ports(); ++j)
+ {
+ if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
+ f->next[j] = 0;
+ clear_endpoints(f->next[j]);
+ }
+ }
+
+/*
+* Append a Filter to the Pipe
+*/
+void Pipe::append(Filter* filter)
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot append to a Pipe while it is processing");
+ if(!filter)
+ return;
+ if(dynamic_cast<SecureQueue*>(filter))
+ throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
+ if(filter->owned)
+ throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
+
+ filter->owned = true;
+
+ if(!pipe) pipe = filter;
+ else pipe->attach(filter);
+ }
+
+/*
+* Prepend a Filter to the Pipe
+*/
+void Pipe::prepend(Filter* filter)
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot prepend to a Pipe while it is processing");
+ if(!filter)
+ return;
+ if(dynamic_cast<SecureQueue*>(filter))
+ throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
+ if(filter->owned)
+ throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
+
+ filter->owned = true;
+
+ if(pipe) filter->attach(pipe);
+ pipe = filter;
+ }
+
+/*
+* Pop a Filter off the Pipe
+*/
+void Pipe::pop()
+ {
+ if(inside_msg)
+ throw Invalid_State("Cannot pop off a Pipe while it is processing");
+
+ if(!pipe)
+ return;
+
+ if(pipe->total_ports() > 1)
+ throw Invalid_State("Cannot pop off a Filter with multiple ports");
+
+ Filter* f = pipe;
+ u32bit owns = f->owns();
+ pipe = pipe->next[0];
+ delete f;
+
+ while(owns--)
+ {
+ f = pipe;
+ pipe = pipe->next[0];
+ delete f;
+ }
+ }
+
+/*
+* Return the number of messages in this Pipe
+*/
+Pipe::message_id Pipe::message_count() const
+ {
+ return outputs->message_count();
+ }
+
+/*
+* Static Member Variables
+*/
+const Pipe::message_id Pipe::LAST_MESSAGE =
+ static_cast<Pipe::message_id>(-2);
+
+const Pipe::message_id Pipe::DEFAULT_MESSAGE =
+ static_cast<Pipe::message_id>(-1);
+
+}
diff --git a/botan/src/filters/pipe.h b/botan/src/filters/pipe.h
new file mode 100644
index 0000000..120f2fb
--- /dev/null
+++ b/botan/src/filters/pipe.h
@@ -0,0 +1,275 @@
+/*
+* Pipe
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PIPE_H__
+#define BOTAN_PIPE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+#include <botan/exceptn.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents pipe objects.
+* A set of filters can be placed into a pipe, and information flows
+* through the pipe until it reaches the end, where the output is
+* collected for retrieval. If you're familiar with the Unix shell
+* environment, this design will sound quite familiar.
+*/
+
+class BOTAN_DLL Pipe : public DataSource
+ {
+ public:
+ typedef u32bit message_id;
+
+ class Invalid_Message_Number : public Invalid_Argument
+ {
+ public:
+ Invalid_Message_Number(const std::string&, message_id);
+ };
+
+ static const message_id LAST_MESSAGE;
+ static const message_id DEFAULT_MESSAGE;
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the byte array to write
+ * @param length the length of the byte array in
+ */
+ void write(const byte in[], u32bit length);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void write(const MemoryRegion<byte>& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the string containing the data to write
+ */
+ void write(const std::string& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in the DataSource to read the data from
+ */
+ void write(DataSource& in);
+
+ /**
+ * Write input to the pipe, i.e. to its first filter.
+ * @param in a single byte to be written
+ */
+ void write(byte in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the byte array containing the data to write
+ * @param length the length of the byte array to write
+ */
+ void process_msg(const byte in[], u32bit length);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the MemoryRegion containing the data to write
+ */
+ void process_msg(const MemoryRegion<byte>& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the string containing the data to write
+ */
+ void process_msg(const std::string& in);
+
+ /**
+ * Perform start_msg(), write() and end_msg() sequentially.
+ * @param in the DataSource providing the data to write
+ */
+ void process_msg(DataSource& in);
+
+ /**
+ * Find out how many bytes are ready to read.
+ * @param msg the number identifying the message
+ * for which the information is desired
+ * @return the number of bytes that can still be read
+ */
+ u32bit remaining(message_id msg = DEFAULT_MESSAGE) const;
+
+ /**
+ * Read the default message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length);
+
+ /**
+ * Read a specified message from the pipe. Moves the internal
+ * offset so that every call to read will return a new portion of
+ * the message.
+ * @param output the byte array to write the read bytes to
+ * @param length the length of the byte array output
+ * @param msg the number identifying the message to read from
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte output[], u32bit length, message_id msg);
+
+ /**
+ * Read a single byte from the pipe. Moves the internal offset so that
+ * every call to read will return a new portion of the message.
+ * @param output the byte to write the result to
+ * @return the number of bytes actually read into output
+ */
+ u32bit read(byte& output, message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a SecureVector holding the contents of the pipe
+ */
+ SecureVector<byte> read_all(message_id msg = DEFAULT_MESSAGE);
+
+ /**
+ * Read the full contents of the pipe.
+ * @param msg the number identifying the message to read from
+ * @return a string holding the contents of the pipe
+ */
+ std::string read_all_as_string(message_id = DEFAULT_MESSAGE);
+
+ /** Read from the default message but do not modify the internal
+ * offset. Consecutive calls to peek() will return portions of
+ * the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length, u32bit offset) const;
+
+ /** Read from the specified message but do not modify the
+ * internal offset. Consecutive calls to peek() will return
+ * portions of the message starting at the same position.
+ * @param output the byte array to write the peeked message part to
+ * @param length the length of the byte array output
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte output[], u32bit length,
+ u32bit offset, message_id msg) const;
+
+ /** Read a single byte from the specified message but do not
+ * modify the internal offset. Consecutive calls to peek() will
+ * return portions of the message starting at the same position.
+ * @param output the byte to write the peeked message byte to
+ * @param offset the offset from the current position in message
+ * @param msg the number identifying the message to peek from
+ * @return the number of bytes actually peeked and written into output
+ */
+ u32bit peek(byte& output, u32bit offset,
+ message_id msg = DEFAULT_MESSAGE) const;
+
+ u32bit default_msg() const { return default_read; }
+
+ /**
+ * Set the default message
+ * @param msg the number identifying the message which is going to
+ * be the new default message
+ */
+ void set_default_msg(message_id msg);
+
+ /**
+ * Get the number of messages the are in this pipe.
+ * @return the number of messages the are in this pipe
+ */
+ message_id message_count() const;
+
+ /**
+ * Test whether this pipe has any data that can be read from.
+ * @return true if there is more data to read, false otherwise
+ */
+ bool end_of_data() const;
+
+ /**
+ * Start a new message in the pipe. A potential other message in this pipe
+ * must be closed with end_msg() before this function may be called.
+ */
+ void start_msg();
+
+ /**
+ * End the current message.
+ */
+ void end_msg();
+
+ /**
+ * Insert a new filter at the front of the pipe
+ * @param filt the new filter to insert
+ */
+ void prepend(Filter* filt);
+
+ /**
+ * Insert a new filter at the back of the pipe
+ * @param filt the new filter to insert
+ */
+ void append(Filter* filt);
+
+ /**
+ * Remove the first filter at the front of the pipe.
+ */
+ void pop();
+
+ /**
+ * Reset this pipe to an empty pipe.
+ */
+ void reset();
+
+ /**
+ * Construct a Pipe of up to four filters. The filters are set up
+ * in the same order as the arguments.
+ */
+ Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+
+ /**
+ * Construct a Pipe from range of filters passed as an array
+ * @param filters the set of filters to use
+ * @param count the number of elements in filters
+ */
+ Pipe(Filter* filters[], u32bit count);
+ ~Pipe();
+ private:
+ Pipe(const Pipe&) : DataSource() {}
+ Pipe& operator=(const Pipe&) { return (*this); }
+ void init();
+ void destruct(Filter*);
+ void find_endpoints(Filter*);
+ void clear_endpoints(Filter*);
+
+ message_id get_message_no(const std::string&, message_id) const;
+
+ Filter* pipe;
+ class Output_Buffers* outputs;
+ message_id default_read;
+ bool inside_msg;
+ };
+
+/*
+* I/O Operators for Pipe
+*/
+BOTAN_DLL std::ostream& operator<<(std::ostream&, Pipe&);
+BOTAN_DLL std::istream& operator>>(std::istream&, Pipe&);
+
+}
+
+#endif
+
+#if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
+ #include <botan/fd_unix.h>
+#endif
diff --git a/botan/src/filters/pipe_io.cpp b/botan/src/filters/pipe_io.cpp
new file mode 100644
index 0000000..c57be6d
--- /dev/null
+++ b/botan/src/filters/pipe_io.cpp
@@ -0,0 +1,45 @@
+/*
+* Pipe I/O
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <iostream>
+
+namespace Botan {
+
+/*
+* Write data from a pipe into an ostream
+*/
+std::ostream& operator<<(std::ostream& stream, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(stream.good() && pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ stream.write(reinterpret_cast<const char*>(buffer.begin()), got);
+ }
+ if(!stream.good())
+ throw Stream_IO_Error("Pipe output operator (iostream) has failed");
+ return stream;
+ }
+
+/*
+* Read data from an istream into a pipe
+*/
+std::istream& operator>>(std::istream& stream, Pipe& pipe)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(stream.good())
+ {
+ stream.read(reinterpret_cast<char*>(buffer.begin()), buffer.size());
+ pipe.write(buffer, stream.gcount());
+ }
+ if(stream.bad() || (stream.fail() && !stream.eof()))
+ throw Stream_IO_Error("Pipe input operator (iostream) has failed");
+ return stream;
+ }
+
+}
diff --git a/botan/src/filters/pipe_rw.cpp b/botan/src/filters/pipe_rw.cpp
new file mode 100644
index 0000000..41b57a7
--- /dev/null
+++ b/botan/src/filters/pipe_rw.cpp
@@ -0,0 +1,167 @@
+/*
+* Pipe Reading/Writing
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pipe.h>
+#include <botan/out_buf.h>
+#include <botan/secqueue.h>
+
+namespace Botan {
+
+/*
+* Look up the canonical ID for a queue
+*/
+Pipe::message_id Pipe::get_message_no(const std::string& func_name,
+ message_id msg) const
+ {
+ if(msg == DEFAULT_MESSAGE)
+ msg = default_msg();
+ else if(msg == LAST_MESSAGE)
+ msg = message_count() - 1;
+
+ if(msg >= message_count())
+ throw Invalid_Message_Number(func_name, msg);
+
+ return msg;
+ }
+
+/*
+* Write into a Pipe
+*/
+void Pipe::write(const byte input[], u32bit length)
+ {
+ if(!inside_msg)
+ throw Exception("Cannot write to a Pipe while it is not processing");
+ pipe->write(input, length);
+ }
+
+/*
+* Write into a Pipe
+*/
+void Pipe::write(const MemoryRegion<byte>& input)
+ {
+ write(input.begin(), input.size());
+ }
+
+/*
+* Write a string into a Pipe
+*/
+void Pipe::write(const std::string& str)
+ {
+ write(reinterpret_cast<const byte*>(str.data()), str.size());
+ }
+
+/*
+* Write a single byte into a Pipe
+*/
+void Pipe::write(byte input)
+ {
+ write(&input, 1);
+ }
+
+/*
+* Write the contents of a DataSource into a Pipe
+*/
+void Pipe::write(DataSource& source)
+ {
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(!source.end_of_data())
+ {
+ u32bit got = source.read(buffer, buffer.size());
+ write(buffer, got);
+ }
+ }
+
+/*
+* Read some data from the pipe
+*/
+u32bit Pipe::read(byte output[], u32bit length, message_id msg)
+ {
+ return outputs->read(output, length, get_message_no("read", msg));
+ }
+
+/*
+* Read some data from the pipe
+*/
+u32bit Pipe::read(byte output[], u32bit length)
+ {
+ return read(output, length, DEFAULT_MESSAGE);
+ }
+
+/*
+* Read a single byte from the pipe
+*/
+u32bit Pipe::read(byte& out, message_id msg)
+ {
+ return read(&out, 1, msg);
+ }
+
+/*
+* Return all data in the pipe
+*/
+SecureVector<byte> Pipe::read_all(message_id msg)
+ {
+ msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
+ SecureVector<byte> buffer(remaining(msg));
+ read(buffer, buffer.size(), msg);
+ return buffer;
+ }
+
+/*
+* Return all data in the pipe as a string
+*/
+std::string Pipe::read_all_as_string(message_id msg)
+ {
+ msg = ((msg != DEFAULT_MESSAGE) ? msg : default_msg());
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ std::string str;
+ str.reserve(remaining(msg));
+
+ while(true)
+ {
+ u32bit got = read(buffer, buffer.size(), msg);
+ if(got == 0)
+ break;
+ str.append(reinterpret_cast<const char*>(buffer.begin()), got);
+ }
+
+ return str;
+ }
+
+/*
+* Find out how many bytes are ready to read
+*/
+u32bit Pipe::remaining(message_id msg) const
+ {
+ return outputs->remaining(get_message_no("remaining", msg));
+ }
+
+/*
+* Peek at some data in the pipe
+*/
+u32bit Pipe::peek(byte output[], u32bit length,
+ u32bit offset, message_id msg) const
+ {
+ return outputs->peek(output, length, offset, get_message_no("peek", msg));
+ }
+
+/*
+* Peek at some data in the pipe
+*/
+u32bit Pipe::peek(byte output[], u32bit length, u32bit offset) const
+ {
+ return peek(output, length, offset, DEFAULT_MESSAGE);
+ }
+
+/*
+* Peek at a byte in the pipe
+*/
+u32bit Pipe::peek(byte& out, u32bit offset, message_id msg) const
+ {
+ return peek(&out, 1, offset, msg);
+ }
+
+}
diff --git a/botan/src/filters/secqueue.cpp b/botan/src/filters/secqueue.cpp
new file mode 100644
index 0000000..f63ef89
--- /dev/null
+++ b/botan/src/filters/secqueue.cpp
@@ -0,0 +1,205 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/secqueue.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* SecureQueueNode
+*/
+class SecureQueueNode
+ {
+ public:
+ u32bit write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(length, buffer.size() - end);
+ copy_mem(buffer + end, input, copied);
+ end += copied;
+ return copied;
+ }
+ u32bit read(byte output[], u32bit length)
+ {
+ u32bit copied = std::min(length, end - start);
+ copy_mem(output, buffer + start, copied);
+ start += copied;
+ return copied;
+ }
+ u32bit peek(byte output[], u32bit length, u32bit offset = 0)
+ {
+ const u32bit left = end - start;
+ if(offset >= left) return 0;
+ u32bit copied = std::min(length, left - offset);
+ copy_mem(output, buffer + start + offset, copied);
+ return copied;
+ }
+ u32bit size() const { return (end - start); }
+ SecureQueueNode() { next = 0; start = end = 0; }
+ ~SecureQueueNode() { next = 0; start = end = 0; }
+ private:
+ friend class SecureQueue;
+ SecureQueueNode* next;
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ u32bit start, end;
+ };
+
+/*
+* Create a SecureQueue
+*/
+SecureQueue::SecureQueue()
+ {
+ set_next(0, 0);
+ head = tail = new SecureQueueNode;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue::SecureQueue(const SecureQueue& input) :
+ Fanout_Filter(), DataSource()
+ {
+ set_next(0, 0);
+
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ }
+
+/*
+* Destroy this SecureQueue
+*/
+void SecureQueue::destroy()
+ {
+ SecureQueueNode* temp = head;
+ while(temp)
+ {
+ SecureQueueNode* holder = temp->next;
+ delete temp;
+ temp = holder;
+ }
+ head = tail = 0;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue& SecureQueue::operator=(const SecureQueue& input)
+ {
+ destroy();
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ return (*this);
+ }
+
+/*
+* Add some bytes to the queue
+*/
+void SecureQueue::write(const byte input[], u32bit length)
+ {
+ if(!head)
+ head = tail = new SecureQueueNode;
+ while(length)
+ {
+ const u32bit n = tail->write(input, length);
+ input += n;
+ length -= n;
+ if(length)
+ {
+ tail->next = new SecureQueueNode;
+ tail = tail->next;
+ }
+ }
+ }
+
+/*
+* Read some bytes from the queue
+*/
+u32bit SecureQueue::read(byte output[], u32bit length)
+ {
+ u32bit got = 0;
+ while(length && head)
+ {
+ const u32bit n = head->read(output, length);
+ output += n;
+ got += n;
+ length -= n;
+ if(head->size() == 0)
+ {
+ SecureQueueNode* holder = head->next;
+ delete head;
+ head = holder;
+ }
+ }
+ return got;
+ }
+
+/*
+* Read data, but do not remove it from queue
+*/
+u32bit SecureQueue::peek(byte output[], u32bit length, u32bit offset) const
+ {
+ SecureQueueNode* current = head;
+
+ while(offset && current)
+ {
+ if(offset >= current->size())
+ {
+ offset -= current->size();
+ current = current->next;
+ }
+ else
+ break;
+ }
+
+ u32bit got = 0;
+ while(length && current)
+ {
+ const u32bit n = current->peek(output, length, offset);
+ offset = 0;
+ output += n;
+ got += n;
+ length -= n;
+ current = current->next;
+ }
+ return got;
+ }
+
+/*
+* Return how many bytes the queue holds
+*/
+u32bit SecureQueue::size() const
+ {
+ SecureQueueNode* current = head;
+ u32bit count = 0;
+
+ while(current)
+ {
+ count += current->size();
+ current = current->next;
+ }
+ return count;
+ }
+
+/*
+* Test if the queue has any data in it
+*/
+bool SecureQueue::end_of_data() const
+ {
+ return (size() == 0);
+ }
+
+}
diff --git a/botan/src/filters/secqueue.h b/botan/src/filters/secqueue.h
new file mode 100644
index 0000000..fc1fc21
--- /dev/null
+++ b/botan/src/filters/secqueue.h
@@ -0,0 +1,43 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SECURE_QUEUE_H__
+#define BOTAN_SECURE_QUEUE_H__
+
+#include <botan/data_src.h>
+#include <botan/filter.h>
+
+namespace Botan {
+
+/*
+* SecureQueue
+*/
+class BOTAN_DLL SecureQueue : public Fanout_Filter, public DataSource
+ {
+ public:
+ void write(const byte[], u32bit);
+
+ u32bit read(byte[], u32bit);
+ u32bit peek(byte[], u32bit, u32bit = 0) const;
+
+ bool end_of_data() const;
+ u32bit size() const;
+ bool attachable() { return false; }
+
+ SecureQueue& operator=(const SecureQueue&);
+ SecureQueue();
+ SecureQueue(const SecureQueue&);
+ ~SecureQueue() { destroy(); }
+ private:
+ void destroy();
+ class SecureQueueNode* head;
+ class SecureQueueNode* tail;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/fork256/fork256.cpp b/botan/src/hash/fork256/fork256.cpp
new file mode 100644
index 0000000..f80bff4
--- /dev/null
+++ b/botan/src/hash/fork256/fork256.cpp
@@ -0,0 +1,149 @@
+/*
+* FORK-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/fork256.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* FORK-256 Step Function
+*/
+inline void step(u32bit& A, u32bit& B, u32bit& C, u32bit& D,
+ u32bit& E, u32bit& F, u32bit& G, u32bit& H,
+ u32bit M1, u32bit M2, u32bit D1, u32bit D2)
+ {
+ u32bit T0, T1;
+
+ A += M1; T0 = A + (rotate_left(A, 7) ^ rotate_left(A, 22));
+ A += D1; T1 = A ^ (rotate_left(A, 13) + rotate_left(A, 27));
+
+ B = (B + T0) ^ T1;
+ C = (C + rotate_left(T0, 5)) ^ rotate_left(T1, 9);
+ D = (D + rotate_left(T0, 17)) ^ rotate_left(T1, 21);
+
+ E += M2; T0 = E ^ (rotate_left(E, 13) + rotate_left(E, 27));
+ E += D2; T1 = E + (rotate_left(E, 7) ^ rotate_left(E, 22));
+
+ F = (F + T0) ^ T1;
+ G = (G + rotate_left(T0, 9)) ^ rotate_left(T1, 5);
+ H = (H + rotate_left(T0, 21)) ^ rotate_left(T1, 17);
+ }
+
+}
+
+/*
+* FORK-256 Compression Function
+*/
+void FORK_256::compress_n(const byte input[], u32bit blocks)
+ {
+ const u32bit DELTA[16] = {
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1,
+ 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174
+ };
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ u32bit A1, B1, C1, D1, E1, F1, G1, H1;
+ u32bit A2, B2, C2, D2, E2, F2, G2, H2;
+ u32bit A3, B3, C3, D3, E3, F3, G3, H3;
+ u32bit A4, B4, C4, D4, E4, F4, G4, H4;
+
+ A1 = A2 = A3 = A4 = digest[0];
+ B1 = B2 = B3 = B4 = digest[1];
+ C1 = C2 = C3 = C4 = digest[2];
+ D1 = D2 = D3 = D4 = digest[3];
+ E1 = E2 = E3 = E4 = digest[4];
+ F1 = F2 = F3 = F4 = digest[5];
+ G1 = G2 = G3 = G4 = digest[6];
+ H1 = H2 = H3 = H4 = digest[7];
+
+ for(u32bit j = 0; j != 16; ++j)
+ M[j] = load_be<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ step(A1, B1, C1, D1, E1, F1, G1, H1, M[ 0], M[ 1], DELTA[ 0], DELTA[ 1]);
+ step(A2, B2, C2, D2, E2, F2, G2, H2, M[14], M[15], DELTA[15], DELTA[14]);
+ step(A3, B3, C3, D3, E3, F3, G3, H3, M[ 7], M[ 6], DELTA[ 1], DELTA[ 0]);
+ step(A4, B4, C4, D4, E4, F4, G4, H4, M[ 5], M[12], DELTA[14], DELTA[15]);
+
+ step(H1, A1, B1, C1, D1, E1, F1, G1, M[ 2], M[ 3], DELTA[ 2], DELTA[ 3]);
+ step(H2, A2, B2, C2, D2, E2, F2, G2, M[11], M[ 9], DELTA[13], DELTA[12]);
+ step(H3, A3, B3, C3, D3, E3, F3, G3, M[10], M[14], DELTA[ 3], DELTA[ 2]);
+ step(H4, A4, B4, C4, D4, E4, F4, G4, M[ 1], M[ 8], DELTA[12], DELTA[13]);
+
+ step(G1, H1, A1, B1, C1, D1, E1, F1, M[ 4], M[ 5], DELTA[ 4], DELTA[ 5]);
+ step(G2, H2, A2, B2, C2, D2, E2, F2, M[ 8], M[10], DELTA[11], DELTA[10]);
+ step(G3, H3, A3, B3, C3, D3, E3, F3, M[13], M[ 2], DELTA[ 5], DELTA[ 4]);
+ step(G4, H4, A4, B4, C4, D4, E4, F4, M[15], M[ 0], DELTA[10], DELTA[11]);
+
+ step(F1, G1, H1, A1, B1, C1, D1, E1, M[ 6], M[ 7], DELTA[ 6], DELTA[ 7]);
+ step(F2, G2, H2, A2, B2, C2, D2, E2, M[ 3], M[ 4], DELTA[ 9], DELTA[ 8]);
+ step(F3, G3, H3, A3, B3, C3, D3, E3, M[ 9], M[12], DELTA[ 7], DELTA[ 6]);
+ step(F4, G4, H4, A4, B4, C4, D4, E4, M[13], M[11], DELTA[ 8], DELTA[ 9]);
+
+ step(E1, F1, G1, H1, A1, B1, C1, D1, M[ 8], M[ 9], DELTA[ 8], DELTA[ 9]);
+ step(E2, F2, G2, H2, A2, B2, C2, D2, M[ 2], M[13], DELTA[ 7], DELTA[ 6]);
+ step(E3, F3, G3, H3, A3, B3, C3, D3, M[11], M[ 4], DELTA[ 9], DELTA[ 8]);
+ step(E4, F4, G4, H4, A4, B4, C4, D4, M[ 3], M[10], DELTA[ 6], DELTA[ 7]);
+
+ step(D1, E1, F1, G1, H1, A1, B1, C1, M[10], M[11], DELTA[10], DELTA[11]);
+ step(D2, E2, F2, G2, H2, A2, B2, C2, M[ 0], M[ 5], DELTA[ 5], DELTA[ 4]);
+ step(D3, E3, F3, G3, H3, A3, B3, C3, M[15], M[ 8], DELTA[11], DELTA[10]);
+ step(D4, E4, F4, G4, H4, A4, B4, C4, M[ 9], M[ 2], DELTA[ 4], DELTA[ 5]);
+
+ step(C1, D1, E1, F1, G1, H1, A1, B1, M[12], M[13], DELTA[12], DELTA[13]);
+ step(C2, D2, E2, F2, G2, H2, A2, B2, M[ 6], M[ 7], DELTA[ 3], DELTA[ 2]);
+ step(C3, D3, E3, F3, G3, H3, A3, B3, M[ 5], M[ 0], DELTA[13], DELTA[12]);
+ step(C4, D4, E4, F4, G4, H4, A4, B4, M[ 7], M[14], DELTA[ 2], DELTA[ 3]);
+
+ step(B1, C1, D1, E1, F1, G1, H1, A1, M[14], M[15], DELTA[14], DELTA[15]);
+ step(B2, C2, D2, E2, F2, G2, H2, A2, M[12], M[ 1], DELTA[ 1], DELTA[ 0]);
+ step(B3, C3, D3, E3, F3, G3, H3, A3, M[ 1], M[ 3], DELTA[15], DELTA[14]);
+ step(B4, C4, D4, E4, F4, G4, H4, A4, M[ 4], M[ 6], DELTA[ 0], DELTA[ 1]);
+
+ digest[0] += (A1 + A2) ^ (A3 + A4);
+ digest[1] += (B1 + B2) ^ (B3 + B4);
+ digest[2] += (C1 + C2) ^ (C3 + C4);
+ digest[3] += (D1 + D2) ^ (D3 + D4);
+ digest[4] += (E1 + E2) ^ (E3 + E4);
+ digest[5] += (F1 + F2) ^ (F3 + F4);
+ digest[6] += (G1 + G2) ^ (G3 + G4);
+ digest[7] += (H1 + H2) ^ (H3 + H4);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void FORK_256::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_be(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void FORK_256::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ digest[0] = 0x6A09E667;
+ digest[1] = 0xBB67AE85;
+ digest[2] = 0x3C6EF372;
+ digest[3] = 0xA54FF53A;
+ digest[4] = 0x510E527F;
+ digest[5] = 0x9B05688C;
+ digest[6] = 0x1F83D9AB;
+ digest[7] = 0x5BE0CD19;
+ }
+
+}
diff --git a/botan/src/hash/fork256/fork256.h b/botan/src/hash/fork256/fork256.h
new file mode 100644
index 0000000..70d336c
--- /dev/null
+++ b/botan/src/hash/fork256/fork256.h
@@ -0,0 +1,35 @@
+/*
+* FORK-256
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_FORK_256_H__
+#define BOTAN_FORK_256_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* FORK-256
+*/
+class BOTAN_DLL FORK_256 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "FORK-256"; }
+ HashFunction* clone() const { return new FORK_256; }
+ FORK_256() : MDx_HashFunction(32, 64, true, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 8> digest;
+ SecureBuffer<u32bit, 16> M;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/fork256/info.txt b/botan/src/hash/fork256/info.txt
new file mode 100644
index 0000000..ae0c9f1
--- /dev/null
+++ b/botan/src/hash/fork256/info.txt
@@ -0,0 +1,14 @@
+realname "FORK-256"
+
+define FORK_256
+
+load_on auto
+
+<add>
+fork256.cpp
+fork256.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/gost_3411/gost_3411.cpp b/botan/src/hash/gost_3411/gost_3411.cpp
new file mode 100644
index 0000000..5cbb8a7
--- /dev/null
+++ b/botan/src/hash/gost_3411/gost_3411.cpp
@@ -0,0 +1,236 @@
+/*
+* GOST 34.11
+* (C) 2009 Jack Lloyd
+*/
+
+#include <botan/gost_3411.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/**
+* GOST 34.11 Constructor
+*/
+GOST_34_11::GOST_34_11() :
+ HashFunction(32, 32),
+ cipher(GOST_28147_89_Params("R3411_CryptoPro"))
+ {
+ count = 0;
+ position = 0;
+ }
+
+void GOST_34_11::clear() throw()
+ {
+ cipher.clear();
+ sum.clear();
+ hash.clear();
+ count = 0;
+ position = 0;
+ }
+
+/**
+* Hash additional inputs
+*/
+void GOST_34_11::add_data(const byte input[], u32bit length)
+ {
+ count += length;
+
+ if(position)
+ {
+ buffer.copy(position, input, length);
+
+ if(position + length >= HASH_BLOCK_SIZE)
+ {
+ compress_n(buffer.begin(), 1);
+ input += (HASH_BLOCK_SIZE - position);
+ length -= (HASH_BLOCK_SIZE - position);
+ position = 0;
+ }
+ }
+
+ const u32bit full_blocks = length / HASH_BLOCK_SIZE;
+ const u32bit remaining = length % HASH_BLOCK_SIZE;
+
+ if(full_blocks)
+ compress_n(input, full_blocks);
+
+ buffer.copy(position, input + full_blocks * HASH_BLOCK_SIZE, remaining);
+ position += remaining;
+ }
+
+/**
+* The GOST 34.11 compression function
+*/
+void GOST_34_11::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0, carry = 0; j != 32; ++j)
+ {
+ u16bit s = sum[j] + input[32*i+j] + carry;
+ carry = get_byte(0, s);
+ sum[j] = get_byte(1, s);
+ }
+
+ byte S[32] = { 0 };
+
+ u64bit U[4], V[4];
+
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ U[j] = load_be<u64bit>(hash, j);
+ V[j] = load_be<u64bit>(input + 32*i, j);
+ }
+
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ byte key[32] = { 0 };
+
+ // P transformation
+ for(size_t k = 0; k != 4; ++k)
+ for(size_t l = 0; l != 8; ++l)
+ key[4*l+k] = get_byte(l, U[k]) ^ get_byte(l, V[k]);
+
+ cipher.set_key(key, 32);
+ cipher.encrypt(hash + 8*j, S + 8*j);
+
+ if(j == 3)
+ break;
+
+ // A(x)
+ u64bit A_U = U[0];
+ U[0] = U[1];
+ U[1] = U[2];
+ U[2] = U[3];
+ U[3] = U[0] ^ A_U;
+
+ if(j == 1) // C_3
+ {
+ U[0] ^= (u64bit) 0x00FF00FF00FF00FFULL;
+ U[1] ^= (u64bit) 0xFF00FF00FF00FF00ULL;
+ U[2] ^= (u64bit) 0x00FFFF00FF0000FFULL;
+ U[3] ^= (u64bit) 0xFF000000FFFF00FFULL;
+ }
+
+ // A(A(x))
+ u64bit AA_V_1 = V[0] ^ V[1];
+ u64bit AA_V_2 = V[1] ^ V[2];
+ V[0] = V[2];
+ V[1] = V[3];
+ V[2] = AA_V_1;
+ V[3] = AA_V_2;
+ }
+
+ byte S2[32] = { 0 };
+
+ // 12 rounds of psi
+ S2[ 0] = S[24];
+ S2[ 1] = S[25];
+ S2[ 2] = S[26];
+ S2[ 3] = S[27];
+ S2[ 4] = S[28];
+ S2[ 5] = S[29];
+ S2[ 6] = S[30];
+ S2[ 7] = S[31];
+ S2[ 8] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[24] ^ S[30];
+ S2[ 9] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[25] ^ S[31];
+ S2[10] = S[ 0] ^ S[ 8] ^ S[24] ^ S[26] ^ S[30];
+ S2[11] = S[ 1] ^ S[ 9] ^ S[25] ^ S[27] ^ S[31];
+ S2[12] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[10] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
+ S2[13] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[11] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
+ S2[14] = S[ 0] ^ S[ 4] ^ S[ 8] ^ S[12] ^ S[24] ^ S[26] ^ S[28];
+ S2[15] = S[ 1] ^ S[ 5] ^ S[ 9] ^ S[13] ^ S[25] ^ S[27] ^ S[29];
+ S2[16] = S[ 2] ^ S[ 6] ^ S[10] ^ S[14] ^ S[26] ^ S[28] ^ S[30];
+ S2[17] = S[ 3] ^ S[ 7] ^ S[11] ^ S[15] ^ S[27] ^ S[29] ^ S[31];
+ S2[18] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[12] ^ S[16] ^ S[24] ^ S[28];
+ S2[19] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[13] ^ S[17] ^ S[25] ^ S[29];
+ S2[20] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[14] ^ S[18] ^ S[26] ^ S[30];
+ S2[21] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[15] ^ S[19] ^ S[27] ^ S[31];
+ S2[22] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[16] ^ S[20] ^ S[24] ^ S[28] ^ S[30];
+ S2[23] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[17] ^ S[21] ^ S[25] ^ S[29] ^ S[31];
+ S2[24] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[18] ^ S[22] ^ S[24] ^ S[26];
+ S2[25] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[19] ^ S[23] ^ S[25] ^ S[27];
+ S2[26] = S[ 2] ^ S[ 8] ^ S[14] ^ S[16] ^ S[20] ^ S[24] ^ S[26] ^ S[28];
+ S2[27] = S[ 3] ^ S[ 9] ^ S[15] ^ S[17] ^ S[21] ^ S[25] ^ S[27] ^ S[29];
+ S2[28] = S[ 4] ^ S[10] ^ S[16] ^ S[18] ^ S[22] ^ S[26] ^ S[28] ^ S[30];
+ S2[29] = S[ 5] ^ S[11] ^ S[17] ^ S[19] ^ S[23] ^ S[27] ^ S[29] ^ S[31];
+ S2[30] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[12] ^ S[18] ^ S[20] ^ S[28];
+ S2[31] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[13] ^ S[19] ^ S[21] ^ S[29];
+
+ xor_buf(S, S2, input + 32*i, 32);
+
+ S2[0] = S[0] ^ S[2] ^ S[4] ^ S[6] ^ S[24] ^ S[30];
+ S2[1] = S[1] ^ S[3] ^ S[5] ^ S[7] ^ S[25] ^ S[31];
+
+ copy_mem(S, S+2, 30);
+ S[30] = S2[0];
+ S[31] = S2[1];
+
+ xor_buf(S, hash, 32);
+
+ // 61 rounds of psi
+ S2[ 0] = S[ 2] ^ S[ 6] ^ S[14] ^ S[20] ^ S[22] ^ S[26] ^ S[28] ^ S[30];
+ S2[ 1] = S[ 3] ^ S[ 7] ^ S[15] ^ S[21] ^ S[23] ^ S[27] ^ S[29] ^ S[31];
+ S2[ 2] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[16] ^ S[22] ^ S[28];
+ S2[ 3] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[17] ^ S[23] ^ S[29];
+ S2[ 4] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[18] ^ S[24] ^ S[30];
+ S2[ 5] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[19] ^ S[25] ^ S[31];
+ S2[ 6] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[20] ^ S[24] ^ S[26] ^ S[30];
+ S2[ 7] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[21] ^ S[25] ^ S[27] ^ S[31];
+ S2[ 8] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
+ S2[ 9] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
+ S2[10] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[14] ^ S[16] ^ S[26] ^ S[28];
+ S2[11] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[15] ^ S[17] ^ S[27] ^ S[29];
+ S2[12] = S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[16] ^ S[18] ^ S[28] ^ S[30];
+ S2[13] = S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[17] ^ S[19] ^ S[29] ^ S[31];
+ S2[14] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[12] ^ S[18] ^ S[20] ^ S[24];
+ S2[15] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[13] ^ S[19] ^ S[21] ^ S[25];
+ S2[16] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[12] ^ S[14] ^ S[20] ^ S[22] ^ S[26];
+ S2[17] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[13] ^ S[15] ^ S[21] ^ S[23] ^ S[27];
+ S2[18] = S[ 4] ^ S[ 6] ^ S[10] ^ S[12] ^ S[14] ^ S[16] ^ S[22] ^ S[24] ^ S[28];
+ S2[19] = S[ 5] ^ S[ 7] ^ S[11] ^ S[13] ^ S[15] ^ S[17] ^ S[23] ^ S[25] ^ S[29];
+ S2[20] = S[ 6] ^ S[ 8] ^ S[12] ^ S[14] ^ S[16] ^ S[18] ^ S[24] ^ S[26] ^ S[30];
+ S2[21] = S[ 7] ^ S[ 9] ^ S[13] ^ S[15] ^ S[17] ^ S[19] ^ S[25] ^ S[27] ^ S[31];
+ S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
+ S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
+ S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28];
+ S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29];
+ S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
+ S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
+ S2[28] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[12] ^ S[14] ^ S[16] ^ S[20] ^ S[22] ^ S[26] ^ S[28];
+ S2[29] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[13] ^ S[15] ^ S[17] ^ S[21] ^ S[23] ^ S[27] ^ S[29];
+ S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30];
+ S2[31] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[15] ^ S[17] ^ S[19] ^ S[23] ^ S[25] ^ S[29] ^ S[31];
+
+ hash.copy(S2, 32);
+ }
+ }
+
+/**
+* Produce the final GOST 34.11 output
+*/
+void GOST_34_11::final_result(byte out[])
+ {
+ if(position)
+ {
+ clear_mem(buffer.begin() + position, buffer.size() - position);
+ compress_n(buffer, 1);
+ }
+
+ SecureBuffer<byte, 32> length_buf;
+ const u64bit bit_count = count * 8;
+ store_le(bit_count, length_buf);
+
+ SecureBuffer<byte, 32> sum_buf(sum);
+
+ compress_n(length_buf, 1);
+ compress_n(sum_buf, 1);
+
+ copy_mem(out, hash.begin(), 32);
+
+ clear();
+ }
+
+}
diff --git a/botan/src/hash/gost_3411/gost_3411.h b/botan/src/hash/gost_3411/gost_3411.h
new file mode 100644
index 0000000..c695550
--- /dev/null
+++ b/botan/src/hash/gost_3411/gost_3411.h
@@ -0,0 +1,41 @@
+/**
+* GOST 34.11
+* (C) 2009 Jack Lloyd
+*/
+
+#ifndef BOTAN_GOST_3411_H__
+#define BOTAN_GOST_3411_H__
+
+#include <botan/hash.h>
+#include <botan/gost_28147.h>
+
+namespace Botan {
+
+/**
+* GOST 34.11
+*/
+class BOTAN_DLL GOST_34_11 : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "GOST-R-34.11-94" ; }
+ HashFunction* clone() const { return new GOST_34_11; }
+
+ GOST_34_11();
+ protected:
+ void compress_n(const byte input[], u32bit blocks);
+
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+
+ GOST_28147_89 cipher;
+ SecureBuffer<byte, 32> buffer;
+ SecureBuffer<byte, 32> sum;
+ SecureBuffer<byte, 32> hash;
+ u64bit count;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/gost_3411/info.txt b/botan/src/hash/gost_3411/info.txt
new file mode 100644
index 0000000..65b9475
--- /dev/null
+++ b/botan/src/hash/gost_3411/info.txt
@@ -0,0 +1,14 @@
+realname "GOST 34.11"
+
+define GOST_34_11
+
+load_on auto
+
+<add>
+gost_3411.cpp
+gost_3411.h
+</add>
+
+<requires>
+gost_28147
+</requires>
diff --git a/botan/src/hash/has160/has160.cpp b/botan/src/hash/has160/has160.cpp
new file mode 100644
index 0000000..9a505d3
--- /dev/null
+++ b/botan/src/hash/has160/has160.cpp
@@ -0,0 +1,159 @@
+/*
+* HAS-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/has160.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* HAS-160 F1 Function
+*/
+inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E,
+ u32bit msg, u32bit rot)
+ {
+ E += rotate_left(A, rot) + (D ^ (B & (C ^ D))) + msg;
+ B = rotate_left(B, 10);
+ }
+
+/*
+* HAS-160 F2 Function
+*/
+inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E,
+ u32bit msg, u32bit rot)
+ {
+ E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x5A827999;
+ B = rotate_left(B, 17);
+ }
+
+/*
+* HAS-160 F3 Function
+*/
+inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E,
+ u32bit msg, u32bit rot)
+ {
+ E += rotate_left(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1;
+ B = rotate_left(B, 25);
+ }
+
+/*
+* HAS-160 F4 Function
+*/
+inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E,
+ u32bit msg, u32bit rot)
+ {
+ E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC;
+ B = rotate_left(B, 30);
+ }
+
+}
+
+/*
+* HAS-160 Compression Function
+*/
+void HAS_160::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ X[j] = load_le<u32bit>(input, j);
+
+ u32bit A = digest[0], B = digest[1], C = digest[2],
+ D = digest[3], E = digest[4];
+
+ X[16] = X[ 0] ^ X[ 1] ^ X[ 2] ^ X[ 3];
+ X[17] = X[ 4] ^ X[ 5] ^ X[ 6] ^ X[ 7];
+ X[18] = X[ 8] ^ X[ 9] ^ X[10] ^ X[11];
+ X[19] = X[12] ^ X[13] ^ X[14] ^ X[15];
+ F1(A,B,C,D,E,X[18], 5); F1(E,A,B,C,D,X[ 0],11);
+ F1(D,E,A,B,C,X[ 1], 7); F1(C,D,E,A,B,X[ 2],15);
+ F1(B,C,D,E,A,X[ 3], 6); F1(A,B,C,D,E,X[19],13);
+ F1(E,A,B,C,D,X[ 4], 8); F1(D,E,A,B,C,X[ 5],14);
+ F1(C,D,E,A,B,X[ 6], 7); F1(B,C,D,E,A,X[ 7],12);
+ F1(A,B,C,D,E,X[16], 9); F1(E,A,B,C,D,X[ 8],11);
+ F1(D,E,A,B,C,X[ 9], 8); F1(C,D,E,A,B,X[10],15);
+ F1(B,C,D,E,A,X[11], 6); F1(A,B,C,D,E,X[17],12);
+ F1(E,A,B,C,D,X[12], 9); F1(D,E,A,B,C,X[13],14);
+ F1(C,D,E,A,B,X[14], 5); F1(B,C,D,E,A,X[15],13);
+
+ X[16] = X[ 3] ^ X[ 6] ^ X[ 9] ^ X[12];
+ X[17] = X[ 2] ^ X[ 5] ^ X[ 8] ^ X[15];
+ X[18] = X[ 1] ^ X[ 4] ^ X[11] ^ X[14];
+ X[19] = X[ 0] ^ X[ 7] ^ X[10] ^ X[13];
+ F2(A,B,C,D,E,X[18], 5); F2(E,A,B,C,D,X[ 3],11);
+ F2(D,E,A,B,C,X[ 6], 7); F2(C,D,E,A,B,X[ 9],15);
+ F2(B,C,D,E,A,X[12], 6); F2(A,B,C,D,E,X[19],13);
+ F2(E,A,B,C,D,X[15], 8); F2(D,E,A,B,C,X[ 2],14);
+ F2(C,D,E,A,B,X[ 5], 7); F2(B,C,D,E,A,X[ 8],12);
+ F2(A,B,C,D,E,X[16], 9); F2(E,A,B,C,D,X[11],11);
+ F2(D,E,A,B,C,X[14], 8); F2(C,D,E,A,B,X[ 1],15);
+ F2(B,C,D,E,A,X[ 4], 6); F2(A,B,C,D,E,X[17],12);
+ F2(E,A,B,C,D,X[ 7], 9); F2(D,E,A,B,C,X[10],14);
+ F2(C,D,E,A,B,X[13], 5); F2(B,C,D,E,A,X[ 0],13);
+
+ X[16] = X[ 5] ^ X[ 7] ^ X[12] ^ X[14];
+ X[17] = X[ 0] ^ X[ 2] ^ X[ 9] ^ X[11];
+ X[18] = X[ 4] ^ X[ 6] ^ X[13] ^ X[15];
+ X[19] = X[ 1] ^ X[ 3] ^ X[ 8] ^ X[10];
+ F3(A,B,C,D,E,X[18], 5); F3(E,A,B,C,D,X[12],11);
+ F3(D,E,A,B,C,X[ 5], 7); F3(C,D,E,A,B,X[14],15);
+ F3(B,C,D,E,A,X[ 7], 6); F3(A,B,C,D,E,X[19],13);
+ F3(E,A,B,C,D,X[ 0], 8); F3(D,E,A,B,C,X[ 9],14);
+ F3(C,D,E,A,B,X[ 2], 7); F3(B,C,D,E,A,X[11],12);
+ F3(A,B,C,D,E,X[16], 9); F3(E,A,B,C,D,X[ 4],11);
+ F3(D,E,A,B,C,X[13], 8); F3(C,D,E,A,B,X[ 6],15);
+ F3(B,C,D,E,A,X[15], 6); F3(A,B,C,D,E,X[17],12);
+ F3(E,A,B,C,D,X[ 8], 9); F3(D,E,A,B,C,X[ 1],14);
+ F3(C,D,E,A,B,X[10], 5); F3(B,C,D,E,A,X[ 3],13);
+
+ X[16] = X[ 2] ^ X[ 7] ^ X[ 8] ^ X[13];
+ X[17] = X[ 3] ^ X[ 4] ^ X[ 9] ^ X[14];
+ X[18] = X[ 0] ^ X[ 5] ^ X[10] ^ X[15];
+ X[19] = X[ 1] ^ X[ 6] ^ X[11] ^ X[12];
+ F4(A,B,C,D,E,X[18], 5); F4(E,A,B,C,D,X[ 7],11);
+ F4(D,E,A,B,C,X[ 2], 7); F4(C,D,E,A,B,X[13],15);
+ F4(B,C,D,E,A,X[ 8], 6); F4(A,B,C,D,E,X[19],13);
+ F4(E,A,B,C,D,X[ 3], 8); F4(D,E,A,B,C,X[14],14);
+ F4(C,D,E,A,B,X[ 9], 7); F4(B,C,D,E,A,X[ 4],12);
+ F4(A,B,C,D,E,X[16], 9); F4(E,A,B,C,D,X[15],11);
+ F4(D,E,A,B,C,X[10], 8); F4(C,D,E,A,B,X[ 5],15);
+ F4(B,C,D,E,A,X[ 0], 6); F4(A,B,C,D,E,X[17],12);
+ F4(E,A,B,C,D,X[11], 9); F4(D,E,A,B,C,X[ 6],14);
+ F4(C,D,E,A,B,X[ 1], 5); F4(B,C,D,E,A,X[12],13);
+
+ digest[0] += A; digest[1] += B; digest[2] += C;
+ digest[3] += D; digest[4] += E;
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void HAS_160::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_le(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HAS_160::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ X.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ digest[4] = 0xC3D2E1F0;
+ }
+
+}
diff --git a/botan/src/hash/has160/has160.h b/botan/src/hash/has160/has160.h
new file mode 100644
index 0000000..44bb63b
--- /dev/null
+++ b/botan/src/hash/has160/has160.h
@@ -0,0 +1,35 @@
+/*
+* HAS-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HAS_160_H__
+#define BOTAN_HAS_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* HAS-160
+*/
+class BOTAN_DLL HAS_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "HAS-160"; }
+ HashFunction* clone() const { return new HAS_160; }
+ HAS_160() : MDx_HashFunction(20, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 20> X;
+ SecureBuffer<u32bit, 5> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/has160/info.txt b/botan/src/hash/has160/info.txt
new file mode 100644
index 0000000..a945f32
--- /dev/null
+++ b/botan/src/hash/has160/info.txt
@@ -0,0 +1,14 @@
+realname "HAS-160"
+
+define HAS_160
+
+load_on auto
+
+<add>
+has160.cpp
+has160.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/hash.h b/botan/src/hash/hash.h
new file mode 100644
index 0000000..a30234b
--- /dev/null
+++ b/botan/src/hash/hash.h
@@ -0,0 +1,52 @@
+/**
+* Hash Function Base Class
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HASH_FUNCTION_BASE_CLASS_H__
+#define BOTAN_HASH_FUNCTION_BASE_CLASS_H__
+
+#include <botan/buf_comp.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents hash function (message digest) objects.
+*/
+class BOTAN_DLL HashFunction : public BufferedComputation
+ {
+ public:
+ /**
+ * The hash block size as defined for this algorithm.
+ */
+ const u32bit HASH_BLOCK_SIZE;
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual HashFunction* clone() const = 0;
+
+ /**
+ * Get the name of this algorithm.
+ * @return the name of this algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Reset the internal state of this object.
+ */
+ virtual void clear() throw() = 0;
+
+ HashFunction(u32bit hash_len, u32bit block_len = 0) :
+ BufferedComputation(hash_len), HASH_BLOCK_SIZE(block_len) {}
+ virtual ~HashFunction() {}
+ private:
+ HashFunction& operator=(const HashFunction&);
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/info.txt b/botan/src/hash/info.txt
new file mode 100644
index 0000000..ce55f7d
--- /dev/null
+++ b/botan/src/hash/info.txt
@@ -0,0 +1,11 @@
+realname "Hash Functions"
+
+load_on auto
+
+<add>
+hash.h
+</add>
+
+<requires>
+buf_comp
+</requires>
diff --git a/botan/src/hash/md2/info.txt b/botan/src/hash/md2/info.txt
new file mode 100644
index 0000000..ff33e1e
--- /dev/null
+++ b/botan/src/hash/md2/info.txt
@@ -0,0 +1,10 @@
+realname "MD2"
+
+define MD2
+
+load_on auto
+
+<add>
+md2.cpp
+md2.h
+</add>
diff --git a/botan/src/hash/md2/md2.cpp b/botan/src/hash/md2/md2.cpp
new file mode 100644
index 0000000..c67e72b
--- /dev/null
+++ b/botan/src/hash/md2/md2.cpp
@@ -0,0 +1,108 @@
+/*
+* MD2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/md2.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/**
+* MD2 Compression Function
+*/
+void MD2::hash(const byte input[])
+ {
+ static const byte SBOX[256] = {
+ 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 };
+
+ X.copy(16, input, HASH_BLOCK_SIZE);
+ xor_buf(X + 32, X, X + 16, HASH_BLOCK_SIZE);
+ byte T = 0;
+ for(u32bit j = 0; j != 18; ++j)
+ {
+ for(u32bit k = 0; k != 48; k += 8)
+ {
+ T = X[k ] ^= SBOX[T]; T = X[k+1] ^= SBOX[T];
+ T = X[k+2] ^= SBOX[T]; T = X[k+3] ^= SBOX[T];
+ T = X[k+4] ^= SBOX[T]; T = X[k+5] ^= SBOX[T];
+ T = X[k+6] ^= SBOX[T]; T = X[k+7] ^= SBOX[T];
+ }
+ T += j;
+ }
+ T = checksum[15];
+ for(u32bit j = 0; j != HASH_BLOCK_SIZE; ++j)
+ T = checksum[j] ^= SBOX[input[j] ^ T];
+ }
+
+/**
+* Update the hash
+*/
+void MD2::add_data(const byte input[], u32bit length)
+ {
+ buffer.copy(position, input, length);
+ if(position + length >= HASH_BLOCK_SIZE)
+ {
+ hash(buffer.begin());
+ input += (HASH_BLOCK_SIZE - position);
+ length -= (HASH_BLOCK_SIZE - position);
+ while(length >= HASH_BLOCK_SIZE)
+ {
+ hash(input);
+ input += HASH_BLOCK_SIZE;
+ length -= HASH_BLOCK_SIZE;
+ }
+ buffer.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/**
+* Finalize a MD2 Hash
+*/
+void MD2::final_result(byte output[])
+ {
+ for(u32bit j = position; j != HASH_BLOCK_SIZE; ++j)
+ buffer[j] = static_cast<byte>(HASH_BLOCK_SIZE - position);
+ hash(buffer);
+ hash(checksum);
+ copy_mem(output, X.begin(), OUTPUT_LENGTH);
+ clear();
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void MD2::clear() throw()
+ {
+ X.clear();
+ checksum.clear();
+ buffer.clear();
+ position = 0;
+ }
+
+}
diff --git a/botan/src/hash/md2/md2.h b/botan/src/hash/md2/md2.h
new file mode 100644
index 0000000..9337c43
--- /dev/null
+++ b/botan/src/hash/md2/md2.h
@@ -0,0 +1,37 @@
+/*
+* MD2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD2_H__
+#define BOTAN_MD2_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* MD2
+*/
+class BOTAN_DLL MD2 : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD2"; }
+ HashFunction* clone() const { return new MD2; }
+ MD2() : HashFunction(16, 16) { clear(); }
+ private:
+ void add_data(const byte[], u32bit);
+ void hash(const byte[]);
+ void final_result(byte[]);
+
+ SecureBuffer<byte, 48> X;
+ SecureBuffer<byte, 16> checksum, buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/md4/info.txt b/botan/src/hash/md4/info.txt
new file mode 100644
index 0000000..fc9cbe1
--- /dev/null
+++ b/botan/src/hash/md4/info.txt
@@ -0,0 +1,14 @@
+realname "MD4"
+
+define MD4
+
+load_on auto
+
+<add>
+md4.cpp
+md4.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/md4/md4.cpp b/botan/src/hash/md4/md4.cpp
new file mode 100644
index 0000000..39e3c8c
--- /dev/null
+++ b/botan/src/hash/md4/md4.cpp
@@ -0,0 +1,108 @@
+/*
+* MD4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/md4.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* MD4 FF Function
+*/
+inline void FF(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S)
+ {
+ A += (D ^ (B & (C ^ D))) + M;
+ A = rotate_left(A, S);
+ }
+
+/*
+* MD4 GG Function
+*/
+inline void GG(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S)
+ {
+ A += ((B & C) | (D & (B | C))) + M + 0x5A827999;
+ A = rotate_left(A, S);
+ }
+
+/*
+* MD4 HH Function
+*/
+inline void HH(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit M, byte S)
+ {
+ A += (B ^ C ^ D) + M + 0x6ED9EBA1;
+ A = rotate_left(A, S);
+ }
+
+}
+
+/*
+* MD4 Compression Function
+*/
+void MD4::compress_n(const byte input[], u32bit blocks)
+ {
+ u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ M[j] = load_le<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ FF(A,B,C,D,M[ 0], 3); FF(D,A,B,C,M[ 1], 7); FF(C,D,A,B,M[ 2],11);
+ FF(B,C,D,A,M[ 3],19); FF(A,B,C,D,M[ 4], 3); FF(D,A,B,C,M[ 5], 7);
+ FF(C,D,A,B,M[ 6],11); FF(B,C,D,A,M[ 7],19); FF(A,B,C,D,M[ 8], 3);
+ FF(D,A,B,C,M[ 9], 7); FF(C,D,A,B,M[10],11); FF(B,C,D,A,M[11],19);
+ FF(A,B,C,D,M[12], 3); FF(D,A,B,C,M[13], 7); FF(C,D,A,B,M[14],11);
+ FF(B,C,D,A,M[15],19);
+
+ GG(A,B,C,D,M[ 0], 3); GG(D,A,B,C,M[ 4], 5); GG(C,D,A,B,M[ 8], 9);
+ GG(B,C,D,A,M[12],13); GG(A,B,C,D,M[ 1], 3); GG(D,A,B,C,M[ 5], 5);
+ GG(C,D,A,B,M[ 9], 9); GG(B,C,D,A,M[13],13); GG(A,B,C,D,M[ 2], 3);
+ GG(D,A,B,C,M[ 6], 5); GG(C,D,A,B,M[10], 9); GG(B,C,D,A,M[14],13);
+ GG(A,B,C,D,M[ 3], 3); GG(D,A,B,C,M[ 7], 5); GG(C,D,A,B,M[11], 9);
+ GG(B,C,D,A,M[15],13);
+
+ HH(A,B,C,D,M[ 0], 3); HH(D,A,B,C,M[ 8], 9); HH(C,D,A,B,M[ 4],11);
+ HH(B,C,D,A,M[12],15); HH(A,B,C,D,M[ 2], 3); HH(D,A,B,C,M[10], 9);
+ HH(C,D,A,B,M[ 6],11); HH(B,C,D,A,M[14],15); HH(A,B,C,D,M[ 1], 3);
+ HH(D,A,B,C,M[ 9], 9); HH(C,D,A,B,M[ 5],11); HH(B,C,D,A,M[13],15);
+ HH(A,B,C,D,M[ 3], 3); HH(D,A,B,C,M[11], 9); HH(C,D,A,B,M[ 7],11);
+ HH(B,C,D,A,M[15],15);
+
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void MD4::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_le(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void MD4::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ M.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ }
+
+}
diff --git a/botan/src/hash/md4/md4.h b/botan/src/hash/md4/md4.h
new file mode 100644
index 0000000..df6f229
--- /dev/null
+++ b/botan/src/hash/md4/md4.h
@@ -0,0 +1,36 @@
+/*
+* MD4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD4_H__
+#define BOTAN_MD4_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* MD4
+*/
+class BOTAN_DLL MD4 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD4"; }
+ HashFunction* clone() const { return new MD4; }
+ MD4() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ protected:
+ void compress_n(const byte input[], u32bit blocks);
+ void hash_old(const byte[]);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 48> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/md4_ia32/info.txt b/botan/src/hash/md4_ia32/info.txt
new file mode 100644
index 0000000..fee7dd1
--- /dev/null
+++ b/botan/src/hash/md4_ia32/info.txt
@@ -0,0 +1,35 @@
+realname "MD4 (IA-32)"
+
+define MD4_IA32
+
+load_on asm_ok
+
+<add>
+md4_ia32_imp.S
+md4_ia32.cpp
+md4_ia32.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_ia32
+md4
+</requires>
diff --git a/botan/src/hash/md4_ia32/md4_ia32.cpp b/botan/src/hash/md4_ia32/md4_ia32.cpp
new file mode 100644
index 0000000..12fe71d
--- /dev/null
+++ b/botan/src/hash/md4_ia32/md4_ia32.cpp
@@ -0,0 +1,27 @@
+/*
+* MD4 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/md4_ia32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+extern "C" void botan_md4_ia32_compress(u32bit[4], const byte[64], u32bit[16]);
+
+/*
+* MD4 Compression Function
+*/
+void MD4_IA32::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ botan_md4_ia32_compress(digest, input, M);
+ input += HASH_BLOCK_SIZE;
+ }
+ }
+
+}
diff --git a/botan/src/hash/md4_ia32/md4_ia32.h b/botan/src/hash/md4_ia32/md4_ia32.h
new file mode 100644
index 0000000..f01d148
--- /dev/null
+++ b/botan/src/hash/md4_ia32/md4_ia32.h
@@ -0,0 +1,28 @@
+/*
+* MD4 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD4_IA32_H__
+#define BOTAN_MD4_IA32_H__
+
+#include <botan/md4.h>
+
+namespace Botan {
+
+/*
+* MD4
+*/
+class BOTAN_DLL MD4_IA32 : public MD4
+ {
+ public:
+ HashFunction* clone() const { return new MD4_IA32; }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/md4_ia32/md4_ia32_imp.S b/botan/src/hash/md4_ia32/md4_ia32_imp.S
new file mode 100644
index 0000000..ca04cbe
--- /dev/null
+++ b/botan/src/hash/md4_ia32/md4_ia32_imp.S
@@ -0,0 +1,137 @@
+/*
+* MD4 Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(md4_ia32.S)
+
+START_FUNCTION(botan_md4_ia32_compress)
+ SPILL_REGS()
+
+#define PUSHED 4
+
+ ASSIGN(EBP, ARG(2)) /* input block */
+ ASSIGN(EDI, ARG(3)) /* expanded words */
+
+ ZEROIZE(ESI)
+
+START_LOOP(.LOAD_INPUT)
+ ADD_IMM(ESI, 4)
+
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+ ADD_IMM(EBP, 16)
+
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-4), EAX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-3), EBX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-2), ECX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-1), EDX)
+LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
+
+ ASSIGN(EBP, ARG(1))
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+#define MSG EDI
+#define T1 ESI
+#define T2 EBP
+
+#define FF(A, B, C, D, N, S) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, C) ; \
+ XOR(T2, D) ; \
+ AND(T2, B) ; \
+ XOR(T2, D) ; \
+ ADD(A, T1) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ;
+
+#define GG(A, B, C, D, N, S) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, B) ; \
+ OR(T2, C) ; \
+ AND(T2, D) ; \
+ ADD3_IMM(A, T1, 0x5A827999) ; \
+ ASSIGN(T1, B) ; \
+ AND(T1, C) ; \
+ OR(T2, T1) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ;
+
+#define HH(A, B, C, D, N, S) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, B) ; \
+ XOR(T2, C) ; \
+ XOR(T2, D) ; \
+ ADD3_IMM(A, T1, 0x6ED9EBA1) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ;
+
+ FF(EAX,EBX,ECX,EDX, 0, 3);
+ FF(EDX,EAX,EBX,ECX, 1, 7);
+ FF(ECX,EDX,EAX,EBX, 2,11);
+ FF(EBX,ECX,EDX,EAX, 3,19);
+ FF(EAX,EBX,ECX,EDX, 4, 3);
+ FF(EDX,EAX,EBX,ECX, 5, 7);
+ FF(ECX,EDX,EAX,EBX, 6,11);
+ FF(EBX,ECX,EDX,EAX, 7,19);
+ FF(EAX,EBX,ECX,EDX, 8, 3);
+ FF(EDX,EAX,EBX,ECX, 9, 7);
+ FF(ECX,EDX,EAX,EBX,10,11);
+ FF(EBX,ECX,EDX,EAX,11,19);
+ FF(EAX,EBX,ECX,EDX,12, 3);
+ FF(EDX,EAX,EBX,ECX,13, 7);
+ FF(ECX,EDX,EAX,EBX,14,11);
+ FF(EBX,ECX,EDX,EAX,15,19);
+
+ GG(EAX,EBX,ECX,EDX, 0, 3);
+ GG(EDX,EAX,EBX,ECX, 4, 5);
+ GG(ECX,EDX,EAX,EBX, 8, 9);
+ GG(EBX,ECX,EDX,EAX,12,13);
+ GG(EAX,EBX,ECX,EDX, 1, 3);
+ GG(EDX,EAX,EBX,ECX, 5, 5);
+ GG(ECX,EDX,EAX,EBX, 9, 9);
+ GG(EBX,ECX,EDX,EAX,13,13);
+ GG(EAX,EBX,ECX,EDX, 2, 3);
+ GG(EDX,EAX,EBX,ECX, 6, 5);
+ GG(ECX,EDX,EAX,EBX,10, 9);
+ GG(EBX,ECX,EDX,EAX,14,13);
+ GG(EAX,EBX,ECX,EDX, 3, 3);
+ GG(EDX,EAX,EBX,ECX, 7, 5);
+ GG(ECX,EDX,EAX,EBX,11, 9);
+ GG(EBX,ECX,EDX,EAX,15,13);
+
+ HH(EAX,EBX,ECX,EDX, 0, 3);
+ HH(EDX,EAX,EBX,ECX, 8, 9);
+ HH(ECX,EDX,EAX,EBX, 4,11);
+ HH(EBX,ECX,EDX,EAX,12,15);
+ HH(EAX,EBX,ECX,EDX, 2, 3);
+ HH(EDX,EAX,EBX,ECX,10, 9);
+ HH(ECX,EDX,EAX,EBX, 6,11);
+ HH(EBX,ECX,EDX,EAX,14,15);
+ HH(EAX,EBX,ECX,EDX, 1, 3);
+ HH(EDX,EAX,EBX,ECX, 9, 9);
+ HH(ECX,EDX,EAX,EBX, 5,11);
+ HH(EBX,ECX,EDX,EAX,13,15);
+ HH(EAX,EBX,ECX,EDX, 3, 3);
+ HH(EDX,EAX,EBX,ECX,11, 9);
+ HH(ECX,EDX,EAX,EBX, 7,11);
+ HH(EBX,ECX,EDX,EAX,15,15);
+
+ ASSIGN(EBP, ARG(1))
+ ADD(ARRAY4(EBP, 0), EAX)
+ ADD(ARRAY4(EBP, 1), EBX)
+ ADD(ARRAY4(EBP, 2), ECX)
+ ADD(ARRAY4(EBP, 3), EDX)
+
+ RESTORE_REGS()
+END_FUNCTION(botan_md4_ia32_compress)
diff --git a/botan/src/hash/md5/info.txt b/botan/src/hash/md5/info.txt
new file mode 100644
index 0000000..525a45a
--- /dev/null
+++ b/botan/src/hash/md5/info.txt
@@ -0,0 +1,14 @@
+realname "MD5"
+
+define MD5
+
+load_on auto
+
+<add>
+md5.cpp
+md5.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/md5/md5.cpp b/botan/src/hash/md5/md5.cpp
new file mode 100644
index 0000000..7c280aa
--- /dev/null
+++ b/botan/src/hash/md5/md5.cpp
@@ -0,0 +1,136 @@
+/*
+* MD5
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/md5.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* MD5 FF Function
+*/
+inline void FF(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg,
+ byte S, u32bit magic)
+ {
+ A += (D ^ (B & (C ^ D))) + msg + magic;
+ A = rotate_left(A, S) + B;
+ }
+
+/*
+* MD5 GG Function
+*/
+inline void GG(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg,
+ byte S, u32bit magic)
+ {
+ A += (C ^ (D & (B ^ C))) + msg + magic;
+ A = rotate_left(A, S) + B;
+ }
+
+/*
+* MD5 HH Function
+*/
+inline void HH(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg,
+ byte S, u32bit magic)
+ {
+ A += (B ^ C ^ D) + msg + magic;
+ A = rotate_left(A, S) + B;
+ }
+
+/*
+* MD5 II Function
+*/
+inline void II(u32bit& A, u32bit B, u32bit C, u32bit D, u32bit msg,
+ byte S, u32bit magic)
+ {
+ A += (C ^ (B | ~D)) + msg + magic;
+ A = rotate_left(A, S) + B;
+ }
+
+}
+
+/*
+* MD5 Compression Function
+*/
+void MD5::compress_n(const byte input[], u32bit blocks)
+ {
+ u32bit A = digest[0], B = digest[1], C = digest[2], D = digest[3];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ M[j] = load_le<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ FF(A,B,C,D,M[ 0], 7,0xD76AA478); FF(D,A,B,C,M[ 1],12,0xE8C7B756);
+ FF(C,D,A,B,M[ 2],17,0x242070DB); FF(B,C,D,A,M[ 3],22,0xC1BDCEEE);
+ FF(A,B,C,D,M[ 4], 7,0xF57C0FAF); FF(D,A,B,C,M[ 5],12,0x4787C62A);
+ FF(C,D,A,B,M[ 6],17,0xA8304613); FF(B,C,D,A,M[ 7],22,0xFD469501);
+ FF(A,B,C,D,M[ 8], 7,0x698098D8); FF(D,A,B,C,M[ 9],12,0x8B44F7AF);
+ FF(C,D,A,B,M[10],17,0xFFFF5BB1); FF(B,C,D,A,M[11],22,0x895CD7BE);
+ FF(A,B,C,D,M[12], 7,0x6B901122); FF(D,A,B,C,M[13],12,0xFD987193);
+ FF(C,D,A,B,M[14],17,0xA679438E); FF(B,C,D,A,M[15],22,0x49B40821);
+
+ GG(A,B,C,D,M[ 1], 5,0xF61E2562); GG(D,A,B,C,M[ 6], 9,0xC040B340);
+ GG(C,D,A,B,M[11],14,0x265E5A51); GG(B,C,D,A,M[ 0],20,0xE9B6C7AA);
+ GG(A,B,C,D,M[ 5], 5,0xD62F105D); GG(D,A,B,C,M[10], 9,0x02441453);
+ GG(C,D,A,B,M[15],14,0xD8A1E681); GG(B,C,D,A,M[ 4],20,0xE7D3FBC8);
+ GG(A,B,C,D,M[ 9], 5,0x21E1CDE6); GG(D,A,B,C,M[14], 9,0xC33707D6);
+ GG(C,D,A,B,M[ 3],14,0xF4D50D87); GG(B,C,D,A,M[ 8],20,0x455A14ED);
+ GG(A,B,C,D,M[13], 5,0xA9E3E905); GG(D,A,B,C,M[ 2], 9,0xFCEFA3F8);
+ GG(C,D,A,B,M[ 7],14,0x676F02D9); GG(B,C,D,A,M[12],20,0x8D2A4C8A);
+
+ HH(A,B,C,D,M[ 5], 4,0xFFFA3942); HH(D,A,B,C,M[ 8],11,0x8771F681);
+ HH(C,D,A,B,M[11],16,0x6D9D6122); HH(B,C,D,A,M[14],23,0xFDE5380C);
+ HH(A,B,C,D,M[ 1], 4,0xA4BEEA44); HH(D,A,B,C,M[ 4],11,0x4BDECFA9);
+ HH(C,D,A,B,M[ 7],16,0xF6BB4B60); HH(B,C,D,A,M[10],23,0xBEBFBC70);
+ HH(A,B,C,D,M[13], 4,0x289B7EC6); HH(D,A,B,C,M[ 0],11,0xEAA127FA);
+ HH(C,D,A,B,M[ 3],16,0xD4EF3085); HH(B,C,D,A,M[ 6],23,0x04881D05);
+ HH(A,B,C,D,M[ 9], 4,0xD9D4D039); HH(D,A,B,C,M[12],11,0xE6DB99E5);
+ HH(C,D,A,B,M[15],16,0x1FA27CF8); HH(B,C,D,A,M[ 2],23,0xC4AC5665);
+
+ II(A,B,C,D,M[ 0], 6,0xF4292244); II(D,A,B,C,M[ 7],10,0x432AFF97);
+ II(C,D,A,B,M[14],15,0xAB9423A7); II(B,C,D,A,M[ 5],21,0xFC93A039);
+ II(A,B,C,D,M[12], 6,0x655B59C3); II(D,A,B,C,M[ 3],10,0x8F0CCC92);
+ II(C,D,A,B,M[10],15,0xFFEFF47D); II(B,C,D,A,M[ 1],21,0x85845DD1);
+ II(A,B,C,D,M[ 8], 6,0x6FA87E4F); II(D,A,B,C,M[15],10,0xFE2CE6E0);
+ II(C,D,A,B,M[ 6],15,0xA3014314); II(B,C,D,A,M[13],21,0x4E0811A1);
+ II(A,B,C,D,M[ 4], 6,0xF7537E82); II(D,A,B,C,M[11],10,0xBD3AF235);
+ II(C,D,A,B,M[ 2],15,0x2AD7D2BB); II(B,C,D,A,M[ 9],21,0xEB86D391);
+
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void MD5::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_le(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void MD5::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ M.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ }
+
+}
diff --git a/botan/src/hash/md5/md5.h b/botan/src/hash/md5/md5.h
new file mode 100644
index 0000000..85f684d
--- /dev/null
+++ b/botan/src/hash/md5/md5.h
@@ -0,0 +1,35 @@
+/**
+* MD5
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD5_H__
+#define BOTAN_MD5_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/**
+* MD5
+*/
+class BOTAN_DLL MD5 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "MD5"; }
+ HashFunction* clone() const { return new MD5; }
+ MD5() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ protected:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/md5_ia32/info.txt b/botan/src/hash/md5_ia32/info.txt
new file mode 100644
index 0000000..ad9923b
--- /dev/null
+++ b/botan/src/hash/md5_ia32/info.txt
@@ -0,0 +1,35 @@
+realname "MD5 (IA-32)"
+
+define MD5_IA32
+
+load_on asm_ok
+
+<add>
+md5_ia32_imp.S
+md5_ia32.cpp
+md5_ia32.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_ia32
+md5
+</requires>
diff --git a/botan/src/hash/md5_ia32/md5_ia32.cpp b/botan/src/hash/md5_ia32/md5_ia32.cpp
new file mode 100644
index 0000000..443569b
--- /dev/null
+++ b/botan/src/hash/md5_ia32/md5_ia32.cpp
@@ -0,0 +1,32 @@
+/*
+* MD5 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/md5_ia32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace {
+
+extern "C"
+void botan_md5_ia32_compress(u32bit[4], const byte[64], u32bit[16]);
+
+}
+
+/*
+* MD5 Compression Function
+*/
+void MD5_IA32::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ botan_md5_ia32_compress(digest, input, M);
+ input += HASH_BLOCK_SIZE;
+ }
+ }
+
+}
diff --git a/botan/src/hash/md5_ia32/md5_ia32.h b/botan/src/hash/md5_ia32/md5_ia32.h
new file mode 100644
index 0000000..723d724
--- /dev/null
+++ b/botan/src/hash/md5_ia32/md5_ia32.h
@@ -0,0 +1,28 @@
+/*
+* MD5 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MD5_IA32_H__
+#define BOTAN_MD5_IA32_H__
+
+#include <botan/md5.h>
+
+namespace Botan {
+
+/*
+* MD5
+*/
+class BOTAN_DLL MD5_IA32 : public MD5
+ {
+ public:
+ HashFunction* clone() const { return new MD5_IA32; }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/md5_ia32/md5_ia32_imp.S b/botan/src/hash/md5_ia32/md5_ia32_imp.S
new file mode 100644
index 0000000..8087bbd
--- /dev/null
+++ b/botan/src/hash/md5_ia32/md5_ia32_imp.S
@@ -0,0 +1,166 @@
+/*
+* MD5 Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(md5_ia32.S)
+
+START_FUNCTION(botan_md5_ia32_compress)
+ SPILL_REGS()
+
+#define PUSHED 4
+
+ ASSIGN(EBP, ARG(2)) /* input block */
+ ASSIGN(EDI, ARG(3)) /* expanded words */
+
+ ZEROIZE(ESI)
+
+START_LOOP(.LOAD_INPUT)
+ ADD_IMM(ESI, 4)
+
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+ ADD_IMM(EBP, 16)
+
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-4), EAX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-3), EBX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-2), ECX)
+ ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-1), EDX)
+LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
+
+ ASSIGN(EBP, ARG(1))
+ ASSIGN(EAX, ARRAY4(EBP, 0))
+ ASSIGN(EBX, ARRAY4(EBP, 1))
+ ASSIGN(ECX, ARRAY4(EBP, 2))
+ ASSIGN(EDX, ARRAY4(EBP, 3))
+
+#define MSG EDI
+#define T1 ESI
+#define T2 EBP
+
+#define FF(A, B, C, D, N, S, MAGIC) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, C) ; \
+ XOR(T2, D) ; \
+ AND(T2, B) ; \
+ XOR(T2, D) ; \
+ ADD3_IMM(A, T1, MAGIC) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ; \
+ ADD(A, B) ;
+
+#define GG(A, B, C, D, N, S, MAGIC) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, B) ; \
+ XOR(T2, C) ; \
+ AND(T2, D) ; \
+ XOR(T2, C) ; \
+ ADD3_IMM(A, T1, MAGIC) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ; \
+ ADD(A, B) ;
+
+#define HH(A, B, C, D, N, S, MAGIC) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, B) ; \
+ XOR(T2, C) ; \
+ XOR(T2, D) ; \
+ ADD3_IMM(A, T1, MAGIC) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ; \
+ ADD(A, B) ;
+
+#define II(A, B, C, D, N, S, MAGIC) \
+ ASSIGN(T1, ARRAY4(MSG, N)) ; \
+ ASSIGN(T2, D) ; \
+ NOT(T2) ; \
+ OR(T2, B) ; \
+ XOR(T2, C) ; \
+ ADD3_IMM(A, T1, MAGIC) ; \
+ ADD(A, T2) ; \
+ ROTL_IMM(A, S) ; \
+ ADD(A, B) ;
+
+ FF(EAX,EBX,ECX,EDX, 0, 7,0xD76AA478);
+ FF(EDX,EAX,EBX,ECX, 1,12,0xE8C7B756);
+ FF(ECX,EDX,EAX,EBX, 2,17,0x242070DB);
+ FF(EBX,ECX,EDX,EAX, 3,22,0xC1BDCEEE);
+ FF(EAX,EBX,ECX,EDX, 4, 7,0xF57C0FAF);
+ FF(EDX,EAX,EBX,ECX, 5,12,0x4787C62A);
+ FF(ECX,EDX,EAX,EBX, 6,17,0xA8304613);
+ FF(EBX,ECX,EDX,EAX, 7,22,0xFD469501);
+ FF(EAX,EBX,ECX,EDX, 8, 7,0x698098D8);
+ FF(EDX,EAX,EBX,ECX, 9,12,0x8B44F7AF);
+ FF(ECX,EDX,EAX,EBX,10,17,0xFFFF5BB1);
+ FF(EBX,ECX,EDX,EAX,11,22,0x895CD7BE);
+ FF(EAX,EBX,ECX,EDX,12, 7,0x6B901122);
+ FF(EDX,EAX,EBX,ECX,13,12,0xFD987193);
+ FF(ECX,EDX,EAX,EBX,14,17,0xA679438E);
+ FF(EBX,ECX,EDX,EAX,15,22,0x49B40821);
+
+ GG(EAX,EBX,ECX,EDX, 1, 5,0xF61E2562);
+ GG(EDX,EAX,EBX,ECX, 6, 9,0xC040B340);
+ GG(ECX,EDX,EAX,EBX,11,14,0x265E5A51);
+ GG(EBX,ECX,EDX,EAX, 0,20,0xE9B6C7AA);
+ GG(EAX,EBX,ECX,EDX, 5, 5,0xD62F105D);
+ GG(EDX,EAX,EBX,ECX,10, 9,0x02441453);
+ GG(ECX,EDX,EAX,EBX,15,14,0xD8A1E681);
+ GG(EBX,ECX,EDX,EAX, 4,20,0xE7D3FBC8);
+ GG(EAX,EBX,ECX,EDX, 9, 5,0x21E1CDE6);
+ GG(EDX,EAX,EBX,ECX,14, 9,0xC33707D6);
+ GG(ECX,EDX,EAX,EBX, 3,14,0xF4D50D87);
+ GG(EBX,ECX,EDX,EAX, 8,20,0x455A14ED);
+ GG(EAX,EBX,ECX,EDX,13, 5,0xA9E3E905);
+ GG(EDX,EAX,EBX,ECX, 2, 9,0xFCEFA3F8);
+ GG(ECX,EDX,EAX,EBX, 7,14,0x676F02D9);
+ GG(EBX,ECX,EDX,EAX,12,20,0x8D2A4C8A);
+
+ HH(EAX,EBX,ECX,EDX, 5, 4,0xFFFA3942);
+ HH(EDX,EAX,EBX,ECX, 8,11,0x8771F681);
+ HH(ECX,EDX,EAX,EBX,11,16,0x6D9D6122);
+ HH(EBX,ECX,EDX,EAX,14,23,0xFDE5380C);
+ HH(EAX,EBX,ECX,EDX, 1, 4,0xA4BEEA44);
+ HH(EDX,EAX,EBX,ECX, 4,11,0x4BDECFA9);
+ HH(ECX,EDX,EAX,EBX, 7,16,0xF6BB4B60);
+ HH(EBX,ECX,EDX,EAX,10,23,0xBEBFBC70);
+ HH(EAX,EBX,ECX,EDX,13, 4,0x289B7EC6);
+ HH(EDX,EAX,EBX,ECX, 0,11,0xEAA127FA);
+ HH(ECX,EDX,EAX,EBX, 3,16,0xD4EF3085);
+ HH(EBX,ECX,EDX,EAX, 6,23,0x04881D05);
+ HH(EAX,EBX,ECX,EDX, 9, 4,0xD9D4D039);
+ HH(EDX,EAX,EBX,ECX,12,11,0xE6DB99E5);
+ HH(ECX,EDX,EAX,EBX,15,16,0x1FA27CF8);
+ HH(EBX,ECX,EDX,EAX, 2,23,0xC4AC5665);
+
+ II(EAX,EBX,ECX,EDX, 0, 6,0xF4292244);
+ II(EDX,EAX,EBX,ECX, 7,10,0x432AFF97);
+ II(ECX,EDX,EAX,EBX,14,15,0xAB9423A7);
+ II(EBX,ECX,EDX,EAX, 5,21,0xFC93A039);
+ II(EAX,EBX,ECX,EDX,12, 6,0x655B59C3);
+ II(EDX,EAX,EBX,ECX, 3,10,0x8F0CCC92);
+ II(ECX,EDX,EAX,EBX,10,15,0xFFEFF47D);
+ II(EBX,ECX,EDX,EAX, 1,21,0x85845DD1);
+ II(EAX,EBX,ECX,EDX, 8, 6,0x6FA87E4F);
+ II(EDX,EAX,EBX,ECX,15,10,0xFE2CE6E0);
+ II(ECX,EDX,EAX,EBX, 6,15,0xA3014314);
+ II(EBX,ECX,EDX,EAX,13,21,0x4E0811A1);
+ II(EAX,EBX,ECX,EDX, 4, 6,0xF7537E82);
+ II(EDX,EAX,EBX,ECX,11,10,0xBD3AF235);
+ II(ECX,EDX,EAX,EBX, 2,15,0x2AD7D2BB);
+ II(EBX,ECX,EDX,EAX, 9,21,0xEB86D391);
+
+ ASSIGN(EBP, ARG(1))
+ ADD(ARRAY4(EBP, 0), EAX)
+ ADD(ARRAY4(EBP, 1), EBX)
+ ADD(ARRAY4(EBP, 2), ECX)
+ ADD(ARRAY4(EBP, 3), EDX)
+
+ RESTORE_REGS()
+END_FUNCTION(botan_md5_ia32_compress)
diff --git a/botan/src/hash/mdx_hash/info.txt b/botan/src/hash/mdx_hash/info.txt
new file mode 100644
index 0000000..412c933
--- /dev/null
+++ b/botan/src/hash/mdx_hash/info.txt
@@ -0,0 +1,10 @@
+realname "MDx Hash Base"
+
+define MDX_HASH_FUNCTION
+
+load_on dep
+
+<add>
+mdx_hash.cpp
+mdx_hash.h
+</add>
diff --git a/botan/src/hash/mdx_hash/mdx_hash.cpp b/botan/src/hash/mdx_hash/mdx_hash.cpp
new file mode 100644
index 0000000..b630ec2
--- /dev/null
+++ b/botan/src/hash/mdx_hash/mdx_hash.cpp
@@ -0,0 +1,105 @@
+/**
+* Merkle-Damgard Hash Function
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mdx_hash.h>
+#include <botan/exceptn.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/**
+* MDx_HashFunction Constructor
+*/
+MDx_HashFunction::MDx_HashFunction(u32bit hash_len, u32bit block_len,
+ bool byte_end, bool bit_end,
+ u32bit cnt_size) :
+ HashFunction(hash_len, block_len), buffer(block_len),
+ BIG_BYTE_ENDIAN(byte_end), BIG_BIT_ENDIAN(bit_end), COUNT_SIZE(cnt_size)
+ {
+ if(COUNT_SIZE >= OUTPUT_LENGTH || COUNT_SIZE >= HASH_BLOCK_SIZE)
+ throw Invalid_Argument("MDx_HashFunction: COUNT_SIZE is too big");
+ count = position = 0;
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void MDx_HashFunction::clear() throw()
+ {
+ buffer.clear();
+ count = position = 0;
+ }
+
+/**
+* Update the hash
+*/
+void MDx_HashFunction::add_data(const byte input[], u32bit length)
+ {
+ count += length;
+
+ if(position)
+ {
+ buffer.copy(position, input, length);
+
+ if(position + length >= HASH_BLOCK_SIZE)
+ {
+ compress_n(buffer.begin(), 1);
+ input += (HASH_BLOCK_SIZE - position);
+ length -= (HASH_BLOCK_SIZE - position);
+ position = 0;
+ }
+ }
+
+ const u32bit full_blocks = length / HASH_BLOCK_SIZE;
+ const u32bit remaining = length % HASH_BLOCK_SIZE;
+
+ if(full_blocks)
+ compress_n(input, full_blocks);
+
+ buffer.copy(position, input + full_blocks * HASH_BLOCK_SIZE, remaining);
+ position += remaining;
+ }
+
+/**
+* Finalize a hash
+*/
+void MDx_HashFunction::final_result(byte output[])
+ {
+ buffer[position] = (BIG_BIT_ENDIAN ? 0x80 : 0x01);
+ for(u32bit j = position+1; j != HASH_BLOCK_SIZE; ++j)
+ buffer[j] = 0;
+
+ if(position >= HASH_BLOCK_SIZE - COUNT_SIZE)
+ {
+ compress_n(buffer, 1);
+ buffer.clear();
+ }
+
+ write_count(buffer + HASH_BLOCK_SIZE - COUNT_SIZE);
+
+ compress_n(buffer, 1);
+ copy_out(output);
+ clear();
+ }
+
+/**
+* Write the count bits to the buffer
+*/
+void MDx_HashFunction::write_count(byte out[])
+ {
+ if(COUNT_SIZE < 8)
+ throw Invalid_State("MDx_HashFunction::write_count: COUNT_SIZE < 8");
+
+ const u64bit bit_count = count * 8;
+
+ if(BIG_BYTE_ENDIAN)
+ store_be(bit_count, out + COUNT_SIZE - 8);
+ else
+ store_le(bit_count, out + COUNT_SIZE - 8);
+ }
+
+}
diff --git a/botan/src/hash/mdx_hash/mdx_hash.h b/botan/src/hash/mdx_hash/mdx_hash.h
new file mode 100644
index 0000000..0c3aa78
--- /dev/null
+++ b/botan/src/hash/mdx_hash/mdx_hash.h
@@ -0,0 +1,42 @@
+/**
+* MDx Hash Function
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MDX_BASE_H__
+#define BOTAN_MDX_BASE_H__
+
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* MDx Hash Function Base Class
+*/
+class BOTAN_DLL MDx_HashFunction : public HashFunction
+ {
+ public:
+ MDx_HashFunction(u32bit, u32bit, bool, bool, u32bit = 8);
+ virtual ~MDx_HashFunction() {}
+ protected:
+ void add_data(const byte[], u32bit);
+ void final_result(byte output[]);
+ virtual void compress_n(const byte block[], u32bit block_n) = 0;
+
+ void clear() throw();
+ virtual void copy_out(byte[]) = 0;
+ virtual void write_count(byte[]);
+ private:
+ SecureVector<byte> buffer;
+ u64bit count;
+ u32bit position;
+
+ const bool BIG_BYTE_ENDIAN, BIG_BIT_ENDIAN;
+ const u32bit COUNT_SIZE;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/par_hash/info.txt b/botan/src/hash/par_hash/info.txt
new file mode 100644
index 0000000..45716aa
--- /dev/null
+++ b/botan/src/hash/par_hash/info.txt
@@ -0,0 +1,10 @@
+realname "Parallel Hash"
+
+define PARALLEL_HASH
+
+load_on auto
+
+<add>
+par_hash.cpp
+par_hash.h
+</add>
diff --git a/botan/src/hash/par_hash/par_hash.cpp b/botan/src/hash/par_hash/par_hash.cpp
new file mode 100644
index 0000000..4b0c7c4
--- /dev/null
+++ b/botan/src/hash/par_hash/par_hash.cpp
@@ -0,0 +1,103 @@
+/*
+* Parallel
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/par_hash.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Return the sum of the hash sizes
+*/
+u32bit sum_of_hash_lengths(const std::vector<HashFunction*>& hashes)
+ {
+ u32bit sum = 0;
+
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ sum += hashes[j]->OUTPUT_LENGTH;
+
+ return sum;
+ }
+
+}
+
+/*
+* Update the hash
+*/
+void Parallel::add_data(const byte input[], u32bit length)
+ {
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ hashes[j]->update(input, length);
+ }
+
+/*
+* Finalize the hash
+*/
+void Parallel::final_result(byte hash[])
+ {
+ u32bit offset = 0;
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ {
+ hashes[j]->final(hash + offset);
+ offset += hashes[j]->OUTPUT_LENGTH;
+ }
+ }
+
+/*
+* Return the name of this type
+*/
+std::string Parallel::name() const
+ {
+ std::string hash_names;
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ {
+ if(j)
+ hash_names += ',';
+ hash_names += hashes[j]->name();
+ }
+ return "Parallel(" + hash_names + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+HashFunction* Parallel::clone() const
+ {
+ std::vector<HashFunction*> hash_copies;
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ hash_copies.push_back(hashes[j]->clone());
+ return new Parallel(hash_copies);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Parallel::clear() throw()
+ {
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ hashes[j]->clear();
+ }
+
+/*
+* Parallel Constructor
+*/
+Parallel::Parallel(const std::vector<HashFunction*>& hash_in) :
+ HashFunction(sum_of_hash_lengths(hash_in)), hashes(hash_in)
+ {
+ }
+
+/*
+* Parallel Destructor
+*/
+Parallel::~Parallel()
+ {
+ for(u32bit j = 0; j != hashes.size(); ++j)
+ delete hashes[j];
+ }
+
+}
diff --git a/botan/src/hash/par_hash/par_hash.h b/botan/src/hash/par_hash/par_hash.h
new file mode 100644
index 0000000..7e75c27
--- /dev/null
+++ b/botan/src/hash/par_hash/par_hash.h
@@ -0,0 +1,36 @@
+/*
+* Parallel Hash
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PARALLEL_HASH_H__
+#define BOTAN_PARALLEL_HASH_H__
+
+#include <botan/hash.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Parallel
+*/
+class BOTAN_DLL Parallel : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ HashFunction* clone() const;
+
+ Parallel(const std::vector<HashFunction*>&);
+ ~Parallel();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ std::vector<HashFunction*> hashes;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/rmd128/info.txt b/botan/src/hash/rmd128/info.txt
new file mode 100644
index 0000000..402271d
--- /dev/null
+++ b/botan/src/hash/rmd128/info.txt
@@ -0,0 +1,14 @@
+realname "RIPEMD-128"
+
+define RIPEMD_128
+
+load_on auto
+
+<add>
+rmd128.cpp
+rmd128.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/rmd128/rmd128.cpp b/botan/src/hash/rmd128/rmd128.cpp
new file mode 100644
index 0000000..8b2c0cc
--- /dev/null
+++ b/botan/src/hash/rmd128/rmd128.cpp
@@ -0,0 +1,172 @@
+/*
+* RIPEMD-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rmd128.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* RIPEMD-128 F1 Function
+*/
+inline void F1(u32bit& A, u32bit B, u32bit C, u32bit D,
+ u32bit msg, u32bit shift)
+ {
+ A += (B ^ C ^ D) + msg;
+ A = rotate_left(A, shift);
+ }
+
+/*
+* RIPEMD-128 F2 Function
+*/
+inline void F2(u32bit& A, u32bit B, u32bit C, u32bit D,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (D ^ (B & (C ^ D))) + msg + magic;
+ A = rotate_left(A, shift);
+ }
+
+/*
+* RIPEMD-128 F3 Function
+*/
+inline void F3(u32bit& A, u32bit B, u32bit C, u32bit D,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (D ^ (B | ~C)) + msg + magic;
+ A = rotate_left(A, shift);
+ }
+
+/*
+* RIPEMD-128 F4 Function
+*/
+inline void F4(u32bit& A, u32bit B, u32bit C, u32bit D,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (C ^ (D & (B ^ C))) + msg + magic;
+ A = rotate_left(A, shift);
+ }
+
+}
+
+/*
+* RIPEMD-128 Compression Function
+*/
+void RIPEMD_128::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ M[j] = load_le<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ u32bit A1 = digest[0], A2 = A1, B1 = digest[1], B2 = B1,
+ C1 = digest[2], C2 = C1, D1 = digest[3], D2 = D1;
+
+ const u32bit MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1,
+ MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0x50A28BE6,
+ MAGIC6 = 0x5C4DD124, MAGIC7 = 0x6D703EF3;
+
+ F1(A1,B1,C1,D1,M[ 0],11 ); F4(A2,B2,C2,D2,M[ 5], 8,MAGIC5);
+ F1(D1,A1,B1,C1,M[ 1],14 ); F4(D2,A2,B2,C2,M[14], 9,MAGIC5);
+ F1(C1,D1,A1,B1,M[ 2],15 ); F4(C2,D2,A2,B2,M[ 7], 9,MAGIC5);
+ F1(B1,C1,D1,A1,M[ 3],12 ); F4(B2,C2,D2,A2,M[ 0],11,MAGIC5);
+ F1(A1,B1,C1,D1,M[ 4], 5 ); F4(A2,B2,C2,D2,M[ 9],13,MAGIC5);
+ F1(D1,A1,B1,C1,M[ 5], 8 ); F4(D2,A2,B2,C2,M[ 2],15,MAGIC5);
+ F1(C1,D1,A1,B1,M[ 6], 7 ); F4(C2,D2,A2,B2,M[11],15,MAGIC5);
+ F1(B1,C1,D1,A1,M[ 7], 9 ); F4(B2,C2,D2,A2,M[ 4], 5,MAGIC5);
+ F1(A1,B1,C1,D1,M[ 8],11 ); F4(A2,B2,C2,D2,M[13], 7,MAGIC5);
+ F1(D1,A1,B1,C1,M[ 9],13 ); F4(D2,A2,B2,C2,M[ 6], 7,MAGIC5);
+ F1(C1,D1,A1,B1,M[10],14 ); F4(C2,D2,A2,B2,M[15], 8,MAGIC5);
+ F1(B1,C1,D1,A1,M[11],15 ); F4(B2,C2,D2,A2,M[ 8],11,MAGIC5);
+ F1(A1,B1,C1,D1,M[12], 6 ); F4(A2,B2,C2,D2,M[ 1],14,MAGIC5);
+ F1(D1,A1,B1,C1,M[13], 7 ); F4(D2,A2,B2,C2,M[10],14,MAGIC5);
+ F1(C1,D1,A1,B1,M[14], 9 ); F4(C2,D2,A2,B2,M[ 3],12,MAGIC5);
+ F1(B1,C1,D1,A1,M[15], 8 ); F4(B2,C2,D2,A2,M[12], 6,MAGIC5);
+
+ F2(A1,B1,C1,D1,M[ 7], 7,MAGIC2); F3(A2,B2,C2,D2,M[ 6], 9,MAGIC6);
+ F2(D1,A1,B1,C1,M[ 4], 6,MAGIC2); F3(D2,A2,B2,C2,M[11],13,MAGIC6);
+ F2(C1,D1,A1,B1,M[13], 8,MAGIC2); F3(C2,D2,A2,B2,M[ 3],15,MAGIC6);
+ F2(B1,C1,D1,A1,M[ 1],13,MAGIC2); F3(B2,C2,D2,A2,M[ 7], 7,MAGIC6);
+ F2(A1,B1,C1,D1,M[10],11,MAGIC2); F3(A2,B2,C2,D2,M[ 0],12,MAGIC6);
+ F2(D1,A1,B1,C1,M[ 6], 9,MAGIC2); F3(D2,A2,B2,C2,M[13], 8,MAGIC6);
+ F2(C1,D1,A1,B1,M[15], 7,MAGIC2); F3(C2,D2,A2,B2,M[ 5], 9,MAGIC6);
+ F2(B1,C1,D1,A1,M[ 3],15,MAGIC2); F3(B2,C2,D2,A2,M[10],11,MAGIC6);
+ F2(A1,B1,C1,D1,M[12], 7,MAGIC2); F3(A2,B2,C2,D2,M[14], 7,MAGIC6);
+ F2(D1,A1,B1,C1,M[ 0],12,MAGIC2); F3(D2,A2,B2,C2,M[15], 7,MAGIC6);
+ F2(C1,D1,A1,B1,M[ 9],15,MAGIC2); F3(C2,D2,A2,B2,M[ 8],12,MAGIC6);
+ F2(B1,C1,D1,A1,M[ 5], 9,MAGIC2); F3(B2,C2,D2,A2,M[12], 7,MAGIC6);
+ F2(A1,B1,C1,D1,M[ 2],11,MAGIC2); F3(A2,B2,C2,D2,M[ 4], 6,MAGIC6);
+ F2(D1,A1,B1,C1,M[14], 7,MAGIC2); F3(D2,A2,B2,C2,M[ 9],15,MAGIC6);
+ F2(C1,D1,A1,B1,M[11],13,MAGIC2); F3(C2,D2,A2,B2,M[ 1],13,MAGIC6);
+ F2(B1,C1,D1,A1,M[ 8],12,MAGIC2); F3(B2,C2,D2,A2,M[ 2],11,MAGIC6);
+
+ F3(A1,B1,C1,D1,M[ 3],11,MAGIC3); F2(A2,B2,C2,D2,M[15], 9,MAGIC7);
+ F3(D1,A1,B1,C1,M[10],13,MAGIC3); F2(D2,A2,B2,C2,M[ 5], 7,MAGIC7);
+ F3(C1,D1,A1,B1,M[14], 6,MAGIC3); F2(C2,D2,A2,B2,M[ 1],15,MAGIC7);
+ F3(B1,C1,D1,A1,M[ 4], 7,MAGIC3); F2(B2,C2,D2,A2,M[ 3],11,MAGIC7);
+ F3(A1,B1,C1,D1,M[ 9],14,MAGIC3); F2(A2,B2,C2,D2,M[ 7], 8,MAGIC7);
+ F3(D1,A1,B1,C1,M[15], 9,MAGIC3); F2(D2,A2,B2,C2,M[14], 6,MAGIC7);
+ F3(C1,D1,A1,B1,M[ 8],13,MAGIC3); F2(C2,D2,A2,B2,M[ 6], 6,MAGIC7);
+ F3(B1,C1,D1,A1,M[ 1],15,MAGIC3); F2(B2,C2,D2,A2,M[ 9],14,MAGIC7);
+ F3(A1,B1,C1,D1,M[ 2],14,MAGIC3); F2(A2,B2,C2,D2,M[11],12,MAGIC7);
+ F3(D1,A1,B1,C1,M[ 7], 8,MAGIC3); F2(D2,A2,B2,C2,M[ 8],13,MAGIC7);
+ F3(C1,D1,A1,B1,M[ 0],13,MAGIC3); F2(C2,D2,A2,B2,M[12], 5,MAGIC7);
+ F3(B1,C1,D1,A1,M[ 6], 6,MAGIC3); F2(B2,C2,D2,A2,M[ 2],14,MAGIC7);
+ F3(A1,B1,C1,D1,M[13], 5,MAGIC3); F2(A2,B2,C2,D2,M[10],13,MAGIC7);
+ F3(D1,A1,B1,C1,M[11],12,MAGIC3); F2(D2,A2,B2,C2,M[ 0],13,MAGIC7);
+ F3(C1,D1,A1,B1,M[ 5], 7,MAGIC3); F2(C2,D2,A2,B2,M[ 4], 7,MAGIC7);
+ F3(B1,C1,D1,A1,M[12], 5,MAGIC3); F2(B2,C2,D2,A2,M[13], 5,MAGIC7);
+
+ F4(A1,B1,C1,D1,M[ 1],11,MAGIC4); F1(A2,B2,C2,D2,M[ 8],15 );
+ F4(D1,A1,B1,C1,M[ 9],12,MAGIC4); F1(D2,A2,B2,C2,M[ 6], 5 );
+ F4(C1,D1,A1,B1,M[11],14,MAGIC4); F1(C2,D2,A2,B2,M[ 4], 8 );
+ F4(B1,C1,D1,A1,M[10],15,MAGIC4); F1(B2,C2,D2,A2,M[ 1],11 );
+ F4(A1,B1,C1,D1,M[ 0],14,MAGIC4); F1(A2,B2,C2,D2,M[ 3],14 );
+ F4(D1,A1,B1,C1,M[ 8],15,MAGIC4); F1(D2,A2,B2,C2,M[11],14 );
+ F4(C1,D1,A1,B1,M[12], 9,MAGIC4); F1(C2,D2,A2,B2,M[15], 6 );
+ F4(B1,C1,D1,A1,M[ 4], 8,MAGIC4); F1(B2,C2,D2,A2,M[ 0],14 );
+ F4(A1,B1,C1,D1,M[13], 9,MAGIC4); F1(A2,B2,C2,D2,M[ 5], 6 );
+ F4(D1,A1,B1,C1,M[ 3],14,MAGIC4); F1(D2,A2,B2,C2,M[12], 9 );
+ F4(C1,D1,A1,B1,M[ 7], 5,MAGIC4); F1(C2,D2,A2,B2,M[ 2],12 );
+ F4(B1,C1,D1,A1,M[15], 6,MAGIC4); F1(B2,C2,D2,A2,M[13], 9 );
+ F4(A1,B1,C1,D1,M[14], 8,MAGIC4); F1(A2,B2,C2,D2,M[ 9],12 );
+ F4(D1,A1,B1,C1,M[ 5], 6,MAGIC4); F1(D2,A2,B2,C2,M[ 7], 5 );
+ F4(C1,D1,A1,B1,M[ 6], 5,MAGIC4); F1(C2,D2,A2,B2,M[10],15 );
+ F4(B1,C1,D1,A1,M[ 2],12,MAGIC4); F1(B2,C2,D2,A2,M[14], 8 );
+
+ D2 = digest[1] + C1 + D2; digest[1] = digest[2] + D1 + A2;
+ digest[2] = digest[3] + A1 + B2; digest[3] = digest[0] + B1 + C2;
+ digest[0] = D2;
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void RIPEMD_128::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_le(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void RIPEMD_128::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ M.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ }
+
+}
diff --git a/botan/src/hash/rmd128/rmd128.h b/botan/src/hash/rmd128/rmd128.h
new file mode 100644
index 0000000..031ae57
--- /dev/null
+++ b/botan/src/hash/rmd128/rmd128.h
@@ -0,0 +1,35 @@
+/*
+* RIPEMD-128
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RIPEMD_128_H__
+#define BOTAN_RIPEMD_128_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* RIPEMD-128
+*/
+class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "RIPEMD-128"; }
+ HashFunction* clone() const { return new RIPEMD_128; }
+ RIPEMD_128() : MDx_HashFunction(16, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 4> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/rmd160/info.txt b/botan/src/hash/rmd160/info.txt
new file mode 100644
index 0000000..af4b5c2
--- /dev/null
+++ b/botan/src/hash/rmd160/info.txt
@@ -0,0 +1,14 @@
+realname "RIPEMD-160"
+
+define RIPEMD_160
+
+load_on auto
+
+<add>
+rmd160.cpp
+rmd160.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/rmd160/rmd160.cpp b/botan/src/hash/rmd160/rmd160.cpp
new file mode 100644
index 0000000..863de84
--- /dev/null
+++ b/botan/src/hash/rmd160/rmd160.cpp
@@ -0,0 +1,210 @@
+/*
+* RIPEMD-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rmd160.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* RIPEMD-160 F1 Function
+*/
+inline void F1(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E,
+ u32bit msg, u32bit shift)
+ {
+ A += (B ^ C ^ D) + msg;
+ A = rotate_left(A, shift) + E;
+ C = rotate_left(C, 10);
+ }
+
+/*
+* RIPEMD-160 F2 Function
+*/
+inline void F2(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (D ^ (B & (C ^ D))) + msg + magic;
+ A = rotate_left(A, shift) + E;
+ C = rotate_left(C, 10);
+ }
+
+/*
+* RIPEMD-160 F3 Function
+*/
+inline void F3(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (D ^ (B | ~C)) + msg + magic;
+ A = rotate_left(A, shift) + E;
+ C = rotate_left(C, 10);
+ }
+
+/*
+* RIPEMD-160 F4 Function
+*/
+inline void F4(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (C ^ (D & (B ^ C))) + msg + magic;
+ A = rotate_left(A, shift) + E;
+ C = rotate_left(C, 10);
+ }
+
+/*
+* RIPEMD-160 F5 Function
+*/
+inline void F5(u32bit& A, u32bit B, u32bit& C, u32bit D, u32bit E,
+ u32bit msg, u32bit shift, u32bit magic)
+ {
+ A += (B ^ (C | ~D)) + msg + magic;
+ A = rotate_left(A, shift) + E;
+ C = rotate_left(C, 10);
+ }
+
+}
+
+/*
+* RIPEMD-160 Compression Function
+*/
+void RIPEMD_160::compress_n(const byte input[], u32bit blocks)
+ {
+ const u32bit MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1,
+ MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0xA953FD4E,
+ MAGIC6 = 0x50A28BE6, MAGIC7 = 0x5C4DD124,
+ MAGIC8 = 0x6D703EF3, MAGIC9 = 0x7A6D76E9;
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ M[j] = load_le<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ u32bit A1 = digest[0], A2 = A1, B1 = digest[1], B2 = B1,
+ C1 = digest[2], C2 = C1, D1 = digest[3], D2 = D1,
+ E1 = digest[4], E2 = E1;
+
+ F1(A1,B1,C1,D1,E1,M[ 0],11 ); F5(A2,B2,C2,D2,E2,M[ 5], 8,MAGIC6);
+ F1(E1,A1,B1,C1,D1,M[ 1],14 ); F5(E2,A2,B2,C2,D2,M[14], 9,MAGIC6);
+ F1(D1,E1,A1,B1,C1,M[ 2],15 ); F5(D2,E2,A2,B2,C2,M[ 7], 9,MAGIC6);
+ F1(C1,D1,E1,A1,B1,M[ 3],12 ); F5(C2,D2,E2,A2,B2,M[ 0],11,MAGIC6);
+ F1(B1,C1,D1,E1,A1,M[ 4], 5 ); F5(B2,C2,D2,E2,A2,M[ 9],13,MAGIC6);
+ F1(A1,B1,C1,D1,E1,M[ 5], 8 ); F5(A2,B2,C2,D2,E2,M[ 2],15,MAGIC6);
+ F1(E1,A1,B1,C1,D1,M[ 6], 7 ); F5(E2,A2,B2,C2,D2,M[11],15,MAGIC6);
+ F1(D1,E1,A1,B1,C1,M[ 7], 9 ); F5(D2,E2,A2,B2,C2,M[ 4], 5,MAGIC6);
+ F1(C1,D1,E1,A1,B1,M[ 8],11 ); F5(C2,D2,E2,A2,B2,M[13], 7,MAGIC6);
+ F1(B1,C1,D1,E1,A1,M[ 9],13 ); F5(B2,C2,D2,E2,A2,M[ 6], 7,MAGIC6);
+ F1(A1,B1,C1,D1,E1,M[10],14 ); F5(A2,B2,C2,D2,E2,M[15], 8,MAGIC6);
+ F1(E1,A1,B1,C1,D1,M[11],15 ); F5(E2,A2,B2,C2,D2,M[ 8],11,MAGIC6);
+ F1(D1,E1,A1,B1,C1,M[12], 6 ); F5(D2,E2,A2,B2,C2,M[ 1],14,MAGIC6);
+ F1(C1,D1,E1,A1,B1,M[13], 7 ); F5(C2,D2,E2,A2,B2,M[10],14,MAGIC6);
+ F1(B1,C1,D1,E1,A1,M[14], 9 ); F5(B2,C2,D2,E2,A2,M[ 3],12,MAGIC6);
+ F1(A1,B1,C1,D1,E1,M[15], 8 ); F5(A2,B2,C2,D2,E2,M[12], 6,MAGIC6);
+
+ F2(E1,A1,B1,C1,D1,M[ 7], 7,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 6], 9,MAGIC7);
+ F2(D1,E1,A1,B1,C1,M[ 4], 6,MAGIC2); F4(D2,E2,A2,B2,C2,M[11],13,MAGIC7);
+ F2(C1,D1,E1,A1,B1,M[13], 8,MAGIC2); F4(C2,D2,E2,A2,B2,M[ 3],15,MAGIC7);
+ F2(B1,C1,D1,E1,A1,M[ 1],13,MAGIC2); F4(B2,C2,D2,E2,A2,M[ 7], 7,MAGIC7);
+ F2(A1,B1,C1,D1,E1,M[10],11,MAGIC2); F4(A2,B2,C2,D2,E2,M[ 0],12,MAGIC7);
+ F2(E1,A1,B1,C1,D1,M[ 6], 9,MAGIC2); F4(E2,A2,B2,C2,D2,M[13], 8,MAGIC7);
+ F2(D1,E1,A1,B1,C1,M[15], 7,MAGIC2); F4(D2,E2,A2,B2,C2,M[ 5], 9,MAGIC7);
+ F2(C1,D1,E1,A1,B1,M[ 3],15,MAGIC2); F4(C2,D2,E2,A2,B2,M[10],11,MAGIC7);
+ F2(B1,C1,D1,E1,A1,M[12], 7,MAGIC2); F4(B2,C2,D2,E2,A2,M[14], 7,MAGIC7);
+ F2(A1,B1,C1,D1,E1,M[ 0],12,MAGIC2); F4(A2,B2,C2,D2,E2,M[15], 7,MAGIC7);
+ F2(E1,A1,B1,C1,D1,M[ 9],15,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 8],12,MAGIC7);
+ F2(D1,E1,A1,B1,C1,M[ 5], 9,MAGIC2); F4(D2,E2,A2,B2,C2,M[12], 7,MAGIC7);
+ F2(C1,D1,E1,A1,B1,M[ 2],11,MAGIC2); F4(C2,D2,E2,A2,B2,M[ 4], 6,MAGIC7);
+ F2(B1,C1,D1,E1,A1,M[14], 7,MAGIC2); F4(B2,C2,D2,E2,A2,M[ 9],15,MAGIC7);
+ F2(A1,B1,C1,D1,E1,M[11],13,MAGIC2); F4(A2,B2,C2,D2,E2,M[ 1],13,MAGIC7);
+ F2(E1,A1,B1,C1,D1,M[ 8],12,MAGIC2); F4(E2,A2,B2,C2,D2,M[ 2],11,MAGIC7);
+
+ F3(D1,E1,A1,B1,C1,M[ 3],11,MAGIC3); F3(D2,E2,A2,B2,C2,M[15], 9,MAGIC8);
+ F3(C1,D1,E1,A1,B1,M[10],13,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 5], 7,MAGIC8);
+ F3(B1,C1,D1,E1,A1,M[14], 6,MAGIC3); F3(B2,C2,D2,E2,A2,M[ 1],15,MAGIC8);
+ F3(A1,B1,C1,D1,E1,M[ 4], 7,MAGIC3); F3(A2,B2,C2,D2,E2,M[ 3],11,MAGIC8);
+ F3(E1,A1,B1,C1,D1,M[ 9],14,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 7], 8,MAGIC8);
+ F3(D1,E1,A1,B1,C1,M[15], 9,MAGIC3); F3(D2,E2,A2,B2,C2,M[14], 6,MAGIC8);
+ F3(C1,D1,E1,A1,B1,M[ 8],13,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 6], 6,MAGIC8);
+ F3(B1,C1,D1,E1,A1,M[ 1],15,MAGIC3); F3(B2,C2,D2,E2,A2,M[ 9],14,MAGIC8);
+ F3(A1,B1,C1,D1,E1,M[ 2],14,MAGIC3); F3(A2,B2,C2,D2,E2,M[11],12,MAGIC8);
+ F3(E1,A1,B1,C1,D1,M[ 7], 8,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 8],13,MAGIC8);
+ F3(D1,E1,A1,B1,C1,M[ 0],13,MAGIC3); F3(D2,E2,A2,B2,C2,M[12], 5,MAGIC8);
+ F3(C1,D1,E1,A1,B1,M[ 6], 6,MAGIC3); F3(C2,D2,E2,A2,B2,M[ 2],14,MAGIC8);
+ F3(B1,C1,D1,E1,A1,M[13], 5,MAGIC3); F3(B2,C2,D2,E2,A2,M[10],13,MAGIC8);
+ F3(A1,B1,C1,D1,E1,M[11],12,MAGIC3); F3(A2,B2,C2,D2,E2,M[ 0],13,MAGIC8);
+ F3(E1,A1,B1,C1,D1,M[ 5], 7,MAGIC3); F3(E2,A2,B2,C2,D2,M[ 4], 7,MAGIC8);
+ F3(D1,E1,A1,B1,C1,M[12], 5,MAGIC3); F3(D2,E2,A2,B2,C2,M[13], 5,MAGIC8);
+
+ F4(C1,D1,E1,A1,B1,M[ 1],11,MAGIC4); F2(C2,D2,E2,A2,B2,M[ 8],15,MAGIC9);
+ F4(B1,C1,D1,E1,A1,M[ 9],12,MAGIC4); F2(B2,C2,D2,E2,A2,M[ 6], 5,MAGIC9);
+ F4(A1,B1,C1,D1,E1,M[11],14,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 4], 8,MAGIC9);
+ F4(E1,A1,B1,C1,D1,M[10],15,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 1],11,MAGIC9);
+ F4(D1,E1,A1,B1,C1,M[ 0],14,MAGIC4); F2(D2,E2,A2,B2,C2,M[ 3],14,MAGIC9);
+ F4(C1,D1,E1,A1,B1,M[ 8],15,MAGIC4); F2(C2,D2,E2,A2,B2,M[11],14,MAGIC9);
+ F4(B1,C1,D1,E1,A1,M[12], 9,MAGIC4); F2(B2,C2,D2,E2,A2,M[15], 6,MAGIC9);
+ F4(A1,B1,C1,D1,E1,M[ 4], 8,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 0],14,MAGIC9);
+ F4(E1,A1,B1,C1,D1,M[13], 9,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 5], 6,MAGIC9);
+ F4(D1,E1,A1,B1,C1,M[ 3],14,MAGIC4); F2(D2,E2,A2,B2,C2,M[12], 9,MAGIC9);
+ F4(C1,D1,E1,A1,B1,M[ 7], 5,MAGIC4); F2(C2,D2,E2,A2,B2,M[ 2],12,MAGIC9);
+ F4(B1,C1,D1,E1,A1,M[15], 6,MAGIC4); F2(B2,C2,D2,E2,A2,M[13], 9,MAGIC9);
+ F4(A1,B1,C1,D1,E1,M[14], 8,MAGIC4); F2(A2,B2,C2,D2,E2,M[ 9],12,MAGIC9);
+ F4(E1,A1,B1,C1,D1,M[ 5], 6,MAGIC4); F2(E2,A2,B2,C2,D2,M[ 7], 5,MAGIC9);
+ F4(D1,E1,A1,B1,C1,M[ 6], 5,MAGIC4); F2(D2,E2,A2,B2,C2,M[10],15,MAGIC9);
+ F4(C1,D1,E1,A1,B1,M[ 2],12,MAGIC4); F2(C2,D2,E2,A2,B2,M[14], 8,MAGIC9);
+
+ F5(B1,C1,D1,E1,A1,M[ 4], 9,MAGIC5); F1(B2,C2,D2,E2,A2,M[12], 8 );
+ F5(A1,B1,C1,D1,E1,M[ 0],15,MAGIC5); F1(A2,B2,C2,D2,E2,M[15], 5 );
+ F5(E1,A1,B1,C1,D1,M[ 5], 5,MAGIC5); F1(E2,A2,B2,C2,D2,M[10],12 );
+ F5(D1,E1,A1,B1,C1,M[ 9],11,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 4], 9 );
+ F5(C1,D1,E1,A1,B1,M[ 7], 6,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 1],12 );
+ F5(B1,C1,D1,E1,A1,M[12], 8,MAGIC5); F1(B2,C2,D2,E2,A2,M[ 5], 5 );
+ F5(A1,B1,C1,D1,E1,M[ 2],13,MAGIC5); F1(A2,B2,C2,D2,E2,M[ 8],14 );
+ F5(E1,A1,B1,C1,D1,M[10],12,MAGIC5); F1(E2,A2,B2,C2,D2,M[ 7], 6 );
+ F5(D1,E1,A1,B1,C1,M[14], 5,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 6], 8 );
+ F5(C1,D1,E1,A1,B1,M[ 1],12,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 2],13 );
+ F5(B1,C1,D1,E1,A1,M[ 3],13,MAGIC5); F1(B2,C2,D2,E2,A2,M[13], 6 );
+ F5(A1,B1,C1,D1,E1,M[ 8],14,MAGIC5); F1(A2,B2,C2,D2,E2,M[14], 5 );
+ F5(E1,A1,B1,C1,D1,M[11],11,MAGIC5); F1(E2,A2,B2,C2,D2,M[ 0],15 );
+ F5(D1,E1,A1,B1,C1,M[ 6], 8,MAGIC5); F1(D2,E2,A2,B2,C2,M[ 3],13 );
+ F5(C1,D1,E1,A1,B1,M[15], 5,MAGIC5); F1(C2,D2,E2,A2,B2,M[ 9],11 );
+ F5(B1,C1,D1,E1,A1,M[13], 6,MAGIC5); F1(B2,C2,D2,E2,A2,M[11],11 );
+
+ C1 = digest[1] + C1 + D2;
+ digest[1] = digest[2] + D1 + E2;
+ digest[2] = digest[3] + E1 + A2;
+ digest[3] = digest[4] + A1 + B2;
+ digest[4] = digest[0] + B1 + C2;
+ digest[0] = C1;
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void RIPEMD_160::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_le(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void RIPEMD_160::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ M.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ digest[4] = 0xC3D2E1F0;
+ }
+
+}
diff --git a/botan/src/hash/rmd160/rmd160.h b/botan/src/hash/rmd160/rmd160.h
new file mode 100644
index 0000000..f2babc5
--- /dev/null
+++ b/botan/src/hash/rmd160/rmd160.h
@@ -0,0 +1,35 @@
+/*
+* RIPEMD-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RIPEMD_160_H__
+#define BOTAN_RIPEMD_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* RIPEMD-160
+*/
+class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "RIPEMD-160"; }
+ HashFunction* clone() const { return new RIPEMD_160; }
+ RIPEMD_160() : MDx_HashFunction(20, 64, false, true) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 16> M;
+ SecureBuffer<u32bit, 5> digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/sha1/info.txt b/botan/src/hash/sha1/info.txt
new file mode 100644
index 0000000..a0ae30b
--- /dev/null
+++ b/botan/src/hash/sha1/info.txt
@@ -0,0 +1,14 @@
+realname "SHA-1"
+
+define SHA1
+
+load_on auto
+
+<add>
+sha160.cpp
+sha160.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/sha1/sha160.cpp b/botan/src/hash/sha1/sha160.cpp
new file mode 100644
index 0000000..45323a1
--- /dev/null
+++ b/botan/src/hash/sha1/sha160.cpp
@@ -0,0 +1,162 @@
+/*
+* SHA-160
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha160.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* SHA-160 F1 Function
+*/
+inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
+ {
+ E += (D ^ (B & (C ^ D))) + msg + 0x5A827999 + rotate_left(A, 5);
+ B = rotate_left(B, 30);
+ }
+
+/*
+* SHA-160 F2 Function
+*/
+inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
+ {
+ E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotate_left(A, 5);
+ B = rotate_left(B, 30);
+ }
+
+/*
+* SHA-160 F3 Function
+*/
+inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
+ {
+ E += ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC + rotate_left(A, 5);
+ B = rotate_left(B, 30);
+ }
+
+/*
+* SHA-160 F4 Function
+*/
+inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
+ {
+ E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotate_left(A, 5);
+ B = rotate_left(B, 30);
+ }
+
+}
+
+/*
+* SHA-160 Compression Function
+*/
+void SHA_160::compress_n(const byte input[], u32bit blocks)
+ {
+ u32bit A = digest[0], B = digest[1], C = digest[2],
+ D = digest[3], E = digest[4];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; j += 4)
+ {
+ W[j ] = load_be<u32bit>(input, j);
+ W[j+1] = load_be<u32bit>(input, j+1);
+ W[j+2] = load_be<u32bit>(input, j+2);
+ W[j+3] = load_be<u32bit>(input, j+3);
+ }
+ input += HASH_BLOCK_SIZE;
+
+ for(u32bit j = 16; j != 80; j += 4)
+ {
+ W[j ] = rotate_left((W[j-3] ^ W[j-8] ^ W[j-14] ^ W[j-16]), 1);
+ W[j+1] = rotate_left((W[j-2] ^ W[j-7] ^ W[j-13] ^ W[j-15]), 1);
+ W[j+2] = rotate_left((W[j-1] ^ W[j-6] ^ W[j-12] ^ W[j-14]), 1);
+ W[j+3] = rotate_left((W[j ] ^ W[j-5] ^ W[j-11] ^ W[j-13]), 1);
+ }
+
+ F1(A,B,C,D,E,W[ 0]); F1(E,A,B,C,D,W[ 1]); F1(D,E,A,B,C,W[ 2]);
+ F1(C,D,E,A,B,W[ 3]); F1(B,C,D,E,A,W[ 4]); F1(A,B,C,D,E,W[ 5]);
+ F1(E,A,B,C,D,W[ 6]); F1(D,E,A,B,C,W[ 7]); F1(C,D,E,A,B,W[ 8]);
+ F1(B,C,D,E,A,W[ 9]); F1(A,B,C,D,E,W[10]); F1(E,A,B,C,D,W[11]);
+ F1(D,E,A,B,C,W[12]); F1(C,D,E,A,B,W[13]); F1(B,C,D,E,A,W[14]);
+ F1(A,B,C,D,E,W[15]); F1(E,A,B,C,D,W[16]); F1(D,E,A,B,C,W[17]);
+ F1(C,D,E,A,B,W[18]); F1(B,C,D,E,A,W[19]);
+
+ F2(A,B,C,D,E,W[20]); F2(E,A,B,C,D,W[21]); F2(D,E,A,B,C,W[22]);
+ F2(C,D,E,A,B,W[23]); F2(B,C,D,E,A,W[24]); F2(A,B,C,D,E,W[25]);
+ F2(E,A,B,C,D,W[26]); F2(D,E,A,B,C,W[27]); F2(C,D,E,A,B,W[28]);
+ F2(B,C,D,E,A,W[29]); F2(A,B,C,D,E,W[30]); F2(E,A,B,C,D,W[31]);
+ F2(D,E,A,B,C,W[32]); F2(C,D,E,A,B,W[33]); F2(B,C,D,E,A,W[34]);
+ F2(A,B,C,D,E,W[35]); F2(E,A,B,C,D,W[36]); F2(D,E,A,B,C,W[37]);
+ F2(C,D,E,A,B,W[38]); F2(B,C,D,E,A,W[39]);
+
+ F3(A,B,C,D,E,W[40]); F3(E,A,B,C,D,W[41]); F3(D,E,A,B,C,W[42]);
+ F3(C,D,E,A,B,W[43]); F3(B,C,D,E,A,W[44]); F3(A,B,C,D,E,W[45]);
+ F3(E,A,B,C,D,W[46]); F3(D,E,A,B,C,W[47]); F3(C,D,E,A,B,W[48]);
+ F3(B,C,D,E,A,W[49]); F3(A,B,C,D,E,W[50]); F3(E,A,B,C,D,W[51]);
+ F3(D,E,A,B,C,W[52]); F3(C,D,E,A,B,W[53]); F3(B,C,D,E,A,W[54]);
+ F3(A,B,C,D,E,W[55]); F3(E,A,B,C,D,W[56]); F3(D,E,A,B,C,W[57]);
+ F3(C,D,E,A,B,W[58]); F3(B,C,D,E,A,W[59]);
+
+ F4(A,B,C,D,E,W[60]); F4(E,A,B,C,D,W[61]); F4(D,E,A,B,C,W[62]);
+ F4(C,D,E,A,B,W[63]); F4(B,C,D,E,A,W[64]); F4(A,B,C,D,E,W[65]);
+ F4(E,A,B,C,D,W[66]); F4(D,E,A,B,C,W[67]); F4(C,D,E,A,B,W[68]);
+ F4(B,C,D,E,A,W[69]); F4(A,B,C,D,E,W[70]); F4(E,A,B,C,D,W[71]);
+ F4(D,E,A,B,C,W[72]); F4(C,D,E,A,B,W[73]); F4(B,C,D,E,A,W[74]);
+ F4(A,B,C,D,E,W[75]); F4(E,A,B,C,D,W[76]); F4(D,E,A,B,C,W[77]);
+ F4(C,D,E,A,B,W[78]); F4(B,C,D,E,A,W[79]);
+
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ E = (digest[4] += E);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void SHA_160::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_be(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_160::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ W.clear();
+ digest[0] = 0x67452301;
+ digest[1] = 0xEFCDAB89;
+ digest[2] = 0x98BADCFE;
+ digest[3] = 0x10325476;
+ digest[4] = 0xC3D2E1F0;
+ }
+
+/*
+* SHA_160 Constructor
+*/
+SHA_160::SHA_160() :
+ MDx_HashFunction(20, 64, true, true), W(80)
+ {
+ clear();
+ }
+
+/*
+* SHA_160 Constructor
+*/
+SHA_160::SHA_160(u32bit W_size) :
+ MDx_HashFunction(20, 64, true, true), W(W_size)
+ {
+ clear();
+ }
+
+}
diff --git a/botan/src/hash/sha1/sha160.h b/botan/src/hash/sha1/sha160.h
new file mode 100644
index 0000000..232cf03
--- /dev/null
+++ b/botan/src/hash/sha1/sha160.h
@@ -0,0 +1,38 @@
+/*
+* SHA-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_H__
+#define BOTAN_SHA_160_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-160
+*/
+class BOTAN_DLL SHA_160 : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-160"; }
+ HashFunction* clone() const { return new SHA_160; }
+ SHA_160();
+
+ protected:
+ SHA_160(u32bit W_size);
+
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u32bit, 5> digest;
+ SecureVector<u32bit> W;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/sha1_amd64/info.txt b/botan/src/hash/sha1_amd64/info.txt
new file mode 100644
index 0000000..ddbc7d3
--- /dev/null
+++ b/botan/src/hash/sha1_amd64/info.txt
@@ -0,0 +1,34 @@
+realname "SHA-1 (x86-64 assembler)"
+
+define SHA1_AMD64
+
+load_on asm_ok
+
+<add>
+sha1_amd64_imp.S
+sha1_amd64.cpp
+sha1_amd64.h
+</add>
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+amd64_eng
+asm_amd64
+sha1
+</requires>
diff --git a/botan/src/hash/sha1_amd64/sha1_amd64.cpp b/botan/src/hash/sha1_amd64/sha1_amd64.cpp
new file mode 100644
index 0000000..0efbd85
--- /dev/null
+++ b/botan/src/hash/sha1_amd64/sha1_amd64.cpp
@@ -0,0 +1,31 @@
+/*
+* SHA-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha1_amd64.h>
+
+namespace Botan {
+
+namespace {
+
+extern "C"
+void botan_sha160_amd64_compress(u32bit[5], const byte[64], u32bit[80]);
+
+}
+
+/*
+* SHA-160 Compression Function
+*/
+void SHA_160_AMD64::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ botan_sha160_amd64_compress(digest, input, W);
+ input += HASH_BLOCK_SIZE;
+ }
+ }
+
+}
diff --git a/botan/src/hash/sha1_amd64/sha1_amd64.h b/botan/src/hash/sha1_amd64/sha1_amd64.h
new file mode 100644
index 0000000..f182627
--- /dev/null
+++ b/botan/src/hash/sha1_amd64/sha1_amd64.h
@@ -0,0 +1,28 @@
+/*
+* SHA-160 (x86-64)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_AMD64_H__
+#define BOTAN_SHA_160_AMD64_H__
+
+#include <botan/sha160.h>
+
+namespace Botan {
+
+/*
+* SHA-160
+*/
+class BOTAN_DLL SHA_160_AMD64 : public SHA_160
+ {
+ public:
+ HashFunction* clone() const { return new SHA_160_AMD64; }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/sha1_amd64/sha1_amd64_imp.S b/botan/src/hash/sha1_amd64/sha1_amd64_imp.S
new file mode 100644
index 0000000..34a8318
--- /dev/null
+++ b/botan/src/hash/sha1_amd64/sha1_amd64_imp.S
@@ -0,0 +1,260 @@
+/*
+* SHA-160 Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(sha1_amd64.S)
+
+START_FUNCTION(botan_sha160_amd64_compress)
+
+#define DIGEST_ARR %rdi
+#define INPUT %rsi
+#define W %rdx
+#define LOOP_CTR %eax
+
+#define A %r8d
+#define B %r9d
+#define C %r10d
+#define D %r11d
+#define E %ecx
+
+ ZEROIZE(LOOP_CTR)
+
+ALIGN;
+.LOOP_LOAD_INPUT:
+ addl $8, %eax
+
+ movq ARRAY8(INPUT, 0), %r8
+ movq ARRAY8(INPUT, 1), %r9
+ movq ARRAY8(INPUT, 2), %r10
+ movq ARRAY8(INPUT, 3), %r11
+
+ bswap %r8
+ bswap %r9
+ bswap %r10
+ bswap %r11
+
+ rolq $32, %r8
+ rolq $32, %r9
+ rolq $32, %r10
+ rolq $32, %r11
+
+ movq %r8, ARRAY8(W, 0)
+ movq %r9, ARRAY8(W, 1)
+ movq %r10, ARRAY8(W, 2)
+ movq %r11, ARRAY8(W, 3)
+
+ addq $32, W
+ addq $32, INPUT
+
+ cmp IMM(16), LOOP_CTR
+ jne .LOOP_LOAD_INPUT
+
+/*
+#define A %r8d
+#define B %r9d
+#define C %r10d
+#define D %r11d
+#define E %ecx
+*/
+
+ALIGN;
+.LOOP_EXPANSION:
+ addl $4, LOOP_CTR
+
+ ZEROIZE(A)
+ ASSIGN(B, ARRAY4(W, -1))
+ ASSIGN(C, ARRAY4(W, -2))
+ ASSIGN(D, ARRAY4(W, -3))
+
+ XOR(A, ARRAY4(W, -5))
+ XOR(B, ARRAY4(W, -6))
+ XOR(C, ARRAY4(W, -7))
+ XOR(D, ARRAY4(W, -8))
+
+ XOR(A, ARRAY4(W, -11))
+ XOR(B, ARRAY4(W, -12))
+ XOR(C, ARRAY4(W, -13))
+ XOR(D, ARRAY4(W, -14))
+
+ XOR(A, ARRAY4(W, -13))
+ XOR(B, ARRAY4(W, -14))
+ XOR(C, ARRAY4(W, -15))
+ XOR(D, ARRAY4(W, -16))
+
+ ROTL_IMM(D, 1)
+ ROTL_IMM(C, 1)
+ ROTL_IMM(B, 1)
+ XOR(A, D)
+ ROTL_IMM(A, 1)
+
+ ASSIGN(ARRAY4(W, 0), D)
+ ASSIGN(ARRAY4(W, 1), C)
+ ASSIGN(ARRAY4(W, 2), B)
+ ASSIGN(ARRAY4(W, 3), A)
+
+ addq $16, W
+ cmp IMM(80), LOOP_CTR
+ jne .LOOP_EXPANSION
+
+ subq $320, W
+
+#define MAGIC1 0x5A827999
+#define MAGIC2 0x6ED9EBA1
+#define MAGIC3 0x8F1BBCDC
+#define MAGIC4 0xCA62C1D6
+
+#define T %esi
+#define T2 %eax
+
+#define F1(A, B, C, D, E, F, N) \
+ ASSIGN(T2, ARRAY4(W, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, C) ; \
+ XOR(E, D) ; \
+ ADD3_IMM(F, T2, MAGIC1) ; \
+ AND(E, B) ; \
+ XOR(E, D) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F2_4(A, B, C, D, E, F, N, MAGIC) \
+ ASSIGN(T2, ARRAY4(W, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, B) ; \
+ XOR(E, C) ; \
+ ADD3_IMM(F, T2, MAGIC) ; \
+ XOR(E, D) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F3(A, B, C, D, E, F, N) \
+ ASSIGN(T2, ARRAY4(W, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, B) ; \
+ OR(E, C) ; \
+ AND(E, D) ; \
+ ADD3_IMM(F, T2, MAGIC3) ; \
+ ASSIGN(T2, B) ; \
+ AND(T2, C) ; \
+ OR(E, T2) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F2(A, B, C, D, E, F, W) \
+ F2_4(A, B, C, D, E, F, W, MAGIC2)
+
+#define F4(A, B, C, D, E, F, W) \
+ F2_4(A, B, C, D, E, F, W, MAGIC4)
+
+ ASSIGN(T, ARRAY4(DIGEST_ARR, 0))
+ ASSIGN(B, ARRAY4(DIGEST_ARR, 1))
+ ASSIGN(C, ARRAY4(DIGEST_ARR, 2))
+ ASSIGN(D, ARRAY4(DIGEST_ARR, 3))
+ ASSIGN(E, ARRAY4(DIGEST_ARR, 4))
+
+ /* First Round */
+ F1(A, B, C, D, E, T, 0)
+ F1(T, A, B, C, D, E, 1)
+ F1(E, T, A, B, C, D, 2)
+ F1(D, E, T, A, B, C, 3)
+ F1(C, D, E, T, A, B, 4)
+ F1(B, C, D, E, T, A, 5)
+ F1(A, B, C, D, E, T, 6)
+ F1(T, A, B, C, D, E, 7)
+ F1(E, T, A, B, C, D, 8)
+ F1(D, E, T, A, B, C, 9)
+ F1(C, D, E, T, A, B, 10)
+ F1(B, C, D, E, T, A, 11)
+ F1(A, B, C, D, E, T, 12)
+ F1(T, A, B, C, D, E, 13)
+ F1(E, T, A, B, C, D, 14)
+ F1(D, E, T, A, B, C, 15)
+ F1(C, D, E, T, A, B, 16)
+ F1(B, C, D, E, T, A, 17)
+ F1(A, B, C, D, E, T, 18)
+ F1(T, A, B, C, D, E, 19)
+
+ /* Second Round */
+ F2(E, T, A, B, C, D, 20)
+ F2(D, E, T, A, B, C, 21)
+ F2(C, D, E, T, A, B, 22)
+ F2(B, C, D, E, T, A, 23)
+ F2(A, B, C, D, E, T, 24)
+ F2(T, A, B, C, D, E, 25)
+ F2(E, T, A, B, C, D, 26)
+ F2(D, E, T, A, B, C, 27)
+ F2(C, D, E, T, A, B, 28)
+ F2(B, C, D, E, T, A, 29)
+ F2(A, B, C, D, E, T, 30)
+ F2(T, A, B, C, D, E, 31)
+ F2(E, T, A, B, C, D, 32)
+ F2(D, E, T, A, B, C, 33)
+ F2(C, D, E, T, A, B, 34)
+ F2(B, C, D, E, T, A, 35)
+ F2(A, B, C, D, E, T, 36)
+ F2(T, A, B, C, D, E, 37)
+ F2(E, T, A, B, C, D, 38)
+ F2(D, E, T, A, B, C, 39)
+
+ /* Third Round */
+ F3(C, D, E, T, A, B, 40)
+ F3(B, C, D, E, T, A, 41)
+ F3(A, B, C, D, E, T, 42)
+ F3(T, A, B, C, D, E, 43)
+ F3(E, T, A, B, C, D, 44)
+ F3(D, E, T, A, B, C, 45)
+ F3(C, D, E, T, A, B, 46)
+ F3(B, C, D, E, T, A, 47)
+ F3(A, B, C, D, E, T, 48)
+ F3(T, A, B, C, D, E, 49)
+ F3(E, T, A, B, C, D, 50)
+ F3(D, E, T, A, B, C, 51)
+ F3(C, D, E, T, A, B, 52)
+ F3(B, C, D, E, T, A, 53)
+ F3(A, B, C, D, E, T, 54)
+ F3(T, A, B, C, D, E, 55)
+ F3(E, T, A, B, C, D, 56)
+ F3(D, E, T, A, B, C, 57)
+ F3(C, D, E, T, A, B, 58)
+ F3(B, C, D, E, T, A, 59)
+
+ /* Fourth Round */
+ F4(A, B, C, D, E, T, 60)
+ F4(T, A, B, C, D, E, 61)
+ F4(E, T, A, B, C, D, 62)
+ F4(D, E, T, A, B, C, 63)
+ F4(C, D, E, T, A, B, 64)
+ F4(B, C, D, E, T, A, 65)
+ F4(A, B, C, D, E, T, 66)
+ F4(T, A, B, C, D, E, 67)
+ F4(E, T, A, B, C, D, 68)
+ F4(D, E, T, A, B, C, 69)
+ F4(C, D, E, T, A, B, 70)
+ F4(B, C, D, E, T, A, 71)
+ F4(A, B, C, D, E, T, 72)
+ F4(T, A, B, C, D, E, 73)
+ F4(E, T, A, B, C, D, 74)
+ F4(D, E, T, A, B, C, 75)
+ F4(C, D, E, T, A, B, 76)
+ F4(B, C, D, E, T, A, 77)
+ F4(A, B, C, D, E, T, 78)
+ F4(T, A, B, C, D, E, 79)
+
+ ADD(ARRAY4(DIGEST_ARR, 0), D)
+ ADD(ARRAY4(DIGEST_ARR, 1), T)
+ ADD(ARRAY4(DIGEST_ARR, 2), A)
+ ADD(ARRAY4(DIGEST_ARR, 3), B)
+ ADD(ARRAY4(DIGEST_ARR, 4), C)
+
+END_FUNCTION(botan_sha160_amd64_compress)
diff --git a/botan/src/hash/sha1_ia32/info.txt b/botan/src/hash/sha1_ia32/info.txt
new file mode 100644
index 0000000..bfb3211
--- /dev/null
+++ b/botan/src/hash/sha1_ia32/info.txt
@@ -0,0 +1,35 @@
+realname "SHA-1 (IA-32)"
+
+define SHA1_IA32
+
+load_on asm_ok
+
+<add>
+sha1_ia32_imp.S
+sha1_ia32.cpp
+sha1_ia32.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_ia32
+sha1
+</requires>
diff --git a/botan/src/hash/sha1_ia32/sha1_ia32.cpp b/botan/src/hash/sha1_ia32/sha1_ia32.cpp
new file mode 100644
index 0000000..0fa0b6b
--- /dev/null
+++ b/botan/src/hash/sha1_ia32/sha1_ia32.cpp
@@ -0,0 +1,32 @@
+/*
+* SHA-160 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha1_ia32.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+namespace {
+
+extern "C"
+void botan_sha160_ia32_compress(u32bit[5], const byte[64], u32bit[81]);
+
+}
+
+/*
+* SHA-160 Compression Function
+*/
+void SHA_160_IA32::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ botan_sha160_ia32_compress(digest, input, W);
+ input += HASH_BLOCK_SIZE;
+ }
+ }
+
+}
diff --git a/botan/src/hash/sha1_ia32/sha1_ia32.h b/botan/src/hash/sha1_ia32/sha1_ia32.h
new file mode 100644
index 0000000..fd34971
--- /dev/null
+++ b/botan/src/hash/sha1_ia32/sha1_ia32.h
@@ -0,0 +1,31 @@
+/*
+* SHA-160 (IA-32)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_IA32_H__
+#define BOTAN_SHA_160_IA32_H__
+
+#include <botan/sha160.h>
+
+namespace Botan {
+
+/*
+* SHA-160
+*/
+class BOTAN_DLL SHA_160_IA32 : public SHA_160
+ {
+ public:
+ HashFunction* clone() const { return new SHA_160_IA32; }
+
+ // Note 81 instead of normal 80: IA-32 asm needs an extra temp
+ SHA_160_IA32() : SHA_160(81) {}
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/sha1_ia32/sha1_ia32_imp.S b/botan/src/hash/sha1_ia32/sha1_ia32_imp.S
new file mode 100644
index 0000000..e76b9fb
--- /dev/null
+++ b/botan/src/hash/sha1_ia32/sha1_ia32_imp.S
@@ -0,0 +1,244 @@
+/*
+* SHA-160 Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(sha1_ia32.S)
+
+START_FUNCTION(botan_sha160_ia32_compress)
+ SPILL_REGS()
+
+#define PUSHED 4
+
+ ASSIGN(EDI, ARG(2))
+ ASSIGN(EBP, ARG(3))
+
+ ZEROIZE(ESI)
+
+START_LOOP(.LOAD_INPUT)
+ ADD_IMM(ESI, 4)
+
+ ASSIGN(EAX, ARRAY4(EDI, 0))
+ ASSIGN(EBX, ARRAY4(EDI, 1))
+ ASSIGN(ECX, ARRAY4(EDI, 2))
+ ASSIGN(EDX, ARRAY4(EDI, 3))
+
+ ADD_IMM(EDI, 16)
+
+ BSWAP(EAX)
+ BSWAP(EBX)
+ BSWAP(ECX)
+ BSWAP(EDX)
+
+ ASSIGN(ARRAY4_INDIRECT(EBP,ESI,-4), EAX)
+ ASSIGN(ARRAY4_INDIRECT(EBP,ESI,-3), EBX)
+ ASSIGN(ARRAY4_INDIRECT(EBP,ESI,-2), ECX)
+ ASSIGN(ARRAY4_INDIRECT(EBP,ESI,-1), EDX)
+LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
+
+ ADD2_IMM(EDI, EBP, 64)
+
+START_LOOP(.EXPANSION)
+ ADD_IMM(ESI, 4)
+
+ ZEROIZE(EAX)
+ ASSIGN(EBX, ARRAY4(EDI, -1))
+ ASSIGN(ECX, ARRAY4(EDI, -2))
+ ASSIGN(EDX, ARRAY4(EDI, -3))
+
+ XOR(EAX, ARRAY4(EDI, -5))
+ XOR(EBX, ARRAY4(EDI, -6))
+ XOR(ECX, ARRAY4(EDI, -7))
+ XOR(EDX, ARRAY4(EDI, -8))
+
+ XOR(EAX, ARRAY4(EDI, -11))
+ XOR(EBX, ARRAY4(EDI, -12))
+ XOR(ECX, ARRAY4(EDI, -13))
+ XOR(EDX, ARRAY4(EDI, -14))
+
+ XOR(EAX, ARRAY4(EDI, -13))
+ XOR(EBX, ARRAY4(EDI, -14))
+ XOR(ECX, ARRAY4(EDI, -15))
+ XOR(EDX, ARRAY4(EDI, -16))
+
+ ROTL_IMM(EDX, 1)
+ ROTL_IMM(ECX, 1)
+ ROTL_IMM(EBX, 1)
+ XOR(EAX, EDX)
+ ROTL_IMM(EAX, 1)
+
+ ASSIGN(ARRAY4(EDI, 0), EDX)
+ ASSIGN(ARRAY4(EDI, 1), ECX)
+ ASSIGN(ARRAY4(EDI, 2), EBX)
+ ASSIGN(ARRAY4(EDI, 3), EAX)
+
+ ADD_IMM(EDI, 16)
+LOOP_UNTIL_EQ(ESI, 80, .EXPANSION)
+
+#define MAGIC1 0x5A827999
+#define MAGIC2 0x6ED9EBA1
+#define MAGIC3 0x8F1BBCDC
+#define MAGIC4 0xCA62C1D6
+
+#define MSG ESP
+#define T2 EBP
+
+#define F1(A, B, C, D, E, F, N) \
+ ASSIGN(T2, ARRAY4(MSG, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, C) ; \
+ XOR(E, D) ; \
+ ADD3_IMM(F, T2, MAGIC1) ; \
+ AND(E, B) ; \
+ XOR(E, D) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F2_4(A, B, C, D, E, F, N, MAGIC) \
+ ASSIGN(T2, ARRAY4(MSG, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, B) ; \
+ XOR(E, C) ; \
+ ADD3_IMM(F, T2, MAGIC) ; \
+ XOR(E, D) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F3(A, B, C, D, E, F, N) \
+ ASSIGN(T2, ARRAY4(MSG, N)) ; \
+ ASSIGN(A, F) ; \
+ ROTL_IMM(F, 5) ; \
+ ADD(F, E) ; \
+ ASSIGN(E, B) ; \
+ OR(E, C) ; \
+ AND(E, D) ; \
+ ADD3_IMM(F, T2, MAGIC3) ; \
+ ASSIGN(T2, B) ; \
+ AND(T2, C) ; \
+ OR(E, T2) ; \
+ ROTR_IMM(B, 2) ; \
+ ADD(E, F) ;
+
+#define F2(A, B, C, D, E, F, MSG) \
+ F2_4(A, B, C, D, E, F, MSG, MAGIC2)
+
+#define F4(A, B, C, D, E, F, MSG) \
+ F2_4(A, B, C, D, E, F, MSG, MAGIC4)
+
+ ASSIGN(EAX, ARG(1))
+ ASSIGN(EDI, ARRAY4(EAX, 0))
+ ASSIGN(EBX, ARRAY4(EAX, 1))
+ ASSIGN(ECX, ARRAY4(EAX, 2))
+ ASSIGN(EDX, ARRAY4(EAX, 3))
+ ASSIGN(ESI, ARRAY4(EAX, 4))
+
+ ASSIGN(ARRAY4(EBP, 80), ESP)
+ ASSIGN(ESP, EBP)
+
+ /* First Round */
+ F1(EAX, EBX, ECX, EDX, ESI, EDI, 0)
+ F1(EDI, EAX, EBX, ECX, EDX, ESI, 1)
+ F1(ESI, EDI, EAX, EBX, ECX, EDX, 2)
+ F1(EDX, ESI, EDI, EAX, EBX, ECX, 3)
+ F1(ECX, EDX, ESI, EDI, EAX, EBX, 4)
+ F1(EBX, ECX, EDX, ESI, EDI, EAX, 5)
+ F1(EAX, EBX, ECX, EDX, ESI, EDI, 6)
+ F1(EDI, EAX, EBX, ECX, EDX, ESI, 7)
+ F1(ESI, EDI, EAX, EBX, ECX, EDX, 8)
+ F1(EDX, ESI, EDI, EAX, EBX, ECX, 9)
+ F1(ECX, EDX, ESI, EDI, EAX, EBX, 10)
+ F1(EBX, ECX, EDX, ESI, EDI, EAX, 11)
+ F1(EAX, EBX, ECX, EDX, ESI, EDI, 12)
+ F1(EDI, EAX, EBX, ECX, EDX, ESI, 13)
+ F1(ESI, EDI, EAX, EBX, ECX, EDX, 14)
+ F1(EDX, ESI, EDI, EAX, EBX, ECX, 15)
+ F1(ECX, EDX, ESI, EDI, EAX, EBX, 16)
+ F1(EBX, ECX, EDX, ESI, EDI, EAX, 17)
+ F1(EAX, EBX, ECX, EDX, ESI, EDI, 18)
+ F1(EDI, EAX, EBX, ECX, EDX, ESI, 19)
+
+ /* Second Round */
+ F2(ESI, EDI, EAX, EBX, ECX, EDX, 20)
+ F2(EDX, ESI, EDI, EAX, EBX, ECX, 21)
+ F2(ECX, EDX, ESI, EDI, EAX, EBX, 22)
+ F2(EBX, ECX, EDX, ESI, EDI, EAX, 23)
+ F2(EAX, EBX, ECX, EDX, ESI, EDI, 24)
+ F2(EDI, EAX, EBX, ECX, EDX, ESI, 25)
+ F2(ESI, EDI, EAX, EBX, ECX, EDX, 26)
+ F2(EDX, ESI, EDI, EAX, EBX, ECX, 27)
+ F2(ECX, EDX, ESI, EDI, EAX, EBX, 28)
+ F2(EBX, ECX, EDX, ESI, EDI, EAX, 29)
+ F2(EAX, EBX, ECX, EDX, ESI, EDI, 30)
+ F2(EDI, EAX, EBX, ECX, EDX, ESI, 31)
+ F2(ESI, EDI, EAX, EBX, ECX, EDX, 32)
+ F2(EDX, ESI, EDI, EAX, EBX, ECX, 33)
+ F2(ECX, EDX, ESI, EDI, EAX, EBX, 34)
+ F2(EBX, ECX, EDX, ESI, EDI, EAX, 35)
+ F2(EAX, EBX, ECX, EDX, ESI, EDI, 36)
+ F2(EDI, EAX, EBX, ECX, EDX, ESI, 37)
+ F2(ESI, EDI, EAX, EBX, ECX, EDX, 38)
+ F2(EDX, ESI, EDI, EAX, EBX, ECX, 39)
+
+ /* Third Round */
+ F3(ECX, EDX, ESI, EDI, EAX, EBX, 40)
+ F3(EBX, ECX, EDX, ESI, EDI, EAX, 41)
+ F3(EAX, EBX, ECX, EDX, ESI, EDI, 42)
+ F3(EDI, EAX, EBX, ECX, EDX, ESI, 43)
+ F3(ESI, EDI, EAX, EBX, ECX, EDX, 44)
+ F3(EDX, ESI, EDI, EAX, EBX, ECX, 45)
+ F3(ECX, EDX, ESI, EDI, EAX, EBX, 46)
+ F3(EBX, ECX, EDX, ESI, EDI, EAX, 47)
+ F3(EAX, EBX, ECX, EDX, ESI, EDI, 48)
+ F3(EDI, EAX, EBX, ECX, EDX, ESI, 49)
+ F3(ESI, EDI, EAX, EBX, ECX, EDX, 50)
+ F3(EDX, ESI, EDI, EAX, EBX, ECX, 51)
+ F3(ECX, EDX, ESI, EDI, EAX, EBX, 52)
+ F3(EBX, ECX, EDX, ESI, EDI, EAX, 53)
+ F3(EAX, EBX, ECX, EDX, ESI, EDI, 54)
+ F3(EDI, EAX, EBX, ECX, EDX, ESI, 55)
+ F3(ESI, EDI, EAX, EBX, ECX, EDX, 56)
+ F3(EDX, ESI, EDI, EAX, EBX, ECX, 57)
+ F3(ECX, EDX, ESI, EDI, EAX, EBX, 58)
+ F3(EBX, ECX, EDX, ESI, EDI, EAX, 59)
+
+ /* Fourth Round */
+ F4(EAX, EBX, ECX, EDX, ESI, EDI, 60)
+ F4(EDI, EAX, EBX, ECX, EDX, ESI, 61)
+ F4(ESI, EDI, EAX, EBX, ECX, EDX, 62)
+ F4(EDX, ESI, EDI, EAX, EBX, ECX, 63)
+ F4(ECX, EDX, ESI, EDI, EAX, EBX, 64)
+ F4(EBX, ECX, EDX, ESI, EDI, EAX, 65)
+ F4(EAX, EBX, ECX, EDX, ESI, EDI, 66)
+ F4(EDI, EAX, EBX, ECX, EDX, ESI, 67)
+ F4(ESI, EDI, EAX, EBX, ECX, EDX, 68)
+ F4(EDX, ESI, EDI, EAX, EBX, ECX, 69)
+ F4(ECX, EDX, ESI, EDI, EAX, EBX, 70)
+ F4(EBX, ECX, EDX, ESI, EDI, EAX, 71)
+ F4(EAX, EBX, ECX, EDX, ESI, EDI, 72)
+ F4(EDI, EAX, EBX, ECX, EDX, ESI, 73)
+ F4(ESI, EDI, EAX, EBX, ECX, EDX, 74)
+ F4(EDX, ESI, EDI, EAX, EBX, ECX, 75)
+ F4(ECX, EDX, ESI, EDI, EAX, EBX, 76)
+ F4(EBX, ECX, EDX, ESI, EDI, EAX, 77)
+ F4(EAX, EBX, ECX, EDX, ESI, EDI, 78)
+ F4(EDI, EAX, EBX, ECX, EDX, ESI, 79)
+
+ ASSIGN(ESP, ARRAY4(ESP, 80))
+
+ ASSIGN(EBP, ARG(1))
+ ADD(ARRAY4(EBP, 0), EDX)
+ ADD(ARRAY4(EBP, 1), EDI)
+ ADD(ARRAY4(EBP, 2), EAX)
+ ADD(ARRAY4(EBP, 3), EBX)
+ ADD(ARRAY4(EBP, 4), ECX)
+
+ RESTORE_REGS()
+END_FUNCTION(botan_sha160_ia32_compress)
diff --git a/botan/src/hash/sha1_sse2/info.txt b/botan/src/hash/sha1_sse2/info.txt
new file mode 100644
index 0000000..b8d693b
--- /dev/null
+++ b/botan/src/hash/sha1_sse2/info.txt
@@ -0,0 +1,28 @@
+realname "SHA-1 (SSE2)"
+
+define SHA1_SSE2
+
+load_on auto
+
+<add>
+sha1_sse2_imp.cpp
+sha1_sse2.cpp
+sha1_sse2.h
+</add>
+
+<arch>
+pentium-m
+pentium4
+prescott
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+<requires>
+sha1
+sse2_eng
+</requires>
diff --git a/botan/src/hash/sha1_sse2/sha1_sse2.cpp b/botan/src/hash/sha1_sse2/sha1_sse2.cpp
new file mode 100644
index 0000000..dddc06b
--- /dev/null
+++ b/botan/src/hash/sha1_sse2/sha1_sse2.cpp
@@ -0,0 +1,24 @@
+/*
+* SHA-160 (SSE2)
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha1_sse2.h>
+
+namespace Botan {
+
+/*
+* SHA-160 Compression Function
+*/
+void SHA_160_SSE2::compress_n(const byte input[], u32bit blocks)
+ {
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ botan_sha1_sse2_compress(digest, reinterpret_cast<const u32bit*>(input));
+ input += HASH_BLOCK_SIZE;
+ }
+ }
+
+}
diff --git a/botan/src/hash/sha1_sse2/sha1_sse2.h b/botan/src/hash/sha1_sse2/sha1_sse2.h
new file mode 100644
index 0000000..0f8eebe
--- /dev/null
+++ b/botan/src/hash/sha1_sse2/sha1_sse2.h
@@ -0,0 +1,31 @@
+/*
+* SHA-160
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_SSE2_H__
+#define BOTAN_SHA_160_SSE2_H__
+
+#include <botan/sha160.h>
+
+namespace Botan {
+
+/*
+* SHA-160
+*/
+class BOTAN_DLL SHA_160_SSE2 : public SHA_160
+ {
+ public:
+ HashFunction* clone() const { return new SHA_160_SSE2; }
+ SHA_160_SSE2() : SHA_160(0) {} // no W needed
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ };
+
+extern "C" void botan_sha1_sse2_compress(u32bit[5], const u32bit*);
+
+}
+
+#endif
diff --git a/botan/src/hash/sha1_sse2/sha1_sse2_imp.cpp b/botan/src/hash/sha1_sse2/sha1_sse2_imp.cpp
new file mode 100644
index 0000000..90a8dcc
--- /dev/null
+++ b/botan/src/hash/sha1_sse2/sha1_sse2_imp.cpp
@@ -0,0 +1,331 @@
+/* this code is public domain.
+
+ * dean gaudet <dean@arctic.org>
+
+ * this code was inspired by this paper:
+
+ * SHA: A Design for Parallel Architectures?
+ * Antoon Bosselaers, Ren´e Govaerts and Joos Vandewalle
+ * <http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9700.pdf>
+
+ * more information available on this implementation here:
+
+ * http://arctic.org/~dean/crypto/sha1.html
+
+ * version: 2
+ */
+
+/*
+ * Lightly modified for Botan, tested under GCC 4.1.1 and ICC 9.1
+ * on a Linux/Core2 system.
+
+ */
+#include <botan/sha1_sse2.h>
+#include <xmmintrin.h>
+
+namespace Botan {
+
+namespace {
+
+typedef union {
+ u32bit u32[4];
+ __m128i u128;
+ } v4si __attribute__((aligned(16)));
+
+static const v4si K00_19 = { { 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999 } };
+static const v4si K20_39 = { { 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1 } };
+static const v4si K40_59 = { { 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc } };
+static const v4si K60_79 = { { 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 } };
+
+#define UNALIGNED 1
+#if UNALIGNED
+#define load(p) _mm_loadu_si128(p)
+#else
+#define load(p) (*p)
+#endif
+
+
+/*
+the first 16 bytes only need byte swapping
+
+prepared points to 4x u32bit, 16-byte aligned
+
+W points to the 4 dwords which need preparing --
+and is overwritten with the swapped bytes
+*/
+#define prep00_15(prep, W) do { \
+ __m128i r1, r2; \
+ \
+ r1 = (W); \
+ if (1) { \
+ r1 = _mm_shufflehi_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \
+ r1 = _mm_shufflelo_epi16(r1, _MM_SHUFFLE(2, 3, 0, 1)); \
+ r2 = _mm_slli_epi16(r1, 8); \
+ r1 = _mm_srli_epi16(r1, 8); \
+ r1 = _mm_or_si128(r1, r2); \
+ (W) = r1; \
+ } \
+ (prep).u128 = _mm_add_epi32(K00_19.u128, r1); \
+ } while(0)
+
+
+
+/*
+for each multiple of 4, t, we want to calculate this:
+
+W[t+0] = rol(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
+W[t+1] = rol(W[t-2] ^ W[t-7] ^ W[t-13] ^ W[t-15], 1);
+W[t+2] = rol(W[t-1] ^ W[t-6] ^ W[t-12] ^ W[t-14], 1);
+W[t+3] = rol(W[t] ^ W[t-5] ^ W[t-11] ^ W[t-13], 1);
+
+we'll actually calculate this:
+
+W[t+0] = rol(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
+W[t+1] = rol(W[t-2] ^ W[t-7] ^ W[t-13] ^ W[t-15], 1);
+W[t+2] = rol(W[t-1] ^ W[t-6] ^ W[t-12] ^ W[t-14], 1);
+W[t+3] = rol( 0 ^ W[t-5] ^ W[t-11] ^ W[t-13], 1);
+W[t+3] ^= rol(W[t+0], 1);
+
+the parameters are:
+
+W0 = &W[t-16];
+W1 = &W[t-12];
+W2 = &W[t- 8];
+W3 = &W[t- 4];
+
+and on output:
+prepared = W0 + K
+W0 = W[t]..W[t+3]
+*/
+
+/* note that there is a step here where i want to do a rol by 1, which
+* normally would look like this:
+*
+* r1 = psrld r0,$31
+* r0 = pslld r0,$1
+* r0 = por r0,r1
+*
+* but instead i do this:
+*
+* r1 = pcmpltd r0,zero
+* r0 = paddd r0,r0
+* r0 = psub r0,r1
+*
+* because pcmpltd and paddd are availabe in both MMX units on
+* efficeon, pentium-m, and opteron but shifts are available in
+* only one unit.
+*/
+#define prep(prep, XW0, XW1, XW2, XW3, K) do { \
+ __m128i r0, r1, r2, r3; \
+ \
+ /* load W[t-4] 16-byte aligned, and shift */ \
+ r3 = _mm_srli_si128((XW3), 4); \
+ r0 = (XW0); \
+ /* get high 64-bits of XW0 into low 64-bits */ \
+ r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \
+ /* load high 64-bits of r1 */ \
+ r1 = _mm_unpacklo_epi64(r1, (XW1)); \
+ r2 = (XW2); \
+ \
+ r0 = _mm_xor_si128(r1, r0); \
+ r2 = _mm_xor_si128(r3, r2); \
+ r0 = _mm_xor_si128(r2, r0); \
+ /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \
+ \
+ r2 = _mm_slli_si128(r0, 12); \
+ r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \
+ r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \
+ r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \
+ \
+ r3 = _mm_srli_epi32(r2, 30); \
+ r2 = _mm_slli_epi32(r2, 2); \
+ \
+ r0 = _mm_xor_si128(r0, r3); \
+ r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \
+ \
+ (XW0) = r0; \
+ (prep).u128 = _mm_add_epi32(r0, (K).u128); \
+ } while(0)
+
+
+static inline u32bit rol(u32bit src, u32bit amt)
+ {
+ /* gcc and icc appear to turn this into a rotate */
+ return (src << amt) | (src >> (32 - amt));
+ }
+
+
+static inline u32bit f00_19(u32bit x, u32bit y, u32bit z)
+ {
+ /* FIPS 180-2 says this: (x & y) ^ (~x & z)
+ * but we can calculate it in fewer steps.
+ */
+ return ((y ^ z) & x) ^ z;
+ }
+
+
+static inline u32bit f20_39(u32bit x, u32bit y, u32bit z)
+ {
+ return (x ^ z) ^ y;
+ }
+
+
+static inline u32bit f40_59(u32bit x, u32bit y, u32bit z)
+ {
+ /* FIPS 180-2 says this: (x & y) ^ (x & z) ^ (y & z)
+ * but we can calculate it in fewer steps.
+ */
+ return (x & z) | ((x | z) & y);
+ }
+
+
+static inline u32bit f60_79(u32bit x, u32bit y, u32bit z)
+ {
+ return f20_39(x, y, z);
+ }
+
+#define step(nn_mm, xa, xb, xc, xd, xe, xt, input) do { \
+ (xt) = (input) + f##nn_mm((xb), (xc), (xd)); \
+ (xb) = rol((xb), 30); \
+ (xt) += ((xe) + rol((xa), 5)); \
+ } while(0)
+
+}
+
+extern "C" void botan_sha1_sse2_compress(u32bit H[5],
+ const u32bit* inputu)
+ {
+ const __m128i * input = (const __m128i *)inputu;
+ __m128i W0, W1, W2, W3;
+ v4si prep0, prep1, prep2;
+ u32bit a, b, c, d, e, t;
+
+ a = H[0];
+ b = H[1];
+ c = H[2];
+ d = H[3];
+ e = H[4];
+
+ /* i've tried arranging the SSE2 code to be 4, 8, 12, and 16
+ * steps ahead of the integer code. 12 steps ahead seems
+ * to produce the best performance. -dean
+ */
+ W0 = load(&input[0]);
+ prep00_15(prep0, W0); /* prepare for 00 through 03 */
+ W1 = load(&input[1]);
+ prep00_15(prep1, W1); /* prepare for 04 through 07 */
+ W2 = load(&input[2]);
+ prep00_15(prep2, W2); /* prepare for 08 through 11 */
+
+ W3 = load(&input[3]);
+ step(00_19, a, b, c, d, e, t, prep0.u32[0]); /* 00 */
+ step(00_19, t, a, b, c, d, e, prep0.u32[1]); /* 01 */
+ step(00_19, e, t, a, b, c, d, prep0.u32[2]); /* 02 */
+ step(00_19, d, e, t, a, b, c, prep0.u32[3]); /* 03 */
+ prep00_15(prep0, W3);
+ step(00_19, c, d, e, t, a, b, prep1.u32[0]); /* 04 */
+ step(00_19, b, c, d, e, t, a, prep1.u32[1]); /* 05 */
+ step(00_19, a, b, c, d, e, t, prep1.u32[2]); /* 06 */
+ step(00_19, t, a, b, c, d, e, prep1.u32[3]); /* 07 */
+ prep(prep1, W0, W1, W2, W3, K00_19); /* prepare for 16 through 19 */
+ step(00_19, e, t, a, b, c, d, prep2.u32[0]); /* 08 */
+ step(00_19, d, e, t, a, b, c, prep2.u32[1]); /* 09 */
+ step(00_19, c, d, e, t, a, b, prep2.u32[2]); /* 10 */
+ step(00_19, b, c, d, e, t, a, prep2.u32[3]); /* 11 */
+ prep(prep2, W1, W2, W3, W0, K20_39); /* prepare for 20 through 23 */
+ step(00_19, a, b, c, d, e, t, prep0.u32[0]); /* 12 */
+ step(00_19, t, a, b, c, d, e, prep0.u32[1]); /* 13 */
+ step(00_19, e, t, a, b, c, d, prep0.u32[2]); /* 14 */
+ step(00_19, d, e, t, a, b, c, prep0.u32[3]); /* 15 */
+ prep(prep0, W2, W3, W0, W1, K20_39);
+ step(00_19, c, d, e, t, a, b, prep1.u32[0]); /* 16 */
+ step(00_19, b, c, d, e, t, a, prep1.u32[1]); /* 17 */
+ step(00_19, a, b, c, d, e, t, prep1.u32[2]); /* 18 */
+ step(00_19, t, a, b, c, d, e, prep1.u32[3]); /* 19 */
+
+ prep(prep1, W3, W0, W1, W2, K20_39);
+ step(20_39, e, t, a, b, c, d, prep2.u32[0]); /* 20 */
+ step(20_39, d, e, t, a, b, c, prep2.u32[1]); /* 21 */
+ step(20_39, c, d, e, t, a, b, prep2.u32[2]); /* 22 */
+ step(20_39, b, c, d, e, t, a, prep2.u32[3]); /* 23 */
+ prep(prep2, W0, W1, W2, W3, K20_39);
+ step(20_39, a, b, c, d, e, t, prep0.u32[0]); /* 24 */
+ step(20_39, t, a, b, c, d, e, prep0.u32[1]); /* 25 */
+ step(20_39, e, t, a, b, c, d, prep0.u32[2]); /* 26 */
+ step(20_39, d, e, t, a, b, c, prep0.u32[3]); /* 27 */
+ prep(prep0, W1, W2, W3, W0, K20_39);
+ step(20_39, c, d, e, t, a, b, prep1.u32[0]); /* 28 */
+ step(20_39, b, c, d, e, t, a, prep1.u32[1]); /* 29 */
+ step(20_39, a, b, c, d, e, t, prep1.u32[2]); /* 30 */
+ step(20_39, t, a, b, c, d, e, prep1.u32[3]); /* 31 */
+ prep(prep1, W2, W3, W0, W1, K40_59);
+ step(20_39, e, t, a, b, c, d, prep2.u32[0]); /* 32 */
+ step(20_39, d, e, t, a, b, c, prep2.u32[1]); /* 33 */
+ step(20_39, c, d, e, t, a, b, prep2.u32[2]); /* 34 */
+ step(20_39, b, c, d, e, t, a, prep2.u32[3]); /* 35 */
+ prep(prep2, W3, W0, W1, W2, K40_59);
+ step(20_39, a, b, c, d, e, t, prep0.u32[0]); /* 36 */
+ step(20_39, t, a, b, c, d, e, prep0.u32[1]); /* 37 */
+ step(20_39, e, t, a, b, c, d, prep0.u32[2]); /* 38 */
+ step(20_39, d, e, t, a, b, c, prep0.u32[3]); /* 39 */
+
+ prep(prep0, W0, W1, W2, W3, K40_59);
+ step(40_59, c, d, e, t, a, b, prep1.u32[0]); /* 40 */
+ step(40_59, b, c, d, e, t, a, prep1.u32[1]); /* 41 */
+ step(40_59, a, b, c, d, e, t, prep1.u32[2]); /* 42 */
+ step(40_59, t, a, b, c, d, e, prep1.u32[3]); /* 43 */
+ prep(prep1, W1, W2, W3, W0, K40_59);
+ step(40_59, e, t, a, b, c, d, prep2.u32[0]); /* 44 */
+ step(40_59, d, e, t, a, b, c, prep2.u32[1]); /* 45 */
+ step(40_59, c, d, e, t, a, b, prep2.u32[2]); /* 46 */
+ step(40_59, b, c, d, e, t, a, prep2.u32[3]); /* 47 */
+ prep(prep2, W2, W3, W0, W1, K40_59);
+ step(40_59, a, b, c, d, e, t, prep0.u32[0]); /* 48 */
+ step(40_59, t, a, b, c, d, e, prep0.u32[1]); /* 49 */
+ step(40_59, e, t, a, b, c, d, prep0.u32[2]); /* 50 */
+ step(40_59, d, e, t, a, b, c, prep0.u32[3]); /* 51 */
+ prep(prep0, W3, W0, W1, W2, K60_79);
+ step(40_59, c, d, e, t, a, b, prep1.u32[0]); /* 52 */
+ step(40_59, b, c, d, e, t, a, prep1.u32[1]); /* 53 */
+ step(40_59, a, b, c, d, e, t, prep1.u32[2]); /* 54 */
+ step(40_59, t, a, b, c, d, e, prep1.u32[3]); /* 55 */
+ prep(prep1, W0, W1, W2, W3, K60_79);
+ step(40_59, e, t, a, b, c, d, prep2.u32[0]); /* 56 */
+ step(40_59, d, e, t, a, b, c, prep2.u32[1]); /* 57 */
+ step(40_59, c, d, e, t, a, b, prep2.u32[2]); /* 58 */
+ step(40_59, b, c, d, e, t, a, prep2.u32[3]); /* 59 */
+
+ prep(prep2, W1, W2, W3, W0, K60_79);
+ step(60_79, a, b, c, d, e, t, prep0.u32[0]); /* 60 */
+ step(60_79, t, a, b, c, d, e, prep0.u32[1]); /* 61 */
+ step(60_79, e, t, a, b, c, d, prep0.u32[2]); /* 62 */
+ step(60_79, d, e, t, a, b, c, prep0.u32[3]); /* 63 */
+ prep(prep0, W2, W3, W0, W1, K60_79);
+ step(60_79, c, d, e, t, a, b, prep1.u32[0]); /* 64 */
+ step(60_79, b, c, d, e, t, a, prep1.u32[1]); /* 65 */
+ step(60_79, a, b, c, d, e, t, prep1.u32[2]); /* 66 */
+ step(60_79, t, a, b, c, d, e, prep1.u32[3]); /* 67 */
+ prep(prep1, W3, W0, W1, W2, K60_79);
+ step(60_79, e, t, a, b, c, d, prep2.u32[0]); /* 68 */
+ step(60_79, d, e, t, a, b, c, prep2.u32[1]); /* 69 */
+ step(60_79, c, d, e, t, a, b, prep2.u32[2]); /* 70 */
+ step(60_79, b, c, d, e, t, a, prep2.u32[3]); /* 71 */
+
+ step(60_79, a, b, c, d, e, t, prep0.u32[0]); /* 72 */
+ step(60_79, t, a, b, c, d, e, prep0.u32[1]); /* 73 */
+ step(60_79, e, t, a, b, c, d, prep0.u32[2]); /* 74 */
+ step(60_79, d, e, t, a, b, c, prep0.u32[3]); /* 75 */
+ /* no more input to prepare */
+ step(60_79, c, d, e, t, a, b, prep1.u32[0]); /* 76 */
+ step(60_79, b, c, d, e, t, a, prep1.u32[1]); /* 77 */
+ step(60_79, a, b, c, d, e, t, prep1.u32[2]); /* 78 */
+ step(60_79, t, a, b, c, d, e, prep1.u32[3]); /* 79 */
+ /* e, t, a, b, c, d */
+ H[0] += e;
+ H[1] += t;
+ H[2] += a;
+ H[3] += b;
+ H[4] += c;
+ }
+
+}
diff --git a/botan/src/hash/sha2/info.txt b/botan/src/hash/sha2/info.txt
new file mode 100644
index 0000000..9b92ff3
--- /dev/null
+++ b/botan/src/hash/sha2/info.txt
@@ -0,0 +1,16 @@
+realname "SHA-2 (224, 256, 384, 512)"
+
+define SHA2
+
+load_on auto
+
+<add>
+sha2_32.cpp
+sha2_32.h
+sha2_64.cpp
+sha2_64.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/sha2/sha2_32.cpp b/botan/src/hash/sha2/sha2_32.cpp
new file mode 100644
index 0000000..9da2ec2
--- /dev/null
+++ b/botan/src/hash/sha2/sha2_32.cpp
@@ -0,0 +1,193 @@
+/*
+* SHA-{224,256}
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha2_32.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* SHA-256 Rho Function
+*/
+inline u32bit rho(u32bit X, u32bit rot1, u32bit rot2, u32bit rot3)
+ {
+ return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^
+ rotate_right(X, rot3));
+ }
+
+/*
+* SHA-256 Sigma Function
+*/
+inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift)
+ {
+ return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift));
+ }
+
+/*
+* SHA-256 F1 Function
+*/
+inline void F1(u32bit A, u32bit B, u32bit C, u32bit& D,
+ u32bit E, u32bit F, u32bit G, u32bit& H,
+ u32bit msg, u32bit magic)
+ {
+ magic += rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + msg;
+ D += magic + H;
+ H += magic + rho(A, 2, 13, 22) + ((A & B) ^ (A & C) ^ (B & C));
+ }
+
+}
+
+/*
+* SHA-256 Compression Function
+*/
+void SHA_224_256_BASE::compress_n(const byte input[], u32bit blocks)
+ {
+ u32bit A = digest[0], B = digest[1], C = digest[2],
+ D = digest[3], E = digest[4], F = digest[5],
+ G = digest[6], H = digest[7];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ W[j] = load_be<u32bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ for(u32bit j = 16; j != 64; ++j)
+ W[j] = sigma(W[j- 2], 17, 19, 10) + W[j- 7] +
+ sigma(W[j-15], 7, 18, 3) + W[j-16];
+
+ F1(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
+ F1(H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
+ F1(G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
+ F1(F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
+ F1(E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
+ F1(D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
+ F1(C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
+ F1(B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
+ F1(A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
+ F1(H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
+ F1(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ F1(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ F1(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ F1(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ F1(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ F1(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ F1(A, B, C, D, E, F, G, H, W[16], 0xE49B69C1);
+ F1(H, A, B, C, D, E, F, G, W[17], 0xEFBE4786);
+ F1(G, H, A, B, C, D, E, F, W[18], 0x0FC19DC6);
+ F1(F, G, H, A, B, C, D, E, W[19], 0x240CA1CC);
+ F1(E, F, G, H, A, B, C, D, W[20], 0x2DE92C6F);
+ F1(D, E, F, G, H, A, B, C, W[21], 0x4A7484AA);
+ F1(C, D, E, F, G, H, A, B, W[22], 0x5CB0A9DC);
+ F1(B, C, D, E, F, G, H, A, W[23], 0x76F988DA);
+ F1(A, B, C, D, E, F, G, H, W[24], 0x983E5152);
+ F1(H, A, B, C, D, E, F, G, W[25], 0xA831C66D);
+ F1(G, H, A, B, C, D, E, F, W[26], 0xB00327C8);
+ F1(F, G, H, A, B, C, D, E, W[27], 0xBF597FC7);
+ F1(E, F, G, H, A, B, C, D, W[28], 0xC6E00BF3);
+ F1(D, E, F, G, H, A, B, C, W[29], 0xD5A79147);
+ F1(C, D, E, F, G, H, A, B, W[30], 0x06CA6351);
+ F1(B, C, D, E, F, G, H, A, W[31], 0x14292967);
+ F1(A, B, C, D, E, F, G, H, W[32], 0x27B70A85);
+ F1(H, A, B, C, D, E, F, G, W[33], 0x2E1B2138);
+ F1(G, H, A, B, C, D, E, F, W[34], 0x4D2C6DFC);
+ F1(F, G, H, A, B, C, D, E, W[35], 0x53380D13);
+ F1(E, F, G, H, A, B, C, D, W[36], 0x650A7354);
+ F1(D, E, F, G, H, A, B, C, W[37], 0x766A0ABB);
+ F1(C, D, E, F, G, H, A, B, W[38], 0x81C2C92E);
+ F1(B, C, D, E, F, G, H, A, W[39], 0x92722C85);
+ F1(A, B, C, D, E, F, G, H, W[40], 0xA2BFE8A1);
+ F1(H, A, B, C, D, E, F, G, W[41], 0xA81A664B);
+ F1(G, H, A, B, C, D, E, F, W[42], 0xC24B8B70);
+ F1(F, G, H, A, B, C, D, E, W[43], 0xC76C51A3);
+ F1(E, F, G, H, A, B, C, D, W[44], 0xD192E819);
+ F1(D, E, F, G, H, A, B, C, W[45], 0xD6990624);
+ F1(C, D, E, F, G, H, A, B, W[46], 0xF40E3585);
+ F1(B, C, D, E, F, G, H, A, W[47], 0x106AA070);
+ F1(A, B, C, D, E, F, G, H, W[48], 0x19A4C116);
+ F1(H, A, B, C, D, E, F, G, W[49], 0x1E376C08);
+ F1(G, H, A, B, C, D, E, F, W[50], 0x2748774C);
+ F1(F, G, H, A, B, C, D, E, W[51], 0x34B0BCB5);
+ F1(E, F, G, H, A, B, C, D, W[52], 0x391C0CB3);
+ F1(D, E, F, G, H, A, B, C, W[53], 0x4ED8AA4A);
+ F1(C, D, E, F, G, H, A, B, W[54], 0x5B9CCA4F);
+ F1(B, C, D, E, F, G, H, A, W[55], 0x682E6FF3);
+ F1(A, B, C, D, E, F, G, H, W[56], 0x748F82EE);
+ F1(H, A, B, C, D, E, F, G, W[57], 0x78A5636F);
+ F1(G, H, A, B, C, D, E, F, W[58], 0x84C87814);
+ F1(F, G, H, A, B, C, D, E, W[59], 0x8CC70208);
+ F1(E, F, G, H, A, B, C, D, W[60], 0x90BEFFFA);
+ F1(D, E, F, G, H, A, B, C, W[61], 0xA4506CEB);
+ F1(C, D, E, F, G, H, A, B, W[62], 0xBEF9A3F7);
+ F1(B, C, D, E, F, G, H, A, W[63], 0xC67178F2);
+
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ E = (digest[4] += E);
+ F = (digest[5] += F);
+ G = (digest[6] += G);
+ H = (digest[7] += H);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void SHA_224_256_BASE::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 4)
+ store_be(digest[j/4], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_224_256_BASE::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ W.clear();
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_224::clear() throw()
+ {
+ SHA_224_256_BASE::clear();
+ digest[0] = 0xc1059ed8;
+ digest[1] = 0x367cd507;
+ digest[2] = 0x3070dd17;
+ digest[3] = 0xf70e5939;
+ digest[4] = 0xffc00b31;
+ digest[5] = 0x68581511;
+ digest[6] = 0x64f98fa7;
+ digest[7] = 0xbefa4fa4;
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_256::clear() throw()
+ {
+ SHA_224_256_BASE::clear();
+ digest[0] = 0x6A09E667;
+ digest[1] = 0xBB67AE85;
+ digest[2] = 0x3C6EF372;
+ digest[3] = 0xA54FF53A;
+ digest[4] = 0x510E527F;
+ digest[5] = 0x9B05688C;
+ digest[6] = 0x1F83D9AB;
+ digest[7] = 0x5BE0CD19;
+ }
+
+}
diff --git a/botan/src/hash/sha2/sha2_32.h b/botan/src/hash/sha2/sha2_32.h
new file mode 100644
index 0000000..05083d1
--- /dev/null
+++ b/botan/src/hash/sha2/sha2_32.h
@@ -0,0 +1,59 @@
+/*
+* SHA-{224,256}
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_256_H__
+#define BOTAN_SHA_256_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-{224,256} Base
+*/
+class BOTAN_DLL SHA_224_256_BASE : public MDx_HashFunction
+ {
+ protected:
+ void clear() throw();
+ SHA_224_256_BASE(u32bit out) :
+ MDx_HashFunction(out, 64, true, true) { clear(); }
+
+ SecureBuffer<u32bit, 64> W;
+ SecureBuffer<u32bit, 8> digest;
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+ };
+
+/*
+* SHA-224
+*/
+class BOTAN_DLL SHA_224 : public SHA_224_256_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-224"; }
+ HashFunction* clone() const { return new SHA_224; }
+ SHA_224() : SHA_224_256_BASE(28) { clear(); }
+ };
+
+/*
+* SHA-256
+*/
+class BOTAN_DLL SHA_256 : public SHA_224_256_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-256"; }
+ HashFunction* clone() const { return new SHA_256; }
+ SHA_256() : SHA_224_256_BASE(32) { clear (); }
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/sha2/sha2_64.cpp b/botan/src/hash/sha2/sha2_64.cpp
new file mode 100644
index 0000000..c2a8749
--- /dev/null
+++ b/botan/src/hash/sha2/sha2_64.cpp
@@ -0,0 +1,208 @@
+/*
+* SHA-{384,512}
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/sha2_64.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* SHA-{384,512} Rho Function
+*/
+inline u64bit rho(u64bit X, u32bit rot1, u32bit rot2, u32bit rot3)
+ {
+ return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^
+ rotate_right(X, rot3));
+ }
+
+/*
+* SHA-{384,512} F1 Function
+*/
+inline void F1(u64bit A, u64bit B, u64bit C, u64bit& D,
+ u64bit E, u64bit F, u64bit G, u64bit& H,
+ u64bit msg, u64bit magic)
+ {
+ magic += rho(E, 14, 18, 41) + ((E & F) ^ (~E & G)) + msg;
+ D += magic + H;
+ H += magic + rho(A, 28, 34, 39) + ((A & B) ^ (A & C) ^ (B & C));
+ }
+
+/*
+* SHA-{384,512} Sigma Function
+*/
+inline u64bit sigma(u64bit X, u32bit rot1, u32bit rot2, u32bit shift)
+ {
+ return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift));
+ }
+
+}
+
+/*
+* SHA-{384,512} Compression Function
+*/
+void SHA_384_512_BASE::compress_n(const byte input[], u32bit blocks)
+ {
+ u64bit A = digest[0], B = digest[1], C = digest[2],
+ D = digest[3], E = digest[4], F = digest[5],
+ G = digest[6], H = digest[7];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 16; ++j)
+ W[j] = load_be<u64bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ for(u32bit j = 16; j != 80; ++j)
+ W[j] = sigma(W[j- 2], 19, 61, 6) + W[j- 7] +
+ sigma(W[j-15], 1, 8, 7) + W[j-16];
+
+ F1(A, B, C, D, E, F, G, H, W[ 0], (u64bit) 0x428A2F98D728AE22ULL);
+ F1(H, A, B, C, D, E, F, G, W[ 1], (u64bit) 0x7137449123EF65CDULL);
+ F1(G, H, A, B, C, D, E, F, W[ 2], (u64bit) 0xB5C0FBCFEC4D3B2FULL);
+ F1(F, G, H, A, B, C, D, E, W[ 3], (u64bit) 0xE9B5DBA58189DBBCULL);
+ F1(E, F, G, H, A, B, C, D, W[ 4], (u64bit) 0x3956C25BF348B538ULL);
+ F1(D, E, F, G, H, A, B, C, W[ 5], (u64bit) 0x59F111F1B605D019ULL);
+ F1(C, D, E, F, G, H, A, B, W[ 6], (u64bit) 0x923F82A4AF194F9BULL);
+ F1(B, C, D, E, F, G, H, A, W[ 7], (u64bit) 0xAB1C5ED5DA6D8118ULL);
+ F1(A, B, C, D, E, F, G, H, W[ 8], (u64bit) 0xD807AA98A3030242ULL);
+ F1(H, A, B, C, D, E, F, G, W[ 9], (u64bit) 0x12835B0145706FBEULL);
+ F1(G, H, A, B, C, D, E, F, W[10], (u64bit) 0x243185BE4EE4B28CULL);
+ F1(F, G, H, A, B, C, D, E, W[11], (u64bit) 0x550C7DC3D5FFB4E2ULL);
+ F1(E, F, G, H, A, B, C, D, W[12], (u64bit) 0x72BE5D74F27B896FULL);
+ F1(D, E, F, G, H, A, B, C, W[13], (u64bit) 0x80DEB1FE3B1696B1ULL);
+ F1(C, D, E, F, G, H, A, B, W[14], (u64bit) 0x9BDC06A725C71235ULL);
+ F1(B, C, D, E, F, G, H, A, W[15], (u64bit) 0xC19BF174CF692694ULL);
+ F1(A, B, C, D, E, F, G, H, W[16], (u64bit) 0xE49B69C19EF14AD2ULL);
+ F1(H, A, B, C, D, E, F, G, W[17], (u64bit) 0xEFBE4786384F25E3ULL);
+ F1(G, H, A, B, C, D, E, F, W[18], (u64bit) 0x0FC19DC68B8CD5B5ULL);
+ F1(F, G, H, A, B, C, D, E, W[19], (u64bit) 0x240CA1CC77AC9C65ULL);
+ F1(E, F, G, H, A, B, C, D, W[20], (u64bit) 0x2DE92C6F592B0275ULL);
+ F1(D, E, F, G, H, A, B, C, W[21], (u64bit) 0x4A7484AA6EA6E483ULL);
+ F1(C, D, E, F, G, H, A, B, W[22], (u64bit) 0x5CB0A9DCBD41FBD4ULL);
+ F1(B, C, D, E, F, G, H, A, W[23], (u64bit) 0x76F988DA831153B5ULL);
+ F1(A, B, C, D, E, F, G, H, W[24], (u64bit) 0x983E5152EE66DFABULL);
+ F1(H, A, B, C, D, E, F, G, W[25], (u64bit) 0xA831C66D2DB43210ULL);
+ F1(G, H, A, B, C, D, E, F, W[26], (u64bit) 0xB00327C898FB213FULL);
+ F1(F, G, H, A, B, C, D, E, W[27], (u64bit) 0xBF597FC7BEEF0EE4ULL);
+ F1(E, F, G, H, A, B, C, D, W[28], (u64bit) 0xC6E00BF33DA88FC2ULL);
+ F1(D, E, F, G, H, A, B, C, W[29], (u64bit) 0xD5A79147930AA725ULL);
+ F1(C, D, E, F, G, H, A, B, W[30], (u64bit) 0x06CA6351E003826FULL);
+ F1(B, C, D, E, F, G, H, A, W[31], (u64bit) 0x142929670A0E6E70ULL);
+ F1(A, B, C, D, E, F, G, H, W[32], (u64bit) 0x27B70A8546D22FFCULL);
+ F1(H, A, B, C, D, E, F, G, W[33], (u64bit) 0x2E1B21385C26C926ULL);
+ F1(G, H, A, B, C, D, E, F, W[34], (u64bit) 0x4D2C6DFC5AC42AEDULL);
+ F1(F, G, H, A, B, C, D, E, W[35], (u64bit) 0x53380D139D95B3DFULL);
+ F1(E, F, G, H, A, B, C, D, W[36], (u64bit) 0x650A73548BAF63DEULL);
+ F1(D, E, F, G, H, A, B, C, W[37], (u64bit) 0x766A0ABB3C77B2A8ULL);
+ F1(C, D, E, F, G, H, A, B, W[38], (u64bit) 0x81C2C92E47EDAEE6ULL);
+ F1(B, C, D, E, F, G, H, A, W[39], (u64bit) 0x92722C851482353BULL);
+ F1(A, B, C, D, E, F, G, H, W[40], (u64bit) 0xA2BFE8A14CF10364ULL);
+ F1(H, A, B, C, D, E, F, G, W[41], (u64bit) 0xA81A664BBC423001ULL);
+ F1(G, H, A, B, C, D, E, F, W[42], (u64bit) 0xC24B8B70D0F89791ULL);
+ F1(F, G, H, A, B, C, D, E, W[43], (u64bit) 0xC76C51A30654BE30ULL);
+ F1(E, F, G, H, A, B, C, D, W[44], (u64bit) 0xD192E819D6EF5218ULL);
+ F1(D, E, F, G, H, A, B, C, W[45], (u64bit) 0xD69906245565A910ULL);
+ F1(C, D, E, F, G, H, A, B, W[46], (u64bit) 0xF40E35855771202AULL);
+ F1(B, C, D, E, F, G, H, A, W[47], (u64bit) 0x106AA07032BBD1B8ULL);
+ F1(A, B, C, D, E, F, G, H, W[48], (u64bit) 0x19A4C116B8D2D0C8ULL);
+ F1(H, A, B, C, D, E, F, G, W[49], (u64bit) 0x1E376C085141AB53ULL);
+ F1(G, H, A, B, C, D, E, F, W[50], (u64bit) 0x2748774CDF8EEB99ULL);
+ F1(F, G, H, A, B, C, D, E, W[51], (u64bit) 0x34B0BCB5E19B48A8ULL);
+ F1(E, F, G, H, A, B, C, D, W[52], (u64bit) 0x391C0CB3C5C95A63ULL);
+ F1(D, E, F, G, H, A, B, C, W[53], (u64bit) 0x4ED8AA4AE3418ACBULL);
+ F1(C, D, E, F, G, H, A, B, W[54], (u64bit) 0x5B9CCA4F7763E373ULL);
+ F1(B, C, D, E, F, G, H, A, W[55], (u64bit) 0x682E6FF3D6B2B8A3ULL);
+ F1(A, B, C, D, E, F, G, H, W[56], (u64bit) 0x748F82EE5DEFB2FCULL);
+ F1(H, A, B, C, D, E, F, G, W[57], (u64bit) 0x78A5636F43172F60ULL);
+ F1(G, H, A, B, C, D, E, F, W[58], (u64bit) 0x84C87814A1F0AB72ULL);
+ F1(F, G, H, A, B, C, D, E, W[59], (u64bit) 0x8CC702081A6439ECULL);
+ F1(E, F, G, H, A, B, C, D, W[60], (u64bit) 0x90BEFFFA23631E28ULL);
+ F1(D, E, F, G, H, A, B, C, W[61], (u64bit) 0xA4506CEBDE82BDE9ULL);
+ F1(C, D, E, F, G, H, A, B, W[62], (u64bit) 0xBEF9A3F7B2C67915ULL);
+ F1(B, C, D, E, F, G, H, A, W[63], (u64bit) 0xC67178F2E372532BULL);
+ F1(A, B, C, D, E, F, G, H, W[64], (u64bit) 0xCA273ECEEA26619CULL);
+ F1(H, A, B, C, D, E, F, G, W[65], (u64bit) 0xD186B8C721C0C207ULL);
+ F1(G, H, A, B, C, D, E, F, W[66], (u64bit) 0xEADA7DD6CDE0EB1EULL);
+ F1(F, G, H, A, B, C, D, E, W[67], (u64bit) 0xF57D4F7FEE6ED178ULL);
+ F1(E, F, G, H, A, B, C, D, W[68], (u64bit) 0x06F067AA72176FBAULL);
+ F1(D, E, F, G, H, A, B, C, W[69], (u64bit) 0x0A637DC5A2C898A6ULL);
+ F1(C, D, E, F, G, H, A, B, W[70], (u64bit) 0x113F9804BEF90DAEULL);
+ F1(B, C, D, E, F, G, H, A, W[71], (u64bit) 0x1B710B35131C471BULL);
+ F1(A, B, C, D, E, F, G, H, W[72], (u64bit) 0x28DB77F523047D84ULL);
+ F1(H, A, B, C, D, E, F, G, W[73], (u64bit) 0x32CAAB7B40C72493ULL);
+ F1(G, H, A, B, C, D, E, F, W[74], (u64bit) 0x3C9EBE0A15C9BEBCULL);
+ F1(F, G, H, A, B, C, D, E, W[75], (u64bit) 0x431D67C49C100D4CULL);
+ F1(E, F, G, H, A, B, C, D, W[76], (u64bit) 0x4CC5D4BECB3E42B6ULL);
+ F1(D, E, F, G, H, A, B, C, W[77], (u64bit) 0x597F299CFC657E2AULL);
+ F1(C, D, E, F, G, H, A, B, W[78], (u64bit) 0x5FCB6FAB3AD6FAECULL);
+ F1(B, C, D, E, F, G, H, A, W[79], (u64bit) 0x6C44198C4A475817ULL);
+
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ E = (digest[4] += E);
+ F = (digest[5] += F);
+ G = (digest[6] += G);
+ H = (digest[7] += H);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void SHA_384_512_BASE::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 8)
+ store_be(digest[j/8], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_384_512_BASE::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ W.clear();
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_384::clear() throw()
+ {
+ SHA_384_512_BASE::clear();
+ digest[0] = (u64bit) 0xCBBB9D5DC1059ED8ULL;
+ digest[1] = (u64bit) 0x629A292A367CD507ULL;
+ digest[2] = (u64bit) 0x9159015A3070DD17ULL;
+ digest[3] = (u64bit) 0x152FECD8F70E5939ULL;
+ digest[4] = (u64bit) 0x67332667FFC00B31ULL;
+ digest[5] = (u64bit) 0x8EB44A8768581511ULL;
+ digest[6] = (u64bit) 0xDB0C2E0D64F98FA7ULL;
+ digest[7] = (u64bit) 0x47B5481DBEFA4FA4ULL;
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SHA_512::clear() throw()
+ {
+ SHA_384_512_BASE::clear();
+ digest[0] = (u64bit) 0x6A09E667F3BCC908ULL;
+ digest[1] = (u64bit) 0xBB67AE8584CAA73BULL;
+ digest[2] = (u64bit) 0x3C6EF372FE94F82BULL;
+ digest[3] = (u64bit) 0xA54FF53A5F1D36F1ULL;
+ digest[4] = (u64bit) 0x510E527FADE682D1ULL;
+ digest[5] = (u64bit) 0x9B05688C2B3E6C1FULL;
+ digest[6] = (u64bit) 0x1F83D9ABFB41BD6BULL;
+ digest[7] = (u64bit) 0x5BE0CD19137E2179ULL;
+ }
+
+}
diff --git a/botan/src/hash/sha2/sha2_64.h b/botan/src/hash/sha2/sha2_64.h
new file mode 100644
index 0000000..dcc6dc8
--- /dev/null
+++ b/botan/src/hash/sha2/sha2_64.h
@@ -0,0 +1,60 @@
+/*
+* SHA-{384,512}
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_64BIT_H__
+#define BOTAN_SHA_64BIT_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* SHA-{384,512} Base
+*/
+class BOTAN_DLL SHA_384_512_BASE : public MDx_HashFunction
+ {
+ protected:
+ void clear() throw();
+
+ SHA_384_512_BASE(u32bit out) :
+ MDx_HashFunction(out, 128, true, true, 16) {}
+
+ SecureBuffer<u64bit, 8> digest;
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ SecureBuffer<u64bit, 80> W;
+ };
+
+/*
+* SHA-384
+*/
+class BOTAN_DLL SHA_384 : public SHA_384_512_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-384"; }
+ HashFunction* clone() const { return new SHA_384; }
+ SHA_384() : SHA_384_512_BASE(48) { clear(); }
+ };
+
+/*
+* SHA-512
+*/
+class BOTAN_DLL SHA_512 : public SHA_384_512_BASE
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "SHA-512"; }
+ HashFunction* clone() const { return new SHA_512; }
+ SHA_512() : SHA_384_512_BASE(64) { clear(); }
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/skein/info.txt b/botan/src/hash/skein/info.txt
new file mode 100644
index 0000000..bab8497
--- /dev/null
+++ b/botan/src/hash/skein/info.txt
@@ -0,0 +1,14 @@
+realname "Skein"
+
+define SKEIN_512
+
+load_on auto
+
+<add>
+skein_512.cpp
+skein_512.h
+</add>
+
+<requires>
+alloc
+</requires>
diff --git a/botan/src/hash/skein/skein_512.cpp b/botan/src/hash/skein/skein_512.cpp
new file mode 100644
index 0000000..da4715d
--- /dev/null
+++ b/botan/src/hash/skein/skein_512.cpp
@@ -0,0 +1,262 @@
+/**
+* The Skein-512 hash function
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/skein_512.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+enum type_code {
+ SKEIN_KEY = 0,
+ SKEIN_CONFIG = 4,
+ SKEIN_PERSONALIZATION = 8,
+ SKEIN_PUBLIC_KEY = 12,
+ SKEIN_KEY_IDENTIFIER = 16,
+ SKEIN_NONCE = 20,
+ SKEIN_MSG = 48,
+ SKEIN_OUTPUT = 63
+};
+
+void ubi_512(u64bit H[9], u64bit T[], const byte msg[], u64bit msg_len)
+ {
+ do
+ {
+ const u64bit to_proc = std::min<u64bit>(msg_len, 64);
+ T[0] += to_proc;
+
+ u64bit M[8] = { 0 };
+ for(u32bit j = 0; j != to_proc / 8; ++j)
+ M[j] = load_le<u64bit>(msg, j);
+
+ if(to_proc % 8)
+ {
+ for(u32bit j = 0; j != to_proc % 8; ++j)
+ M[to_proc/8] |= ((u64bit)msg[8*(to_proc/8)+j] << (8*j));
+ }
+
+ H[8] = H[0] ^ H[1] ^ H[2] ^ H[3] ^
+ H[4] ^ H[5] ^ H[6] ^ H[7] ^ (u64bit) 0x5555555555555555ULL;
+
+ T[2] = T[0] ^ T[1];
+
+ u64bit X0 = M[0] + H[0];
+ u64bit X1 = M[1] + H[1];
+ u64bit X2 = M[2] + H[2];
+ u64bit X3 = M[3] + H[3];
+ u64bit X4 = M[4] + H[4];
+ u64bit X5 = M[5] + H[5] + T[0];
+ u64bit X6 = M[6] + H[6] + T[1];
+ u64bit X7 = M[7] + H[7];
+
+#define THREEFISH_ROUND(I1,I2,I3,I4,I5,I6,I7,I8,ROT1,ROT2,ROT3,ROT4) \
+ do { \
+ X##I1 += X##I2; X##I2 = rotate_left(X##I2, ROT1) ^ X##I1; \
+ X##I3 += X##I4; X##I4 = rotate_left(X##I4, ROT2) ^ X##I3; \
+ X##I5 += X##I6; X##I6 = rotate_left(X##I6, ROT3) ^ X##I5; \
+ X##I7 += X##I8; X##I8 = rotate_left(X##I8, ROT4) ^ X##I7; \
+ } while(0);
+
+#define THREEFISH_INJECT_KEY(r) \
+ do { \
+ X0 += H[(r ) % 9]; \
+ X1 += H[(r+1) % 9]; \
+ X2 += H[(r+2) % 9]; \
+ X3 += H[(r+3) % 9]; \
+ X4 += H[(r+4) % 9]; \
+ X5 += H[(r+5) % 9] + T[(r ) % 3]; \
+ X6 += H[(r+6) % 9] + T[(r+1) % 3]; \
+ X7 += H[(r+7) % 9] + (r); \
+ } while(0);
+
+#define THREEFISH_8_ROUNDS(R1,R2) \
+ do { \
+ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 46,36,19,37); \
+ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 33,27,14,42); \
+ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 17,49,36,39); \
+ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 44, 9,54,56); \
+ \
+ THREEFISH_INJECT_KEY(R1); \
+ \
+ THREEFISH_ROUND(0,1,2,3,4,5,6,7, 39,30,34,24); \
+ THREEFISH_ROUND(2,1,4,7,6,5,0,3, 13,50,10,17); \
+ THREEFISH_ROUND(4,1,6,3,0,5,2,7, 25,29,39,43); \
+ THREEFISH_ROUND(6,1,0,7,2,5,4,3, 8,35,56,22); \
+ \
+ THREEFISH_INJECT_KEY(R2); \
+ } while(0);
+
+ THREEFISH_8_ROUNDS(1,2);
+ THREEFISH_8_ROUNDS(3,4);
+ THREEFISH_8_ROUNDS(5,6);
+ THREEFISH_8_ROUNDS(7,8);
+ THREEFISH_8_ROUNDS(9,10);
+ THREEFISH_8_ROUNDS(11,12);
+ THREEFISH_8_ROUNDS(13,14);
+ THREEFISH_8_ROUNDS(15,16);
+ THREEFISH_8_ROUNDS(17,18);
+
+ // message feed forward
+ H[0] = X0 ^ M[0];
+ H[1] = X1 ^ M[1];
+ H[2] = X2 ^ M[2];
+ H[3] = X3 ^ M[3];
+ H[4] = X4 ^ M[4];
+ H[5] = X5 ^ M[5];
+ H[6] = X6 ^ M[6];
+ H[7] = X7 ^ M[7];
+
+ T[1] &= ~((u64bit)1 << 62); // clear first flag if set
+
+ msg_len -= to_proc;
+ msg += to_proc;
+ } while(msg_len);
+ }
+
+void reset_tweak(u64bit T[3], type_code type, bool final)
+ {
+ T[0] = 0;
+ T[1] = ((u64bit)type << 56) | ((u64bit)1 << 62) | ((u64bit)final << 63);
+ }
+
+void initial_block(u64bit H[9], u64bit T[3], u32bit output_bits,
+ const std::string& personalization)
+ {
+ clear_mem(H, 9);
+
+ // ASCII("SHA3") followed by version (0x0001) code
+ byte config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 };
+ store_le(output_bits, config_str + 8);
+
+ reset_tweak(T, SKEIN_CONFIG, true);
+ ubi_512(H, T, config_str, sizeof(config_str));
+
+ if(personalization != "")
+ {
+ /*
+ This is a limitation of this implementation, and not of the
+ algorithm specification. Could be fixed relatively easily, but
+ doesn't seem worth the trouble.
+ */
+ if(personalization.length() > 64)
+ throw Invalid_Argument("Skein personalization must be <= 64 bytes");
+
+ const byte* bits = reinterpret_cast<const byte*>(personalization.data());
+
+ reset_tweak(T, SKEIN_PERSONALIZATION, true);
+ ubi_512(H, T, bits, personalization.length());
+ }
+
+ reset_tweak(T, SKEIN_MSG, false);
+ }
+
+}
+
+Skein_512::Skein_512(u32bit arg_output_bits,
+ const std::string& arg_personalization) :
+ HashFunction(arg_output_bits / 8, 64),
+ personalization(arg_personalization),
+ output_bits(arg_output_bits)
+ {
+ if(output_bits == 0 || output_bits % 8 != 0)
+ throw Invalid_Argument("Bad output bits size for Skein-512");
+
+ buf_pos = 0;
+ initial_block(H, T, output_bits, personalization);
+ }
+
+std::string Skein_512::name() const
+ {
+ return "Skein-512(" + to_string(output_bits) + ")";
+ }
+
+HashFunction* Skein_512::clone() const
+ {
+ return new Skein_512(output_bits, personalization);
+ }
+
+void Skein_512::clear() throw()
+ {
+ H.clear();
+ T.clear();
+ buffer.clear();
+ buf_pos = 0;
+ }
+
+void Skein_512::add_data(const byte input[], u32bit length)
+ {
+ if(length == 0)
+ return;
+
+ if(buf_pos)
+ {
+ buffer.copy(buf_pos, input, length);
+ if(buf_pos + length > 64)
+ {
+ ubi_512(H, T, &buffer[0], buffer.size());
+
+ input += (64 - buf_pos);
+ length -= (64 - buf_pos);
+ buf_pos = 0;
+ }
+ }
+
+ const u32bit full_blocks = (length - 1) / 64;
+
+ if(full_blocks)
+ ubi_512(H, T, input, 64*full_blocks);
+
+ length -= full_blocks * 64;
+
+ buffer.copy(buf_pos, input + full_blocks * 64, length);
+ buf_pos += length;
+ }
+
+void Skein_512::final_result(byte out[])
+ {
+ T[1] |= ((u64bit)1 << 63); // final block flag
+
+ for(u32bit i = buf_pos; i != buffer.size(); ++i)
+ buffer[i] = 0;
+
+ ubi_512(H, T, &buffer[0], buf_pos);
+
+ byte counter[8] = { 0 };
+
+ u32bit out_bytes = output_bits / 8;
+
+ SecureBuffer<u64bit, 9> H_out;
+
+ while(out_bytes)
+ {
+ const u32bit to_proc = std::min<u32bit>(out_bytes, 64);
+
+ H_out.copy(H.begin(), 8);
+
+ reset_tweak(T, SKEIN_OUTPUT, true);
+ ubi_512(H_out, T, counter, sizeof(counter));
+
+ for(u32bit i = 0; i != to_proc; ++i)
+ out[i] = get_byte(7-i%8, H_out[i/8]);
+
+ out_bytes -= to_proc;
+ out += to_proc;
+
+ for(u32bit i = 0; i != sizeof(counter); ++i)
+ if(++counter[i])
+ break;
+ }
+
+ buf_pos = 0;
+ initial_block(H, T, output_bits, personalization);
+ }
+
+}
diff --git a/botan/src/hash/skein/skein_512.h b/botan/src/hash/skein/skein_512.h
new file mode 100644
index 0000000..fa558fc
--- /dev/null
+++ b/botan/src/hash/skein/skein_512.h
@@ -0,0 +1,41 @@
+/**
+* The Skein-512 hash function
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SKEIN_512_H__
+#define BOTAN_SKEIN_512_H__
+
+#include <botan/secmem.h>
+#include <botan/hash.h>
+#include <string>
+
+namespace Botan {
+
+class BOTAN_DLL Skein_512 : public HashFunction
+ {
+ public:
+ Skein_512(u32bit output_bits = 512,
+ const std::string& personalization = "");
+
+ HashFunction* clone() const;
+ std::string name() const;
+ void clear() throw();
+ private:
+ void add_data(const byte input[], u32bit length);
+ void final_result(byte out[]);
+
+ std::string personalization;
+ u32bit output_bits;
+ SecureBuffer<u64bit, 9> H;
+ SecureBuffer<u64bit, 3> T;
+
+ SecureBuffer<byte, 64> buffer;
+ u32bit buf_pos;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/tiger/info.txt b/botan/src/hash/tiger/info.txt
new file mode 100644
index 0000000..7d4cd71
--- /dev/null
+++ b/botan/src/hash/tiger/info.txt
@@ -0,0 +1,15 @@
+realname "Tiger"
+
+define TIGER
+
+load_on auto
+
+<add>
+tig_tab.cpp
+tiger.cpp
+tiger.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/tiger/tig_tab.cpp b/botan/src/hash/tiger/tig_tab.cpp
new file mode 100644
index 0000000..6fc8686
--- /dev/null
+++ b/botan/src/hash/tiger/tig_tab.cpp
@@ -0,0 +1,364 @@
+/*
+* S-Box Tables for Tiger
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tiger.h>
+
+namespace Botan {
+
+const u64bit Tiger::SBOX1[256] = {
+ (u64bit) 0x02AAB17CF7E90C5EULL, (u64bit) 0xAC424B03E243A8ECULL, (u64bit) 0x72CD5BE30DD5FCD3ULL,
+ (u64bit) 0x6D019B93F6F97F3AULL, (u64bit) 0xCD9978FFD21F9193ULL, (u64bit) 0x7573A1C9708029E2ULL,
+ (u64bit) 0xB164326B922A83C3ULL, (u64bit) 0x46883EEE04915870ULL, (u64bit) 0xEAACE3057103ECE6ULL,
+ (u64bit) 0xC54169B808A3535CULL, (u64bit) 0x4CE754918DDEC47CULL, (u64bit) 0x0AA2F4DFDC0DF40CULL,
+ (u64bit) 0x10B76F18A74DBEFAULL, (u64bit) 0xC6CCB6235AD1AB6AULL, (u64bit) 0x13726121572FE2FFULL,
+ (u64bit) 0x1A488C6F199D921EULL, (u64bit) 0x4BC9F9F4DA0007CAULL, (u64bit) 0x26F5E6F6E85241C7ULL,
+ (u64bit) 0x859079DBEA5947B6ULL, (u64bit) 0x4F1885C5C99E8C92ULL, (u64bit) 0xD78E761EA96F864BULL,
+ (u64bit) 0x8E36428C52B5C17DULL, (u64bit) 0x69CF6827373063C1ULL, (u64bit) 0xB607C93D9BB4C56EULL,
+ (u64bit) 0x7D820E760E76B5EAULL, (u64bit) 0x645C9CC6F07FDC42ULL, (u64bit) 0xBF38A078243342E0ULL,
+ (u64bit) 0x5F6B343C9D2E7D04ULL, (u64bit) 0xF2C28AEB600B0EC6ULL, (u64bit) 0x6C0ED85F7254BCACULL,
+ (u64bit) 0x71592281A4DB4FE5ULL, (u64bit) 0x1967FA69CE0FED9FULL, (u64bit) 0xFD5293F8B96545DBULL,
+ (u64bit) 0xC879E9D7F2A7600BULL, (u64bit) 0x860248920193194EULL, (u64bit) 0xA4F9533B2D9CC0B3ULL,
+ (u64bit) 0x9053836C15957613ULL, (u64bit) 0xDB6DCF8AFC357BF1ULL, (u64bit) 0x18BEEA7A7A370F57ULL,
+ (u64bit) 0x037117CA50B99066ULL, (u64bit) 0x6AB30A9774424A35ULL, (u64bit) 0xF4E92F02E325249BULL,
+ (u64bit) 0x7739DB07061CCAE1ULL, (u64bit) 0xD8F3B49CECA42A05ULL, (u64bit) 0xBD56BE3F51382F73ULL,
+ (u64bit) 0x45FAED5843B0BB28ULL, (u64bit) 0x1C813D5C11BF1F83ULL, (u64bit) 0x8AF0E4B6D75FA169ULL,
+ (u64bit) 0x33EE18A487AD9999ULL, (u64bit) 0x3C26E8EAB1C94410ULL, (u64bit) 0xB510102BC0A822F9ULL,
+ (u64bit) 0x141EEF310CE6123BULL, (u64bit) 0xFC65B90059DDB154ULL, (u64bit) 0xE0158640C5E0E607ULL,
+ (u64bit) 0x884E079826C3A3CFULL, (u64bit) 0x930D0D9523C535FDULL, (u64bit) 0x35638D754E9A2B00ULL,
+ (u64bit) 0x4085FCCF40469DD5ULL, (u64bit) 0xC4B17AD28BE23A4CULL, (u64bit) 0xCAB2F0FC6A3E6A2EULL,
+ (u64bit) 0x2860971A6B943FCDULL, (u64bit) 0x3DDE6EE212E30446ULL, (u64bit) 0x6222F32AE01765AEULL,
+ (u64bit) 0x5D550BB5478308FEULL, (u64bit) 0xA9EFA98DA0EDA22AULL, (u64bit) 0xC351A71686C40DA7ULL,
+ (u64bit) 0x1105586D9C867C84ULL, (u64bit) 0xDCFFEE85FDA22853ULL, (u64bit) 0xCCFBD0262C5EEF76ULL,
+ (u64bit) 0xBAF294CB8990D201ULL, (u64bit) 0xE69464F52AFAD975ULL, (u64bit) 0x94B013AFDF133E14ULL,
+ (u64bit) 0x06A7D1A32823C958ULL, (u64bit) 0x6F95FE5130F61119ULL, (u64bit) 0xD92AB34E462C06C0ULL,
+ (u64bit) 0xED7BDE33887C71D2ULL, (u64bit) 0x79746D6E6518393EULL, (u64bit) 0x5BA419385D713329ULL,
+ (u64bit) 0x7C1BA6B948A97564ULL, (u64bit) 0x31987C197BFDAC67ULL, (u64bit) 0xDE6C23C44B053D02ULL,
+ (u64bit) 0x581C49FED002D64DULL, (u64bit) 0xDD474D6338261571ULL, (u64bit) 0xAA4546C3E473D062ULL,
+ (u64bit) 0x928FCE349455F860ULL, (u64bit) 0x48161BBACAAB94D9ULL, (u64bit) 0x63912430770E6F68ULL,
+ (u64bit) 0x6EC8A5E602C6641CULL, (u64bit) 0x87282515337DDD2BULL, (u64bit) 0x2CDA6B42034B701BULL,
+ (u64bit) 0xB03D37C181CB096DULL, (u64bit) 0xE108438266C71C6FULL, (u64bit) 0x2B3180C7EB51B255ULL,
+ (u64bit) 0xDF92B82F96C08BBCULL, (u64bit) 0x5C68C8C0A632F3BAULL, (u64bit) 0x5504CC861C3D0556ULL,
+ (u64bit) 0xABBFA4E55FB26B8FULL, (u64bit) 0x41848B0AB3BACEB4ULL, (u64bit) 0xB334A273AA445D32ULL,
+ (u64bit) 0xBCA696F0A85AD881ULL, (u64bit) 0x24F6EC65B528D56CULL, (u64bit) 0x0CE1512E90F4524AULL,
+ (u64bit) 0x4E9DD79D5506D35AULL, (u64bit) 0x258905FAC6CE9779ULL, (u64bit) 0x2019295B3E109B33ULL,
+ (u64bit) 0xF8A9478B73A054CCULL, (u64bit) 0x2924F2F934417EB0ULL, (u64bit) 0x3993357D536D1BC4ULL,
+ (u64bit) 0x38A81AC21DB6FF8BULL, (u64bit) 0x47C4FBF17D6016BFULL, (u64bit) 0x1E0FAADD7667E3F5ULL,
+ (u64bit) 0x7ABCFF62938BEB96ULL, (u64bit) 0xA78DAD948FC179C9ULL, (u64bit) 0x8F1F98B72911E50DULL,
+ (u64bit) 0x61E48EAE27121A91ULL, (u64bit) 0x4D62F7AD31859808ULL, (u64bit) 0xECEBA345EF5CEAEBULL,
+ (u64bit) 0xF5CEB25EBC9684CEULL, (u64bit) 0xF633E20CB7F76221ULL, (u64bit) 0xA32CDF06AB8293E4ULL,
+ (u64bit) 0x985A202CA5EE2CA4ULL, (u64bit) 0xCF0B8447CC8A8FB1ULL, (u64bit) 0x9F765244979859A3ULL,
+ (u64bit) 0xA8D516B1A1240017ULL, (u64bit) 0x0BD7BA3EBB5DC726ULL, (u64bit) 0xE54BCA55B86ADB39ULL,
+ (u64bit) 0x1D7A3AFD6C478063ULL, (u64bit) 0x519EC608E7669EDDULL, (u64bit) 0x0E5715A2D149AA23ULL,
+ (u64bit) 0x177D4571848FF194ULL, (u64bit) 0xEEB55F3241014C22ULL, (u64bit) 0x0F5E5CA13A6E2EC2ULL,
+ (u64bit) 0x8029927B75F5C361ULL, (u64bit) 0xAD139FABC3D6E436ULL, (u64bit) 0x0D5DF1A94CCF402FULL,
+ (u64bit) 0x3E8BD948BEA5DFC8ULL, (u64bit) 0xA5A0D357BD3FF77EULL, (u64bit) 0xA2D12E251F74F645ULL,
+ (u64bit) 0x66FD9E525E81A082ULL, (u64bit) 0x2E0C90CE7F687A49ULL, (u64bit) 0xC2E8BCBEBA973BC5ULL,
+ (u64bit) 0x000001BCE509745FULL, (u64bit) 0x423777BBE6DAB3D6ULL, (u64bit) 0xD1661C7EAEF06EB5ULL,
+ (u64bit) 0xA1781F354DAACFD8ULL, (u64bit) 0x2D11284A2B16AFFCULL, (u64bit) 0xF1FC4F67FA891D1FULL,
+ (u64bit) 0x73ECC25DCB920ADAULL, (u64bit) 0xAE610C22C2A12651ULL, (u64bit) 0x96E0A810D356B78AULL,
+ (u64bit) 0x5A9A381F2FE7870FULL, (u64bit) 0xD5AD62EDE94E5530ULL, (u64bit) 0xD225E5E8368D1427ULL,
+ (u64bit) 0x65977B70C7AF4631ULL, (u64bit) 0x99F889B2DE39D74FULL, (u64bit) 0x233F30BF54E1D143ULL,
+ (u64bit) 0x9A9675D3D9A63C97ULL, (u64bit) 0x5470554FF334F9A8ULL, (u64bit) 0x166ACB744A4F5688ULL,
+ (u64bit) 0x70C74CAAB2E4AEADULL, (u64bit) 0xF0D091646F294D12ULL, (u64bit) 0x57B82A89684031D1ULL,
+ (u64bit) 0xEFD95A5A61BE0B6BULL, (u64bit) 0x2FBD12E969F2F29AULL, (u64bit) 0x9BD37013FEFF9FE8ULL,
+ (u64bit) 0x3F9B0404D6085A06ULL, (u64bit) 0x4940C1F3166CFE15ULL, (u64bit) 0x09542C4DCDF3DEFBULL,
+ (u64bit) 0xB4C5218385CD5CE3ULL, (u64bit) 0xC935B7DC4462A641ULL, (u64bit) 0x3417F8A68ED3B63FULL,
+ (u64bit) 0xB80959295B215B40ULL, (u64bit) 0xF99CDAEF3B8C8572ULL, (u64bit) 0x018C0614F8FCB95DULL,
+ (u64bit) 0x1B14ACCD1A3ACDF3ULL, (u64bit) 0x84D471F200BB732DULL, (u64bit) 0xC1A3110E95E8DA16ULL,
+ (u64bit) 0x430A7220BF1A82B8ULL, (u64bit) 0xB77E090D39DF210EULL, (u64bit) 0x5EF4BD9F3CD05E9DULL,
+ (u64bit) 0x9D4FF6DA7E57A444ULL, (u64bit) 0xDA1D60E183D4A5F8ULL, (u64bit) 0xB287C38417998E47ULL,
+ (u64bit) 0xFE3EDC121BB31886ULL, (u64bit) 0xC7FE3CCC980CCBEFULL, (u64bit) 0xE46FB590189BFD03ULL,
+ (u64bit) 0x3732FD469A4C57DCULL, (u64bit) 0x7EF700A07CF1AD65ULL, (u64bit) 0x59C64468A31D8859ULL,
+ (u64bit) 0x762FB0B4D45B61F6ULL, (u64bit) 0x155BAED099047718ULL, (u64bit) 0x68755E4C3D50BAA6ULL,
+ (u64bit) 0xE9214E7F22D8B4DFULL, (u64bit) 0x2ADDBF532EAC95F4ULL, (u64bit) 0x32AE3909B4BD0109ULL,
+ (u64bit) 0x834DF537B08E3450ULL, (u64bit) 0xFA209DA84220728DULL, (u64bit) 0x9E691D9B9EFE23F7ULL,
+ (u64bit) 0x0446D288C4AE8D7FULL, (u64bit) 0x7B4CC524E169785BULL, (u64bit) 0x21D87F0135CA1385ULL,
+ (u64bit) 0xCEBB400F137B8AA5ULL, (u64bit) 0x272E2B66580796BEULL, (u64bit) 0x3612264125C2B0DEULL,
+ (u64bit) 0x057702BDAD1EFBB2ULL, (u64bit) 0xD4BABB8EACF84BE9ULL, (u64bit) 0x91583139641BC67BULL,
+ (u64bit) 0x8BDC2DE08036E024ULL, (u64bit) 0x603C8156F49F68EDULL, (u64bit) 0xF7D236F7DBEF5111ULL,
+ (u64bit) 0x9727C4598AD21E80ULL, (u64bit) 0xA08A0896670A5FD7ULL, (u64bit) 0xCB4A8F4309EBA9CBULL,
+ (u64bit) 0x81AF564B0F7036A1ULL, (u64bit) 0xC0B99AA778199ABDULL, (u64bit) 0x959F1EC83FC8E952ULL,
+ (u64bit) 0x8C505077794A81B9ULL, (u64bit) 0x3ACAAF8F056338F0ULL, (u64bit) 0x07B43F50627A6778ULL,
+ (u64bit) 0x4A44AB49F5ECCC77ULL, (u64bit) 0x3BC3D6E4B679EE98ULL, (u64bit) 0x9CC0D4D1CF14108CULL,
+ (u64bit) 0x4406C00B206BC8A0ULL, (u64bit) 0x82A18854C8D72D89ULL, (u64bit) 0x67E366B35C3C432CULL,
+ (u64bit) 0xB923DD61102B37F2ULL, (u64bit) 0x56AB2779D884271DULL, (u64bit) 0xBE83E1B0FF1525AFULL,
+ (u64bit) 0xFB7C65D4217E49A9ULL, (u64bit) 0x6BDBE0E76D48E7D4ULL, (u64bit) 0x08DF828745D9179EULL,
+ (u64bit) 0x22EA6A9ADD53BD34ULL, (u64bit) 0xE36E141C5622200AULL, (u64bit) 0x7F805D1B8CB750EEULL,
+ (u64bit) 0xAFE5C7A59F58E837ULL, (u64bit) 0xE27F996A4FB1C23CULL, (u64bit) 0xD3867DFB0775F0D0ULL,
+ (u64bit) 0xD0E673DE6E88891AULL, (u64bit) 0x123AEB9EAFB86C25ULL, (u64bit) 0x30F1D5D5C145B895ULL,
+ (u64bit) 0xBB434A2DEE7269E7ULL, (u64bit) 0x78CB67ECF931FA38ULL, (u64bit) 0xF33B0372323BBF9CULL,
+ (u64bit) 0x52D66336FB279C74ULL, (u64bit) 0x505F33AC0AFB4EAAULL, (u64bit) 0xE8A5CD99A2CCE187ULL,
+ (u64bit) 0x534974801E2D30BBULL, (u64bit) 0x8D2D5711D5876D90ULL, (u64bit) 0x1F1A412891BC038EULL,
+ (u64bit) 0xD6E2E71D82E56648ULL, (u64bit) 0x74036C3A497732B7ULL, (u64bit) 0x89B67ED96361F5ABULL,
+ (u64bit) 0xFFED95D8F1EA02A2ULL, (u64bit) 0xE72B3BD61464D43DULL, (u64bit) 0xA6300F170BDC4820ULL,
+ (u64bit) 0xEBC18760ED78A77AULL };
+
+const u64bit Tiger::SBOX2[256] = {
+ (u64bit) 0xE6A6BE5A05A12138ULL, (u64bit) 0xB5A122A5B4F87C98ULL, (u64bit) 0x563C6089140B6990ULL,
+ (u64bit) 0x4C46CB2E391F5DD5ULL, (u64bit) 0xD932ADDBC9B79434ULL, (u64bit) 0x08EA70E42015AFF5ULL,
+ (u64bit) 0xD765A6673E478CF1ULL, (u64bit) 0xC4FB757EAB278D99ULL, (u64bit) 0xDF11C6862D6E0692ULL,
+ (u64bit) 0xDDEB84F10D7F3B16ULL, (u64bit) 0x6F2EF604A665EA04ULL, (u64bit) 0x4A8E0F0FF0E0DFB3ULL,
+ (u64bit) 0xA5EDEEF83DBCBA51ULL, (u64bit) 0xFC4F0A2A0EA4371EULL, (u64bit) 0xE83E1DA85CB38429ULL,
+ (u64bit) 0xDC8FF882BA1B1CE2ULL, (u64bit) 0xCD45505E8353E80DULL, (u64bit) 0x18D19A00D4DB0717ULL,
+ (u64bit) 0x34A0CFEDA5F38101ULL, (u64bit) 0x0BE77E518887CAF2ULL, (u64bit) 0x1E341438B3C45136ULL,
+ (u64bit) 0xE05797F49089CCF9ULL, (u64bit) 0xFFD23F9DF2591D14ULL, (u64bit) 0x543DDA228595C5CDULL,
+ (u64bit) 0x661F81FD99052A33ULL, (u64bit) 0x8736E641DB0F7B76ULL, (u64bit) 0x15227725418E5307ULL,
+ (u64bit) 0xE25F7F46162EB2FAULL, (u64bit) 0x48A8B2126C13D9FEULL, (u64bit) 0xAFDC541792E76EEAULL,
+ (u64bit) 0x03D912BFC6D1898FULL, (u64bit) 0x31B1AAFA1B83F51BULL, (u64bit) 0xF1AC2796E42AB7D9ULL,
+ (u64bit) 0x40A3A7D7FCD2EBACULL, (u64bit) 0x1056136D0AFBBCC5ULL, (u64bit) 0x7889E1DD9A6D0C85ULL,
+ (u64bit) 0xD33525782A7974AAULL, (u64bit) 0xA7E25D09078AC09BULL, (u64bit) 0xBD4138B3EAC6EDD0ULL,
+ (u64bit) 0x920ABFBE71EB9E70ULL, (u64bit) 0xA2A5D0F54FC2625CULL, (u64bit) 0xC054E36B0B1290A3ULL,
+ (u64bit) 0xF6DD59FF62FE932BULL, (u64bit) 0x3537354511A8AC7DULL, (u64bit) 0xCA845E9172FADCD4ULL,
+ (u64bit) 0x84F82B60329D20DCULL, (u64bit) 0x79C62CE1CD672F18ULL, (u64bit) 0x8B09A2ADD124642CULL,
+ (u64bit) 0xD0C1E96A19D9E726ULL, (u64bit) 0x5A786A9B4BA9500CULL, (u64bit) 0x0E020336634C43F3ULL,
+ (u64bit) 0xC17B474AEB66D822ULL, (u64bit) 0x6A731AE3EC9BAAC2ULL, (u64bit) 0x8226667AE0840258ULL,
+ (u64bit) 0x67D4567691CAECA5ULL, (u64bit) 0x1D94155C4875ADB5ULL, (u64bit) 0x6D00FD985B813FDFULL,
+ (u64bit) 0x51286EFCB774CD06ULL, (u64bit) 0x5E8834471FA744AFULL, (u64bit) 0xF72CA0AEE761AE2EULL,
+ (u64bit) 0xBE40E4CDAEE8E09AULL, (u64bit) 0xE9970BBB5118F665ULL, (u64bit) 0x726E4BEB33DF1964ULL,
+ (u64bit) 0x703B000729199762ULL, (u64bit) 0x4631D816F5EF30A7ULL, (u64bit) 0xB880B5B51504A6BEULL,
+ (u64bit) 0x641793C37ED84B6CULL, (u64bit) 0x7B21ED77F6E97D96ULL, (u64bit) 0x776306312EF96B73ULL,
+ (u64bit) 0xAE528948E86FF3F4ULL, (u64bit) 0x53DBD7F286A3F8F8ULL, (u64bit) 0x16CADCE74CFC1063ULL,
+ (u64bit) 0x005C19BDFA52C6DDULL, (u64bit) 0x68868F5D64D46AD3ULL, (u64bit) 0x3A9D512CCF1E186AULL,
+ (u64bit) 0x367E62C2385660AEULL, (u64bit) 0xE359E7EA77DCB1D7ULL, (u64bit) 0x526C0773749ABE6EULL,
+ (u64bit) 0x735AE5F9D09F734BULL, (u64bit) 0x493FC7CC8A558BA8ULL, (u64bit) 0xB0B9C1533041AB45ULL,
+ (u64bit) 0x321958BA470A59BDULL, (u64bit) 0x852DB00B5F46C393ULL, (u64bit) 0x91209B2BD336B0E5ULL,
+ (u64bit) 0x6E604F7D659EF19FULL, (u64bit) 0xB99A8AE2782CCB24ULL, (u64bit) 0xCCF52AB6C814C4C7ULL,
+ (u64bit) 0x4727D9AFBE11727BULL, (u64bit) 0x7E950D0C0121B34DULL, (u64bit) 0x756F435670AD471FULL,
+ (u64bit) 0xF5ADD442615A6849ULL, (u64bit) 0x4E87E09980B9957AULL, (u64bit) 0x2ACFA1DF50AEE355ULL,
+ (u64bit) 0xD898263AFD2FD556ULL, (u64bit) 0xC8F4924DD80C8FD6ULL, (u64bit) 0xCF99CA3D754A173AULL,
+ (u64bit) 0xFE477BACAF91BF3CULL, (u64bit) 0xED5371F6D690C12DULL, (u64bit) 0x831A5C285E687094ULL,
+ (u64bit) 0xC5D3C90A3708A0A4ULL, (u64bit) 0x0F7F903717D06580ULL, (u64bit) 0x19F9BB13B8FDF27FULL,
+ (u64bit) 0xB1BD6F1B4D502843ULL, (u64bit) 0x1C761BA38FFF4012ULL, (u64bit) 0x0D1530C4E2E21F3BULL,
+ (u64bit) 0x8943CE69A7372C8AULL, (u64bit) 0xE5184E11FEB5CE66ULL, (u64bit) 0x618BDB80BD736621ULL,
+ (u64bit) 0x7D29BAD68B574D0BULL, (u64bit) 0x81BB613E25E6FE5BULL, (u64bit) 0x071C9C10BC07913FULL,
+ (u64bit) 0xC7BEEB7909AC2D97ULL, (u64bit) 0xC3E58D353BC5D757ULL, (u64bit) 0xEB017892F38F61E8ULL,
+ (u64bit) 0xD4EFFB9C9B1CC21AULL, (u64bit) 0x99727D26F494F7ABULL, (u64bit) 0xA3E063A2956B3E03ULL,
+ (u64bit) 0x9D4A8B9A4AA09C30ULL, (u64bit) 0x3F6AB7D500090FB4ULL, (u64bit) 0x9CC0F2A057268AC0ULL,
+ (u64bit) 0x3DEE9D2DEDBF42D1ULL, (u64bit) 0x330F49C87960A972ULL, (u64bit) 0xC6B2720287421B41ULL,
+ (u64bit) 0x0AC59EC07C00369CULL, (u64bit) 0xEF4EAC49CB353425ULL, (u64bit) 0xF450244EEF0129D8ULL,
+ (u64bit) 0x8ACC46E5CAF4DEB6ULL, (u64bit) 0x2FFEAB63989263F7ULL, (u64bit) 0x8F7CB9FE5D7A4578ULL,
+ (u64bit) 0x5BD8F7644E634635ULL, (u64bit) 0x427A7315BF2DC900ULL, (u64bit) 0x17D0C4AA2125261CULL,
+ (u64bit) 0x3992486C93518E50ULL, (u64bit) 0xB4CBFEE0A2D7D4C3ULL, (u64bit) 0x7C75D6202C5DDD8DULL,
+ (u64bit) 0xDBC295D8E35B6C61ULL, (u64bit) 0x60B369D302032B19ULL, (u64bit) 0xCE42685FDCE44132ULL,
+ (u64bit) 0x06F3DDB9DDF65610ULL, (u64bit) 0x8EA4D21DB5E148F0ULL, (u64bit) 0x20B0FCE62FCD496FULL,
+ (u64bit) 0x2C1B912358B0EE31ULL, (u64bit) 0xB28317B818F5A308ULL, (u64bit) 0xA89C1E189CA6D2CFULL,
+ (u64bit) 0x0C6B18576AAADBC8ULL, (u64bit) 0xB65DEAA91299FAE3ULL, (u64bit) 0xFB2B794B7F1027E7ULL,
+ (u64bit) 0x04E4317F443B5BEBULL, (u64bit) 0x4B852D325939D0A6ULL, (u64bit) 0xD5AE6BEEFB207FFCULL,
+ (u64bit) 0x309682B281C7D374ULL, (u64bit) 0xBAE309A194C3B475ULL, (u64bit) 0x8CC3F97B13B49F05ULL,
+ (u64bit) 0x98A9422FF8293967ULL, (u64bit) 0x244B16B01076FF7CULL, (u64bit) 0xF8BF571C663D67EEULL,
+ (u64bit) 0x1F0D6758EEE30DA1ULL, (u64bit) 0xC9B611D97ADEB9B7ULL, (u64bit) 0xB7AFD5887B6C57A2ULL,
+ (u64bit) 0x6290AE846B984FE1ULL, (u64bit) 0x94DF4CDEACC1A5FDULL, (u64bit) 0x058A5BD1C5483AFFULL,
+ (u64bit) 0x63166CC142BA3C37ULL, (u64bit) 0x8DB8526EB2F76F40ULL, (u64bit) 0xE10880036F0D6D4EULL,
+ (u64bit) 0x9E0523C9971D311DULL, (u64bit) 0x45EC2824CC7CD691ULL, (u64bit) 0x575B8359E62382C9ULL,
+ (u64bit) 0xFA9E400DC4889995ULL, (u64bit) 0xD1823ECB45721568ULL, (u64bit) 0xDAFD983B8206082FULL,
+ (u64bit) 0xAA7D29082386A8CBULL, (u64bit) 0x269FCD4403B87588ULL, (u64bit) 0x1B91F5F728BDD1E0ULL,
+ (u64bit) 0xE4669F39040201F6ULL, (u64bit) 0x7A1D7C218CF04ADEULL, (u64bit) 0x65623C29D79CE5CEULL,
+ (u64bit) 0x2368449096C00BB1ULL, (u64bit) 0xAB9BF1879DA503BAULL, (u64bit) 0xBC23ECB1A458058EULL,
+ (u64bit) 0x9A58DF01BB401ECCULL, (u64bit) 0xA070E868A85F143DULL, (u64bit) 0x4FF188307DF2239EULL,
+ (u64bit) 0x14D565B41A641183ULL, (u64bit) 0xEE13337452701602ULL, (u64bit) 0x950E3DCF3F285E09ULL,
+ (u64bit) 0x59930254B9C80953ULL, (u64bit) 0x3BF299408930DA6DULL, (u64bit) 0xA955943F53691387ULL,
+ (u64bit) 0xA15EDECAA9CB8784ULL, (u64bit) 0x29142127352BE9A0ULL, (u64bit) 0x76F0371FFF4E7AFBULL,
+ (u64bit) 0x0239F450274F2228ULL, (u64bit) 0xBB073AF01D5E868BULL, (u64bit) 0xBFC80571C10E96C1ULL,
+ (u64bit) 0xD267088568222E23ULL, (u64bit) 0x9671A3D48E80B5B0ULL, (u64bit) 0x55B5D38AE193BB81ULL,
+ (u64bit) 0x693AE2D0A18B04B8ULL, (u64bit) 0x5C48B4ECADD5335FULL, (u64bit) 0xFD743B194916A1CAULL,
+ (u64bit) 0x2577018134BE98C4ULL, (u64bit) 0xE77987E83C54A4ADULL, (u64bit) 0x28E11014DA33E1B9ULL,
+ (u64bit) 0x270CC59E226AA213ULL, (u64bit) 0x71495F756D1A5F60ULL, (u64bit) 0x9BE853FB60AFEF77ULL,
+ (u64bit) 0xADC786A7F7443DBFULL, (u64bit) 0x0904456173B29A82ULL, (u64bit) 0x58BC7A66C232BD5EULL,
+ (u64bit) 0xF306558C673AC8B2ULL, (u64bit) 0x41F639C6B6C9772AULL, (u64bit) 0x216DEFE99FDA35DAULL,
+ (u64bit) 0x11640CC71C7BE615ULL, (u64bit) 0x93C43694565C5527ULL, (u64bit) 0xEA038E6246777839ULL,
+ (u64bit) 0xF9ABF3CE5A3E2469ULL, (u64bit) 0x741E768D0FD312D2ULL, (u64bit) 0x0144B883CED652C6ULL,
+ (u64bit) 0xC20B5A5BA33F8552ULL, (u64bit) 0x1AE69633C3435A9DULL, (u64bit) 0x97A28CA4088CFDECULL,
+ (u64bit) 0x8824A43C1E96F420ULL, (u64bit) 0x37612FA66EEEA746ULL, (u64bit) 0x6B4CB165F9CF0E5AULL,
+ (u64bit) 0x43AA1C06A0ABFB4AULL, (u64bit) 0x7F4DC26FF162796BULL, (u64bit) 0x6CBACC8E54ED9B0FULL,
+ (u64bit) 0xA6B7FFEFD2BB253EULL, (u64bit) 0x2E25BC95B0A29D4FULL, (u64bit) 0x86D6A58BDEF1388CULL,
+ (u64bit) 0xDED74AC576B6F054ULL, (u64bit) 0x8030BDBC2B45805DULL, (u64bit) 0x3C81AF70E94D9289ULL,
+ (u64bit) 0x3EFF6DDA9E3100DBULL, (u64bit) 0xB38DC39FDFCC8847ULL, (u64bit) 0x123885528D17B87EULL,
+ (u64bit) 0xF2DA0ED240B1B642ULL, (u64bit) 0x44CEFADCD54BF9A9ULL, (u64bit) 0x1312200E433C7EE6ULL,
+ (u64bit) 0x9FFCC84F3A78C748ULL, (u64bit) 0xF0CD1F72248576BBULL, (u64bit) 0xEC6974053638CFE4ULL,
+ (u64bit) 0x2BA7B67C0CEC4E4CULL, (u64bit) 0xAC2F4DF3E5CE32EDULL, (u64bit) 0xCB33D14326EA4C11ULL,
+ (u64bit) 0xA4E9044CC77E58BCULL, (u64bit) 0x5F513293D934FCEFULL, (u64bit) 0x5DC9645506E55444ULL,
+ (u64bit) 0x50DE418F317DE40AULL, (u64bit) 0x388CB31A69DDE259ULL, (u64bit) 0x2DB4A83455820A86ULL,
+ (u64bit) 0x9010A91E84711AE9ULL, (u64bit) 0x4DF7F0B7B1498371ULL, (u64bit) 0xD62A2EABC0977179ULL,
+ (u64bit) 0x22FAC097AA8D5C0EULL };
+
+const u64bit Tiger::SBOX3[256] = {
+ (u64bit) 0xF49FCC2FF1DAF39BULL, (u64bit) 0x487FD5C66FF29281ULL, (u64bit) 0xE8A30667FCDCA83FULL,
+ (u64bit) 0x2C9B4BE3D2FCCE63ULL, (u64bit) 0xDA3FF74B93FBBBC2ULL, (u64bit) 0x2FA165D2FE70BA66ULL,
+ (u64bit) 0xA103E279970E93D4ULL, (u64bit) 0xBECDEC77B0E45E71ULL, (u64bit) 0xCFB41E723985E497ULL,
+ (u64bit) 0xB70AAA025EF75017ULL, (u64bit) 0xD42309F03840B8E0ULL, (u64bit) 0x8EFC1AD035898579ULL,
+ (u64bit) 0x96C6920BE2B2ABC5ULL, (u64bit) 0x66AF4163375A9172ULL, (u64bit) 0x2174ABDCCA7127FBULL,
+ (u64bit) 0xB33CCEA64A72FF41ULL, (u64bit) 0xF04A4933083066A5ULL, (u64bit) 0x8D970ACDD7289AF5ULL,
+ (u64bit) 0x8F96E8E031C8C25EULL, (u64bit) 0xF3FEC02276875D47ULL, (u64bit) 0xEC7BF310056190DDULL,
+ (u64bit) 0xF5ADB0AEBB0F1491ULL, (u64bit) 0x9B50F8850FD58892ULL, (u64bit) 0x4975488358B74DE8ULL,
+ (u64bit) 0xA3354FF691531C61ULL, (u64bit) 0x0702BBE481D2C6EEULL, (u64bit) 0x89FB24057DEDED98ULL,
+ (u64bit) 0xAC3075138596E902ULL, (u64bit) 0x1D2D3580172772EDULL, (u64bit) 0xEB738FC28E6BC30DULL,
+ (u64bit) 0x5854EF8F63044326ULL, (u64bit) 0x9E5C52325ADD3BBEULL, (u64bit) 0x90AA53CF325C4623ULL,
+ (u64bit) 0xC1D24D51349DD067ULL, (u64bit) 0x2051CFEEA69EA624ULL, (u64bit) 0x13220F0A862E7E4FULL,
+ (u64bit) 0xCE39399404E04864ULL, (u64bit) 0xD9C42CA47086FCB7ULL, (u64bit) 0x685AD2238A03E7CCULL,
+ (u64bit) 0x066484B2AB2FF1DBULL, (u64bit) 0xFE9D5D70EFBF79ECULL, (u64bit) 0x5B13B9DD9C481854ULL,
+ (u64bit) 0x15F0D475ED1509ADULL, (u64bit) 0x0BEBCD060EC79851ULL, (u64bit) 0xD58C6791183AB7F8ULL,
+ (u64bit) 0xD1187C5052F3EEE4ULL, (u64bit) 0xC95D1192E54E82FFULL, (u64bit) 0x86EEA14CB9AC6CA2ULL,
+ (u64bit) 0x3485BEB153677D5DULL, (u64bit) 0xDD191D781F8C492AULL, (u64bit) 0xF60866BAA784EBF9ULL,
+ (u64bit) 0x518F643BA2D08C74ULL, (u64bit) 0x8852E956E1087C22ULL, (u64bit) 0xA768CB8DC410AE8DULL,
+ (u64bit) 0x38047726BFEC8E1AULL, (u64bit) 0xA67738B4CD3B45AAULL, (u64bit) 0xAD16691CEC0DDE19ULL,
+ (u64bit) 0xC6D4319380462E07ULL, (u64bit) 0xC5A5876D0BA61938ULL, (u64bit) 0x16B9FA1FA58FD840ULL,
+ (u64bit) 0x188AB1173CA74F18ULL, (u64bit) 0xABDA2F98C99C021FULL, (u64bit) 0x3E0580AB134AE816ULL,
+ (u64bit) 0x5F3B05B773645ABBULL, (u64bit) 0x2501A2BE5575F2F6ULL, (u64bit) 0x1B2F74004E7E8BA9ULL,
+ (u64bit) 0x1CD7580371E8D953ULL, (u64bit) 0x7F6ED89562764E30ULL, (u64bit) 0xB15926FF596F003DULL,
+ (u64bit) 0x9F65293DA8C5D6B9ULL, (u64bit) 0x6ECEF04DD690F84CULL, (u64bit) 0x4782275FFF33AF88ULL,
+ (u64bit) 0xE41433083F820801ULL, (u64bit) 0xFD0DFE409A1AF9B5ULL, (u64bit) 0x4325A3342CDB396BULL,
+ (u64bit) 0x8AE77E62B301B252ULL, (u64bit) 0xC36F9E9F6655615AULL, (u64bit) 0x85455A2D92D32C09ULL,
+ (u64bit) 0xF2C7DEA949477485ULL, (u64bit) 0x63CFB4C133A39EBAULL, (u64bit) 0x83B040CC6EBC5462ULL,
+ (u64bit) 0x3B9454C8FDB326B0ULL, (u64bit) 0x56F56A9E87FFD78CULL, (u64bit) 0x2DC2940D99F42BC6ULL,
+ (u64bit) 0x98F7DF096B096E2DULL, (u64bit) 0x19A6E01E3AD852BFULL, (u64bit) 0x42A99CCBDBD4B40BULL,
+ (u64bit) 0xA59998AF45E9C559ULL, (u64bit) 0x366295E807D93186ULL, (u64bit) 0x6B48181BFAA1F773ULL,
+ (u64bit) 0x1FEC57E2157A0A1DULL, (u64bit) 0x4667446AF6201AD5ULL, (u64bit) 0xE615EBCACFB0F075ULL,
+ (u64bit) 0xB8F31F4F68290778ULL, (u64bit) 0x22713ED6CE22D11EULL, (u64bit) 0x3057C1A72EC3C93BULL,
+ (u64bit) 0xCB46ACC37C3F1F2FULL, (u64bit) 0xDBB893FD02AAF50EULL, (u64bit) 0x331FD92E600B9FCFULL,
+ (u64bit) 0xA498F96148EA3AD6ULL, (u64bit) 0xA8D8426E8B6A83EAULL, (u64bit) 0xA089B274B7735CDCULL,
+ (u64bit) 0x87F6B3731E524A11ULL, (u64bit) 0x118808E5CBC96749ULL, (u64bit) 0x9906E4C7B19BD394ULL,
+ (u64bit) 0xAFED7F7E9B24A20CULL, (u64bit) 0x6509EADEEB3644A7ULL, (u64bit) 0x6C1EF1D3E8EF0EDEULL,
+ (u64bit) 0xB9C97D43E9798FB4ULL, (u64bit) 0xA2F2D784740C28A3ULL, (u64bit) 0x7B8496476197566FULL,
+ (u64bit) 0x7A5BE3E6B65F069DULL, (u64bit) 0xF96330ED78BE6F10ULL, (u64bit) 0xEEE60DE77A076A15ULL,
+ (u64bit) 0x2B4BEE4AA08B9BD0ULL, (u64bit) 0x6A56A63EC7B8894EULL, (u64bit) 0x02121359BA34FEF4ULL,
+ (u64bit) 0x4CBF99F8283703FCULL, (u64bit) 0x398071350CAF30C8ULL, (u64bit) 0xD0A77A89F017687AULL,
+ (u64bit) 0xF1C1A9EB9E423569ULL, (u64bit) 0x8C7976282DEE8199ULL, (u64bit) 0x5D1737A5DD1F7ABDULL,
+ (u64bit) 0x4F53433C09A9FA80ULL, (u64bit) 0xFA8B0C53DF7CA1D9ULL, (u64bit) 0x3FD9DCBC886CCB77ULL,
+ (u64bit) 0xC040917CA91B4720ULL, (u64bit) 0x7DD00142F9D1DCDFULL, (u64bit) 0x8476FC1D4F387B58ULL,
+ (u64bit) 0x23F8E7C5F3316503ULL, (u64bit) 0x032A2244E7E37339ULL, (u64bit) 0x5C87A5D750F5A74BULL,
+ (u64bit) 0x082B4CC43698992EULL, (u64bit) 0xDF917BECB858F63CULL, (u64bit) 0x3270B8FC5BF86DDAULL,
+ (u64bit) 0x10AE72BB29B5DD76ULL, (u64bit) 0x576AC94E7700362BULL, (u64bit) 0x1AD112DAC61EFB8FULL,
+ (u64bit) 0x691BC30EC5FAA427ULL, (u64bit) 0xFF246311CC327143ULL, (u64bit) 0x3142368E30E53206ULL,
+ (u64bit) 0x71380E31E02CA396ULL, (u64bit) 0x958D5C960AAD76F1ULL, (u64bit) 0xF8D6F430C16DA536ULL,
+ (u64bit) 0xC8FFD13F1BE7E1D2ULL, (u64bit) 0x7578AE66004DDBE1ULL, (u64bit) 0x05833F01067BE646ULL,
+ (u64bit) 0xBB34B5AD3BFE586DULL, (u64bit) 0x095F34C9A12B97F0ULL, (u64bit) 0x247AB64525D60CA8ULL,
+ (u64bit) 0xDCDBC6F3017477D1ULL, (u64bit) 0x4A2E14D4DECAD24DULL, (u64bit) 0xBDB5E6D9BE0A1EEBULL,
+ (u64bit) 0x2A7E70F7794301ABULL, (u64bit) 0xDEF42D8A270540FDULL, (u64bit) 0x01078EC0A34C22C1ULL,
+ (u64bit) 0xE5DE511AF4C16387ULL, (u64bit) 0x7EBB3A52BD9A330AULL, (u64bit) 0x77697857AA7D6435ULL,
+ (u64bit) 0x004E831603AE4C32ULL, (u64bit) 0xE7A21020AD78E312ULL, (u64bit) 0x9D41A70C6AB420F2ULL,
+ (u64bit) 0x28E06C18EA1141E6ULL, (u64bit) 0xD2B28CBD984F6B28ULL, (u64bit) 0x26B75F6C446E9D83ULL,
+ (u64bit) 0xBA47568C4D418D7FULL, (u64bit) 0xD80BADBFE6183D8EULL, (u64bit) 0x0E206D7F5F166044ULL,
+ (u64bit) 0xE258A43911CBCA3EULL, (u64bit) 0x723A1746B21DC0BCULL, (u64bit) 0xC7CAA854F5D7CDD3ULL,
+ (u64bit) 0x7CAC32883D261D9CULL, (u64bit) 0x7690C26423BA942CULL, (u64bit) 0x17E55524478042B8ULL,
+ (u64bit) 0xE0BE477656A2389FULL, (u64bit) 0x4D289B5E67AB2DA0ULL, (u64bit) 0x44862B9C8FBBFD31ULL,
+ (u64bit) 0xB47CC8049D141365ULL, (u64bit) 0x822C1B362B91C793ULL, (u64bit) 0x4EB14655FB13DFD8ULL,
+ (u64bit) 0x1ECBBA0714E2A97BULL, (u64bit) 0x6143459D5CDE5F14ULL, (u64bit) 0x53A8FBF1D5F0AC89ULL,
+ (u64bit) 0x97EA04D81C5E5B00ULL, (u64bit) 0x622181A8D4FDB3F3ULL, (u64bit) 0xE9BCD341572A1208ULL,
+ (u64bit) 0x1411258643CCE58AULL, (u64bit) 0x9144C5FEA4C6E0A4ULL, (u64bit) 0x0D33D06565CF620FULL,
+ (u64bit) 0x54A48D489F219CA1ULL, (u64bit) 0xC43E5EAC6D63C821ULL, (u64bit) 0xA9728B3A72770DAFULL,
+ (u64bit) 0xD7934E7B20DF87EFULL, (u64bit) 0xE35503B61A3E86E5ULL, (u64bit) 0xCAE321FBC819D504ULL,
+ (u64bit) 0x129A50B3AC60BFA6ULL, (u64bit) 0xCD5E68EA7E9FB6C3ULL, (u64bit) 0xB01C90199483B1C7ULL,
+ (u64bit) 0x3DE93CD5C295376CULL, (u64bit) 0xAED52EDF2AB9AD13ULL, (u64bit) 0x2E60F512C0A07884ULL,
+ (u64bit) 0xBC3D86A3E36210C9ULL, (u64bit) 0x35269D9B163951CEULL, (u64bit) 0x0C7D6E2AD0CDB5FAULL,
+ (u64bit) 0x59E86297D87F5733ULL, (u64bit) 0x298EF221898DB0E7ULL, (u64bit) 0x55000029D1A5AA7EULL,
+ (u64bit) 0x8BC08AE1B5061B45ULL, (u64bit) 0xC2C31C2B6C92703AULL, (u64bit) 0x94CC596BAF25EF42ULL,
+ (u64bit) 0x0A1D73DB22540456ULL, (u64bit) 0x04B6A0F9D9C4179AULL, (u64bit) 0xEFFDAFA2AE3D3C60ULL,
+ (u64bit) 0xF7C8075BB49496C4ULL, (u64bit) 0x9CC5C7141D1CD4E3ULL, (u64bit) 0x78BD1638218E5534ULL,
+ (u64bit) 0xB2F11568F850246AULL, (u64bit) 0xEDFABCFA9502BC29ULL, (u64bit) 0x796CE5F2DA23051BULL,
+ (u64bit) 0xAAE128B0DC93537CULL, (u64bit) 0x3A493DA0EE4B29AEULL, (u64bit) 0xB5DF6B2C416895D7ULL,
+ (u64bit) 0xFCABBD25122D7F37ULL, (u64bit) 0x70810B58105DC4B1ULL, (u64bit) 0xE10FDD37F7882A90ULL,
+ (u64bit) 0x524DCAB5518A3F5CULL, (u64bit) 0x3C9E85878451255BULL, (u64bit) 0x4029828119BD34E2ULL,
+ (u64bit) 0x74A05B6F5D3CECCBULL, (u64bit) 0xB610021542E13ECAULL, (u64bit) 0x0FF979D12F59E2ACULL,
+ (u64bit) 0x6037DA27E4F9CC50ULL, (u64bit) 0x5E92975A0DF1847DULL, (u64bit) 0xD66DE190D3E623FEULL,
+ (u64bit) 0x5032D6B87B568048ULL, (u64bit) 0x9A36B7CE8235216EULL, (u64bit) 0x80272A7A24F64B4AULL,
+ (u64bit) 0x93EFED8B8C6916F7ULL, (u64bit) 0x37DDBFF44CCE1555ULL, (u64bit) 0x4B95DB5D4B99BD25ULL,
+ (u64bit) 0x92D3FDA169812FC0ULL, (u64bit) 0xFB1A4A9A90660BB6ULL, (u64bit) 0x730C196946A4B9B2ULL,
+ (u64bit) 0x81E289AA7F49DA68ULL, (u64bit) 0x64669A0F83B1A05FULL, (u64bit) 0x27B3FF7D9644F48BULL,
+ (u64bit) 0xCC6B615C8DB675B3ULL, (u64bit) 0x674F20B9BCEBBE95ULL, (u64bit) 0x6F31238275655982ULL,
+ (u64bit) 0x5AE488713E45CF05ULL, (u64bit) 0xBF619F9954C21157ULL, (u64bit) 0xEABAC46040A8EAE9ULL,
+ (u64bit) 0x454C6FE9F2C0C1CDULL, (u64bit) 0x419CF6496412691CULL, (u64bit) 0xD3DC3BEF265B0F70ULL,
+ (u64bit) 0x6D0E60F5C3578A9EULL };
+
+const u64bit Tiger::SBOX4[256] = {
+ (u64bit) 0x5B0E608526323C55ULL, (u64bit) 0x1A46C1A9FA1B59F5ULL, (u64bit) 0xA9E245A17C4C8FFAULL,
+ (u64bit) 0x65CA5159DB2955D7ULL, (u64bit) 0x05DB0A76CE35AFC2ULL, (u64bit) 0x81EAC77EA9113D45ULL,
+ (u64bit) 0x528EF88AB6AC0A0DULL, (u64bit) 0xA09EA253597BE3FFULL, (u64bit) 0x430DDFB3AC48CD56ULL,
+ (u64bit) 0xC4B3A67AF45CE46FULL, (u64bit) 0x4ECECFD8FBE2D05EULL, (u64bit) 0x3EF56F10B39935F0ULL,
+ (u64bit) 0x0B22D6829CD619C6ULL, (u64bit) 0x17FD460A74DF2069ULL, (u64bit) 0x6CF8CC8E8510ED40ULL,
+ (u64bit) 0xD6C824BF3A6ECAA7ULL, (u64bit) 0x61243D581A817049ULL, (u64bit) 0x048BACB6BBC163A2ULL,
+ (u64bit) 0xD9A38AC27D44CC32ULL, (u64bit) 0x7FDDFF5BAAF410ABULL, (u64bit) 0xAD6D495AA804824BULL,
+ (u64bit) 0xE1A6A74F2D8C9F94ULL, (u64bit) 0xD4F7851235DEE8E3ULL, (u64bit) 0xFD4B7F886540D893ULL,
+ (u64bit) 0x247C20042AA4BFDAULL, (u64bit) 0x096EA1C517D1327CULL, (u64bit) 0xD56966B4361A6685ULL,
+ (u64bit) 0x277DA5C31221057DULL, (u64bit) 0x94D59893A43ACFF7ULL, (u64bit) 0x64F0C51CCDC02281ULL,
+ (u64bit) 0x3D33BCC4FF6189DBULL, (u64bit) 0xE005CB184CE66AF1ULL, (u64bit) 0xFF5CCD1D1DB99BEAULL,
+ (u64bit) 0xB0B854A7FE42980FULL, (u64bit) 0x7BD46A6A718D4B9FULL, (u64bit) 0xD10FA8CC22A5FD8CULL,
+ (u64bit) 0xD31484952BE4BD31ULL, (u64bit) 0xC7FA975FCB243847ULL, (u64bit) 0x4886ED1E5846C407ULL,
+ (u64bit) 0x28CDDB791EB70B04ULL, (u64bit) 0xC2B00BE2F573417FULL, (u64bit) 0x5C9590452180F877ULL,
+ (u64bit) 0x7A6BDDFFF370EB00ULL, (u64bit) 0xCE509E38D6D9D6A4ULL, (u64bit) 0xEBEB0F00647FA702ULL,
+ (u64bit) 0x1DCC06CF76606F06ULL, (u64bit) 0xE4D9F28BA286FF0AULL, (u64bit) 0xD85A305DC918C262ULL,
+ (u64bit) 0x475B1D8732225F54ULL, (u64bit) 0x2D4FB51668CCB5FEULL, (u64bit) 0xA679B9D9D72BBA20ULL,
+ (u64bit) 0x53841C0D912D43A5ULL, (u64bit) 0x3B7EAA48BF12A4E8ULL, (u64bit) 0x781E0E47F22F1DDFULL,
+ (u64bit) 0xEFF20CE60AB50973ULL, (u64bit) 0x20D261D19DFFB742ULL, (u64bit) 0x16A12B03062A2E39ULL,
+ (u64bit) 0x1960EB2239650495ULL, (u64bit) 0x251C16FED50EB8B8ULL, (u64bit) 0x9AC0C330F826016EULL,
+ (u64bit) 0xED152665953E7671ULL, (u64bit) 0x02D63194A6369570ULL, (u64bit) 0x5074F08394B1C987ULL,
+ (u64bit) 0x70BA598C90B25CE1ULL, (u64bit) 0x794A15810B9742F6ULL, (u64bit) 0x0D5925E9FCAF8C6CULL,
+ (u64bit) 0x3067716CD868744EULL, (u64bit) 0x910AB077E8D7731BULL, (u64bit) 0x6A61BBDB5AC42F61ULL,
+ (u64bit) 0x93513EFBF0851567ULL, (u64bit) 0xF494724B9E83E9D5ULL, (u64bit) 0xE887E1985C09648DULL,
+ (u64bit) 0x34B1D3C675370CFDULL, (u64bit) 0xDC35E433BC0D255DULL, (u64bit) 0xD0AAB84234131BE0ULL,
+ (u64bit) 0x08042A50B48B7EAFULL, (u64bit) 0x9997C4EE44A3AB35ULL, (u64bit) 0x829A7B49201799D0ULL,
+ (u64bit) 0x263B8307B7C54441ULL, (u64bit) 0x752F95F4FD6A6CA6ULL, (u64bit) 0x927217402C08C6E5ULL,
+ (u64bit) 0x2A8AB754A795D9EEULL, (u64bit) 0xA442F7552F72943DULL, (u64bit) 0x2C31334E19781208ULL,
+ (u64bit) 0x4FA98D7CEAEE6291ULL, (u64bit) 0x55C3862F665DB309ULL, (u64bit) 0xBD0610175D53B1F3ULL,
+ (u64bit) 0x46FE6CB840413F27ULL, (u64bit) 0x3FE03792DF0CFA59ULL, (u64bit) 0xCFE700372EB85E8FULL,
+ (u64bit) 0xA7BE29E7ADBCE118ULL, (u64bit) 0xE544EE5CDE8431DDULL, (u64bit) 0x8A781B1B41F1873EULL,
+ (u64bit) 0xA5C94C78A0D2F0E7ULL, (u64bit) 0x39412E2877B60728ULL, (u64bit) 0xA1265EF3AFC9A62CULL,
+ (u64bit) 0xBCC2770C6A2506C5ULL, (u64bit) 0x3AB66DD5DCE1CE12ULL, (u64bit) 0xE65499D04A675B37ULL,
+ (u64bit) 0x7D8F523481BFD216ULL, (u64bit) 0x0F6F64FCEC15F389ULL, (u64bit) 0x74EFBE618B5B13C8ULL,
+ (u64bit) 0xACDC82B714273E1DULL, (u64bit) 0xDD40BFE003199D17ULL, (u64bit) 0x37E99257E7E061F8ULL,
+ (u64bit) 0xFA52626904775AAAULL, (u64bit) 0x8BBBF63A463D56F9ULL, (u64bit) 0xF0013F1543A26E64ULL,
+ (u64bit) 0xA8307E9F879EC898ULL, (u64bit) 0xCC4C27A4150177CCULL, (u64bit) 0x1B432F2CCA1D3348ULL,
+ (u64bit) 0xDE1D1F8F9F6FA013ULL, (u64bit) 0x606602A047A7DDD6ULL, (u64bit) 0xD237AB64CC1CB2C7ULL,
+ (u64bit) 0x9B938E7225FCD1D3ULL, (u64bit) 0xEC4E03708E0FF476ULL, (u64bit) 0xFEB2FBDA3D03C12DULL,
+ (u64bit) 0xAE0BCED2EE43889AULL, (u64bit) 0x22CB8923EBFB4F43ULL, (u64bit) 0x69360D013CF7396DULL,
+ (u64bit) 0x855E3602D2D4E022ULL, (u64bit) 0x073805BAD01F784CULL, (u64bit) 0x33E17A133852F546ULL,
+ (u64bit) 0xDF4874058AC7B638ULL, (u64bit) 0xBA92B29C678AA14AULL, (u64bit) 0x0CE89FC76CFAADCDULL,
+ (u64bit) 0x5F9D4E0908339E34ULL, (u64bit) 0xF1AFE9291F5923B9ULL, (u64bit) 0x6E3480F60F4A265FULL,
+ (u64bit) 0xEEBF3A2AB29B841CULL, (u64bit) 0xE21938A88F91B4ADULL, (u64bit) 0x57DFEFF845C6D3C3ULL,
+ (u64bit) 0x2F006B0BF62CAAF2ULL, (u64bit) 0x62F479EF6F75EE78ULL, (u64bit) 0x11A55AD41C8916A9ULL,
+ (u64bit) 0xF229D29084FED453ULL, (u64bit) 0x42F1C27B16B000E6ULL, (u64bit) 0x2B1F76749823C074ULL,
+ (u64bit) 0x4B76ECA3C2745360ULL, (u64bit) 0x8C98F463B91691BDULL, (u64bit) 0x14BCC93CF1ADE66AULL,
+ (u64bit) 0x8885213E6D458397ULL, (u64bit) 0x8E177DF0274D4711ULL, (u64bit) 0xB49B73B5503F2951ULL,
+ (u64bit) 0x10168168C3F96B6BULL, (u64bit) 0x0E3D963B63CAB0AEULL, (u64bit) 0x8DFC4B5655A1DB14ULL,
+ (u64bit) 0xF789F1356E14DE5CULL, (u64bit) 0x683E68AF4E51DAC1ULL, (u64bit) 0xC9A84F9D8D4B0FD9ULL,
+ (u64bit) 0x3691E03F52A0F9D1ULL, (u64bit) 0x5ED86E46E1878E80ULL, (u64bit) 0x3C711A0E99D07150ULL,
+ (u64bit) 0x5A0865B20C4E9310ULL, (u64bit) 0x56FBFC1FE4F0682EULL, (u64bit) 0xEA8D5DE3105EDF9BULL,
+ (u64bit) 0x71ABFDB12379187AULL, (u64bit) 0x2EB99DE1BEE77B9CULL, (u64bit) 0x21ECC0EA33CF4523ULL,
+ (u64bit) 0x59A4D7521805C7A1ULL, (u64bit) 0x3896F5EB56AE7C72ULL, (u64bit) 0xAA638F3DB18F75DCULL,
+ (u64bit) 0x9F39358DABE9808EULL, (u64bit) 0xB7DEFA91C00B72ACULL, (u64bit) 0x6B5541FD62492D92ULL,
+ (u64bit) 0x6DC6DEE8F92E4D5BULL, (u64bit) 0x353F57ABC4BEEA7EULL, (u64bit) 0x735769D6DA5690CEULL,
+ (u64bit) 0x0A234AA642391484ULL, (u64bit) 0xF6F9508028F80D9DULL, (u64bit) 0xB8E319A27AB3F215ULL,
+ (u64bit) 0x31AD9C1151341A4DULL, (u64bit) 0x773C22A57BEF5805ULL, (u64bit) 0x45C7561A07968633ULL,
+ (u64bit) 0xF913DA9E249DBE36ULL, (u64bit) 0xDA652D9B78A64C68ULL, (u64bit) 0x4C27A97F3BC334EFULL,
+ (u64bit) 0x76621220E66B17F4ULL, (u64bit) 0x967743899ACD7D0BULL, (u64bit) 0xF3EE5BCAE0ED6782ULL,
+ (u64bit) 0x409F753600C879FCULL, (u64bit) 0x06D09A39B5926DB6ULL, (u64bit) 0x6F83AEB0317AC588ULL,
+ (u64bit) 0x01E6CA4A86381F21ULL, (u64bit) 0x66FF3462D19F3025ULL, (u64bit) 0x72207C24DDFD3BFBULL,
+ (u64bit) 0x4AF6B6D3E2ECE2EBULL, (u64bit) 0x9C994DBEC7EA08DEULL, (u64bit) 0x49ACE597B09A8BC4ULL,
+ (u64bit) 0xB38C4766CF0797BAULL, (u64bit) 0x131B9373C57C2A75ULL, (u64bit) 0xB1822CCE61931E58ULL,
+ (u64bit) 0x9D7555B909BA1C0CULL, (u64bit) 0x127FAFDD937D11D2ULL, (u64bit) 0x29DA3BADC66D92E4ULL,
+ (u64bit) 0xA2C1D57154C2ECBCULL, (u64bit) 0x58C5134D82F6FE24ULL, (u64bit) 0x1C3AE3515B62274FULL,
+ (u64bit) 0xE907C82E01CB8126ULL, (u64bit) 0xF8ED091913E37FCBULL, (u64bit) 0x3249D8F9C80046C9ULL,
+ (u64bit) 0x80CF9BEDE388FB63ULL, (u64bit) 0x1881539A116CF19EULL, (u64bit) 0x5103F3F76BD52457ULL,
+ (u64bit) 0x15B7E6F5AE47F7A8ULL, (u64bit) 0xDBD7C6DED47E9CCFULL, (u64bit) 0x44E55C410228BB1AULL,
+ (u64bit) 0xB647D4255EDB4E99ULL, (u64bit) 0x5D11882BB8AAFC30ULL, (u64bit) 0xF5098BBB29D3212AULL,
+ (u64bit) 0x8FB5EA14E90296B3ULL, (u64bit) 0x677B942157DD025AULL, (u64bit) 0xFB58E7C0A390ACB5ULL,
+ (u64bit) 0x89D3674C83BD4A01ULL, (u64bit) 0x9E2DA4DF4BF3B93BULL, (u64bit) 0xFCC41E328CAB4829ULL,
+ (u64bit) 0x03F38C96BA582C52ULL, (u64bit) 0xCAD1BDBD7FD85DB2ULL, (u64bit) 0xBBB442C16082AE83ULL,
+ (u64bit) 0xB95FE86BA5DA9AB0ULL, (u64bit) 0xB22E04673771A93FULL, (u64bit) 0x845358C9493152D8ULL,
+ (u64bit) 0xBE2A488697B4541EULL, (u64bit) 0x95A2DC2DD38E6966ULL, (u64bit) 0xC02C11AC923C852BULL,
+ (u64bit) 0x2388B1990DF2A87BULL, (u64bit) 0x7C8008FA1B4F37BEULL, (u64bit) 0x1F70D0C84D54E503ULL,
+ (u64bit) 0x5490ADEC7ECE57D4ULL, (u64bit) 0x002B3C27D9063A3AULL, (u64bit) 0x7EAEA3848030A2BFULL,
+ (u64bit) 0xC602326DED2003C0ULL, (u64bit) 0x83A7287D69A94086ULL, (u64bit) 0xC57A5FCB30F57A8AULL,
+ (u64bit) 0xB56844E479EBE779ULL, (u64bit) 0xA373B40F05DCBCE9ULL, (u64bit) 0xD71A786E88570EE2ULL,
+ (u64bit) 0x879CBACDBDE8F6A0ULL, (u64bit) 0x976AD1BCC164A32FULL, (u64bit) 0xAB21E25E9666D78BULL,
+ (u64bit) 0x901063AAE5E5C33CULL, (u64bit) 0x9818B34448698D90ULL, (u64bit) 0xE36487AE3E1E8ABBULL,
+ (u64bit) 0xAFBDF931893BDCB4ULL, (u64bit) 0x6345A0DC5FBBD519ULL, (u64bit) 0x8628FE269B9465CAULL,
+ (u64bit) 0x1E5D01603F9C51ECULL, (u64bit) 0x4DE44006A15049B7ULL, (u64bit) 0xBF6C70E5F776CBB1ULL,
+ (u64bit) 0x411218F2EF552BEDULL, (u64bit) 0xCB0C0708705A36A3ULL, (u64bit) 0xE74D14754F986044ULL,
+ (u64bit) 0xCD56D9430EA8280EULL, (u64bit) 0xC12591D7535F5065ULL, (u64bit) 0xC83223F1720AEF96ULL,
+ (u64bit) 0xC3A0396F7363A51FULL };
+
+}
diff --git a/botan/src/hash/tiger/tiger.cpp b/botan/src/hash/tiger/tiger.cpp
new file mode 100644
index 0000000..08af9c7
--- /dev/null
+++ b/botan/src/hash/tiger/tiger.cpp
@@ -0,0 +1,164 @@
+/*
+* Tiger
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tiger.h>
+#include <botan/exceptn.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Tiger Compression Function
+*/
+void Tiger::compress_n(const byte input[], u32bit blocks)
+ {
+ u64bit A = digest[0], B = digest[1], C = digest[2];
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 8; ++j)
+ X[j] = load_le<u64bit>(input, j);
+ input += HASH_BLOCK_SIZE;
+
+ pass(A, B, C, X, 5); mix(X);
+ pass(C, A, B, X, 7); mix(X);
+ pass(B, C, A, X, 9);
+
+ for(u32bit j = 3; j != PASS; ++j)
+ {
+ mix(X);
+ pass(A, B, C, X, 9);
+ u64bit T = A; A = C; C = B; B = T;
+ }
+
+ A = (digest[0] ^= A);
+ B = digest[1] = B - digest[1];
+ C = (digest[2] += C);
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void Tiger::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; ++j)
+ output[j] = get_byte(7 - (j % 8), digest[j/8]);
+ }
+
+/*
+* Tiger Pass
+*/
+void Tiger::pass(u64bit& A, u64bit& B, u64bit& C, u64bit X[8], byte mul)
+ {
+ C ^= X[0];
+ A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^
+ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)];
+ B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^
+ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)];
+ B *= mul;
+
+ A ^= X[1];
+ B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^
+ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)];
+ C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^
+ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)];
+ C *= mul;
+
+ B ^= X[2];
+ C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^
+ SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)];
+ A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^
+ SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)];
+ A *= mul;
+
+ C ^= X[3];
+ A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^
+ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)];
+ B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^
+ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)];
+ B *= mul;
+
+ A ^= X[4];
+ B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^
+ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)];
+ C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^
+ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)];
+ C *= mul;
+
+ B ^= X[5];
+ C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^
+ SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)];
+ A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^
+ SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)];
+ A *= mul;
+
+ C ^= X[6];
+ A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^
+ SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)];
+ B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^
+ SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)];
+ B *= mul;
+
+ A ^= X[7];
+ B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^
+ SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)];
+ C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^
+ SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)];
+ C *= mul;
+ }
+
+/*
+* Tiger Mixing Function
+*/
+void Tiger::mix(u64bit X[8])
+ {
+ X[0] -= X[7] ^ (u64bit) 0xA5A5A5A5A5A5A5A5ULL; X[1] ^= X[0];
+ X[2] += X[1]; X[3] -= X[2] ^ ((~X[1]) << 19); X[4] ^= X[3];
+ X[5] += X[4]; X[6] -= X[5] ^ ((~X[4]) >> 23); X[7] ^= X[6];
+ X[0] += X[7]; X[1] -= X[0] ^ ((~X[7]) << 19); X[2] ^= X[1];
+ X[3] += X[2]; X[4] -= X[3] ^ ((~X[2]) >> 23); X[5] ^= X[4];
+ X[6] += X[5]; X[7] -= X[6] ^ (u64bit) 0x0123456789ABCDEFULL;
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Tiger::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ X.clear();
+ digest[0] = (u64bit) 0x0123456789ABCDEFULL;
+ digest[1] = (u64bit) 0xFEDCBA9876543210ULL;
+ digest[2] = (u64bit) 0xF096A5B4C3B2E187ULL;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string Tiger::name() const
+ {
+ return "Tiger(" + to_string(OUTPUT_LENGTH) + "," + to_string(PASS) + ")";
+ }
+
+/*
+* Tiger Constructor
+*/
+Tiger::Tiger(u32bit hashlen, u32bit pass) :
+ MDx_HashFunction(hashlen, 64, false, false), PASS(pass)
+ {
+ if(OUTPUT_LENGTH != 16 && OUTPUT_LENGTH != 20 && OUTPUT_LENGTH != 24)
+ throw Invalid_Argument("Tiger: Illegal hash output size: " +
+ to_string(OUTPUT_LENGTH));
+ if(PASS < 3)
+ throw Invalid_Argument("Tiger: Invalid number of passes: "
+ + to_string(PASS));
+ clear();
+ }
+
+}
diff --git a/botan/src/hash/tiger/tiger.h b/botan/src/hash/tiger/tiger.h
new file mode 100644
index 0000000..63184a9
--- /dev/null
+++ b/botan/src/hash/tiger/tiger.h
@@ -0,0 +1,44 @@
+/*
+* Tiger
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIGER_H__
+#define BOTAN_TIGER_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* Tiger
+*/
+class BOTAN_DLL Tiger : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ HashFunction* clone() const { return new Tiger(OUTPUT_LENGTH); }
+ Tiger(u32bit = 24, u32bit = 3);
+ private:
+ void compress_n(const byte[], u32bit block);
+ void copy_out(byte[]);
+
+ static void pass(u64bit&, u64bit&, u64bit&, u64bit[8], byte);
+ static void mix(u64bit[8]);
+
+ static const u64bit SBOX1[256];
+ static const u64bit SBOX2[256];
+ static const u64bit SBOX3[256];
+ static const u64bit SBOX4[256];
+
+ SecureBuffer<u64bit, 8> X;
+ SecureBuffer<u64bit, 3> digest;
+ const u32bit PASS;
+ };
+
+}
+
+#endif
diff --git a/botan/src/hash/whirlpool/info.txt b/botan/src/hash/whirlpool/info.txt
new file mode 100644
index 0000000..be55b5c
--- /dev/null
+++ b/botan/src/hash/whirlpool/info.txt
@@ -0,0 +1,15 @@
+realname "Whirlpool"
+
+define WHIRLPOOL
+
+load_on auto
+
+<add>
+whrl_tab.cpp
+whrlpool.cpp
+whrlpool.h
+</add>
+
+<requires>
+mdx_hash
+</requires>
diff --git a/botan/src/hash/whirlpool/whrl_tab.cpp b/botan/src/hash/whirlpool/whrl_tab.cpp
new file mode 100644
index 0000000..7ece927
--- /dev/null
+++ b/botan/src/hash/whirlpool/whrl_tab.cpp
@@ -0,0 +1,540 @@
+/*
+* Diffusion Tables for Whirlpool
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/whrlpool.h>
+
+namespace Botan {
+
+const u64bit Whirlpool::C0[256] = {
+(u64bit) 0x18186018C07830D8ULL, (u64bit) 0x23238C2305AF4626ULL, (u64bit) 0xC6C63FC67EF991B8ULL, (u64bit) 0xE8E887E8136FCDFBULL,
+(u64bit) 0x878726874CA113CBULL, (u64bit) 0xB8B8DAB8A9626D11ULL, (u64bit) 0x0101040108050209ULL, (u64bit) 0x4F4F214F426E9E0DULL,
+(u64bit) 0x3636D836ADEE6C9BULL, (u64bit) 0xA6A6A2A6590451FFULL, (u64bit) 0xD2D26FD2DEBDB90CULL, (u64bit) 0xF5F5F3F5FB06F70EULL,
+(u64bit) 0x7979F979EF80F296ULL, (u64bit) 0x6F6FA16F5FCEDE30ULL, (u64bit) 0x91917E91FCEF3F6DULL, (u64bit) 0x52525552AA07A4F8ULL,
+(u64bit) 0x60609D6027FDC047ULL, (u64bit) 0xBCBCCABC89766535ULL, (u64bit) 0x9B9B569BACCD2B37ULL, (u64bit) 0x8E8E028E048C018AULL,
+(u64bit) 0xA3A3B6A371155BD2ULL, (u64bit) 0x0C0C300C603C186CULL, (u64bit) 0x7B7BF17BFF8AF684ULL, (u64bit) 0x3535D435B5E16A80ULL,
+(u64bit) 0x1D1D741DE8693AF5ULL, (u64bit) 0xE0E0A7E05347DDB3ULL, (u64bit) 0xD7D77BD7F6ACB321ULL, (u64bit) 0xC2C22FC25EED999CULL,
+(u64bit) 0x2E2EB82E6D965C43ULL, (u64bit) 0x4B4B314B627A9629ULL, (u64bit) 0xFEFEDFFEA321E15DULL, (u64bit) 0x575741578216AED5ULL,
+(u64bit) 0x15155415A8412ABDULL, (u64bit) 0x7777C1779FB6EEE8ULL, (u64bit) 0x3737DC37A5EB6E92ULL, (u64bit) 0xE5E5B3E57B56D79EULL,
+(u64bit) 0x9F9F469F8CD92313ULL, (u64bit) 0xF0F0E7F0D317FD23ULL, (u64bit) 0x4A4A354A6A7F9420ULL, (u64bit) 0xDADA4FDA9E95A944ULL,
+(u64bit) 0x58587D58FA25B0A2ULL, (u64bit) 0xC9C903C906CA8FCFULL, (u64bit) 0x2929A429558D527CULL, (u64bit) 0x0A0A280A5022145AULL,
+(u64bit) 0xB1B1FEB1E14F7F50ULL, (u64bit) 0xA0A0BAA0691A5DC9ULL, (u64bit) 0x6B6BB16B7FDAD614ULL, (u64bit) 0x85852E855CAB17D9ULL,
+(u64bit) 0xBDBDCEBD8173673CULL, (u64bit) 0x5D5D695DD234BA8FULL, (u64bit) 0x1010401080502090ULL, (u64bit) 0xF4F4F7F4F303F507ULL,
+(u64bit) 0xCBCB0BCB16C08BDDULL, (u64bit) 0x3E3EF83EEDC67CD3ULL, (u64bit) 0x0505140528110A2DULL, (u64bit) 0x676781671FE6CE78ULL,
+(u64bit) 0xE4E4B7E47353D597ULL, (u64bit) 0x27279C2725BB4E02ULL, (u64bit) 0x4141194132588273ULL, (u64bit) 0x8B8B168B2C9D0BA7ULL,
+(u64bit) 0xA7A7A6A7510153F6ULL, (u64bit) 0x7D7DE97DCF94FAB2ULL, (u64bit) 0x95956E95DCFB3749ULL, (u64bit) 0xD8D847D88E9FAD56ULL,
+(u64bit) 0xFBFBCBFB8B30EB70ULL, (u64bit) 0xEEEE9FEE2371C1CDULL, (u64bit) 0x7C7CED7CC791F8BBULL, (u64bit) 0x6666856617E3CC71ULL,
+(u64bit) 0xDDDD53DDA68EA77BULL, (u64bit) 0x17175C17B84B2EAFULL, (u64bit) 0x4747014702468E45ULL, (u64bit) 0x9E9E429E84DC211AULL,
+(u64bit) 0xCACA0FCA1EC589D4ULL, (u64bit) 0x2D2DB42D75995A58ULL, (u64bit) 0xBFBFC6BF9179632EULL, (u64bit) 0x07071C07381B0E3FULL,
+(u64bit) 0xADAD8EAD012347ACULL, (u64bit) 0x5A5A755AEA2FB4B0ULL, (u64bit) 0x838336836CB51BEFULL, (u64bit) 0x3333CC3385FF66B6ULL,
+(u64bit) 0x636391633FF2C65CULL, (u64bit) 0x02020802100A0412ULL, (u64bit) 0xAAAA92AA39384993ULL, (u64bit) 0x7171D971AFA8E2DEULL,
+(u64bit) 0xC8C807C80ECF8DC6ULL, (u64bit) 0x19196419C87D32D1ULL, (u64bit) 0x494939497270923BULL, (u64bit) 0xD9D943D9869AAF5FULL,
+(u64bit) 0xF2F2EFF2C31DF931ULL, (u64bit) 0xE3E3ABE34B48DBA8ULL, (u64bit) 0x5B5B715BE22AB6B9ULL, (u64bit) 0x88881A8834920DBCULL,
+(u64bit) 0x9A9A529AA4C8293EULL, (u64bit) 0x262698262DBE4C0BULL, (u64bit) 0x3232C8328DFA64BFULL, (u64bit) 0xB0B0FAB0E94A7D59ULL,
+(u64bit) 0xE9E983E91B6ACFF2ULL, (u64bit) 0x0F0F3C0F78331E77ULL, (u64bit) 0xD5D573D5E6A6B733ULL, (u64bit) 0x80803A8074BA1DF4ULL,
+(u64bit) 0xBEBEC2BE997C6127ULL, (u64bit) 0xCDCD13CD26DE87EBULL, (u64bit) 0x3434D034BDE46889ULL, (u64bit) 0x48483D487A759032ULL,
+(u64bit) 0xFFFFDBFFAB24E354ULL, (u64bit) 0x7A7AF57AF78FF48DULL, (u64bit) 0x90907A90F4EA3D64ULL, (u64bit) 0x5F5F615FC23EBE9DULL,
+(u64bit) 0x202080201DA0403DULL, (u64bit) 0x6868BD6867D5D00FULL, (u64bit) 0x1A1A681AD07234CAULL, (u64bit) 0xAEAE82AE192C41B7ULL,
+(u64bit) 0xB4B4EAB4C95E757DULL, (u64bit) 0x54544D549A19A8CEULL, (u64bit) 0x93937693ECE53B7FULL, (u64bit) 0x222288220DAA442FULL,
+(u64bit) 0x64648D6407E9C863ULL, (u64bit) 0xF1F1E3F1DB12FF2AULL, (u64bit) 0x7373D173BFA2E6CCULL, (u64bit) 0x12124812905A2482ULL,
+(u64bit) 0x40401D403A5D807AULL, (u64bit) 0x0808200840281048ULL, (u64bit) 0xC3C32BC356E89B95ULL, (u64bit) 0xECEC97EC337BC5DFULL,
+(u64bit) 0xDBDB4BDB9690AB4DULL, (u64bit) 0xA1A1BEA1611F5FC0ULL, (u64bit) 0x8D8D0E8D1C830791ULL, (u64bit) 0x3D3DF43DF5C97AC8ULL,
+(u64bit) 0x97976697CCF1335BULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0xCFCF1BCF36D483F9ULL, (u64bit) 0x2B2BAC2B4587566EULL,
+(u64bit) 0x7676C57697B3ECE1ULL, (u64bit) 0x8282328264B019E6ULL, (u64bit) 0xD6D67FD6FEA9B128ULL, (u64bit) 0x1B1B6C1BD87736C3ULL,
+(u64bit) 0xB5B5EEB5C15B7774ULL, (u64bit) 0xAFAF86AF112943BEULL, (u64bit) 0x6A6AB56A77DFD41DULL, (u64bit) 0x50505D50BA0DA0EAULL,
+(u64bit) 0x45450945124C8A57ULL, (u64bit) 0xF3F3EBF3CB18FB38ULL, (u64bit) 0x3030C0309DF060ADULL, (u64bit) 0xEFEF9BEF2B74C3C4ULL,
+(u64bit) 0x3F3FFC3FE5C37EDAULL, (u64bit) 0x55554955921CAAC7ULL, (u64bit) 0xA2A2B2A2791059DBULL, (u64bit) 0xEAEA8FEA0365C9E9ULL,
+(u64bit) 0x656589650FECCA6AULL, (u64bit) 0xBABAD2BAB9686903ULL, (u64bit) 0x2F2FBC2F65935E4AULL, (u64bit) 0xC0C027C04EE79D8EULL,
+(u64bit) 0xDEDE5FDEBE81A160ULL, (u64bit) 0x1C1C701CE06C38FCULL, (u64bit) 0xFDFDD3FDBB2EE746ULL, (u64bit) 0x4D4D294D52649A1FULL,
+(u64bit) 0x92927292E4E03976ULL, (u64bit) 0x7575C9758FBCEAFAULL, (u64bit) 0x06061806301E0C36ULL, (u64bit) 0x8A8A128A249809AEULL,
+(u64bit) 0xB2B2F2B2F940794BULL, (u64bit) 0xE6E6BFE66359D185ULL, (u64bit) 0x0E0E380E70361C7EULL, (u64bit) 0x1F1F7C1FF8633EE7ULL,
+(u64bit) 0x6262956237F7C455ULL, (u64bit) 0xD4D477D4EEA3B53AULL, (u64bit) 0xA8A89AA829324D81ULL, (u64bit) 0x96966296C4F43152ULL,
+(u64bit) 0xF9F9C3F99B3AEF62ULL, (u64bit) 0xC5C533C566F697A3ULL, (u64bit) 0x2525942535B14A10ULL, (u64bit) 0x59597959F220B2ABULL,
+(u64bit) 0x84842A8454AE15D0ULL, (u64bit) 0x7272D572B7A7E4C5ULL, (u64bit) 0x3939E439D5DD72ECULL, (u64bit) 0x4C4C2D4C5A619816ULL,
+(u64bit) 0x5E5E655ECA3BBC94ULL, (u64bit) 0x7878FD78E785F09FULL, (u64bit) 0x3838E038DDD870E5ULL, (u64bit) 0x8C8C0A8C14860598ULL,
+(u64bit) 0xD1D163D1C6B2BF17ULL, (u64bit) 0xA5A5AEA5410B57E4ULL, (u64bit) 0xE2E2AFE2434DD9A1ULL, (u64bit) 0x616199612FF8C24EULL,
+(u64bit) 0xB3B3F6B3F1457B42ULL, (u64bit) 0x2121842115A54234ULL, (u64bit) 0x9C9C4A9C94D62508ULL, (u64bit) 0x1E1E781EF0663CEEULL,
+(u64bit) 0x4343114322528661ULL, (u64bit) 0xC7C73BC776FC93B1ULL, (u64bit) 0xFCFCD7FCB32BE54FULL, (u64bit) 0x0404100420140824ULL,
+(u64bit) 0x51515951B208A2E3ULL, (u64bit) 0x99995E99BCC72F25ULL, (u64bit) 0x6D6DA96D4FC4DA22ULL, (u64bit) 0x0D0D340D68391A65ULL,
+(u64bit) 0xFAFACFFA8335E979ULL, (u64bit) 0xDFDF5BDFB684A369ULL, (u64bit) 0x7E7EE57ED79BFCA9ULL, (u64bit) 0x242490243DB44819ULL,
+(u64bit) 0x3B3BEC3BC5D776FEULL, (u64bit) 0xABAB96AB313D4B9AULL, (u64bit) 0xCECE1FCE3ED181F0ULL, (u64bit) 0x1111441188552299ULL,
+(u64bit) 0x8F8F068F0C890383ULL, (u64bit) 0x4E4E254E4A6B9C04ULL, (u64bit) 0xB7B7E6B7D1517366ULL, (u64bit) 0xEBEB8BEB0B60CBE0ULL,
+(u64bit) 0x3C3CF03CFDCC78C1ULL, (u64bit) 0x81813E817CBF1FFDULL, (u64bit) 0x94946A94D4FE3540ULL, (u64bit) 0xF7F7FBF7EB0CF31CULL,
+(u64bit) 0xB9B9DEB9A1676F18ULL, (u64bit) 0x13134C13985F268BULL, (u64bit) 0x2C2CB02C7D9C5851ULL, (u64bit) 0xD3D36BD3D6B8BB05ULL,
+(u64bit) 0xE7E7BBE76B5CD38CULL, (u64bit) 0x6E6EA56E57CBDC39ULL, (u64bit) 0xC4C437C46EF395AAULL, (u64bit) 0x03030C03180F061BULL,
+(u64bit) 0x565645568A13ACDCULL, (u64bit) 0x44440D441A49885EULL, (u64bit) 0x7F7FE17FDF9EFEA0ULL, (u64bit) 0xA9A99EA921374F88ULL,
+(u64bit) 0x2A2AA82A4D825467ULL, (u64bit) 0xBBBBD6BBB16D6B0AULL, (u64bit) 0xC1C123C146E29F87ULL, (u64bit) 0x53535153A202A6F1ULL,
+(u64bit) 0xDCDC57DCAE8BA572ULL, (u64bit) 0x0B0B2C0B58271653ULL, (u64bit) 0x9D9D4E9D9CD32701ULL, (u64bit) 0x6C6CAD6C47C1D82BULL,
+(u64bit) 0x3131C43195F562A4ULL, (u64bit) 0x7474CD7487B9E8F3ULL, (u64bit) 0xF6F6FFF6E309F115ULL, (u64bit) 0x464605460A438C4CULL,
+(u64bit) 0xACAC8AAC092645A5ULL, (u64bit) 0x89891E893C970FB5ULL, (u64bit) 0x14145014A04428B4ULL, (u64bit) 0xE1E1A3E15B42DFBAULL,
+(u64bit) 0x16165816B04E2CA6ULL, (u64bit) 0x3A3AE83ACDD274F7ULL, (u64bit) 0x6969B9696FD0D206ULL, (u64bit) 0x09092409482D1241ULL,
+(u64bit) 0x7070DD70A7ADE0D7ULL, (u64bit) 0xB6B6E2B6D954716FULL, (u64bit) 0xD0D067D0CEB7BD1EULL, (u64bit) 0xEDED93ED3B7EC7D6ULL,
+(u64bit) 0xCCCC17CC2EDB85E2ULL, (u64bit) 0x424215422A578468ULL, (u64bit) 0x98985A98B4C22D2CULL, (u64bit) 0xA4A4AAA4490E55EDULL,
+(u64bit) 0x2828A0285D885075ULL, (u64bit) 0x5C5C6D5CDA31B886ULL, (u64bit) 0xF8F8C7F8933FED6BULL, (u64bit) 0x8686228644A411C2ULL };
+
+const u64bit Whirlpool::C1[256] = {
+(u64bit) 0xD818186018C07830ULL, (u64bit) 0x2623238C2305AF46ULL, (u64bit) 0xB8C6C63FC67EF991ULL, (u64bit) 0xFBE8E887E8136FCDULL,
+(u64bit) 0xCB878726874CA113ULL, (u64bit) 0x11B8B8DAB8A9626DULL, (u64bit) 0x0901010401080502ULL, (u64bit) 0x0D4F4F214F426E9EULL,
+(u64bit) 0x9B3636D836ADEE6CULL, (u64bit) 0xFFA6A6A2A6590451ULL, (u64bit) 0x0CD2D26FD2DEBDB9ULL, (u64bit) 0x0EF5F5F3F5FB06F7ULL,
+(u64bit) 0x967979F979EF80F2ULL, (u64bit) 0x306F6FA16F5FCEDEULL, (u64bit) 0x6D91917E91FCEF3FULL, (u64bit) 0xF852525552AA07A4ULL,
+(u64bit) 0x4760609D6027FDC0ULL, (u64bit) 0x35BCBCCABC897665ULL, (u64bit) 0x379B9B569BACCD2BULL, (u64bit) 0x8A8E8E028E048C01ULL,
+(u64bit) 0xD2A3A3B6A371155BULL, (u64bit) 0x6C0C0C300C603C18ULL, (u64bit) 0x847B7BF17BFF8AF6ULL, (u64bit) 0x803535D435B5E16AULL,
+(u64bit) 0xF51D1D741DE8693AULL, (u64bit) 0xB3E0E0A7E05347DDULL, (u64bit) 0x21D7D77BD7F6ACB3ULL, (u64bit) 0x9CC2C22FC25EED99ULL,
+(u64bit) 0x432E2EB82E6D965CULL, (u64bit) 0x294B4B314B627A96ULL, (u64bit) 0x5DFEFEDFFEA321E1ULL, (u64bit) 0xD5575741578216AEULL,
+(u64bit) 0xBD15155415A8412AULL, (u64bit) 0xE87777C1779FB6EEULL, (u64bit) 0x923737DC37A5EB6EULL, (u64bit) 0x9EE5E5B3E57B56D7ULL,
+(u64bit) 0x139F9F469F8CD923ULL, (u64bit) 0x23F0F0E7F0D317FDULL, (u64bit) 0x204A4A354A6A7F94ULL, (u64bit) 0x44DADA4FDA9E95A9ULL,
+(u64bit) 0xA258587D58FA25B0ULL, (u64bit) 0xCFC9C903C906CA8FULL, (u64bit) 0x7C2929A429558D52ULL, (u64bit) 0x5A0A0A280A502214ULL,
+(u64bit) 0x50B1B1FEB1E14F7FULL, (u64bit) 0xC9A0A0BAA0691A5DULL, (u64bit) 0x146B6BB16B7FDAD6ULL, (u64bit) 0xD985852E855CAB17ULL,
+(u64bit) 0x3CBDBDCEBD817367ULL, (u64bit) 0x8F5D5D695DD234BAULL, (u64bit) 0x9010104010805020ULL, (u64bit) 0x07F4F4F7F4F303F5ULL,
+(u64bit) 0xDDCBCB0BCB16C08BULL, (u64bit) 0xD33E3EF83EEDC67CULL, (u64bit) 0x2D0505140528110AULL, (u64bit) 0x78676781671FE6CEULL,
+(u64bit) 0x97E4E4B7E47353D5ULL, (u64bit) 0x0227279C2725BB4EULL, (u64bit) 0x7341411941325882ULL, (u64bit) 0xA78B8B168B2C9D0BULL,
+(u64bit) 0xF6A7A7A6A7510153ULL, (u64bit) 0xB27D7DE97DCF94FAULL, (u64bit) 0x4995956E95DCFB37ULL, (u64bit) 0x56D8D847D88E9FADULL,
+(u64bit) 0x70FBFBCBFB8B30EBULL, (u64bit) 0xCDEEEE9FEE2371C1ULL, (u64bit) 0xBB7C7CED7CC791F8ULL, (u64bit) 0x716666856617E3CCULL,
+(u64bit) 0x7BDDDD53DDA68EA7ULL, (u64bit) 0xAF17175C17B84B2EULL, (u64bit) 0x454747014702468EULL, (u64bit) 0x1A9E9E429E84DC21ULL,
+(u64bit) 0xD4CACA0FCA1EC589ULL, (u64bit) 0x582D2DB42D75995AULL, (u64bit) 0x2EBFBFC6BF917963ULL, (u64bit) 0x3F07071C07381B0EULL,
+(u64bit) 0xACADAD8EAD012347ULL, (u64bit) 0xB05A5A755AEA2FB4ULL, (u64bit) 0xEF838336836CB51BULL, (u64bit) 0xB63333CC3385FF66ULL,
+(u64bit) 0x5C636391633FF2C6ULL, (u64bit) 0x1202020802100A04ULL, (u64bit) 0x93AAAA92AA393849ULL, (u64bit) 0xDE7171D971AFA8E2ULL,
+(u64bit) 0xC6C8C807C80ECF8DULL, (u64bit) 0xD119196419C87D32ULL, (u64bit) 0x3B49493949727092ULL, (u64bit) 0x5FD9D943D9869AAFULL,
+(u64bit) 0x31F2F2EFF2C31DF9ULL, (u64bit) 0xA8E3E3ABE34B48DBULL, (u64bit) 0xB95B5B715BE22AB6ULL, (u64bit) 0xBC88881A8834920DULL,
+(u64bit) 0x3E9A9A529AA4C829ULL, (u64bit) 0x0B262698262DBE4CULL, (u64bit) 0xBF3232C8328DFA64ULL, (u64bit) 0x59B0B0FAB0E94A7DULL,
+(u64bit) 0xF2E9E983E91B6ACFULL, (u64bit) 0x770F0F3C0F78331EULL, (u64bit) 0x33D5D573D5E6A6B7ULL, (u64bit) 0xF480803A8074BA1DULL,
+(u64bit) 0x27BEBEC2BE997C61ULL, (u64bit) 0xEBCDCD13CD26DE87ULL, (u64bit) 0x893434D034BDE468ULL, (u64bit) 0x3248483D487A7590ULL,
+(u64bit) 0x54FFFFDBFFAB24E3ULL, (u64bit) 0x8D7A7AF57AF78FF4ULL, (u64bit) 0x6490907A90F4EA3DULL, (u64bit) 0x9D5F5F615FC23EBEULL,
+(u64bit) 0x3D202080201DA040ULL, (u64bit) 0x0F6868BD6867D5D0ULL, (u64bit) 0xCA1A1A681AD07234ULL, (u64bit) 0xB7AEAE82AE192C41ULL,
+(u64bit) 0x7DB4B4EAB4C95E75ULL, (u64bit) 0xCE54544D549A19A8ULL, (u64bit) 0x7F93937693ECE53BULL, (u64bit) 0x2F222288220DAA44ULL,
+(u64bit) 0x6364648D6407E9C8ULL, (u64bit) 0x2AF1F1E3F1DB12FFULL, (u64bit) 0xCC7373D173BFA2E6ULL, (u64bit) 0x8212124812905A24ULL,
+(u64bit) 0x7A40401D403A5D80ULL, (u64bit) 0x4808082008402810ULL, (u64bit) 0x95C3C32BC356E89BULL, (u64bit) 0xDFECEC97EC337BC5ULL,
+(u64bit) 0x4DDBDB4BDB9690ABULL, (u64bit) 0xC0A1A1BEA1611F5FULL, (u64bit) 0x918D8D0E8D1C8307ULL, (u64bit) 0xC83D3DF43DF5C97AULL,
+(u64bit) 0x5B97976697CCF133ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0xF9CFCF1BCF36D483ULL, (u64bit) 0x6E2B2BAC2B458756ULL,
+(u64bit) 0xE17676C57697B3ECULL, (u64bit) 0xE68282328264B019ULL, (u64bit) 0x28D6D67FD6FEA9B1ULL, (u64bit) 0xC31B1B6C1BD87736ULL,
+(u64bit) 0x74B5B5EEB5C15B77ULL, (u64bit) 0xBEAFAF86AF112943ULL, (u64bit) 0x1D6A6AB56A77DFD4ULL, (u64bit) 0xEA50505D50BA0DA0ULL,
+(u64bit) 0x5745450945124C8AULL, (u64bit) 0x38F3F3EBF3CB18FBULL, (u64bit) 0xAD3030C0309DF060ULL, (u64bit) 0xC4EFEF9BEF2B74C3ULL,
+(u64bit) 0xDA3F3FFC3FE5C37EULL, (u64bit) 0xC755554955921CAAULL, (u64bit) 0xDBA2A2B2A2791059ULL, (u64bit) 0xE9EAEA8FEA0365C9ULL,
+(u64bit) 0x6A656589650FECCAULL, (u64bit) 0x03BABAD2BAB96869ULL, (u64bit) 0x4A2F2FBC2F65935EULL, (u64bit) 0x8EC0C027C04EE79DULL,
+(u64bit) 0x60DEDE5FDEBE81A1ULL, (u64bit) 0xFC1C1C701CE06C38ULL, (u64bit) 0x46FDFDD3FDBB2EE7ULL, (u64bit) 0x1F4D4D294D52649AULL,
+(u64bit) 0x7692927292E4E039ULL, (u64bit) 0xFA7575C9758FBCEAULL, (u64bit) 0x3606061806301E0CULL, (u64bit) 0xAE8A8A128A249809ULL,
+(u64bit) 0x4BB2B2F2B2F94079ULL, (u64bit) 0x85E6E6BFE66359D1ULL, (u64bit) 0x7E0E0E380E70361CULL, (u64bit) 0xE71F1F7C1FF8633EULL,
+(u64bit) 0x556262956237F7C4ULL, (u64bit) 0x3AD4D477D4EEA3B5ULL, (u64bit) 0x81A8A89AA829324DULL, (u64bit) 0x5296966296C4F431ULL,
+(u64bit) 0x62F9F9C3F99B3AEFULL, (u64bit) 0xA3C5C533C566F697ULL, (u64bit) 0x102525942535B14AULL, (u64bit) 0xAB59597959F220B2ULL,
+(u64bit) 0xD084842A8454AE15ULL, (u64bit) 0xC57272D572B7A7E4ULL, (u64bit) 0xEC3939E439D5DD72ULL, (u64bit) 0x164C4C2D4C5A6198ULL,
+(u64bit) 0x945E5E655ECA3BBCULL, (u64bit) 0x9F7878FD78E785F0ULL, (u64bit) 0xE53838E038DDD870ULL, (u64bit) 0x988C8C0A8C148605ULL,
+(u64bit) 0x17D1D163D1C6B2BFULL, (u64bit) 0xE4A5A5AEA5410B57ULL, (u64bit) 0xA1E2E2AFE2434DD9ULL, (u64bit) 0x4E616199612FF8C2ULL,
+(u64bit) 0x42B3B3F6B3F1457BULL, (u64bit) 0x342121842115A542ULL, (u64bit) 0x089C9C4A9C94D625ULL, (u64bit) 0xEE1E1E781EF0663CULL,
+(u64bit) 0x6143431143225286ULL, (u64bit) 0xB1C7C73BC776FC93ULL, (u64bit) 0x4FFCFCD7FCB32BE5ULL, (u64bit) 0x2404041004201408ULL,
+(u64bit) 0xE351515951B208A2ULL, (u64bit) 0x2599995E99BCC72FULL, (u64bit) 0x226D6DA96D4FC4DAULL, (u64bit) 0x650D0D340D68391AULL,
+(u64bit) 0x79FAFACFFA8335E9ULL, (u64bit) 0x69DFDF5BDFB684A3ULL, (u64bit) 0xA97E7EE57ED79BFCULL, (u64bit) 0x19242490243DB448ULL,
+(u64bit) 0xFE3B3BEC3BC5D776ULL, (u64bit) 0x9AABAB96AB313D4BULL, (u64bit) 0xF0CECE1FCE3ED181ULL, (u64bit) 0x9911114411885522ULL,
+(u64bit) 0x838F8F068F0C8903ULL, (u64bit) 0x044E4E254E4A6B9CULL, (u64bit) 0x66B7B7E6B7D15173ULL, (u64bit) 0xE0EBEB8BEB0B60CBULL,
+(u64bit) 0xC13C3CF03CFDCC78ULL, (u64bit) 0xFD81813E817CBF1FULL, (u64bit) 0x4094946A94D4FE35ULL, (u64bit) 0x1CF7F7FBF7EB0CF3ULL,
+(u64bit) 0x18B9B9DEB9A1676FULL, (u64bit) 0x8B13134C13985F26ULL, (u64bit) 0x512C2CB02C7D9C58ULL, (u64bit) 0x05D3D36BD3D6B8BBULL,
+(u64bit) 0x8CE7E7BBE76B5CD3ULL, (u64bit) 0x396E6EA56E57CBDCULL, (u64bit) 0xAAC4C437C46EF395ULL, (u64bit) 0x1B03030C03180F06ULL,
+(u64bit) 0xDC565645568A13ACULL, (u64bit) 0x5E44440D441A4988ULL, (u64bit) 0xA07F7FE17FDF9EFEULL, (u64bit) 0x88A9A99EA921374FULL,
+(u64bit) 0x672A2AA82A4D8254ULL, (u64bit) 0x0ABBBBD6BBB16D6BULL, (u64bit) 0x87C1C123C146E29FULL, (u64bit) 0xF153535153A202A6ULL,
+(u64bit) 0x72DCDC57DCAE8BA5ULL, (u64bit) 0x530B0B2C0B582716ULL, (u64bit) 0x019D9D4E9D9CD327ULL, (u64bit) 0x2B6C6CAD6C47C1D8ULL,
+(u64bit) 0xA43131C43195F562ULL, (u64bit) 0xF37474CD7487B9E8ULL, (u64bit) 0x15F6F6FFF6E309F1ULL, (u64bit) 0x4C464605460A438CULL,
+(u64bit) 0xA5ACAC8AAC092645ULL, (u64bit) 0xB589891E893C970FULL, (u64bit) 0xB414145014A04428ULL, (u64bit) 0xBAE1E1A3E15B42DFULL,
+(u64bit) 0xA616165816B04E2CULL, (u64bit) 0xF73A3AE83ACDD274ULL, (u64bit) 0x066969B9696FD0D2ULL, (u64bit) 0x4109092409482D12ULL,
+(u64bit) 0xD77070DD70A7ADE0ULL, (u64bit) 0x6FB6B6E2B6D95471ULL, (u64bit) 0x1ED0D067D0CEB7BDULL, (u64bit) 0xD6EDED93ED3B7EC7ULL,
+(u64bit) 0xE2CCCC17CC2EDB85ULL, (u64bit) 0x68424215422A5784ULL, (u64bit) 0x2C98985A98B4C22DULL, (u64bit) 0xEDA4A4AAA4490E55ULL,
+(u64bit) 0x752828A0285D8850ULL, (u64bit) 0x865C5C6D5CDA31B8ULL, (u64bit) 0x6BF8F8C7F8933FEDULL, (u64bit) 0xC28686228644A411ULL };
+
+const u64bit Whirlpool::C2[256] = {
+(u64bit) 0x30D818186018C078ULL, (u64bit) 0x462623238C2305AFULL, (u64bit) 0x91B8C6C63FC67EF9ULL, (u64bit) 0xCDFBE8E887E8136FULL,
+(u64bit) 0x13CB878726874CA1ULL, (u64bit) 0x6D11B8B8DAB8A962ULL, (u64bit) 0x0209010104010805ULL, (u64bit) 0x9E0D4F4F214F426EULL,
+(u64bit) 0x6C9B3636D836ADEEULL, (u64bit) 0x51FFA6A6A2A65904ULL, (u64bit) 0xB90CD2D26FD2DEBDULL, (u64bit) 0xF70EF5F5F3F5FB06ULL,
+(u64bit) 0xF2967979F979EF80ULL, (u64bit) 0xDE306F6FA16F5FCEULL, (u64bit) 0x3F6D91917E91FCEFULL, (u64bit) 0xA4F852525552AA07ULL,
+(u64bit) 0xC04760609D6027FDULL, (u64bit) 0x6535BCBCCABC8976ULL, (u64bit) 0x2B379B9B569BACCDULL, (u64bit) 0x018A8E8E028E048CULL,
+(u64bit) 0x5BD2A3A3B6A37115ULL, (u64bit) 0x186C0C0C300C603CULL, (u64bit) 0xF6847B7BF17BFF8AULL, (u64bit) 0x6A803535D435B5E1ULL,
+(u64bit) 0x3AF51D1D741DE869ULL, (u64bit) 0xDDB3E0E0A7E05347ULL, (u64bit) 0xB321D7D77BD7F6ACULL, (u64bit) 0x999CC2C22FC25EEDULL,
+(u64bit) 0x5C432E2EB82E6D96ULL, (u64bit) 0x96294B4B314B627AULL, (u64bit) 0xE15DFEFEDFFEA321ULL, (u64bit) 0xAED5575741578216ULL,
+(u64bit) 0x2ABD15155415A841ULL, (u64bit) 0xEEE87777C1779FB6ULL, (u64bit) 0x6E923737DC37A5EBULL, (u64bit) 0xD79EE5E5B3E57B56ULL,
+(u64bit) 0x23139F9F469F8CD9ULL, (u64bit) 0xFD23F0F0E7F0D317ULL, (u64bit) 0x94204A4A354A6A7FULL, (u64bit) 0xA944DADA4FDA9E95ULL,
+(u64bit) 0xB0A258587D58FA25ULL, (u64bit) 0x8FCFC9C903C906CAULL, (u64bit) 0x527C2929A429558DULL, (u64bit) 0x145A0A0A280A5022ULL,
+(u64bit) 0x7F50B1B1FEB1E14FULL, (u64bit) 0x5DC9A0A0BAA0691AULL, (u64bit) 0xD6146B6BB16B7FDAULL, (u64bit) 0x17D985852E855CABULL,
+(u64bit) 0x673CBDBDCEBD8173ULL, (u64bit) 0xBA8F5D5D695DD234ULL, (u64bit) 0x2090101040108050ULL, (u64bit) 0xF507F4F4F7F4F303ULL,
+(u64bit) 0x8BDDCBCB0BCB16C0ULL, (u64bit) 0x7CD33E3EF83EEDC6ULL, (u64bit) 0x0A2D050514052811ULL, (u64bit) 0xCE78676781671FE6ULL,
+(u64bit) 0xD597E4E4B7E47353ULL, (u64bit) 0x4E0227279C2725BBULL, (u64bit) 0x8273414119413258ULL, (u64bit) 0x0BA78B8B168B2C9DULL,
+(u64bit) 0x53F6A7A7A6A75101ULL, (u64bit) 0xFAB27D7DE97DCF94ULL, (u64bit) 0x374995956E95DCFBULL, (u64bit) 0xAD56D8D847D88E9FULL,
+(u64bit) 0xEB70FBFBCBFB8B30ULL, (u64bit) 0xC1CDEEEE9FEE2371ULL, (u64bit) 0xF8BB7C7CED7CC791ULL, (u64bit) 0xCC716666856617E3ULL,
+(u64bit) 0xA77BDDDD53DDA68EULL, (u64bit) 0x2EAF17175C17B84BULL, (u64bit) 0x8E45474701470246ULL, (u64bit) 0x211A9E9E429E84DCULL,
+(u64bit) 0x89D4CACA0FCA1EC5ULL, (u64bit) 0x5A582D2DB42D7599ULL, (u64bit) 0x632EBFBFC6BF9179ULL, (u64bit) 0x0E3F07071C07381BULL,
+(u64bit) 0x47ACADAD8EAD0123ULL, (u64bit) 0xB4B05A5A755AEA2FULL, (u64bit) 0x1BEF838336836CB5ULL, (u64bit) 0x66B63333CC3385FFULL,
+(u64bit) 0xC65C636391633FF2ULL, (u64bit) 0x041202020802100AULL, (u64bit) 0x4993AAAA92AA3938ULL, (u64bit) 0xE2DE7171D971AFA8ULL,
+(u64bit) 0x8DC6C8C807C80ECFULL, (u64bit) 0x32D119196419C87DULL, (u64bit) 0x923B494939497270ULL, (u64bit) 0xAF5FD9D943D9869AULL,
+(u64bit) 0xF931F2F2EFF2C31DULL, (u64bit) 0xDBA8E3E3ABE34B48ULL, (u64bit) 0xB6B95B5B715BE22AULL, (u64bit) 0x0DBC88881A883492ULL,
+(u64bit) 0x293E9A9A529AA4C8ULL, (u64bit) 0x4C0B262698262DBEULL, (u64bit) 0x64BF3232C8328DFAULL, (u64bit) 0x7D59B0B0FAB0E94AULL,
+(u64bit) 0xCFF2E9E983E91B6AULL, (u64bit) 0x1E770F0F3C0F7833ULL, (u64bit) 0xB733D5D573D5E6A6ULL, (u64bit) 0x1DF480803A8074BAULL,
+(u64bit) 0x6127BEBEC2BE997CULL, (u64bit) 0x87EBCDCD13CD26DEULL, (u64bit) 0x68893434D034BDE4ULL, (u64bit) 0x903248483D487A75ULL,
+(u64bit) 0xE354FFFFDBFFAB24ULL, (u64bit) 0xF48D7A7AF57AF78FULL, (u64bit) 0x3D6490907A90F4EAULL, (u64bit) 0xBE9D5F5F615FC23EULL,
+(u64bit) 0x403D202080201DA0ULL, (u64bit) 0xD00F6868BD6867D5ULL, (u64bit) 0x34CA1A1A681AD072ULL, (u64bit) 0x41B7AEAE82AE192CULL,
+(u64bit) 0x757DB4B4EAB4C95EULL, (u64bit) 0xA8CE54544D549A19ULL, (u64bit) 0x3B7F93937693ECE5ULL, (u64bit) 0x442F222288220DAAULL,
+(u64bit) 0xC86364648D6407E9ULL, (u64bit) 0xFF2AF1F1E3F1DB12ULL, (u64bit) 0xE6CC7373D173BFA2ULL, (u64bit) 0x248212124812905AULL,
+(u64bit) 0x807A40401D403A5DULL, (u64bit) 0x1048080820084028ULL, (u64bit) 0x9B95C3C32BC356E8ULL, (u64bit) 0xC5DFECEC97EC337BULL,
+(u64bit) 0xAB4DDBDB4BDB9690ULL, (u64bit) 0x5FC0A1A1BEA1611FULL, (u64bit) 0x07918D8D0E8D1C83ULL, (u64bit) 0x7AC83D3DF43DF5C9ULL,
+(u64bit) 0x335B97976697CCF1ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0x83F9CFCF1BCF36D4ULL, (u64bit) 0x566E2B2BAC2B4587ULL,
+(u64bit) 0xECE17676C57697B3ULL, (u64bit) 0x19E68282328264B0ULL, (u64bit) 0xB128D6D67FD6FEA9ULL, (u64bit) 0x36C31B1B6C1BD877ULL,
+(u64bit) 0x7774B5B5EEB5C15BULL, (u64bit) 0x43BEAFAF86AF1129ULL, (u64bit) 0xD41D6A6AB56A77DFULL, (u64bit) 0xA0EA50505D50BA0DULL,
+(u64bit) 0x8A5745450945124CULL, (u64bit) 0xFB38F3F3EBF3CB18ULL, (u64bit) 0x60AD3030C0309DF0ULL, (u64bit) 0xC3C4EFEF9BEF2B74ULL,
+(u64bit) 0x7EDA3F3FFC3FE5C3ULL, (u64bit) 0xAAC755554955921CULL, (u64bit) 0x59DBA2A2B2A27910ULL, (u64bit) 0xC9E9EAEA8FEA0365ULL,
+(u64bit) 0xCA6A656589650FECULL, (u64bit) 0x6903BABAD2BAB968ULL, (u64bit) 0x5E4A2F2FBC2F6593ULL, (u64bit) 0x9D8EC0C027C04EE7ULL,
+(u64bit) 0xA160DEDE5FDEBE81ULL, (u64bit) 0x38FC1C1C701CE06CULL, (u64bit) 0xE746FDFDD3FDBB2EULL, (u64bit) 0x9A1F4D4D294D5264ULL,
+(u64bit) 0x397692927292E4E0ULL, (u64bit) 0xEAFA7575C9758FBCULL, (u64bit) 0x0C3606061806301EULL, (u64bit) 0x09AE8A8A128A2498ULL,
+(u64bit) 0x794BB2B2F2B2F940ULL, (u64bit) 0xD185E6E6BFE66359ULL, (u64bit) 0x1C7E0E0E380E7036ULL, (u64bit) 0x3EE71F1F7C1FF863ULL,
+(u64bit) 0xC4556262956237F7ULL, (u64bit) 0xB53AD4D477D4EEA3ULL, (u64bit) 0x4D81A8A89AA82932ULL, (u64bit) 0x315296966296C4F4ULL,
+(u64bit) 0xEF62F9F9C3F99B3AULL, (u64bit) 0x97A3C5C533C566F6ULL, (u64bit) 0x4A102525942535B1ULL, (u64bit) 0xB2AB59597959F220ULL,
+(u64bit) 0x15D084842A8454AEULL, (u64bit) 0xE4C57272D572B7A7ULL, (u64bit) 0x72EC3939E439D5DDULL, (u64bit) 0x98164C4C2D4C5A61ULL,
+(u64bit) 0xBC945E5E655ECA3BULL, (u64bit) 0xF09F7878FD78E785ULL, (u64bit) 0x70E53838E038DDD8ULL, (u64bit) 0x05988C8C0A8C1486ULL,
+(u64bit) 0xBF17D1D163D1C6B2ULL, (u64bit) 0x57E4A5A5AEA5410BULL, (u64bit) 0xD9A1E2E2AFE2434DULL, (u64bit) 0xC24E616199612FF8ULL,
+(u64bit) 0x7B42B3B3F6B3F145ULL, (u64bit) 0x42342121842115A5ULL, (u64bit) 0x25089C9C4A9C94D6ULL, (u64bit) 0x3CEE1E1E781EF066ULL,
+(u64bit) 0x8661434311432252ULL, (u64bit) 0x93B1C7C73BC776FCULL, (u64bit) 0xE54FFCFCD7FCB32BULL, (u64bit) 0x0824040410042014ULL,
+(u64bit) 0xA2E351515951B208ULL, (u64bit) 0x2F2599995E99BCC7ULL, (u64bit) 0xDA226D6DA96D4FC4ULL, (u64bit) 0x1A650D0D340D6839ULL,
+(u64bit) 0xE979FAFACFFA8335ULL, (u64bit) 0xA369DFDF5BDFB684ULL, (u64bit) 0xFCA97E7EE57ED79BULL, (u64bit) 0x4819242490243DB4ULL,
+(u64bit) 0x76FE3B3BEC3BC5D7ULL, (u64bit) 0x4B9AABAB96AB313DULL, (u64bit) 0x81F0CECE1FCE3ED1ULL, (u64bit) 0x2299111144118855ULL,
+(u64bit) 0x03838F8F068F0C89ULL, (u64bit) 0x9C044E4E254E4A6BULL, (u64bit) 0x7366B7B7E6B7D151ULL, (u64bit) 0xCBE0EBEB8BEB0B60ULL,
+(u64bit) 0x78C13C3CF03CFDCCULL, (u64bit) 0x1FFD81813E817CBFULL, (u64bit) 0x354094946A94D4FEULL, (u64bit) 0xF31CF7F7FBF7EB0CULL,
+(u64bit) 0x6F18B9B9DEB9A167ULL, (u64bit) 0x268B13134C13985FULL, (u64bit) 0x58512C2CB02C7D9CULL, (u64bit) 0xBB05D3D36BD3D6B8ULL,
+(u64bit) 0xD38CE7E7BBE76B5CULL, (u64bit) 0xDC396E6EA56E57CBULL, (u64bit) 0x95AAC4C437C46EF3ULL, (u64bit) 0x061B03030C03180FULL,
+(u64bit) 0xACDC565645568A13ULL, (u64bit) 0x885E44440D441A49ULL, (u64bit) 0xFEA07F7FE17FDF9EULL, (u64bit) 0x4F88A9A99EA92137ULL,
+(u64bit) 0x54672A2AA82A4D82ULL, (u64bit) 0x6B0ABBBBD6BBB16DULL, (u64bit) 0x9F87C1C123C146E2ULL, (u64bit) 0xA6F153535153A202ULL,
+(u64bit) 0xA572DCDC57DCAE8BULL, (u64bit) 0x16530B0B2C0B5827ULL, (u64bit) 0x27019D9D4E9D9CD3ULL, (u64bit) 0xD82B6C6CAD6C47C1ULL,
+(u64bit) 0x62A43131C43195F5ULL, (u64bit) 0xE8F37474CD7487B9ULL, (u64bit) 0xF115F6F6FFF6E309ULL, (u64bit) 0x8C4C464605460A43ULL,
+(u64bit) 0x45A5ACAC8AAC0926ULL, (u64bit) 0x0FB589891E893C97ULL, (u64bit) 0x28B414145014A044ULL, (u64bit) 0xDFBAE1E1A3E15B42ULL,
+(u64bit) 0x2CA616165816B04EULL, (u64bit) 0x74F73A3AE83ACDD2ULL, (u64bit) 0xD2066969B9696FD0ULL, (u64bit) 0x124109092409482DULL,
+(u64bit) 0xE0D77070DD70A7ADULL, (u64bit) 0x716FB6B6E2B6D954ULL, (u64bit) 0xBD1ED0D067D0CEB7ULL, (u64bit) 0xC7D6EDED93ED3B7EULL,
+(u64bit) 0x85E2CCCC17CC2EDBULL, (u64bit) 0x8468424215422A57ULL, (u64bit) 0x2D2C98985A98B4C2ULL, (u64bit) 0x55EDA4A4AAA4490EULL,
+(u64bit) 0x50752828A0285D88ULL, (u64bit) 0xB8865C5C6D5CDA31ULL, (u64bit) 0xED6BF8F8C7F8933FULL, (u64bit) 0x11C28686228644A4ULL };
+
+const u64bit Whirlpool::C3[256] = {
+(u64bit) 0x7830D818186018C0ULL, (u64bit) 0xAF462623238C2305ULL, (u64bit) 0xF991B8C6C63FC67EULL, (u64bit) 0x6FCDFBE8E887E813ULL,
+(u64bit) 0xA113CB878726874CULL, (u64bit) 0x626D11B8B8DAB8A9ULL, (u64bit) 0x0502090101040108ULL, (u64bit) 0x6E9E0D4F4F214F42ULL,
+(u64bit) 0xEE6C9B3636D836ADULL, (u64bit) 0x0451FFA6A6A2A659ULL, (u64bit) 0xBDB90CD2D26FD2DEULL, (u64bit) 0x06F70EF5F5F3F5FBULL,
+(u64bit) 0x80F2967979F979EFULL, (u64bit) 0xCEDE306F6FA16F5FULL, (u64bit) 0xEF3F6D91917E91FCULL, (u64bit) 0x07A4F852525552AAULL,
+(u64bit) 0xFDC04760609D6027ULL, (u64bit) 0x766535BCBCCABC89ULL, (u64bit) 0xCD2B379B9B569BACULL, (u64bit) 0x8C018A8E8E028E04ULL,
+(u64bit) 0x155BD2A3A3B6A371ULL, (u64bit) 0x3C186C0C0C300C60ULL, (u64bit) 0x8AF6847B7BF17BFFULL, (u64bit) 0xE16A803535D435B5ULL,
+(u64bit) 0x693AF51D1D741DE8ULL, (u64bit) 0x47DDB3E0E0A7E053ULL, (u64bit) 0xACB321D7D77BD7F6ULL, (u64bit) 0xED999CC2C22FC25EULL,
+(u64bit) 0x965C432E2EB82E6DULL, (u64bit) 0x7A96294B4B314B62ULL, (u64bit) 0x21E15DFEFEDFFEA3ULL, (u64bit) 0x16AED55757415782ULL,
+(u64bit) 0x412ABD15155415A8ULL, (u64bit) 0xB6EEE87777C1779FULL, (u64bit) 0xEB6E923737DC37A5ULL, (u64bit) 0x56D79EE5E5B3E57BULL,
+(u64bit) 0xD923139F9F469F8CULL, (u64bit) 0x17FD23F0F0E7F0D3ULL, (u64bit) 0x7F94204A4A354A6AULL, (u64bit) 0x95A944DADA4FDA9EULL,
+(u64bit) 0x25B0A258587D58FAULL, (u64bit) 0xCA8FCFC9C903C906ULL, (u64bit) 0x8D527C2929A42955ULL, (u64bit) 0x22145A0A0A280A50ULL,
+(u64bit) 0x4F7F50B1B1FEB1E1ULL, (u64bit) 0x1A5DC9A0A0BAA069ULL, (u64bit) 0xDAD6146B6BB16B7FULL, (u64bit) 0xAB17D985852E855CULL,
+(u64bit) 0x73673CBDBDCEBD81ULL, (u64bit) 0x34BA8F5D5D695DD2ULL, (u64bit) 0x5020901010401080ULL, (u64bit) 0x03F507F4F4F7F4F3ULL,
+(u64bit) 0xC08BDDCBCB0BCB16ULL, (u64bit) 0xC67CD33E3EF83EEDULL, (u64bit) 0x110A2D0505140528ULL, (u64bit) 0xE6CE78676781671FULL,
+(u64bit) 0x53D597E4E4B7E473ULL, (u64bit) 0xBB4E0227279C2725ULL, (u64bit) 0x5882734141194132ULL, (u64bit) 0x9D0BA78B8B168B2CULL,
+(u64bit) 0x0153F6A7A7A6A751ULL, (u64bit) 0x94FAB27D7DE97DCFULL, (u64bit) 0xFB374995956E95DCULL, (u64bit) 0x9FAD56D8D847D88EULL,
+(u64bit) 0x30EB70FBFBCBFB8BULL, (u64bit) 0x71C1CDEEEE9FEE23ULL, (u64bit) 0x91F8BB7C7CED7CC7ULL, (u64bit) 0xE3CC716666856617ULL,
+(u64bit) 0x8EA77BDDDD53DDA6ULL, (u64bit) 0x4B2EAF17175C17B8ULL, (u64bit) 0x468E454747014702ULL, (u64bit) 0xDC211A9E9E429E84ULL,
+(u64bit) 0xC589D4CACA0FCA1EULL, (u64bit) 0x995A582D2DB42D75ULL, (u64bit) 0x79632EBFBFC6BF91ULL, (u64bit) 0x1B0E3F07071C0738ULL,
+(u64bit) 0x2347ACADAD8EAD01ULL, (u64bit) 0x2FB4B05A5A755AEAULL, (u64bit) 0xB51BEF838336836CULL, (u64bit) 0xFF66B63333CC3385ULL,
+(u64bit) 0xF2C65C636391633FULL, (u64bit) 0x0A04120202080210ULL, (u64bit) 0x384993AAAA92AA39ULL, (u64bit) 0xA8E2DE7171D971AFULL,
+(u64bit) 0xCF8DC6C8C807C80EULL, (u64bit) 0x7D32D119196419C8ULL, (u64bit) 0x70923B4949394972ULL, (u64bit) 0x9AAF5FD9D943D986ULL,
+(u64bit) 0x1DF931F2F2EFF2C3ULL, (u64bit) 0x48DBA8E3E3ABE34BULL, (u64bit) 0x2AB6B95B5B715BE2ULL, (u64bit) 0x920DBC88881A8834ULL,
+(u64bit) 0xC8293E9A9A529AA4ULL, (u64bit) 0xBE4C0B262698262DULL, (u64bit) 0xFA64BF3232C8328DULL, (u64bit) 0x4A7D59B0B0FAB0E9ULL,
+(u64bit) 0x6ACFF2E9E983E91BULL, (u64bit) 0x331E770F0F3C0F78ULL, (u64bit) 0xA6B733D5D573D5E6ULL, (u64bit) 0xBA1DF480803A8074ULL,
+(u64bit) 0x7C6127BEBEC2BE99ULL, (u64bit) 0xDE87EBCDCD13CD26ULL, (u64bit) 0xE468893434D034BDULL, (u64bit) 0x75903248483D487AULL,
+(u64bit) 0x24E354FFFFDBFFABULL, (u64bit) 0x8FF48D7A7AF57AF7ULL, (u64bit) 0xEA3D6490907A90F4ULL, (u64bit) 0x3EBE9D5F5F615FC2ULL,
+(u64bit) 0xA0403D202080201DULL, (u64bit) 0xD5D00F6868BD6867ULL, (u64bit) 0x7234CA1A1A681AD0ULL, (u64bit) 0x2C41B7AEAE82AE19ULL,
+(u64bit) 0x5E757DB4B4EAB4C9ULL, (u64bit) 0x19A8CE54544D549AULL, (u64bit) 0xE53B7F93937693ECULL, (u64bit) 0xAA442F222288220DULL,
+(u64bit) 0xE9C86364648D6407ULL, (u64bit) 0x12FF2AF1F1E3F1DBULL, (u64bit) 0xA2E6CC7373D173BFULL, (u64bit) 0x5A24821212481290ULL,
+(u64bit) 0x5D807A40401D403AULL, (u64bit) 0x2810480808200840ULL, (u64bit) 0xE89B95C3C32BC356ULL, (u64bit) 0x7BC5DFECEC97EC33ULL,
+(u64bit) 0x90AB4DDBDB4BDB96ULL, (u64bit) 0x1F5FC0A1A1BEA161ULL, (u64bit) 0x8307918D8D0E8D1CULL, (u64bit) 0xC97AC83D3DF43DF5ULL,
+(u64bit) 0xF1335B97976697CCULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0xD483F9CFCF1BCF36ULL, (u64bit) 0x87566E2B2BAC2B45ULL,
+(u64bit) 0xB3ECE17676C57697ULL, (u64bit) 0xB019E68282328264ULL, (u64bit) 0xA9B128D6D67FD6FEULL, (u64bit) 0x7736C31B1B6C1BD8ULL,
+(u64bit) 0x5B7774B5B5EEB5C1ULL, (u64bit) 0x2943BEAFAF86AF11ULL, (u64bit) 0xDFD41D6A6AB56A77ULL, (u64bit) 0x0DA0EA50505D50BAULL,
+(u64bit) 0x4C8A574545094512ULL, (u64bit) 0x18FB38F3F3EBF3CBULL, (u64bit) 0xF060AD3030C0309DULL, (u64bit) 0x74C3C4EFEF9BEF2BULL,
+(u64bit) 0xC37EDA3F3FFC3FE5ULL, (u64bit) 0x1CAAC75555495592ULL, (u64bit) 0x1059DBA2A2B2A279ULL, (u64bit) 0x65C9E9EAEA8FEA03ULL,
+(u64bit) 0xECCA6A656589650FULL, (u64bit) 0x686903BABAD2BAB9ULL, (u64bit) 0x935E4A2F2FBC2F65ULL, (u64bit) 0xE79D8EC0C027C04EULL,
+(u64bit) 0x81A160DEDE5FDEBEULL, (u64bit) 0x6C38FC1C1C701CE0ULL, (u64bit) 0x2EE746FDFDD3FDBBULL, (u64bit) 0x649A1F4D4D294D52ULL,
+(u64bit) 0xE0397692927292E4ULL, (u64bit) 0xBCEAFA7575C9758FULL, (u64bit) 0x1E0C360606180630ULL, (u64bit) 0x9809AE8A8A128A24ULL,
+(u64bit) 0x40794BB2B2F2B2F9ULL, (u64bit) 0x59D185E6E6BFE663ULL, (u64bit) 0x361C7E0E0E380E70ULL, (u64bit) 0x633EE71F1F7C1FF8ULL,
+(u64bit) 0xF7C4556262956237ULL, (u64bit) 0xA3B53AD4D477D4EEULL, (u64bit) 0x324D81A8A89AA829ULL, (u64bit) 0xF4315296966296C4ULL,
+(u64bit) 0x3AEF62F9F9C3F99BULL, (u64bit) 0xF697A3C5C533C566ULL, (u64bit) 0xB14A102525942535ULL, (u64bit) 0x20B2AB59597959F2ULL,
+(u64bit) 0xAE15D084842A8454ULL, (u64bit) 0xA7E4C57272D572B7ULL, (u64bit) 0xDD72EC3939E439D5ULL, (u64bit) 0x6198164C4C2D4C5AULL,
+(u64bit) 0x3BBC945E5E655ECAULL, (u64bit) 0x85F09F7878FD78E7ULL, (u64bit) 0xD870E53838E038DDULL, (u64bit) 0x8605988C8C0A8C14ULL,
+(u64bit) 0xB2BF17D1D163D1C6ULL, (u64bit) 0x0B57E4A5A5AEA541ULL, (u64bit) 0x4DD9A1E2E2AFE243ULL, (u64bit) 0xF8C24E616199612FULL,
+(u64bit) 0x457B42B3B3F6B3F1ULL, (u64bit) 0xA542342121842115ULL, (u64bit) 0xD625089C9C4A9C94ULL, (u64bit) 0x663CEE1E1E781EF0ULL,
+(u64bit) 0x5286614343114322ULL, (u64bit) 0xFC93B1C7C73BC776ULL, (u64bit) 0x2BE54FFCFCD7FCB3ULL, (u64bit) 0x1408240404100420ULL,
+(u64bit) 0x08A2E351515951B2ULL, (u64bit) 0xC72F2599995E99BCULL, (u64bit) 0xC4DA226D6DA96D4FULL, (u64bit) 0x391A650D0D340D68ULL,
+(u64bit) 0x35E979FAFACFFA83ULL, (u64bit) 0x84A369DFDF5BDFB6ULL, (u64bit) 0x9BFCA97E7EE57ED7ULL, (u64bit) 0xB44819242490243DULL,
+(u64bit) 0xD776FE3B3BEC3BC5ULL, (u64bit) 0x3D4B9AABAB96AB31ULL, (u64bit) 0xD181F0CECE1FCE3EULL, (u64bit) 0x5522991111441188ULL,
+(u64bit) 0x8903838F8F068F0CULL, (u64bit) 0x6B9C044E4E254E4AULL, (u64bit) 0x517366B7B7E6B7D1ULL, (u64bit) 0x60CBE0EBEB8BEB0BULL,
+(u64bit) 0xCC78C13C3CF03CFDULL, (u64bit) 0xBF1FFD81813E817CULL, (u64bit) 0xFE354094946A94D4ULL, (u64bit) 0x0CF31CF7F7FBF7EBULL,
+(u64bit) 0x676F18B9B9DEB9A1ULL, (u64bit) 0x5F268B13134C1398ULL, (u64bit) 0x9C58512C2CB02C7DULL, (u64bit) 0xB8BB05D3D36BD3D6ULL,
+(u64bit) 0x5CD38CE7E7BBE76BULL, (u64bit) 0xCBDC396E6EA56E57ULL, (u64bit) 0xF395AAC4C437C46EULL, (u64bit) 0x0F061B03030C0318ULL,
+(u64bit) 0x13ACDC565645568AULL, (u64bit) 0x49885E44440D441AULL, (u64bit) 0x9EFEA07F7FE17FDFULL, (u64bit) 0x374F88A9A99EA921ULL,
+(u64bit) 0x8254672A2AA82A4DULL, (u64bit) 0x6D6B0ABBBBD6BBB1ULL, (u64bit) 0xE29F87C1C123C146ULL, (u64bit) 0x02A6F153535153A2ULL,
+(u64bit) 0x8BA572DCDC57DCAEULL, (u64bit) 0x2716530B0B2C0B58ULL, (u64bit) 0xD327019D9D4E9D9CULL, (u64bit) 0xC1D82B6C6CAD6C47ULL,
+(u64bit) 0xF562A43131C43195ULL, (u64bit) 0xB9E8F37474CD7487ULL, (u64bit) 0x09F115F6F6FFF6E3ULL, (u64bit) 0x438C4C464605460AULL,
+(u64bit) 0x2645A5ACAC8AAC09ULL, (u64bit) 0x970FB589891E893CULL, (u64bit) 0x4428B414145014A0ULL, (u64bit) 0x42DFBAE1E1A3E15BULL,
+(u64bit) 0x4E2CA616165816B0ULL, (u64bit) 0xD274F73A3AE83ACDULL, (u64bit) 0xD0D2066969B9696FULL, (u64bit) 0x2D12410909240948ULL,
+(u64bit) 0xADE0D77070DD70A7ULL, (u64bit) 0x54716FB6B6E2B6D9ULL, (u64bit) 0xB7BD1ED0D067D0CEULL, (u64bit) 0x7EC7D6EDED93ED3BULL,
+(u64bit) 0xDB85E2CCCC17CC2EULL, (u64bit) 0x578468424215422AULL, (u64bit) 0xC22D2C98985A98B4ULL, (u64bit) 0x0E55EDA4A4AAA449ULL,
+(u64bit) 0x8850752828A0285DULL, (u64bit) 0x31B8865C5C6D5CDAULL, (u64bit) 0x3FED6BF8F8C7F893ULL, (u64bit) 0xA411C28686228644ULL };
+
+const u64bit Whirlpool::C4[256] = {
+(u64bit) 0xC07830D818186018ULL, (u64bit) 0x05AF462623238C23ULL, (u64bit) 0x7EF991B8C6C63FC6ULL, (u64bit) 0x136FCDFBE8E887E8ULL,
+(u64bit) 0x4CA113CB87872687ULL, (u64bit) 0xA9626D11B8B8DAB8ULL, (u64bit) 0x0805020901010401ULL, (u64bit) 0x426E9E0D4F4F214FULL,
+(u64bit) 0xADEE6C9B3636D836ULL, (u64bit) 0x590451FFA6A6A2A6ULL, (u64bit) 0xDEBDB90CD2D26FD2ULL, (u64bit) 0xFB06F70EF5F5F3F5ULL,
+(u64bit) 0xEF80F2967979F979ULL, (u64bit) 0x5FCEDE306F6FA16FULL, (u64bit) 0xFCEF3F6D91917E91ULL, (u64bit) 0xAA07A4F852525552ULL,
+(u64bit) 0x27FDC04760609D60ULL, (u64bit) 0x89766535BCBCCABCULL, (u64bit) 0xACCD2B379B9B569BULL, (u64bit) 0x048C018A8E8E028EULL,
+(u64bit) 0x71155BD2A3A3B6A3ULL, (u64bit) 0x603C186C0C0C300CULL, (u64bit) 0xFF8AF6847B7BF17BULL, (u64bit) 0xB5E16A803535D435ULL,
+(u64bit) 0xE8693AF51D1D741DULL, (u64bit) 0x5347DDB3E0E0A7E0ULL, (u64bit) 0xF6ACB321D7D77BD7ULL, (u64bit) 0x5EED999CC2C22FC2ULL,
+(u64bit) 0x6D965C432E2EB82EULL, (u64bit) 0x627A96294B4B314BULL, (u64bit) 0xA321E15DFEFEDFFEULL, (u64bit) 0x8216AED557574157ULL,
+(u64bit) 0xA8412ABD15155415ULL, (u64bit) 0x9FB6EEE87777C177ULL, (u64bit) 0xA5EB6E923737DC37ULL, (u64bit) 0x7B56D79EE5E5B3E5ULL,
+(u64bit) 0x8CD923139F9F469FULL, (u64bit) 0xD317FD23F0F0E7F0ULL, (u64bit) 0x6A7F94204A4A354AULL, (u64bit) 0x9E95A944DADA4FDAULL,
+(u64bit) 0xFA25B0A258587D58ULL, (u64bit) 0x06CA8FCFC9C903C9ULL, (u64bit) 0x558D527C2929A429ULL, (u64bit) 0x5022145A0A0A280AULL,
+(u64bit) 0xE14F7F50B1B1FEB1ULL, (u64bit) 0x691A5DC9A0A0BAA0ULL, (u64bit) 0x7FDAD6146B6BB16BULL, (u64bit) 0x5CAB17D985852E85ULL,
+(u64bit) 0x8173673CBDBDCEBDULL, (u64bit) 0xD234BA8F5D5D695DULL, (u64bit) 0x8050209010104010ULL, (u64bit) 0xF303F507F4F4F7F4ULL,
+(u64bit) 0x16C08BDDCBCB0BCBULL, (u64bit) 0xEDC67CD33E3EF83EULL, (u64bit) 0x28110A2D05051405ULL, (u64bit) 0x1FE6CE7867678167ULL,
+(u64bit) 0x7353D597E4E4B7E4ULL, (u64bit) 0x25BB4E0227279C27ULL, (u64bit) 0x3258827341411941ULL, (u64bit) 0x2C9D0BA78B8B168BULL,
+(u64bit) 0x510153F6A7A7A6A7ULL, (u64bit) 0xCF94FAB27D7DE97DULL, (u64bit) 0xDCFB374995956E95ULL, (u64bit) 0x8E9FAD56D8D847D8ULL,
+(u64bit) 0x8B30EB70FBFBCBFBULL, (u64bit) 0x2371C1CDEEEE9FEEULL, (u64bit) 0xC791F8BB7C7CED7CULL, (u64bit) 0x17E3CC7166668566ULL,
+(u64bit) 0xA68EA77BDDDD53DDULL, (u64bit) 0xB84B2EAF17175C17ULL, (u64bit) 0x02468E4547470147ULL, (u64bit) 0x84DC211A9E9E429EULL,
+(u64bit) 0x1EC589D4CACA0FCAULL, (u64bit) 0x75995A582D2DB42DULL, (u64bit) 0x9179632EBFBFC6BFULL, (u64bit) 0x381B0E3F07071C07ULL,
+(u64bit) 0x012347ACADAD8EADULL, (u64bit) 0xEA2FB4B05A5A755AULL, (u64bit) 0x6CB51BEF83833683ULL, (u64bit) 0x85FF66B63333CC33ULL,
+(u64bit) 0x3FF2C65C63639163ULL, (u64bit) 0x100A041202020802ULL, (u64bit) 0x39384993AAAA92AAULL, (u64bit) 0xAFA8E2DE7171D971ULL,
+(u64bit) 0x0ECF8DC6C8C807C8ULL, (u64bit) 0xC87D32D119196419ULL, (u64bit) 0x7270923B49493949ULL, (u64bit) 0x869AAF5FD9D943D9ULL,
+(u64bit) 0xC31DF931F2F2EFF2ULL, (u64bit) 0x4B48DBA8E3E3ABE3ULL, (u64bit) 0xE22AB6B95B5B715BULL, (u64bit) 0x34920DBC88881A88ULL,
+(u64bit) 0xA4C8293E9A9A529AULL, (u64bit) 0x2DBE4C0B26269826ULL, (u64bit) 0x8DFA64BF3232C832ULL, (u64bit) 0xE94A7D59B0B0FAB0ULL,
+(u64bit) 0x1B6ACFF2E9E983E9ULL, (u64bit) 0x78331E770F0F3C0FULL, (u64bit) 0xE6A6B733D5D573D5ULL, (u64bit) 0x74BA1DF480803A80ULL,
+(u64bit) 0x997C6127BEBEC2BEULL, (u64bit) 0x26DE87EBCDCD13CDULL, (u64bit) 0xBDE468893434D034ULL, (u64bit) 0x7A75903248483D48ULL,
+(u64bit) 0xAB24E354FFFFDBFFULL, (u64bit) 0xF78FF48D7A7AF57AULL, (u64bit) 0xF4EA3D6490907A90ULL, (u64bit) 0xC23EBE9D5F5F615FULL,
+(u64bit) 0x1DA0403D20208020ULL, (u64bit) 0x67D5D00F6868BD68ULL, (u64bit) 0xD07234CA1A1A681AULL, (u64bit) 0x192C41B7AEAE82AEULL,
+(u64bit) 0xC95E757DB4B4EAB4ULL, (u64bit) 0x9A19A8CE54544D54ULL, (u64bit) 0xECE53B7F93937693ULL, (u64bit) 0x0DAA442F22228822ULL,
+(u64bit) 0x07E9C86364648D64ULL, (u64bit) 0xDB12FF2AF1F1E3F1ULL, (u64bit) 0xBFA2E6CC7373D173ULL, (u64bit) 0x905A248212124812ULL,
+(u64bit) 0x3A5D807A40401D40ULL, (u64bit) 0x4028104808082008ULL, (u64bit) 0x56E89B95C3C32BC3ULL, (u64bit) 0x337BC5DFECEC97ECULL,
+(u64bit) 0x9690AB4DDBDB4BDBULL, (u64bit) 0x611F5FC0A1A1BEA1ULL, (u64bit) 0x1C8307918D8D0E8DULL, (u64bit) 0xF5C97AC83D3DF43DULL,
+(u64bit) 0xCCF1335B97976697ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0x36D483F9CFCF1BCFULL, (u64bit) 0x4587566E2B2BAC2BULL,
+(u64bit) 0x97B3ECE17676C576ULL, (u64bit) 0x64B019E682823282ULL, (u64bit) 0xFEA9B128D6D67FD6ULL, (u64bit) 0xD87736C31B1B6C1BULL,
+(u64bit) 0xC15B7774B5B5EEB5ULL, (u64bit) 0x112943BEAFAF86AFULL, (u64bit) 0x77DFD41D6A6AB56AULL, (u64bit) 0xBA0DA0EA50505D50ULL,
+(u64bit) 0x124C8A5745450945ULL, (u64bit) 0xCB18FB38F3F3EBF3ULL, (u64bit) 0x9DF060AD3030C030ULL, (u64bit) 0x2B74C3C4EFEF9BEFULL,
+(u64bit) 0xE5C37EDA3F3FFC3FULL, (u64bit) 0x921CAAC755554955ULL, (u64bit) 0x791059DBA2A2B2A2ULL, (u64bit) 0x0365C9E9EAEA8FEAULL,
+(u64bit) 0x0FECCA6A65658965ULL, (u64bit) 0xB9686903BABAD2BAULL, (u64bit) 0x65935E4A2F2FBC2FULL, (u64bit) 0x4EE79D8EC0C027C0ULL,
+(u64bit) 0xBE81A160DEDE5FDEULL, (u64bit) 0xE06C38FC1C1C701CULL, (u64bit) 0xBB2EE746FDFDD3FDULL, (u64bit) 0x52649A1F4D4D294DULL,
+(u64bit) 0xE4E0397692927292ULL, (u64bit) 0x8FBCEAFA7575C975ULL, (u64bit) 0x301E0C3606061806ULL, (u64bit) 0x249809AE8A8A128AULL,
+(u64bit) 0xF940794BB2B2F2B2ULL, (u64bit) 0x6359D185E6E6BFE6ULL, (u64bit) 0x70361C7E0E0E380EULL, (u64bit) 0xF8633EE71F1F7C1FULL,
+(u64bit) 0x37F7C45562629562ULL, (u64bit) 0xEEA3B53AD4D477D4ULL, (u64bit) 0x29324D81A8A89AA8ULL, (u64bit) 0xC4F4315296966296ULL,
+(u64bit) 0x9B3AEF62F9F9C3F9ULL, (u64bit) 0x66F697A3C5C533C5ULL, (u64bit) 0x35B14A1025259425ULL, (u64bit) 0xF220B2AB59597959ULL,
+(u64bit) 0x54AE15D084842A84ULL, (u64bit) 0xB7A7E4C57272D572ULL, (u64bit) 0xD5DD72EC3939E439ULL, (u64bit) 0x5A6198164C4C2D4CULL,
+(u64bit) 0xCA3BBC945E5E655EULL, (u64bit) 0xE785F09F7878FD78ULL, (u64bit) 0xDDD870E53838E038ULL, (u64bit) 0x148605988C8C0A8CULL,
+(u64bit) 0xC6B2BF17D1D163D1ULL, (u64bit) 0x410B57E4A5A5AEA5ULL, (u64bit) 0x434DD9A1E2E2AFE2ULL, (u64bit) 0x2FF8C24E61619961ULL,
+(u64bit) 0xF1457B42B3B3F6B3ULL, (u64bit) 0x15A5423421218421ULL, (u64bit) 0x94D625089C9C4A9CULL, (u64bit) 0xF0663CEE1E1E781EULL,
+(u64bit) 0x2252866143431143ULL, (u64bit) 0x76FC93B1C7C73BC7ULL, (u64bit) 0xB32BE54FFCFCD7FCULL, (u64bit) 0x2014082404041004ULL,
+(u64bit) 0xB208A2E351515951ULL, (u64bit) 0xBCC72F2599995E99ULL, (u64bit) 0x4FC4DA226D6DA96DULL, (u64bit) 0x68391A650D0D340DULL,
+(u64bit) 0x8335E979FAFACFFAULL, (u64bit) 0xB684A369DFDF5BDFULL, (u64bit) 0xD79BFCA97E7EE57EULL, (u64bit) 0x3DB4481924249024ULL,
+(u64bit) 0xC5D776FE3B3BEC3BULL, (u64bit) 0x313D4B9AABAB96ABULL, (u64bit) 0x3ED181F0CECE1FCEULL, (u64bit) 0x8855229911114411ULL,
+(u64bit) 0x0C8903838F8F068FULL, (u64bit) 0x4A6B9C044E4E254EULL, (u64bit) 0xD1517366B7B7E6B7ULL, (u64bit) 0x0B60CBE0EBEB8BEBULL,
+(u64bit) 0xFDCC78C13C3CF03CULL, (u64bit) 0x7CBF1FFD81813E81ULL, (u64bit) 0xD4FE354094946A94ULL, (u64bit) 0xEB0CF31CF7F7FBF7ULL,
+(u64bit) 0xA1676F18B9B9DEB9ULL, (u64bit) 0x985F268B13134C13ULL, (u64bit) 0x7D9C58512C2CB02CULL, (u64bit) 0xD6B8BB05D3D36BD3ULL,
+(u64bit) 0x6B5CD38CE7E7BBE7ULL, (u64bit) 0x57CBDC396E6EA56EULL, (u64bit) 0x6EF395AAC4C437C4ULL, (u64bit) 0x180F061B03030C03ULL,
+(u64bit) 0x8A13ACDC56564556ULL, (u64bit) 0x1A49885E44440D44ULL, (u64bit) 0xDF9EFEA07F7FE17FULL, (u64bit) 0x21374F88A9A99EA9ULL,
+(u64bit) 0x4D8254672A2AA82AULL, (u64bit) 0xB16D6B0ABBBBD6BBULL, (u64bit) 0x46E29F87C1C123C1ULL, (u64bit) 0xA202A6F153535153ULL,
+(u64bit) 0xAE8BA572DCDC57DCULL, (u64bit) 0x582716530B0B2C0BULL, (u64bit) 0x9CD327019D9D4E9DULL, (u64bit) 0x47C1D82B6C6CAD6CULL,
+(u64bit) 0x95F562A43131C431ULL, (u64bit) 0x87B9E8F37474CD74ULL, (u64bit) 0xE309F115F6F6FFF6ULL, (u64bit) 0x0A438C4C46460546ULL,
+(u64bit) 0x092645A5ACAC8AACULL, (u64bit) 0x3C970FB589891E89ULL, (u64bit) 0xA04428B414145014ULL, (u64bit) 0x5B42DFBAE1E1A3E1ULL,
+(u64bit) 0xB04E2CA616165816ULL, (u64bit) 0xCDD274F73A3AE83AULL, (u64bit) 0x6FD0D2066969B969ULL, (u64bit) 0x482D124109092409ULL,
+(u64bit) 0xA7ADE0D77070DD70ULL, (u64bit) 0xD954716FB6B6E2B6ULL, (u64bit) 0xCEB7BD1ED0D067D0ULL, (u64bit) 0x3B7EC7D6EDED93EDULL,
+(u64bit) 0x2EDB85E2CCCC17CCULL, (u64bit) 0x2A57846842421542ULL, (u64bit) 0xB4C22D2C98985A98ULL, (u64bit) 0x490E55EDA4A4AAA4ULL,
+(u64bit) 0x5D8850752828A028ULL, (u64bit) 0xDA31B8865C5C6D5CULL, (u64bit) 0x933FED6BF8F8C7F8ULL, (u64bit) 0x44A411C286862286ULL };
+
+const u64bit Whirlpool::C5[256] = {
+(u64bit) 0x18C07830D8181860ULL, (u64bit) 0x2305AF462623238CULL, (u64bit) 0xC67EF991B8C6C63FULL, (u64bit) 0xE8136FCDFBE8E887ULL,
+(u64bit) 0x874CA113CB878726ULL, (u64bit) 0xB8A9626D11B8B8DAULL, (u64bit) 0x0108050209010104ULL, (u64bit) 0x4F426E9E0D4F4F21ULL,
+(u64bit) 0x36ADEE6C9B3636D8ULL, (u64bit) 0xA6590451FFA6A6A2ULL, (u64bit) 0xD2DEBDB90CD2D26FULL, (u64bit) 0xF5FB06F70EF5F5F3ULL,
+(u64bit) 0x79EF80F2967979F9ULL, (u64bit) 0x6F5FCEDE306F6FA1ULL, (u64bit) 0x91FCEF3F6D91917EULL, (u64bit) 0x52AA07A4F8525255ULL,
+(u64bit) 0x6027FDC04760609DULL, (u64bit) 0xBC89766535BCBCCAULL, (u64bit) 0x9BACCD2B379B9B56ULL, (u64bit) 0x8E048C018A8E8E02ULL,
+(u64bit) 0xA371155BD2A3A3B6ULL, (u64bit) 0x0C603C186C0C0C30ULL, (u64bit) 0x7BFF8AF6847B7BF1ULL, (u64bit) 0x35B5E16A803535D4ULL,
+(u64bit) 0x1DE8693AF51D1D74ULL, (u64bit) 0xE05347DDB3E0E0A7ULL, (u64bit) 0xD7F6ACB321D7D77BULL, (u64bit) 0xC25EED999CC2C22FULL,
+(u64bit) 0x2E6D965C432E2EB8ULL, (u64bit) 0x4B627A96294B4B31ULL, (u64bit) 0xFEA321E15DFEFEDFULL, (u64bit) 0x578216AED5575741ULL,
+(u64bit) 0x15A8412ABD151554ULL, (u64bit) 0x779FB6EEE87777C1ULL, (u64bit) 0x37A5EB6E923737DCULL, (u64bit) 0xE57B56D79EE5E5B3ULL,
+(u64bit) 0x9F8CD923139F9F46ULL, (u64bit) 0xF0D317FD23F0F0E7ULL, (u64bit) 0x4A6A7F94204A4A35ULL, (u64bit) 0xDA9E95A944DADA4FULL,
+(u64bit) 0x58FA25B0A258587DULL, (u64bit) 0xC906CA8FCFC9C903ULL, (u64bit) 0x29558D527C2929A4ULL, (u64bit) 0x0A5022145A0A0A28ULL,
+(u64bit) 0xB1E14F7F50B1B1FEULL, (u64bit) 0xA0691A5DC9A0A0BAULL, (u64bit) 0x6B7FDAD6146B6BB1ULL, (u64bit) 0x855CAB17D985852EULL,
+(u64bit) 0xBD8173673CBDBDCEULL, (u64bit) 0x5DD234BA8F5D5D69ULL, (u64bit) 0x1080502090101040ULL, (u64bit) 0xF4F303F507F4F4F7ULL,
+(u64bit) 0xCB16C08BDDCBCB0BULL, (u64bit) 0x3EEDC67CD33E3EF8ULL, (u64bit) 0x0528110A2D050514ULL, (u64bit) 0x671FE6CE78676781ULL,
+(u64bit) 0xE47353D597E4E4B7ULL, (u64bit) 0x2725BB4E0227279CULL, (u64bit) 0x4132588273414119ULL, (u64bit) 0x8B2C9D0BA78B8B16ULL,
+(u64bit) 0xA7510153F6A7A7A6ULL, (u64bit) 0x7DCF94FAB27D7DE9ULL, (u64bit) 0x95DCFB374995956EULL, (u64bit) 0xD88E9FAD56D8D847ULL,
+(u64bit) 0xFB8B30EB70FBFBCBULL, (u64bit) 0xEE2371C1CDEEEE9FULL, (u64bit) 0x7CC791F8BB7C7CEDULL, (u64bit) 0x6617E3CC71666685ULL,
+(u64bit) 0xDDA68EA77BDDDD53ULL, (u64bit) 0x17B84B2EAF17175CULL, (u64bit) 0x4702468E45474701ULL, (u64bit) 0x9E84DC211A9E9E42ULL,
+(u64bit) 0xCA1EC589D4CACA0FULL, (u64bit) 0x2D75995A582D2DB4ULL, (u64bit) 0xBF9179632EBFBFC6ULL, (u64bit) 0x07381B0E3F07071CULL,
+(u64bit) 0xAD012347ACADAD8EULL, (u64bit) 0x5AEA2FB4B05A5A75ULL, (u64bit) 0x836CB51BEF838336ULL, (u64bit) 0x3385FF66B63333CCULL,
+(u64bit) 0x633FF2C65C636391ULL, (u64bit) 0x02100A0412020208ULL, (u64bit) 0xAA39384993AAAA92ULL, (u64bit) 0x71AFA8E2DE7171D9ULL,
+(u64bit) 0xC80ECF8DC6C8C807ULL, (u64bit) 0x19C87D32D1191964ULL, (u64bit) 0x497270923B494939ULL, (u64bit) 0xD9869AAF5FD9D943ULL,
+(u64bit) 0xF2C31DF931F2F2EFULL, (u64bit) 0xE34B48DBA8E3E3ABULL, (u64bit) 0x5BE22AB6B95B5B71ULL, (u64bit) 0x8834920DBC88881AULL,
+(u64bit) 0x9AA4C8293E9A9A52ULL, (u64bit) 0x262DBE4C0B262698ULL, (u64bit) 0x328DFA64BF3232C8ULL, (u64bit) 0xB0E94A7D59B0B0FAULL,
+(u64bit) 0xE91B6ACFF2E9E983ULL, (u64bit) 0x0F78331E770F0F3CULL, (u64bit) 0xD5E6A6B733D5D573ULL, (u64bit) 0x8074BA1DF480803AULL,
+(u64bit) 0xBE997C6127BEBEC2ULL, (u64bit) 0xCD26DE87EBCDCD13ULL, (u64bit) 0x34BDE468893434D0ULL, (u64bit) 0x487A75903248483DULL,
+(u64bit) 0xFFAB24E354FFFFDBULL, (u64bit) 0x7AF78FF48D7A7AF5ULL, (u64bit) 0x90F4EA3D6490907AULL, (u64bit) 0x5FC23EBE9D5F5F61ULL,
+(u64bit) 0x201DA0403D202080ULL, (u64bit) 0x6867D5D00F6868BDULL, (u64bit) 0x1AD07234CA1A1A68ULL, (u64bit) 0xAE192C41B7AEAE82ULL,
+(u64bit) 0xB4C95E757DB4B4EAULL, (u64bit) 0x549A19A8CE54544DULL, (u64bit) 0x93ECE53B7F939376ULL, (u64bit) 0x220DAA442F222288ULL,
+(u64bit) 0x6407E9C86364648DULL, (u64bit) 0xF1DB12FF2AF1F1E3ULL, (u64bit) 0x73BFA2E6CC7373D1ULL, (u64bit) 0x12905A2482121248ULL,
+(u64bit) 0x403A5D807A40401DULL, (u64bit) 0x0840281048080820ULL, (u64bit) 0xC356E89B95C3C32BULL, (u64bit) 0xEC337BC5DFECEC97ULL,
+(u64bit) 0xDB9690AB4DDBDB4BULL, (u64bit) 0xA1611F5FC0A1A1BEULL, (u64bit) 0x8D1C8307918D8D0EULL, (u64bit) 0x3DF5C97AC83D3DF4ULL,
+(u64bit) 0x97CCF1335B979766ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0xCF36D483F9CFCF1BULL, (u64bit) 0x2B4587566E2B2BACULL,
+(u64bit) 0x7697B3ECE17676C5ULL, (u64bit) 0x8264B019E6828232ULL, (u64bit) 0xD6FEA9B128D6D67FULL, (u64bit) 0x1BD87736C31B1B6CULL,
+(u64bit) 0xB5C15B7774B5B5EEULL, (u64bit) 0xAF112943BEAFAF86ULL, (u64bit) 0x6A77DFD41D6A6AB5ULL, (u64bit) 0x50BA0DA0EA50505DULL,
+(u64bit) 0x45124C8A57454509ULL, (u64bit) 0xF3CB18FB38F3F3EBULL, (u64bit) 0x309DF060AD3030C0ULL, (u64bit) 0xEF2B74C3C4EFEF9BULL,
+(u64bit) 0x3FE5C37EDA3F3FFCULL, (u64bit) 0x55921CAAC7555549ULL, (u64bit) 0xA2791059DBA2A2B2ULL, (u64bit) 0xEA0365C9E9EAEA8FULL,
+(u64bit) 0x650FECCA6A656589ULL, (u64bit) 0xBAB9686903BABAD2ULL, (u64bit) 0x2F65935E4A2F2FBCULL, (u64bit) 0xC04EE79D8EC0C027ULL,
+(u64bit) 0xDEBE81A160DEDE5FULL, (u64bit) 0x1CE06C38FC1C1C70ULL, (u64bit) 0xFDBB2EE746FDFDD3ULL, (u64bit) 0x4D52649A1F4D4D29ULL,
+(u64bit) 0x92E4E03976929272ULL, (u64bit) 0x758FBCEAFA7575C9ULL, (u64bit) 0x06301E0C36060618ULL, (u64bit) 0x8A249809AE8A8A12ULL,
+(u64bit) 0xB2F940794BB2B2F2ULL, (u64bit) 0xE66359D185E6E6BFULL, (u64bit) 0x0E70361C7E0E0E38ULL, (u64bit) 0x1FF8633EE71F1F7CULL,
+(u64bit) 0x6237F7C455626295ULL, (u64bit) 0xD4EEA3B53AD4D477ULL, (u64bit) 0xA829324D81A8A89AULL, (u64bit) 0x96C4F43152969662ULL,
+(u64bit) 0xF99B3AEF62F9F9C3ULL, (u64bit) 0xC566F697A3C5C533ULL, (u64bit) 0x2535B14A10252594ULL, (u64bit) 0x59F220B2AB595979ULL,
+(u64bit) 0x8454AE15D084842AULL, (u64bit) 0x72B7A7E4C57272D5ULL, (u64bit) 0x39D5DD72EC3939E4ULL, (u64bit) 0x4C5A6198164C4C2DULL,
+(u64bit) 0x5ECA3BBC945E5E65ULL, (u64bit) 0x78E785F09F7878FDULL, (u64bit) 0x38DDD870E53838E0ULL, (u64bit) 0x8C148605988C8C0AULL,
+(u64bit) 0xD1C6B2BF17D1D163ULL, (u64bit) 0xA5410B57E4A5A5AEULL, (u64bit) 0xE2434DD9A1E2E2AFULL, (u64bit) 0x612FF8C24E616199ULL,
+(u64bit) 0xB3F1457B42B3B3F6ULL, (u64bit) 0x2115A54234212184ULL, (u64bit) 0x9C94D625089C9C4AULL, (u64bit) 0x1EF0663CEE1E1E78ULL,
+(u64bit) 0x4322528661434311ULL, (u64bit) 0xC776FC93B1C7C73BULL, (u64bit) 0xFCB32BE54FFCFCD7ULL, (u64bit) 0x0420140824040410ULL,
+(u64bit) 0x51B208A2E3515159ULL, (u64bit) 0x99BCC72F2599995EULL, (u64bit) 0x6D4FC4DA226D6DA9ULL, (u64bit) 0x0D68391A650D0D34ULL,
+(u64bit) 0xFA8335E979FAFACFULL, (u64bit) 0xDFB684A369DFDF5BULL, (u64bit) 0x7ED79BFCA97E7EE5ULL, (u64bit) 0x243DB44819242490ULL,
+(u64bit) 0x3BC5D776FE3B3BECULL, (u64bit) 0xAB313D4B9AABAB96ULL, (u64bit) 0xCE3ED181F0CECE1FULL, (u64bit) 0x1188552299111144ULL,
+(u64bit) 0x8F0C8903838F8F06ULL, (u64bit) 0x4E4A6B9C044E4E25ULL, (u64bit) 0xB7D1517366B7B7E6ULL, (u64bit) 0xEB0B60CBE0EBEB8BULL,
+(u64bit) 0x3CFDCC78C13C3CF0ULL, (u64bit) 0x817CBF1FFD81813EULL, (u64bit) 0x94D4FE354094946AULL, (u64bit) 0xF7EB0CF31CF7F7FBULL,
+(u64bit) 0xB9A1676F18B9B9DEULL, (u64bit) 0x13985F268B13134CULL, (u64bit) 0x2C7D9C58512C2CB0ULL, (u64bit) 0xD3D6B8BB05D3D36BULL,
+(u64bit) 0xE76B5CD38CE7E7BBULL, (u64bit) 0x6E57CBDC396E6EA5ULL, (u64bit) 0xC46EF395AAC4C437ULL, (u64bit) 0x03180F061B03030CULL,
+(u64bit) 0x568A13ACDC565645ULL, (u64bit) 0x441A49885E44440DULL, (u64bit) 0x7FDF9EFEA07F7FE1ULL, (u64bit) 0xA921374F88A9A99EULL,
+(u64bit) 0x2A4D8254672A2AA8ULL, (u64bit) 0xBBB16D6B0ABBBBD6ULL, (u64bit) 0xC146E29F87C1C123ULL, (u64bit) 0x53A202A6F1535351ULL,
+(u64bit) 0xDCAE8BA572DCDC57ULL, (u64bit) 0x0B582716530B0B2CULL, (u64bit) 0x9D9CD327019D9D4EULL, (u64bit) 0x6C47C1D82B6C6CADULL,
+(u64bit) 0x3195F562A43131C4ULL, (u64bit) 0x7487B9E8F37474CDULL, (u64bit) 0xF6E309F115F6F6FFULL, (u64bit) 0x460A438C4C464605ULL,
+(u64bit) 0xAC092645A5ACAC8AULL, (u64bit) 0x893C970FB589891EULL, (u64bit) 0x14A04428B4141450ULL, (u64bit) 0xE15B42DFBAE1E1A3ULL,
+(u64bit) 0x16B04E2CA6161658ULL, (u64bit) 0x3ACDD274F73A3AE8ULL, (u64bit) 0x696FD0D2066969B9ULL, (u64bit) 0x09482D1241090924ULL,
+(u64bit) 0x70A7ADE0D77070DDULL, (u64bit) 0xB6D954716FB6B6E2ULL, (u64bit) 0xD0CEB7BD1ED0D067ULL, (u64bit) 0xED3B7EC7D6EDED93ULL,
+(u64bit) 0xCC2EDB85E2CCCC17ULL, (u64bit) 0x422A578468424215ULL, (u64bit) 0x98B4C22D2C98985AULL, (u64bit) 0xA4490E55EDA4A4AAULL,
+(u64bit) 0x285D8850752828A0ULL, (u64bit) 0x5CDA31B8865C5C6DULL, (u64bit) 0xF8933FED6BF8F8C7ULL, (u64bit) 0x8644A411C2868622ULL };
+
+const u64bit Whirlpool::C6[256] = {
+(u64bit) 0x6018C07830D81818ULL, (u64bit) 0x8C2305AF46262323ULL, (u64bit) 0x3FC67EF991B8C6C6ULL, (u64bit) 0x87E8136FCDFBE8E8ULL,
+(u64bit) 0x26874CA113CB8787ULL, (u64bit) 0xDAB8A9626D11B8B8ULL, (u64bit) 0x0401080502090101ULL, (u64bit) 0x214F426E9E0D4F4FULL,
+(u64bit) 0xD836ADEE6C9B3636ULL, (u64bit) 0xA2A6590451FFA6A6ULL, (u64bit) 0x6FD2DEBDB90CD2D2ULL, (u64bit) 0xF3F5FB06F70EF5F5ULL,
+(u64bit) 0xF979EF80F2967979ULL, (u64bit) 0xA16F5FCEDE306F6FULL, (u64bit) 0x7E91FCEF3F6D9191ULL, (u64bit) 0x5552AA07A4F85252ULL,
+(u64bit) 0x9D6027FDC0476060ULL, (u64bit) 0xCABC89766535BCBCULL, (u64bit) 0x569BACCD2B379B9BULL, (u64bit) 0x028E048C018A8E8EULL,
+(u64bit) 0xB6A371155BD2A3A3ULL, (u64bit) 0x300C603C186C0C0CULL, (u64bit) 0xF17BFF8AF6847B7BULL, (u64bit) 0xD435B5E16A803535ULL,
+(u64bit) 0x741DE8693AF51D1DULL, (u64bit) 0xA7E05347DDB3E0E0ULL, (u64bit) 0x7BD7F6ACB321D7D7ULL, (u64bit) 0x2FC25EED999CC2C2ULL,
+(u64bit) 0xB82E6D965C432E2EULL, (u64bit) 0x314B627A96294B4BULL, (u64bit) 0xDFFEA321E15DFEFEULL, (u64bit) 0x41578216AED55757ULL,
+(u64bit) 0x5415A8412ABD1515ULL, (u64bit) 0xC1779FB6EEE87777ULL, (u64bit) 0xDC37A5EB6E923737ULL, (u64bit) 0xB3E57B56D79EE5E5ULL,
+(u64bit) 0x469F8CD923139F9FULL, (u64bit) 0xE7F0D317FD23F0F0ULL, (u64bit) 0x354A6A7F94204A4AULL, (u64bit) 0x4FDA9E95A944DADAULL,
+(u64bit) 0x7D58FA25B0A25858ULL, (u64bit) 0x03C906CA8FCFC9C9ULL, (u64bit) 0xA429558D527C2929ULL, (u64bit) 0x280A5022145A0A0AULL,
+(u64bit) 0xFEB1E14F7F50B1B1ULL, (u64bit) 0xBAA0691A5DC9A0A0ULL, (u64bit) 0xB16B7FDAD6146B6BULL, (u64bit) 0x2E855CAB17D98585ULL,
+(u64bit) 0xCEBD8173673CBDBDULL, (u64bit) 0x695DD234BA8F5D5DULL, (u64bit) 0x4010805020901010ULL, (u64bit) 0xF7F4F303F507F4F4ULL,
+(u64bit) 0x0BCB16C08BDDCBCBULL, (u64bit) 0xF83EEDC67CD33E3EULL, (u64bit) 0x140528110A2D0505ULL, (u64bit) 0x81671FE6CE786767ULL,
+(u64bit) 0xB7E47353D597E4E4ULL, (u64bit) 0x9C2725BB4E022727ULL, (u64bit) 0x1941325882734141ULL, (u64bit) 0x168B2C9D0BA78B8BULL,
+(u64bit) 0xA6A7510153F6A7A7ULL, (u64bit) 0xE97DCF94FAB27D7DULL, (u64bit) 0x6E95DCFB37499595ULL, (u64bit) 0x47D88E9FAD56D8D8ULL,
+(u64bit) 0xCBFB8B30EB70FBFBULL, (u64bit) 0x9FEE2371C1CDEEEEULL, (u64bit) 0xED7CC791F8BB7C7CULL, (u64bit) 0x856617E3CC716666ULL,
+(u64bit) 0x53DDA68EA77BDDDDULL, (u64bit) 0x5C17B84B2EAF1717ULL, (u64bit) 0x014702468E454747ULL, (u64bit) 0x429E84DC211A9E9EULL,
+(u64bit) 0x0FCA1EC589D4CACAULL, (u64bit) 0xB42D75995A582D2DULL, (u64bit) 0xC6BF9179632EBFBFULL, (u64bit) 0x1C07381B0E3F0707ULL,
+(u64bit) 0x8EAD012347ACADADULL, (u64bit) 0x755AEA2FB4B05A5AULL, (u64bit) 0x36836CB51BEF8383ULL, (u64bit) 0xCC3385FF66B63333ULL,
+(u64bit) 0x91633FF2C65C6363ULL, (u64bit) 0x0802100A04120202ULL, (u64bit) 0x92AA39384993AAAAULL, (u64bit) 0xD971AFA8E2DE7171ULL,
+(u64bit) 0x07C80ECF8DC6C8C8ULL, (u64bit) 0x6419C87D32D11919ULL, (u64bit) 0x39497270923B4949ULL, (u64bit) 0x43D9869AAF5FD9D9ULL,
+(u64bit) 0xEFF2C31DF931F2F2ULL, (u64bit) 0xABE34B48DBA8E3E3ULL, (u64bit) 0x715BE22AB6B95B5BULL, (u64bit) 0x1A8834920DBC8888ULL,
+(u64bit) 0x529AA4C8293E9A9AULL, (u64bit) 0x98262DBE4C0B2626ULL, (u64bit) 0xC8328DFA64BF3232ULL, (u64bit) 0xFAB0E94A7D59B0B0ULL,
+(u64bit) 0x83E91B6ACFF2E9E9ULL, (u64bit) 0x3C0F78331E770F0FULL, (u64bit) 0x73D5E6A6B733D5D5ULL, (u64bit) 0x3A8074BA1DF48080ULL,
+(u64bit) 0xC2BE997C6127BEBEULL, (u64bit) 0x13CD26DE87EBCDCDULL, (u64bit) 0xD034BDE468893434ULL, (u64bit) 0x3D487A7590324848ULL,
+(u64bit) 0xDBFFAB24E354FFFFULL, (u64bit) 0xF57AF78FF48D7A7AULL, (u64bit) 0x7A90F4EA3D649090ULL, (u64bit) 0x615FC23EBE9D5F5FULL,
+(u64bit) 0x80201DA0403D2020ULL, (u64bit) 0xBD6867D5D00F6868ULL, (u64bit) 0x681AD07234CA1A1AULL, (u64bit) 0x82AE192C41B7AEAEULL,
+(u64bit) 0xEAB4C95E757DB4B4ULL, (u64bit) 0x4D549A19A8CE5454ULL, (u64bit) 0x7693ECE53B7F9393ULL, (u64bit) 0x88220DAA442F2222ULL,
+(u64bit) 0x8D6407E9C8636464ULL, (u64bit) 0xE3F1DB12FF2AF1F1ULL, (u64bit) 0xD173BFA2E6CC7373ULL, (u64bit) 0x4812905A24821212ULL,
+(u64bit) 0x1D403A5D807A4040ULL, (u64bit) 0x2008402810480808ULL, (u64bit) 0x2BC356E89B95C3C3ULL, (u64bit) 0x97EC337BC5DFECECULL,
+(u64bit) 0x4BDB9690AB4DDBDBULL, (u64bit) 0xBEA1611F5FC0A1A1ULL, (u64bit) 0x0E8D1C8307918D8DULL, (u64bit) 0xF43DF5C97AC83D3DULL,
+(u64bit) 0x6697CCF1335B9797ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0x1BCF36D483F9CFCFULL, (u64bit) 0xAC2B4587566E2B2BULL,
+(u64bit) 0xC57697B3ECE17676ULL, (u64bit) 0x328264B019E68282ULL, (u64bit) 0x7FD6FEA9B128D6D6ULL, (u64bit) 0x6C1BD87736C31B1BULL,
+(u64bit) 0xEEB5C15B7774B5B5ULL, (u64bit) 0x86AF112943BEAFAFULL, (u64bit) 0xB56A77DFD41D6A6AULL, (u64bit) 0x5D50BA0DA0EA5050ULL,
+(u64bit) 0x0945124C8A574545ULL, (u64bit) 0xEBF3CB18FB38F3F3ULL, (u64bit) 0xC0309DF060AD3030ULL, (u64bit) 0x9BEF2B74C3C4EFEFULL,
+(u64bit) 0xFC3FE5C37EDA3F3FULL, (u64bit) 0x4955921CAAC75555ULL, (u64bit) 0xB2A2791059DBA2A2ULL, (u64bit) 0x8FEA0365C9E9EAEAULL,
+(u64bit) 0x89650FECCA6A6565ULL, (u64bit) 0xD2BAB9686903BABAULL, (u64bit) 0xBC2F65935E4A2F2FULL, (u64bit) 0x27C04EE79D8EC0C0ULL,
+(u64bit) 0x5FDEBE81A160DEDEULL, (u64bit) 0x701CE06C38FC1C1CULL, (u64bit) 0xD3FDBB2EE746FDFDULL, (u64bit) 0x294D52649A1F4D4DULL,
+(u64bit) 0x7292E4E039769292ULL, (u64bit) 0xC9758FBCEAFA7575ULL, (u64bit) 0x1806301E0C360606ULL, (u64bit) 0x128A249809AE8A8AULL,
+(u64bit) 0xF2B2F940794BB2B2ULL, (u64bit) 0xBFE66359D185E6E6ULL, (u64bit) 0x380E70361C7E0E0EULL, (u64bit) 0x7C1FF8633EE71F1FULL,
+(u64bit) 0x956237F7C4556262ULL, (u64bit) 0x77D4EEA3B53AD4D4ULL, (u64bit) 0x9AA829324D81A8A8ULL, (u64bit) 0x6296C4F431529696ULL,
+(u64bit) 0xC3F99B3AEF62F9F9ULL, (u64bit) 0x33C566F697A3C5C5ULL, (u64bit) 0x942535B14A102525ULL, (u64bit) 0x7959F220B2AB5959ULL,
+(u64bit) 0x2A8454AE15D08484ULL, (u64bit) 0xD572B7A7E4C57272ULL, (u64bit) 0xE439D5DD72EC3939ULL, (u64bit) 0x2D4C5A6198164C4CULL,
+(u64bit) 0x655ECA3BBC945E5EULL, (u64bit) 0xFD78E785F09F7878ULL, (u64bit) 0xE038DDD870E53838ULL, (u64bit) 0x0A8C148605988C8CULL,
+(u64bit) 0x63D1C6B2BF17D1D1ULL, (u64bit) 0xAEA5410B57E4A5A5ULL, (u64bit) 0xAFE2434DD9A1E2E2ULL, (u64bit) 0x99612FF8C24E6161ULL,
+(u64bit) 0xF6B3F1457B42B3B3ULL, (u64bit) 0x842115A542342121ULL, (u64bit) 0x4A9C94D625089C9CULL, (u64bit) 0x781EF0663CEE1E1EULL,
+(u64bit) 0x1143225286614343ULL, (u64bit) 0x3BC776FC93B1C7C7ULL, (u64bit) 0xD7FCB32BE54FFCFCULL, (u64bit) 0x1004201408240404ULL,
+(u64bit) 0x5951B208A2E35151ULL, (u64bit) 0x5E99BCC72F259999ULL, (u64bit) 0xA96D4FC4DA226D6DULL, (u64bit) 0x340D68391A650D0DULL,
+(u64bit) 0xCFFA8335E979FAFAULL, (u64bit) 0x5BDFB684A369DFDFULL, (u64bit) 0xE57ED79BFCA97E7EULL, (u64bit) 0x90243DB448192424ULL,
+(u64bit) 0xEC3BC5D776FE3B3BULL, (u64bit) 0x96AB313D4B9AABABULL, (u64bit) 0x1FCE3ED181F0CECEULL, (u64bit) 0x4411885522991111ULL,
+(u64bit) 0x068F0C8903838F8FULL, (u64bit) 0x254E4A6B9C044E4EULL, (u64bit) 0xE6B7D1517366B7B7ULL, (u64bit) 0x8BEB0B60CBE0EBEBULL,
+(u64bit) 0xF03CFDCC78C13C3CULL, (u64bit) 0x3E817CBF1FFD8181ULL, (u64bit) 0x6A94D4FE35409494ULL, (u64bit) 0xFBF7EB0CF31CF7F7ULL,
+(u64bit) 0xDEB9A1676F18B9B9ULL, (u64bit) 0x4C13985F268B1313ULL, (u64bit) 0xB02C7D9C58512C2CULL, (u64bit) 0x6BD3D6B8BB05D3D3ULL,
+(u64bit) 0xBBE76B5CD38CE7E7ULL, (u64bit) 0xA56E57CBDC396E6EULL, (u64bit) 0x37C46EF395AAC4C4ULL, (u64bit) 0x0C03180F061B0303ULL,
+(u64bit) 0x45568A13ACDC5656ULL, (u64bit) 0x0D441A49885E4444ULL, (u64bit) 0xE17FDF9EFEA07F7FULL, (u64bit) 0x9EA921374F88A9A9ULL,
+(u64bit) 0xA82A4D8254672A2AULL, (u64bit) 0xD6BBB16D6B0ABBBBULL, (u64bit) 0x23C146E29F87C1C1ULL, (u64bit) 0x5153A202A6F15353ULL,
+(u64bit) 0x57DCAE8BA572DCDCULL, (u64bit) 0x2C0B582716530B0BULL, (u64bit) 0x4E9D9CD327019D9DULL, (u64bit) 0xAD6C47C1D82B6C6CULL,
+(u64bit) 0xC43195F562A43131ULL, (u64bit) 0xCD7487B9E8F37474ULL, (u64bit) 0xFFF6E309F115F6F6ULL, (u64bit) 0x05460A438C4C4646ULL,
+(u64bit) 0x8AAC092645A5ACACULL, (u64bit) 0x1E893C970FB58989ULL, (u64bit) 0x5014A04428B41414ULL, (u64bit) 0xA3E15B42DFBAE1E1ULL,
+(u64bit) 0x5816B04E2CA61616ULL, (u64bit) 0xE83ACDD274F73A3AULL, (u64bit) 0xB9696FD0D2066969ULL, (u64bit) 0x2409482D12410909ULL,
+(u64bit) 0xDD70A7ADE0D77070ULL, (u64bit) 0xE2B6D954716FB6B6ULL, (u64bit) 0x67D0CEB7BD1ED0D0ULL, (u64bit) 0x93ED3B7EC7D6EDEDULL,
+(u64bit) 0x17CC2EDB85E2CCCCULL, (u64bit) 0x15422A5784684242ULL, (u64bit) 0x5A98B4C22D2C9898ULL, (u64bit) 0xAAA4490E55EDA4A4ULL,
+(u64bit) 0xA0285D8850752828ULL, (u64bit) 0x6D5CDA31B8865C5CULL, (u64bit) 0xC7F8933FED6BF8F8ULL, (u64bit) 0x228644A411C28686ULL };
+
+const u64bit Whirlpool::C7[256] = {
+(u64bit) 0x186018C07830D818ULL, (u64bit) 0x238C2305AF462623ULL, (u64bit) 0xC63FC67EF991B8C6ULL, (u64bit) 0xE887E8136FCDFBE8ULL,
+(u64bit) 0x8726874CA113CB87ULL, (u64bit) 0xB8DAB8A9626D11B8ULL, (u64bit) 0x0104010805020901ULL, (u64bit) 0x4F214F426E9E0D4FULL,
+(u64bit) 0x36D836ADEE6C9B36ULL, (u64bit) 0xA6A2A6590451FFA6ULL, (u64bit) 0xD26FD2DEBDB90CD2ULL, (u64bit) 0xF5F3F5FB06F70EF5ULL,
+(u64bit) 0x79F979EF80F29679ULL, (u64bit) 0x6FA16F5FCEDE306FULL, (u64bit) 0x917E91FCEF3F6D91ULL, (u64bit) 0x525552AA07A4F852ULL,
+(u64bit) 0x609D6027FDC04760ULL, (u64bit) 0xBCCABC89766535BCULL, (u64bit) 0x9B569BACCD2B379BULL, (u64bit) 0x8E028E048C018A8EULL,
+(u64bit) 0xA3B6A371155BD2A3ULL, (u64bit) 0x0C300C603C186C0CULL, (u64bit) 0x7BF17BFF8AF6847BULL, (u64bit) 0x35D435B5E16A8035ULL,
+(u64bit) 0x1D741DE8693AF51DULL, (u64bit) 0xE0A7E05347DDB3E0ULL, (u64bit) 0xD77BD7F6ACB321D7ULL, (u64bit) 0xC22FC25EED999CC2ULL,
+(u64bit) 0x2EB82E6D965C432EULL, (u64bit) 0x4B314B627A96294BULL, (u64bit) 0xFEDFFEA321E15DFEULL, (u64bit) 0x5741578216AED557ULL,
+(u64bit) 0x155415A8412ABD15ULL, (u64bit) 0x77C1779FB6EEE877ULL, (u64bit) 0x37DC37A5EB6E9237ULL, (u64bit) 0xE5B3E57B56D79EE5ULL,
+(u64bit) 0x9F469F8CD923139FULL, (u64bit) 0xF0E7F0D317FD23F0ULL, (u64bit) 0x4A354A6A7F94204AULL, (u64bit) 0xDA4FDA9E95A944DAULL,
+(u64bit) 0x587D58FA25B0A258ULL, (u64bit) 0xC903C906CA8FCFC9ULL, (u64bit) 0x29A429558D527C29ULL, (u64bit) 0x0A280A5022145A0AULL,
+(u64bit) 0xB1FEB1E14F7F50B1ULL, (u64bit) 0xA0BAA0691A5DC9A0ULL, (u64bit) 0x6BB16B7FDAD6146BULL, (u64bit) 0x852E855CAB17D985ULL,
+(u64bit) 0xBDCEBD8173673CBDULL, (u64bit) 0x5D695DD234BA8F5DULL, (u64bit) 0x1040108050209010ULL, (u64bit) 0xF4F7F4F303F507F4ULL,
+(u64bit) 0xCB0BCB16C08BDDCBULL, (u64bit) 0x3EF83EEDC67CD33EULL, (u64bit) 0x05140528110A2D05ULL, (u64bit) 0x6781671FE6CE7867ULL,
+(u64bit) 0xE4B7E47353D597E4ULL, (u64bit) 0x279C2725BB4E0227ULL, (u64bit) 0x4119413258827341ULL, (u64bit) 0x8B168B2C9D0BA78BULL,
+(u64bit) 0xA7A6A7510153F6A7ULL, (u64bit) 0x7DE97DCF94FAB27DULL, (u64bit) 0x956E95DCFB374995ULL, (u64bit) 0xD847D88E9FAD56D8ULL,
+(u64bit) 0xFBCBFB8B30EB70FBULL, (u64bit) 0xEE9FEE2371C1CDEEULL, (u64bit) 0x7CED7CC791F8BB7CULL, (u64bit) 0x66856617E3CC7166ULL,
+(u64bit) 0xDD53DDA68EA77BDDULL, (u64bit) 0x175C17B84B2EAF17ULL, (u64bit) 0x47014702468E4547ULL, (u64bit) 0x9E429E84DC211A9EULL,
+(u64bit) 0xCA0FCA1EC589D4CAULL, (u64bit) 0x2DB42D75995A582DULL, (u64bit) 0xBFC6BF9179632EBFULL, (u64bit) 0x071C07381B0E3F07ULL,
+(u64bit) 0xAD8EAD012347ACADULL, (u64bit) 0x5A755AEA2FB4B05AULL, (u64bit) 0x8336836CB51BEF83ULL, (u64bit) 0x33CC3385FF66B633ULL,
+(u64bit) 0x6391633FF2C65C63ULL, (u64bit) 0x020802100A041202ULL, (u64bit) 0xAA92AA39384993AAULL, (u64bit) 0x71D971AFA8E2DE71ULL,
+(u64bit) 0xC807C80ECF8DC6C8ULL, (u64bit) 0x196419C87D32D119ULL, (u64bit) 0x4939497270923B49ULL, (u64bit) 0xD943D9869AAF5FD9ULL,
+(u64bit) 0xF2EFF2C31DF931F2ULL, (u64bit) 0xE3ABE34B48DBA8E3ULL, (u64bit) 0x5B715BE22AB6B95BULL, (u64bit) 0x881A8834920DBC88ULL,
+(u64bit) 0x9A529AA4C8293E9AULL, (u64bit) 0x2698262DBE4C0B26ULL, (u64bit) 0x32C8328DFA64BF32ULL, (u64bit) 0xB0FAB0E94A7D59B0ULL,
+(u64bit) 0xE983E91B6ACFF2E9ULL, (u64bit) 0x0F3C0F78331E770FULL, (u64bit) 0xD573D5E6A6B733D5ULL, (u64bit) 0x803A8074BA1DF480ULL,
+(u64bit) 0xBEC2BE997C6127BEULL, (u64bit) 0xCD13CD26DE87EBCDULL, (u64bit) 0x34D034BDE4688934ULL, (u64bit) 0x483D487A75903248ULL,
+(u64bit) 0xFFDBFFAB24E354FFULL, (u64bit) 0x7AF57AF78FF48D7AULL, (u64bit) 0x907A90F4EA3D6490ULL, (u64bit) 0x5F615FC23EBE9D5FULL,
+(u64bit) 0x2080201DA0403D20ULL, (u64bit) 0x68BD6867D5D00F68ULL, (u64bit) 0x1A681AD07234CA1AULL, (u64bit) 0xAE82AE192C41B7AEULL,
+(u64bit) 0xB4EAB4C95E757DB4ULL, (u64bit) 0x544D549A19A8CE54ULL, (u64bit) 0x937693ECE53B7F93ULL, (u64bit) 0x2288220DAA442F22ULL,
+(u64bit) 0x648D6407E9C86364ULL, (u64bit) 0xF1E3F1DB12FF2AF1ULL, (u64bit) 0x73D173BFA2E6CC73ULL, (u64bit) 0x124812905A248212ULL,
+(u64bit) 0x401D403A5D807A40ULL, (u64bit) 0x0820084028104808ULL, (u64bit) 0xC32BC356E89B95C3ULL, (u64bit) 0xEC97EC337BC5DFECULL,
+(u64bit) 0xDB4BDB9690AB4DDBULL, (u64bit) 0xA1BEA1611F5FC0A1ULL, (u64bit) 0x8D0E8D1C8307918DULL, (u64bit) 0x3DF43DF5C97AC83DULL,
+(u64bit) 0x976697CCF1335B97ULL, (u64bit) 0x0000000000000000ULL, (u64bit) 0xCF1BCF36D483F9CFULL, (u64bit) 0x2BAC2B4587566E2BULL,
+(u64bit) 0x76C57697B3ECE176ULL, (u64bit) 0x82328264B019E682ULL, (u64bit) 0xD67FD6FEA9B128D6ULL, (u64bit) 0x1B6C1BD87736C31BULL,
+(u64bit) 0xB5EEB5C15B7774B5ULL, (u64bit) 0xAF86AF112943BEAFULL, (u64bit) 0x6AB56A77DFD41D6AULL, (u64bit) 0x505D50BA0DA0EA50ULL,
+(u64bit) 0x450945124C8A5745ULL, (u64bit) 0xF3EBF3CB18FB38F3ULL, (u64bit) 0x30C0309DF060AD30ULL, (u64bit) 0xEF9BEF2B74C3C4EFULL,
+(u64bit) 0x3FFC3FE5C37EDA3FULL, (u64bit) 0x554955921CAAC755ULL, (u64bit) 0xA2B2A2791059DBA2ULL, (u64bit) 0xEA8FEA0365C9E9EAULL,
+(u64bit) 0x6589650FECCA6A65ULL, (u64bit) 0xBAD2BAB9686903BAULL, (u64bit) 0x2FBC2F65935E4A2FULL, (u64bit) 0xC027C04EE79D8EC0ULL,
+(u64bit) 0xDE5FDEBE81A160DEULL, (u64bit) 0x1C701CE06C38FC1CULL, (u64bit) 0xFDD3FDBB2EE746FDULL, (u64bit) 0x4D294D52649A1F4DULL,
+(u64bit) 0x927292E4E0397692ULL, (u64bit) 0x75C9758FBCEAFA75ULL, (u64bit) 0x061806301E0C3606ULL, (u64bit) 0x8A128A249809AE8AULL,
+(u64bit) 0xB2F2B2F940794BB2ULL, (u64bit) 0xE6BFE66359D185E6ULL, (u64bit) 0x0E380E70361C7E0EULL, (u64bit) 0x1F7C1FF8633EE71FULL,
+(u64bit) 0x62956237F7C45562ULL, (u64bit) 0xD477D4EEA3B53AD4ULL, (u64bit) 0xA89AA829324D81A8ULL, (u64bit) 0x966296C4F4315296ULL,
+(u64bit) 0xF9C3F99B3AEF62F9ULL, (u64bit) 0xC533C566F697A3C5ULL, (u64bit) 0x25942535B14A1025ULL, (u64bit) 0x597959F220B2AB59ULL,
+(u64bit) 0x842A8454AE15D084ULL, (u64bit) 0x72D572B7A7E4C572ULL, (u64bit) 0x39E439D5DD72EC39ULL, (u64bit) 0x4C2D4C5A6198164CULL,
+(u64bit) 0x5E655ECA3BBC945EULL, (u64bit) 0x78FD78E785F09F78ULL, (u64bit) 0x38E038DDD870E538ULL, (u64bit) 0x8C0A8C148605988CULL,
+(u64bit) 0xD163D1C6B2BF17D1ULL, (u64bit) 0xA5AEA5410B57E4A5ULL, (u64bit) 0xE2AFE2434DD9A1E2ULL, (u64bit) 0x6199612FF8C24E61ULL,
+(u64bit) 0xB3F6B3F1457B42B3ULL, (u64bit) 0x21842115A5423421ULL, (u64bit) 0x9C4A9C94D625089CULL, (u64bit) 0x1E781EF0663CEE1EULL,
+(u64bit) 0x4311432252866143ULL, (u64bit) 0xC73BC776FC93B1C7ULL, (u64bit) 0xFCD7FCB32BE54FFCULL, (u64bit) 0x0410042014082404ULL,
+(u64bit) 0x515951B208A2E351ULL, (u64bit) 0x995E99BCC72F2599ULL, (u64bit) 0x6DA96D4FC4DA226DULL, (u64bit) 0x0D340D68391A650DULL,
+(u64bit) 0xFACFFA8335E979FAULL, (u64bit) 0xDF5BDFB684A369DFULL, (u64bit) 0x7EE57ED79BFCA97EULL, (u64bit) 0x2490243DB4481924ULL,
+(u64bit) 0x3BEC3BC5D776FE3BULL, (u64bit) 0xAB96AB313D4B9AABULL, (u64bit) 0xCE1FCE3ED181F0CEULL, (u64bit) 0x1144118855229911ULL,
+(u64bit) 0x8F068F0C8903838FULL, (u64bit) 0x4E254E4A6B9C044EULL, (u64bit) 0xB7E6B7D1517366B7ULL, (u64bit) 0xEB8BEB0B60CBE0EBULL,
+(u64bit) 0x3CF03CFDCC78C13CULL, (u64bit) 0x813E817CBF1FFD81ULL, (u64bit) 0x946A94D4FE354094ULL, (u64bit) 0xF7FBF7EB0CF31CF7ULL,
+(u64bit) 0xB9DEB9A1676F18B9ULL, (u64bit) 0x134C13985F268B13ULL, (u64bit) 0x2CB02C7D9C58512CULL, (u64bit) 0xD36BD3D6B8BB05D3ULL,
+(u64bit) 0xE7BBE76B5CD38CE7ULL, (u64bit) 0x6EA56E57CBDC396EULL, (u64bit) 0xC437C46EF395AAC4ULL, (u64bit) 0x030C03180F061B03ULL,
+(u64bit) 0x5645568A13ACDC56ULL, (u64bit) 0x440D441A49885E44ULL, (u64bit) 0x7FE17FDF9EFEA07FULL, (u64bit) 0xA99EA921374F88A9ULL,
+(u64bit) 0x2AA82A4D8254672AULL, (u64bit) 0xBBD6BBB16D6B0ABBULL, (u64bit) 0xC123C146E29F87C1ULL, (u64bit) 0x535153A202A6F153ULL,
+(u64bit) 0xDC57DCAE8BA572DCULL, (u64bit) 0x0B2C0B582716530BULL, (u64bit) 0x9D4E9D9CD327019DULL, (u64bit) 0x6CAD6C47C1D82B6CULL,
+(u64bit) 0x31C43195F562A431ULL, (u64bit) 0x74CD7487B9E8F374ULL, (u64bit) 0xF6FFF6E309F115F6ULL, (u64bit) 0x4605460A438C4C46ULL,
+(u64bit) 0xAC8AAC092645A5ACULL, (u64bit) 0x891E893C970FB589ULL, (u64bit) 0x145014A04428B414ULL, (u64bit) 0xE1A3E15B42DFBAE1ULL,
+(u64bit) 0x165816B04E2CA616ULL, (u64bit) 0x3AE83ACDD274F73AULL, (u64bit) 0x69B9696FD0D20669ULL, (u64bit) 0x092409482D124109ULL,
+(u64bit) 0x70DD70A7ADE0D770ULL, (u64bit) 0xB6E2B6D954716FB6ULL, (u64bit) 0xD067D0CEB7BD1ED0ULL, (u64bit) 0xED93ED3B7EC7D6EDULL,
+(u64bit) 0xCC17CC2EDB85E2CCULL, (u64bit) 0x4215422A57846842ULL, (u64bit) 0x985A98B4C22D2C98ULL, (u64bit) 0xA4AAA4490E55EDA4ULL,
+(u64bit) 0x28A0285D88507528ULL, (u64bit) 0x5C6D5CDA31B8865CULL, (u64bit) 0xF8C7F8933FED6BF8ULL, (u64bit) 0x86228644A411C286ULL };
+
+}
diff --git a/botan/src/hash/whirlpool/whrlpool.cpp b/botan/src/hash/whirlpool/whrlpool.cpp
new file mode 100644
index 0000000..53c057b
--- /dev/null
+++ b/botan/src/hash/whirlpool/whrlpool.cpp
@@ -0,0 +1,146 @@
+/*
+* Whirlpool
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/whrlpool.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Whirlpool Compression Function
+*/
+void Whirlpool::compress_n(const byte in[], u32bit blocks)
+ {
+ static const u64bit RC[10] = {
+ (u64bit) 0x1823C6E887B8014FULL, (u64bit) 0x36A6D2F5796F9152ULL,
+ (u64bit) 0x60BC9B8EA30C7B35ULL, (u64bit) 0x1DE0D7C22E4BFE57ULL,
+ (u64bit) 0x157737E59FF04ADAULL, (u64bit) 0x58C9290AB1A06B85ULL,
+ (u64bit) 0xBD5D10F4CB3E0567ULL, (u64bit) 0xE427418BA77D95D8ULL,
+ (u64bit) 0xFBEE7C66DD17479EULL, (u64bit) 0xCA2DBF07AD5A8333ULL
+ };
+
+ for(u32bit i = 0; i != blocks; ++i)
+ {
+ for(u32bit j = 0; j != 8; ++j)
+ M[j] = load_be<u64bit>(in, j);
+ in += HASH_BLOCK_SIZE;
+
+ u64bit K0, K1, K2, K3, K4, K5, K6, K7;
+ K0 = digest[0]; K1 = digest[1]; K2 = digest[2]; K3 = digest[3];
+ K4 = digest[4]; K5 = digest[5]; K6 = digest[6]; K7 = digest[7];
+
+ u64bit B0, B1, B2, B3, B4, B5, B6, B7;
+ B0 = K0 ^ M[0]; B1 = K1 ^ M[1]; B2 = K2 ^ M[2]; B3 = K3 ^ M[3];
+ B4 = K4 ^ M[4]; B5 = K5 ^ M[5]; B6 = K6 ^ M[6]; B7 = K7 ^ M[7];
+
+ for(u32bit j = 0; j != 10; ++j)
+ {
+ u64bit T0, T1, T2, T3, T4, T5, T6, T7;
+ T0 = C0[get_byte(0, K0)] ^ C1[get_byte(1, K7)] ^
+ C2[get_byte(2, K6)] ^ C3[get_byte(3, K5)] ^
+ C4[get_byte(4, K4)] ^ C5[get_byte(5, K3)] ^
+ C6[get_byte(6, K2)] ^ C7[get_byte(7, K1)] ^ RC[j];
+ T1 = C0[get_byte(0, K1)] ^ C1[get_byte(1, K0)] ^
+ C2[get_byte(2, K7)] ^ C3[get_byte(3, K6)] ^
+ C4[get_byte(4, K5)] ^ C5[get_byte(5, K4)] ^
+ C6[get_byte(6, K3)] ^ C7[get_byte(7, K2)];
+ T2 = C0[get_byte(0, K2)] ^ C1[get_byte(1, K1)] ^
+ C2[get_byte(2, K0)] ^ C3[get_byte(3, K7)] ^
+ C4[get_byte(4, K6)] ^ C5[get_byte(5, K5)] ^
+ C6[get_byte(6, K4)] ^ C7[get_byte(7, K3)];
+ T3 = C0[get_byte(0, K3)] ^ C1[get_byte(1, K2)] ^
+ C2[get_byte(2, K1)] ^ C3[get_byte(3, K0)] ^
+ C4[get_byte(4, K7)] ^ C5[get_byte(5, K6)] ^
+ C6[get_byte(6, K5)] ^ C7[get_byte(7, K4)];
+ T4 = C0[get_byte(0, K4)] ^ C1[get_byte(1, K3)] ^
+ C2[get_byte(2, K2)] ^ C3[get_byte(3, K1)] ^
+ C4[get_byte(4, K0)] ^ C5[get_byte(5, K7)] ^
+ C6[get_byte(6, K6)] ^ C7[get_byte(7, K5)];
+ T5 = C0[get_byte(0, K5)] ^ C1[get_byte(1, K4)] ^
+ C2[get_byte(2, K3)] ^ C3[get_byte(3, K2)] ^
+ C4[get_byte(4, K1)] ^ C5[get_byte(5, K0)] ^
+ C6[get_byte(6, K7)] ^ C7[get_byte(7, K6)];
+ T6 = C0[get_byte(0, K6)] ^ C1[get_byte(1, K5)] ^
+ C2[get_byte(2, K4)] ^ C3[get_byte(3, K3)] ^
+ C4[get_byte(4, K2)] ^ C5[get_byte(5, K1)] ^
+ C6[get_byte(6, K0)] ^ C7[get_byte(7, K7)];
+ T7 = C0[get_byte(0, K7)] ^ C1[get_byte(1, K6)] ^
+ C2[get_byte(2, K5)] ^ C3[get_byte(3, K4)] ^
+ C4[get_byte(4, K3)] ^ C5[get_byte(5, K2)] ^
+ C6[get_byte(6, K1)] ^ C7[get_byte(7, K0)];
+
+ K0 = T0; K1 = T1; K2 = T2; K3 = T3;
+ K4 = T4; K5 = T5; K6 = T6; K7 = T7;
+
+ T0 = C0[get_byte(0, B0)] ^ C1[get_byte(1, B7)] ^
+ C2[get_byte(2, B6)] ^ C3[get_byte(3, B5)] ^
+ C4[get_byte(4, B4)] ^ C5[get_byte(5, B3)] ^
+ C6[get_byte(6, B2)] ^ C7[get_byte(7, B1)] ^ K0;
+ T1 = C0[get_byte(0, B1)] ^ C1[get_byte(1, B0)] ^
+ C2[get_byte(2, B7)] ^ C3[get_byte(3, B6)] ^
+ C4[get_byte(4, B5)] ^ C5[get_byte(5, B4)] ^
+ C6[get_byte(6, B3)] ^ C7[get_byte(7, B2)] ^ K1;
+ T2 = C0[get_byte(0, B2)] ^ C1[get_byte(1, B1)] ^
+ C2[get_byte(2, B0)] ^ C3[get_byte(3, B7)] ^
+ C4[get_byte(4, B6)] ^ C5[get_byte(5, B5)] ^
+ C6[get_byte(6, B4)] ^ C7[get_byte(7, B3)] ^ K2;
+ T3 = C0[get_byte(0, B3)] ^ C1[get_byte(1, B2)] ^
+ C2[get_byte(2, B1)] ^ C3[get_byte(3, B0)] ^
+ C4[get_byte(4, B7)] ^ C5[get_byte(5, B6)] ^
+ C6[get_byte(6, B5)] ^ C7[get_byte(7, B4)] ^ K3;
+ T4 = C0[get_byte(0, B4)] ^ C1[get_byte(1, B3)] ^
+ C2[get_byte(2, B2)] ^ C3[get_byte(3, B1)] ^
+ C4[get_byte(4, B0)] ^ C5[get_byte(5, B7)] ^
+ C6[get_byte(6, B6)] ^ C7[get_byte(7, B5)] ^ K4;
+ T5 = C0[get_byte(0, B5)] ^ C1[get_byte(1, B4)] ^
+ C2[get_byte(2, B3)] ^ C3[get_byte(3, B2)] ^
+ C4[get_byte(4, B1)] ^ C5[get_byte(5, B0)] ^
+ C6[get_byte(6, B7)] ^ C7[get_byte(7, B6)] ^ K5;
+ T6 = C0[get_byte(0, B6)] ^ C1[get_byte(1, B5)] ^
+ C2[get_byte(2, B4)] ^ C3[get_byte(3, B3)] ^
+ C4[get_byte(4, B2)] ^ C5[get_byte(5, B1)] ^
+ C6[get_byte(6, B0)] ^ C7[get_byte(7, B7)] ^ K6;
+ T7 = C0[get_byte(0, B7)] ^ C1[get_byte(1, B6)] ^
+ C2[get_byte(2, B5)] ^ C3[get_byte(3, B4)] ^
+ C4[get_byte(4, B3)] ^ C5[get_byte(5, B2)] ^
+ C6[get_byte(6, B1)] ^ C7[get_byte(7, B0)] ^ K7;
+
+ B0 = T0; B1 = T1; B2 = T2; B3 = T3;
+ B4 = T4; B5 = T5; B6 = T6; B7 = T7;
+ }
+
+ digest[0] ^= B0 ^ M[0];
+ digest[1] ^= B1 ^ M[1];
+ digest[2] ^= B2 ^ M[2];
+ digest[3] ^= B3 ^ M[3];
+ digest[4] ^= B4 ^ M[4];
+ digest[5] ^= B5 ^ M[5];
+ digest[6] ^= B6 ^ M[6];
+ digest[7] ^= B7 ^ M[7];
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void Whirlpool::copy_out(byte output[])
+ {
+ for(u32bit j = 0; j != OUTPUT_LENGTH; j += 8)
+ store_be(digest[j/8], output + j);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Whirlpool::clear() throw()
+ {
+ MDx_HashFunction::clear();
+ M.clear();
+ digest.clear();
+ }
+
+}
diff --git a/botan/src/hash/whirlpool/whrlpool.h b/botan/src/hash/whirlpool/whrlpool.h
new file mode 100644
index 0000000..b72ff60
--- /dev/null
+++ b/botan/src/hash/whirlpool/whrlpool.h
@@ -0,0 +1,42 @@
+/*
+* Whirlpool
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WHIRLPOOL_H__
+#define BOTAN_WHIRLPOOL_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+/*
+* Whirlpool
+*/
+class BOTAN_DLL Whirlpool : public MDx_HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Whirlpool"; }
+ HashFunction* clone() const { return new Whirlpool; }
+ Whirlpool() : MDx_HashFunction(64, 64, true, true, 32) { clear(); }
+ private:
+ void compress_n(const byte[], u32bit blocks);
+ void copy_out(byte[]);
+
+ static const u64bit C0[256];
+ static const u64bit C1[256];
+ static const u64bit C2[256];
+ static const u64bit C3[256];
+ static const u64bit C4[256];
+ static const u64bit C5[256];
+ static const u64bit C6[256];
+ static const u64bit C7[256];
+ SecureBuffer<u64bit, 8> M, digest;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/info.txt b/botan/src/kdf/info.txt
new file mode 100644
index 0000000..1965a20
--- /dev/null
+++ b/botan/src/kdf/info.txt
@@ -0,0 +1,14 @@
+realname "KDF Base Class"
+
+define KDF_BASE
+
+load_on auto
+
+<add>
+kdf.cpp
+kdf.h
+</add>
+
+<requires>
+alloc
+</requires>
diff --git a/botan/src/kdf/kdf.cpp b/botan/src/kdf/kdf.cpp
new file mode 100644
index 0000000..4be8475
--- /dev/null
+++ b/botan/src/kdf/kdf.cpp
@@ -0,0 +1,68 @@
+/*
+* KDF Base Class
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* Derive a key
+*/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret.size(),
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt, salt_len);
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const MemoryRegion<byte>& salt) const
+ {
+ return derive_key(key_len, secret.begin(), secret.size(),
+ salt.begin(), salt.size());
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const std::string& salt) const
+ {
+ return derive_key(key_len, secret, secret_len,
+ reinterpret_cast<const byte*>(salt.data()),
+ salt.length());
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> KDF::derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const
+ {
+ return derive(key_len, secret, secret_len, salt, salt_len);
+ }
+
+}
diff --git a/botan/src/kdf/kdf.h b/botan/src/kdf/kdf.h
new file mode 100644
index 0000000..70f636b
--- /dev/null
+++ b/botan/src/kdf/kdf.h
@@ -0,0 +1,60 @@
+/*
+* KDF/MGF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF_BASE_H__
+#define BOTAN_KDF_BASE_H__
+
+#include <botan/secmem.h>
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Key Derivation Function
+*/
+class BOTAN_DLL KDF
+ {
+ public:
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const std::string& salt = "") const;
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const MemoryRegion<byte>& salt) const;
+
+ SecureVector<byte> derive_key(u32bit key_len,
+ const MemoryRegion<byte>& secret,
+ const byte salt[], u32bit salt_len) const;
+
+ SecureVector<byte> derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const std::string& salt = "") const;
+ SecureVector<byte> derive_key(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const;
+
+ virtual ~KDF() {}
+ private:
+ virtual SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ };
+
+/*
+* Mask Generation Function
+*/
+class BOTAN_DLL MGF
+ {
+ public:
+ virtual void mask(const byte in[], u32bit in_len,
+ byte out[], u32bit out_len) const = 0;
+
+ virtual ~MGF() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/kdf1/info.txt b/botan/src/kdf/kdf1/info.txt
new file mode 100644
index 0000000..ede1001
--- /dev/null
+++ b/botan/src/kdf/kdf1/info.txt
@@ -0,0 +1,14 @@
+realname "KDF1"
+
+define KDF1
+
+load_on auto
+
+<add>
+kdf1.h
+kdf1.cpp
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/kdf/kdf1/kdf1.cpp b/botan/src/kdf/kdf1/kdf1.cpp
new file mode 100644
index 0000000..539d9ed
--- /dev/null
+++ b/botan/src/kdf/kdf1/kdf1.cpp
@@ -0,0 +1,24 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kdf1.h>
+
+namespace Botan {
+
+/*
+* KDF1 Key Derivation Mechanism
+*/
+SecureVector<byte> KDF1::derive(u32bit,
+ const byte secret[], u32bit secret_len,
+ const byte P[], u32bit P_len) const
+ {
+ hash->update(secret, secret_len);
+ hash->update(P, P_len);
+ return hash->final();
+ }
+
+}
diff --git a/botan/src/kdf/kdf1/kdf1.h b/botan/src/kdf/kdf1/kdf1.h
new file mode 100644
index 0000000..d657ccc
--- /dev/null
+++ b/botan/src/kdf/kdf1/kdf1.h
@@ -0,0 +1,36 @@
+/*
+* KDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF1_H__
+#define BOTAN_KDF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* KDF1
+*/
+class BOTAN_DLL KDF1 : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit,
+ const byte secret[], u32bit secret_len,
+ const byte P[], u32bit P_len) const;
+
+ KDF1(HashFunction* h) : hash(h) {}
+ KDF1(const KDF1& other) : KDF(), hash(other.hash->clone()) {}
+
+ ~KDF1() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/kdf2/info.txt b/botan/src/kdf/kdf2/info.txt
new file mode 100644
index 0000000..1858f89
--- /dev/null
+++ b/botan/src/kdf/kdf2/info.txt
@@ -0,0 +1,14 @@
+realname "KDF2"
+
+define KDF2
+
+load_on auto
+
+<add>
+kdf2.cpp
+kdf2.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/kdf/kdf2/kdf2.cpp b/botan/src/kdf/kdf2/kdf2.cpp
new file mode 100644
index 0000000..167f644
--- /dev/null
+++ b/botan/src/kdf/kdf2/kdf2.cpp
@@ -0,0 +1,41 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/kdf2.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* KDF2 Key Derivation Mechanism
+*/
+SecureVector<byte> KDF2::derive(u32bit out_len,
+ const byte secret[], u32bit secret_len,
+ const byte P[], u32bit P_len) const
+ {
+ SecureVector<byte> output;
+ u32bit counter = 1;
+
+ while(out_len && counter)
+ {
+ hash->update(secret, secret_len);
+ for(u32bit j = 0; j != 4; ++j)
+ hash->update(get_byte(j, counter));
+ hash->update(P, P_len);
+ SecureVector<byte> hash_result = hash->final();
+
+ u32bit added = std::min(hash_result.size(), out_len);
+ output.append(hash_result, added);
+ out_len -= added;
+
+ ++counter;
+ }
+
+ return output;
+ }
+
+}
diff --git a/botan/src/kdf/kdf2/kdf2.h b/botan/src/kdf/kdf2/kdf2.h
new file mode 100644
index 0000000..f748bed
--- /dev/null
+++ b/botan/src/kdf/kdf2/kdf2.h
@@ -0,0 +1,34 @@
+/*
+* KDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KDF2_H__
+#define BOTAN_KDF2_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* KDF2
+*/
+class BOTAN_DLL KDF2 : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ KDF2(HashFunction* h) : hash(h) {}
+ KDF2(const KDF2& other) : KDF(), hash(other.hash->clone()) {}
+ ~KDF2() { delete hash; }
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/mgf1/info.txt b/botan/src/kdf/mgf1/info.txt
new file mode 100644
index 0000000..f9e952f
--- /dev/null
+++ b/botan/src/kdf/mgf1/info.txt
@@ -0,0 +1,14 @@
+realname "MGF1"
+
+define MGF1
+
+load_on dep
+
+<add>
+mgf1.h
+mgf1.cpp
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/kdf/mgf1/mgf1.cpp b/botan/src/kdf/mgf1/mgf1.cpp
new file mode 100644
index 0000000..a26e33a
--- /dev/null
+++ b/botan/src/kdf/mgf1/mgf1.cpp
@@ -0,0 +1,58 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mgf1.h>
+#include <botan/loadstor.h>
+#include <botan/exceptn.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*
+* MGF1 Mask Generation Function
+*/
+void MGF1::mask(const byte in[], u32bit in_len, byte out[],
+ u32bit out_len) const
+ {
+ u32bit counter = 0;
+
+ while(out_len)
+ {
+ hash->update(in, in_len);
+ for(u32bit j = 0; j != 4; ++j)
+ hash->update(get_byte(j, counter));
+ SecureVector<byte> buffer = hash->final();
+
+ u32bit xored = std::min(buffer.size(), out_len);
+ xor_buf(out, buffer.begin(), xored);
+ out += xored;
+ out_len -= xored;
+
+ ++counter;
+ }
+ }
+
+/*
+* MGF1 Constructor
+*/
+MGF1::MGF1(HashFunction* h) : hash(h)
+ {
+ if(!hash)
+ throw Invalid_Argument("MGF1 given null hash object");
+ }
+
+/*
+* MGF1 Destructor
+*/
+MGF1::~MGF1()
+ {
+ delete hash;
+ }
+
+}
diff --git a/botan/src/kdf/mgf1/mgf1.h b/botan/src/kdf/mgf1/mgf1.h
new file mode 100644
index 0000000..799ba7e
--- /dev/null
+++ b/botan/src/kdf/mgf1/mgf1.h
@@ -0,0 +1,36 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MGF1_H__
+#define BOTAN_MGF1_H__
+
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* MGF1 (Mask Generation Function)
+*/
+class BOTAN_DLL MGF1 : public MGF
+ {
+ public:
+ void mask(const byte[], u32bit, byte[], u32bit) const;
+
+ /**
+ MGF1 constructor: takes ownership of hash
+ */
+ MGF1(HashFunction* hash);
+
+ ~MGF1();
+ private:
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/ssl_prf/info.txt b/botan/src/kdf/ssl_prf/info.txt
new file mode 100644
index 0000000..f862905
--- /dev/null
+++ b/botan/src/kdf/ssl_prf/info.txt
@@ -0,0 +1,16 @@
+realname "SSLv3 PRF"
+
+define SSL_V3_PRF
+
+load_on auto
+
+<add>
+prf_ssl3.h
+prf_ssl3.cpp
+</add>
+
+<requires>
+md5
+sha1
+sym_algo
+</requires>
diff --git a/botan/src/kdf/ssl_prf/prf_ssl3.cpp b/botan/src/kdf/ssl_prf/prf_ssl3.cpp
new file mode 100644
index 0000000..2b67644
--- /dev/null
+++ b/botan/src/kdf/ssl_prf/prf_ssl3.cpp
@@ -0,0 +1,76 @@
+/*
+* SSLv3 PRF
+* (C) 2004-2006 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_ssl3.h>
+#include <botan/symkey.h>
+#include <botan/exceptn.h>
+#include <botan/sha160.h>
+#include <botan/md5.h>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Return the next inner hash
+*/
+OctetString next_hash(u32bit where, u32bit want,
+ HashFunction& md5, HashFunction& sha1,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len)
+ {
+ if(want > md5.OUTPUT_LENGTH)
+ throw Internal_Error("SSL3_PRF:next_hash: want is too big");
+
+ const byte ASCII_A_CHAR = 0x41;
+
+ for(u32bit j = 0; j != where + 1; j++)
+ sha1.update(ASCII_A_CHAR + where);
+ sha1.update(secret, secret_len);
+ sha1.update(seed, seed_len);
+ SecureVector<byte> sha1_hash = sha1.final();
+
+ md5.update(secret, secret_len);
+ md5.update(sha1_hash);
+ SecureVector<byte> md5_hash = md5.final();
+
+ return OctetString(md5_hash, want);
+ }
+
+}
+
+/*
+* SSL3 PRF
+*/
+SecureVector<byte> SSL3_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ if(key_len > 416)
+ throw Internal_Error("SSL3_PRF: Requested key length is too large");
+
+ MD5 md5;
+ SHA_160 sha1;
+
+ OctetString output;
+
+ int counter = 0;
+ while(key_len)
+ {
+ const u32bit produce = std::min(key_len, md5.OUTPUT_LENGTH);
+
+ output = output + next_hash(counter++, produce, md5, sha1,
+ secret, secret_len, seed, seed_len);
+
+ key_len -= produce;
+ }
+
+ return output.bits_of();
+ }
+
+}
diff --git a/botan/src/kdf/ssl_prf/prf_ssl3.h b/botan/src/kdf/ssl_prf/prf_ssl3.h
new file mode 100644
index 0000000..165fc7c
--- /dev/null
+++ b/botan/src/kdf/ssl_prf/prf_ssl3.h
@@ -0,0 +1,27 @@
+/*
+* SSLv3 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSLV3_PRF_H__
+#define BOTAN_SSLV3_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* SSL3 PRF
+*/
+class BOTAN_DLL SSL3_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/tls_prf/info.txt b/botan/src/kdf/tls_prf/info.txt
new file mode 100644
index 0000000..f95ef9c
--- /dev/null
+++ b/botan/src/kdf/tls_prf/info.txt
@@ -0,0 +1,17 @@
+realname "TLS v1.0 PRF"
+
+define TLS_V10_PRF
+
+load_on auto
+
+<add>
+prf_tls.h
+prf_tls.cpp
+</add>
+
+<requires>
+hmac
+mac
+md5
+sha1
+</requires>
diff --git a/botan/src/kdf/tls_prf/prf_tls.cpp b/botan/src/kdf/tls_prf/prf_tls.cpp
new file mode 100644
index 0000000..7c638b9
--- /dev/null
+++ b/botan/src/kdf/tls_prf/prf_tls.cpp
@@ -0,0 +1,85 @@
+/*
+* TLS PRF
+* (C) 2004-2006 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_tls.h>
+#include <botan/xor_buf.h>
+#include <botan/hmac.h>
+#include <botan/md5.h>
+#include <botan/sha160.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* TLS PRF P_hash function
+*/
+SecureVector<byte> P_hash(MessageAuthenticationCode* mac,
+ u32bit len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len)
+ {
+ SecureVector<byte> out;
+
+ mac->set_key(secret, secret_len);
+
+ SecureVector<byte> A(seed, seed_len);
+ while(len)
+ {
+ const u32bit this_block_len = std::min(mac->OUTPUT_LENGTH, len);
+
+ A = mac->process(A);
+
+ mac->update(A);
+ mac->update(seed, seed_len);
+ SecureVector<byte> block = mac->final();
+
+ out.append(block, this_block_len);
+ len -= this_block_len;
+ }
+ return out;
+ }
+
+}
+
+/*
+* TLS PRF Constructor and Destructor
+*/
+TLS_PRF::TLS_PRF()
+ {
+ hmac_md5 = new HMAC(new MD5);
+ hmac_sha1 = new HMAC(new SHA_160);
+ }
+
+TLS_PRF::~TLS_PRF()
+ {
+ delete hmac_md5;
+ delete hmac_sha1;
+ }
+
+/*
+* TLS PRF
+*/
+SecureVector<byte> TLS_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte seed[], u32bit seed_len) const
+ {
+ u32bit S1_len = (secret_len + 1) / 2,
+ S2_len = (secret_len + 1) / 2;
+ const byte* S1 = secret;
+ const byte* S2 = secret + (secret_len - S2_len);
+
+ SecureVector<byte> key1, key2;
+ key1 = P_hash(hmac_md5, key_len, S1, S1_len, seed, seed_len);
+ key2 = P_hash(hmac_sha1, key_len, S2, S2_len, seed, seed_len);
+
+ xor_buf(key1.begin(), key2.begin(), key2.size());
+
+ return key1;
+ }
+
+}
diff --git a/botan/src/kdf/tls_prf/prf_tls.h b/botan/src/kdf/tls_prf/prf_tls.h
new file mode 100644
index 0000000..d212795
--- /dev/null
+++ b/botan/src/kdf/tls_prf/prf_tls.h
@@ -0,0 +1,34 @@
+/*
+* TLS v1.0 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TLS_PRF_H__
+#define BOTAN_TLS_PRF_H__
+
+#include <botan/kdf.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* TLS PRF
+*/
+class BOTAN_DLL TLS_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ TLS_PRF();
+ ~TLS_PRF();
+ private:
+ MessageAuthenticationCode* hmac_md5;
+ MessageAuthenticationCode* hmac_sha1;
+ };
+
+}
+
+#endif
diff --git a/botan/src/kdf/x942_prf/info.txt b/botan/src/kdf/x942_prf/info.txt
new file mode 100644
index 0000000..295c2cd
--- /dev/null
+++ b/botan/src/kdf/x942_prf/info.txt
@@ -0,0 +1,16 @@
+realname "X942 PRF"
+
+define X942_PRF
+
+load_on auto
+
+<add>
+prf_x942.cpp
+prf_x942.h
+</add>
+
+<requires>
+asn1
+oid_lookup
+sha1
+</requires>
diff --git a/botan/src/kdf/x942_prf/prf_x942.cpp b/botan/src/kdf/x942_prf/prf_x942.cpp
new file mode 100644
index 0000000..d9ee09d
--- /dev/null
+++ b/botan/src/kdf/x942_prf/prf_x942.cpp
@@ -0,0 +1,91 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/prf_x942.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/sha160.h>
+#include <botan/loadstor.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Encode an integer as an OCTET STRING
+*/
+MemoryVector<byte> encode_x942_int(u32bit n)
+ {
+ byte n_buf[4] = { 0 };
+ store_be(n, n_buf);
+ return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents();
+ }
+
+}
+
+/*
+* X9.42 PRF
+*/
+SecureVector<byte> X942_PRF::derive(u32bit key_len,
+ const byte secret[], u32bit secret_len,
+ const byte salt[], u32bit salt_len) const
+ {
+ SHA_160 hash;
+ const OID kek_algo(key_wrap_oid);
+
+ SecureVector<byte> key;
+ u32bit counter = 1;
+
+ while(key.size() != key_len && counter)
+ {
+ hash.update(secret, secret_len);
+
+ hash.update(
+ DER_Encoder().start_cons(SEQUENCE)
+
+ .start_cons(SEQUENCE)
+ .encode(kek_algo)
+ .raw_bytes(encode_x942_int(counter))
+ .end_cons()
+
+ .encode_if(salt_len != 0,
+ DER_Encoder()
+ .start_explicit(0)
+ .encode(salt, salt_len, OCTET_STRING)
+ .end_explicit()
+ )
+
+ .start_explicit(2)
+ .raw_bytes(encode_x942_int(8 * key_len))
+ .end_explicit()
+
+ .end_cons().get_contents()
+ );
+
+ SecureVector<byte> digest = hash.final();
+ key.append(digest, std::min(digest.size(), key_len - key.size()));
+
+ ++counter;
+ }
+
+ return key;
+ }
+
+/*
+* X9.42 Constructor
+*/
+X942_PRF::X942_PRF(const std::string& oid)
+ {
+ if(OIDS::have_oid(oid))
+ key_wrap_oid = OIDS::lookup(oid).as_string();
+ else
+ key_wrap_oid = oid;
+ }
+
+}
diff --git a/botan/src/kdf/x942_prf/prf_x942.h b/botan/src/kdf/x942_prf/prf_x942.h
new file mode 100644
index 0000000..f957566
--- /dev/null
+++ b/botan/src/kdf/x942_prf/prf_x942.h
@@ -0,0 +1,31 @@
+/*
+* X9.42 PRF
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X942_PRF_H__
+#define BOTAN_ANSI_X942_PRF_H__
+
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* X9.42 PRF
+*/
+class BOTAN_DLL X942_PRF : public KDF
+ {
+ public:
+ SecureVector<byte> derive(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ X942_PRF(const std::string&);
+ private:
+ std::string key_wrap_oid;
+ };
+
+}
+
+#endif
diff --git a/botan/src/libstate/botan.h b/botan/src/libstate/botan.h
new file mode 100644
index 0000000..3fa1312
--- /dev/null
+++ b/botan/src/libstate/botan.h
@@ -0,0 +1,18 @@
+/**
+* A vague catch all include file for Botan
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/init.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/version.h>
+#include <botan/parsing.h>
+
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ #include <botan/auto_rng.h>
+#endif
diff --git a/botan/src/libstate/get_enc.cpp b/botan/src/libstate/get_enc.cpp
new file mode 100644
index 0000000..ab4d158
--- /dev/null
+++ b/botan/src/libstate/get_enc.cpp
@@ -0,0 +1,238 @@
+/*
+* PBKDF/EMSA/EME/KDF/MGF Retrieval
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_PBKDF1)
+ #include <botan/pbkdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ #include <botan/pbkdf2.h>
+ #include <botan/hmac.h>
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ #include <botan/pgp_s2k.h>
+#endif
+
+#if defined(BOTAN_HAS_MGF1)
+ #include <botan/mgf1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA1)
+ #include <botan/emsa1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA1_BSI)
+ #include <botan/emsa1_bsi.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA2)
+ #include <botan/emsa2.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA3)
+ #include <botan/emsa3.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA4)
+ #include <botan/emsa4.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ #include <botan/emsa_raw.h>
+#endif
+
+#if defined(BOTAN_HAS_EME1)
+ #include <botan/eme1.h>
+#endif
+
+#if defined(BOTAN_HAS_EME_PKCS1v15)
+ #include <botan/eme_pkcs.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF1)
+ #include <botan/kdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ #include <botan/kdf2.h>
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ #include <botan/prf_x942.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ #include <botan/prf_ssl3.h>
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ #include <botan/prf_tls.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get a S2K algorithm by name
+*/
+S2K* get_s2k(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+#if defined(BOTAN_HAS_PBKDF1)
+ if(request.algo_name() == "PBKDF1" && request.arg_count() == 1)
+ return new PKCS5_PBKDF1(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ if(request.algo_name() == "PBKDF2" && request.arg_count() == 1)
+ return new PKCS5_PBKDF2(new HMAC(af.make_hash_function(request.arg(0))));
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ if(request.algo_name() == "OpenPGP-S2K" && request.arg_count() == 1)
+ return new OpenPGP_S2K(af.make_hash_function(request.arg(0)));
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*
+* Get an EMSA by name
+*/
+EMSA* get_emsa(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ if(request.algo_name() == "Raw" && request.arg_count() == 0)
+ return new EMSA_Raw;
+#endif
+
+#if defined(BOTAN_HAS_EMSA1)
+ if(request.algo_name() == "EMSA1" && request.arg_count() == 1)
+ return new EMSA1(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_EMSA1_BSI)
+ if(request.algo_name() == "EMSA1_BSI" && request.arg_count() == 1)
+ return new EMSA1_BSI(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_EMSA2)
+ if(request.algo_name() == "EMSA2" && request.arg_count() == 1)
+ return new EMSA2(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_EMSA3)
+ if(request.algo_name() == "EMSA3" && request.arg_count() == 1)
+ {
+ if(request.arg(0) == "Raw")
+ return new EMSA3_Raw;
+ return new EMSA3(af.make_hash_function(request.arg(0)));
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA4)
+ if(request.algo_name() == "EMSA4" && request.arg_count_between(1, 3))
+ {
+ // 3 args: Hash, MGF, salt size (MGF is hardcoded MGF1 in Botan)
+ if(request.arg_count() == 1)
+ return new EMSA4(af.make_hash_function(request.arg(0)));
+
+ if(request.arg_count() == 2 && request.arg(1) != "MGF1")
+ return new EMSA4(af.make_hash_function(request.arg(0)));
+
+ if(request.arg_count() == 3)
+ return new EMSA4(af.make_hash_function(request.arg(0)),
+ request.arg_as_u32bit(2, 0));
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*
+* Get an EME by name
+*/
+EME* get_eme(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(request.algo_name() == "Raw")
+ return 0; // No padding
+
+#if defined(BOTAN_HAS_EME_PKCS1v15)
+ if(request.algo_name() == "PKCS1v15" && request.arg_count() == 0)
+ return new EME_PKCS1v15;
+#endif
+
+#if defined(BOTAN_HAS_EME1)
+ if(request.algo_name() == "EME1" && request.arg_count_between(1, 2))
+ {
+ if(request.arg_count() == 1 ||
+ (request.arg_count() == 2 && request.arg(1) == "MGF1"))
+ {
+ return new EME1(af.make_hash_function(request.arg(0)));
+ }
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*
+* Get an KDF by name
+*/
+KDF* get_kdf(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(request.algo_name() == "Raw")
+ return 0; // No KDF
+
+#if defined(BOTAN_HAS_KDF1)
+ if(request.algo_name() == "KDF1" && request.arg_count() == 1)
+ return new KDF1(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_KDF2)
+ if(request.algo_name() == "KDF2" && request.arg_count() == 1)
+ return new KDF2(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_X942_PRF)
+ if(request.algo_name() == "X9.42-PRF" && request.arg_count() == 1)
+ return new X942_PRF(request.arg(0)); // OID
+#endif
+
+#if defined(BOTAN_HAS_TLS_V10_PRF)
+ if(request.algo_name() == "TLS-PRF" && request.arg_count() == 0)
+ return new TLS_PRF;
+#endif
+
+#if defined(BOTAN_HAS_SSL_V3_PRF)
+ if(request.algo_name() == "SSL3-PRF" && request.arg_count() == 0)
+ return new SSL3_PRF;
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+}
diff --git a/botan/src/libstate/info.txt b/botan/src/libstate/info.txt
new file mode 100644
index 0000000..6eaa2f7
--- /dev/null
+++ b/botan/src/libstate/info.txt
@@ -0,0 +1,45 @@
+realname "Botan Libstate Module"
+
+load_on always
+
+define LIBSTATE_MODULE
+
+<add>
+botan.h
+get_enc.cpp
+init.cpp
+init.h
+libstate.cpp
+libstate.h
+look_pk.cpp
+look_pk.h
+lookup.cpp
+lookup.h
+pk_engine.cpp
+pk_engine.h
+policy.cpp
+scan_name.cpp
+scan_name.h
+</add>
+
+<requires>
+algo_factory
+alloc
+bigint
+block
+def_engine
+engine
+filters
+hash
+kdf
+mac
+mode_pad
+mutex
+noop_mutex
+pk_pad
+pubkey
+rng
+s2k
+stream
+system_alloc
+</requires>
diff --git a/botan/src/libstate/init.cpp b/botan/src/libstate/init.cpp
new file mode 100644
index 0000000..b908de6
--- /dev/null
+++ b/botan/src/libstate/init.cpp
@@ -0,0 +1,75 @@
+/**
+* Default Initialization Function
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/init.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+
+namespace Botan {
+
+/*
+* Library Initialization
+*/
+void LibraryInitializer::initialize(const std::string& arg_string)
+ {
+ bool thread_safe = false;
+
+ const std::vector<std::string> arg_list = split_on(arg_string, ' ');
+ for(u32bit j = 0; j != arg_list.size(); ++j)
+ {
+ if(arg_list[j].size() == 0)
+ continue;
+
+ std::string name, value;
+
+ if(arg_list[j].find('=') == std::string::npos)
+ {
+ name = arg_list[j];
+ value = "true";
+ }
+ else
+ {
+ std::vector<std::string> name_and_value = split_on(arg_list[j], '=');
+ name = name_and_value[0];
+ value = name_and_value[1];
+ }
+
+ bool is_on =
+ (value == "1" || value == "true" || value == "yes" || value == "on");
+
+ if(name == "thread_safe")
+ thread_safe = is_on;
+ }
+
+ try
+ {
+ /*
+ This two stage initialization process is because Library_State's
+ constructor will implicitly refer to global state through the
+ allocators and so for, so global_state() has to be a valid
+ reference before initialize() can be called. Yeah, gross.
+ */
+ set_global_state(new Library_State);
+
+ global_state().initialize(thread_safe);
+ }
+ catch(...)
+ {
+ deinitialize();
+ throw;
+ }
+ }
+
+/*
+* Library Shutdown
+*/
+void LibraryInitializer::deinitialize()
+ {
+ set_global_state(0);
+ }
+
+}
diff --git a/botan/src/libstate/init.h b/botan/src/libstate/init.h
new file mode 100644
index 0000000..254f945
--- /dev/null
+++ b/botan/src/libstate/init.h
@@ -0,0 +1,41 @@
+/**
+* Library Initialization
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LIBRARY_INITIALIZER_H__
+#define BOTAN_LIBRARY_INITIALIZER_H__
+
+#include <botan/build.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents the Library Initialization/Shutdown Object. It
+* has to exceed the lifetime of any Botan object used in an
+* application. You can call initialize/deinitialize or use
+* LibraryInitializer in the RAII style.
+*/
+class BOTAN_DLL LibraryInitializer
+ {
+ public:
+ static void initialize(const std::string& options = "");
+
+ static void deinitialize();
+
+ /**
+ * Initialize the library
+ * @param thread_safe if the library should use a thread-safe mutex
+ */
+ LibraryInitializer(const std::string& options = "")
+ { LibraryInitializer::initialize(options); }
+
+ ~LibraryInitializer() { LibraryInitializer::deinitialize(); }
+ };
+
+}
+
+#endif
diff --git a/botan/src/libstate/libstate.cpp b/botan/src/libstate/libstate.cpp
new file mode 100644
index 0000000..3275c64
--- /dev/null
+++ b/botan/src/libstate/libstate.cpp
@@ -0,0 +1,338 @@
+/*
+* Library Internal/Global State
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/libstate.h>
+#include <botan/init.h>
+#include <botan/engine.h>
+#include <botan/stl_util.h>
+#include <botan/mutex.h>
+#include <botan/mux_noop.h>
+#include <botan/charset.h>
+#include <botan/defalloc.h>
+#include <botan/def_eng.h>
+#include <algorithm>
+
+#if defined(BOTAN_HAS_MUTEX_PTHREAD)
+ #include <botan/mux_pthr.h>
+#elif defined(BOTAN_HAS_MUTEX_WIN32)
+ #include <botan/mux_win32.h>
+#elif defined(BOTAN_HAS_MUTEX_QT)
+ #include <botan/mux_qt.h>
+#endif
+
+#if defined(BOTAN_HAS_ALLOC_MMAP)
+ #include <botan/mmap_mem.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_IA32_ASSEMBLER)
+ #include <botan/eng_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_AMD64_ASSEMBLER)
+ #include <botan/eng_amd64.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_SSE2_ASSEMBLER)
+ #include <botan/eng_sse2.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_GNU_MP)
+ #include <botan/eng_gmp.h>
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_OPENSSL)
+ #include <botan/eng_ossl.h>
+#endif
+
+namespace Botan {
+
+/*
+* Botan's global state
+*/
+namespace {
+
+Library_State* global_lib_state = 0;
+
+}
+
+/*
+* Access the global state object
+*/
+Library_State& global_state()
+ {
+ /* Lazy initialization. Botan still needs to be deinitialized later
+ on or memory might leak.
+ */
+ if(!global_lib_state)
+ LibraryInitializer::initialize("thread_safe=true");
+
+ return (*global_lib_state);
+ }
+
+/*
+* Set a new global state object
+*/
+void set_global_state(Library_State* new_state)
+ {
+ delete swap_global_state(new_state);
+ }
+
+/*
+* Swap two global state objects
+*/
+Library_State* swap_global_state(Library_State* new_state)
+ {
+ Library_State* old_state = global_lib_state;
+ global_lib_state = new_state;
+ return old_state;
+ }
+
+/*
+* Get a new mutex object
+*/
+Mutex* Library_State::get_mutex() const
+ {
+ return mutex_factory->make();
+ }
+
+/*
+* Get an allocator by its name
+*/
+Allocator* Library_State::get_allocator(const std::string& type) const
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ if(type != "")
+ return search_map<std::string, Allocator*>(alloc_factory, type, 0);
+
+ if(!cached_default_allocator)
+ {
+ std::string chosen = this->option("base/default_allocator");
+
+ if(chosen == "")
+ chosen = "malloc";
+
+ cached_default_allocator =
+ search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
+ }
+
+ return cached_default_allocator;
+ }
+
+/*
+* Create a new name to object mapping
+*/
+void Library_State::add_allocator(Allocator* allocator)
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ allocator->init();
+
+ allocators.push_back(allocator);
+ alloc_factory[allocator->type()] = allocator;
+ }
+
+/*
+* Set the default allocator type
+*/
+void Library_State::set_default_allocator(const std::string& type)
+ {
+ Mutex_Holder lock(allocator_lock);
+
+ if(type == "")
+ return;
+
+ this->set("conf", "base/default_allocator", type);
+ cached_default_allocator = 0;
+ }
+
+/*
+* Get a configuration value
+*/
+std::string Library_State::get(const std::string& section,
+ const std::string& key) const
+ {
+ Mutex_Holder lock(config_lock);
+
+ return search_map<std::string, std::string>(config,
+ section + "/" + key, "");
+ }
+
+/*
+* See if a particular option has been set
+*/
+bool Library_State::is_set(const std::string& section,
+ const std::string& key) const
+ {
+ Mutex_Holder lock(config_lock);
+
+ return search_map(config, section + "/" + key, false, true);
+ }
+
+/*
+* Set a configuration value
+*/
+void Library_State::set(const std::string& section, const std::string& key,
+ const std::string& value, bool overwrite)
+ {
+ Mutex_Holder lock(config_lock);
+
+ std::string full_key = section + "/" + key;
+
+ std::map<std::string, std::string>::const_iterator i =
+ config.find(full_key);
+
+ if(overwrite || i == config.end() || i->second == "")
+ config[full_key] = value;
+ }
+
+/*
+* Add an alias
+*/
+void Library_State::add_alias(const std::string& key, const std::string& value)
+ {
+ set("alias", key, value);
+ }
+
+/*
+* Dereference an alias to a fixed name
+*/
+std::string Library_State::deref_alias(const std::string& key) const
+ {
+ std::string result = key;
+ while(is_set("alias", result))
+ result = get("alias", result);
+ return result;
+ }
+
+/*
+* Set/Add an option
+*/
+void Library_State::set_option(const std::string key,
+ const std::string& value)
+ {
+ set("conf", key, value);
+ }
+
+/*
+* Get an option value
+*/
+std::string Library_State::option(const std::string& key) const
+ {
+ return get("conf", key);
+ }
+
+/**
+Return a reference to the Algorithm_Factory
+*/
+Algorithm_Factory& Library_State::algorithm_factory()
+ {
+ if(!m_algorithm_factory)
+ throw Invalid_State("Uninitialized in Library_State::algorithm_factory");
+ return *m_algorithm_factory;
+ }
+
+/*
+* Load a set of modules
+*/
+void Library_State::initialize(bool thread_safe)
+ {
+ if(mutex_factory)
+ throw Invalid_State("Library_State has already been initialized");
+
+ if(!thread_safe)
+ {
+ mutex_factory = new Noop_Mutex_Factory;
+ }
+ else
+ {
+#if defined(BOTAN_HAS_MUTEX_PTHREAD)
+ mutex_factory = new Pthread_Mutex_Factory;
+#elif defined(BOTAN_HAS_MUTEX_WIN32)
+ mutex_factory = new Win32_Mutex_Factory;
+#elif defined(BOTAN_HAS_MUTEX_QT)
+ mutex_factory Qt_Mutex_Factory;
+#else
+ throw Invalid_State("Could not find a thread-safe mutex object to use");
+#endif
+ }
+
+ allocator_lock = mutex_factory->make();
+ config_lock = mutex_factory->make();
+
+ cached_default_allocator = 0;
+
+ add_allocator(new Malloc_Allocator);
+ add_allocator(new Locking_Allocator(mutex_factory->make()));
+
+#if defined(BOTAN_HAS_ALLOC_MMAP)
+ add_allocator(new MemoryMapping_Allocator(mutex_factory->make()));
+#endif
+
+ set_default_allocator("locking");
+
+ load_default_config();
+
+ std::vector<Engine*> engines;
+
+#if defined(BOTAN_HAS_ENGINE_GNU_MP)
+ engines.push_back(new GMP_Engine);
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_OPENSSL)
+ engines.push_back(new OpenSSL_Engine);
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_SSE2_ASSEMBLER)
+ engines.push_back(new SSE2_Assembler_Engine);
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_AMD64_ASSEMBLER)
+ engines.push_back(new AMD64_Assembler_Engine);
+#endif
+
+#if defined(BOTAN_HAS_ENGINE_IA32_ASSEMBLER)
+ engines.push_back(new IA32_Assembler_Engine);
+#endif
+
+ engines.push_back(new Default_Engine);
+
+ m_algorithm_factory = new Algorithm_Factory(engines, *mutex_factory);
+ }
+
+/*
+* Library_State Constructor
+*/
+Library_State::Library_State()
+ {
+ mutex_factory = 0;
+ allocator_lock = config_lock = 0;
+ cached_default_allocator = 0;
+ m_algorithm_factory = 0;
+ }
+
+/*
+* Library_State Destructor
+*/
+Library_State::~Library_State()
+ {
+ delete m_algorithm_factory;
+
+ cached_default_allocator = 0;
+
+ for(u32bit j = 0; j != allocators.size(); ++j)
+ {
+ allocators[j]->destroy();
+ delete allocators[j];
+ }
+
+ delete allocator_lock;
+ delete mutex_factory;
+ delete config_lock;
+ }
+
+}
diff --git a/botan/src/libstate/libstate.h b/botan/src/libstate/libstate.h
new file mode 100644
index 0000000..2493863
--- /dev/null
+++ b/botan/src/libstate/libstate.h
@@ -0,0 +1,125 @@
+/*
+* Library Internal/Global State
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LIB_STATE_H__
+#define BOTAN_LIB_STATE_H__
+
+#include <botan/types.h>
+#include <botan/allocate.h>
+#include <botan/algo_factory.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/*
+* Global State Container Base
+*/
+class BOTAN_DLL Library_State
+ {
+ public:
+ Library_State();
+ ~Library_State();
+
+ void initialize(bool thread_safe);
+
+ Algorithm_Factory& algorithm_factory();
+
+ Allocator* get_allocator(const std::string& = "") const;
+ void add_allocator(Allocator*);
+ void set_default_allocator(const std::string&);
+
+ /**
+ * Get a parameter value as std::string.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @result the value of the parameter
+ */
+ std::string get(const std::string& section,
+ const std::string& key) const;
+
+ /**
+ * Check whether a certain parameter is set
+ * or not.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @result true if the parameters value is set,
+ * false otherwise
+ */
+ bool is_set(const std::string& section, const std::string& key) const;
+
+ /**
+ * Set a configuration parameter.
+ * @param section the section of the desired key
+ * @param key the desired keys name
+ * @param overwrite if set to true, the parameters value
+ * will be overwritten even if it is already set, otherwise
+ * no existing values will be overwritten.
+ */
+ void set(const std::string& section, const std::string& key,
+ const std::string& value, bool overwrite = true);
+
+ /**
+ * Get a parameters value out of the "conf" section (
+ * referred to as option).
+ * @param key the desired keys name
+ */
+ std::string option(const std::string& key) const;
+
+ /**
+ * Set an option.
+ * @param key the key of the option to set
+ * @param value the value to set
+ */
+ void set_option(const std::string key, const std::string& value);
+
+ /**
+ * Add a parameter value to the "alias" section.
+ * @param key the name of the parameter which shall have a new alias
+ * @param value the new alias
+ */
+ void add_alias(const std::string&, const std::string&);
+
+ /**
+ * Resolve an alias.
+ * @param alias the alias to resolve.
+ * @return what the alias stands for
+ */
+ std::string deref_alias(const std::string&) const;
+
+ class Mutex* get_mutex() const;
+ private:
+ void load_default_config();
+
+ Library_State(const Library_State&) {}
+ Library_State& operator=(const Library_State&) { return (*this); }
+
+ class Mutex_Factory* mutex_factory;
+
+ std::map<std::string, std::string> config;
+ class Mutex* config_lock;
+
+ class Mutex* allocator_lock;
+ std::map<std::string, Allocator*> alloc_factory;
+ mutable Allocator* cached_default_allocator;
+ std::vector<Allocator*> allocators;
+
+ Algorithm_Factory* m_algorithm_factory;
+ };
+
+/*
+* Global State
+*/
+BOTAN_DLL Library_State& global_state();
+BOTAN_DLL void set_global_state(Library_State*);
+BOTAN_DLL Library_State* swap_global_state(Library_State*);
+
+}
+
+#endif
diff --git a/botan/src/libstate/look_pk.cpp b/botan/src/libstate/look_pk.cpp
new file mode 100644
index 0000000..8eb4738
--- /dev/null
+++ b/botan/src/libstate/look_pk.cpp
@@ -0,0 +1,76 @@
+/*
+* PK Algorithm Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/look_pk.h>
+#include <botan/lookup.h>
+
+namespace Botan {
+
+/*
+* Get a PK_Encryptor object
+*/
+PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key,
+ const std::string& eme)
+ {
+ return new PK_Encryptor_MR_with_EME(key, get_eme(eme));
+ }
+
+/*
+* Get a PK_Decryptor object
+*/
+PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key,
+ const std::string& eme)
+ {
+ return new PK_Decryptor_MR_with_EME(key, get_eme(eme));
+ }
+
+/*
+* Get a PK_Signer object
+*/
+PK_Signer* get_pk_signer(const PK_Signing_Key& key,
+ const std::string& emsa,
+ Signature_Format sig_format)
+ {
+ PK_Signer* signer = new PK_Signer(key, get_emsa(emsa));
+ signer->set_output_format(sig_format);
+ return signer;
+ }
+
+/*
+* Get a PK_Verifier object
+*/
+PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key,
+ const std::string& emsa,
+ Signature_Format sig_format)
+ {
+ PK_Verifier* verifier = new PK_Verifier_with_MR(key, get_emsa(emsa));
+ verifier->set_input_format(sig_format);
+ return verifier;
+ }
+
+/*
+* Get a PK_Verifier object
+*/
+PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key,
+ const std::string& emsa,
+ Signature_Format sig_format)
+ {
+ PK_Verifier* verifier = new PK_Verifier_wo_MR(key, get_emsa(emsa));
+ verifier->set_input_format(sig_format);
+ return verifier;
+ }
+
+/*
+* Get a PK_Key_Agreement object
+*/
+PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key,
+ const std::string& kdf)
+ {
+ return new PK_Key_Agreement(key, get_kdf(kdf));
+ }
+
+}
diff --git a/botan/src/libstate/look_pk.h b/botan/src/libstate/look_pk.h
new file mode 100644
index 0000000..27b67dc
--- /dev/null
+++ b/botan/src/libstate/look_pk.h
@@ -0,0 +1,78 @@
+/*
+* PK Algorithm Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_LOOKUP_H__
+#define BOTAN_PK_LOOKUP_H__
+
+#include <botan/build.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/**
+* Public key encryptor factory method.
+* @param key the key that will work inside the encryptor
+* @param pad determines the algorithm and encoding
+* @return the public key encryptor object
+*/
+BOTAN_DLL PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key,
+ const std::string& pad);
+
+/**
+* Public key decryptor factory method.
+* @param key the key that will work inside the decryptor
+* @param pad determines the algorithm and encoding
+* @return the public key decryptor object
+*/
+BOTAN_DLL PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key,
+ const std::string& pad);
+
+/**
+* Public key signer factory method.
+* @param key the key that will work inside the signer
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_format the signature format to be used
+* @return the public key signer object
+*/
+BOTAN_DLL PK_Signer* get_pk_signer(const PK_Signing_Key& key,
+ const std::string& pad,
+ Signature_Format = IEEE_1363);
+
+/**
+* Public key verifier factory method.
+* @param key the key that will work inside the verifier
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_format the signature format to be used
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key,
+ const std::string& pad,
+ Signature_Format = IEEE_1363);
+
+/**
+* Public key verifier factory method.
+* @param key the key that will work inside the verifier
+* @param pad determines the algorithm, encoding and hash algorithm
+* @param sig_form the signature format to be used
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key,
+ const std::string& pad,
+ Signature_Format sig_form = IEEE_1363);
+
+/**
+* Public key key agreement factory method.
+* @param key the key that will work inside the key agreement
+* @param pad determines the algorithm, encoding and hash algorithm
+* @return the public key verifier object
+*/
+BOTAN_DLL PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key,
+ const std::string& pad);
+
+}
+
+#endif
diff --git a/botan/src/libstate/lookup.cpp b/botan/src/libstate/lookup.cpp
new file mode 100644
index 0000000..3b49116
--- /dev/null
+++ b/botan/src/libstate/lookup.cpp
@@ -0,0 +1,296 @@
+/*
+* Algorithm Retrieval
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Acquire a block cipher
+*/
+const BlockCipher* retrieve_block_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_block_cipher(algo_spec);
+ }
+
+/**
+* Get a block cipher by name
+*/
+BlockCipher* get_block_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_block_cipher(algo_spec);
+ }
+
+/**
+* Acquire a stream cipher
+*/
+const StreamCipher* retrieve_stream_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_stream_cipher(algo_spec);
+ }
+
+/**
+* Get a stream cipher by name
+*/
+StreamCipher* get_stream_cipher(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_stream_cipher(algo_spec);
+ }
+
+/**
+* Acquire a hash function
+*/
+const HashFunction* retrieve_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_hash_function(algo_spec);
+ }
+
+/**
+* Get a hash function by name
+*/
+HashFunction* get_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_hash_function(algo_spec);
+ }
+
+/**
+* Query if Botan has the named hash function
+*/
+bool have_hash(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_hash_function(algo_spec);
+ }
+
+/**
+* Acquire an authentication code
+*/
+const MessageAuthenticationCode* retrieve_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_mac(algo_spec);
+ }
+
+/**
+* Get a MAC by name
+*/
+MessageAuthenticationCode* get_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.make_mac(algo_spec);
+ }
+
+/**
+* Query if Botan has the named MAC
+*/
+bool have_mac(const std::string& algo_spec)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ return af.prototype_mac(algo_spec);
+ }
+
+/**
+* Query if an algorithm exists
+*/
+bool have_algorithm(const std::string& name)
+ {
+ if(retrieve_block_cipher(name))
+ return true;
+ if(retrieve_stream_cipher(name))
+ return true;
+ if(retrieve_hash(name))
+ return true;
+ if(retrieve_mac(name))
+ return true;
+ return false;
+ }
+
+/**
+* Query if Botan has the named block cipher
+*/
+bool have_block_cipher(const std::string& name)
+ {
+ return (retrieve_block_cipher(name) != 0);
+ }
+
+/**
+* Query if Botan has the named stream cipher
+*/
+bool have_stream_cipher(const std::string& name)
+ {
+ return (retrieve_stream_cipher(name) != 0);
+ }
+
+/**
+* Query the block size of a cipher or hash
+*/
+u32bit block_size_of(const std::string& name)
+ {
+ const BlockCipher* cipher = retrieve_block_cipher(name);
+ if(cipher)
+ return cipher->BLOCK_SIZE;
+
+ const HashFunction* hash = retrieve_hash(name);
+ if(hash)
+ return hash->HASH_BLOCK_SIZE;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Query the OUTPUT_LENGTH of a hash or MAC
+*/
+u32bit output_length_of(const std::string& name)
+ {
+ const HashFunction* hash = retrieve_hash(name);
+ if(hash)
+ return hash->OUTPUT_LENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->OUTPUT_LENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Check if a keylength is valid for this algo
+*/
+bool valid_keylength_for(u32bit key_len, const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->valid_keylength(key_len);
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->valid_keylength(key_len);
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->valid_keylength(key_len);
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Query the MINIMUM_KEYLENGTH of an algorithm
+*/
+u32bit min_keylength_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->MINIMUM_KEYLENGTH;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->MINIMUM_KEYLENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->MINIMUM_KEYLENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Query the MAXIMUM_KEYLENGTH of an algorithm
+*/
+u32bit max_keylength_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->MAXIMUM_KEYLENGTH;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->MAXIMUM_KEYLENGTH;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->MAXIMUM_KEYLENGTH;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Query the KEYLENGTH_MULTIPLE of an algorithm
+*/
+u32bit keylength_multiple_of(const std::string& name)
+ {
+ const BlockCipher* bc = retrieve_block_cipher(name);
+ if(bc)
+ return bc->KEYLENGTH_MULTIPLE;
+
+ const StreamCipher* sc = retrieve_stream_cipher(name);
+ if(sc)
+ return sc->KEYLENGTH_MULTIPLE;
+
+ const MessageAuthenticationCode* mac = retrieve_mac(name);
+ if(mac)
+ return mac->KEYLENGTH_MULTIPLE;
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/**
+* Get a cipher object
+*/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ Algorithm_Factory::Engine_Iterator i(af);
+
+ while(Engine* engine = i.next())
+ {
+ Keyed_Filter* algo = engine->get_cipher(algo_spec, direction, af);
+ if(algo)
+ return algo;
+ }
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/**
+* Get a cipher object
+*/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir direction)
+ {
+ Keyed_Filter* cipher = get_cipher(algo_spec, direction);
+ cipher->set_key(key);
+
+ if(iv.length())
+ cipher->set_iv(iv);
+
+ return cipher;
+ }
+
+/**
+* Get a cipher object
+*/
+Keyed_Filter* get_cipher(const std::string& algo_spec,
+ const SymmetricKey& key,
+ Cipher_Dir direction)
+ {
+ return get_cipher(algo_spec,
+ key, InitializationVector(), direction);
+ }
+
+}
diff --git a/botan/src/libstate/lookup.h b/botan/src/libstate/lookup.h
new file mode 100644
index 0000000..0f48ddd
--- /dev/null
+++ b/botan/src/libstate/lookup.h
@@ -0,0 +1,239 @@
+/*
+* Algorithm Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOOKUP_H__
+#define BOTAN_LOOKUP_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/s2k.h>
+
+#include <botan/filters.h>
+#include <botan/mode_pad.h>
+#include <botan/kdf.h>
+#include <botan/eme.h>
+#include <botan/emsa.h>
+
+namespace Botan {
+
+/*
+* Retrieve an object from the lookup table
+*/
+// NOTE: these functions return internally stored objects, library
+// retains ownership
+
+BOTAN_DLL const BlockCipher*
+retrieve_block_cipher(const std::string&);
+
+BOTAN_DLL const StreamCipher*
+retrieve_stream_cipher(const std::string&);
+
+BOTAN_DLL const HashFunction*
+retrieve_hash(const std::string&);
+
+BOTAN_DLL const MessageAuthenticationCode*
+retrieve_mac(const std::string&);
+
+/*
+* Get an algorithm object
+*/
+// NOTE: these functions create and return new objects, letting the
+// caller assume ownership of them
+
+/**
+* Block cipher factory method.
+* @param algo_spec the name of the desired block cipher
+* @return a pointer to the block cipher object
+*/
+BOTAN_DLL BlockCipher* get_block_cipher(const std::string& name);
+
+
+/**
+* Stream cipher factory method.
+* @param algo_spec the name of the desired stream cipher
+* @return a pointer to the stream cipher object
+*/
+BOTAN_DLL StreamCipher* get_stream_cipher(const std::string& name);
+
+/**
+* Hash function factory method.
+* @param algo_spec the name of the desired hash function
+* @return a pointer to the hash function object
+*/
+BOTAN_DLL HashFunction* get_hash(const std::string& name);
+
+/**
+* MAC factory method.
+* @param algo_spec the name of the desired MAC
+* @return a pointer to the MAC object
+*/
+BOTAN_DLL MessageAuthenticationCode* get_mac(const std::string& name);
+
+/**
+* String to key algorithm factory method.
+* @param name the name of the desired string to key (S2K) algorithm
+* @return a pointer to the string to key algorithm object
+*/
+BOTAN_DLL S2K* get_s2k(const std::string& name);
+
+/*
+* Get an EMSA/EME/KDF/MGF function
+*/
+// NOTE: these functions create and return new objects, letting the
+// caller assume ownership of them
+
+/**
+* Factory method for EME (message-encoding methods for encryption) objects
+* @param name the name of the EME to create
+* @return a pointer to the desired EME object
+*/
+BOTAN_DLL EME* get_eme(const std::string& name);
+
+/**
+* Factory method for EMSA (message-encoding methods for signatures
+* with appendix) objects
+* @param name the name of the EME to create
+* @return a pointer to the desired EME object
+*/
+BOTAN_DLL EMSA* get_emsa(const std::string& name);
+
+/**
+* Factory method for KDF (key derivation function)
+* @param name the name of the KDF to create
+* @return a pointer to the desired KDF object
+*/
+BOTAN_DLL KDF* get_kdf(const std::string& name);
+
+/*
+* Get a cipher object
+*/
+
+/**
+* Factory method for general symmetric cipher filters.
+* @param algo_spec the name of the desired cipher
+* @param key the key to be used for encryption/decryption performed by
+* the filter
+* @param iv the initialization vector to be used
+* @param direction determines whether the filter will be an encrypting or decrypting
+* filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir dir);
+/**
+* Factory method for general symmetric cipher filters.
+* @param algo_spec the name of the desired cipher
+* @param key the key to be used for encryption/decryption performed by
+* the filter
+* @param direction determines whether the filter will be an encrypting or decrypting
+* filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name,
+ const SymmetricKey& key,
+ Cipher_Dir dir);
+
+/** Factory method for general symmetric cipher filters. No key will
+* be set in the filter.
+* @param algo_spec the name of the desired cipher
+
+* @param direction determines whether the filter will be an encrypting or
+* decrypting filter
+* @return a pointer to the encryption or decryption filter
+*/
+BOTAN_DLL Keyed_Filter* get_cipher(const std::string& name, Cipher_Dir dir);
+
+/**
+* Check if an algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_algorithm(const std::string& name);
+
+/**
+* Check if a block cipher algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_block_cipher(const std::string& name);
+
+/**
+* Check if a stream cipher algorithm exists.
+* @param name the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_stream_cipher(const std::string& name);
+
+/**
+* Check if a hash algorithm exists.
+* @param algo_spec the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_hash(const std::string& name);
+
+/**
+* Check if a MAC algorithm exists.
+* @param algo_spec the name of the algorithm to check for
+* @return true if the algorithm exists, false otherwise
+*/
+BOTAN_DLL bool have_mac(const std::string& name);
+
+/*
+* Query information about an algorithm
+*/
+
+/**
+* Find out the block size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the block size of the specified algorithm
+*/
+BOTAN_DLL u32bit block_size_of(const std::string& name);
+
+/**
+* Find out the output length of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the output length of the specified algorithm
+*/
+BOTAN_DLL u32bit output_length_of(const std::string& name);
+
+/**
+* Find out the whether a certain key length is allowd for a given
+* symmetric algorithm.
+* @param key_len the key length in question
+* @param name the name of the algorithm
+* @return true if the key length is valid for that algorithm, false otherwise
+*/
+BOTAN_DLL bool valid_keylength_for(u32bit keylen, const std::string& name);
+
+/**
+* Find out the minimum key size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the minimum key length of the specified algorithm
+*/
+BOTAN_DLL u32bit min_keylength_of(const std::string& name);
+
+/**
+* Find out the maximum key size of a certain symmetric algorithm.
+* @param name the name of the algorithm
+* @return the maximum key length of the specified algorithm
+*/
+BOTAN_DLL u32bit max_keylength_of(const std::string& name);
+
+/**
+* Find out the size any valid key is a multiple of for a certain algorithm.
+* @param name the name of the algorithm
+* @return the size any valid key is a multiple of
+*/
+BOTAN_DLL u32bit keylength_multiple_of(const std::string& name);
+
+}
+
+#endif
diff --git a/botan/src/libstate/oid_lookup/info.txt b/botan/src/libstate/oid_lookup/info.txt
new file mode 100644
index 0000000..609eb91
--- /dev/null
+++ b/botan/src/libstate/oid_lookup/info.txt
@@ -0,0 +1,14 @@
+realname "OID Lookup"
+
+load_on dep
+
+define OID_LOOKUP
+
+<add>
+oids.cpp
+oids.h
+</add>
+
+<requires>
+asn1
+</requires>
diff --git a/botan/src/libstate/oid_lookup/oids.cpp b/botan/src/libstate/oid_lookup/oids.cpp
new file mode 100644
index 0000000..232c633
--- /dev/null
+++ b/botan/src/libstate/oid_lookup/oids.cpp
@@ -0,0 +1,76 @@
+/*
+* OID Registry
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/oids.h>
+#include <botan/libstate.h>
+
+namespace Botan {
+
+namespace OIDS {
+
+/*
+* Register an OID to string mapping
+*/
+void add_oid(const OID& oid, const std::string& name)
+ {
+ const std::string oid_str = oid.as_string();
+
+ if(!global_state().is_set("oid2str", oid_str))
+ global_state().set("oid2str", oid_str, name);
+ if(!global_state().is_set("str2oid", name))
+ global_state().set("str2oid", name, oid_str);
+ }
+
+/*
+* Do an OID to string lookup
+*/
+std::string lookup(const OID& oid)
+ {
+ std::string name = global_state().get("oid2str", oid.as_string());
+ if(name == "")
+ return oid.as_string();
+ return name;
+ }
+
+/*
+* Do a string to OID lookup
+*/
+OID lookup(const std::string& name)
+ {
+ std::string value = global_state().get("str2oid", name);
+ if(value != "")
+ return OID(value);
+
+ try
+ {
+ return OID(name);
+ }
+ catch(Exception)
+ {
+ throw Lookup_Error("No object identifier found for " + name);
+ }
+ }
+
+/*
+* Check to see if an OID exists in the table
+*/
+bool have_oid(const std::string& name)
+ {
+ return global_state().is_set("str2oid", name);
+ }
+
+/*
+* Check to see if an OID exists in the table
+*/
+bool name_of(const OID& oid, const std::string& name)
+ {
+ return (oid == lookup(name));
+ }
+
+}
+
+}
diff --git a/botan/src/libstate/oid_lookup/oids.h b/botan/src/libstate/oid_lookup/oids.h
new file mode 100644
index 0000000..fdfe61f
--- /dev/null
+++ b/botan/src/libstate/oid_lookup/oids.h
@@ -0,0 +1,58 @@
+/*
+* OID Registry
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OIDS_H__
+#define BOTAN_OIDS_H__
+
+#include <botan/asn1_oid.h>
+
+namespace Botan {
+
+namespace OIDS {
+
+/**
+* Register an OID to string mapping.
+* @param oid the oid to register
+* @param name the name to be associated with the oid
+*/
+BOTAN_DLL void add_oid(const OID& oid, const std::string& name);
+
+/**
+* See if an OID exists in the internal table.
+* @param oid the oid to check for
+* @return true if the oid is registered
+*/
+BOTAN_DLL bool have_oid(const std::string& oid);
+
+/**
+* Resolve an OID
+* @param oid the OID to look up
+* @return the name associated with this OID
+*/
+BOTAN_DLL std::string lookup(const OID& oid);
+
+/**
+* Find the OID to a name. The lookup will be performed in the
+* general OID section of the configuration.
+* @param name the name to resolve
+* @return the OID associated with the specified name
+*/
+BOTAN_DLL OID lookup(const std::string& name);
+
+/**
+* Tests whether the specified OID stands for the specified name.
+* @param oid the OID to check
+* @param name the name to check
+* @return true if the specified OID stands for the specified name
+*/
+BOTAN_DLL bool name_of(const OID& oid, const std::string& name);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/libstate/pk_engine.cpp b/botan/src/libstate/pk_engine.cpp
new file mode 100644
index 0000000..790ddcd
--- /dev/null
+++ b/botan/src/libstate/pk_engine.cpp
@@ -0,0 +1,175 @@
+/*
+* PK Engine Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pk_engine.h>
+#include <botan/libstate.h>
+#include <botan/engine.h>
+
+namespace Botan {
+
+namespace Engine_Core {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+/*
+* Acquire an IF op
+*/
+IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ IF_Operation* op = engine->if_op(e, n, d, p, q, d1, d2, c);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+/*
+* Acquire a DSA op
+*/
+DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ DSA_Operation* op = engine->dsa_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+/*
+* Acquire a NR op
+*/
+NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ NR_Operation* op = engine->nr_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+/*
+* Acquire an ElGamal op
+*/
+ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ ELG_Operation* op = engine->elg_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+/*
+* Acquire a DH op
+*/
+DH_Operation* dh_op(const DL_Group& group, const BigInt& x)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ DH_Operation* op = engine->dh_op(group, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+/*
+* Acquire an ECDSA op
+*/
+ECDSA_Operation* ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ ECDSA_Operation* op = engine->ecdsa_op(dom_pars, priv_key, pub_key);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::ecdsa_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+/*
+* Acquire a ECKAEG op
+*/
+ECKAEG_Operation* eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ ECKAEG_Operation* op = engine->eckaeg_op(dom_pars, priv_key, pub_key);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::eckaeg_op: Unable to find a working engine");
+ }
+#endif
+
+/*
+* Acquire a modular exponentiator
+*/
+Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints)
+ {
+ Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+
+ while(const Engine* engine = i.next())
+ {
+ Modular_Exponentiator* op = engine->mod_exp(n, hints);
+
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::mod_exp: Unable to find a working engine");
+ }
+
+}
+
+}
diff --git a/botan/src/libstate/pk_engine.h b/botan/src/libstate/pk_engine.h
new file mode 100644
index 0000000..256a47c
--- /dev/null
+++ b/botan/src/libstate/pk_engine.h
@@ -0,0 +1,95 @@
+/**
+* Engine for PK
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_PK_LOOKUP_H__
+#define BOTAN_ENGINE_PK_LOOKUP_H__
+
+#include <botan/bigint.h>
+#include <botan/pow_mod.h>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+namespace Botan {
+
+class Algorithm_Factory;
+class Keyed_Filter;
+class Modular_Exponentiator;
+
+namespace Engine_Core {
+
+/*
+* Get an operation from an Engine
+*/
+Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints);
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+DH_Operation* dh_op(const DL_Group&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ECDSA_Operation* ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ECKAEG_Operation* eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+}
+
+}
+
+#endif
diff --git a/botan/src/libstate/policy.cpp b/botan/src/libstate/policy.cpp
new file mode 100644
index 0000000..dfc1dfc
--- /dev/null
+++ b/botan/src/libstate/policy.cpp
@@ -0,0 +1,511 @@
+/*
+* Default Policy
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/libstate.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* OID loading helper function
+*/
+void add_oid(Library_State& config,
+ const std::string& oid_str,
+ const std::string& name)
+ {
+ if(!config.is_set("oid2str", oid_str))
+ config.set("oid2str", oid_str, name);
+ if(!config.is_set("str2oid", name))
+ config.set("str2oid", name, oid_str);
+ }
+
+/*
+* Load all of the default OIDs
+*/
+void set_default_oids(Library_State& config)
+ {
+ /* Public key types */
+ add_oid(config, "1.2.840.113549.1.1.1", "RSA");
+ add_oid(config, "2.5.8.1.1", "RSA"); // RSA alternate
+ add_oid(config, "1.2.840.10040.4.1", "DSA");
+ add_oid(config, "1.2.840.10046.2.1", "DH");
+ add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ELG");
+ add_oid(config, "1.3.6.1.4.1.25258.1.1", "RW");
+ add_oid(config, "1.3.6.1.4.1.25258.1.2", "NR");
+ add_oid(config, "1.2.840.10045.2.1", "ECDSA"); // X9.62
+
+ /* Ciphers */
+ add_oid(config, "1.3.14.3.2.7", "DES/CBC");
+ add_oid(config, "1.2.840.113549.3.7", "TripleDES/CBC");
+ add_oid(config, "1.2.840.113549.3.2", "RC2/CBC");
+ add_oid(config, "1.2.840.113533.7.66.10", "CAST-128/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.2", "AES-128/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.22", "AES-192/CBC");
+ add_oid(config, "2.16.840.1.101.3.4.1.42", "AES-256/CBC");
+
+ /* Hash Functions */
+ add_oid(config, "1.2.840.113549.2.5", "MD5");
+ add_oid(config, "1.3.6.1.4.1.11591.12.2", "Tiger(24,3)");
+
+ add_oid(config, "1.3.14.3.2.26", "SHA-160");
+ add_oid(config, "2.16.840.1.101.3.4.2.4", "SHA-224");
+ add_oid(config, "2.16.840.1.101.3.4.2.1", "SHA-256");
+ add_oid(config, "2.16.840.1.101.3.4.2.2", "SHA-384");
+ add_oid(config, "2.16.840.1.101.3.4.2.3", "SHA-512");
+
+ /* Key Wrap */
+ add_oid(config, "1.2.840.113549.1.9.16.3.6", "KeyWrap.TripleDES");
+ add_oid(config, "1.2.840.113549.1.9.16.3.7", "KeyWrap.RC2");
+ add_oid(config, "1.2.840.113533.7.66.15", "KeyWrap.CAST-128");
+ add_oid(config, "2.16.840.1.101.3.4.1.5", "KeyWrap.AES-128");
+ add_oid(config, "2.16.840.1.101.3.4.1.25", "KeyWrap.AES-192");
+ add_oid(config, "2.16.840.1.101.3.4.1.45", "KeyWrap.AES-256");
+
+ /* Compression */
+ add_oid(config, "1.2.840.113549.1.9.16.3.8", "Compression.Zlib");
+
+ /* Public key signature schemes */
+ add_oid(config, "1.2.840.113549.1.1.1", "RSA/EME-PKCS1-v1_5");
+ add_oid(config, "1.2.840.113549.1.1.2", "RSA/EMSA3(MD2)");
+ add_oid(config, "1.2.840.113549.1.1.4", "RSA/EMSA3(MD5)");
+ add_oid(config, "1.2.840.113549.1.1.5", "RSA/EMSA3(SHA-160)");
+ add_oid(config, "1.2.840.113549.1.1.11", "RSA/EMSA3(SHA-256)");
+ add_oid(config, "1.2.840.113549.1.1.12", "RSA/EMSA3(SHA-384)");
+ add_oid(config, "1.2.840.113549.1.1.13", "RSA/EMSA3(SHA-512)");
+ add_oid(config, "1.3.36.3.3.1.2", "RSA/EMSA3(RIPEMD-160)");
+
+ add_oid(config, "1.2.840.10040.4.3", "DSA/EMSA1(SHA-160)");
+ add_oid(config, "2.16.840.1.101.3.4.3.1", "DSA/EMSA1(SHA-224)");
+ add_oid(config, "2.16.840.1.101.3.4.3.2", "DSA/EMSA1(SHA-256)");
+
+ add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1_BSI(SHA-160)");
+ add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1_BSI(SHA-224)");
+ add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1_BSI(SHA-256)");
+ add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1_BSI(SHA-384)");
+ add_oid(config, "1.2.840.10045.4.3.4", "ECDSA/EMSA1_BSI(SHA-512)");
+
+ add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1(SHA-224)");
+ add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1(SHA-256)");
+ add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1(SHA-384)");
+ add_oid(config, "1.2.840.10045.4.3.4", "ECDSA/EMSA1(SHA-512)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.1", "RW/EMSA2(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.2", "RW/EMSA2(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.3", "RW/EMSA2(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.4", "RW/EMSA2(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.5", "RW/EMSA2(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.1.6", "RW/EMSA2(SHA-512)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.1", "RW/EMSA4(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.2", "RW/EMSA4(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.3", "RW/EMSA4(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.4", "RW/EMSA4(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.5", "RW/EMSA4(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.1.2.6", "RW/EMSA4(SHA-512)");
+
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.1", "NR/EMSA2(RIPEMD-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.2", "NR/EMSA2(SHA-160)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.3", "NR/EMSA2(SHA-224)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.4", "NR/EMSA2(SHA-256)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.5", "NR/EMSA2(SHA-384)");
+ add_oid(config, "1.3.6.1.4.1.25258.2.2.1.6", "NR/EMSA2(SHA-512)");
+
+ add_oid(config, "2.5.4.3", "X520.CommonName");
+ add_oid(config, "2.5.4.4", "X520.Surname");
+ add_oid(config, "2.5.4.5", "X520.SerialNumber");
+ add_oid(config, "2.5.4.6", "X520.Country");
+ add_oid(config, "2.5.4.7", "X520.Locality");
+ add_oid(config, "2.5.4.8", "X520.State");
+ add_oid(config, "2.5.4.10", "X520.Organization");
+ add_oid(config, "2.5.4.11", "X520.OrganizationalUnit");
+ add_oid(config, "2.5.4.12", "X520.Title");
+ add_oid(config, "2.5.4.42", "X520.GivenName");
+ add_oid(config, "2.5.4.43", "X520.Initials");
+ add_oid(config, "2.5.4.44", "X520.GenerationalQualifier");
+ add_oid(config, "2.5.4.46", "X520.DNQualifier");
+ add_oid(config, "2.5.4.65", "X520.Pseudonym");
+
+ add_oid(config, "1.2.840.113549.1.5.12", "PKCS5.PBKDF2");
+ add_oid(config, "1.2.840.113549.1.5.1", "PBE-PKCS5v15(MD2,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.4", "PBE-PKCS5v15(MD2,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.3", "PBE-PKCS5v15(MD5,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.6", "PBE-PKCS5v15(MD5,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.10", "PBE-PKCS5v15(SHA-160,DES/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.11", "PBE-PKCS5v15(SHA-160,RC2/CBC)");
+ add_oid(config, "1.2.840.113549.1.5.13", "PBE-PKCS5v20");
+
+ add_oid(config, "1.2.840.113549.1.9.1", "PKCS9.EmailAddress");
+ add_oid(config, "1.2.840.113549.1.9.2", "PKCS9.UnstructuredName");
+ add_oid(config, "1.2.840.113549.1.9.3", "PKCS9.ContentType");
+ add_oid(config, "1.2.840.113549.1.9.4", "PKCS9.MessageDigest");
+ add_oid(config, "1.2.840.113549.1.9.7", "PKCS9.ChallengePassword");
+ add_oid(config, "1.2.840.113549.1.9.14", "PKCS9.ExtensionRequest");
+
+ add_oid(config, "1.2.840.113549.1.7.1", "CMS.DataContent");
+ add_oid(config, "1.2.840.113549.1.7.2", "CMS.SignedData");
+ add_oid(config, "1.2.840.113549.1.7.3", "CMS.EnvelopedData");
+ add_oid(config, "1.2.840.113549.1.7.5", "CMS.DigestedData");
+ add_oid(config, "1.2.840.113549.1.7.6", "CMS.EncryptedData");
+ add_oid(config, "1.2.840.113549.1.9.16.1.2", "CMS.AuthenticatedData");
+ add_oid(config, "1.2.840.113549.1.9.16.1.9", "CMS.CompressedData");
+
+ add_oid(config, "2.5.29.14", "X509v3.SubjectKeyIdentifier");
+ add_oid(config, "2.5.29.15", "X509v3.KeyUsage");
+ add_oid(config, "2.5.29.17", "X509v3.SubjectAlternativeName");
+ add_oid(config, "2.5.29.18", "X509v3.IssuerAlternativeName");
+ add_oid(config, "2.5.29.19", "X509v3.BasicConstraints");
+ add_oid(config, "2.5.29.20", "X509v3.CRLNumber");
+ add_oid(config, "2.5.29.21", "X509v3.ReasonCode");
+ add_oid(config, "2.5.29.23", "X509v3.HoldInstructionCode");
+ add_oid(config, "2.5.29.24", "X509v3.InvalidityDate");
+ add_oid(config, "2.5.29.32", "X509v3.CertificatePolicies");
+ add_oid(config, "2.5.29.35", "X509v3.AuthorityKeyIdentifier");
+ add_oid(config, "2.5.29.36", "X509v3.PolicyConstraints");
+ add_oid(config, "2.5.29.37", "X509v3.ExtendedKeyUsage");
+
+ add_oid(config, "2.5.29.32.0", "X509v3.AnyPolicy");
+
+ add_oid(config, "1.3.6.1.5.5.7.3.1", "PKIX.ServerAuth");
+ add_oid(config, "1.3.6.1.5.5.7.3.2", "PKIX.ClientAuth");
+ add_oid(config, "1.3.6.1.5.5.7.3.3", "PKIX.CodeSigning");
+ add_oid(config, "1.3.6.1.5.5.7.3.4", "PKIX.EmailProtection");
+ add_oid(config, "1.3.6.1.5.5.7.3.5", "PKIX.IPsecEndSystem");
+ add_oid(config, "1.3.6.1.5.5.7.3.6", "PKIX.IPsecTunnel");
+ add_oid(config, "1.3.6.1.5.5.7.3.7", "PKIX.IPsecUser");
+ add_oid(config, "1.3.6.1.5.5.7.3.8", "PKIX.TimeStamping");
+ add_oid(config, "1.3.6.1.5.5.7.3.9", "PKIX.OCSPSigning");
+
+ add_oid(config, "1.3.6.1.5.5.7.8.5", "PKIX.XMPPAddr");
+
+ /* CVC */
+ add_oid(config, "0.4.0.127.0.7.3.1.2.1",
+ "CertificateHolderAuthorizationTemplate");
+ }
+
+/*
+* Set the default algorithm aliases
+*/
+void set_default_aliases(Library_State& config)
+ {
+ config.add_alias("OpenPGP.Cipher.1", "IDEA");
+ config.add_alias("OpenPGP.Cipher.2", "TripleDES");
+ config.add_alias("OpenPGP.Cipher.3", "CAST-128");
+ config.add_alias("OpenPGP.Cipher.4", "Blowfish");
+ config.add_alias("OpenPGP.Cipher.5", "SAFER-SK(13)");
+ config.add_alias("OpenPGP.Cipher.7", "AES-128");
+ config.add_alias("OpenPGP.Cipher.8", "AES-192");
+ config.add_alias("OpenPGP.Cipher.9", "AES-256");
+ config.add_alias("OpenPGP.Cipher.10", "Twofish");
+
+ config.add_alias("OpenPGP.Digest.1", "MD5");
+ config.add_alias("OpenPGP.Digest.2", "SHA-1");
+ config.add_alias("OpenPGP.Digest.3", "RIPEMD-160");
+ config.add_alias("OpenPGP.Digest.5", "MD2");
+ config.add_alias("OpenPGP.Digest.6", "Tiger(24,3)");
+ config.add_alias("OpenPGP.Digest.8", "SHA-256");
+
+ config.add_alias("TLS.Digest.0", "Parallel(MD5,SHA-160)");
+
+ config.add_alias("EME-PKCS1-v1_5", "PKCS1v15");
+ config.add_alias("OAEP-MGF1", "EME1");
+ config.add_alias("EME-OAEP", "EME1");
+ config.add_alias("X9.31", "EMSA2");
+ config.add_alias("EMSA-PKCS1-v1_5", "EMSA3");
+ config.add_alias("PSS-MGF1", "EMSA4");
+ config.add_alias("EMSA-PSS", "EMSA4");
+
+ config.add_alias("Rijndael", "AES");
+ config.add_alias("3DES", "TripleDES");
+ config.add_alias("DES-EDE", "TripleDES");
+ config.add_alias("CAST5", "CAST-128");
+ config.add_alias("SHA1", "SHA-160");
+ config.add_alias("SHA-1", "SHA-160");
+ config.add_alias("MARK-4", "ARC4(256)");
+ config.add_alias("OMAC", "CMAC");
+ config.add_alias("GOST", "GOST-28147-89");
+ }
+
+/*
+* Set the default configuration toggles
+*/
+void set_default_config(Library_State& config)
+ {
+ config.set_option("base/default_allocator", "malloc");
+
+ config.set_option("x509/exts/basic_constraints", "critical");
+ config.set_option("x509/exts/subject_key_id", "yes");
+ config.set_option("x509/exts/authority_key_id", "yes");
+ config.set_option("x509/exts/subject_alternative_name", "yes");
+ config.set_option("x509/exts/issuer_alternative_name", "no");
+ config.set_option("x509/exts/key_usage", "critical");
+ config.set_option("x509/exts/extended_key_usage", "yes");
+ config.set_option("x509/exts/crl_number", "yes");
+ }
+
+/*
+* Set the built-in discrete log groups
+*/
+void set_default_dl_groups(Library_State& config)
+ {
+ config.set("dl", "modp/ietf/768",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIHIAmEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFK"
+ "CHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP//"
+ "////////AgECAmB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF31Md"
+ "ic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3omIXTT"
+ "HRsQf/////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/1024",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBCgKBgQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezmU4H//////////wIBAgKBgH//"
+ "////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXfUx2JzZEopQQ8xxoCbvfK"
+ "jNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYhdNMb9rWF/65begNb9vcc"
+ "Nf2tRM/S10+SCL4lj/MklDMo9nMpwP//////////"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/1536",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIBigKBwQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si"
+ "UUoIeY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummN+1r"
+ "C/9ctvQGt+3uOGv7Womfpa6fJBF8Sx/mSShmUezkWz3CAHy4oWO/BZjaSDYcVdOa"
+ "aRY/qP0kz1+DZV0j3KOtlhxi81YghVK7ntUpB3CWlm1nDDVOSryYBPF0bAjKI3Mn"
+ "//////////8CAQICgcB//////////+SH7VEQtGEaYmMxRcBuDmiUgScERTPmOgEF"
+ "31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Catrao4SLyQtq7MS8/Y3om"
+ "IXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQzKPZyLZ7hAD5cULHfgsxt"
+ "JBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qUg7hLSzazhhqnJV5MAni6"
+ "NgRlEbmT//////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/2048",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIICDAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAgKCAQB//////////+SH7VEQtGEa"
+ "YmMxRcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4ob"
+ "p/Catrao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/z"
+ "JJQzKPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqld"
+ "z2qUg7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH"
+ "2uKu+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVZVNH//////////"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/3072",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIDDAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS"
+ "yv//////////AgECAoIBgH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6"
+ "AQXfUx2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9j"
+ "eiYhdNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+C"
+ "zG0kGw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwC"
+ "eLo2BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuM"
+ "HMqkvnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeF"
+ "RXU4q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQy"
+ "bDsBOZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohH"
+ "JcFokFSdaWV//////////w=="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/4096",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIEDAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQICggIA"
+ "f//////////kh+1RELRhGmJjMUXAbg5olIEnBEUz5joBBd9THYnNkSilBDzHGgJu"
+ "98qM2eadIY2YFYU2+S+KG6fwmra2qOEi8kLauzEvP2N6JiF00xv2tYX/rlt6A1v2"
+ "9xw1/a1Ez9LXT5IIviWP8ySUMyj2ci2e4QA+XFCx34LMbSQbDirpzTSLH9R+kmev"
+ "wbKuke5R1ssOMXmrEEKpXc9qlIO4S0s2s4YapyVeTAJ4ujYEZQwQvhlILyMXG2cd"
+ "8c87lgwHQwHNk8HRdgPRR9rirvg3pilk7xXl+0qsC4wcyqS+dUq1corpEwxMfQKI"
+ "CrlHLUVVYhbWmYuGgig9GdQqkNXvjl0ydn3Cgixt94VFdTirroMGPtnLh8LTcPJj"
+ "1frXRm2EmeuPRkpwJRKwzudx6RMNaXc1+Jf9A2zFBDJsOwE5n2Q1MikPlYwLvZAG"
+ "XfCLq70wrrY7hMRgXWyjcQRxJ9A6ctWYoe2t/nB+iEclwWiQVJCEAI05HglTw/Nr"
+ "xDjNCF7dLZNM4ZOMNXpxHg1KNBpbCoXtEsH05RVqJnRt3eFtgm9HfJdHfgoP32VT"
+ "FD4so6c14C7M2Usn0Ehh0RGd0MMorfP2j7CUuGdxa9fcDe67ELgkDmgDSJPq2C1U"
+ "ydp1TEbH7uDDf9vuSFNgR6b6GuSaAxjM//////////8="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/6144",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIGDAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA"
+ "JP//////////AoIDAH//////////5IftURC0YRpiYzFFwG4OaJSBJwRFM+Y6AQXf"
+ "Ux2JzZEopQQ8xxoCbvfKjNnmnSGNmBWFNvkvihun8Jq2tqjhIvJC2rsxLz9jeiYh"
+ "dNMb9rWF/65begNb9vccNf2tRM/S10+SCL4lj/MklDMo9nItnuEAPlxQsd+CzG0k"
+ "Gw4q6c00ix/UfpJnr8GyrpHuUdbLDjF5qxBCqV3PapSDuEtLNrOGGqclXkwCeLo2"
+ "BGUMEL4ZSC8jFxtnHfHPO5YMB0MBzZPB0XYD0Ufa4q74N6YpZO8V5ftKrAuMHMqk"
+ "vnVKtXKK6RMMTH0CiAq5Ry1FVWIW1pmLhoIoPRnUKpDV745dMnZ9woIsbfeFRXU4"
+ "q66DBj7Zy4fC03DyY9X610ZthJnrj0ZKcCUSsM7ncekTDWl3NfiX/QNsxQQybDsB"
+ "OZ9kNTIpD5WMC72QBl3wi6u9MK62O4TEYF1so3EEcSfQOnLVmKHtrf5wfohHJcFo"
+ "kFSQhACNOR4JU8Pza8Q4zQhe3S2TTOGTjDV6cR4NSjQaWwqF7RLB9OUVaiZ0bd3h"
+ "bYJvR3yXR34KD99lUxQ+LKOnNeAuzNlLJ9BIYdERndDDKK3z9o+wlLhncWvX3A3u"
+ "uxC4JA5oA0iT6tgtVMnadUxGx+7gw3/b7khTYEem+hrkmgFCSRth/VppPjgTYOpu"
+ "WTATI29kuo87Ht0b3vx/ygNWzymHcu2cF6CYANdYNSn2yBPsGIvLk9hDLUSMbR9t"
+ "9efNinaiZzZdZ2pdje2/iiPzZhKlmZAoqJXr16E33HoAm8ZpX6zB5QDjJcl2eBl1"
+ "Cui5DoH6QWvnNzp/e2qvOBejTAZBWtQgGMgFjk8s8+S/32P0eZHUvT8bZkRfB46i"
+ "2/+sLWKl6gPZFaCqVWZHtr9fpHDsCmYvaQfAG/BTy4r3eU3xlANQ6sXb4u07eqhV"
+ "HsUP3/h1jOZY0Ynqrm0rZPYXeUsZHD/0a7ceAjQCH0ezH6Qwdwlflq2Fujprc0p8"
+ "jzbmIBJ//////////wIBAg=="
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "modp/ietf/8192",
+ "-----BEGIN X942 DH PARAMETERS-----"
+ "MIIIDAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb"
+ "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft"
+ "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT"
+ "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh"
+ "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq"
+ "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM"
+ "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq"
+ "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI"
+ "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O"
+ "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI"
+ "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG"
+ "3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU"
+ "7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId"
+ "A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha"
+ "xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/"
+ "8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R"
+ "WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk"
+ "ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw"
+ "xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4"
+ "Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i"
+ "aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU"
+ "38gfVuiAuW5xYMmA3Zjt09///////////wKCBAB//////////+SH7VEQtGEaYmMx"
+ "RcBuDmiUgScERTPmOgEF31Mdic2RKKUEPMcaAm73yozZ5p0hjZgVhTb5L4obp/Ca"
+ "trao4SLyQtq7MS8/Y3omIXTTG/a1hf+uW3oDW/b3HDX9rUTP0tdPkgi+JY/zJJQz"
+ "KPZyLZ7hAD5cULHfgsxtJBsOKunNNIsf1H6SZ6/Bsq6R7lHWyw4xeasQQqldz2qU"
+ "g7hLSzazhhqnJV5MAni6NgRlDBC+GUgvIxcbZx3xzzuWDAdDAc2TwdF2A9FH2uKu"
+ "+DemKWTvFeX7SqwLjBzKpL51SrVyiukTDEx9AogKuUctRVViFtaZi4aCKD0Z1CqQ"
+ "1e+OXTJ2fcKCLG33hUV1OKuugwY+2cuHwtNw8mPV+tdGbYSZ649GSnAlErDO53Hp"
+ "Ew1pdzX4l/0DbMUEMmw7ATmfZDUyKQ+VjAu9kAZd8IurvTCutjuExGBdbKNxBHEn"
+ "0Dpy1Zih7a3+cH6IRyXBaJBUkIQAjTkeCVPD82vEOM0IXt0tk0zhk4w1enEeDUo0"
+ "GlsKhe0SwfTlFWomdG3d4W2Cb0d8l0d+Cg/fZVMUPiyjpzXgLszZSyfQSGHREZ3Q"
+ "wyit8/aPsJS4Z3Fr19wN7rsQuCQOaANIk+rYLVTJ2nVMRsfu4MN/2+5IU2BHpvoa"
+ "5JoBQkkbYf1aaT44E2DqblkwEyNvZLqPOx7dG978f8oDVs8ph3LtnBegmADXWDUp"
+ "9sgT7BiLy5PYQy1EjG0fbfXnzYp2omc2XWdqXY3tv4oj82YSpZmQKKiV69ehN9x6"
+ "AJvGaV+sweUA4yXJdngZdQrouQ6B+kFr5zc6f3tqrzgXo0wGQVrUIBjIBY5PLPPk"
+ "v99j9HmR1L0/G2ZEXweOotv/rC1ipeoD2RWgqlVmR7a/X6Rw7ApmL2kHwBvwU8uK"
+ "93lN8ZQDUOrF2+LtO3qoVR7FD9/4dYzmWNGJ6q5tK2T2F3lLGRw/9Gu3HgI0Ah9H"
+ "sx+kMHcJX5athbo6a3NKfI823wisulHJN4l/cvIcO75bVJlvxmxfYmg53JjdHeQZ"
+ "W0bO6YA6D9PfxX4j9pK7e0m10hIzHVWxzi1yerQaEdo6FfjkvBHHi2XxzrKW8f7c"
+ "X35CRWyRERcCUgG+A4n1q9QNEfhjmjn+MjZ1GDWl5eRDF8HC7v1Opb/RYEP0PLQZ"
+ "gfat7p0DFZ562dE8UzaVCfwfonwW75iHcDpVtRsiy/RM0BKu4LJ5jmKEI0KO/NWk"
+ "DK72v1DY6ohev3Omuf15teGPZ9E0GsgjenXDz8kgBKHFpA42a8RNABdq9xwV5IyG"
+ "034BNyPKrHIjqzv01U8YKHE7K0pv5A+rdEBctziwZMBuzHbp7///////////AgEC"
+ "-----END X942 DH PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/512",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIGdAkEA/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQT"
+ "xeEu0ImbzRMqzVDZkVG9xD7nN1kuFwIVAJYu3cw2nLqOuyYO5rahJtk0bjjFAkEA"
+ "3gtU76vylwh+5iPVylWIxkgo70/eT/uuHs0gBndrBbEbgeo83pvDlkwWh8UyW/Q9"
+ "fM76DQqGvl3/3dDRFD3NdQ=="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/768",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIHdAmEA6eZCWZ01XzfJf/01ZxILjiXJzUPpJ7OpZw++xdiQFBki0sOzrSSACTeZ"
+ "hp0ehGqrSfqwrSbSzmoiIZ1HC859d31KIfvpwnC1f2BwAvPO+Dk2lM9F7jaIwRqM"
+ "VqsSej2vAhUAnNvYTJ8awvOND4D0KrlS5zOL9RECYQDe7p717RUWzn5pXmcrjO5F"
+ "5s17NuDmOF+JS6hhY/bz5sbU6KgRRtQBfe/dccvZD6Akdlm4i3zByJT0gmn9Txqs"
+ "CjBTjf9rP8ds+xMcnnlltYhYqwpDtVczWRKoqlR/lWg="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/jce/1024",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIBHgKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9"
+ "jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX"
+ "58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8V"
+ "IwvMspK5gqLrhAvwWBz1AoGARpYDUS4wJ4zTlHWV2yLuyYJqYyKtyXNE9B10DDJX"
+ "JMj577qn1NgD/4xgnc0QDrxb38+tfGpCX66nhuogUOvpg1HqH9of3yTWlHqmuaoj"
+ "dmlTgC9NfUqOy6BtGXaKJJH/sW0O+cQ6mbX3FnL/bwoktETQc20E04oaEyLa9s3Y"
+ "jJ0="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/botan/2048",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIICLAKCAQEAkcSKT9+898Aq6V59oSYSK13Shk9Vm4fo50oobVL1m9HeaN/WRdDg"
+ "DGDAgAMYkZgDdO61lKUyv9Z7mgnqxLhmOgeRDmjzlGX7cEDSXfE5MuusQ0elMOy6"
+ "YchU+biA08DDZgCAWHxFVm2t4mvVo5S+CTtMDyS1r/747GxbPlf7iQJam8FnaZMh"
+ "MeFtPJTvyrGNDfBhIDzFPmEDvHLVWUv9QMplOA9EqahR3LB1SV/AM6ilgHGhvXj+"
+ "BS9mVVZI60txnSr+i0iA+NrW8VgYuhePiSdMhwvpuW6wjEbEAEDMLv4d+xsYaN0x"
+ "nePDSjKmOrbrEiQgmkGWgMx5AtFyjU354QIhAIzX1FD4bwrZTu5M5GmodW0evRBY"
+ "JBlD6v+ws1RYXpJNAoIBAA2fXgdhtNvRgz1qsalhoJlsXyIwP3LYTBQPZ8Qx2Uq1"
+ "cVvqgaDJjTnOS8941rnryJXTT+idlAkdWEhhXvFfXobxHZb2yWniA936WDVkIKSc"
+ "tES1lbkBqTPP4HZ7WU8YoHt/kd7NukRriJkPePL/kfL+fNQ/0uRtGOraH3u2YCxh"
+ "f27zpLKE8v2boQo2BC3o+oeiyjZZf+yBFXoUheRAQd8CgwERy4gLvm7UlIFIhvll"
+ "zcMTX1zPE4Nyi/ZbgG+WksCxDWxMCcdabKO0ATyxarLBBfa+I66pAA6rIXiYX5cs"
+ "mAV+HIbkTnIYaI6krg82NtzKdFydzU5q/7Z8y8E9YTE="
+ "-----END DSA PARAMETERS-----");
+
+ config.set("dl", "dsa/botan/3072",
+ "-----BEGIN DSA PARAMETERS-----"
+ "MIIDLAKCAYEA5LUIgHWWY1heFCRgyi2d/xMviuTIQN2jomZoiRJP5WOLhOiim3rz"
+ "+hIJvmv8S1By7Tsrc4e68/hX9HioAijvNgC3az3Pth0g00RlslBtLK+H3259wM6R"
+ "vS0Wekb2rcwxxTHk+cervbkq3fNbCoBsZikqX14X6WTdCZkDczrEKKs12A6m9oW/"
+ "uovkBo5UGK5eytno/wc94rY+Tn6tNciptwtb1Hz7iNNztm83kxk5sKtxvVWVgJCG"
+ "2gFVM30YWg5Ps2pRmxtiArhZHmACRJzxzTpmOE9tIHOxzXO+ypO68eGmEX0COPIi"
+ "rh7X/tGFqJDn9n+rj+uXU8wTSlGD3+h64llfe1wtn7tCJJ/dWVE+HTOWs+sv2GaE"
+ "8oWoRI/nV6ApiBxAdguU75Gb35dAw4OJWZ7FGm6btRmo4GhJHpzgovz+PLYNZs8N"
+ "+tIKjsaEBIaEphREV1vRck1zUrRKdgB3s71r04XOWwpyUMwL92jagpI4Buuc+7E4"
+ "hDcxthggjHWbAiEAs+vTZOxp74zzuvZDt1c0sWM5suSeXN4bWcHp+0DuDFsCggGA"
+ "K+0h7vg5ZKIwrom7px2ffDnFL8gim047x+WUTTKdoQ8BDqyee69sAJ/E6ylgcj4r"
+ "Vt9GY+TDrIAOkljeL3ZJ0gZ4KJP4Ze/KSY0u7zAHTqXop6smJxKk2UovOwuaku5A"
+ "D7OKPMWaXcfkNtXABLIuNQKDgbUck0B+sy1K4P1Cy0XhLQ7O6KJiOO3iCCp7FSIR"
+ "PGbO+NdFxs88uUX4TS9N4W1Epx3hmCcOE/A1U8iLjTI60LlIob8hA6lJl5tu0W+1"
+ "88lT2Vt8jojKZ9z1pjb7nKOdkkIV96iE7Wx+48ltjZcVQnl0t8Q1EoLhPTdz99KL"
+ "RS8QiSoTx1hzKN6kgntrNpsqjcFyrcWD9R8qZZjFSD5bxGewL5HQWcQC0Y4sJoD3"
+ "dqoG9JKAoscsF8xC1bbnQMXEsas8UcLtCSviotiwU65Xc9FCXtKwjwbi3VBZLfGk"
+ "eMFVkc39EVZP+I/zi3IdQjkv2kcyEtz9jS2IqXagCv/m//tDCjWeZMorNRyiQSOU"
+ "-----END DSA PARAMETERS-----");
+ }
+}
+
+/*
+* Set the default policy
+*/
+void Library_State::load_default_config()
+ {
+ set_default_config(*this);
+ set_default_aliases(*this);
+ set_default_oids(*this);
+ set_default_dl_groups(*this);
+ }
+
+}
diff --git a/botan/src/libstate/scan_name.cpp b/botan/src/libstate/scan_name.cpp
new file mode 100644
index 0000000..ef77187
--- /dev/null
+++ b/botan/src/libstate/scan_name.cpp
@@ -0,0 +1,74 @@
+/**
+SCAN Name Abstraction
+(C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/scan_name.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <stdexcept>
+
+namespace Botan {
+
+namespace {
+
+std::vector<std::string>
+parse_and_deref_aliases(const std::string& algo_spec)
+ {
+ std::vector<std::string> parts = parse_algorithm_name(algo_spec);
+ std::vector<std::string> out;
+
+ for(size_t i = 0; i != parts.size(); ++i)
+ {
+ std::string part_i = global_state().deref_alias(parts[i]);
+
+ if(i == 0 && part_i.find_first_of(",()") != std::string::npos)
+ {
+ std::vector<std::string> parts_i = parse_and_deref_aliases(part_i);
+
+ for(size_t j = 0; j != parts_i.size(); ++j)
+ out.push_back(parts_i[j]);
+ }
+ else
+ out.push_back(part_i);
+ }
+
+ return out;
+ }
+
+}
+
+SCAN_Name::SCAN_Name(const std::string& algo_spec)
+ {
+ orig_algo_spec = algo_spec;
+
+ name = parse_and_deref_aliases(algo_spec);
+
+ if(name.size() == 0)
+ throw Decoding_Error("Bad SCAN name " + algo_spec);
+ }
+
+std::string SCAN_Name::arg(u32bit i) const
+ {
+ if(i >= arg_count())
+ throw std::range_error("SCAN_Name::argument");
+ return name[i+1];
+ }
+
+std::string SCAN_Name::arg(u32bit i, const std::string& def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return name[i+1];
+ }
+
+u32bit SCAN_Name::arg_as_u32bit(u32bit i, u32bit def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return to_u32bit(name[i+1]);
+ }
+
+}
diff --git a/botan/src/libstate/scan_name.h b/botan/src/libstate/scan_name.h
new file mode 100644
index 0000000..9e7af40
--- /dev/null
+++ b/botan/src/libstate/scan_name.h
@@ -0,0 +1,77 @@
+/**
+SCAN Name Abstraction
+(C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SCAN_NAME_H__
+#define BOTAN_SCAN_NAME_H__
+
+#include <botan/types.h>
+#include <string>
+#include <vector>
+#include <set>
+
+namespace Botan {
+
+/**
+A class encapsulating a SCAN name (similar to JCE conventions)
+http://www.users.zetnet.co.uk/hopwood/crypto/scan/
+*/
+class SCAN_Name
+ {
+ public:
+ /**
+ @param algo_spec A SCAN name
+ */
+ SCAN_Name(const std::string& algo_spec);
+
+ /**
+ @return the original input string
+ */
+ std::string as_string() const { return orig_algo_spec; }
+
+ /**
+ @return the algorithm name
+ */
+ std::string algo_name() const { return name[0]; }
+
+ /**
+ @return the number of arguments
+ */
+ u32bit arg_count() const { return name.size() - 1; }
+
+ /**
+ @return if the number of arguments is between lower and upper
+ */
+ bool arg_count_between(u32bit lower, u32bit upper) const
+ { return ((arg_count() >= lower) && (arg_count() <= upper)); }
+
+ /**
+ @param i which argument
+ @return the ith argument
+ */
+ std::string arg(u32bit i) const;
+
+ /**
+ @param i which argument
+ @param def_value the default value
+ @return the ith argument or the default value
+ */
+ std::string arg(u32bit i, const std::string& def_value) const;
+
+ /**
+ @param i which argument
+ @param def_value the default value
+ @return the ith argument as a u32bit, or the default value
+ */
+ u32bit arg_as_u32bit(u32bit i, u32bit def_value) const;
+ private:
+ std::string orig_algo_spec;
+ std::vector<std::string> name;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/cbc_mac/cbc_mac.cpp b/botan/src/mac/cbc_mac/cbc_mac.cpp
new file mode 100644
index 0000000..f5d9e15
--- /dev/null
+++ b/botan/src/mac/cbc_mac/cbc_mac.cpp
@@ -0,0 +1,109 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cbc_mac.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Update an CBC-MAC Calculation
+*/
+void CBC_MAC::add_data(const byte input[], u32bit length)
+ {
+ u32bit xored = std::min(OUTPUT_LENGTH - position, length);
+ xor_buf(state + position, input, xored);
+ position += xored;
+
+ if(position < OUTPUT_LENGTH)
+ return;
+
+ e->encrypt(state);
+ input += xored;
+ length -= xored;
+ while(length >= OUTPUT_LENGTH)
+ {
+ xor_buf(state, input, OUTPUT_LENGTH);
+ e->encrypt(state);
+ input += OUTPUT_LENGTH;
+ length -= OUTPUT_LENGTH;
+ }
+
+ xor_buf(state, input, length);
+ position = length;
+ }
+
+/*
+* Finalize an CBC-MAC Calculation
+*/
+void CBC_MAC::final_result(byte mac[])
+ {
+ if(position)
+ e->encrypt(state);
+
+ copy_mem(mac, state.begin(), state.size());
+ state.clear();
+ position = 0;
+ }
+
+/*
+* CBC-MAC Key Schedule
+*/
+void CBC_MAC::key_schedule(const byte key[], u32bit length)
+ {
+ e->set_key(key, length);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CBC_MAC::clear() throw()
+ {
+ e->clear();
+ state.clear();
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CBC_MAC::name() const
+ {
+ return "CBC-MAC(" + e->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CBC_MAC::clone() const
+ {
+ return new CBC_MAC(e->clone());
+ }
+
+/*
+* CBC-MAC Constructor
+*/
+CBC_MAC::CBC_MAC(BlockCipher* e_in) :
+ MessageAuthenticationCode(e_in->BLOCK_SIZE,
+ e_in->MINIMUM_KEYLENGTH,
+ e_in->MAXIMUM_KEYLENGTH,
+ e_in->KEYLENGTH_MULTIPLE),
+ e(e_in), state(e->BLOCK_SIZE)
+ {
+ position = 0;
+ }
+
+/*
+* CBC-MAC Destructor
+*/
+CBC_MAC::~CBC_MAC()
+ {
+ delete e;
+ }
+
+}
diff --git a/botan/src/mac/cbc_mac/cbc_mac.h b/botan/src/mac/cbc_mac/cbc_mac.h
new file mode 100644
index 0000000..d17d792
--- /dev/null
+++ b/botan/src/mac/cbc_mac/cbc_mac.h
@@ -0,0 +1,40 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_MAC_H__
+#define BOTAN_CBC_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CBC-MAC
+*/
+class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ CBC_MAC(BlockCipher* e);
+ ~CBC_MAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ SecureVector<byte> state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/cbc_mac/info.txt b/botan/src/mac/cbc_mac/info.txt
new file mode 100644
index 0000000..3a54349
--- /dev/null
+++ b/botan/src/mac/cbc_mac/info.txt
@@ -0,0 +1,14 @@
+realname "CBC-MAC"
+
+define CBC_MAC
+
+load_on auto
+
+<add>
+cbc_mac.cpp
+cbc_mac.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/mac/cmac/cmac.cpp b/botan/src/mac/cmac/cmac.cpp
new file mode 100644
index 0000000..84aa61e
--- /dev/null
+++ b/botan/src/mac/cmac/cmac.cpp
@@ -0,0 +1,162 @@
+/*
+* CMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cmac.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Perform CMAC's multiplication in GF(2^n)
+*/
+SecureVector<byte> CMAC::poly_double(const MemoryRegion<byte>& in,
+ byte polynomial)
+ {
+ const bool do_xor = (in[0] & 0x80) ? true : false;
+
+ SecureVector<byte> out = in;
+
+ byte carry = 0;
+ for(u32bit j = out.size(); j != 0; --j)
+ {
+ byte temp = out[j-1];
+ out[j-1] = (temp << 1) | carry;
+ carry = (temp >> 7);
+ }
+
+ if(do_xor)
+ out[out.size()-1] ^= polynomial;
+
+ return out;
+ }
+
+/*
+* Update an CMAC Calculation
+*/
+void CMAC::add_data(const byte input[], u32bit length)
+ {
+ buffer.copy(position, input, length);
+ if(position + length > OUTPUT_LENGTH)
+ {
+ xor_buf(state, buffer, OUTPUT_LENGTH);
+ e->encrypt(state);
+ input += (OUTPUT_LENGTH - position);
+ length -= (OUTPUT_LENGTH - position);
+ while(length > OUTPUT_LENGTH)
+ {
+ xor_buf(state, input, OUTPUT_LENGTH);
+ e->encrypt(state);
+ input += OUTPUT_LENGTH;
+ length -= OUTPUT_LENGTH;
+ }
+ buffer.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Finalize an CMAC Calculation
+*/
+void CMAC::final_result(byte mac[])
+ {
+ xor_buf(state, buffer, position);
+
+ if(position == OUTPUT_LENGTH)
+ {
+ xor_buf(state, B, OUTPUT_LENGTH);
+ }
+ else
+ {
+ state[position] ^= 0x80;
+ xor_buf(state, P, OUTPUT_LENGTH);
+ }
+
+ e->encrypt(state);
+
+ for(u32bit j = 0; j != OUTPUT_LENGTH; ++j)
+ mac[j] = state[j];
+
+ state.clear();
+ buffer.clear();
+ position = 0;
+ }
+
+/*
+* CMAC Key Schedule
+*/
+void CMAC::key_schedule(const byte key[], u32bit length)
+ {
+ clear();
+ e->set_key(key, length);
+ e->encrypt(B);
+ B = poly_double(B, polynomial);
+ P = poly_double(B, polynomial);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CMAC::clear() throw()
+ {
+ e->clear();
+ state.clear();
+ buffer.clear();
+ B.clear();
+ P.clear();
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CMAC::name() const
+ {
+ return "CMAC(" + e->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CMAC::clone() const
+ {
+ return new CMAC(e->clone());
+ }
+
+/*
+* CMAC Constructor
+*/
+CMAC::CMAC(BlockCipher* e_in) :
+ MessageAuthenticationCode(e_in->BLOCK_SIZE,
+ e_in->MINIMUM_KEYLENGTH,
+ e_in->MAXIMUM_KEYLENGTH,
+ e_in->KEYLENGTH_MULTIPLE),
+ e(e_in)
+ {
+ if(e->BLOCK_SIZE == 16)
+ polynomial = 0x87;
+ else if(e->BLOCK_SIZE == 8)
+ polynomial = 0x1B;
+ else
+ throw Invalid_Argument("CMAC cannot use the cipher " + e->name());
+
+ state.create(OUTPUT_LENGTH);
+ buffer.create(OUTPUT_LENGTH);
+ B.create(OUTPUT_LENGTH);
+ P.create(OUTPUT_LENGTH);
+ position = 0;
+ }
+
+/*
+* CMAC Destructor
+*/
+CMAC::~CMAC()
+ {
+ delete e;
+ }
+
+}
diff --git a/botan/src/mac/cmac/cmac.h b/botan/src/mac/cmac/cmac.h
new file mode 100644
index 0000000..5a6deb7
--- /dev/null
+++ b/botan/src/mac/cmac/cmac.h
@@ -0,0 +1,44 @@
+/*
+* CMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMAC_H__
+#define BOTAN_CMAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CMAC
+*/
+class BOTAN_DLL CMAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ static SecureVector<byte> poly_double(const MemoryRegion<byte>& in,
+ byte polynomial);
+
+ CMAC(BlockCipher* e);
+ ~CMAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ SecureVector<byte> buffer, state, B, P;
+ u32bit position;
+ byte polynomial;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/cmac/info.txt b/botan/src/mac/cmac/info.txt
new file mode 100644
index 0000000..b593c9d
--- /dev/null
+++ b/botan/src/mac/cmac/info.txt
@@ -0,0 +1,14 @@
+realname "CMAC"
+
+define CMAC
+
+load_on auto
+
+<add>
+cmac.cpp
+cmac.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/mac/hmac/hmac.cpp b/botan/src/mac/hmac/hmac.cpp
new file mode 100644
index 0000000..717e264
--- /dev/null
+++ b/botan/src/mac/hmac/hmac.cpp
@@ -0,0 +1,99 @@
+/*
+* HMAC
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hmac.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Update a HMAC Calculation
+*/
+void HMAC::add_data(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Finalize a HMAC Calculation
+*/
+void HMAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, OUTPUT_LENGTH);
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*
+* HMAC Key Schedule
+*/
+void HMAC::key_schedule(const byte key[], u32bit length)
+ {
+ hash->clear();
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ if(length > hash->HASH_BLOCK_SIZE)
+ {
+ SecureVector<byte> hmac_key = hash->process(key, length);
+ xor_buf(i_key, hmac_key, hmac_key.size());
+ xor_buf(o_key, hmac_key, hmac_key.size());
+ }
+ else
+ {
+ xor_buf(i_key, key, length);
+ xor_buf(o_key, key, length);
+ }
+
+ hash->update(i_key);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HMAC::clear() throw()
+ {
+ hash->clear();
+ i_key.clear();
+ o_key.clear();
+ }
+
+/*
+* Return the name of this type
+*/
+std::string HMAC::name() const
+ {
+ return "HMAC(" + hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* HMAC::clone() const
+ {
+ return new HMAC(hash->clone());
+ }
+
+/*
+* HMAC Constructor
+*/
+HMAC::HMAC(HashFunction* hash_in) :
+ MessageAuthenticationCode(hash_in->OUTPUT_LENGTH,
+ 1, 2*hash_in->HASH_BLOCK_SIZE),
+ hash(hash_in)
+ {
+ if(hash->HASH_BLOCK_SIZE == 0)
+ throw Invalid_Argument("HMAC cannot be used with " + hash->name());
+
+ i_key.create(hash->HASH_BLOCK_SIZE);
+ o_key.create(hash->HASH_BLOCK_SIZE);
+ }
+
+}
diff --git a/botan/src/mac/hmac/hmac.h b/botan/src/mac/hmac/hmac.h
new file mode 100644
index 0000000..932af71
--- /dev/null
+++ b/botan/src/mac/hmac/hmac.h
@@ -0,0 +1,38 @@
+/*
+* HMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_H__
+#define BOTAN_HMAC_H__
+
+#include <botan/mac.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* HMAC
+*/
+class BOTAN_DLL HMAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ HMAC(HashFunction* hash);
+ ~HMAC() { delete hash; }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+ HashFunction* hash;
+ SecureVector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/hmac/info.txt b/botan/src/mac/hmac/info.txt
new file mode 100644
index 0000000..cdf2e67
--- /dev/null
+++ b/botan/src/mac/hmac/info.txt
@@ -0,0 +1,14 @@
+realname "HMAC"
+
+define HMAC
+
+load_on auto
+
+<add>
+hmac.cpp
+hmac.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/mac/info.txt b/botan/src/mac/info.txt
new file mode 100644
index 0000000..239eb63
--- /dev/null
+++ b/botan/src/mac/info.txt
@@ -0,0 +1,13 @@
+realname "Message Authentication Codes"
+
+load_on auto
+
+<add>
+mac.h
+mac.cpp
+</add>
+
+<requires>
+buf_comp
+sym_algo
+</requires>
diff --git a/botan/src/mac/mac.cpp b/botan/src/mac/mac.cpp
new file mode 100644
index 0000000..96df255
--- /dev/null
+++ b/botan/src/mac/mac.cpp
@@ -0,0 +1,26 @@
+/**
+Message Authentication Code base class
+(C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mac.h>
+
+namespace Botan {
+
+/**
+* Default (deterministic) MAC verification operation
+*/
+bool MessageAuthenticationCode::verify_mac(const byte mac[], u32bit length)
+ {
+ SecureVector<byte> our_mac = final();
+ if(our_mac.size() != length)
+ return false;
+ for(u32bit j = 0; j != length; ++j)
+ if(mac[j] != our_mac[j])
+ return false;
+ return true;
+ }
+
+}
diff --git a/botan/src/mac/mac.h b/botan/src/mac/mac.h
new file mode 100644
index 0000000..3ec5fff
--- /dev/null
+++ b/botan/src/mac/mac.h
@@ -0,0 +1,60 @@
+/**
+* Base class for message authentiction codes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+#define BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+
+#include <botan/buf_comp.h>
+#include <botan/sym_algo.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents Message Authentication Code (MAC) objects.
+*/
+class BOTAN_DLL MessageAuthenticationCode : public BufferedComputation,
+ public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @param length the length of the byte array
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const byte[], u32bit);
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual MessageAuthenticationCode* clone() const = 0;
+
+ /**
+ * Get the name of this algorithm.
+ * @return the name of this algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Reset the internal state of this object.
+ */
+ virtual void clear() throw() = 0;
+
+ MessageAuthenticationCode(u32bit mac_len,
+ u32bit key_min,
+ u32bit key_max = 0,
+ u32bit key_mod = 1) :
+ BufferedComputation(mac_len),
+ SymmetricAlgorithm(key_min, key_max, key_mod) {}
+
+ virtual ~MessageAuthenticationCode() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/ssl3mac/info.txt b/botan/src/mac/ssl3mac/info.txt
new file mode 100644
index 0000000..f879116
--- /dev/null
+++ b/botan/src/mac/ssl3mac/info.txt
@@ -0,0 +1,14 @@
+realname "SSLv3 MAC"
+
+define SSL3_MAC
+
+load_on auto
+
+<add>
+ssl3_mac.cpp
+ssl3_mac.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/mac/ssl3mac/ssl3_mac.cpp b/botan/src/mac/ssl3mac/ssl3_mac.cpp
new file mode 100644
index 0000000..c29296c
--- /dev/null
+++ b/botan/src/mac/ssl3mac/ssl3_mac.cpp
@@ -0,0 +1,90 @@
+/*
+* SSL3-MAC
+* (C) 1999-2004 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ssl3_mac.h>
+
+namespace Botan {
+
+/*
+* Update a SSL3-MAC Calculation
+*/
+void SSL3_MAC::add_data(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Finalize a SSL3-MAC Calculation
+*/
+void SSL3_MAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, OUTPUT_LENGTH);
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*
+* SSL3-MAC Key Schedule
+*/
+void SSL3_MAC::key_schedule(const byte key[], u32bit length)
+ {
+ hash->clear();
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ i_key.copy(key, length);
+ o_key.copy(key, length);
+ hash->update(i_key);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SSL3_MAC::clear() throw()
+ {
+ hash->clear();
+ i_key.clear();
+ o_key.clear();
+ }
+
+/*
+* Return the name of this type
+*/
+std::string SSL3_MAC::name() const
+ {
+ return "SSL3-MAC(" + hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* SSL3_MAC::clone() const
+ {
+ return new SSL3_MAC(hash->clone());
+ }
+
+/*
+* SSL3-MAC Constructor
+*/
+SSL3_MAC::SSL3_MAC(HashFunction* hash_in) :
+ MessageAuthenticationCode(hash_in->OUTPUT_LENGTH,
+ hash_in->OUTPUT_LENGTH),
+ hash(hash_in)
+ {
+ if(hash->HASH_BLOCK_SIZE == 0)
+ throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
+
+ u32bit INNER_HASH_LENGTH =
+ (hash->name() == "SHA-160") ? 60 : hash->HASH_BLOCK_SIZE;
+
+ i_key.create(INNER_HASH_LENGTH);
+ o_key.create(INNER_HASH_LENGTH);
+ }
+
+}
diff --git a/botan/src/mac/ssl3mac/ssl3_mac.h b/botan/src/mac/ssl3mac/ssl3_mac.h
new file mode 100644
index 0000000..dcaf7f4
--- /dev/null
+++ b/botan/src/mac/ssl3mac/ssl3_mac.h
@@ -0,0 +1,39 @@
+/*
+* SSL3-MAC
+* (C) 1999-2004 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSL3_MAC_H__
+#define BOTAN_SSL3_MAC_H__
+
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* SSL3-MAC
+*/
+class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ SSL3_MAC(HashFunction*);
+ ~SSL3_MAC() { delete hash; }
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ HashFunction* hash;
+ SecureVector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mac/x919_mac/info.txt b/botan/src/mac/x919_mac/info.txt
new file mode 100644
index 0000000..f2ebd5b
--- /dev/null
+++ b/botan/src/mac/x919_mac/info.txt
@@ -0,0 +1,14 @@
+realname "ANSI X9.19 MAC"
+
+define ANSI_X919_MAC
+
+load_on auto
+
+<add>
+x919_mac.cpp
+x919_mac.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/mac/x919_mac/x919_mac.cpp b/botan/src/mac/x919_mac/x919_mac.cpp
new file mode 100644
index 0000000..ef89cac
--- /dev/null
+++ b/botan/src/mac/x919_mac/x919_mac.cpp
@@ -0,0 +1,107 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x919_mac.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Update an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::add_data(const byte input[], u32bit length)
+ {
+ u32bit xored = std::min(8 - position, length);
+ xor_buf(state + position, input, xored);
+ position += xored;
+
+ if(position < 8) return;
+
+ e->encrypt(state);
+ input += xored;
+ length -= xored;
+ while(length >= 8)
+ {
+ xor_buf(state, input, 8);
+ e->encrypt(state);
+ input += 8;
+ length -= 8;
+ }
+
+ xor_buf(state, input, length);
+ position = length;
+ }
+
+/*
+* Finalize an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::final_result(byte mac[])
+ {
+ if(position)
+ e->encrypt(state);
+ d->decrypt(state, mac);
+ e->encrypt(mac);
+ state.clear();
+ position = 0;
+ }
+
+/*
+* ANSI X9.19 MAC Key Schedule
+*/
+void ANSI_X919_MAC::key_schedule(const byte key[], u32bit length)
+ {
+ e->set_key(key, 8);
+ if(length == 8) d->set_key(key, 8);
+ else d->set_key(key + 8, 8);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void ANSI_X919_MAC::clear() throw()
+ {
+ e->clear();
+ d->clear();
+ state.clear();
+ position = 0;
+ }
+
+std::string ANSI_X919_MAC::name() const
+ {
+ return "X9.19-MAC";
+ }
+
+MessageAuthenticationCode* ANSI_X919_MAC::clone() const
+ {
+ return new ANSI_X919_MAC(e->clone());
+ }
+
+/*
+* ANSI X9.19 MAC Constructor
+*/
+ANSI_X919_MAC::ANSI_X919_MAC(BlockCipher* e_in) :
+ MessageAuthenticationCode(e_in->BLOCK_SIZE,
+ e_in->MINIMUM_KEYLENGTH,
+ 2*e_in->MAXIMUM_KEYLENGTH,
+ 2*e_in->KEYLENGTH_MULTIPLE),
+ e(e_in), d(e->clone()), position(0)
+ {
+ if(e->name() != "DES")
+ throw Invalid_Argument("ANSI X9.19 MAC only supports DES");
+ }
+
+/*
+* ANSI X9.19 MAC Destructor
+le*/
+ANSI_X919_MAC::~ANSI_X919_MAC()
+ {
+ delete e;
+ delete d;
+ }
+
+}
diff --git a/botan/src/mac/x919_mac/x919_mac.h b/botan/src/mac/x919_mac/x919_mac.h
new file mode 100644
index 0000000..1c2a06b
--- /dev/null
+++ b/botan/src/mac/x919_mac/x919_mac.h
@@ -0,0 +1,41 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X919_MAC_H__
+#define BOTAN_ANSI_X919_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* DES/3DES-based MAC from ANSI X9.19
+*/
+class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ ANSI_X919_MAC(BlockCipher*);
+ ~ANSI_X919_MAC();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+ void key_schedule(const byte[], u32bit);
+
+ BlockCipher* e;
+ BlockCipher* d;
+ SecureBuffer<byte, 8> state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/big_code.cpp b/botan/src/math/bigint/big_code.cpp
new file mode 100644
index 0000000..74701e5
--- /dev/null
+++ b/botan/src/math/bigint/big_code.cpp
@@ -0,0 +1,154 @@
+/*
+* BigInt Encoding/Decoding
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <botan/divide.h>
+#include <botan/charset.h>
+#include <botan/hex.h>
+
+namespace Botan {
+
+/*
+* Encode a BigInt
+*/
+void BigInt::encode(byte output[], const BigInt& n, Base base)
+ {
+ if(base == Binary)
+ n.binary_encode(output);
+ else if(base == Hexadecimal)
+ {
+ SecureVector<byte> binary(n.encoded_size(Binary));
+ n.binary_encode(binary);
+ for(u32bit j = 0; j != binary.size(); ++j)
+ Hex_Encoder::encode(binary[j], output + 2*j);
+ }
+ else if(base == Octal)
+ {
+ BigInt copy = n;
+ const u32bit output_size = n.encoded_size(Octal);
+ for(u32bit j = 0; j != output_size; ++j)
+ {
+ output[output_size - 1 - j] = Charset::digit2char(copy % 8);
+ copy /= 8;
+ }
+ }
+ else if(base == Decimal)
+ {
+ BigInt copy = n;
+ BigInt remainder;
+ copy.set_sign(Positive);
+ const u32bit output_size = n.encoded_size(Decimal);
+ for(u32bit j = 0; j != output_size; ++j)
+ {
+ divide(copy, 10, copy, remainder);
+ output[output_size - 1 - j] =
+ Charset::digit2char(remainder.word_at(0));
+ if(copy.is_zero())
+ break;
+ }
+ }
+ else
+ throw Invalid_Argument("Unknown BigInt encoding method");
+ }
+
+/*
+* Encode a BigInt
+*/
+SecureVector<byte> BigInt::encode(const BigInt& n, Base base)
+ {
+ SecureVector<byte> output(n.encoded_size(base));
+ encode(output, n, base);
+ if(base != Binary)
+ for(u32bit j = 0; j != output.size(); ++j)
+ if(output[j] == 0)
+ output[j] = '0';
+ return output;
+ }
+
+/*
+* Encode a BigInt, with leading 0s if needed
+*/
+SecureVector<byte> BigInt::encode_1363(const BigInt& n, u32bit bytes)
+ {
+ const u32bit n_bytes = n.bytes();
+ if(n_bytes > bytes)
+ throw Encoding_Error("encode_1363: n is too large to encode properly");
+
+ const u32bit leading_0s = bytes - n_bytes;
+
+ SecureVector<byte> output(bytes);
+ encode(output + leading_0s, n, Binary);
+ return output;
+ }
+
+/*
+* Decode a BigInt
+*/
+BigInt BigInt::decode(const MemoryRegion<byte>& buf, Base base)
+ {
+ return BigInt::decode(buf, buf.size(), base);
+ }
+
+/*
+* Decode a BigInt
+*/
+BigInt BigInt::decode(const byte buf[], u32bit length, Base base)
+ {
+ BigInt r;
+ if(base == Binary)
+ r.binary_decode(buf, length);
+ else if(base == Hexadecimal)
+ {
+ SecureVector<byte> hex;
+ for(u32bit j = 0; j != length; ++j)
+ if(Hex_Decoder::is_valid(buf[j]))
+ hex.append(buf[j]);
+
+ u32bit offset = (hex.size() % 2);
+ SecureVector<byte> binary(hex.size() / 2 + offset);
+
+ if(offset)
+ {
+ byte temp[2] = { '0', hex[0] };
+ binary[0] = Hex_Decoder::decode(temp);
+ }
+
+ for(u32bit j = offset; j != binary.size(); ++j)
+ binary[j] = Hex_Decoder::decode(hex+2*j-offset);
+ r.binary_decode(binary, binary.size());
+ }
+ else if(base == Decimal || base == Octal)
+ {
+ const u32bit RADIX = ((base == Decimal) ? 10 : 8);
+ for(u32bit j = 0; j != length; ++j)
+ {
+ if(Charset::is_space(buf[j]))
+ continue;
+
+ if(!Charset::is_digit(buf[j]))
+ throw Invalid_Argument("BigInt::decode: "
+ "Invalid character in decimal input");
+
+ byte x = Charset::char2digit(buf[j]);
+ if(x >= RADIX)
+ {
+ if(RADIX == 10)
+ throw Invalid_Argument("BigInt: Invalid decimal string");
+ else
+ throw Invalid_Argument("BigInt: Invalid octal string");
+ }
+
+ r *= RADIX;
+ r += x;
+ }
+ }
+ else
+ throw Invalid_Argument("Unknown BigInt decoding method");
+ return r;
+ }
+
+}
diff --git a/botan/src/math/bigint/big_io.cpp b/botan/src/math/bigint/big_io.cpp
new file mode 100644
index 0000000..b50fcce
--- /dev/null
+++ b/botan/src/math/bigint/big_io.cpp
@@ -0,0 +1,55 @@
+/*
+* BigInt Input/Output
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <iostream>
+
+namespace Botan {
+
+/*
+* Write the BigInt into a stream
+*/
+std::ostream& operator<<(std::ostream& stream, const BigInt& n)
+ {
+ BigInt::Base base = BigInt::Decimal;
+ if(stream.flags() & std::ios::hex)
+ base = BigInt::Hexadecimal;
+ else if(stream.flags() & std::ios::oct)
+ base = BigInt::Octal;
+
+ if(n == 0)
+ stream.write("0", 1);
+ else
+ {
+ if(n < 0)
+ stream.write("-", 1);
+ SecureVector<byte> buffer = BigInt::encode(n, base);
+ u32bit skip = 0;
+ while(buffer[skip] == '0' && skip < buffer.size())
+ ++skip;
+ stream.write(reinterpret_cast<const char*>(buffer.begin()) + skip,
+ buffer.size() - skip);
+ }
+ if(!stream.good())
+ throw Stream_IO_Error("BigInt output operator has failed");
+ return stream;
+ }
+
+/*
+* Read the BigInt from a stream
+*/
+std::istream& operator>>(std::istream& stream, BigInt& n)
+ {
+ std::string str;
+ std::getline(stream, str);
+ if(stream.bad() || (stream.fail() && !stream.eof()))
+ throw Stream_IO_Error("BigInt input operator has failed");
+ n = BigInt(str);
+ return stream;
+ }
+
+}
diff --git a/botan/src/math/bigint/big_ops2.cpp b/botan/src/math/bigint/big_ops2.cpp
new file mode 100644
index 0000000..488eca9
--- /dev/null
+++ b/botan/src/math/bigint/big_ops2.cpp
@@ -0,0 +1,224 @@
+/*
+* BigInt Assignment Operators
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <botan/mp_core.h>
+#include <botan/bit_ops.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Addition Operator
+*/
+BigInt& BigInt::operator+=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+
+ const u32bit reg_size = std::max(x_sw, y_sw) + 1;
+ grow_to(reg_size);
+
+ if(sign() == y.sign())
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ else
+ {
+ s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
+
+ if(relative_size < 0)
+ {
+ SecureVector<word> z(reg_size - 1);
+ bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
+ copy_mem(get_reg().begin(), z.begin(), z.size());
+ set_sign(y.sign());
+ }
+ else if(relative_size == 0)
+ {
+ get_reg().clear();
+ set_sign(Positive);
+ }
+ else if(relative_size > 0)
+ bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*
+* Subtraction Operator
+*/
+BigInt& BigInt::operator-=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+
+ s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
+
+ const u32bit reg_size = std::max(x_sw, y_sw) + 1;
+ grow_to(reg_size);
+
+ if(relative_size < 0)
+ {
+ if(sign() == y.sign())
+ {
+ SecureVector<word> z(reg_size - 1);
+ bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
+ copy_mem(get_reg().begin(), z.begin(), z.size());
+ }
+ else
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+
+ set_sign(y.reverse_sign());
+ }
+ else if(relative_size == 0)
+ {
+ if(sign() == y.sign())
+ {
+ get_reg().clear();
+ set_sign(Positive);
+ }
+ else
+ bigint_shl1(get_reg(), x_sw, 0, 1);
+ }
+ else if(relative_size > 0)
+ {
+ if(sign() == y.sign())
+ bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ else
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*
+* Multiplication Operator
+*/
+BigInt& BigInt::operator*=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+ set_sign((sign() == y.sign()) ? Positive : Negative);
+
+ if(x_sw == 0 || y_sw == 0)
+ {
+ get_reg().clear();
+ set_sign(Positive);
+ }
+ else if(x_sw == 1 && y_sw)
+ {
+ grow_to(y_sw + 2);
+ bigint_linmul3(get_reg(), y.data(), y_sw, word_at(0));
+ }
+ else if(y_sw == 1 && x_sw)
+ {
+ grow_to(x_sw + 2);
+ bigint_linmul2(get_reg(), x_sw, y.word_at(0));
+ }
+ else
+ {
+ grow_to(size() + y.size());
+
+ SecureVector<word> z(data(), x_sw);
+ SecureVector<word> workspace(size());
+
+ bigint_mul(get_reg(), size(), workspace,
+ z, z.size(), x_sw,
+ y.data(), y.size(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*
+* Division Operator
+*/
+BigInt& BigInt::operator/=(const BigInt& y)
+ {
+ if(y.sig_words() == 1 && power_of_2(y.word_at(0)))
+ (*this) >>= (y.bits() - 1);
+ else
+ (*this) = (*this) / y;
+ return (*this);
+ }
+
+/*
+* Modulo Operator
+*/
+BigInt& BigInt::operator%=(const BigInt& mod)
+ {
+ return (*this = (*this) % mod);
+ }
+
+/*
+* Modulo Operator
+*/
+word BigInt::operator%=(word mod)
+ {
+ if(mod == 0)
+ throw BigInt::DivideByZero();
+ if(power_of_2(mod))
+ {
+ word result = (word_at(0) & (mod - 1));
+ clear();
+ grow_to(2);
+ get_reg()[0] = result;
+ return result;
+ }
+
+ word remainder = 0;
+
+ for(u32bit j = sig_words(); j > 0; --j)
+ remainder = bigint_modop(remainder, word_at(j-1), mod);
+ clear();
+ grow_to(2);
+
+ if(remainder && sign() == BigInt::Negative)
+ get_reg()[0] = mod - remainder;
+ else
+ get_reg()[0] = remainder;
+
+ set_sign(BigInt::Positive);
+
+ return word_at(0);
+ }
+
+/*
+* Left Shift Operator
+*/
+BigInt& BigInt::operator<<=(u32bit shift)
+ {
+ if(shift)
+ {
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS,
+ words = sig_words();
+
+ grow_to(words + shift_words + (shift_bits ? 1 : 0));
+ bigint_shl1(get_reg(), words, shift_words, shift_bits);
+ }
+
+ return (*this);
+ }
+
+/*
+* Right Shift Operator
+*/
+BigInt& BigInt::operator>>=(u32bit shift)
+ {
+ if(shift)
+ {
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS;
+
+ bigint_shr1(get_reg(), sig_words(), shift_words, shift_bits);
+
+ if(is_zero())
+ set_sign(Positive);
+ }
+
+ return (*this);
+ }
+
+}
diff --git a/botan/src/math/bigint/big_ops3.cpp b/botan/src/math/bigint/big_ops3.cpp
new file mode 100644
index 0000000..ad8b7bb
--- /dev/null
+++ b/botan/src/math/bigint/big_ops3.cpp
@@ -0,0 +1,190 @@
+/*
+* BigInt Binary Operators
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <botan/divide.h>
+#include <botan/mp_core.h>
+#include <botan/bit_ops.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Addition Operator
+*/
+BigInt operator+(const BigInt& x, const BigInt& y)
+ {
+ const u32bit x_sw = x.sig_words(), y_sw = y.sig_words();
+
+ BigInt z(x.sign(), std::max(x_sw, y_sw) + 1);
+
+ if((x.sign() == y.sign()))
+ bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ else
+ {
+ s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw);
+
+ if(relative_size < 0)
+ {
+ bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
+ z.set_sign(y.sign());
+ }
+ else if(relative_size == 0)
+ z.set_sign(BigInt::Positive);
+ else if(relative_size > 0)
+ bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ }
+
+ return z;
+ }
+
+/*
+* Subtraction Operator
+*/
+BigInt operator-(const BigInt& x, const BigInt& y)
+ {
+ const u32bit x_sw = x.sig_words(), y_sw = y.sig_words();
+
+ s32bit relative_size = bigint_cmp(x.data(), x_sw, y.data(), y_sw);
+
+ BigInt z(BigInt::Positive, std::max(x_sw, y_sw) + 1);
+
+ if(relative_size < 0)
+ {
+ if(x.sign() == y.sign())
+ bigint_sub3(z.get_reg(), y.data(), y_sw, x.data(), x_sw);
+ else
+ bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ z.set_sign(y.reverse_sign());
+ }
+ else if(relative_size == 0)
+ {
+ if(x.sign() != y.sign())
+ bigint_shl2(z.get_reg(), x.data(), x_sw, 0, 1);
+ }
+ else if(relative_size > 0)
+ {
+ if(x.sign() == y.sign())
+ bigint_sub3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ else
+ bigint_add3(z.get_reg(), x.data(), x_sw, y.data(), y_sw);
+ z.set_sign(x.sign());
+ }
+ return z;
+ }
+
+/*
+* Multiplication Operator
+*/
+BigInt operator*(const BigInt& x, const BigInt& y)
+ {
+ const u32bit x_sw = x.sig_words(), y_sw = y.sig_words();
+
+ BigInt z(BigInt::Positive, x.size() + y.size());
+
+ if(x_sw == 1 && y_sw)
+ bigint_linmul3(z.get_reg(), y.data(), y_sw, x.word_at(0));
+ else if(y_sw == 1 && x_sw)
+ bigint_linmul3(z.get_reg(), x.data(), x_sw, y.word_at(0));
+ else if(x_sw && y_sw)
+ {
+ SecureVector<word> workspace(z.size());
+ bigint_mul(z.get_reg(), z.size(), workspace,
+ x.data(), x.size(), x_sw,
+ y.data(), y.size(), y_sw);
+ }
+
+ if(x_sw && y_sw && x.sign() != y.sign())
+ z.flip_sign();
+ return z;
+ }
+
+/*
+* Division Operator
+*/
+BigInt operator/(const BigInt& x, const BigInt& y)
+ {
+ BigInt q, r;
+ divide(x, y, q, r);
+ return q;
+ }
+
+/*
+* Modulo Operator
+*/
+BigInt operator%(const BigInt& n, const BigInt& mod)
+ {
+ if(mod.is_zero())
+ throw BigInt::DivideByZero();
+ if(mod.is_negative())
+ throw Invalid_Argument("BigInt::operator%: modulus must be > 0");
+ if(n.is_positive() && mod.is_positive() && n < mod)
+ return n;
+
+ BigInt q, r;
+ divide(n, mod, q, r);
+ return r;
+ }
+
+/*
+* Modulo Operator
+*/
+word operator%(const BigInt& n, word mod)
+ {
+ if(mod == 0)
+ throw BigInt::DivideByZero();
+ if(power_of_2(mod))
+ return (n.word_at(0) & (mod - 1));
+
+ word remainder = 0;
+
+ for(u32bit j = n.sig_words(); j > 0; --j)
+ remainder = bigint_modop(remainder, n.word_at(j-1), mod);
+
+ if(remainder && n.sign() == BigInt::Negative)
+ return mod - remainder;
+ return remainder;
+ }
+
+/*
+* Left Shift Operator
+*/
+BigInt operator<<(const BigInt& x, u32bit shift)
+ {
+ if(shift == 0)
+ return x;
+
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS;
+
+ const u32bit x_sw = x.sig_words();
+
+ BigInt y(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0));
+ bigint_shl2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
+ return y;
+ }
+
+/*
+* Right Shift Operator
+*/
+BigInt operator>>(const BigInt& x, u32bit shift)
+ {
+ if(shift == 0)
+ return x;
+ if(x.bits() <= shift)
+ return 0;
+
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS,
+ x_sw = x.sig_words();
+
+ BigInt y(x.sign(), x_sw - shift_words);
+ bigint_shr2(y.get_reg(), x.data(), x_sw, shift_words, shift_bits);
+ return y;
+ }
+
+}
diff --git a/botan/src/math/bigint/big_rand.cpp b/botan/src/math/bigint/big_rand.cpp
new file mode 100644
index 0000000..b641bae
--- /dev/null
+++ b/botan/src/math/bigint/big_rand.cpp
@@ -0,0 +1,61 @@
+/*
+* BigInt Random Generation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Construct a BigInt of a specific form
+*/
+BigInt::BigInt(NumberType type, u32bit bits)
+ {
+ set_sign(Positive);
+
+ if(type == Power2)
+ set_bit(bits);
+ else
+ throw Invalid_Argument("BigInt(NumberType): Unknown type");
+ }
+
+/*
+* Randomize this number
+*/
+void BigInt::randomize(RandomNumberGenerator& rng,
+ u32bit bitsize)
+ {
+ set_sign(Positive);
+
+ if(bitsize == 0)
+ clear();
+ else
+ {
+ SecureVector<byte> array((bitsize + 7) / 8);
+ rng.randomize(array, array.size());
+ if(bitsize % 8)
+ array[0] &= 0xFF >> (8 - (bitsize % 8));
+ array[0] |= 0x80 >> ((bitsize % 8) ? (8 - bitsize % 8) : 0);
+ binary_decode(array, array.size());
+ }
+ }
+
+/*
+* Generate a random integer within given range
+*/
+BigInt BigInt::random_integer(RandomNumberGenerator& rng,
+ const BigInt& min, const BigInt& max)
+ {
+ BigInt range = max - min;
+
+ if(range <= 0)
+ throw Invalid_Argument("random_integer: invalid min/max values");
+
+ return (min + (BigInt(rng, range.bits() + 2) % range));
+ }
+
+}
diff --git a/botan/src/math/bigint/bigint.cpp b/botan/src/math/bigint/bigint.cpp
new file mode 100644
index 0000000..926bedc
--- /dev/null
+++ b/botan/src/math/bigint/bigint.cpp
@@ -0,0 +1,369 @@
+/*
+* BigInt Base
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bigint.h>
+#include <botan/mp_core.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*
+* Construct a BigInt from a regular number
+*/
+BigInt::BigInt(u64bit n)
+ {
+ set_sign(Positive);
+
+ if(n == 0)
+ return;
+
+ const u32bit limbs_needed = sizeof(u64bit) / sizeof(word);
+
+ reg.create(4*limbs_needed);
+ for(u32bit j = 0; j != limbs_needed; ++j)
+ reg[j] = ((n >> (j*MP_WORD_BITS)) & MP_WORD_MASK);
+ }
+
+/*
+* Construct a BigInt of the specified size
+*/
+BigInt::BigInt(Sign s, u32bit size)
+ {
+ reg.create(round_up(size, 8));
+ signedness = s;
+ }
+
+/*
+* Construct a BigInt from a "raw" BigInt
+*/
+BigInt::BigInt(const BigInt& b)
+ {
+ const u32bit b_words = b.sig_words();
+
+ if(b_words)
+ {
+ reg.create(round_up(b_words, 8));
+ reg.copy(b.data(), b_words);
+ set_sign(b.sign());
+ }
+ else
+ {
+ reg.create(2);
+ set_sign(Positive);
+ }
+ }
+
+/*
+* Construct a BigInt from a string
+*/
+BigInt::BigInt(const std::string& str)
+ {
+ Base base = Decimal;
+ u32bit markers = 0;
+ bool negative = false;
+ if(str.length() > 0 && str[0] == '-') { markers += 1; negative = true; }
+
+ if(str.length() > markers + 2 && str[markers ] == '0' &&
+ str[markers + 1] == 'x')
+ { markers += 2; base = Hexadecimal; }
+ else if(str.length() > markers + 1 && str[markers] == '0')
+ { markers += 1; base = Octal; }
+
+ *this = decode(reinterpret_cast<const byte*>(str.data()) + markers,
+ str.length() - markers, base);
+
+ if(negative) set_sign(Negative);
+ else set_sign(Positive);
+ }
+
+/*
+* Construct a BigInt from an encoded BigInt
+*/
+BigInt::BigInt(const byte input[], u32bit length, Base base)
+ {
+ set_sign(Positive);
+ *this = decode(input, length, base);
+ }
+
+/*
+* Construct a BigInt from an encoded BigInt
+*/
+BigInt::BigInt(RandomNumberGenerator& rng, u32bit bits)
+ {
+ set_sign(Positive);
+ randomize(rng, bits);
+ }
+
+/*
+* Swap this BigInt with another
+*/
+void BigInt::swap(BigInt& other)
+ {
+ reg.swap(other.reg);
+ std::swap(signedness, other.signedness);
+ }
+
+/*
+* Grow the internal storage
+*/
+void BigInt::grow_reg(u32bit n)
+ {
+ reg.grow_to(round_up(size() + n, 8));
+ }
+
+/*
+* Grow the internal storage
+*/
+void BigInt::grow_to(u32bit n)
+ {
+ if(n > size())
+ reg.grow_to(round_up(n, 8));
+ }
+
+/*
+* Comparison Function
+*/
+s32bit BigInt::cmp(const BigInt& n, bool check_signs) const
+ {
+ if(check_signs)
+ {
+ if(n.is_positive() && this->is_negative()) return -1;
+ if(n.is_negative() && this->is_positive()) return 1;
+ if(n.is_negative() && this->is_negative())
+ return (-bigint_cmp(data(), sig_words(), n.data(), n.sig_words()));
+ }
+ return bigint_cmp(data(), sig_words(), n.data(), n.sig_words());
+ }
+
+/*
+* Convert this number to a u32bit, if possible
+*/
+u32bit BigInt::to_u32bit() const
+ {
+ if(is_negative())
+ throw Encoding_Error("BigInt::to_u32bit: Number is negative");
+ if(bits() >= 32)
+ throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
+
+ u32bit out = 0;
+ for(u32bit j = 0; j != 4; ++j)
+ out = (out << 8) | byte_at(3-j);
+ return out;
+ }
+
+/*
+* Return byte n of this number
+*/
+byte BigInt::byte_at(u32bit n) const
+ {
+ const u32bit WORD_BYTES = sizeof(word);
+ u32bit word_num = n / WORD_BYTES, byte_num = n % WORD_BYTES;
+ if(word_num >= size())
+ return 0;
+ else
+ return get_byte(WORD_BYTES - byte_num - 1, reg[word_num]);
+ }
+
+/*
+* Return bit n of this number
+*/
+bool BigInt::get_bit(u32bit n) const
+ {
+ return ((word_at(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1);
+ }
+
+/*
+* Return bits {offset...offset+length}
+*/
+u32bit BigInt::get_substring(u32bit offset, u32bit length) const
+ {
+ if(length > 32)
+ throw Invalid_Argument("BigInt::get_substring: Substring size too big");
+
+ u64bit piece = 0;
+ for(u32bit j = 0; j != 8; ++j)
+ piece = (piece << 8) | byte_at((offset / 8) + (7-j));
+
+ u64bit mask = (1 << length) - 1;
+ u32bit shift = (offset % 8);
+
+ return static_cast<u32bit>((piece >> shift) & mask);
+ }
+
+/*
+* Set bit number n
+*/
+void BigInt::set_bit(u32bit n)
+ {
+ const u32bit which = n / MP_WORD_BITS;
+ const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
+ if(which >= size()) grow_to(which + 1);
+ reg[which] |= mask;
+ }
+
+/*
+* Clear bit number n
+*/
+void BigInt::clear_bit(u32bit n)
+ {
+ const u32bit which = n / MP_WORD_BITS;
+ const word mask = static_cast<word>(1) << (n % MP_WORD_BITS);
+ if(which < size())
+ reg[which] &= ~mask;
+ }
+
+/*
+* Clear all but the lowest n bits
+*/
+void BigInt::mask_bits(u32bit n)
+ {
+ if(n == 0) { clear(); return; }
+ if(n >= bits()) return;
+
+ const u32bit top_word = n / MP_WORD_BITS;
+ const word mask = (static_cast<word>(1) << (n % MP_WORD_BITS)) - 1;
+
+ if(top_word < size())
+ for(u32bit j = top_word + 1; j != size(); ++j)
+ reg[j] = 0;
+
+ reg[top_word] &= mask;
+ }
+
+/*
+* Count how many bytes are being used
+*/
+u32bit BigInt::bytes() const
+ {
+ return (bits() + 7) / 8;
+ }
+
+/*
+* Count how many bits are being used
+*/
+u32bit BigInt::bits() const
+ {
+ if(sig_words() == 0)
+ return 0;
+
+ u32bit full_words = sig_words() - 1, top_bits = MP_WORD_BITS;
+ word top_word = word_at(full_words), mask = MP_WORD_TOP_BIT;
+
+ while(top_bits && ((top_word & mask) == 0))
+ { mask >>= 1; top_bits--; }
+
+ return (full_words * MP_WORD_BITS + top_bits);
+ }
+
+/*
+* Calcluate the size in a certain base
+*/
+u32bit BigInt::encoded_size(Base base) const
+ {
+ static const double LOG_2_BASE_10 = 0.30102999566;
+
+ if(base == Binary)
+ return bytes();
+ else if(base == Hexadecimal)
+ return 2*bytes();
+ else if(base == Octal)
+ return ((bits() + 2) / 3);
+ else if(base == Decimal)
+ return static_cast<u32bit>((bits() * LOG_2_BASE_10) + 1);
+ else
+ throw Invalid_Argument("Unknown base for BigInt encoding");
+ }
+
+/*
+* Set the sign
+*/
+void BigInt::set_sign(Sign s)
+ {
+ if(is_zero())
+ signedness = Positive;
+ else
+ signedness = s;
+ }
+
+/*
+* Reverse the value of the sign flag
+*/
+void BigInt::flip_sign()
+ {
+ set_sign(reverse_sign());
+ }
+
+/*
+* Return the opposite value of the current sign
+*/
+BigInt::Sign BigInt::reverse_sign() const
+ {
+ if(sign() == Positive)
+ return Negative;
+ return Positive;
+ }
+
+/*
+* Return the negation of this number
+*/
+BigInt BigInt::operator-() const
+ {
+ BigInt x = (*this);
+ x.flip_sign();
+ return x;
+ }
+
+/*
+* Return the absolute value of this number
+*/
+BigInt BigInt::abs() const
+ {
+ BigInt x = (*this);
+ x.set_sign(Positive);
+ return x;
+ }
+
+/*
+* Encode this number into bytes
+*/
+void BigInt::binary_encode(byte output[]) const
+ {
+ const u32bit sig_bytes = bytes();
+ for(u32bit j = 0; j != sig_bytes; ++j)
+ output[sig_bytes-j-1] = byte_at(j);
+ }
+
+/*
+* Set this number to the value in buf
+*/
+void BigInt::binary_decode(const byte buf[], u32bit length)
+ {
+ const u32bit WORD_BYTES = sizeof(word);
+
+ reg.create(round_up((length / WORD_BYTES) + 1, 8));
+
+ for(u32bit j = 0; j != length / WORD_BYTES; ++j)
+ {
+ u32bit top = length - WORD_BYTES*j;
+ for(u32bit k = WORD_BYTES; k > 0; --k)
+ reg[j] = (reg[j] << 8) | buf[top - k];
+ }
+ for(u32bit j = 0; j != length % WORD_BYTES; ++j)
+ reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[j];
+ }
+
+/*
+* Set this number to the value in buf
+*/
+void BigInt::binary_decode(const MemoryRegion<byte>& buf)
+ {
+ binary_decode(buf, buf.size());
+ }
+
+}
diff --git a/botan/src/math/bigint/bigint.h b/botan/src/math/bigint/bigint.h
new file mode 100644
index 0000000..16a1bba
--- /dev/null
+++ b/botan/src/math/bigint/bigint.h
@@ -0,0 +1,534 @@
+/*
+* BigInt
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BIGINT_H__
+#define BOTAN_BIGINT_H__
+
+#include <botan/rng.h>
+#include <botan/secmem.h>
+#include <botan/mp_types.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+ * Big Integer representation. This class defines an integer type,
+ * that can be very big. Additionally some helper functions are
+ * defined to work more comfortably.
+
+ */
+class BOTAN_DLL BigInt
+ {
+ public:
+ /**
+ * Base-Enumerator (currently 8,10,16 and 256 are defined)
+ */
+ enum Base { Octal = 8, Decimal = 10, Hexadecimal = 16, Binary = 256 };
+
+ /**
+ * Sign symbol definitions for positive and negative numbers
+ */
+ enum Sign { Negative = 0, Positive = 1 };
+
+ /**
+ * Number types (Powers of 2)
+ */
+ enum NumberType { Power2 };
+
+ /**
+ * DivideByZero Exception
+ */
+ struct DivideByZero : public Exception
+ { DivideByZero() : Exception("BigInt divide by zero") {} };
+
+ /*************
+ * operators
+ *************/
+
+ /**
+ * += Operator
+ * @param y the BigInt to add to the local value
+ */
+ BigInt& operator+=(const BigInt& y);
+
+ /**
+ * -= Operator
+ * @param y the BigInt to subtract from the local value
+ */
+ BigInt& operator-=(const BigInt& y);
+
+ /**
+ * *= Operator
+ * @param y the BigInt to multiply with the local value
+ */
+ BigInt& operator*=(const BigInt& y);
+
+ /**
+ * /= Operator
+ * @param y the BigInt to divide the local value by
+ */
+ BigInt& operator/=(const BigInt& y);
+
+ /**
+ * %= Operator, modulo operator.
+ * @param y the modulus to reduce the local value by
+ */
+ BigInt& operator%=(const BigInt& y);
+
+ /**
+ * %= Operator
+ * @param y the modulus (word) to reduce the local value by
+ */
+ word operator%=(word y);
+
+ /**
+ * <<= Operator
+ * @param y the amount of bits to shift the local value left
+ */
+ BigInt& operator<<=(u32bit y);
+
+ /**
+ * >>= Operator
+ * @param y the amount of bits to shift the local value right
+ */
+ BigInt& operator>>=(u32bit y);
+
+ /**
+ * ++ Operator
+ */
+ BigInt& operator++() { return (*this += 1); }
+
+ /**
+ * -- Operator
+ */
+ BigInt& operator--() { return (*this -= 1); }
+
+ /**
+ * ++ Operator (postfix)
+ */
+ BigInt operator++(int) { BigInt x = (*this); ++(*this); return x; }
+
+ /**
+ * -- Operator (postfix)
+ */
+ BigInt operator--(int) { BigInt x = (*this); --(*this); return x; }
+
+ /**
+ * - Operator
+ */
+ BigInt operator-() const;
+
+ /**
+ * ! Operator
+ */
+ bool operator !() const { return (!is_nonzero()); }
+
+ /**
+ * [] Operator (array access)
+ */
+ word& operator[](u32bit i) { return reg[i]; }
+
+ /**
+ * [] Operator (array access)
+ */
+ word operator[](u32bit i) const { return reg[i]; }
+
+ /**
+ * Zeroize the BigInt
+ */
+ void clear() { get_reg().clear(); }
+
+ /*************
+ * functions
+ ************/
+
+ /**
+ * Compare *this to another BigInt.
+ * @param n the BigInt value to compare to the local value.
+ * @param check_signs Include sign in comparison?
+ * @result if (this<n) return -1, if (this>n) return 1, if both
+ * values are identical return 0.
+ */
+ s32bit cmp(const BigInt& n, bool check_signs = true) const;
+
+ /**
+ * Test if the integer has an even value
+ * @result true, if the integer an even value, false otherwise
+ */
+ bool is_even() const { return (get_bit(0) == 0); }
+
+ /**
+ * Test if the integer has an odd value
+ * @result true, if the integer an odd value, false otherwise
+ */
+ bool is_odd() const { return (get_bit(0) == 1); }
+
+ /**
+ * Test if the integer is not zero.
+ * @result true, if the integer has a non-zero value, false otherwise
+ */
+ bool is_nonzero() const { return (!is_zero()); }
+
+ /**
+ * Test if the integer is zero.
+ * @result true, if the integer has the value zero, false otherwise
+ */
+ bool is_zero() const
+ {
+ const u32bit sw = sig_words();
+
+ for(u32bit i = 0; i != sw; ++i)
+ if(reg[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Set bit at specified position
+ * @param n bit position to set
+ */
+ void set_bit(u32bit n);
+
+ /**
+ * Clear bit at specified position
+ * @param n bit position to clear
+ */
+ void clear_bit(u32bit n);
+
+ /**
+ * Clear all but the lowest n bits
+ * @param n amount of bits to keep
+ */
+ void mask_bits(u32bit n);
+
+ /**
+ * Return bit value at specified position
+ * @param n the bit offset to test
+ * @result true, if the bit at position n is set, false otherwise
+ */
+ bool get_bit(u32bit n) const;
+
+ /**
+ * Return (a maximum of) 32 bits of the complete value
+ * @param offset the offset to start extracting
+ * @param length amount of bits to extract (starting at offset)
+ * @result the integer extracted from the register starting at
+ * offset with specified length
+ */
+ u32bit get_substring(u32bit offset, u32bit length) const;
+
+ byte byte_at(u32bit) const;
+
+ /**
+ * Return the word at a specified position of the internal register
+ * @param n position in the register
+ * @return the value at position n
+ */
+ word word_at(u32bit n) const
+ { return ((n < size()) ? reg[n] : 0); }
+
+ /**
+ * Return the integer as an unsigned 32bit-integer-value. If the
+ * value is negative OR to big to be stored in 32bits, this
+ * function will throw an exception.
+ * @result a 32bit-integer
+ */
+ u32bit to_u32bit() const;
+
+ /**
+ * Tests if the sign of the integer is negative.
+ * @result true, if the integer has a negative sign,
+ */
+ bool is_negative() const { return (sign() == Negative); }
+
+ /**
+ * Tests if the sign of the integer is positive.
+ * @result true, if the integer has a positive sign,
+ */
+ bool is_positive() const { return (sign() == Positive); }
+
+ /**
+ * Return the sign of the integer
+ * @result the sign of the integer
+ */
+ Sign sign() const { return (signedness); }
+
+ /**
+ * Return the opposite sign of the represented integer value
+ * @result the opposite sign of the represented integer value
+ */
+ Sign reverse_sign() const;
+
+ /**
+ * Flip (change!) the sign of the integer to its opposite value
+ */
+ void flip_sign();
+
+ /**
+ * Set sign of the integer
+ * @param sign new Sign to set
+ */
+ void set_sign(Sign sign);
+
+ /**
+ * Give absolute (positive) value of the integer
+ * @result absolute (positive) value of the integer
+ */
+ BigInt abs() const;
+
+ /**
+ * Give size of internal register
+ * @result size of internal register in words
+ */
+ u32bit size() const { return get_reg().size(); }
+
+ /**
+ * Give significant words of the represented integer value
+ * @result significant words of the represented integer value
+ */
+ u32bit sig_words() const
+ {
+ const word* x = reg.begin();
+ u32bit sig = reg.size();
+
+ while(sig && (x[sig-1] == 0))
+ sig--;
+ return sig;
+ }
+
+ /**
+ * Give byte-length of the integer
+ * @result byte-length of the represented integer value
+ */
+ u32bit bytes() const;
+
+ /**
+ * Get the bit-length of the integer.
+ * @result bit-length of the represented integer value
+ */
+ u32bit bits() const;
+
+ /**
+ * Return a pointer to the big integer word register.
+ * @result a pointer to the start of the internal register of
+ * the integer value
+ */
+ const word* data() const { return reg.begin(); }
+
+ /**
+ * return a reference to the internal register containing the value
+ * @result a reference to the word-array (SecureVector<word>)
+ * with the internal register value (containing the integer
+ * value)
+ */
+ SecureVector<word>& get_reg() { return reg; }
+
+ /**
+ * return a const reference to the internal register containing the value
+ * @result a const reference to the word-array (SecureVector<word>)
+ * with the internal register value (containing the integer
+ * value)
+ */
+ const SecureVector<word>& get_reg() const { return reg; }
+
+ /**
+ * Increase internal register buffer by n words
+ * @param n increase by n words
+ */
+ void grow_reg(u32bit n);
+
+ void grow_to(u32bit n);
+
+ /**
+ * Fill BigInt with a random number with size of bitsize
+ * @param rng the random number generator to use
+ * @param bitsize number of bits the created random value should have
+ */
+ void randomize(RandomNumberGenerator& rng, u32bit bitsize = 0);
+
+ /**
+ * Store BigInt-value in a given byte array
+ * @param buf destination byte array for the integer value
+ */
+ void binary_encode(byte buf[]) const;
+
+ /**
+ * Read integer value from a byte array with given size
+ * @param buf byte array buffer containing the integer
+ * @param length size of buf
+ */
+ void binary_decode(const byte buf[], u32bit length);
+
+ /**
+ * Read integer value from a byte array (MemoryRegion<byte>)
+ * @param buf the BigInt value to compare to the local value.
+ */
+ void binary_decode(const MemoryRegion<byte>& buf);
+
+ u32bit encoded_size(Base = Binary) const;
+
+ /**
+ @param rng a random number generator
+ @result a random integer between min and max
+ */
+ static BigInt random_integer(RandomNumberGenerator& rng,
+ const BigInt& min, const BigInt& max);
+
+ /**
+ * Encode the integer value from a BigInt to a SecureVector of bytes
+ * @param n the BigInt to use as integer source
+ * @param base number-base of resulting byte array representation
+ * @result SecureVector of bytes containing the integer with given base
+ */
+ static SecureVector<byte> encode(const BigInt& n, Base base = Binary);
+
+ /**
+ * Encode the integer value from a BigInt to a byte array
+ * @param buf destination byte array for the encoded integer
+ * value with given base
+ * @param n the BigInt to use as integer source
+ * @param base number-base of resulting byte array representation
+ */
+ static void encode(byte buf[], const BigInt& n, Base base = Binary);
+
+ /**
+ * Create a BigInt from an integer in a byte array
+ * @param buf the BigInt value to compare to the local value.
+ * @param length size of buf
+ * @param base number-base of the integer in buf
+ * @result BigInt-representing the given integer read from the byte array
+ */
+ static BigInt decode(const byte buf[], u32bit length,
+ Base base = Binary);
+
+ static BigInt decode(const MemoryRegion<byte>&, Base = Binary);
+
+ /**
+ * Encode a Big Integer to a byte array according to IEEE1363.
+ * @param n the Big Integer to encode
+ * @param bytes the length of the resulting SecureVector<byte>
+ * @result a SecureVector<byte> containing the encoded Big Integer
+ */
+ static SecureVector<byte> encode_1363(const BigInt& n, u32bit bytes);
+
+ /**
+ * Swap BigInt-value with given BigInt.
+ * @param bigint the BigInt to swap values with
+ */
+ void swap(BigInt& bigint);
+
+ /**
+ * constructors
+ */
+
+ /**
+ * Create empty BigInt
+ */
+ BigInt() { signedness = Positive; }
+
+ /**
+ * Create BigInt from 64bit-Integer value
+ * @param n 64bit-integer
+ */
+ BigInt(u64bit n);
+
+ /**
+ * Copy-Constructor: clone given BigInt
+ * @param bigint the BigInt to clone
+ */
+ BigInt(const BigInt& bigint);
+
+ /**
+ * Create BigInt from a string.
+ * If the string starts with 0x the rest of the string will be
+ * interpreted as hexadecimal digits.
+ * If the string starts with 0 and the second character is NOT
+ * an 'x' the string will be interpreted as octal digits.
+ * If the string starts with non-zero digit, it will be
+ * interpreted as a decimal number.
+ * @param str the string to parse for an integer value
+ */
+ BigInt(const std::string& str);
+
+ /**
+ * Create a BigInt from an integer in a byte array
+ * @param buf the BigInt value to compare to the local value.
+ * @param length size of buf
+ * @param base number-base of the integer in buf
+ */
+ BigInt(const byte buf[], u32bit length, Base base = Binary);
+
+ /**
+ * Create a random BigInt of the specified size
+ * @param rng random number generator
+ * @param bits size in bits
+ */
+ BigInt(RandomNumberGenerator& rng, u32bit bits);
+
+ /**
+ * Create BigInt from unsigned 32 bit integer value and an
+ * also specify the sign of the value
+ * @param n integer value
+ */
+ BigInt(Sign, u32bit n);
+
+ /**
+ * Create a number of the specified type and size
+ * @param type the type of number to create
+ * @param n the size
+ */
+ BigInt(NumberType type, u32bit n);
+
+ private:
+ SecureVector<word> reg;
+ Sign signedness;
+ };
+
+/*
+* Arithmetic Operators
+*/
+BigInt BOTAN_DLL operator+(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator-(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator*(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator/(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL operator%(const BigInt&, const BigInt&);
+word BOTAN_DLL operator%(const BigInt&, word);
+BigInt BOTAN_DLL operator<<(const BigInt&, u32bit);
+BigInt BOTAN_DLL operator>>(const BigInt&, u32bit);
+
+/*
+* Comparison Operators
+*/
+inline bool operator==(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) == 0); }
+inline bool operator!=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) != 0); }
+inline bool operator<=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) <= 0); }
+inline bool operator>=(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) >= 0); }
+inline bool operator<(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) < 0); }
+inline bool operator>(const BigInt& a, const BigInt& b)
+ { return (a.cmp(b) > 0); }
+
+/*
+* I/O Operators
+*/
+BOTAN_DLL std::ostream& operator<<(std::ostream&, const BigInt&);
+BOTAN_DLL std::istream& operator>>(std::istream&, BigInt&);
+
+}
+
+namespace std {
+
+inline void swap(Botan::BigInt& a, Botan::BigInt& b) { a.swap(b); }
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/divide.cpp b/botan/src/math/bigint/divide.cpp
new file mode 100644
index 0000000..6afaa0f
--- /dev/null
+++ b/botan/src/math/bigint/divide.cpp
@@ -0,0 +1,106 @@
+/*
+* Division Algorithm
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/divide.h>
+#include <botan/mp_core.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Handle signed operands, if necessary
+*/
+void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r)
+ {
+ if(x.sign() == BigInt::Negative)
+ {
+ q.flip_sign();
+ if(r.is_nonzero()) { --q; r = y.abs() - r; }
+ }
+ if(y.sign() == BigInt::Negative)
+ q.flip_sign();
+ }
+
+}
+
+/*
+* Solve x = q * y + r
+*/
+void divide(const BigInt& x, const BigInt& y_arg, BigInt& q, BigInt& r)
+ {
+ if(y_arg.is_zero())
+ throw BigInt::DivideByZero();
+
+ BigInt y = y_arg;
+ const u32bit y_words = y.sig_words();
+ r = x;
+
+ r.set_sign(BigInt::Positive);
+ y.set_sign(BigInt::Positive);
+
+ s32bit compare = r.cmp(y);
+
+ if(compare < 0)
+ q = 0;
+ else if(compare == 0)
+ {
+ q = 1;
+ r = 0;
+ }
+ else
+ {
+ u32bit shifts = 0;
+ word y_top = y[y.sig_words()-1];
+ while(y_top < MP_WORD_TOP_BIT) { y_top <<= 1; ++shifts; }
+ y <<= shifts;
+ r <<= shifts;
+
+ const u32bit n = r.sig_words() - 1, t = y_words - 1;
+
+ q.get_reg().create(n - t + 1);
+ if(n <= t)
+ {
+ while(r > y) { r -= y; ++q; }
+ r >>= shifts;
+ sign_fixup(x, y_arg, q, r);
+ return;
+ }
+
+ BigInt temp = y << (MP_WORD_BITS * (n-t));
+
+ while(r >= temp) { r -= temp; ++q[n-t]; }
+
+ for(u32bit j = n; j != t; --j)
+ {
+ const word x_j0 = r.word_at(j);
+ const word x_j1 = r.word_at(j-1);
+ const word y_t = y.word_at(t);
+
+ if(x_j0 == y_t)
+ q[j-t-1] = MP_WORD_MAX;
+ else
+ q[j-t-1] = bigint_divop(x_j0, x_j1, y_t);
+
+ while(bigint_divcore(q[j-t-1], y_t, y.word_at(t-1),
+ x_j0, x_j1, r.word_at(j-2)))
+ --q[j-t-1];
+
+ r -= (q[j-t-1] * y) << (MP_WORD_BITS * (j-t-1));
+ if(r.is_negative())
+ {
+ r += y << (MP_WORD_BITS * (j-t-1));
+ --q[j-t-1];
+ }
+ }
+ r >>= shifts;
+ }
+
+ sign_fixup(x, y_arg, q, r);
+ }
+
+}
diff --git a/botan/src/math/bigint/divide.h b/botan/src/math/bigint/divide.h
new file mode 100644
index 0000000..9445b13
--- /dev/null
+++ b/botan/src/math/bigint/divide.h
@@ -0,0 +1,19 @@
+/*
+* Division
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DIVISON_ALGORITHM_H__
+#define BOTAN_DIVISON_ALGORITHM_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+void BOTAN_DLL divide(const BigInt&, const BigInt&, BigInt&, BigInt&);
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/info.txt b/botan/src/math/bigint/info.txt
new file mode 100644
index 0000000..513703d
--- /dev/null
+++ b/botan/src/math/bigint/info.txt
@@ -0,0 +1,33 @@
+realname "BigInt"
+
+load_on auto
+
+define BIGINT
+
+<add>
+bigint.h
+divide.h
+mp_core.h
+mp_types.h
+big_code.cpp
+big_io.cpp
+big_ops2.cpp
+big_ops3.cpp
+big_rand.cpp
+bigint.cpp
+divide.cpp
+mp_asm.cpp
+mp_comba.cpp
+mp_karat.cpp
+mp_misc.cpp
+mp_shift.cpp
+</add>
+
+<requires>
+alloc
+hex
+mp_amd64|mp_asm64|mp_ia32|mp_ia32_msvc|mp_generic
+monty_generic
+mulop_generic
+rng
+</requires>
diff --git a/botan/src/math/bigint/monty_amd64/info.txt b/botan/src/math/bigint/monty_amd64/info.txt
new file mode 100644
index 0000000..a897045
--- /dev/null
+++ b/botan/src/math/bigint/monty_amd64/info.txt
@@ -0,0 +1,32 @@
+realname "Montgomery Reduction (x86-64)"
+
+mp_bits 64
+
+load_on never
+
+<add>
+mp_monty.S
+</add>
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_amd64
+</requires>
diff --git a/botan/src/math/bigint/monty_amd64/mp_monty.S b/botan/src/math/bigint/monty_amd64/mp_monty.S
new file mode 100644
index 0000000..22045c3
--- /dev/null
+++ b/botan/src/math/bigint/monty_amd64/mp_monty.S
@@ -0,0 +1,399 @@
+/*
+* Montgomery Reduction Source File
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(mp_monty.S)
+
+START_FUNCTION(bigint_monty_redc)
+ pushq %r15 #
+ pushq %r14 #
+ pushq %r13 #
+ pushq %r12 #
+ pushq %rbp #
+ pushq %rbx #
+
+ movq %rdi, %r14 # z
+ movq %rdx, %r12 # x
+ movl %esi, %ebp # z_size
+
+ xorl %esi, %esi # j.76
+ movq %r8, -16(%rsp) # u, u
+ movl %ecx, %ebx # x_size, x_size
+ movl %ecx, %r8d # x_size, blocks_of_8
+ andl $-8, %r8d #, blocks_of_8
+ testl %ecx, %ecx # x_size
+ je .L3 #,
+ mov %ecx, %eax # x_size, pretmp.71
+ leal 1(%rbx), %r15d #, k.73
+ salq $3, %rax #,
+ xorl %r13d, %r13d # j
+ movq %rax, -8(%rsp) #, pretmp.21
+ .p2align 4,,10
+ .p2align 3
+.L11:
+ mov %r13d, %eax # j, j
+ movq -16(%rsp), %rdi # u, y
+ leaq (%r14,%rax,8), %r11 #, z_j
+ xorl %r9d, %r9d # i
+ imulq (%r11), %rdi #* z_j, y
+ xorl %r10d, %r10d # carry
+ testl %r8d, %r8d # blocks_of_8
+ je .L7 #,
+ .p2align 4,,10
+ .p2align 3
+.LOOP_MUL_ADD:
+ mov %r9d, %ecx # i, i
+ addl $8, %r9d #, i
+ salq $3, %rcx #, D.2315
+ leaq (%r11,%rcx), %rsi #, tmp130
+ leaq (%r12,%rcx), %rcx #, tmp131
+
+ movq 8*0(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*0(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*0 (%rsi)
+
+ movq 8*1(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*1(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*1 (%rsi)
+
+ movq 8*2(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*2(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*2 (%rsi)
+
+ movq 8*3(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*3(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*3 (%rsi)
+
+ movq 8*4(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*4(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*4 (%rsi)
+
+ movq 8*5(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*5(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*5 (%rsi)
+
+ movq 8*6(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*6(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*6 (%rsi)
+
+ movq 8*7(%rcx), %rax
+ mulq %rdi # y
+ addq %r10, %rax # carry
+ adcq $0,%rdx
+ addq 8*7(%rsi), %rax
+ adcq $0,%rdx
+ movq %rdx,%r10 # carry
+ movq %rax, 8*7 (%rsi)
+
+ cmpl %r9d, %r8d # i, blocks_of_8
+ jne .LOOP_MUL_ADD #,
+ cmpl %r8d, %ebx # blocks_of_8, x_size
+ je .L8 #,
+.L7:
+ movl %r8d, %esi # blocks_of_8, i
+ .p2align 4,,10
+ .p2align 3
+.L5:
+ mov %esi, %eax # i, i
+ movq %rdi, %rcx # y, b
+ leaq (%r11, %rax,8), %r9 #, D.2325
+ incl %esi # i
+ movq (%r12, %rax,8), %rax #* x, tmp133
+
+ mulq %rcx # b
+ addq (%r9), %rax #* D.2325, a
+ adcq $0,%rdx #
+ addq %r10, %rax # carry, a
+ adcq $0,%rdx #
+
+ cmpl %esi, %ebx # i, x_size
+ movq %rdx, %r10 #, carry
+ movq %rax, (%r9) # a,* D.2325
+ jne .L5 #,
+.L8:
+ movq -8(%rsp), %rdx # pretmp.21,
+ leaq (%r11,%rdx), %rax #, D.2332
+ movq (%rax), %rcx #* D.2332, D.2333
+ leaq (%r10,%rcx), %rdx #, z_sum
+ movq %rdx, (%rax) # z_sum,* D.2332
+ cmpq %rdx, %rcx # z_sum, D.2333
+ jbe .L9 #,
+ cmpl %ebp, %r15d # z_size, k.73
+ je .L9 #,
+ movl %r15d, %ecx # k.73, k
+ jmp .L10 #
+ .p2align 4,,10
+ .p2align 3
+.L31:
+ incl %ecx # k
+ cmpl %ecx, %ebp # k, z_size
+ .p2align 4,,4
+ .p2align 3
+ je .L9 #,
+.L10:
+ mov %ecx, %edx # k, k
+ leaq (%r11,%rdx,8), %rdx #, D.2342
+ movq (%rdx), %rax #* D.2342, tmp136
+ incq %rax # D.2344
+ movq %rax, (%rdx) # D.2344,* D.2342
+ testq %rax, %rax # D.2344
+ je .L31 #,
+.L9:
+ incl %r13d # j
+ decl %ebp # z_size
+ cmpl %r13d, %ebx # j, x_size
+ jne .L11 #,
+ movl %ebx, %esi # x_size, j.76
+.L3:
+ leal (%rbx,%rbx), %eax #, tmp137
+ mov %eax, %eax
+ leaq (%r14, %rax,8), %rdi #, D.2349
+ cmpq $0, (%rdi) #,* D.2349
+ jne .L12 #,
+ testl %ebx, %ebx # x_size
+ je .L12 #,
+ leal -1(%rbx), %ecx #, j
+ leal (%rsi,%rcx), %edx #, tmp141
+ mov %ecx, %eax # j, j
+ movq (%r14,%rdx,8), %rbp #* z,
+ cmpq %rbp, (%r12, %rax,8) #,* x
+ jb .L12 #,
+ ja .L_EXIT #,
+ leal -2(%rsi,%rbx), %edx #, ivtmp.45
+ jmp .L14 #
+ .p2align 4,,10
+ .p2align 3
+.L15:
+ mov %edx, %eax # ivtmp.45, ivtmp.45
+ decl %ecx # j
+ movq (%r14, %rax,8), %rsi #* z, D.2360
+ mov %ecx, %eax # j, j
+ movq (%r12, %rax,8), %rax #* x, temp.68
+ cmpq %rax, %rsi
+ ja .L12 #,
+ decl %edx # ivtmp.45
+ cmpq %rax, %rsi
+ jb .L_EXIT #,
+.L14:
+ testl %ecx, %ecx # j
+ jne .L15 #,
+.L12:
+ xorl %ecx, %ecx # j
+ xorl %r10d, %r10d # carry
+ mov %ebx, %esi # x_size, pretmp.19
+ testl %r8d, %r8d # blocks_of_8
+ je .L17 #,
+ .p2align 4,,10
+ .p2align 3
+.L22:
+ mov %ecx, %edx # j, D.2375
+ addl $8, %ecx #, j
+ leaq (%rdx,%rsi), %rax #, tmp146
+ leaq (%r12,%rdx,8), %rdx #, tmp150
+ leaq (%r14, %rax,8), %rax #, tmp148
+
+ rorq %r10 # carry
+
+ movq 8*0(%rdx), %r10
+ sbbq %r10, 8*0(%rax)
+
+ movq 8*1(%rdx), %r10
+ sbbq %r10, 8*1(%rax)
+
+ movq 8*2(%rdx), %r10
+ sbbq %r10, 8*2(%rax)
+
+ movq 8*3(%rdx), %r10
+ sbbq %r10, 8*3(%rax)
+
+ movq 8*4(%rdx), %r10
+ sbbq %r10, 8*4(%rax)
+
+ movq 8*5(%rdx), %r10
+ sbbq %r10, 8*5(%rax)
+
+ movq 8*6(%rdx), %r10
+ sbbq %r10, 8*6(%rax)
+
+ movq 8*7(%rdx), %r10
+ sbbq %r10, 8*7(%rax)
+
+ sbbq %r10,%r10 # carry
+ negq %r10 # carry
+
+ cmpl %ecx, %r8d # j, blocks_of_8
+ jne .L22 #,
+.L17:
+ cmpl %r8d, %ebx # blocks_of_8, x_size
+ je .L19 #,
+ leal (%r8,%rbx), %r9d #, ivtmp.33
+ movl %r8d, %esi # blocks_of_8, j
+ .p2align 4,,10
+ .p2align 3
+.L20:
+ mov %r9d, %eax # ivtmp.33, ivtmp.33
+ mov %esi, %ecx # j, j
+ leaq (%r14, %rax,8), %rax #, D.2387
+ incl %esi # j
+ movq (%rax), %rdx #* D.2387, tmp153
+ incl %r9d # ivtmp.33
+
+ rorq %r10 # carry
+ sbbq (%r12,%rcx,8),%rdx #* x, x
+ sbbq %r10,%r10 # carry
+ negq %r10 # carry
+
+ cmpl %esi, %ebx # j, x_size
+ movq %rdx, (%rax) # x,* D.2387
+ jne .L20 #,
+.L19:
+ testq %r10, %r10 # carry
+ je .L_EXIT #,
+ decq (%rdi) #* D.2349
+.L_EXIT:
+ popq %rbx #
+ popq %rbp #
+ popq %r12 #
+ popq %r13 #
+ popq %r14 #
+ popq %r15 #
+END_FUNCTION(bigint_monty_redc)
+
+
+#if 0
+ #define Z_ARR ARG_1 // rdi
+#define Z_SIZE ARG_2_32 // esi
+// X_ARR is ARG_3 == rdx, moved b/c needed for multiply
+#define X_SIZE ARG_4_32 // ecx
+#define U ARG_5 // r8
+
+/*
+ We need all arguments for a while (we can reuse U eventually)
+ So only temp registers are
+ TEMP_1 %r10
+ TEMP_2 %r11
+ TEMP_3 = ARG_6 = %r9
+ void return, so also
+ R0 %rax (aka TEMP_9)
+ is free (but needed for multiply)
+
+ Can push:
+ %rbx (base pointer, callee saved)
+ %rpb (frame pointer, callee saved)
+ %r12-%r15 (callee saved)
+
+ Can push base/frame pointers since this is a leaf function
+ and does not reference any data.
+*/
+
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+#define LOOP_CTR_I %r12
+#define LOOP_CTR_J %r13
+
+#define CARRY TEMP_1
+#define Z_WORD TEMP_2
+#define X_ARR TEMP_3
+#define MUL_LO %rax
+#define MUL_HI %rdx
+
+ ASSIGN(X_ARR, ARG_3)
+
+ /*
+ ZEROIZE(CARRY)
+
+ ASSIGN(LOOP_CTR, X_SIZE)
+
+ JUMP_IF_ZERO(LOOP_CTR, .L_MULADD_DONE)
+ JUMP_IF_LT(LOOP_CTR, 8, .LOOP_MULADD1)
+
+#define MULADD_OP(N) \
+ ASSIGN(MUL_LO, ARRAY8(X_ARR, N)) ; \
+ ASSIGN(Z_WORD, ARRAY8(Z_ARR, N)) ; \
+ MUL(Y) ; \
+ ADD(Z_WORD, CARRY) ; \
+ ASSIGN(CARRY, MUL_HI) ; \
+ ADD_LAST_CARRY(CARRY) ; \
+ ADD(Z_WORD, MUL_LO) ; \
+ ADD_LAST_CARRY(CARRY) ; \
+ ASSIGN(ARRAY8(Z_ARR, N), Z_WORD)
+
+ALIGN
+.LOOP_MULADD8:
+ MULADD_OP(0)
+ MULADD_OP(1)
+ MULADD_OP(2)
+ MULADD_OP(3)
+ MULADD_OP(4)
+ MULADD_OP(5)
+ MULADD_OP(6)
+ MULADD_OP(7)
+
+ SUB_IMM(LOOP_CTR, 8)
+ ADD_IMM(Z_ARR, 64)
+ ADD_IMM(X_ARR, 64)
+ cmp IMM(8), LOOP_CTR
+ jge .LOOP_MULADD8
+
+ JUMP_IF_ZERO(LOOP_CTR, .L_MULADD_DONE)
+
+ALIGN
+.LOOP_MULADD1:
+ MULADD_OP(0)
+
+ SUB_IMM(LOOP_CTR, 1)
+ ADD_IMM(Z_ARR, 8)
+ ADD_IMM(X_ARR, 8)
+
+ cmp IMM(0), LOOP_CTR
+ jne .LOOP_MULADD1
+*/
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+#endif
diff --git a/botan/src/math/bigint/monty_generic/info.txt b/botan/src/math/bigint/monty_generic/info.txt
new file mode 100644
index 0000000..6f5f0e7
--- /dev/null
+++ b/botan/src/math/bigint/monty_generic/info.txt
@@ -0,0 +1,7 @@
+realname "Montgomery Reduction"
+
+load_on dep
+
+<add>
+mp_monty.cpp
+</add>
diff --git a/botan/src/math/bigint/monty_generic/mp_monty.cpp b/botan/src/math/bigint/monty_generic/mp_monty.cpp
new file mode 100644
index 0000000..5409e25
--- /dev/null
+++ b/botan/src/math/bigint/monty_generic/mp_monty.cpp
@@ -0,0 +1,78 @@
+/*
+* Montgomery Reduction
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_core.h>
+#include <botan/mp_asm.h>
+#include <botan/mp_asmi.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Montgomery Reduction Algorithm
+*/
+void bigint_monty_redc(word z[], u32bit z_size,
+ const word x[], u32bit x_size, word u)
+ {
+ const u32bit blocks_of_8 = x_size - (x_size % 8);
+
+ for(u32bit i = 0; i != x_size; ++i)
+ {
+ word* z_i = z + i;
+
+ const word y = z_i[0] * u;
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks_of_8; j += 8)
+ carry = word8_madd3(z_i + j, x + j, y, carry);
+
+ for(u32bit j = blocks_of_8; j != x_size; ++j)
+ z_i[j] = word_madd3(x[j], y, z_i[j], &carry);
+
+ word z_sum = z_i[x_size] + carry;
+ carry = (z_sum < z_i[x_size]);
+ z_i[x_size] = z_sum;
+
+ for(u32bit j = x_size + 1; carry && j != z_size - i; ++j)
+ {
+ ++z_i[j];
+ carry = !z_i[j];
+ }
+ }
+
+ // Check if z[x_size...x_size+1] >= x[0...x_size] using bigint_cmp (inlined)
+ if(!z[x_size + x_size])
+ {
+ for(u32bit i = x_size; i > 0; --i)
+ {
+ if(z[x_size + i - 1] > x[i-1])
+ break;
+
+ if(z[x_size + i - 1] < x[i-1])
+ return;
+ }
+ }
+
+ // If the compare above is true, subtract using bigint_sub2 (inlined)
+ word carry = 0;
+
+ for(u32bit i = 0; i != blocks_of_8; i += 8)
+ carry = word8_sub2(z + x_size + i, x + i, carry);
+
+ for(u32bit i = blocks_of_8; i != x_size; ++i)
+ z[x_size + i] = word_sub(z[x_size + i], x[i], &carry);
+
+ if(carry)
+ --z[x_size+x_size];
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mp_amd64/info.txt b/botan/src/math/bigint/mp_amd64/info.txt
new file mode 100644
index 0000000..84a5bcf
--- /dev/null
+++ b/botan/src/math/bigint/mp_amd64/info.txt
@@ -0,0 +1,19 @@
+realname "MPI Core (x86-64)"
+
+mp_bits 64
+
+load_on dep
+
+<add>
+mp_asm.h
+mp_asmi.h
+</add>
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/botan/src/math/bigint/mp_amd64/mp_asm.h b/botan/src/math/bigint/mp_amd64/mp_asm.h
new file mode 100644
index 0000000..fa66d04
--- /dev/null
+++ b/botan/src/math/bigint/mp_amd64/mp_asm.h
@@ -0,0 +1,69 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS != 64)
+ #error The mp_amd64 module requires that BOTAN_MP_WORD_BITS == 64
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Helper Macros for amd64 Assembly
+*/
+#define ASM(x) x "\n\t"
+
+/*
+* Word Multiply
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+ asm(
+ ASM("mulq %[b]")
+ ASM("addq %[c],%[a]")
+ ASM("adcq $0,%[carry]")
+
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*c)
+ : "0"(a), "1"(b), [c]"g"(*c) : "cc");
+
+ return a;
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+ asm(
+ ASM("mulq %[b]")
+
+ ASM("addq %[c],%[a]")
+ ASM("adcq $0,%[carry]")
+
+ ASM("addq %[d],%[a]")
+ ASM("adcq $0,%[carry]")
+
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*d)
+ : "0"(a), "1"(b), [c]"g"(c), [d]"g"(*d) : "cc");
+
+ return a;
+ }
+
+#undef ASM
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_amd64/mp_asmi.h b/botan/src/math/bigint/mp_amd64/mp_asmi.h
new file mode 100644
index 0000000..8bccbaa
--- /dev/null
+++ b/botan/src/math/bigint/mp_amd64/mp_asmi.h
@@ -0,0 +1,243 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2007 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Helper Macros for amd64 Assembly
+*/
+#ifndef ASM
+ #define ASM(x) x "\n\t"
+#endif
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movq 8*" #INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 8*" #INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 8*" #INDEX "(%[y]), %[carry]") \
+ ASM("movq %[carry], 8*" #INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" #INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movq 8*" #INDEX "(%[x]),%%rax") \
+ ASM("mulq %[y]") \
+ ASM("addq %[carry],%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("addq 8*" #INDEX "(%[z]),%%rax") \
+ ASM("adcq $0,%%rdx") \
+ ASM("movq %%rdx,%[carry]") \
+ ASM("movq %%rax, 8*" #INDEX " (%[z])")
+
+#define DO_8_TIMES(MACRO, ARG) \
+ MACRO(ARG, 0) \
+ MACRO(ARG, 1) \
+ MACRO(ARG, 2) \
+ MACRO(ARG, 3) \
+ MACRO(ARG, 4) \
+ MACRO(ARG, 5) \
+ MACRO(ARG, 6) \
+ MACRO(ARG, 7)
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorq %[carry]") \
+ CORE_CODE \
+ ASM("sbbq %[carry],%[carry]") \
+ ASM("negq %[carry]")
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+#if 0
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+#else
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+#endif
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbq %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbq"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%rax", "%rdx");
+ return carry;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ ASM("mulq %[y]")
+
+ ASM("addq %[x],%[w0]")
+ ASM("adcq %[y],%[w1]")
+ ASM("adcq $0,%[w2]")
+
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ ASM("mulq %[y]")
+
+ ASM("addq %[x],%[w0]")
+ ASM("adcq %[y],%[w1]")
+ ASM("adcq $0,%[w2]")
+
+ ASM("addq %[x],%[w0]")
+ ASM("adcq %[y],%[w1]")
+ ASM("adcq $0,%[w2]")
+
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+
+#undef ASM
+#undef DO_8_TIMES
+#undef ADD_OR_SUBTRACT
+#undef ADDSUB2_OP
+#undef ADDSUB3_OP
+#undef LINMUL_OP
+#undef MULADD_OP
+
+}
+
+}
+#endif
diff --git a/botan/src/math/bigint/mp_asm.cpp b/botan/src/math/bigint/mp_asm.cpp
new file mode 100644
index 0000000..ea9738d
--- /dev/null
+++ b/botan/src/math/bigint/mp_asm.cpp
@@ -0,0 +1,179 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_asm.h>
+#include <botan/mp_asmi.h>
+#include <botan/mp_core.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Two Operand Addition, No Carry
+*/
+word bigint_add2_nc(word x[], u32bit x_size, const word y[], u32bit y_size)
+ {
+ word carry = 0;
+
+ const u32bit blocks = y_size - (y_size % 8);
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_add2(x + j, y + j, carry);
+
+ for(u32bit j = blocks; j != y_size; ++j)
+ x[j] = word_add(x[j], y[j], &carry);
+
+ if(!carry)
+ return 0;
+
+ for(u32bit j = y_size; j != x_size; ++j)
+ if(++x[j])
+ return 0;
+
+ return 1;
+ }
+
+/*
+* Three Operand Addition, No Carry
+*/
+word bigint_add3_nc(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ if(x_size < y_size)
+ { return bigint_add3_nc(z, y, y_size, x, x_size); }
+
+ word carry = 0;
+
+ const u32bit blocks = y_size - (y_size % 8);
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_add3(z + j, x + j, y + j, carry);
+
+ for(u32bit j = blocks; j != y_size; ++j)
+ z[j] = word_add(x[j], y[j], &carry);
+
+ for(u32bit j = y_size; j != x_size; ++j)
+ {
+ word x_j = x[j] + carry;
+ if(carry && x_j)
+ carry = 0;
+ z[j] = x_j;
+ }
+
+ return carry;
+ }
+
+/*
+* Two Operand Addition
+*/
+void bigint_add2(word x[], u32bit x_size, const word y[], u32bit y_size)
+ {
+ if(bigint_add2_nc(x, x_size, y, y_size))
+ ++x[x_size];
+ }
+
+/*
+* Three Operand Addition
+*/
+void bigint_add3(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ if(bigint_add3_nc(z, x, x_size, y, y_size))
+ ++z[(x_size > y_size ? x_size : y_size)];
+ }
+
+/*
+* Two Operand Subtraction
+*/
+void bigint_sub2(word x[], u32bit x_size, const word y[], u32bit y_size)
+ {
+ word carry = 0;
+
+ const u32bit blocks = y_size - (y_size % 8);
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_sub2(x + j, y + j, carry);
+
+ for(u32bit j = blocks; j != y_size; ++j)
+ x[j] = word_sub(x[j], y[j], &carry);
+
+ if(!carry) return;
+
+ for(u32bit j = y_size; j != x_size; ++j)
+ {
+ --x[j];
+ if(x[j] != MP_WORD_MAX) return;
+ }
+ }
+
+/*
+* Three Operand Subtraction
+*/
+void bigint_sub3(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ word carry = 0;
+
+ const u32bit blocks = y_size - (y_size % 8);
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_sub3(z + j, x + j, y + j, carry);
+
+ for(u32bit j = blocks; j != y_size; ++j)
+ z[j] = word_sub(x[j], y[j], &carry);
+
+ for(u32bit j = y_size; j != x_size; ++j)
+ {
+ word x_j = x[j] - carry;
+ if(carry && x_j != MP_WORD_MAX)
+ carry = 0;
+ z[j] = x_j;
+ }
+ }
+
+/*
+* Two Operand Linear Multiply
+*/
+void bigint_linmul2(word x[], u32bit x_size, word y)
+ {
+ const u32bit blocks = x_size - (x_size % 8);
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_linmul2(x + j, y, carry);
+
+ for(u32bit j = blocks; j != x_size; ++j)
+ x[j] = word_madd2(x[j], y, &carry);
+
+ x[x_size] = carry;
+ }
+
+/*
+* Three Operand Linear Multiply
+*/
+void bigint_linmul3(word z[], const word x[], u32bit x_size, word y)
+ {
+ const u32bit blocks = x_size - (x_size % 8);
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_linmul3(z + j, x + j, y, carry);
+
+ for(u32bit j = blocks; j != x_size; ++j)
+ z[j] = word_madd2(x[j], y, &carry);
+
+ z[x_size] = carry;
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mp_asm64/info.txt b/botan/src/math/bigint/mp_asm64/info.txt
new file mode 100644
index 0000000..5c112c4
--- /dev/null
+++ b/botan/src/math/bigint/mp_asm64/info.txt
@@ -0,0 +1,27 @@
+realname "MPI Core (Alpha/IA-64/MIPS64/PowerPC-64/SPARC64)"
+
+mp_bits 64
+
+load_on dep
+
+<add>
+mp_asm.h
+mp_generic:mp_asmi.h
+</add>
+
+<arch>
+#amd64
+alpha
+ia64
+mips64
+ppc64
+sparc64
+</arch>
+
+# The inline asm only works with gcc, but it looks like (at least on
+# UltraSPARC), using 64-bit words and the sythensized multiply is a 5 to 25%
+# win, so it's probably worth using elsewhere.
+<cc>
+gcc
+sunwspro
+</cc>
diff --git a/botan/src/math/bigint/mp_asm64/mp_asm.h b/botan/src/math/bigint/mp_asm64/mp_asm.h
new file mode 100644
index 0000000..c9159ea
--- /dev/null
+++ b/botan/src/math/bigint/mp_asm64/mp_asm.h
@@ -0,0 +1,119 @@
+/*
+* MPI Multiply-Add Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_MADD_H__
+#define BOTAN_MP_MADD_H__
+
+#include <botan/mp_types.h>
+
+namespace Botan {
+
+#if (BOTAN_MP_WORD_BITS != 64)
+ #error The mp_asm64 module requires that BOTAN_MP_WORD_BITS == 64
+#endif
+
+#if defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("umulh %1,%2,%0" : "=r" (z0) : "r" (a), "r" (b)); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_AMD64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("mulq %3" : "=d" (z0), "=a" (z1) : \
+ "a" (a), "rm" (b) : "cc"); \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("xmpy.hu %0=%1,%2" : "=f" (z0) : "f" (a), "f" (b)); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("mulhdu %0,%1,%2" : "=r" (z0) : "r" (a), "r" (b) : "cc"); \
+ z1 = a * b; \
+} while(0);
+
+#elif defined(BOTAN_TARGET_ARCH_IS_MIPS64)
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) do { \
+ asm("dmultu %2,%3" : "=h" (z0), "=l" (z1) : "r" (a), "r" (b)); \
+} while(0);
+
+#else
+
+// Do a 64x64->128 multiply using four 64x64->64 multiplies
+// plus some adds and shifts. Last resort for CPUs like UltraSPARC,
+// with 64-bit registers/ALU, but no 64x64->128 multiply.
+inline void bigint_2word_mul(word a, word b, word* z1, word* z0)
+ {
+ const u32bit MP_HWORD_BITS = BOTAN_MP_WORD_BITS / 2;
+ const word MP_HWORD_MASK = ((word)1 << MP_HWORD_BITS) - 1;
+
+ const word a_hi = (a >> MP_HWORD_BITS);
+ const word a_lo = (a & MP_HWORD_MASK);
+ const word b_hi = (b >> MP_HWORD_BITS);
+ const word b_lo = (b & MP_HWORD_MASK);
+
+ word x0 = a_hi * b_hi;
+ word x1 = a_lo * b_hi;
+ word x2 = a_hi * b_lo;
+ word x3 = a_lo * b_lo;
+
+ x2 += x3 >> (MP_HWORD_BITS);
+ x2 += x1;
+ if(x2 < x1)
+ x0 += ((word)1 << MP_HWORD_BITS);
+
+ *z0 = x0 + (x2 >> MP_HWORD_BITS);
+ *z1 = ((x2 & MP_HWORD_MASK) << MP_HWORD_BITS) + (x3 & MP_HWORD_MASK);
+ }
+
+#define BOTAN_WORD_MUL(a,b,z1,z0) bigint_2word_mul(a, b, &z1, &z0)
+
+#endif
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+ word z0 = 0, z1 = 0;
+
+ BOTAN_WORD_MUL(a, b, z1, z0);
+
+ z1 += *c; if(z1 < *c) z0++;
+
+ *c = z0;
+ return z1;
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+ word z0 = 0, z1 = 0;
+
+ BOTAN_WORD_MUL(a, b, z1, z0);
+
+ z1 += c; if(z1 < c) z0++;
+ z1 += *d; if(z1 < *d) z0++;
+
+ *d = z0;
+ return z1;
+ }
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_comba.cpp b/botan/src/math/bigint/mp_comba.cpp
new file mode 100644
index 0000000..218038d
--- /dev/null
+++ b/botan/src/math/bigint/mp_comba.cpp
@@ -0,0 +1,920 @@
+/*
+* Comba Multiplication and Squaring
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_core.h>
+#include <botan/mp_asmi.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Comba 4x4 Squaring
+*/
+void bigint_comba_sqr4(word z[8], const word x[4])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], x[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[1]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], x[1]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[3]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[2]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], x[2]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[3]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[3], x[3]);
+ z[6] = w0;
+ z[7] = w1;
+ }
+
+/*
+* Comba 4x4 Multiplication
+*/
+void bigint_comba_mul4(word z[8], const word x[4], const word y[4])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[0]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[0]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[0]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[1], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[1]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[2], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[2]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[3], y[3]);
+ z[6] = w0;
+ z[7] = w1;
+ }
+
+/*
+* Comba 6x6 Squaring
+*/
+void bigint_comba_sqr6(word z[12], const word x[6])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], x[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[1]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], x[1]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[3]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[2]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[4]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], x[2]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[4]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[3]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[4]);
+ word3_muladd(&w2, &w1, &w0, x[3], x[3]);
+ z[6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[4]);
+ z[7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[5]);
+ word3_muladd(&w2, &w1, &w0, x[4], x[4]);
+ z[8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[4], x[5]);
+ z[9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[5], x[5]);
+ z[10] = w0;
+ z[11] = w1;
+ }
+
+/*
+* Comba 6x6 Multiplication
+*/
+void bigint_comba_mul6(word z[12], const word x[6], const word y[6])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[0]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[0]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[0]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[0]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[0]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[1], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[1]);
+ z[6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[2], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[2]);
+ z[7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[3], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[3]);
+ z[8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[4], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[4]);
+ z[9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[5], y[5]);
+ z[10] = w0;
+ z[11] = w1;
+ }
+
+/*
+* Comba 8x8 Squaring
+*/
+void bigint_comba_sqr8(word z[16], const word x[8])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], x[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[1]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], x[1]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[3]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[2]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[4]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], x[2]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[4]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[3]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[6]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[4]);
+ word3_muladd(&w2, &w1, &w0, x[3], x[3]);
+ z[6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[0], x[7]);
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[6]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[5]);
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[4]);
+ z[7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[1], x[7]);
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[6]);
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[5]);
+ word3_muladd(&w2, &w1, &w0, x[4], x[4]);
+ z[8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[2], x[7]);
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[6]);
+ word3_muladd_2(&w2, &w1, &w0, x[4], x[5]);
+ z[9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[3], x[7]);
+ word3_muladd_2(&w2, &w1, &w0, x[4], x[6]);
+ word3_muladd(&w2, &w1, &w0, x[5], x[5]);
+ z[10] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[4], x[7]);
+ word3_muladd_2(&w2, &w1, &w0, x[5], x[6]);
+ z[11] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[5], x[7]);
+ word3_muladd(&w2, &w1, &w0, x[6], x[6]);
+ z[12] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[6], x[7]);
+ z[13] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[7], x[7]);
+ z[14] = w0;
+ z[15] = w1;
+ }
+
+/*
+* Comba 8x8 Multiplication
+*/
+void bigint_comba_mul8(word z[16], const word x[8], const word y[8])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[0]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[0]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[0]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[0]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[0]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[0]);
+ z[6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[0], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[1], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[1]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[0]);
+ z[7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[1], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[2], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[2]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[1]);
+ z[8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[2], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[3], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[3]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[2]);
+ z[9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[3], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[4], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[4]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[3]);
+ z[10] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[4], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[5], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[5]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[4]);
+ z[11] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[5], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[6], y[6]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[5]);
+ z[12] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[6], y[7]);
+ word3_muladd(&w2, &w1, &w0, x[7], y[6]);
+ z[13] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[7], y[7]);
+ z[14] = w0;
+ z[15] = w1;
+ }
+
+/*
+* Comba 16x16 Squaring
+*/
+void bigint_comba_sqr16(word z[32], const word x[16])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], x[ 0]);
+ z[ 0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 1]);
+ z[ 1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], x[ 1]);
+ z[ 2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 3]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 2]);
+ z[ 3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 4]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], x[ 2]);
+ z[ 4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 4]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 3]);
+ z[ 5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], x[ 3]);
+ z[ 6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 5]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 4]);
+ z[ 7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], x[ 4]);
+ z[ 8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 6]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 5]);
+ z[ 9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], x[ 5]);
+ z[10] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 7]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 6]);
+ z[11] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], x[ 6]);
+ z[12] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 8]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 7]);
+ z[13] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], x[ 7]);
+ z[14] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 0], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[ 9]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 8]);
+ z[15] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 1], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], x[ 8]);
+ z[16] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 2], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[10]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[ 9]);
+ z[17] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 3], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], x[ 9]);
+ z[18] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 4], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[11]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[10]);
+ z[19] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 5], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[11]);
+ word3_muladd(&w2, &w1, &w0, x[10], x[10]);
+ z[20] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 6], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[12]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[11]);
+ z[21] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 7], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[12]);
+ word3_muladd(&w2, &w1, &w0, x[11], x[11]);
+ z[22] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 8], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[13]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[12]);
+ z[23] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[ 9], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[13]);
+ word3_muladd(&w2, &w1, &w0, x[12], x[12]);
+ z[24] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[10], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[14]);
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[13]);
+ z[25] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[11], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[14]);
+ word3_muladd(&w2, &w1, &w0, x[13], x[13]);
+ z[26] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[12], x[15]);
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[14]);
+ z[27] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[13], x[15]);
+ word3_muladd(&w2, &w1, &w0, x[14], x[14]);
+ z[28] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd_2(&w2, &w1, &w0, x[14], x[15]);
+ z[29] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[15], x[15]);
+ z[30] = w0;
+ z[31] = w1;
+ }
+
+/*
+* Comba 16x16 Multiplication
+*/
+void bigint_comba_mul16(word z[32], const word x[16], const word y[16])
+ {
+ word w2 = 0, w1 = 0, w0 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 0]);
+ z[0] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 0]);
+ z[1] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 0]);
+ z[2] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 0]);
+ z[3] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 0]);
+ z[4] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 0]);
+ z[5] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 0]);
+ z[6] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 0]);
+ z[7] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 0]);
+ z[8] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 0]);
+ z[9] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 0]);
+ z[10] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 0]);
+ z[11] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 0]);
+ z[12] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 0]);
+ z[13] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 0]);
+ z[14] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 0], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 1]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 0]);
+ z[15] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 1], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 2]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 1]);
+ z[16] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 2], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 3]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 2]);
+ z[17] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 3], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 4]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 3]);
+ z[18] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 4], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 5]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 4]);
+ z[19] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 5], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 6]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 5]);
+ z[20] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 6], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 7]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 6]);
+ z[21] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 7], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 8]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 7]);
+ z[22] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 8], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[ 9]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 8]);
+ z[23] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[ 9], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[10], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[10]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[ 9]);
+ z[24] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[10], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[11], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[11]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[10]);
+ z[25] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[11], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[12], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[12]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[11]);
+ z[26] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[12], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[13], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[13]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[12]);
+ z[27] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[13], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[14], y[14]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[13]);
+ z[28] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[14], y[15]);
+ word3_muladd(&w2, &w1, &w0, x[15], y[14]);
+ z[29] = w0; w0 = w1; w1 = w2; w2 = 0;
+
+ word3_muladd(&w2, &w1, &w0, x[15], y[15]);
+ z[30] = w0;
+ z[31] = w1;
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mp_core.h b/botan/src/math/bigint/mp_core.h
new file mode 100644
index 0000000..ea27a77
--- /dev/null
+++ b/botan/src/math/bigint/mp_core.h
@@ -0,0 +1,98 @@
+/*
+* MPI Algorithms
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_CORE_H__
+#define BOTAN_MP_CORE_H__
+
+#include <botan/mp_types.h>
+
+namespace Botan {
+
+/*
+* The size of the word type, in bits
+*/
+const u32bit MP_WORD_BITS = BOTAN_MP_WORD_BITS;
+
+extern "C" {
+
+/*
+* Addition/Subtraction Operations
+*/
+void bigint_add2(word[], u32bit, const word[], u32bit);
+void bigint_add3(word[], const word[], u32bit, const word[], u32bit);
+
+word bigint_add2_nc(word[], u32bit, const word[], u32bit);
+word bigint_add3_nc(word[], const word[], u32bit, const word[], u32bit);
+
+void bigint_sub2(word[], u32bit, const word[], u32bit);
+void bigint_sub3(word[], const word[], u32bit, const word[], u32bit);
+
+/*
+* Shift Operations
+*/
+void bigint_shl1(word[], u32bit, u32bit, u32bit);
+void bigint_shl2(word[], const word[], u32bit, u32bit, u32bit);
+void bigint_shr1(word[], u32bit, u32bit, u32bit);
+void bigint_shr2(word[], const word[], u32bit, u32bit, u32bit);
+
+/*
+* Simple O(N^2) Multiplication and Squaring
+*/
+void bigint_simple_mul(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size);
+void bigint_simple_sqr(word z[], const word x[], u32bit x_size);
+
+/*
+* Linear Multiply
+*/
+void bigint_linmul2(word[], u32bit, word);
+void bigint_linmul3(word[], const word[], u32bit, word);
+void bigint_linmul_add(word[], u32bit, const word[], u32bit, word);
+
+/*
+* Montgomery Reduction
+*/
+void bigint_monty_redc(word[], u32bit, const word[], u32bit, word);
+
+/*
+* Misc Utility Operations
+*/
+u32bit bigint_divcore(word, word, word, word, word, word);
+s32bit bigint_cmp(const word[], u32bit, const word[], u32bit);
+word bigint_divop(word, word, word);
+word bigint_modop(word, word, word);
+void bigint_wordmul(word, word, word*, word*);
+
+/*
+* Comba Multiplication / Squaring
+*/
+void bigint_comba_mul4(word[8], const word[4], const word[4]);
+void bigint_comba_mul6(word[12], const word[6], const word[6]);
+void bigint_comba_mul8(word[16], const word[8], const word[8]);
+void bigint_comba_mul16(word[32], const word[16], const word[16]);
+
+void bigint_comba_sqr4(word[8], const word[4]);
+void bigint_comba_sqr6(word[12], const word[6]);
+void bigint_comba_sqr8(word[16], const word[8]);
+void bigint_comba_sqr8(word[32], const word[16]);
+void bigint_comba_sqr16(word[64], const word[32]);
+
+}
+
+/*
+* High Level Multiplication/Squaring Interfaces
+*/
+void bigint_mul(word[], u32bit, word[],
+ const word[], u32bit, u32bit,
+ const word[], u32bit, u32bit);
+
+void bigint_sqr(word[], u32bit, word[],
+ const word[], u32bit, u32bit);
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_generic/info.txt b/botan/src/math/bigint/mp_generic/info.txt
new file mode 100644
index 0000000..8bf75fe
--- /dev/null
+++ b/botan/src/math/bigint/mp_generic/info.txt
@@ -0,0 +1,8 @@
+realname "MPI Core (C++)"
+
+load_on dep
+
+<add>
+mp_asm.h
+mp_asmi.h
+</add>
diff --git a/botan/src/math/bigint/mp_generic/mp_asm.h b/botan/src/math/bigint/mp_generic/mp_asm.h
new file mode 100644
index 0000000..7c18343
--- /dev/null
+++ b/botan/src/math/bigint/mp_generic/mp_asm.h
@@ -0,0 +1,54 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS == 8)
+ typedef Botan::u16bit dword;
+#elif (BOTAN_MP_WORD_BITS == 16)
+ typedef Botan::u32bit dword;
+#elif (BOTAN_MP_WORD_BITS == 32)
+ typedef Botan::u64bit dword;
+#elif (BOTAN_MP_WORD_BITS == 64)
+ #error BOTAN_MP_WORD_BITS can be 64 only with assembly support
+#else
+ #error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+ dword z = (dword)a * b + *c;
+ *c = (word)(z >> BOTAN_MP_WORD_BITS);
+ return (word)z;
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+ dword z = (dword)a * b + c + *d;
+ *d = (word)(z >> BOTAN_MP_WORD_BITS);
+ return (word)z;
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_generic/mp_asmi.h b/botan/src/math/bigint/mp_generic/mp_asmi.h
new file mode 100644
index 0000000..21c4db2
--- /dev/null
+++ b/botan/src/math/bigint/mp_generic/mp_asmi.h
@@ -0,0 +1,191 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ x[0] = word_add(x[0], y[0], &carry);
+ x[1] = word_add(x[1], y[1], &carry);
+ x[2] = word_add(x[2], y[2], &carry);
+ x[3] = word_add(x[3], y[3], &carry);
+ x[4] = word_add(x[4], y[4], &carry);
+ x[5] = word_add(x[5], y[5], &carry);
+ x[6] = word_add(x[6], y[6], &carry);
+ x[7] = word_add(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ z[0] = word_add(x[0], y[0], &carry);
+ z[1] = word_add(x[1], y[1], &carry);
+ z[2] = word_add(x[2], y[2], &carry);
+ z[3] = word_add(x[3], y[3], &carry);
+ z[4] = word_add(x[4], y[4], &carry);
+ z[5] = word_add(x[5], y[5], &carry);
+ z[6] = word_add(x[6], y[6], &carry);
+ z[7] = word_add(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+ word t0 = x - y;
+ word c1 = (t0 > x);
+ word z = t0 - *carry;
+ *carry = c1 | (z > t0);
+ return z;
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[4], const word y[4], word carry)
+ {
+ x[0] = word_sub(x[0], y[0], &carry);
+ x[1] = word_sub(x[1], y[1], &carry);
+ x[2] = word_sub(x[2], y[2], &carry);
+ x[3] = word_sub(x[3], y[3], &carry);
+ x[4] = word_sub(x[4], y[4], &carry);
+ x[5] = word_sub(x[5], y[5], &carry);
+ x[6] = word_sub(x[6], y[6], &carry);
+ x[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ z[0] = word_sub(x[0], y[0], &carry);
+ z[1] = word_sub(x[1], y[1], &carry);
+ z[2] = word_sub(x[2], y[2], &carry);
+ z[3] = word_sub(x[3], y[3], &carry);
+ z[4] = word_sub(x[4], y[4], &carry);
+ z[5] = word_sub(x[5], y[5], &carry);
+ z[6] = word_sub(x[6], y[6], &carry);
+ z[7] = word_sub(x[7], y[7], &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[4], word y, word carry)
+ {
+ x[0] = word_madd2(x[0], y, &carry);
+ x[1] = word_madd2(x[1], y, &carry);
+ x[2] = word_madd2(x[2], y, &carry);
+ x[3] = word_madd2(x[3], y, &carry);
+ x[4] = word_madd2(x[4], y, &carry);
+ x[5] = word_madd2(x[5], y, &carry);
+ x[6] = word_madd2(x[6], y, &carry);
+ x[7] = word_madd2(x[7], y, &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ z[0] = word_madd2(x[0], y, &carry);
+ z[1] = word_madd2(x[1], y, &carry);
+ z[2] = word_madd2(x[2], y, &carry);
+ z[3] = word_madd2(x[3], y, &carry);
+ z[4] = word_madd2(x[4], y, &carry);
+ z[5] = word_madd2(x[5], y, &carry);
+ z[6] = word_madd2(x[6], y, &carry);
+ z[7] = word_madd2(x[7], y, &carry);
+ return carry;
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ z[0] = word_madd3(x[0], y, z[0], &carry);
+ z[1] = word_madd3(x[1], y, z[1], &carry);
+ z[2] = word_madd3(x[2], y, z[2], &carry);
+ z[3] = word_madd3(x[3], y, z[3], &carry);
+ z[4] = word_madd3(x[4], y, z[4], &carry);
+ z[5] = word_madd3(x[5], y, z[5], &carry);
+ z[6] = word_madd3(x[6], y, z[6], &carry);
+ z[7] = word_madd3(x[7], y, z[7], &carry);
+ return carry;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = *w0;
+ *w0 = word_madd2(a, b, &carry);
+ *w1 += carry;
+ *w2 += (*w1 < carry) ? 1 : 0;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = 0;
+ a = word_madd2(a, b, &carry);
+ b = carry;
+
+ word top = (b >> (BOTAN_MP_WORD_BITS-1));
+ b <<= 1;
+ b |= (a >> (BOTAN_MP_WORD_BITS-1));
+ a <<= 1;
+
+ carry = 0;
+ *w0 = word_add(*w0, a, &carry);
+ *w1 = word_add(*w1, b, &carry);
+ *w2 = word_add(*w2, top, &carry);
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_ia32/info.txt b/botan/src/math/bigint/mp_ia32/info.txt
new file mode 100644
index 0000000..51f98fd
--- /dev/null
+++ b/botan/src/math/bigint/mp_ia32/info.txt
@@ -0,0 +1,19 @@
+realname "MPI Core (IA-32)"
+
+mp_bits 32
+
+load_on asm_ok
+
+<add>
+mp_asm.h
+mp_asmi.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/botan/src/math/bigint/mp_ia32/mp_asm.h b/botan/src/math/bigint/mp_ia32/mp_asm.h
new file mode 100644
index 0000000..4d3afc9
--- /dev/null
+++ b/botan/src/math/bigint/mp_ia32/mp_asm.h
@@ -0,0 +1,67 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2008 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_H__
+#define BOTAN_MP_ASM_H__
+
+#include <botan/mp_types.h>
+
+#if (BOTAN_MP_WORD_BITS != 32)
+ #error The mp_ia32 module requires that BOTAN_MP_WORD_BITS == 32
+#endif
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Helper Macros for x86 Assembly
+*/
+#define ASM(x) x "\n\t"
+
+/*
+* Word Multiply
+*/
+inline word word_madd2(word a, word b, word* c)
+ {
+ asm(
+ ASM("mull %[b]")
+ ASM("addl %[c],%[a]")
+ ASM("adcl $0,%[carry]")
+
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*c)
+ : "0"(a), "1"(b), [c]"g"(*c) : "cc");
+
+ return a;
+ }
+
+/*
+* Word Multiply/Add
+*/
+inline word word_madd3(word a, word b, word c, word* d)
+ {
+ asm(
+ ASM("mull %[b]")
+
+ ASM("addl %[c],%[a]")
+ ASM("adcl $0,%[carry]")
+
+ ASM("addl %[d],%[a]")
+ ASM("adcl $0,%[carry]")
+
+ : [a]"=a"(a), [b]"=rm"(b), [carry]"=&d"(*d)
+ : "0"(a), "1"(b), [c]"g"(c), [d]"g"(*d) : "cc");
+
+ return a;
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_ia32/mp_asmi.h b/botan/src/math/bigint/mp_ia32/mp_asmi.h
new file mode 100644
index 0000000..28b99ab
--- /dev/null
+++ b/botan/src/math/bigint/mp_ia32/mp_asmi.h
@@ -0,0 +1,235 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2007 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Helper Macros for x86 Assembly
+*/
+#ifndef ASM
+ #define ASM(x) x "\n\t"
+#endif
+
+#define ADDSUB2_OP(OPERATION, INDEX) \
+ ASM("movl 4*" #INDEX "(%[y]), %[carry]") \
+ ASM(OPERATION " %[carry], 4*" #INDEX "(%[x])") \
+
+#define ADDSUB3_OP(OPERATION, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]), %[carry]") \
+ ASM(OPERATION " 4*" #INDEX "(%[y]), %[carry]") \
+ ASM("movl %[carry], 4*" #INDEX "(%[z])") \
+
+#define LINMUL_OP(WRITE_TO, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" #INDEX "(%[" WRITE_TO "])")
+
+#define MULADD_OP(IGNORED, INDEX) \
+ ASM("movl 4*" #INDEX "(%[x]),%%eax") \
+ ASM("mull %[y]") \
+ ASM("addl %[carry],%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("addl 4*" #INDEX "(%[z]),%%eax") \
+ ASM("adcl $0,%%edx") \
+ ASM("movl %%edx,%[carry]") \
+ ASM("movl %%eax, 4*" #INDEX " (%[z])")
+
+#define DO_8_TIMES(MACRO, ARG) \
+ MACRO(ARG, 0) \
+ MACRO(ARG, 1) \
+ MACRO(ARG, 2) \
+ MACRO(ARG, 3) \
+ MACRO(ARG, 4) \
+ MACRO(ARG, 5) \
+ MACRO(ARG, 6) \
+ MACRO(ARG, 7)
+
+#define ADD_OR_SUBTRACT(CORE_CODE) \
+ ASM("rorl %[carry]") \
+ CORE_CODE \
+ ASM("sbbl %[carry],%[carry]") \
+ ASM("negl %[carry]")
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+#if 0
+ asm(
+ ADD_OR_SUBTRACT(ASM("adcl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+#else
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+#endif
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "adcl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(ASM("sbbl %[y],%[x]"))
+ : [x]"=r"(x), [carry]"=r"(*carry)
+ : "0"(x), [y]"rm"(y), "1"(*carry)
+ : "cc");
+ return x;
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB2_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ asm(
+ ADD_OR_SUBTRACT(DO_8_TIMES(ADDSUB3_OP, "sbbl"))
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"r"(y), [z]"r"(z), "0"(carry)
+ : "cc", "memory");
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "x")
+ : [carry]"=r"(carry)
+ : [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(LINMUL_OP, "z")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ asm(
+ DO_8_TIMES(MULADD_OP, "")
+ : [carry]"=r"(carry)
+ : [z]"r"(z), [x]"r"(x), [y]"rm"(y), "0"(carry)
+ : "cc", "%eax", "%edx");
+ return carry;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ ASM("mull %[y]")
+
+ ASM("addl %[x],%[w0]")
+ ASM("adcl %[y],%[w1]")
+ ASM("adcl $0,%[w2]")
+
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word x, word y)
+ {
+ asm(
+ ASM("mull %[y]")
+
+ ASM("addl %[x],%[w0]")
+ ASM("adcl %[y],%[w1]")
+ ASM("adcl $0,%[w2]")
+
+ ASM("addl %[x],%[w0]")
+ ASM("adcl %[y],%[w1]")
+ ASM("adcl $0,%[w2]")
+
+ : [w0]"=r"(*w0), [w1]"=r"(*w1), [w2]"=r"(*w2)
+ : [x]"a"(x), [y]"d"(y), "0"(*w0), "1"(*w1), "2"(*w2)
+ : "cc");
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_ia32_msvc/info.txt b/botan/src/math/bigint/mp_ia32_msvc/info.txt
new file mode 100644
index 0000000..9c7ac9b
--- /dev/null
+++ b/botan/src/math/bigint/mp_ia32_msvc/info.txt
@@ -0,0 +1,18 @@
+realname "x86 MPI Assembler Core (MSVC)"
+
+mp_bits 32
+
+load_on dep
+
+<add>
+mp_generic:mp_asm.h
+mp_asmi.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+msvc
+</cc>
diff --git a/botan/src/math/bigint/mp_ia32_msvc/mp_asmi.h b/botan/src/math/bigint/mp_ia32_msvc/mp_asmi.h
new file mode 100644
index 0000000..33ce6eb
--- /dev/null
+++ b/botan/src/math/bigint/mp_ia32_msvc/mp_asmi.h
@@ -0,0 +1,528 @@
+/*
+* Lowest Level MPI Algorithms
+* (C) 1999-2006 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MP_ASM_INTERNAL_H__
+#define BOTAN_MP_ASM_INTERNAL_H__
+
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Word Addition
+*/
+inline word word_add(word x, word y, word* carry)
+ {
+ word z = x + y;
+ word c1 = (z < x);
+ z += *carry;
+ *carry = c1 | (z < *carry);
+ return z;
+ }
+
+/*
+* Eight Word Block Addition, Two Argument
+*/
+inline word word8_add2(word x[8], const word y[8], word carry)
+ {
+ __asm {
+ mov edx,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[esi]
+ adc [edx],eax
+ mov eax,[esi+4]
+ adc [edx+4],eax
+ mov eax,[esi+8]
+ adc [edx+8],eax
+ mov eax,[esi+12]
+ adc [edx+12],eax
+ mov eax,[esi+16]
+ adc [edx+16],eax
+ mov eax,[esi+20]
+ adc [edx+20],eax
+ mov eax,[esi+24]
+ adc [edx+24],eax
+ mov eax,[esi+28]
+ adc [edx+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*
+* Eight Word Block Addition, Three Argument
+*/
+inline word word8_add3(word z[8], const word x[8], const word y[8], word carry)
+ {
+ __asm {
+ mov edi,[x]
+ mov esi,[y]
+ mov ebx,[z]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[edi]
+ adc eax,[esi]
+ mov [ebx],eax
+
+ mov eax,[edi+4]
+ adc eax,[esi+4]
+ mov [ebx+4],eax
+
+ mov eax,[edi+8]
+ adc eax,[esi+8]
+ mov [ebx+8],eax
+
+ mov eax,[edi+12]
+ adc eax,[esi+12]
+ mov [ebx+12],eax
+
+ mov eax,[edi+16]
+ adc eax,[esi+16]
+ mov [ebx+16],eax
+
+ mov eax,[edi+20]
+ adc eax,[esi+20]
+ mov [ebx+20],eax
+
+ mov eax,[edi+24]
+ adc eax,[esi+24]
+ mov [ebx+24],eax
+
+ mov eax,[edi+28]
+ adc eax,[esi+28]
+ mov [ebx+28],eax
+
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*
+* Word Subtraction
+*/
+inline word word_sub(word x, word y, word* carry)
+ {
+ word t0 = x - y;
+ word c1 = (t0 > x);
+ word z = t0 - *carry;
+ *carry = c1 | (z > t0);
+ return z;
+ }
+
+/*
+* Eight Word Block Subtraction, Two Argument
+*/
+inline word word8_sub2(word x[8], const word y[8], word carry)
+ {
+ _asm {
+ mov edi,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov eax,[edi]
+ sbb eax,[esi]
+ mov [edi],eax
+ mov eax,[edi+4]
+ sbb eax,[esi+4]
+ mov [edi+4],eax
+ mov eax,[edi+8]
+ sbb eax,[esi+8]
+ mov [edi+8],eax
+ mov eax,[edi+12]
+ sbb eax,[esi+12]
+ mov [edi+12],eax
+ mov eax,[edi+16]
+ sbb eax,[esi+16]
+ mov [edi+16],eax
+ mov eax,[edi+20]
+ sbb eax,[esi+20]
+ mov [edi+20],eax
+ mov eax,[edi+24]
+ sbb eax,[esi+24]
+ mov [edi+24],eax
+ mov eax,[edi+28]
+ sbb eax,[esi+28]
+ mov [edi+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*
+* Eight Word Block Subtraction, Three Argument
+*/
+inline word word8_sub3(word z[8], const word x[8],
+ const word y[8], word carry)
+ {
+ __asm {
+ mov edi,[x]
+ mov esi,[y]
+ xor eax,eax
+ sub eax,[carry] //force CF=1 iff *carry==1
+ mov ebx,[z]
+ mov eax,[edi]
+ sbb eax,[esi]
+ mov [ebx],eax
+ mov eax,[edi+4]
+ sbb eax,[esi+4]
+ mov [ebx+4],eax
+ mov eax,[edi+8]
+ sbb eax,[esi+8]
+ mov [ebx+8],eax
+ mov eax,[edi+12]
+ sbb eax,[esi+12]
+ mov [ebx+12],eax
+ mov eax,[edi+16]
+ sbb eax,[esi+16]
+ mov [ebx+16],eax
+ mov eax,[edi+20]
+ sbb eax,[esi+20]
+ mov [ebx+20],eax
+ mov eax,[edi+24]
+ sbb eax,[esi+24]
+ mov [ebx+24],eax
+ mov eax,[edi+28]
+ sbb eax,[esi+28]
+ mov [ebx+28],eax
+ sbb eax,eax
+ neg eax
+ }
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_linmul2(word x[8], word y, word carry)
+ {
+ __asm
+ {
+ mov esi,[x]
+ mov eax,[esi] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi],eax //load a
+
+ mov eax,[esi+4] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+4],eax //load a
+
+ mov eax,[esi+8] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+8],eax //load a
+
+ mov eax,[esi+12] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+12],eax //load a
+
+ mov eax,[esi+16] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+16],eax //load a
+
+ mov eax,[esi+20] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+20],eax //load a
+
+ mov eax,[esi+24] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [esi+24],eax //load a
+
+ mov eax,[esi+28] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov [esi+28],eax //load a
+
+ mov eax,edx //store carry
+ }
+ }
+
+/*
+* Eight Word Block Linear Multiplication
+*/
+inline word word8_muladd(word z[8], const word x[8],
+ word y, word carry)
+ {
+ __asm
+ {
+ mov esi,[x]
+ mov ebx,[y]
+ mov edi,[z]
+ mov eax,[esi] //load a
+ mul ebx //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ add eax,[edi] //sum lo z
+ adc edx,0 //sum hi z
+ mov ecx,edx //carry for next block = hi z
+ mov [edi],eax //save lo z
+
+ mov eax,[esi+4]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+4]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+4],eax
+
+ mov eax,[esi+8]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+8]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+8],eax
+
+ mov eax,[esi+12]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+12]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+12],eax
+
+ mov eax,[esi+16]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+16]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+16],eax
+
+ mov eax,[esi+20]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+20]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+20],eax
+
+ mov eax,[esi+24]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+24]
+ adc edx,0
+ mov ecx,edx
+ mov [edi+24],eax
+
+ mov eax,[esi+28]
+ mul ebx
+ add eax,ecx
+ adc edx,0
+ add eax,[edi+28]
+ adc edx,0
+ mov [edi+28],eax
+ mov eax,edx
+ }
+ }
+
+inline word word8_linmul3(word z[4], const word x[4], word y, word carry)
+ {
+ __asm
+ {
+#if 0
+ //it's slower!!!
+ mov edx,[z]
+ mov eax,[x]
+ movd mm7,[y]
+
+ movd mm0,[eax]
+ movd mm1,[eax+4]
+ movd mm2,[eax+8]
+ pmuludq mm0,mm7
+ pmuludq mm1,mm7
+ pmuludq mm2,mm7
+
+ movd mm6,[carry]
+ paddq mm0,mm6
+ movd [edx],mm0
+
+ psrlq mm0,32
+ paddq mm1,mm0
+ movd [edx+4],mm1
+
+ movd mm3,[eax+12]
+ psrlq mm1,32
+ paddq mm2,mm1
+ movd [edx+8],mm2
+
+ pmuludq mm3,mm7
+ movd mm4,[eax+16]
+ psrlq mm2,32
+ paddq mm3,mm2
+ movd [edx+12],mm3
+
+ pmuludq mm4,mm7
+ movd mm5,[eax+20]
+ psrlq mm3,32
+ paddq mm4,mm3
+ movd [edx+16],mm4
+
+ pmuludq mm5,mm7
+ movd mm0,[eax+24]
+ psrlq mm4,32
+ paddq mm5,mm4
+ movd [edx+20],mm5
+
+ pmuludq mm0,mm7
+ movd mm1,[eax+28]
+ psrlq mm5,32
+ paddq mm0,mm5
+ movd [edx+24],mm0
+
+ pmuludq mm1,mm7
+ psrlq mm0,32
+ paddq mm1,mm0
+ movd [edx+28],mm1
+
+ psrlq mm1,32
+ movd eax,mm1
+ emms
+#else
+ mov edi,[z]
+ mov esi,[x]
+ mov eax,[esi] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,[carry] //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi],eax //load a
+
+ mov eax,[esi+4] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+4],eax //load a
+
+ mov eax,[esi+8] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+8],eax //load a
+
+ mov eax,[esi+12] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+12],eax //load a
+
+ mov eax,[esi+16] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+16],eax //load a
+
+ mov eax,[esi+20] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+20],eax //load a
+
+ mov eax,[esi+24] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov ecx,edx //store carry
+ mov [edi+24],eax //load a
+
+ mov eax,[esi+28] //load a
+ mul [y] //edx(hi):eax(lo)=a*b
+ add eax,ecx //sum lo carry
+ adc edx,0 //sum hi carry
+ mov [edi+28],eax //load a
+ mov eax,edx //store carry
+#endif
+ }
+ }
+
+/*
+* Eight Word Block Multiply/Add
+*/
+inline word word8_madd3(word z[8], const word x[8], word y, word carry)
+ {
+ z[0] = word_madd3(x[0], y, z[0], &carry);
+ z[1] = word_madd3(x[1], y, z[1], &carry);
+ z[2] = word_madd3(x[2], y, z[2], &carry);
+ z[3] = word_madd3(x[3], y, z[3], &carry);
+ z[4] = word_madd3(x[4], y, z[4], &carry);
+ z[5] = word_madd3(x[5], y, z[5], &carry);
+ z[6] = word_madd3(x[6], y, z[6], &carry);
+ z[7] = word_madd3(x[7], y, z[7], &carry);
+ return carry;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = *w0;
+ *w0 = word_madd2(a, b, &carry);
+ *w1 += carry;
+ *w2 += (*w1 < carry) ? 1 : 0;
+ }
+
+/*
+* Multiply-Add Accumulator
+*/
+inline void word3_muladd_2(word* w2, word* w1, word* w0, word a, word b)
+ {
+ word carry = 0;
+ a = word_madd2(a, b, &carry);
+ b = carry;
+
+ word top = (b >> (BOTAN_MP_WORD_BITS-1));
+ b <<= 1;
+ b |= (a >> (BOTAN_MP_WORD_BITS-1));
+ a <<= 1;
+
+ carry = 0;
+ *w0 = word_add(*w0, a, &carry);
+ *w1 = word_add(*w1, b, &carry);
+ *w2 = word_add(*w2, top, &carry);
+ }
+
+}
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mp_karat.cpp b/botan/src/math/bigint/mp_karat.cpp
new file mode 100644
index 0000000..f30d418
--- /dev/null
+++ b/botan/src/math/bigint/mp_karat.cpp
@@ -0,0 +1,336 @@
+/*
+* Karatsuba Multiplication/Squaring
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_core.h>
+#include <botan/mem_ops.h>
+#include <botan/mp_asmi.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Karatsuba Multiplication Operation
+*/
+void karatsuba_mul(word z[], const word x[], const word y[], u32bit N,
+ word workspace[])
+ {
+ if(N == 6)
+ bigint_comba_mul6(z, x, y);
+ else if(N == 8)
+ bigint_comba_mul8(z, x, y);
+ else if(N == 16)
+ bigint_comba_mul16(z, x, y);
+ else if(N < BOTAN_KARAT_MUL_THRESHOLD || N % 2)
+ bigint_simple_mul(z, x, N, y, N);
+ else
+ {
+ const u32bit N2 = N / 2;
+
+ const word* x0 = x;
+ const word* x1 = x + N2;
+ const word* y0 = y;
+ const word* y1 = y + N2;
+ word* z0 = z;
+ word* z1 = z + N;
+
+ const s32bit cmp0 = bigint_cmp(x0, N2, x1, N2);
+ const s32bit cmp1 = bigint_cmp(y1, N2, y0, N2);
+
+ clear_mem(workspace, 2*N);
+
+ if(cmp0 && cmp1)
+ {
+ if(cmp0 > 0)
+ bigint_sub3(z0, x0, N2, x1, N2);
+ else
+ bigint_sub3(z0, x1, N2, x0, N2);
+
+ if(cmp1 > 0)
+ bigint_sub3(z1, y1, N2, y0, N2);
+ else
+ bigint_sub3(z1, y0, N2, y1, N2);
+
+ karatsuba_mul(workspace, z0, z1, N2, workspace+N);
+ }
+
+ karatsuba_mul(z0, x0, y0, N2, workspace+N);
+ karatsuba_mul(z1, x1, y1, N2, workspace+N);
+
+ const u32bit blocks_of_8 = N - (N % 8);
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks_of_8; j += 8)
+ carry = word8_add3(workspace + N + j, z0 + j, z1 + j, carry);
+
+ for(u32bit j = blocks_of_8; j != N; ++j)
+ workspace[N + j] = word_add(z0[j], z1[j], &carry);
+
+ word carry2 = 0;
+
+ for(u32bit j = 0; j != blocks_of_8; j += 8)
+ carry2 = word8_add2(z + N2 + j, workspace + N + j, carry2);
+
+ for(u32bit j = blocks_of_8; j != N; ++j)
+ z[N2 + j] = word_add(z[N2 + j], workspace[N + j], &carry2);
+
+ z[N + N2] = word_add(z[N + N2], carry2, &carry);
+
+ if(carry)
+ for(u32bit j = 1; j != N2; ++j)
+ if(++z[N + N2 + j])
+ break;
+
+ if((cmp0 == cmp1) || (cmp0 == 0) || (cmp1 == 0))
+ bigint_add2(z + N2, 2*N-N2, workspace, N);
+ else
+ bigint_sub2(z + N2, 2*N-N2, workspace, N);
+ }
+ }
+
+/*
+* Karatsuba Squaring Operation
+*/
+void karatsuba_sqr(word z[], const word x[], u32bit N, word workspace[])
+ {
+ if(N == 6)
+ bigint_comba_sqr6(z, x);
+ else if(N == 8)
+ bigint_comba_sqr8(z, x);
+ else if(N == 16)
+ bigint_comba_sqr16(z, x);
+ else if(N < BOTAN_KARAT_SQR_THRESHOLD || N % 2)
+ bigint_simple_sqr(z, x, N);
+ else
+ {
+ const u32bit N2 = N / 2;
+
+ const word* x0 = x;
+ const word* x1 = x + N2;
+ word* z0 = z;
+ word* z1 = z + N;
+
+ const s32bit cmp = bigint_cmp(x0, N2, x1, N2);
+
+ clear_mem(workspace, 2*N);
+
+ if(cmp)
+ {
+ if(cmp > 0)
+ bigint_sub3(z0, x0, N2, x1, N2);
+ else
+ bigint_sub3(z0, x1, N2, x0, N2);
+
+ karatsuba_sqr(workspace, z0, N2, workspace+N);
+ }
+
+ karatsuba_sqr(z0, x0, N2, workspace+N);
+ karatsuba_sqr(z1, x1, N2, workspace+N);
+
+ const u32bit blocks_of_8 = N - (N % 8);
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks_of_8; j += 8)
+ carry = word8_add3(workspace + N + j, z0 + j, z1 + j, carry);
+
+ for(u32bit j = blocks_of_8; j != N; ++j)
+ workspace[N + j] = word_add(z0[j], z1[j], &carry);
+
+ word carry2 = 0;
+
+ for(u32bit j = 0; j != blocks_of_8; j += 8)
+ carry2 = word8_add2(z + N2 + j, workspace + N + j, carry2);
+
+ for(u32bit j = blocks_of_8; j != N; ++j)
+ z[N2 + j] = word_add(z[N2 + j], workspace[N + j], &carry2);
+
+ z[N + N2] = word_add(z[N + N2], carry2, &carry);
+
+ if(carry)
+ for(u32bit j = 1; j != N2; ++j)
+ if(++z[N + N2 + j])
+ break;
+
+ if(cmp == 0)
+ bigint_add2(z + N2, 2*N-N2, workspace, N);
+ else
+ bigint_sub2(z + N2, 2*N-N2, workspace, N);
+ }
+ }
+
+/*
+* Pick a good size for the Karatsuba multiply
+*/
+u32bit karatsuba_size(u32bit z_size,
+ u32bit x_size, u32bit x_sw,
+ u32bit y_size, u32bit y_sw)
+ {
+ if(x_sw > x_size || x_sw > y_size || y_sw > x_size || y_sw > y_size)
+ return 0;
+
+ if(((x_size == x_sw) && (x_size % 2)) ||
+ ((y_size == y_sw) && (y_size % 2)))
+ return 0;
+
+ const u32bit start = (x_sw > y_sw) ? x_sw : y_sw;
+ const u32bit end = (x_size < y_size) ? x_size : y_size;
+
+ if(start == end)
+ {
+ if(start % 2)
+ return 0;
+ return start;
+ }
+
+ for(u32bit j = start; j <= end; ++j)
+ {
+ if(j % 2)
+ continue;
+
+ if(2*j > z_size)
+ return 0;
+
+ if(x_sw <= j && j <= x_size && y_sw <= j && j <= y_size)
+ {
+ if(j % 4 == 2 &&
+ (j+2) <= x_size && (j+2) <= y_size && 2*(j+2) <= z_size)
+ return j+2;
+ return j;
+ }
+ }
+
+ return 0;
+ }
+
+/*
+* Pick a good size for the Karatsuba squaring
+*/
+u32bit karatsuba_size(u32bit z_size, u32bit x_size, u32bit x_sw)
+ {
+ if(x_sw == x_size)
+ {
+ if(x_sw % 2)
+ return 0;
+ return x_sw;
+ }
+
+ for(u32bit j = x_sw; j <= x_size; ++j)
+ {
+ if(j % 2)
+ continue;
+
+ if(2*j > z_size)
+ return 0;
+
+ if(j % 4 == 2 && (j+2) <= x_size && 2*(j+2) <= z_size)
+ return j+2;
+ return j;
+ }
+
+ return 0;
+ }
+
+}
+
+/*
+* Multiplication Algorithm Dispatcher
+*/
+void bigint_mul(word z[], u32bit z_size, word workspace[],
+ const word x[], u32bit x_size, u32bit x_sw,
+ const word y[], u32bit y_size, u32bit y_sw)
+ {
+ if(x_sw == 1)
+ {
+ bigint_linmul3(z, y, y_sw, x[0]);
+ }
+ else if(y_sw == 1)
+ {
+ bigint_linmul3(z, x, x_sw, y[0]);
+ }
+ else if(x_sw <= 4 && x_size >= 4 &&
+ y_sw <= 4 && y_size >= 4 && z_size >= 8)
+ {
+ bigint_comba_mul4(z, x, y);
+ }
+ else if(x_sw <= 6 && x_size >= 6 &&
+ y_sw <= 6 && y_size >= 6 && z_size >= 12)
+ {
+ bigint_comba_mul6(z, x, y);
+ }
+ else if(x_sw <= 8 && x_size >= 8 &&
+ y_sw <= 8 && y_size >= 8 && z_size >= 16)
+ {
+ bigint_comba_mul8(z, x, y);
+ }
+ else if(x_sw <= 16 && x_size >= 16 &&
+ y_sw <= 16 && y_size >= 16 && z_size >= 32)
+ {
+ bigint_comba_mul16(z, x, y);
+ }
+ else if(x_sw < BOTAN_KARAT_MUL_THRESHOLD || y_sw < BOTAN_KARAT_MUL_THRESHOLD)
+ bigint_simple_mul(z, x, x_sw, y, y_sw);
+ else
+ {
+ const u32bit N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);
+
+ if(N)
+ {
+ clear_mem(workspace, 2*N);
+ karatsuba_mul(z, x, y, N, workspace);
+ }
+ else
+ bigint_simple_mul(z, x, x_sw, y, y_sw);
+ }
+ }
+
+/*
+* Squaring Algorithm Dispatcher
+*/
+void bigint_sqr(word z[], u32bit z_size, word workspace[],
+ const word x[], u32bit x_size, u32bit x_sw)
+ {
+ if(x_sw == 1)
+ {
+ bigint_linmul3(z, x, x_sw, x[0]);
+ }
+ else if(x_sw <= 4 && x_size >= 4 && z_size >= 8)
+ {
+ bigint_comba_sqr4(z, x);
+ }
+ else if(x_sw <= 6 && x_size >= 6 && z_size >= 12)
+ {
+ bigint_comba_sqr6(z, x);
+ }
+ else if(x_sw <= 8 && x_size >= 8 && z_size >= 16)
+ {
+ bigint_comba_sqr8(z, x);
+ }
+ else if(x_sw <= 16 && x_size >= 16 && z_size >= 32)
+ {
+ bigint_comba_sqr16(z, x);
+ }
+ else if(x_size < BOTAN_KARAT_SQR_THRESHOLD)
+ {
+ bigint_simple_sqr(z, x, x_sw);
+ }
+ else
+ {
+ const u32bit N = karatsuba_size(z_size, x_size, x_sw);
+
+ if(N)
+ {
+ clear_mem(workspace, 2*N);
+ karatsuba_sqr(z, x, N, workspace);
+ }
+ else
+ bigint_simple_sqr(z, x, x_sw);
+ }
+ }
+
+}
diff --git a/botan/src/math/bigint/mp_misc.cpp b/botan/src/math/bigint/mp_misc.cpp
new file mode 100644
index 0000000..6b7fc65
--- /dev/null
+++ b/botan/src/math/bigint/mp_misc.cpp
@@ -0,0 +1,94 @@
+/*
+* MP Misc Functions
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_core.h>
+#include <botan/mp_asm.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Core Division Operation
+*/
+u32bit bigint_divcore(word q, word y1, word y2,
+ word x1, word x2, word x3)
+ {
+ word y0 = 0;
+ y2 = word_madd2(q, y2, &y0);
+ y1 = word_madd2(q, y1, &y0);
+
+ if(y0 > x1) return 1;
+ if(y0 < x1) return 0;
+ if(y1 > x2) return 1;
+ if(y1 < x2) return 0;
+ if(y2 > x3) return 1;
+ if(y2 < x3) return 0;
+ return 0;
+ }
+
+/*
+* Compare two MP integers
+*/
+s32bit bigint_cmp(const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ if(x_size < y_size) { return (-bigint_cmp(y, y_size, x, x_size)); }
+
+ while(x_size > y_size)
+ {
+ if(x[x_size-1])
+ return 1;
+ x_size--;
+ }
+ for(u32bit j = x_size; j > 0; --j)
+ {
+ if(x[j-1] > y[j-1]) return 1;
+ if(x[j-1] < y[j-1]) return -1;
+ }
+ return 0;
+ }
+
+/*
+* Do a 2-word/1-word Division
+*/
+word bigint_divop(word n1, word n0, word d)
+ {
+ word high = n1 % d, quotient = 0;
+
+ for(u32bit j = 0; j != MP_WORD_BITS; ++j)
+ {
+ word high_top_bit = (high & MP_WORD_TOP_BIT);
+
+ high <<= 1;
+ high |= (n0 >> (MP_WORD_BITS-1-j)) & 1;
+ quotient <<= 1;
+
+ if(high_top_bit || high >= d)
+ {
+ high -= d;
+ quotient |= 1;
+ }
+ }
+
+ return quotient;
+ }
+
+/*
+* Do a 2-word/1-word Modulo
+*/
+word bigint_modop(word n1, word n0, word d)
+ {
+ word z = bigint_divop(n1, n0, d);
+ word dummy = 0;
+ z = word_madd2(z, d, &dummy);
+ return (n0-z);
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mp_shift.cpp b/botan/src/math/bigint/mp_shift.cpp
new file mode 100644
index 0000000..a7de79c
--- /dev/null
+++ b/botan/src/math/bigint/mp_shift.cpp
@@ -0,0 +1,138 @@
+/*
+* MP Shift Algorithms
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_core.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Single Operand Left Shift
+*/
+void bigint_shl1(word x[], u32bit x_size, u32bit word_shift, u32bit bit_shift)
+ {
+ if(word_shift)
+ {
+ for(u32bit j = 1; j != x_size + 1; ++j)
+ x[(x_size - j) + word_shift] = x[x_size - j];
+ clear_mem(x, word_shift);
+ }
+
+ if(bit_shift)
+ {
+ word carry = 0;
+ for(u32bit j = word_shift; j != x_size + word_shift + 1; ++j)
+ {
+ word temp = x[j];
+ x[j] = (temp << bit_shift) | carry;
+ carry = (temp >> (MP_WORD_BITS - bit_shift));
+ }
+ }
+ }
+
+/*
+* Single Operand Right Shift
+*/
+void bigint_shr1(word x[], u32bit x_size, u32bit word_shift, u32bit bit_shift)
+ {
+ if(x_size < word_shift)
+ {
+ clear_mem(x, x_size);
+ return;
+ }
+
+ if(word_shift)
+ {
+ copy_mem(x, x + word_shift, x_size - word_shift);
+ clear_mem(x + x_size - word_shift, word_shift);
+ }
+
+ if(bit_shift)
+ {
+ word carry = 0;
+
+ u32bit top = x_size - word_shift;
+
+ while(top >= 4)
+ {
+ word w = x[top-1];
+ x[top-1] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+
+ w = x[top-2];
+ x[top-2] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+
+ w = x[top-3];
+ x[top-3] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+
+ w = x[top-4];
+ x[top-4] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+
+ top -= 4;
+ }
+
+ while(top)
+ {
+ word w = x[top-1];
+ x[top-1] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+
+ top--;
+ }
+ }
+ }
+
+/*
+* Two Operand Left Shift
+*/
+void bigint_shl2(word y[], const word x[], u32bit x_size,
+ u32bit word_shift, u32bit bit_shift)
+ {
+ for(u32bit j = 0; j != x_size; ++j)
+ y[j + word_shift] = x[j];
+ if(bit_shift)
+ {
+ word carry = 0;
+ for(u32bit j = word_shift; j != x_size + word_shift + 1; ++j)
+ {
+ word w = y[j];
+ y[j] = (w << bit_shift) | carry;
+ carry = (w >> (MP_WORD_BITS - bit_shift));
+ }
+ }
+ }
+
+/*
+* Two Operand Right Shift
+*/
+void bigint_shr2(word y[], const word x[], u32bit x_size,
+ u32bit word_shift, u32bit bit_shift)
+ {
+ if(x_size < word_shift) return;
+
+ for(u32bit j = 0; j != x_size - word_shift; ++j)
+ y[j] = x[j + word_shift];
+ if(bit_shift)
+ {
+ word carry = 0;
+ for(u32bit j = x_size - word_shift; j > 0; --j)
+ {
+ word w = y[j-1];
+ y[j-1] = (w >> bit_shift) | carry;
+ carry = (w << (MP_WORD_BITS - bit_shift));
+ }
+ }
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mp_types.h b/botan/src/math/bigint/mp_types.h
new file mode 100644
index 0000000..1648713
--- /dev/null
+++ b/botan/src/math/bigint/mp_types.h
@@ -0,0 +1,33 @@
+/*
+* Low Level MPI Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MPI_TYPES_H__
+#define BOTAN_MPI_TYPES_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+#if (BOTAN_MP_WORD_BITS == 8)
+ typedef byte word;
+#elif (BOTAN_MP_WORD_BITS == 16)
+ typedef u16bit word;
+#elif (BOTAN_MP_WORD_BITS == 32)
+ typedef u32bit word;
+#elif (BOTAN_MP_WORD_BITS == 64)
+ typedef u64bit word;
+#else
+ #error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
+#endif
+
+const word MP_WORD_MASK = ~static_cast<word>(0);
+const word MP_WORD_TOP_BIT = static_cast<word>(1) << (8*sizeof(word) - 1);
+const word MP_WORD_MAX = MP_WORD_MASK;
+
+}
+
+#endif
diff --git a/botan/src/math/bigint/mulop_amd64/info.txt b/botan/src/math/bigint/mulop_amd64/info.txt
new file mode 100644
index 0000000..77990df
--- /dev/null
+++ b/botan/src/math/bigint/mulop_amd64/info.txt
@@ -0,0 +1,32 @@
+realname "BigInt Multiply-Add (x86-64)"
+
+mp_bits 64
+
+load_on never
+
+<add>
+mp_mulop_amd64.S
+</add>
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_amd64
+</requires>
diff --git a/botan/src/math/bigint/mulop_amd64/mp_mulop.cpp b/botan/src/math/bigint/mulop_amd64/mp_mulop.cpp
new file mode 100644
index 0000000..cbd723e
--- /dev/null
+++ b/botan/src/math/bigint/mulop_amd64/mp_mulop.cpp
@@ -0,0 +1,96 @@
+/*
+* Simple O(N^2) Multiplication and Squaring
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_asm.h>
+#include <botan/mp_asmi.h>
+#include <botan/mp_core.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Simple O(N^2) Multiplication
+*/
+void bigint_simple_mul(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ const u32bit blocks = x_size - (x_size % 8);
+
+ clear_mem(z, x_size + y_size);
+
+ for(u32bit i = 0; i != y_size; ++i)
+ {
+ word carry = 0;
+
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_madd3(z + i + j, x + j, y[i], carry);
+
+ for(u32bit j = blocks; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], y[i], z[i+j], &carry);
+
+ z[x_size+i] = carry;
+ }
+ }
+
+inline word word_sqr(word x,
+
+/*
+* Simple O(N^2) Squaring
+
+This is exactly the same algorithm as bigint_simple_mul,
+however because C/C++ compilers suck at alias analysis it
+is good to have the version where the compiler knows
+that x == y
+*/
+void bigint_simple_sqr(word z[], const word x[], u32bit x_size)
+ {
+ clear_mem(z, 2*x_size);
+
+ for(u32bit i = 0; i != x_size; ++i)
+ {
+ const word x_i = x[i];
+
+ word carry = z[2*i];
+ z[2*i] = word_madd2(x_i, x_i, z[2*i], &carry);
+
+ for(u32bit j = i; j != x_size; ++j)
+ {
+ // z[i+j] = z[i+j] + 2 * x[j] * x_i + carry;
+
+ /*
+ load z[i+j] into register
+ load x[j] into %hi
+ mulq %[x_i] -> x[i] * x[j] -> %lo:%hi
+ shlq %lo, $1
+
+ // put carry bit (cf) from %lo into %temp
+ xorl %temp
+ adcq $0, %temp
+
+ // high bit of lo now in cf
+ shl %hi, $1
+ // add in lowest bid from %lo
+ orl %temp, %hi
+
+ addq %[c], %[lo]
+ adcq $0, %[hi]
+ addq %[z_ij], %[lo]
+ adcq $0, %[hi]
+
+ */
+
+ }
+
+ z[x_size+i] = carry;
+ }
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mulop_amd64/mp_mulop_amd64.S b/botan/src/math/bigint/mulop_amd64/mp_mulop_amd64.S
new file mode 100644
index 0000000..63ac55e
--- /dev/null
+++ b/botan/src/math/bigint/mulop_amd64/mp_mulop_amd64.S
@@ -0,0 +1,130 @@
+/*
+* Simple O(N^2) Multiplication and Squaring
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(mp_mulop.S)
+
+#if 0
+void bigint_simple_sqr(word z[], const word x[], u32bit x_size)
+ {
+ const u32bit blocks = x_size - (x_size % 8);
+
+ clear_mem(z, 2*x_size);
+
+ for(u32bit i = 0; i != x_size; ++i)
+ {
+ word carry = 0;
+
+ /*
+ for(u32bit j = 0; j != blocks; j += 8)
+ carry = word8_madd3(z + i + j, x + j, x[i], carry);
+
+ for(u32bit j = blocks; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], x[i], z[i+j], &carry);
+ */
+
+
+ for(u32bit j = 0; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], x[i], z[i+j], &carry);
+
+ for(u32bit j = 0; j != x_size; ++j)
+ {
+ dword z = (dword)a * b + c + *d;
+ *d = (word)(z >> BOTAN_MP_WORD_BITS);
+ return (word)z;
+ }
+
+
+
+ z[i+j] = word_madd3(x[j], x[i], z[i+j], &carry);
+
+ }
+
+
+
+ z[x_size+i] = carry;
+ }
+ }
+
+#endif
+
+START_FUNCTION(bigint_simple_sqr)
+
+#define Z_ARR ARG_1
+#define X_ARR ARG_2
+//#define X_SIZE ARG_3_32
+
+#define CARRY TEMP_1
+#define Z_WORD TEMP_2
+#define LOOP_I TEMP_3
+#define LOOP_J TEMP_4
+#define X_SIZE TEMP_5
+#define MUL_LO %rax
+// arg 3, xsize
+#define MUL_HI %rdx
+
+// need arg3 == rdx for multiply
+ ASSIGN(X_SIZE, ARG3_32)
+
+ ZEROIZE(CARRY)
+
+ ZEROIZE(LOOP_I)
+
+.LOOP_ZEROIZE_Z:
+
+ cmp LOOP_I, X_SIZE
+
+
+
+
+ JUMP_IF_ZERO(LOOP_CTR, .L_MULADD_DONE)
+ JUMP_IF_LT(LOOP_CTR, 8, .LOOP_MULADD1)
+
+#define MULADD_OP(N) \
+ ASSIGN(MUL_LO, ARRAY8(X_ARR, N)) ; \
+ ASSIGN(Z_WORD, ARRAY8(Z_ARR, N)) ; \
+ MUL(Y) ; \
+ ADD(Z_WORD, CARRY) ; \
+ ASSIGN(CARRY, MUL_HI) ; \
+ ADD_LAST_CARRY(CARRY) ; \
+ ADD(Z_WORD, MUL_LO) ; \
+ ADD_LAST_CARRY(CARRY) ; \
+ ASSIGN(ARRAY8(Z_ARR, N), Z_WORD)
+
+.LOOP_MULADD8:
+ MULADD_OP(0)
+ MULADD_OP(1)
+ MULADD_OP(2)
+ MULADD_OP(3)
+ MULADD_OP(4)
+ MULADD_OP(5)
+ MULADD_OP(6)
+ MULADD_OP(7)
+
+ SUB_IMM(LOOP_CTR, 8)
+ ADD_IMM(Z_ARR, 64)
+ ADD_IMM(X_ARR, 64)
+ cmp IMM(8), LOOP_CTR
+ jge .LOOP_MULADD8
+
+ JUMP_IF_ZERO(LOOP_CTR, .L_MULADD_DONE)
+
+ALIGN
+.LOOP_MULADD1:
+ MULADD_OP(0)
+
+ SUB_IMM(LOOP_CTR, 1)
+ ADD_IMM(Z_ARR, 8)
+ ADD_IMM(X_ARR, 8)
+
+ cmp IMM(0), LOOP_CTR
+ jne .LOOP_MULADD1
+
+.L_MULADD_DONE:
+ RETURN_VALUE_IS(CARRY)
+END_FUNCTION(bigint_simple_square)
diff --git a/botan/src/math/bigint/mulop_generic/info.txt b/botan/src/math/bigint/mulop_generic/info.txt
new file mode 100644
index 0000000..28ebe41
--- /dev/null
+++ b/botan/src/math/bigint/mulop_generic/info.txt
@@ -0,0 +1,7 @@
+realname "BigInt Multiply-Add"
+
+load_on dep
+
+<add>
+mp_mulop.cpp
+</add>
diff --git a/botan/src/math/bigint/mulop_generic/mp_mulop.cpp b/botan/src/math/bigint/mulop_generic/mp_mulop.cpp
new file mode 100644
index 0000000..4647d00
--- /dev/null
+++ b/botan/src/math/bigint/mulop_generic/mp_mulop.cpp
@@ -0,0 +1,77 @@
+/*
+* Simple O(N^2) Multiplication and Squaring
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mp_asm.h>
+#include <botan/mp_asmi.h>
+#include <botan/mp_core.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Simple O(N^2) Multiplication
+*/
+void bigint_simple_mul(word z[], const word x[], u32bit x_size,
+ const word y[], u32bit y_size)
+ {
+ const u32bit x_size_8 = x_size - (x_size % 8);
+
+ clear_mem(z, x_size + y_size);
+
+ for(u32bit i = 0; i != y_size; ++i)
+ {
+ const word y_i = y[i];
+
+ word carry = 0;
+
+ for(u32bit j = 0; j != x_size_8; j += 8)
+ carry = word8_madd3(z + i + j, x + j, y_i, carry);
+
+ for(u32bit j = x_size_8; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], y_i, z[i+j], &carry);
+
+ z[x_size+i] = carry;
+ }
+ }
+
+/*
+* Simple O(N^2) Squaring
+
+This is exactly the same algorithm as bigint_simple_mul,
+however because C/C++ compilers suck at alias analysis it
+is good to have the version where the compiler knows
+that x == y
+
+There is an O(n^1.5) squaring algorithm specified in Handbook of
+Applied Cryptography, chapter 14
+*/
+void bigint_simple_sqr(word z[], const word x[], u32bit x_size)
+ {
+ const u32bit x_size_8 = x_size - (x_size % 8);
+
+ clear_mem(z, 2*x_size);
+
+ for(u32bit i = 0; i != x_size; ++i)
+ {
+ const word x_i = x[i];
+ word carry = 0;
+
+ for(u32bit j = 0; j != x_size_8; j += 8)
+ carry = word8_madd3(z + i + j, x + j, x_i, carry);
+
+ for(u32bit j = x_size_8; j != x_size; ++j)
+ z[i+j] = word_madd3(x[j], x_i, z[i+j], &carry);
+
+ z[x_size+i] = carry;
+ }
+ }
+
+}
+
+}
diff --git a/botan/src/math/bigint/mulop_ia32/info.txt b/botan/src/math/bigint/mulop_ia32/info.txt
new file mode 100644
index 0000000..b995dd8
--- /dev/null
+++ b/botan/src/math/bigint/mulop_ia32/info.txt
@@ -0,0 +1,34 @@
+realname "BigInt Multiply-Add (IA-32)"
+
+mp_bits 32
+
+# Out of date, still implements bigint_mul_add_words
+
+load_on request
+
+<add>
+mp_mulop.S
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
+
+# ELF systems
+<os>
+linux
+freebsd
+dragonfly
+netbsd
+openbsd
+solaris
+</os>
+
+<requires>
+asm_ia32
+</requires>
diff --git a/botan/src/math/bigint/mulop_ia32/mp_mulop.S b/botan/src/math/bigint/mulop_ia32/mp_mulop.S
new file mode 100644
index 0000000..716166f
--- /dev/null
+++ b/botan/src/math/bigint/mulop_ia32/mp_mulop.S
@@ -0,0 +1,64 @@
+/*
+* Multiply/Add Algorithm Source File
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/asm_macr.h>
+
+START_LISTING(mp_muladd.S)
+
+START_FUNCTION(bigint_mul_add_words)
+ SPILL_REGS()
+#define PUSHED 4
+
+#define LOOP_CTR ESI
+ ASSIGN(LOOP_CTR, ARG(3)) /* x_size */
+ ZEROIZE(EDI)
+
+ ASSIGN(ECX, ARG(1)) /* z[] */
+ ASSIGN(EBX, ARG(2)) /* x[] */
+ ASSIGN(EBP, ARG(4)) /* y */
+
+#define MULADD_OP(N) \
+ ASSIGN(EAX, ARRAY4(EBX, N)) ; \
+ MUL(EBP) ; \
+ ADD_W_CARRY(EAX, EDX, EDI) ; \
+ ASSIGN(EDI, EDX) ; \
+ ADD_W_CARRY(ARRAY4(ECX, N), EDI, EAX) ;
+
+ JUMP_IF_ZERO(LOOP_CTR, .MUL_ADD_DONE)
+ JUMP_IF_LT(LOOP_CTR, 8, .MULADD1_LOOP)
+
+START_LOOP(.MULADD8)
+ MULADD_OP(0)
+ MULADD_OP(1)
+ MULADD_OP(2)
+ MULADD_OP(3)
+ MULADD_OP(4)
+ MULADD_OP(5)
+ MULADD_OP(6)
+ MULADD_OP(7)
+
+ SUB_IMM(LOOP_CTR, 8)
+ ADD_IMM(EBX, 32)
+ ADD_IMM(ECX, 32)
+LOOP_UNTIL_LT(LOOP_CTR, 8, .MULADD8)
+
+ JUMP_IF_ZERO(LOOP_CTR, .MUL_ADD_DONE)
+
+START_LOOP(.MULADD1)
+ MULADD_OP(0)
+
+ SUB_IMM(LOOP_CTR, 1)
+ ADD_IMM(EBX, 4)
+ ADD_IMM(ECX, 4)
+LOOP_UNTIL_EQ(LOOP_CTR, 0, .MULADD1)
+
+.MUL_ADD_DONE:
+
+ ASSIGN(EAX, EDI)
+#undef PUSHED
+ RESTORE_REGS()
+END_FUNCTION(bigint_mul_add_words)
diff --git a/botan/src/math/gfpmath/curve_gfp.cpp b/botan/src/math/gfpmath/curve_gfp.cpp
new file mode 100644
index 0000000..e12ade0
--- /dev/null
+++ b/botan/src/math/gfpmath/curve_gfp.cpp
@@ -0,0 +1,165 @@
+/******
+* Elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering
+* Christoph Ludwig
+* Falko Strenzke
+* 2008 Jack Lloyd
+******/
+
+#include <botan/curve_gfp.h>
+#include <botan/bigint.h>
+#include <assert.h>
+#include <ostream>
+
+namespace Botan {
+
+void CurveGFp::set_shrd_mod(const std::tr1::shared_ptr<GFpModulus> mod)
+ {
+ mp_mod = mod;
+ mA.turn_off_sp_red_mul();// m.m. is not needed, must be trf. back
+ mB.turn_off_sp_red_mul();// m.m. is not needed, must be trf. back
+ //ok, above we destroy any evantually computated montg. mult. values,
+ // but that won't influence performance in usual applications
+ mA.set_shrd_mod(mod);
+ mB.set_shrd_mod(mod);
+ }
+
+CurveGFp::CurveGFp(const GFpElement& a, const GFpElement& b,
+ const BigInt& p)
+ : mA(a),
+ mB(b)
+ {
+ if(!((p == mA.get_p()) && (p == mB.get_p())))
+ {
+ throw Invalid_Argument("could not construct curve: moduli of arguments differ");
+ }
+ std::tr1::shared_ptr<GFpModulus> p_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(p));
+ // the above is the creation of the GFpModuls object which will be shared point-wide
+ // (in the context of a point of course)
+ set_shrd_mod(p_mod);
+ }
+// copy constructor
+CurveGFp::CurveGFp(const CurveGFp& other)
+ : mA(other.get_a()),
+ mB(other.get_b())
+ {
+ mp_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(*other.mp_mod));
+ assert(mp_mod->p_equal_to(mA.get_p()));
+ assert(mp_mod->p_equal_to(mB.get_p()));
+ set_shrd_mod(mp_mod);
+ if(other.mp_mres_a.get())
+ {
+ mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_a));
+ }
+ if(other.mp_mres_b.get())
+ {
+ mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_b));
+ }
+ if(other.mp_mres_one.get())
+ {
+ mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_one));
+ }
+
+ }
+
+// assignment operator
+const CurveGFp& CurveGFp::operator=(const CurveGFp& other)
+ {
+ // for exception safety...
+ GFpElement a_tmp = other.mA;
+ GFpElement b_tmp = other.mB;
+ mA.swap(a_tmp);
+ mB.swap(b_tmp);
+
+ std::tr1::shared_ptr<GFpModulus> p_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(*other.mp_mod));
+ set_shrd_mod(p_mod);
+
+ // exception safety note: no problem if we have a throw from here on...
+ if(other.mp_mres_a.get())
+ {
+ mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_a));
+ }
+ if(other.mp_mres_b.get())
+ {
+ mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_b));
+ }
+ if(other.mp_mres_one.get())
+ {
+ mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(*other.mp_mres_one));
+ }
+ return *this;
+ }
+
+// getters
+const GFpElement& CurveGFp::get_a() const
+ {
+ return mA;
+ }
+
+const GFpElement& CurveGFp::get_b() const
+ {
+ return mB;
+ }
+
+const BigInt CurveGFp::get_p() const
+ {
+ assert(mp_mod.get() != 0);
+ return mp_mod->get_p();
+ }
+
+// swaps the states of *this and other, does not throw
+void CurveGFp::swap(CurveGFp& other)
+ {
+ mA.swap(other.mA);
+ mB.swap(other.mB);
+ mp_mod.swap(other.mp_mod);
+ std::swap(mp_mres_a, other.mp_mres_a);
+ std::swap(mp_mres_b, other.mp_mres_b);
+ std::swap(mp_mres_one, other.mp_mres_one);
+ }
+
+GFpElement const CurveGFp::get_mres_a() const
+ {
+ if(mp_mres_a.get() == 0)
+ {
+ mp_mres_a = std::tr1::shared_ptr<GFpElement>(new GFpElement(mA));
+ mp_mres_a->turn_on_sp_red_mul();
+ mp_mres_a->get_mres();
+ }
+ return GFpElement(*mp_mres_a);
+ }
+
+GFpElement const CurveGFp::get_mres_b() const
+ {
+ if(mp_mres_b.get() == 0)
+ {
+ mp_mres_b = std::tr1::shared_ptr<GFpElement>(new GFpElement(mB));
+ mp_mres_b->turn_on_sp_red_mul();
+ mp_mres_b->get_mres();
+ }
+ return GFpElement(*mp_mres_b);
+ }
+
+std::tr1::shared_ptr<GFpElement const> const CurveGFp::get_mres_one() const
+ {
+ if(mp_mres_one.get() == 0)
+ {
+ mp_mres_one = std::tr1::shared_ptr<GFpElement>(new GFpElement(mp_mod->get_p(), 1));
+ mp_mres_one->turn_on_sp_red_mul();
+ mp_mres_one->get_mres();
+ }
+ return mp_mres_one;
+ }
+
+bool operator==(const CurveGFp& lhs, const CurveGFp& rhs)
+ {
+ return (lhs.get_p() == rhs.get_p() && lhs.get_a() == rhs.get_a() && lhs.get_b() == rhs.get_b());
+ }
+
+std::ostream& operator<<(std::ostream& output, const CurveGFp& elem)
+ {
+ return output << "y^2f = x^3 + (" << elem.get_a() << ")x + (" << elem.get_b() << ")";
+ }
+
+}
diff --git a/botan/src/math/gfpmath/curve_gfp.h b/botan/src/math/gfpmath/curve_gfp.h
new file mode 100644
index 0000000..81cf6ce
--- /dev/null
+++ b/botan/src/math/gfpmath/curve_gfp.h
@@ -0,0 +1,177 @@
+/******
+ * Elliptic curves over GF(p) (header file)
+ *
+ * (C) 2007 Martin Doering
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_CURVE_H__
+#define BOTAN_GFP_CURVE_H__
+
+#include <botan/bigint.h>
+#include <botan/gfp_element.h>
+#include <iosfwd>
+
+namespace Botan {
+
+/**
+* This class represents an elliptic curve over GF(p)
+*
+* Distributed under the terms of the Botan license
+*/
+class BOTAN_DLL CurveGFp
+ {
+ public:
+
+ /**
+ * Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
+ * @param a first coefficient
+ * @param b second coefficient
+ * @param p prime number of the field
+ */
+ CurveGFp(const GFpElement& a, const GFpElement& b,
+ const BigInt& p);
+
+ /**
+ * Copy constructor
+ * @param other The curve to clone
+ */
+ CurveGFp(const CurveGFp& other);
+
+ /**
+ * Assignment operator
+ * @param other The curve to use as source for the assignment
+ */
+ const CurveGFp& operator=(const CurveGFp& other);
+
+ /**
+ * Set the shared GFpModulus object.
+ * Warning: do not use this function unless you know in detail how
+ * the sharing of values
+ * in the various EC related objects works.
+ * Do NOT spread pointers to a GFpModulus over different threads!
+ * @param mod a shared pointer to a GFpModulus object suitable for
+ * *this.
+ */
+ void set_shrd_mod(const std::tr1::shared_ptr<GFpModulus> mod);
+
+ // getters
+
+ /**
+ * Get coefficient a
+ * @result coefficient a
+ */
+ const GFpElement& get_a() const;
+
+ /**
+ * Get coefficient b
+ * @result coefficient b
+ */
+ const GFpElement& get_b() const;
+
+ /**
+ * Get the GFpElement coefficient a transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the coefficient a, transformed to its m-residue
+ */
+ GFpElement const get_mres_a() const;
+
+ /**
+ * Get the GFpElement coefficient b transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the coefficient b, transformed to its m-residue
+ */
+ GFpElement const get_mres_b() const;
+
+
+ /**
+ * Get the GFpElement 1 transformed
+ * to its m-residue. This can be used for efficency reasons: the curve
+ * stores the transformed version after the first invocation of this
+ * function.
+ * @result the GFpElement 1, transformed to its m-residue
+ */
+ std::tr1::shared_ptr<GFpElement const> const get_mres_one() const;
+
+ /**
+ * Get prime modulus of the field of the curve
+ * @result prime modulus of the field of the curve
+ */
+ BigInt const get_p() const;
+ /*inline std::tr1::shared_ptr<BigInt> const get_ptr_p() const
+ {
+ return mp_p;
+ }*/
+
+ /**
+ * Retrieve a shared pointer to the curves GFpModulus object for efficient storage
+ * and computation of montgomery multiplication related data members and functions.
+ * Warning: do not use this function unless you know in detail how the sharing of values
+ * in the various EC related objects works.
+ * Do NOT spread pointers to a GFpModulus over different threads!
+ * @result a shared pointer to a GFpModulus object
+ */
+ inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
+ {
+ return mp_mod;
+ }
+
+ /**
+ * swaps the states of *this and other, does not throw
+ * @param other The curve to swap values with
+ */
+ void swap(CurveGFp& other);
+
+ private:
+ std::tr1::shared_ptr<GFpModulus> mp_mod;
+ GFpElement mA;
+ GFpElement mB;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_a;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_b;
+ mutable std::tr1::shared_ptr<GFpElement> mp_mres_one;
+ };
+
+// relational operators
+bool operator==(const CurveGFp& lhs, const CurveGFp& rhs);
+
+inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+// io operators
+std::ostream& operator<<(std::ostream& output, const CurveGFp& elem);
+
+// swaps the states of curve1 and curve2, does not throw!
+// cf. Meyers, Item 25
+inline
+void swap(CurveGFp& curve1, CurveGFp& curve2)
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace Botan
+
+
+namespace std {
+
+// swaps the states of curve1 and curve2, does not throw!
+// cf. Meyers, Item 25
+template<> inline
+void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
+ Botan::CurveGFp& curve2)
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace std
+
+#endif
diff --git a/botan/src/math/gfpmath/gfp_element.cpp b/botan/src/math/gfpmath/gfp_element.cpp
new file mode 100644
index 0000000..b718093
--- /dev/null
+++ b/botan/src/math/gfpmath/gfp_element.cpp
@@ -0,0 +1,699 @@
+/******
+ * Arithmetic for prime fields GF(p) (source file)
+ *
+ * (C) 2007 Martin Doering
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#include <botan/gfp_element.h>
+#include <botan/numthry.h>
+#include <botan/def_powm.h>
+#include <botan/mp_types.h>
+#include <botan/mp_asm.h>
+#include <botan/mp_asmi.h>
+#include <assert.h>
+#include <ostream>
+
+namespace Botan {
+
+namespace {
+
+void inner_montg_mult_sos(word result[], const word* a_bar, const word* b_bar, const word* n, const word* n_dash, u32bit s)
+ {
+ SecureVector<word> t;
+ t.grow_to(2*s+1);
+
+ // t = a_bar * b_bar
+ for (u32bit i=0; i<s; i++)
+ {
+ word C = 0;
+ word S = 0;
+ for (u32bit j=0; j<s; j++)
+ {
+ // we use:
+ // word word_madd3(word a, word b, word c, word d, word* carry)
+ // returns a * b + c + d and resets the carry (not using it as input)
+
+ S = word_madd3(a_bar[j], b_bar[i], t[i+j], &C);
+ t[i+j] = S;
+ }
+ t[i+s] = C;
+ }
+
+ // ???
+ for (u32bit i=0; i<s; i++)
+ {
+ // word word_madd2(word a, word b, word c, word* carry)
+ // returns a * b + c, resets the carry
+
+ word C = 0;
+ word zero = 0;
+ word m = word_madd2(t[i], n_dash[0], &zero);
+
+ for (u32bit j=0; j<s; j++)
+ {
+ word S = word_madd3(m, n[j], t[i+j], &C);
+ t[i+j] = S;
+ }
+
+ //// mp_mulop.cpp:
+ ////word bigint_mul_add_words(word z[], const word x[], u32bit x_size, word y)
+ u32bit cnt = 0;
+ while (C > 0)
+ {
+ // we need not worry here about C > 1, because the other operand is zero
+ word tmp = word_add(t[i+s+cnt], 0, &C);
+ t[i+s+cnt] = tmp;
+ cnt++;
+ }
+ }
+
+ // u = t
+ SecureVector<word> u;
+ u.grow_to(s+1);
+ for (u32bit j=0; j<s+1; j++)
+ {
+ u[j] = t[j+s];
+ }
+
+ // t = u - n
+ word B = 0;
+ word D = 0;
+ for (u32bit i=0; i<s; i++)
+ {
+ D = word_sub(u[i], n[i], &B);
+ t[i] = D;
+ }
+ D = word_sub(u[s], 0, &B);
+ t[s] = D;
+
+ // if t >= 0 (B == 0 -> no borrow), return t
+ if(B == 0)
+ {
+ for (u32bit i=0; i<s; i++)
+ {
+ result[i] = t[i];
+ }
+ }
+ else // else return u
+ {
+ for (u32bit i=0; i<s; i++)
+ {
+ result[i] = u[i];
+ }
+ }
+ }
+
+void montg_mult(BigInt& result, BigInt& a_bar, BigInt& b_bar, const BigInt& m, const BigInt& m_dash, const BigInt)
+ {
+ if(m.is_zero() || m_dash.is_zero())
+ throw Invalid_Argument("montg_mult(): neither modulus nor m_dash may be zero (and one of them was)");
+
+ if(a_bar.is_zero() || b_bar.is_zero())
+ result = 0;
+
+ u32bit s = m.sig_words();
+ a_bar.grow_to(s);
+ b_bar.grow_to(s);
+ result.grow_to(s);
+
+ inner_montg_mult_sos(result.get_reg(), a_bar.data(), b_bar.data(),
+ m.data(), m_dash.data(), s);
+ }
+
+/**
+*calculates R=b^n (here b=2) with R>m (and R beeing as small as possible) for an odd modulus m.
+* no check for oddity is performed!
+*
+* Distributed under the terms of the Botan license
+*/
+BigInt montgm_calc_r_oddmod(const BigInt& prime)
+ {
+ u32bit n = prime.sig_words();
+ BigInt result(1);
+ result <<= n*BOTAN_MP_WORD_BITS;
+ return result;
+ }
+
+/**
+*calculates m' with r*r^-1 - m*m' = 1
+* where r^-1 is the multiplicative inverse of r to the modulus m
+*/
+BigInt montgm_calc_m_dash(const BigInt& r, const BigInt& m, const BigInt& r_inv)
+ {
+ BigInt result = ((r * r_inv) - BigInt(1))/m;
+ return result;
+ }
+
+BigInt montg_trf_to_mres(const BigInt& ord_res, const BigInt& r, const BigInt& m)
+ {
+ BigInt result(ord_res);
+ result *= r;
+ result %= m;
+ return result;
+ }
+
+BigInt montg_trf_to_ordres(const BigInt& m_res, const BigInt& m, const BigInt& r_inv)
+ {
+ BigInt result(m_res);
+ result *= r_inv;
+ result %= m;
+ return result;
+ }
+
+}
+
+GFpElement::GFpElement(const BigInt& p, const BigInt& value, bool use_montgm)
+ : mp_mod(),
+ m_value(value %p),
+ m_use_montgm(use_montgm),
+ m_is_trf(false)
+ {
+ assert(mp_mod.get() == 0);
+ mp_mod = std::tr1::shared_ptr<GFpModulus>(new GFpModulus(p));
+ assert(mp_mod->m_p_dash == 0);
+ if(m_use_montgm)
+ ensure_montgm_precomp();
+ }
+
+GFpElement::GFpElement(std::tr1::shared_ptr<GFpModulus> const mod, const BigInt& value, bool use_montgm)
+ : mp_mod(),
+ m_value(value % mod->m_p),
+ m_use_montgm(use_montgm),
+ m_is_trf(false)
+ {
+ assert(mp_mod.get() == 0);
+ mp_mod = mod;
+ }
+
+GFpElement::GFpElement(const GFpElement& other)
+ : m_value(other.m_value),
+ m_use_montgm(other.m_use_montgm),
+ m_is_trf(other.m_is_trf)
+
+ {
+ //creates an independent copy
+ assert((other.m_is_trf && other.m_use_montgm) || !other.m_is_trf);
+ mp_mod.reset(new GFpModulus(*other.mp_mod)); // copy-ctor of GFpModulus
+ }
+
+void GFpElement::turn_on_sp_red_mul() const
+ {
+ ensure_montgm_precomp();
+ m_use_montgm = true;
+ }
+
+void GFpElement::turn_off_sp_red_mul() const
+ {
+ if(m_is_trf)
+ {
+ trf_to_ordres();
+ // will happen soon anyway, so we can do it here already
+ // (this is not lazy but way more secure concerning our internal logic here)
+ }
+ m_use_montgm = false;
+ }
+
+void GFpElement::ensure_montgm_precomp() const
+ {
+ if((!mp_mod->m_r.is_zero()) && (!mp_mod->m_r_inv.is_zero()) && (!mp_mod->m_p_dash.is_zero()))
+ {
+ // values are already set, nothing more to do
+ }
+ else
+ {
+ BigInt tmp_r(montgm_calc_r_oddmod(mp_mod->m_p));
+
+ BigInt tmp_r_inv(inverse_mod(tmp_r, mp_mod->m_p));
+
+ BigInt tmp_p_dash(montgm_calc_m_dash(tmp_r, mp_mod->m_p, tmp_r_inv));
+
+ mp_mod->m_r.grow_reg(tmp_r.size());
+ mp_mod->m_r_inv.grow_reg(tmp_r_inv.size());
+ mp_mod->m_p_dash.grow_reg(tmp_p_dash.size());
+
+ mp_mod->m_r = tmp_r;
+ mp_mod->m_r_inv = tmp_r_inv;
+ mp_mod->m_p_dash = tmp_p_dash;
+
+ assert(!mp_mod->m_r.is_zero());
+ assert(!mp_mod->m_r_inv.is_zero());
+ assert(!mp_mod->m_p_dash.is_zero());
+ }
+
+ }
+
+void GFpElement::set_shrd_mod(std::tr1::shared_ptr<GFpModulus> const p_mod)
+ {
+ mp_mod = p_mod;
+ }
+
+void GFpElement::trf_to_mres() const
+ {
+ if(!m_use_montgm)
+ {
+ throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
+ }
+ assert(m_is_trf == false);
+ assert(!mp_mod->m_r_inv.is_zero());
+ assert(!mp_mod->m_p_dash.is_zero());
+ m_value = montg_trf_to_mres(m_value, mp_mod->m_r, mp_mod->m_p);
+ m_is_trf = true;
+ }
+
+void GFpElement::trf_to_ordres() const
+ {
+ assert(m_is_trf == true);
+ m_value = montg_trf_to_ordres(m_value, mp_mod->m_p, mp_mod->m_r_inv);
+ m_is_trf = false;
+ }
+
+bool GFpElement::align_operands_res(const GFpElement& lhs, const GFpElement& rhs) //static
+ {
+ assert(lhs.mp_mod->m_p == rhs.mp_mod->m_p);
+ if(lhs.m_use_montgm && rhs.m_use_montgm)
+ {
+ assert(rhs.mp_mod->m_p_dash == lhs.mp_mod->m_p_dash);
+ assert(rhs.mp_mod->m_r == lhs.mp_mod->m_r);
+ assert(rhs.mp_mod->m_r_inv == lhs.mp_mod->m_r_inv);
+ if(!lhs.m_is_trf && !rhs.m_is_trf)
+ {
+ return false;
+ }
+ else if(lhs.m_is_trf && rhs.m_is_trf)
+ {
+ return true;
+ }
+ else // one is transf., the other not
+ {
+ if(!lhs.m_is_trf)
+ {
+ lhs.trf_to_mres();
+ assert(rhs.m_is_trf==true);
+ return true;
+ }
+ assert(rhs.m_is_trf==false);
+ assert(lhs.m_is_trf==true);
+ rhs.trf_to_mres(); // the only possibility left...
+ return true;
+ }
+ }
+ else // at least one of them does not use mm
+ // (so it is impossible that both use it)
+ {
+ if(lhs.m_is_trf)
+ {
+ lhs.trf_to_ordres();
+ assert(rhs.m_is_trf == false);
+ return false;
+ }
+ if(rhs.m_is_trf)
+ {
+ rhs.trf_to_ordres();
+ assert(lhs.m_is_trf == false);
+ return false;
+ }
+ return false;
+ }
+ assert(false);
+ }
+
+bool GFpElement::is_trf_to_mres() const
+ {
+ return m_is_trf;
+ }
+
+const BigInt& GFpElement::get_p() const
+ {
+ return (mp_mod->m_p);
+ }
+
+const BigInt& GFpElement::get_value() const
+ {
+ if(m_is_trf)
+ {
+ assert(m_use_montgm);
+ trf_to_ordres();
+ }
+ return m_value;
+ }
+
+const BigInt& GFpElement::get_mres() const
+ {
+ if(!m_use_montgm)
+ {
+ // does the following exception really make sense?
+ // wouldn´t it be better to simply turn on montg.mult. when
+ // this explicit request is made?
+ throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
+ }
+ if(!m_is_trf)
+ {
+ trf_to_mres();
+ }
+
+ return m_value;
+ }
+
+const GFpElement& GFpElement::operator=(const GFpElement& other)
+ {
+ m_value.grow_reg(other.m_value.size()); // grow first for exception safety
+
+ //m_value = other.m_value;
+
+ // m_use_montgm = other.m_use_montgm;
+ // m_is_trf = other.m_is_trf;
+ // we want to keep the member pointers, which might be part of a "sharing group"
+ // but we may not simply overwrite the BigInt values with those of the argument!!
+ // if ours already contains precomputations, it would be hazardous to
+ // set them back to zero.
+ // thus we first check for equality of the moduli,
+ // then whether either of the two objects already contains
+ // precomputed values.
+
+ // we also deal with the case were the pointers themsevles are equal:
+ if(mp_mod.get() == other.mp_mod.get())
+ {
+ // everything ok, we are in the same sharing group anyway, nothing to do
+ m_value = other.m_value; // cannot throw
+ m_use_montgm = other.m_use_montgm;
+ m_is_trf = other.m_is_trf;
+ return *this;
+ }
+ if(mp_mod->m_p != other.mp_mod->m_p)
+ {
+ // the moduli are different, this is a special case
+ // which will not occur in usual applications,
+ // so we don´t hesitate to simply create new objects
+ // (we do want to create an independent copy)
+ mp_mod.reset(new GFpModulus(*other.mp_mod)); // this could throw,
+ // and because of this
+ // we haven't modified
+ // anything so far
+ m_value = other.m_value; // can't throw
+ m_use_montgm = other.m_use_montgm;
+ m_is_trf = other.m_is_trf;
+ return *this;
+ }
+ // exception safety note: from now on we are on the safe
+ // side with respect to the modulus,
+ // so we can assign the value now:
+ m_value = other.m_value;
+ m_use_montgm = other.m_use_montgm;
+ m_is_trf = other.m_is_trf;
+ // the moduli are equal, but we deal with different sharing groups.
+ // we will NOT fuse the sharing goups
+ // and we will NOT reset already precomputed values
+ if(mp_mod->has_precomputations())
+ {
+ // our own sharing group already has precomputed values,
+ // so nothing to do.
+ return *this;
+ }
+ else
+ {
+ // let´s see whether the argument has something for us...
+ if(other.mp_mod->has_precomputations())
+ {
+ // fetch them for our sharing group
+ // exc. safety note: grow first
+ mp_mod->m_p_dash.grow_reg(other.mp_mod->m_p_dash.size());
+ mp_mod->m_r.grow_reg(other.mp_mod->m_r.size());
+ mp_mod->m_r_inv.grow_reg(other.mp_mod->m_r_inv.size());
+
+ mp_mod->m_p_dash = other.mp_mod->m_p_dash;
+ mp_mod->m_r = other.mp_mod->m_r;
+ mp_mod->m_r_inv = other.mp_mod->m_r_inv;
+ return *this;
+ }
+ }
+ // our precomputations aren´t set, the arguments neither,
+ // so we let them alone
+ return *this;
+ }
+
+void GFpElement::share_assign(const GFpElement& other)
+ {
+ assert((other.m_is_trf && other.m_use_montgm) || !other.m_is_trf);
+
+ // use grow_to to make it exc safe
+ m_value.grow_reg(other.m_value.size());
+ m_value = other.m_value;
+
+ m_use_montgm = other.m_use_montgm;
+ m_is_trf = other.m_is_trf;
+ mp_mod = other.mp_mod; // cannot throw
+ }
+
+GFpElement& GFpElement::operator+=(const GFpElement& rhs)
+ {
+ GFpElement::align_operands_res(*this, rhs);
+
+ workspace = m_value;
+ workspace += rhs.m_value;
+ if(workspace >= mp_mod->m_p)
+ workspace -= mp_mod->m_p;
+
+ m_value = workspace;
+ assert(m_value < mp_mod->m_p);
+ assert(m_value >= 0);
+
+ return *this;
+ }
+
+GFpElement& GFpElement::operator-=(const GFpElement& rhs)
+ {
+ GFpElement::align_operands_res(*this, rhs);
+
+ workspace = m_value;
+
+ workspace -= rhs.m_value;
+
+ if(workspace.is_negative())
+ workspace += mp_mod->m_p;
+
+ m_value = workspace;
+ assert(m_value < mp_mod->m_p);
+ assert(m_value >= 0);
+ return *this;
+ }
+
+GFpElement& GFpElement::operator*= (u32bit rhs)
+ {
+ workspace = m_value;
+ workspace *= rhs;
+ workspace %= mp_mod->m_p;
+ m_value = workspace;
+ return *this;
+ }
+
+GFpElement& GFpElement::operator*=(const GFpElement& rhs)
+ {
+ assert(rhs.mp_mod->m_p == mp_mod->m_p);
+ // here, we do not use align_operands_res() for one simple reason:
+ // we want to enforce the transformation to an m-residue, otherwise it would
+ // never happen
+ if(m_use_montgm && rhs.m_use_montgm)
+ {
+ assert(rhs.mp_mod->m_p == mp_mod->m_p); // is montgm. mult is on, then precomps must be there
+ assert(rhs.mp_mod->m_p_dash == mp_mod->m_p_dash);
+ assert(rhs.mp_mod->m_r == mp_mod->m_r);
+ if(!m_is_trf)
+ {
+ trf_to_mres();
+ }
+ if(!rhs.m_is_trf)
+ {
+ rhs.trf_to_mres();
+ }
+ workspace = m_value;
+ montg_mult(m_value, workspace, rhs.m_value, mp_mod->m_p, mp_mod->m_p_dash, mp_mod->m_r);
+ }
+ else // ordinary multiplication
+ {
+ if(m_is_trf)
+ {
+ assert(m_use_montgm);
+ trf_to_ordres();
+ }
+ if(rhs.m_is_trf)
+ {
+ assert(rhs.m_use_montgm);
+ rhs.trf_to_ordres();
+ }
+
+ workspace = m_value;
+ workspace *= rhs.m_value;
+ workspace %= mp_mod->m_p;
+ m_value = workspace;
+ }
+ return *this;
+ }
+
+GFpElement& GFpElement::operator/=(const GFpElement& rhs)
+ {
+ bool use_mres = GFpElement::align_operands_res(*this, rhs);
+ assert((this->m_is_trf && rhs.m_is_trf) || !(this->m_is_trf && rhs.m_is_trf));
+ // (internal note: see C86)
+ if(use_mres)
+ {
+ assert(m_use_montgm && rhs.m_use_montgm);
+ GFpElement rhs_ordres(rhs);
+ rhs_ordres.trf_to_ordres();
+ rhs_ordres.inverse_in_place();
+ workspace = m_value;
+ workspace *= rhs_ordres.get_value();
+ workspace %= mp_mod->m_p;
+ m_value = workspace;
+
+ }
+ else
+ {
+ GFpElement inv_rhs(rhs);
+ inv_rhs.inverse_in_place();
+ *this *= inv_rhs;
+ }
+ return *this;
+ }
+
+bool GFpElement::is_zero()
+ {
+ return (m_value.is_zero());
+ // this is correct because x_bar = x * r = x = 0 for x = 0
+ }
+
+GFpElement& GFpElement::inverse_in_place()
+ {
+ m_value = inverse_mod(m_value, mp_mod->m_p);
+ if(m_is_trf)
+ {
+ assert(m_use_montgm);
+
+ m_value *= mp_mod->m_r;
+ m_value *= mp_mod->m_r;
+ m_value %= mp_mod->m_p;
+ }
+ assert(m_value <= mp_mod->m_p);
+ return *this;
+ }
+
+GFpElement& GFpElement::negate()
+ {
+ m_value = mp_mod->m_p - m_value;
+ assert(m_value <= mp_mod->m_p);
+ return *this;
+ }
+
+void GFpElement::swap(GFpElement& other)
+ {
+ m_value.swap(other.m_value);
+ mp_mod.swap(other.mp_mod);
+ std::swap<bool>(m_use_montgm,other.m_use_montgm);
+ std::swap<bool>(m_is_trf,other.m_is_trf);
+ }
+
+std::ostream& operator<<(std::ostream& output, const GFpElement& elem)
+ {
+ return output << '(' << elem.get_value() << "," << elem.get_p() << ')';
+ }
+
+bool operator==(const GFpElement& lhs, const GFpElement& rhs)
+ {
+ // for effeciency reasons we firstly check whether
+ //the modulus pointers are different in the first place:
+ if(lhs.get_ptr_mod() != rhs.get_ptr_mod())
+ {
+ if(lhs.get_p() != rhs.get_p())
+ {
+ return false;
+ }
+ }
+ // so the modulus is equal, now check the values
+ bool use_mres = GFpElement::align_operands_res(lhs, rhs);
+
+ if(use_mres)
+ {
+ return (lhs.get_mres() == rhs.get_mres());
+ }
+ else
+ {
+ return(lhs.get_value() == rhs.get_value());
+ }
+ }
+
+GFpElement operator+(const GFpElement& lhs, const GFpElement& rhs)
+ {
+ // consider the case that lhs and rhs both use montgm:
+ // then += returns an element which uses montgm.
+ // thus the return value of op+ here will be an element
+ // using montgm in this case
+ // NOTE: the rhs might be transformed when using op+, the lhs never
+ GFpElement result(lhs);
+ result += rhs;
+ return result;
+ }
+
+GFpElement operator-(const GFpElement& lhs, const GFpElement& rhs)
+ {
+ GFpElement result(lhs);
+ result -= rhs;
+ return result;
+ // NOTE: the rhs might be transformed when using op-, the lhs never
+ }
+
+GFpElement operator-(const GFpElement& lhs)
+ {
+ return(GFpElement(lhs)).negate();
+ }
+
+GFpElement operator*(const GFpElement& lhs, const GFpElement& rhs)
+ {
+ // consider the case that lhs and rhs both use montgm:
+ // then *= returns an element which uses montgm.
+ // thus the return value of op* here will be an element
+ // using montgm in this case
+ GFpElement result(lhs);
+ result *= rhs;
+ return result;
+ }
+
+GFpElement operator*(const GFpElement& lhs, u32bit rhs)
+ {
+ GFpElement result(lhs);
+ result *= rhs;
+ return result;
+ }
+
+GFpElement operator*(u32bit lhs, const GFpElement& rhs)
+ {
+ return rhs*lhs;
+ }
+
+GFpElement operator/(const GFpElement& lhs, const GFpElement& rhs)
+ {
+ GFpElement result (lhs);
+ result /= rhs;
+ return result;
+ }
+
+SecureVector<byte> FE2OSP(const GFpElement& elem)
+ {
+ return BigInt::encode_1363(elem.get_value(), elem.get_p().bytes());
+ }
+
+GFpElement OS2FEP(MemoryRegion<byte> const& os, BigInt p)
+ {
+ return GFpElement(p, BigInt::decode(os.begin(), os.size()));
+ }
+
+GFpElement inverse(const GFpElement& elem)
+ {
+ return GFpElement(elem).inverse_in_place();
+ }
+
+}
+
diff --git a/botan/src/math/gfpmath/gfp_element.h b/botan/src/math/gfpmath/gfp_element.h
new file mode 100644
index 0000000..4e0ee98
--- /dev/null
+++ b/botan/src/math/gfpmath/gfp_element.h
@@ -0,0 +1,311 @@
+/******
+ * Arithmetic for prime fields GF(p) (header file)
+ *
+ * (C) 2007 Martin Doering
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_ELEMENT_H__
+#define BOTAN_GFP_ELEMENT_H__
+
+#include <botan/bigint.h>
+#include <botan/gfp_modulus.h>
+#include <iosfwd>
+
+#if defined(BOTAN_USE_STD_TR1)
+ #include <tr1/memory>
+#elif defined(BOTAN_USE_BOOST_TR1)
+ #include <boost/tr1/memory.hpp>
+#else
+ #error "Please choose a TR1 implementation in build.h"
+#endif
+
+namespace Botan {
+
+struct Illegal_Transformation : public Exception
+ {
+ Illegal_Transformation(const std::string& err =
+ "Requested transformation is not possible")
+ : Exception(err) {}
+ };
+
+/**
+ * This class represents one element in GF(p). Enables the convenient,
+ * transparent use of the montgomery multiplication.
+ */
+class BOTAN_DLL GFpElement
+ {
+ private:
+ std::tr1::shared_ptr<GFpModulus> mp_mod;
+ mutable BigInt m_value; // ordinary residue or m-residue respectively
+ mutable BigInt workspace;
+
+ // *****************************************
+ // data members for montgomery multiplication
+ mutable bool m_use_montgm;
+ //mutable BigInt m_mres;
+ // this bool tells use whether the m_mres carries
+ // the actual value (in this case mValue doesn´t)
+ mutable bool m_is_trf;
+
+ void ensure_montgm_precomp() const;
+ void trf_to_mres() const;
+ void trf_to_ordres() const;
+
+ public:
+
+ /** construct an element of GF(p) with the given value.
+ * use_montg defaults to false and determines wether Montgomery
+ * multiplications will be use when applying operators *, *=
+ * @param p the prime number of the field
+ * @param value the element value
+ * @param use_montgm whether this object will use Montgomery multiplication
+ */
+ explicit GFpElement (const BigInt& p, const BigInt& value, bool use_montgm = false);
+
+
+ /** construct an element of GF(p) with the given value (defaults
+ * to 0). use_montg defaults to false and determines wether
+ * montgomery multiplications will be use when applying operators
+ * '*' , '*='. Use this constructor for efficient use of
+ * Montgomery multiplication in a context with a fixed a modulus.
+ * Warning: do not use this function unless you know in detail
+ * about the implications of using the shared GFpModulus objects!
+ * @param mod shared pointer to the GFpModulus to be shared
+ * @param value the element value
+ * @param use_montgm whether this object will use Montgomery multiplication
+ */
+ explicit GFpElement(std::tr1::shared_ptr<GFpModulus> const mod,
+ const BigInt& value, bool use_mongm = false);
+
+ /**
+ * Copy constructor
+ * @param other The element to clone
+ */
+ GFpElement(const GFpElement& other);
+
+ /**
+ * Assignment operator.
+ * makes *this a totally independent object
+ * (gives *this independent modulus specific values).
+
+ * @param other The element to assign to our object
+ */
+ const GFpElement& operator=(const GFpElement& other);
+
+ /**
+ * Works like the assignment operator, but lets
+ * *this share the modulus dependend value with other.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @param other The element to assign to our object
+ */
+ void share_assign(const GFpElement& other);
+
+ /**
+ * Switch Montgomery multiplcation optimizations ON
+ */
+ void turn_on_sp_red_mul() const;
+
+ /**
+ * Switch Montgomery multiplcation optimizations OFF
+ */
+ void turn_off_sp_red_mul() const;
+
+ /**
+ * += Operator
+ * @param rhs the GFpElement to add to the local value
+ * @result *this
+ */
+ GFpElement& operator+=(const GFpElement& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the GFpElement to subtract from the local value
+ * @result *this
+ */
+ GFpElement& operator-=(const GFpElement& rhs);
+
+ /**
+ * *= Operator
+ * @param rhs the GFpElement to multiply with the local value
+ * @result *this
+ */
+ GFpElement& operator*=(const GFpElement& rhs);
+ /**
+ * /= Operator
+ * @param rhs the GFpElement to divide the local value by
+ * @result *this
+ */
+ GFpElement& operator/=(const GFpElement& rhs);
+
+ /**
+ * *= Operator
+ * @param rhs the value to multiply with the local value
+ * @result *this
+ */
+ GFpElement& operator*= (u32bit rhs);
+
+ /**
+ * Negate internal value(*this *= -1 )
+ * @return *this
+ */
+ GFpElement& negate();
+
+ /**
+ * Assigns the inverse of *this to *this, i.e.
+ * *this = (*this)^(-1)
+ * @result *this
+ */
+ GFpElement& inverse_in_place();
+
+ /**
+ * checks whether the value is zero (without provoking
+ * a backtransformation to the ordinary-residue)
+ * @result true, if the value is zero, false otherwise.
+ */
+ bool is_zero();
+
+ /**
+ * return prime number of GF(p)
+ * @result a prime number
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Return the represented value in GF(p)
+ * @result The value in GF(p)
+ */
+ const BigInt& get_value() const;
+
+ /**
+ * Returns the shared pointer to the GFpModulus of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @result the shared pointer to the GFpModulus of *this
+ */
+ inline std::tr1::shared_ptr<GFpModulus> const get_ptr_mod() const
+ {
+ return mp_mod;
+ }
+
+
+ /**
+ * Sets the shared pointer to the GFpModulus of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * @param mod a shared pointer to a GFpModulus that will be held in *this
+ */
+ void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> const mod);
+
+ /**
+ * Tells whether this GFpElement is currently transformed to it´ m-residue,
+ * i.e. in the form x_bar = x * r mod m.
+ * @result true if it is currently transformed to it´s m-residue.
+ */
+ bool is_trf_to_mres() const;
+
+ /**
+ * Transforms this to x_bar = x * r mod m
+ * @result return the value x_bar.
+ */
+ const BigInt& get_mres() const;
+
+ /**
+ * Check, if montgomery multiplication is used.
+ * @result true, if montgomery multiplication is used, false otherwise
+ */
+ bool is_use_montgm() const
+ {
+ return m_use_montgm;
+ }
+
+ /**
+ * Transforms the arguments in such way that either both
+ * are in m-residue representation (returns true) or both are
+ * in ordinary residue representation (returns false).
+ * m-residue is prefered in case of ambiguity.
+ * does not toggle m_use_montgm of the arguments.
+ * Don´t be confused about the constness of the arguments:
+ * the transformation between normal residue and m-residue is
+ * considered as leaving the object const.
+ * @param lhs the first operand to be aligned
+ * @param rhs the second operand to be aligned
+ * @result true if both are transformed to their m-residue,
+ * false it both are transformed to their normal residue.
+ */
+ static bool align_operands_res(const GFpElement& lhs, const GFpElement& rhs);
+
+ //friend declarations for non-member functions
+
+ /**
+ * write a GFpElement to an output stream.
+ * @param output the output stream to write to
+ * @param elem the object to write
+ * @result the output stream
+ */
+ friend std::ostream& operator<<(std::ostream& output, const GFpElement& elem);
+
+ friend class Point_Coords_GFp;
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other The value to swap with
+ */
+ void swap(GFpElement& other);
+
+ };
+
+// relational operators
+bool operator==(const GFpElement& lhs, const GFpElement& rhs);
+inline bool operator!=(const GFpElement& lhs, const GFpElement& rhs )
+ {
+ return !operator==(lhs, rhs);
+ }
+
+// arithmetic operators
+GFpElement operator+(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator-(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator-(const GFpElement& lhs);
+
+GFpElement operator*(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator/(const GFpElement& lhs, const GFpElement& rhs);
+GFpElement operator* (const GFpElement& lhs, u32bit rhs);
+GFpElement operator* (u32bit rhs, const GFpElement& lhs);
+
+// io operators
+std::ostream& operator<<(std::ostream& output, const GFpElement& elem);
+
+// return (*this)^(-1)
+GFpElement inverse(const GFpElement& elem);
+
+// encoding and decoding
+SecureVector<byte> FE2OSP(const GFpElement& elem);
+GFpElement OS2FEP(MemoryRegion<byte> const& os, BigInt p);
+
+inline void swap(GFpElement& x, GFpElement& y)
+ {
+ x.swap(y);
+ }
+
+}
+
+namespace std {
+
+template<> inline
+void swap<Botan::GFpElement>(Botan::GFpElement& x,
+ Botan::GFpElement& y)
+ {
+ x.swap(y);
+ }
+
+}
+
+#endif
diff --git a/botan/src/math/gfpmath/gfp_modulus.h b/botan/src/math/gfpmath/gfp_modulus.h
new file mode 100644
index 0000000..b5c0857
--- /dev/null
+++ b/botan/src/math/gfpmath/gfp_modulus.h
@@ -0,0 +1,127 @@
+/******
+ * Modulus and related data for a specific
+ * implementation of GF(p) (header file)
+ *
+ * (C) 2008 Martin Döring
+ * doering@cdc.informatik.tu-darmstadt.de
+ * Christoph Ludwig
+ * ludwig@fh-worms.de
+ * Falko Strenzke
+ * strenzke@flexsecure.de
+ ******/
+
+#ifndef BOTAN_GFP_MODULUS_H__
+#define BOTAN_GFP_MODULUS_H__
+
+#include <botan/bigint.h>
+
+namespace Botan
+{
+
+class BOTAN_DLL GFpElement;
+/**
+* This class represents a GFpElement modulus including the modulus related
+* values necessary for the montgomery multiplication.
+*
+* Distributed under the terms of the Botan license
+*/
+class BOTAN_DLL GFpModulus
+ {
+ friend class GFpElement;
+ private:
+ BigInt m_p; // the modulus itself
+ mutable BigInt m_p_dash;
+ mutable BigInt m_r;
+ mutable BigInt m_r_inv;
+ public:
+
+ /**
+ * Construct a GF(P)-Modulus from a BigInt
+ */
+ GFpModulus(BigInt p)
+ : m_p(p),
+ m_p_dash(),
+ m_r(),
+ m_r_inv()
+ {}
+
+ /**
+ * Tells whether the precomputations necessary for the use of the
+ * montgomery multiplication have yet been established.
+ * @result true if the precomputated value are already available.
+ */
+ inline bool has_precomputations() const
+ {
+ return(!m_p_dash.is_zero() && !m_r.is_zero() && !m_r_inv.is_zero());
+ }
+
+ /**
+ * Swaps this with another GFpModulus, does not throw.
+ * @param other the GFpModulus to swap *this with.
+ */
+ inline void swap(GFpModulus& other)
+ {
+ m_p.swap(other.m_p);
+ m_p_dash.swap(other.m_p_dash);
+ m_r.swap(other.m_r);
+ m_r_inv.swap(other.m_r_inv);
+ }
+
+ /**
+ * Tells whether the modulus of *this is equal to the argument.
+ * @param mod the modulus to compare this with
+ * @result true if the modulus of *this and the argument are equal.
+ */
+ inline bool p_equal_to(const BigInt& mod) const
+ {
+ return (m_p == mod);
+ }
+
+ /**
+ * Return the modulus of this GFpModulus.
+ * @result the modulus of *this.
+ */
+ inline const BigInt& get_p() const
+ {
+ return m_p;
+ }
+
+ /**
+ * returns the montgomery multiplication related value r.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result r
+ */
+ inline const BigInt& get_r() const
+ {
+ return m_r;
+ }
+
+ /**
+ * returns the montgomery multiplication related value r^{-1}.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result r^{-1}
+ */
+ inline const BigInt& get_r_inv() const
+ {
+ return m_r_inv;
+ }
+
+ /**
+ * returns the montgomery multiplication related value p'.
+ * Warning: will be zero if precomputations have not yet been
+ * performed!
+ * @result p'
+ */
+ inline const BigInt& get_p_dash() const
+ {
+ return m_p_dash;
+ }
+ // default cp-ctor, op= are fine
+ };
+
+}
+
+#endif
+
diff --git a/botan/src/math/gfpmath/info.txt b/botan/src/math/gfpmath/info.txt
new file mode 100644
index 0000000..1a52144
--- /dev/null
+++ b/botan/src/math/gfpmath/info.txt
@@ -0,0 +1,22 @@
+realname "GF(p) Math"
+
+uses_tr1 yes
+
+load_on auto
+
+define BIGINT_GFP
+
+<add>
+curve_gfp.cpp
+curve_gfp.h
+gfp_element.cpp
+gfp_element.h
+gfp_modulus.h
+point_gfp.cpp
+point_gfp.h
+</add>
+
+<requires>
+bigint
+numbertheory
+</requires>
diff --git a/botan/src/math/gfpmath/point_gfp.cpp b/botan/src/math/gfpmath/point_gfp.cpp
new file mode 100644
index 0000000..9139c3e
--- /dev/null
+++ b/botan/src/math/gfpmath/point_gfp.cpp
@@ -0,0 +1,1154 @@
+/******
+* Arithmetic for point groups of elliptic curves
+* over GF(p) (source file)
+*
+* (C) 2007 Martin Doering
+* Christoph Ludwig
+* Falko Strenzke
+* 2008 Jack Lloyd
+******/
+
+#include <botan/point_gfp.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+// construct the point at infinity or a random point
+PointGFp::PointGFp(const CurveGFp& curve)
+ : mC(curve),
+ mX(curve.get_p(), 0),
+ mY(curve.get_p(), 1),
+ mZ(curve.get_p(), 0),
+ mZpow2(curve.get_p(),0),
+ mZpow3(curve.get_p(),0),
+ mAZpow4(curve.get_p(),0),
+ mZpow2_set(false),
+ mZpow3_set(false),
+ mAZpow4_set(false)
+ {
+ // first set the point wide pointer
+
+ set_shrd_mod(mC.get_ptr_mod());
+
+ }
+
+// construct a point given its jacobian projective coordinates
+PointGFp::PointGFp(const CurveGFp& curve, const GFpElement& x,
+ const GFpElement& y, const GFpElement& z)
+ : mC(curve),
+ mX(x),
+ mY(y),
+ mZ(z),
+ mZpow2(curve.get_p(),0),
+ mZpow3(curve.get_p(),0),
+ mAZpow4(curve.get_p(),0),
+ mZpow2_set(false),
+ mZpow3_set(false),
+ mAZpow4_set(false)
+ {
+ set_shrd_mod(mC.get_ptr_mod());
+ }
+PointGFp::PointGFp ( const CurveGFp& curve, const GFpElement& x,
+ const GFpElement& y )
+ :mC(curve),
+ mX(x),
+ mY(y),
+ mZ(curve.get_p(),1),
+ mZpow2(curve.get_p(),0),
+ mZpow3(curve.get_p(),0),
+ mAZpow4(curve.get_p(),0),
+ mZpow2_set(false),
+ mZpow3_set(false),
+ mAZpow4_set(false)
+ {
+ set_shrd_mod(mC.get_ptr_mod());
+ }
+
+// copy constructor
+PointGFp::PointGFp(const PointGFp& other)
+ : mC(other.mC),
+ mX(other.mX),
+ mY(other.mY),
+ mZ(other.mZ),
+ mZpow2(other.mZpow2),
+ mZpow3(other.mZpow3),
+ mAZpow4(other.mAZpow4),
+ mZpow2_set(other.mZpow2_set),
+ mZpow3_set(other.mZpow3_set),
+ mAZpow4_set(other.mAZpow4_set)
+ {
+ set_shrd_mod(mC.get_ptr_mod());
+ }
+
+// assignment operator
+const PointGFp& PointGFp::operator=(PointGFp const& other)
+ {
+ mC = other.get_curve();
+ mX = other.get_jac_proj_x();
+ mY = other.get_jac_proj_y();
+ mZ = other.get_jac_proj_z();
+ mZpow2 = GFpElement(other.mZpow2);
+ mZpow3 = GFpElement(other.mZpow3);
+ mAZpow4 = GFpElement(other.mAZpow4);
+ mZpow2_set = other.mZpow2_set;
+ mZpow3_set = other.mZpow3_set;
+ mAZpow4_set = other.mAZpow4_set;
+ set_shrd_mod(mC.get_ptr_mod());
+ return *this;
+ }
+
+const PointGFp& PointGFp::assign_within_same_curve(PointGFp const& other)
+ {
+ mX = other.get_jac_proj_x();
+ mY = other.get_jac_proj_y();
+ mZ = other.get_jac_proj_z();
+ mZpow2_set = false;
+ mZpow3_set = false;
+ mAZpow4_set = false;
+ // the rest stays!
+ return *this;
+ }
+
+void PointGFp::set_shrd_mod(std::tr1::shared_ptr<GFpModulus> p_mod)
+ {
+ mX.set_shrd_mod(p_mod);
+ mY.set_shrd_mod(p_mod);
+ mZ.set_shrd_mod(p_mod);
+ mZpow2.set_shrd_mod(p_mod);
+ mZpow3.set_shrd_mod(p_mod);
+ mAZpow4.set_shrd_mod(p_mod);
+ }
+
+void PointGFp::ensure_worksp() const
+ {
+ if (mp_worksp_gfp_el.get() != 0)
+ {
+ if ((*mp_worksp_gfp_el).size() == GFPEL_WKSP_SIZE)
+ {
+ return;
+ }
+ else
+ {
+ throw Invalid_State("encountered incorrect size for PointGFp´s GFpElement workspace");
+ }
+ }
+
+ mp_worksp_gfp_el = std::tr1::shared_ptr<std::vector<GFpElement> >(new std::vector<GFpElement>);
+ mp_worksp_gfp_el->reserve(9);
+ for (u32bit i=0; i<GFPEL_WKSP_SIZE; i++)
+ {
+ mp_worksp_gfp_el->push_back(GFpElement(1,0));
+
+ }
+ }
+
+// arithmetic operators
+PointGFp& PointGFp::operator+=(const PointGFp& rhs)
+ {
+ if (is_zero())
+ {
+ *this = rhs;
+ return *this;
+ }
+ if (rhs.is_zero())
+ {
+ return *this;
+ }
+ ensure_worksp();
+
+ if (rhs.mZ == *(mC.get_mres_one()))
+ {
+ //U1 = mX;
+ (*mp_worksp_gfp_el)[0].share_assign(mX);
+
+ //S1 = mY;
+ (*mp_worksp_gfp_el)[2].share_assign(mY);
+ }
+ else
+ {
+ if ((!rhs.mZpow2_set) || (!rhs.mZpow3_set))
+ {
+ rhs.mZpow2 = rhs.mZ;
+ rhs.mZpow2 *= rhs.mZ;
+ rhs.mZpow3 = rhs.mZpow2;
+ rhs.mZpow3 *= rhs.mZ;
+
+ rhs.mZpow2_set = true;
+ rhs.mZpow3_set = true;
+ }
+ //U1 = mX * rhs.mZpow2;
+ (*mp_worksp_gfp_el)[0].share_assign(mX);
+ (*mp_worksp_gfp_el)[0] *= rhs.mZpow2;
+
+ //S1 = mY * rhs.mZpow3;
+ (*mp_worksp_gfp_el)[2].share_assign(mY);
+ (*mp_worksp_gfp_el)[2] *= rhs.mZpow3;
+
+ }
+ if (mZ == *(mC.get_mres_one()))
+ {
+ //U2 = rhs.mX;
+ (*mp_worksp_gfp_el)[1].share_assign(rhs.mX);
+
+ //S2 = rhs.mY;
+ (*mp_worksp_gfp_el)[3].share_assign(rhs.mY);
+ }
+ else
+ {
+ if ((!mZpow2_set) || (!mZpow3_set))
+ {
+ // precomputation can´t be used, because *this changes anyway
+ mZpow2 = mZ;
+ mZpow2 *= mZ;
+
+ mZpow3 = mZpow2;
+ mZpow3 *= mZ;
+ }
+ //U2 = rhs.mX * mZpow2;
+ (*mp_worksp_gfp_el)[1].share_assign(rhs.mX);
+ (*mp_worksp_gfp_el)[1] *= mZpow2;
+
+ //S2 = rhs.mY * mZpow3;
+ (*mp_worksp_gfp_el)[3].share_assign(rhs.mY);
+ (*mp_worksp_gfp_el)[3] *= mZpow3;
+
+ }
+ //GFpElement H(U2 - U1);
+
+ (*mp_worksp_gfp_el)[4].share_assign((*mp_worksp_gfp_el)[1]);
+ (*mp_worksp_gfp_el)[4] -= (*mp_worksp_gfp_el)[0];
+
+ //GFpElement r(S2 - S1);
+ (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[3]);
+ (*mp_worksp_gfp_el)[5] -= (*mp_worksp_gfp_el)[2];
+
+ //if(H.is_zero())
+ if ((*mp_worksp_gfp_el)[4].is_zero())
+
+ {
+ if ((*mp_worksp_gfp_el)[5].is_zero())
+
+ {
+ mult2_in_place();
+ return *this;
+ }
+ *this = PointGFp(mC); // setting myself to zero
+ return *this;
+ }
+
+ //U2 = H * H;
+ (*mp_worksp_gfp_el)[1].share_assign((*mp_worksp_gfp_el)[4]);
+ (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[4];
+
+ //S2 = U2 * H;
+ (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[1]);
+ (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[4];
+
+ //U2 *= U1;
+ (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[0];
+
+ //GFpElement x(r*r - S2 - (U2+U2));
+ (*mp_worksp_gfp_el)[6].share_assign((*mp_worksp_gfp_el)[5]);
+ (*mp_worksp_gfp_el)[6] *= (*mp_worksp_gfp_el)[5];
+ (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[3];
+ (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[1];
+ (*mp_worksp_gfp_el)[6] -= (*mp_worksp_gfp_el)[1];
+
+ //GFpElement z(S1 * S2);
+ (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[2]);
+ (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[3];
+
+ //GFpElement y(r * (U2-x) - z);
+ (*mp_worksp_gfp_el)[7].share_assign((*mp_worksp_gfp_el)[1]);
+ (*mp_worksp_gfp_el)[7] -= (*mp_worksp_gfp_el)[6];
+ (*mp_worksp_gfp_el)[7] *= (*mp_worksp_gfp_el)[5];
+ (*mp_worksp_gfp_el)[7] -= (*mp_worksp_gfp_el)[8];
+
+ if (mZ == *(mC.get_mres_one()))
+ {
+ if (rhs.mZ != *(mC.get_mres_one()))
+ {
+ //z = rhs.mZ * H;
+ (*mp_worksp_gfp_el)[8].share_assign(rhs.mZ);
+ (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
+ }
+ else
+ {
+ //z = H;
+ (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[4]);
+ }
+ }
+ else if (rhs.mZ != *(mC.get_mres_one()))
+ {
+ //U1 = mZ * rhs.mZ;
+ (*mp_worksp_gfp_el)[0].share_assign(mZ);
+ (*mp_worksp_gfp_el)[0] *= rhs.mZ;
+
+ //z = U1 * H;
+ (*mp_worksp_gfp_el)[8].share_assign((*mp_worksp_gfp_el)[0]);
+ (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
+
+ }
+ else
+ {
+ //z = mZ * H;
+ (*mp_worksp_gfp_el)[8].share_assign(mZ);
+ (*mp_worksp_gfp_el)[8] *= (*mp_worksp_gfp_el)[4];
+
+ }
+ mZpow2_set = false;
+ mZpow3_set = false;
+ mAZpow4_set = false;
+
+ mX = (*mp_worksp_gfp_el)[6];
+ mY = (*mp_worksp_gfp_el)[7];
+ mZ = (*mp_worksp_gfp_el)[8];
+
+ return *this;
+
+ }
+PointGFp& PointGFp::operator-=(const PointGFp& rhs)
+ {
+ PointGFp minus_rhs = PointGFp(rhs).negate();
+
+ if (is_zero())
+ {
+ *this = minus_rhs;
+ }
+ else
+ {
+ *this += minus_rhs;
+ }
+ return *this;
+ }
+
+PointGFp& PointGFp::mult_this_secure(const BigInt& scalar,
+ const BigInt& /*point_order*/,
+ const BigInt& /*max_secr*/)
+ {
+ // NOTE: FS: so far this is code duplication of op*=.
+ // we have to see how we deal with this.
+ // fact is that we will probably modify this function
+ // while evaluating the countermeasures
+ // whereas we probably will not start modifying the
+ // function operator*=.
+ // however, in the end both should be merged.
+
+ // use montgomery mult. in this operation
+ this->turn_on_sp_red_mul();
+
+ std::tr1::shared_ptr<PointGFp> H(new PointGFp(this->mC));
+ std::tr1::shared_ptr<PointGFp> tmp; // used for AADA
+
+ PointGFp P(*this);
+ BigInt m(scalar);
+
+ if (m < BigInt(0))
+ {
+ m = -m;
+ P.negate();
+ }
+ if (P.is_zero() || (m == BigInt(0)))
+ {
+ *this = *H;
+ return *this;
+ }
+ if (m == BigInt(1))
+ {
+ return *this;
+ }
+ //
+#ifdef CM_AADA
+#ifndef CM_RAND_EXP
+ int max_secr_bits = max_secr.bits();
+#endif
+#endif
+
+ int mul_bits = m.bits(); // this is used for a determined number of loop runs in
+ // the mult_loop where leading zero´s are padded if necessary.
+ // Here we assign the value that will be used when no countermeasures are specified
+#ifdef CM_RAND_EXP
+ u32bit rand_r_bit_len = 20; // Coron(99) proposes 20 bit for r
+
+#ifdef CM_AADA
+
+ BigInt r_max(1);
+
+#endif // CM_AADA
+
+ // use randomized exponent
+#ifdef TA_COLL_T
+ static BigInt r_randexp;
+ if (new_rand)
+ {
+ r_randexp = random_integer(rand_r_bit_len);
+ }
+ //assert(!r_randexp.is_zero());
+#else
+ BigInt r_randexp(random_integer(rand_r_bit_len));
+#endif
+
+ m += r_randexp * point_order;
+ // determine mul_bits...
+#ifdef CM_AADA
+ // AADA with rand. Exp.
+ //assert(rand_r_bit_len > 0);
+ r_max <<= rand_r_bit_len;
+ r_max -= 1;
+ //assert(r_max.bits() == rand_r_bit_len);
+ mul_bits = (max_secr + point_order * r_max).bits();
+#else
+ // rand. Exp. without AADA
+ mul_bits = m.bits();
+#endif // CM_AADA
+
+
+#endif // CM_RAND_EXP
+
+ // determine mul_bits...
+#if (CM_AADA == 1 && CM_RAND_EXP != 1)
+
+ mul_bits = max_secr_bits;
+#endif // CM_AADA without CM_RAND_EXP
+
+ //assert(mul_bits != 0);
+
+
+ H = mult_loop(mul_bits-1, m, H, tmp, P);
+
+ if (!H->is_zero()) // cannot convert if H == O
+ {
+ *this = H->get_z_to_one();
+ }else
+ {
+ *this = *H;
+ }
+ mX.turn_off_sp_red_mul();
+ mY.turn_off_sp_red_mul();
+ mZ.turn_off_sp_red_mul();
+ return *this;
+ }
+
+PointGFp& PointGFp::operator*=(const BigInt& scalar)
+ {
+ // use montgomery mult. in this operation
+
+ this->turn_on_sp_red_mul();
+
+ PointGFp H(this->mC); // create as zero
+ H.turn_on_sp_red_mul();
+ PointGFp P(*this);
+ P.turn_on_sp_red_mul();
+ BigInt m(scalar);
+ if (m < BigInt(0))
+ {
+ m = -m;
+ P.negate();
+ }
+ if (P.is_zero() || (m == BigInt(0)))
+ {
+ *this = H;
+ return *this;
+ }
+ if (m == BigInt(1))
+ {
+ //*this == P already
+ return *this;
+ }
+
+ const int l = m.bits() - 1;
+ for (int i=l; i >=0; i--)
+ {
+
+ H.mult2_in_place();
+ if (m.get_bit(i))
+ {
+ H += P;
+ }
+ }
+
+ if (!H.is_zero()) // cannot convert if H == O
+ {
+ *this = H.get_z_to_one();
+ }else
+ {
+ *this = H;
+ }
+ return *this;
+ }
+
+inline std::tr1::shared_ptr<PointGFp> PointGFp::mult_loop(int l,
+ const BigInt& m,
+ std::tr1::shared_ptr<PointGFp> H,
+ std::tr1::shared_ptr<PointGFp> tmp,
+ const PointGFp& P)
+ {
+ //assert(l >= (int)m.bits()- 1);
+ tmp = H;
+ std::tr1::shared_ptr<PointGFp> to_add(new PointGFp(P)); // we just need some point
+ // so that we can use op=
+ // inside the loop
+ for (int i=l; i >=0; i--)
+ {
+ H->mult2_in_place();
+
+#ifndef CM_AADA
+
+ if (m.get_bit(i))
+ {
+ *H += P;
+ }
+#else // (CM_AADA is in)
+
+ if (H.get() == to_add.get())
+ {
+ to_add = tmp; // otherwise all pointers might point to the same object
+ // and we always need two objects to be able to switch around
+ }
+ to_add->assign_within_same_curve(*H);
+ tmp = H;
+ *tmp += P; // tmp already points to H
+
+ if (m.get_bit(i))
+ {
+ H = tmp; // NOTE: assign the pointer, not the value!
+ // (so that the operation is fast and thus as difficult
+ // to detect as possible)
+ }
+ else
+ {
+ H = to_add; // NOTE: this is necessary, because the assignment
+ // "*tmp = ..." already changed what H pointed to
+
+
+ }
+#endif // CM_AADA
+
+ }
+ return H;
+ }
+
+PointGFp& PointGFp::negate()
+ {
+ if (!is_zero())
+ {
+ mY.negate();
+ }
+ return *this;
+ }
+
+// *this *= 2
+PointGFp& PointGFp::mult2_in_place()
+ {
+ if (is_zero())
+ {
+ return *this;
+ }
+ if (mY.is_zero())
+ {
+
+ *this = PointGFp(mC); // setting myself to zero
+ return *this;
+ }
+ ensure_worksp();
+
+ (*mp_worksp_gfp_el)[0].share_assign(mY);
+ (*mp_worksp_gfp_el)[0] *= mY;
+
+ //GFpElement S(mX * z);
+ (*mp_worksp_gfp_el)[1].share_assign(mX);
+ (*mp_worksp_gfp_el)[1] *= (*mp_worksp_gfp_el)[0];
+
+ //GFpElement x(S + S);
+ (*mp_worksp_gfp_el)[2].share_assign((*mp_worksp_gfp_el)[1]);
+ (*mp_worksp_gfp_el)[2] += (*mp_worksp_gfp_el)[1];
+
+ //S = x + x;
+ (*mp_worksp_gfp_el)[1].share_assign((*mp_worksp_gfp_el)[2]);
+ (*mp_worksp_gfp_el)[1] += (*mp_worksp_gfp_el)[2];
+
+ if (!mAZpow4_set)
+ {
+ if (mZ == *(mC.get_mres_one()))
+ {
+ mAZpow4 = mC.get_mres_a();
+ mAZpow4_set = true;
+ }
+ else
+ {
+ if (!mZpow2_set)
+ {
+ mZpow2 = mZ;
+ mZpow2 *= mZ;
+
+ mZpow2_set = true;
+ }
+ //x = mZpow2 * mZpow2;
+ (*mp_worksp_gfp_el)[2].share_assign(mZpow2);
+ (*mp_worksp_gfp_el)[2] *= mZpow2;
+
+ //mAZpow4 = mC.get_mres_a() * x;
+ mAZpow4 = mC.get_mres_a();
+ mAZpow4 *= (*mp_worksp_gfp_el)[2];
+
+ }
+
+ }
+
+ //GFpElement y(mX * mX);
+ (*mp_worksp_gfp_el)[3].share_assign(mX);
+ (*mp_worksp_gfp_el)[3] *= mX;
+
+ //GFpElement M(y + y + y + mAZpow4);
+ (*mp_worksp_gfp_el)[4].share_assign((*mp_worksp_gfp_el)[3]);
+ (*mp_worksp_gfp_el)[4] += (*mp_worksp_gfp_el)[3];
+ (*mp_worksp_gfp_el)[4] += (*mp_worksp_gfp_el)[3];
+ (*mp_worksp_gfp_el)[4] += mAZpow4;
+
+ //x = M * M - (S+S);
+ (*mp_worksp_gfp_el)[2].share_assign((*mp_worksp_gfp_el)[4]);
+ (*mp_worksp_gfp_el)[2] *= (*mp_worksp_gfp_el)[4];
+ (*mp_worksp_gfp_el)[2] -= (*mp_worksp_gfp_el)[1];
+ (*mp_worksp_gfp_el)[2] -= (*mp_worksp_gfp_el)[1];
+
+ //y = z * z;
+ (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[0]);
+ (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[0];
+
+ //GFpElement U(y + y);
+ (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[3]);
+ (*mp_worksp_gfp_el)[5] += (*mp_worksp_gfp_el)[3];
+
+ //z = U + U;
+ (*mp_worksp_gfp_el)[0].share_assign((*mp_worksp_gfp_el)[5]);
+ (*mp_worksp_gfp_el)[0] += (*mp_worksp_gfp_el)[5];
+
+ //U = z + z;
+ (*mp_worksp_gfp_el)[5].share_assign((*mp_worksp_gfp_el)[0]);
+ (*mp_worksp_gfp_el)[5] += (*mp_worksp_gfp_el)[0];
+
+ //y = M * (S - x) - U;
+ (*mp_worksp_gfp_el)[3].share_assign((*mp_worksp_gfp_el)[1]);
+ (*mp_worksp_gfp_el)[3] -= (*mp_worksp_gfp_el)[2];
+ (*mp_worksp_gfp_el)[3] *= (*mp_worksp_gfp_el)[4];
+ (*mp_worksp_gfp_el)[3] -= (*mp_worksp_gfp_el)[5];
+
+ if (mZ != *(mC.get_mres_one()))
+ {
+ //z = mY * mZ;
+ (*mp_worksp_gfp_el)[0].share_assign(mY);
+ (*mp_worksp_gfp_el)[0] *= mZ;
+
+ }
+ else
+ {
+ //z = mY;
+ (*mp_worksp_gfp_el)[0].share_assign(mY);
+
+ }
+ //z = z + z;
+ (*mp_worksp_gfp_el)[6].share_assign((*mp_worksp_gfp_el)[0]);
+ (*mp_worksp_gfp_el)[0] += (*mp_worksp_gfp_el)[6];
+
+ //mX = x;
+ //mY = y;
+ //mZ = z;
+ mX = (*mp_worksp_gfp_el)[2];
+ mY = (*mp_worksp_gfp_el)[3];
+ mZ = (*mp_worksp_gfp_el)[0];
+
+ mZpow2_set = false;
+ mZpow3_set = false;
+ mAZpow4_set = false;
+ return *this;
+ }
+
+void PointGFp::turn_on_sp_red_mul() const
+ {
+ mX.turn_on_sp_red_mul();
+ mY.turn_on_sp_red_mul();
+ mZ.turn_on_sp_red_mul();
+
+ // also pretransform, otherwise
+ // we might have bad results with respect to
+ // performance because
+ // additions/subtractions in mult2_in_place()
+ // and op+= spread untransformed GFpElements
+ mX.get_mres();
+ mY.get_mres();
+ mZ.get_mres();
+
+ mZpow2.turn_on_sp_red_mul();
+ mZpow3.turn_on_sp_red_mul();
+ mAZpow4.turn_on_sp_red_mul();
+ }
+// getters
+
+/**
+* returns a point equivalent to *this but were
+* Z has value one, i.e. x and y correspond to
+* their values in affine coordinates
+*
+* Distributed under the terms of the Botan license
+*/
+PointGFp const PointGFp::get_z_to_one() const
+ {
+ return PointGFp(*this).set_z_to_one();
+ }
+
+/**
+* changes the representation of *this so that
+* Z has value one, i.e. x and y correspond to
+* their values in affine coordinates.
+* returns *this.
+*/
+const PointGFp& PointGFp::set_z_to_one() const
+ {
+ if (!(mZ.get_value() == BigInt(1)) && !(mZ.get_value() == BigInt(0)))
+ {
+ GFpElement z = inverse(mZ);
+ GFpElement z2 = z * z;
+ z *= z2;
+ GFpElement x = mX * z2;
+ GFpElement y = mY * z;
+ mZ = GFpElement(mC.get_p(), BigInt(1));
+ mX = x;
+ mY = y;
+ }
+ else
+ {
+ if (mZ.get_value() == BigInt(0))
+ {
+ throw Illegal_Transformation("cannot convert Z to one");
+ }
+ }
+ return *this; // mZ = 1 already
+ }
+
+const CurveGFp PointGFp::get_curve() const
+ {
+ return mC;
+ }
+
+GFpElement const PointGFp::get_affine_x() const
+ {
+
+ if (is_zero())
+ {
+ throw Illegal_Transformation("cannot convert to affine");
+
+ }
+ /*if(!mZpow2_set)
+ {*/
+ mZpow2 = mZ * mZ;
+ mZpow2_set = true;
+ //}
+ //assert(mZpow2 == mZ*mZ);
+ GFpElement z2 = mZpow2;
+ return mX * z2.inverse_in_place();
+ }
+
+GFpElement const PointGFp::get_affine_y() const
+ {
+
+ if (is_zero())
+ {
+ throw Illegal_Transformation("cannot convert to affine");
+
+ }
+ /*if(!mZpow3_set )
+ {*/
+ mZpow3 = mZ * mZ * mZ;
+ mZpow3_set = true;
+ //}
+ //assert(mZpow3 == mZ * mZ *mZ);
+ GFpElement z3 = mZpow3;
+ return mY * z3.inverse_in_place();
+ }
+
+GFpElement const PointGFp::get_jac_proj_x() const
+ {
+ return GFpElement(mX);
+ }
+
+GFpElement const PointGFp::get_jac_proj_y() const
+ {
+ return GFpElement(mY);
+ }
+
+GFpElement const PointGFp::get_jac_proj_z() const
+ {
+ return GFpElement(mZ);
+ }
+
+// Is this the point at infinity?
+bool PointGFp::is_zero() const
+ {
+ return(mX.is_zero() && mZ.is_zero());
+ //NOTE: the calls to GFpElement::is_zero() instead of getting the value and
+ // and comparing it are import because they do not provoke backtransformations
+ // to the ordinary residue.
+ }
+
+// Is the point still on the curve??
+// (If everything is correct, the point is always on its curve; then the
+// function will return silently. If Oskar managed to corrupt this object's state,
+// then it will throw an exception.)
+
+void PointGFp::check_invariants() const
+ {
+ if (is_zero())
+ {
+ return;
+ }
+ const GFpElement y2 = mY * mY;
+ const GFpElement x3 = mX * mX * mX;
+
+ if (mZ.get_value() == BigInt(1))
+ {
+ GFpElement ax = mC.get_a() * mX;
+ if(y2 != (x3 + ax + mC.get_b()))
+ {
+ throw Illegal_Point();
+ }
+
+ }
+
+ mZpow2 = mZ * mZ;
+ mZpow2_set = true;
+ mZpow3 = mZpow2 * mZ;
+ mZpow3_set = true;
+ mAZpow4 = mZpow3 * mZ * mC.get_a();
+ mAZpow4_set = true;
+ const GFpElement aXZ4 = mAZpow4 * mX;
+ const GFpElement bZ6 = mC.get_b() * mZpow3 * mZpow3;
+
+ if (y2 != (x3 + aXZ4 + bZ6))
+ throw Illegal_Point();
+ }
+
+// swaps the states of *this and other, does not throw!
+void PointGFp::swap(PointGFp& other)
+ {
+ mC.swap(other.mC);
+ mX.swap(other.mX);
+ mY.swap(other.mY);
+ mZ.swap(other.mZ);
+ mZpow2.swap(other.mZpow2);
+ mZpow3.swap(other.mZpow3);
+ mAZpow4.swap(other.mAZpow4);
+ std::swap<bool>(mZpow2_set, other.mZpow2_set);
+ std::swap<bool>(mZpow3_set, other.mZpow3_set);
+ std::swap<bool>(mAZpow4_set, other.mAZpow4_set);
+ }
+
+PointGFp const mult2(const PointGFp& point)
+ {
+ return (PointGFp(point)).mult2_in_place();
+ }
+
+bool operator==(const PointGFp& lhs, PointGFp const& rhs)
+ {
+ if (lhs.is_zero() && rhs.is_zero())
+ {
+ return true;
+ }
+ if ((lhs.is_zero() && !rhs.is_zero()) || (!lhs.is_zero() && rhs.is_zero()))
+ {
+ return false;
+ }
+ // neither operand is zero, so we can call get_z_to_one()
+ //assert(!lhs.is_zero());
+ //assert(!rhs.is_zero());
+ PointGFp aff_lhs = lhs.get_z_to_one();
+ PointGFp aff_rhs = rhs.get_z_to_one();
+ return (aff_lhs.get_curve() == aff_rhs.get_curve() &&
+ aff_lhs.get_jac_proj_x() == aff_rhs.get_jac_proj_x() &&
+ aff_lhs.get_jac_proj_y() == aff_rhs.get_jac_proj_y());
+ }
+
+// arithmetic operators
+PointGFp operator+(const PointGFp& lhs, PointGFp const& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp += rhs;
+ }
+
+PointGFp operator-(const PointGFp& lhs, PointGFp const& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp -= rhs;
+ }
+
+PointGFp operator-(const PointGFp& lhs)
+ {
+ return PointGFp(lhs).negate();
+ }
+
+PointGFp operator*(const BigInt& scalar, const PointGFp& point)
+ {
+ PointGFp result(point);
+ return result *= scalar;
+ }
+
+PointGFp operator*(const PointGFp& point, const BigInt& scalar)
+ {
+ PointGFp result(point);
+ return result *= scalar;
+ }
+
+PointGFp mult_point_secure(const PointGFp& point, const BigInt& scalar,
+ const BigInt& point_order, const BigInt& max_secret)
+ {
+ PointGFp result(point);
+ result.mult_this_secure(scalar, point_order, max_secret);
+ return result;
+ }
+
+// encoding and decoding
+SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
+ {
+ SecureVector<byte> result;
+ if (format == PointGFp::UNCOMPRESSED)
+ {
+ result = encode_uncompressed(point);
+ }
+ else if (format == PointGFp::COMPRESSED)
+ {
+ result = encode_compressed(point);
+
+ }
+ else if (format == PointGFp::HYBRID)
+ {
+ result = encode_hybrid(point);
+ }
+ else
+ {
+ throw Format_Error("illegal point encoding format specification");
+ }
+ return result;
+ }
+SecureVector<byte> encode_compressed(const PointGFp& point)
+ {
+
+
+ if (point.is_zero())
+ {
+ SecureVector<byte> result (1);
+ result[0] = 0;
+ return result;
+
+ }
+ u32bit l = point.get_curve().get_p().bits();
+ int dummy = l & 7;
+ if (dummy != 0)
+ {
+ l += 8 - dummy;
+ }
+ l /= 8;
+ SecureVector<byte> result (l+1);
+ result[0] = 2;
+ BigInt x = point.get_affine_x().get_value();
+ SecureVector<byte> bX = BigInt::encode_1363(x, l);
+ result.copy(1, bX.begin(), bX.size());
+ BigInt y = point.get_affine_y().get_value();
+ if (y.get_bit(0))
+ {
+ result[0] |= 1;
+ }
+ return result;
+ }
+
+
+SecureVector<byte> encode_uncompressed(const PointGFp& point)
+ {
+ if (point.is_zero())
+ {
+ SecureVector<byte> result (1);
+ result[0] = 0;
+ return result;
+ }
+ u32bit l = point.get_curve().get_p().bits();
+ int dummy = l & 7;
+ if (dummy != 0)
+ {
+ l += 8 - dummy;
+ }
+ l /= 8;
+ SecureVector<byte> result (2*l+1);
+ result[0] = 4;
+ BigInt x = point.get_affine_x().get_value();
+ BigInt y = point.get_affine_y().get_value();
+ SecureVector<byte> bX = BigInt::encode_1363(x, l);
+ SecureVector<byte> bY = BigInt::encode_1363(y, l);
+ result.copy(1, bX.begin(), l);
+ result.copy(l+1, bY.begin(), l);
+ return result;
+
+ }
+
+SecureVector<byte> encode_hybrid(const PointGFp& point)
+ {
+ if (point.is_zero())
+ {
+ SecureVector<byte> result (1);
+ result[0] = 0;
+ return result;
+ }
+ u32bit l = point.get_curve().get_p().bits();
+ int dummy = l & 7;
+ if (dummy != 0)
+ {
+ l += 8 - dummy;
+ }
+ l /= 8;
+ SecureVector<byte> result (2*l+1);
+ result[0] = 6;
+ BigInt x = point.get_affine_x().get_value();
+ BigInt y = point.get_affine_y().get_value();
+ SecureVector<byte> bX = BigInt::encode_1363(x, l);
+ SecureVector<byte> bY = BigInt::encode_1363(y, l);
+ result.copy(1, bX.begin(), bX.size());
+ result.copy(l+1, bY.begin(), bY.size());
+ if (y.get_bit(0))
+ {
+ result[0] |= 1;
+ }
+ return result;
+ }
+
+PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve)
+ {
+ if (os.size() == 1 && os[0] == 0)
+ {
+ return PointGFp(curve); // return zero
+ }
+ SecureVector<byte> bX;
+ SecureVector<byte> bY;
+
+ GFpElement x(1,0);
+ GFpElement y(1,0);
+ GFpElement z(1,0);
+
+ const byte pc = os[0];
+ BigInt bi_dec_x;
+ BigInt bi_dec_y;
+ switch (pc)
+ {
+ case 2:
+ case 3:
+ //compressed form
+ bX = SecureVector<byte>(os.size() - 1);
+ bX.copy(os.begin()+1, os.size()-1);
+
+ /* Problem wäre, wenn decode() das erste bit als Vorzeichen interpretiert.
+ *---------------------
+ * AW(FS): decode() interpretiert das erste Bit nicht als Vorzeichen
+ */
+ bi_dec_x = BigInt::decode(bX, bX.size());
+ x = GFpElement(curve.get_p(), bi_dec_x);
+ bool yMod2;
+ yMod2 = (pc & 1) == 1;
+ y = PointGFp::decompress(yMod2, x, curve);
+ break;
+ case 4:
+ // uncompressed form
+ int l;
+ l = (os.size() -1)/2;
+ bX = SecureVector<byte>(l);
+ bY = SecureVector<byte>(l);
+ bX.copy(os.begin()+1, l);
+ bY.copy(os.begin()+1+l, l);
+ bi_dec_x = BigInt::decode(bX.begin(), bX.size());
+
+ bi_dec_y = BigInt::decode(bY.begin(),bY.size());
+ x = GFpElement(curve.get_p(), bi_dec_x);
+ y = GFpElement(curve.get_p(), bi_dec_y);
+ break;
+
+ case 6:
+ case 7:
+ //hybrid form
+ l = (os.size() - 1)/2;
+ bX = SecureVector<byte>(l);
+ bY = SecureVector<byte>(l);
+ bX.copy(os.begin() + 1, l);
+ bY.copy(os.begin()+1+l, l);
+ yMod2 = (pc & 0x01) == 1;
+ if (!(PointGFp::decompress(yMod2, x, curve) == y))
+ {
+ throw Illegal_Point("error during decoding hybrid format");
+ }
+ break;
+ default:
+ throw Format_Error("encountered illegal format specification while decoding point");
+ }
+ z = GFpElement(curve.get_p(), BigInt(1));
+ //assert((x.is_trf_to_mres() && x.is_use_montgm()) || !x.is_trf_to_mres());
+ //assert((y.is_trf_to_mres() && y.is_use_montgm()) || !y.is_trf_to_mres());
+ //assert((z.is_trf_to_mres() && z.is_use_montgm()) || !z.is_trf_to_mres());
+ PointGFp result(curve, x, y, z);
+ result.check_invariants();
+ //assert((result.get_jac_proj_x().is_trf_to_mres() && result.get_jac_proj_x().is_use_montgm()) || !result.get_jac_proj_x().is_trf_to_mres());
+ //assert((result.get_jac_proj_y().is_trf_to_mres() && result.get_jac_proj_y().is_use_montgm()) || !result.get_jac_proj_y().is_trf_to_mres());
+ //assert((result.get_jac_proj_z().is_trf_to_mres() && result.get_jac_proj_z().is_use_montgm()) || !result.get_jac_proj_z().is_trf_to_mres());
+ return result;
+ }
+
+GFpElement PointGFp::decompress(bool yMod2, const GFpElement& x,
+ const CurveGFp& curve)
+ {
+ BigInt xVal = x.get_value();
+ BigInt xpow3 = xVal * xVal * xVal;
+ BigInt g = curve.get_a().get_value() * xVal;
+ g += xpow3;
+ g += curve.get_b().get_value();
+ g = g%curve.get_p();
+ BigInt z = ressol(g, curve.get_p());
+
+ if(z < 0)
+ throw Illegal_Point("error during decompression");
+
+ bool zMod2 = z.get_bit(0);
+ if ((zMod2 && ! yMod2) || (!zMod2 && yMod2))
+ {
+ z = curve.get_p() - z;
+ }
+ return GFpElement(curve.get_p(),z);
+ }
+
+PointGFp const create_random_point(RandomNumberGenerator& rng,
+ const CurveGFp& curve)
+ {
+
+ // create a random point
+ GFpElement mX(1,1);
+ GFpElement mY(1,1);
+ GFpElement mZ(1,1);
+ GFpElement minusOne(curve.get_p(), BigInt(BigInt::Negative,1));
+ mY = minusOne;
+ GFpElement y2(1,1);
+ GFpElement x(1,1);
+
+ while (mY == minusOne)
+ {
+ BigInt value(rng, curve.get_p().bits());
+ mX = GFpElement(curve.get_p(),value);
+ y2 = curve.get_a() * mX;
+ x = mX * mX;
+ x *= mX;
+ y2 += (x + curve.get_b());
+
+ value = ressol(y2.get_value(), curve.get_p());
+
+ if(value < 0)
+ mY = minusOne;
+ else
+ mY = GFpElement(curve.get_p(), value);
+ }
+ mZ = GFpElement(curve.get_p(), BigInt(1));
+
+ return PointGFp(curve, mX, mY, mZ);
+ }
+
+} // namespace Botan
diff --git a/botan/src/math/gfpmath/point_gfp.h b/botan/src/math/gfpmath/point_gfp.h
new file mode 100644
index 0000000..771605e
--- /dev/null
+++ b/botan/src/math/gfpmath/point_gfp.h
@@ -0,0 +1,315 @@
+/*
+* Arithmetic over GF(p)
+*
+* (C) 2007 Martin Doering
+* Christoph Ludwig
+* Falko Strenzke
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POINT_GFP_H__
+#define BOTAN_POINT_GFP_H__
+
+#include <botan/curve_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/bigint.h>
+#include <botan/exceptn.h>
+#include <vector>
+
+namespace Botan {
+
+struct Illegal_Point : public Exception
+ {
+ Illegal_Point(const std::string& err = "") : Exception(err) {}
+ };
+
+/**
+* This class represents one point on a curve of GF(p).
+*/
+class BOTAN_DLL PointGFp
+ {
+ public:
+ /**
+ * uncompressed encoding byte value
+ */
+ static const int UNCOMPRESSED = 0;
+
+ /**
+ * compressed encoding byte value
+ */
+ static const int COMPRESSED = 1;
+
+ /**
+ * hybrid encoding byte value
+ */
+ static const int HYBRID = 2;
+
+ /**
+ * Construct the point O
+ * @param curve The base curve
+ */
+ explicit PointGFp(const CurveGFp& curve);
+
+ /**
+ * Construct a point given its affine coordinates
+ * @param curve the base curve
+ * @param x affine x coordinate
+ * @param y affine y coordinate
+ */
+ explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
+ GFpElement const& y);
+
+ /**
+ * Construct a point given its jacobian projective coordinates
+ * @param curve the base curve
+ * @param x jacobian projective x coordinate
+ * @param y jacobian projective y coordinate
+ * @param z jacobian projective y coordinate
+ */
+ explicit PointGFp(const CurveGFp& curve, GFpElement const& x,
+ GFpElement const& y, GFpElement const& z);
+
+ /**
+ * copy constructor
+ * @param other the value to clone
+ */
+ PointGFp(const PointGFp& other);
+
+ /**
+ * assignment operator
+ * @param other The point to use as source for the assignment
+ */
+ const PointGFp& operator=(const PointGFp& other);
+
+ /**
+ * assign another point which is on the same curve as *this
+ * @param other The point to use as source for the assignment
+ */
+ const PointGFp& assign_within_same_curve(const PointGFp& other);
+
+
+
+ /**
+ * += Operator
+ * @param rhs the PointGFp to add to the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator+=(const PointGFp& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the PointGFp to subtract from the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator-=(const PointGFp& rhs);
+
+ /**
+ * *= Operator
+ * This function turns on the the special reduction multiplication
+ * itself for fast computation, turns it off again when finished.
+ * @param scalar the PointGFp to multiply with *this
+ * @result resulting PointGFp
+ */
+ PointGFp& operator*=(const BigInt& scalar);
+
+ /**
+ * the equivalent to operator*= with countermeasures against
+ * sidechannel attacks, using the randomized exponent
+ * and add-and-double-always
+ * countermeasures (suitable for ECDSA and ECKAEG)
+ * @param scalar the scalar to multiply the point with
+ * @param point_order a multiple of the order of the point
+ *(= n * k in the general case; k is the cofactor)
+ * @param max_secr the maximal size of the scalar
+ * (will usually be n-1 )
+ * @result resulting PointGFp
+ */
+ PointGFp& mult_this_secure(const BigInt& scalar,
+ const BigInt& point_order,
+ const BigInt& max_secr
+ );
+
+ /**
+ * Negate internal value(*this *= -1 )
+ * @return *this
+ */
+ PointGFp& negate();
+
+ /**
+ * Multiply the point by two(*this *= 2 )
+ * @return *this
+ */
+ PointGFp& mult2_in_place();
+
+ /**
+ * Set z coordinate to one.
+ * @return *this
+ */
+ const PointGFp& set_z_to_one() const;
+
+ /**
+ * Turn on the special reduction multiplication (i.e. the
+ * Montgomery multiplication in the current implementation) for
+ * the coordinates. This enables fast execution of mult2_in_place()
+ * and operator+=().
+ */
+ void turn_on_sp_red_mul() const;
+
+ /**
+ * Return a point
+ * where the coordinates are transformed
+ * so that z equals one,
+ * thus x and y have just the affine values.
+ * @result *this
+ */
+ PointGFp const get_z_to_one() const;
+
+ /**
+ * Return base curve of this point
+ * @result the curve over GF(p) of this point
+ */
+ CurveGFp const get_curve() const;
+
+ /**
+ * get affine x coordinate
+ * @result affine x coordinate
+ */
+ GFpElement const get_affine_x() const;
+
+ /**
+ * get affine y coordinate
+ * @result affine y coordinate
+ */
+ GFpElement const get_affine_y() const;
+
+ /**
+ * get the jacobian projective x coordinate
+ * @result jacobian projective x coordinate
+ */
+ GFpElement const get_jac_proj_x() const;
+
+ /**
+ * get the jacobian projective y coordinate
+ * @result jacobian projective y coordinate
+ */
+ GFpElement const get_jac_proj_y() const;
+
+ /**
+ * get the jacobian projective z coordinate
+ * @result jacobian projective z coordinate
+ */
+ GFpElement const get_jac_proj_z() const;
+
+ /**
+ * Is this the point at infinity?
+ * @result true, if this point is at infinity, false otherwise.
+ */
+ bool is_zero() const;
+
+ /**
+ * Checks whether the point is to be found on the underlying curve.
+ * Throws an Invalid_Point exception in case of detecting that the point
+ * does not satisfy the curve equation.
+ * To be used to ensure against fault attacks.
+ */
+ void check_invariants() const;
+
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other the object to swap values with
+ */
+ void swap(PointGFp& other);
+
+ /**
+ * Sets the shared pointer to the GFpModulus that will be
+ * held in *this, specifically the various members of *this.
+ * Warning: do not use this function unless you know in detail about
+ * the implications of using
+ * the shared GFpModulus objects!
+ * Do NOT spread a shared pointer to GFpModulus over different
+ * threads!
+ * @param mod a shared pointer to a GFpModulus that will
+ * be held in the members *this
+ */
+ void set_shrd_mod(std::tr1::shared_ptr<GFpModulus> p_mod);
+
+ static GFpElement decompress(bool yMod2, GFpElement const& x, const CurveGFp& curve);
+
+ private:
+ static const u32bit GFPEL_WKSP_SIZE = 9;
+ void ensure_worksp() const;
+
+ inline std::tr1::shared_ptr<PointGFp> mult_loop(int l, const BigInt& m,
+ std::tr1::shared_ptr<PointGFp> H,
+ std::tr1::shared_ptr<PointGFp> tmp,
+ const PointGFp& P);
+
+ CurveGFp mC;
+ mutable GFpElement mX; // NOTE: these values must be mutable (affine<->proj)
+ mutable GFpElement mY;
+ mutable GFpElement mZ;
+ mutable GFpElement mZpow2; // mZ^2
+ mutable GFpElement mZpow3; // mZ^3
+ mutable GFpElement mAZpow4; // mA*mZ^4
+ mutable bool mZpow2_set;
+ mutable bool mZpow3_set;
+ mutable bool mAZpow4_set;
+ mutable std::tr1::shared_ptr<std::vector<GFpElement> > mp_worksp_gfp_el;
+
+ };
+
+// relational operators
+bool operator==(const PointGFp& lhs, const PointGFp& rhs);
+inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs )
+ {
+ return !operator==(lhs, rhs);
+ }
+
+// arithmetic operators
+PointGFp operator+(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp operator-(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp operator-(const PointGFp& lhs);
+
+PointGFp operator*(const BigInt& scalar, const PointGFp& point);
+PointGFp operator*(const PointGFp& point, const BigInt& scalar);
+PointGFp mult_point_secure(const PointGFp& point,
+ const BigInt& scalar,
+ const BigInt& point_order,
+ const BigInt& max_secret);
+
+PointGFp const mult2(const PointGFp& point);
+
+PointGFp const create_random_point(RandomNumberGenerator& rng,
+ const CurveGFp& curve);
+
+// encoding and decoding
+SecureVector<byte> EC2OSP(const PointGFp& point, byte format);
+PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve);
+
+SecureVector<byte> encode_uncompressed(const PointGFp& point); // maybe make private
+SecureVector<byte> encode_hybrid(const PointGFp& point); // maybe make private
+SecureVector<byte> encode_compressed(const PointGFp& point); // maybe make private
+
+// swaps the states of point1 and point2, does not throw!
+// cf. Meyers, Item 25
+inline
+void swap(PointGFp& point1, PointGFp& point2 )
+ {
+ point1.swap(point2);
+ }
+
+} // namespace Botan
+
+namespace std {
+
+// swaps the states of point1 and point2, does not throw!
+// cf. Meyers, Item 25
+template<> inline void
+swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y) { x.swap(y); }
+
+} // namespace std
+
+#endif
diff --git a/botan/src/math/numbertheory/blinding.cpp b/botan/src/math/numbertheory/blinding.cpp
new file mode 100644
index 0000000..c6a3fd1
--- /dev/null
+++ b/botan/src/math/numbertheory/blinding.cpp
@@ -0,0 +1,49 @@
+/*
+* Blinder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/blinding.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+/*
+* Blinder Constructor
+*/
+Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n)
+ {
+ if(e < 1 || d < 1 || n < 1)
+ throw Invalid_Argument("Blinder: Arguments too small");
+
+ reducer = Modular_Reducer(n);
+ this->e = e;
+ this->d = d;
+ }
+
+/*
+* Blind a number
+*/
+BigInt Blinder::blind(const BigInt& i) const
+ {
+ if(!reducer.initialized())
+ return i;
+
+ e = reducer.square(e);
+ d = reducer.square(d);
+ return reducer.multiply(i, e);
+ }
+
+/*
+* Unblind a number
+*/
+BigInt Blinder::unblind(const BigInt& i) const
+ {
+ if(!reducer.initialized())
+ return i;
+ return reducer.multiply(i, d);
+ }
+
+}
diff --git a/botan/src/math/numbertheory/blinding.h b/botan/src/math/numbertheory/blinding.h
new file mode 100644
index 0000000..5f7f9e6
--- /dev/null
+++ b/botan/src/math/numbertheory/blinding.h
@@ -0,0 +1,34 @@
+/*
+* Blinder
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BLINDER_H__
+#define BOTAN_BLINDER_H__
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/*
+* Blinding Function Object
+*/
+class BOTAN_DLL Blinder
+ {
+ public:
+ BigInt blind(const BigInt&) const;
+ BigInt unblind(const BigInt&) const;
+
+ Blinder() {}
+ Blinder(const BigInt&, const BigInt&, const BigInt&);
+ private:
+ Modular_Reducer reducer;
+ mutable BigInt e, d;
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/numbertheory/def_powm.h b/botan/src/math/numbertheory/def_powm.h
new file mode 100644
index 0000000..472c865
--- /dev/null
+++ b/botan/src/math/numbertheory/def_powm.h
@@ -0,0 +1,64 @@
+/*
+* Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DEFAULT_MODEXP_H__
+#define BOTAN_DEFAULT_MODEXP_H__
+
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+#include <vector>
+
+namespace Botan {
+
+/*
+* Fixed Window Exponentiator
+*/
+class BOTAN_DLL Fixed_Window_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_exponent(const BigInt&);
+ void set_base(const BigInt&);
+ BigInt execute() const;
+
+ Modular_Exponentiator* copy() const
+ { return new Fixed_Window_Exponentiator(*this); }
+
+ Fixed_Window_Exponentiator(const BigInt&, Power_Mod::Usage_Hints);
+ private:
+ Modular_Reducer reducer;
+ BigInt exp;
+ u32bit window_bits;
+ std::vector<BigInt> g;
+ Power_Mod::Usage_Hints hints;
+ };
+
+/*
+* Montgomery Exponentiator
+*/
+class BOTAN_DLL Montgomery_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_exponent(const BigInt&);
+ void set_base(const BigInt&);
+ BigInt execute() const;
+
+ Modular_Exponentiator* copy() const
+ { return new Montgomery_Exponentiator(*this); }
+
+ Montgomery_Exponentiator(const BigInt&, Power_Mod::Usage_Hints);
+ private:
+ BigInt exp, modulus;
+ BigInt R2, R_mod;
+ std::vector<BigInt> g;
+ word mod_prime;
+ u32bit mod_words, exp_bits, window_bits;
+ Power_Mod::Usage_Hints hints;
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/numbertheory/dsa_gen.cpp b/botan/src/math/numbertheory/dsa_gen.cpp
new file mode 100644
index 0000000..83646e5
--- /dev/null
+++ b/botan/src/math/numbertheory/dsa_gen.cpp
@@ -0,0 +1,135 @@
+/*
+* DSA Parameter Generation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+#include <botan/algo_factory.h>
+#include <botan/hash.h>
+#include <botan/parsing.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Check if this size is allowed by FIPS 186-3
+*/
+bool fips186_3_valid_size(u32bit pbits, u32bit qbits)
+ {
+ if(qbits == 160)
+ return (pbits == 512 || pbits == 768 || pbits == 1024);
+
+ if(qbits == 224)
+ return (pbits == 2048);
+
+ if(qbits == 256)
+ return (pbits == 2048 || pbits == 3072);
+
+ return false;
+ }
+
+}
+
+/*
+* Attempt DSA prime generation with given seed
+*/
+bool generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p, BigInt& q,
+ u32bit pbits, u32bit qbits,
+ const MemoryRegion<byte>& seed_c)
+ {
+ if(!fips186_3_valid_size(pbits, qbits))
+ throw Invalid_Argument(
+ "FIPS 186-3 does not allow DSA domain parameters of " +
+ to_string(pbits) + "/" + to_string(qbits) + " bits long");
+
+ if(seed_c.size() * 8 < qbits)
+ throw Invalid_Argument(
+ "Generating a DSA parameter set with a " + to_string(qbits) +
+ "long q requires a seed at least as many bits long");
+
+ std::auto_ptr<HashFunction> hash(
+ af.make_hash_function("SHA-" + to_string(qbits)));
+
+ const u32bit HASH_SIZE = hash->OUTPUT_LENGTH;
+
+ class Seed
+ {
+ public:
+ Seed(const MemoryRegion<byte>& s) : seed(s) {}
+
+ operator MemoryRegion<byte>& () { return seed; }
+
+ Seed& operator++()
+ {
+ for(u32bit j = seed.size(); j > 0; --j)
+ if(++seed[j-1])
+ break;
+ return (*this);
+ }
+ private:
+ SecureVector<byte> seed;
+ };
+
+ Seed seed(seed_c);
+
+ q.binary_decode(hash->process(seed));
+ q.set_bit(qbits-1);
+ q.set_bit(0);
+
+ if(!is_prime(q, rng))
+ return false;
+
+ const u32bit n = (pbits-1) / (HASH_SIZE * 8),
+ b = (pbits-1) % (HASH_SIZE * 8);
+
+ BigInt X;
+ SecureVector<byte> V(HASH_SIZE * (n+1));
+
+ for(u32bit j = 0; j != 4096; ++j)
+ {
+ for(u32bit k = 0; k <= n; ++k)
+ {
+ ++seed;
+ hash->update(seed);
+ hash->final(V + HASH_SIZE * (n-k));
+ }
+
+ X.binary_decode(V + (HASH_SIZE - 1 - b/8),
+ V.size() - (HASH_SIZE - 1 - b/8));
+ X.set_bit(pbits-1);
+
+ p = X - (X % (2*q) - 1);
+
+ if(p.bits() == pbits && is_prime(p, rng))
+ return true;
+ }
+ return false;
+ }
+
+/*
+* Generate DSA Primes
+*/
+SecureVector<byte> generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p, BigInt& q,
+ u32bit pbits, u32bit qbits)
+ {
+ SecureVector<byte> seed(qbits/8);
+
+ while(true)
+ {
+ rng.randomize(seed, seed.size());
+
+ if(generate_dsa_primes(rng, af, p, q, pbits, qbits, seed))
+ return seed;
+ }
+ }
+
+}
diff --git a/botan/src/math/numbertheory/info.txt b/botan/src/math/numbertheory/info.txt
new file mode 100644
index 0000000..1595c73
--- /dev/null
+++ b/botan/src/math/numbertheory/info.txt
@@ -0,0 +1,33 @@
+realname "Math Functions"
+
+load_on auto
+
+define BIGINT_MATH
+
+<add>
+blinding.cpp
+blinding.h
+def_powm.h
+dsa_gen.cpp
+jacobi.cpp
+make_prm.cpp
+mp_numth.cpp
+numthry.cpp
+numthry.h
+pow_mod.cpp
+pow_mod.h
+powm_fw.cpp
+powm_mnt.cpp
+primes.cpp
+reducer.cpp
+reducer.h
+ressol.cpp
+</add>
+
+<requires>
+algo_factory
+bigint
+hash
+libstate
+rng
+</requires>
diff --git a/botan/src/math/numbertheory/jacobi.cpp b/botan/src/math/numbertheory/jacobi.cpp
new file mode 100644
index 0000000..2ad05ff
--- /dev/null
+++ b/botan/src/math/numbertheory/jacobi.cpp
@@ -0,0 +1,53 @@
+/*
+* Jacobi Function
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+
+namespace Botan {
+
+/*
+* Calculate the Jacobi symbol
+*/
+s32bit jacobi(const BigInt& a, const BigInt& n)
+ {
+ if(a.is_negative())
+ throw Invalid_Argument("jacobi: first argument must be non-negative");
+ if(n.is_even() || n < 2)
+ throw Invalid_Argument("jacobi: second argument must be odd and > 1");
+
+ BigInt x = a, y = n;
+ s32bit J = 1;
+
+ while(y > 1)
+ {
+ x %= y;
+ if(x > y / 2)
+ {
+ x = y - x;
+ if(y % 4 == 3)
+ J = -J;
+ }
+ if(x.is_zero())
+ return 0;
+
+ u32bit shifts = low_zero_bits(x);
+ x >>= shifts;
+ if(shifts % 2)
+ {
+ word y_mod_8 = y % 8;
+ if(y_mod_8 == 3 || y_mod_8 == 5)
+ J = -J;
+ }
+
+ if(x % 4 == 3 && y % 4 == 3)
+ J = -J;
+ std::swap(x, y);
+ }
+ return J;
+ }
+
+}
diff --git a/botan/src/math/numbertheory/make_prm.cpp b/botan/src/math/numbertheory/make_prm.cpp
new file mode 100644
index 0000000..b136b6d
--- /dev/null
+++ b/botan/src/math/numbertheory/make_prm.cpp
@@ -0,0 +1,97 @@
+/*
+* Prime Generation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Generate a random prime
+*/
+BigInt random_prime(RandomNumberGenerator& rng,
+ u32bit bits, const BigInt& coprime,
+ u32bit equiv, u32bit modulo)
+ {
+ if(bits <= 1)
+ throw Invalid_Argument("random_prime: Can't make a prime of " +
+ to_string(bits) + " bits");
+ else if(bits == 2)
+ return ((rng.next_byte() % 2) ? 2 : 3);
+ else if(bits == 3)
+ return ((rng.next_byte() % 2) ? 5 : 7);
+ else if(bits == 4)
+ return ((rng.next_byte() % 2) ? 11 : 13);
+
+ if(coprime <= 0)
+ throw Invalid_Argument("random_prime: coprime must be > 0");
+ if(modulo % 2 == 1 || modulo == 0)
+ throw Invalid_Argument("random_prime: Invalid modulo value");
+ if(equiv >= modulo || equiv % 2 == 0)
+ throw Invalid_Argument("random_prime: equiv must be < modulo, and odd");
+
+ while(true)
+ {
+ BigInt p(rng, bits);
+ p.set_bit(bits - 2);
+ p.set_bit(0);
+
+ if(p % modulo != equiv)
+ p += (modulo - p % modulo) + equiv;
+
+ const u32bit sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE);
+ SecureVector<u32bit> sieve(sieve_size);
+
+ for(u32bit j = 0; j != sieve.size(); ++j)
+ sieve[j] = p % PRIMES[j];
+
+ u32bit counter = 0;
+ while(true)
+ {
+ if(counter == 4096 || p.bits() > bits)
+ break;
+
+ bool passes_sieve = true;
+ ++counter;
+ p += modulo;
+
+ if(p.bits() > bits)
+ break;
+
+ for(u32bit j = 0; j != sieve.size(); ++j)
+ {
+ sieve[j] = (sieve[j] + modulo) % PRIMES[j];
+ if(sieve[j] == 0)
+ passes_sieve = false;
+ }
+
+ if(!passes_sieve || gcd(p - 1, coprime) != 1)
+ continue;
+ if(passes_mr_tests(rng, p))
+ return p;
+ }
+ }
+ }
+
+/*
+* Generate a random safe prime
+*/
+BigInt random_safe_prime(RandomNumberGenerator& rng, u32bit bits)
+ {
+ if(bits <= 64)
+ throw Invalid_Argument("random_safe_prime: Can't make a prime of " +
+ to_string(bits) + " bits");
+
+ BigInt p;
+ do
+ p = (random_prime(rng, bits - 1) << 1) + 1;
+ while(!is_prime(p, rng));
+ return p;
+ }
+
+}
diff --git a/botan/src/math/numbertheory/mp_numth.cpp b/botan/src/math/numbertheory/mp_numth.cpp
new file mode 100644
index 0000000..45a3984
--- /dev/null
+++ b/botan/src/math/numbertheory/mp_numth.cpp
@@ -0,0 +1,71 @@
+/*
+* Fused and Important MP Algorithms
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+#include <botan/mp_core.h>
+#include <botan/util.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Square a BigInt
+*/
+BigInt square(const BigInt& x)
+ {
+ const u32bit x_sw = x.sig_words();
+
+ BigInt z(BigInt::Positive, round_up(2*x_sw, 16));
+ SecureVector<word> workspace(z.size());
+
+ bigint_sqr(z.get_reg(), z.size(), workspace,
+ x.data(), x.size(), x_sw);
+ return z;
+ }
+
+/*
+* Multiply-Add Operation
+*/
+BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c)
+ {
+ if(c.is_negative() || c.is_zero())
+ throw Invalid_Argument("mul_add: Third argument must be > 0");
+
+ BigInt::Sign sign = BigInt::Positive;
+ if(a.sign() != b.sign())
+ sign = BigInt::Negative;
+
+ const u32bit a_sw = a.sig_words();
+ const u32bit b_sw = b.sig_words();
+ const u32bit c_sw = c.sig_words();
+
+ BigInt r(sign, std::max(a.size() + b.size(), c_sw) + 1);
+ SecureVector<word> workspace(r.size());
+
+ bigint_mul(r.get_reg(), r.size(), workspace,
+ a.data(), a.size(), a_sw,
+ b.data(), b.size(), b_sw);
+ const u32bit r_size = std::max(r.sig_words(), c_sw);
+ bigint_add2(r.get_reg(), r_size, c.data(), c_sw);
+ return r;
+ }
+
+/*
+* Subtract-Multiply Operation
+*/
+BigInt sub_mul(const BigInt& a, const BigInt& b, const BigInt& c)
+ {
+ if(a.is_negative() || b.is_negative())
+ throw Invalid_Argument("sub_mul: First two arguments must be >= 0");
+
+ BigInt r = a;
+ r -= b;
+ r *= c;
+ return r;
+ }
+
+}
diff --git a/botan/src/math/numbertheory/numthry.cpp b/botan/src/math/numbertheory/numthry.cpp
new file mode 100644
index 0000000..4486813
--- /dev/null
+++ b/botan/src/math/numbertheory/numthry.cpp
@@ -0,0 +1,346 @@
+/*
+* Number Theory Functions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+#include <botan/bit_ops.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Miller-Rabin Iterations
+*/
+u32bit miller_rabin_test_iterations(u32bit bits, bool verify)
+ {
+ struct mapping { u32bit bits; u32bit verify_iter; u32bit check_iter; };
+
+ static const mapping tests[] = {
+ { 50, 55, 25 },
+ { 100, 38, 22 },
+ { 160, 32, 18 },
+ { 163, 31, 17 },
+ { 168, 30, 16 },
+ { 177, 29, 16 },
+ { 181, 28, 15 },
+ { 185, 27, 15 },
+ { 190, 26, 15 },
+ { 195, 25, 14 },
+ { 201, 24, 14 },
+ { 208, 23, 14 },
+ { 215, 22, 13 },
+ { 222, 21, 13 },
+ { 231, 20, 13 },
+ { 241, 19, 12 },
+ { 252, 18, 12 },
+ { 264, 17, 12 },
+ { 278, 16, 11 },
+ { 294, 15, 10 },
+ { 313, 14, 9 },
+ { 334, 13, 8 },
+ { 360, 12, 8 },
+ { 392, 11, 7 },
+ { 430, 10, 7 },
+ { 479, 9, 6 },
+ { 542, 8, 6 },
+ { 626, 7, 5 },
+ { 746, 6, 4 },
+ { 926, 5, 3 },
+ { 1232, 4, 2 },
+ { 1853, 3, 2 },
+ { 0, 0, 0 }
+ };
+
+ for(u32bit i = 0; tests[i].bits; ++i)
+ {
+ if(bits <= tests[i].bits)
+ {
+ if(verify)
+ return tests[i].verify_iter;
+ else
+ return tests[i].check_iter;
+ }
+ }
+ return 2;
+ }
+
+}
+
+/*
+* Return the number of 0 bits at the end of n
+*/
+u32bit low_zero_bits(const BigInt& n)
+ {
+ if(n.is_negative() || n.is_zero()) return 0;
+
+ u32bit low_zero = 0;
+
+ if(n.is_positive() && n.is_nonzero())
+ {
+ for(u32bit i = 0; i != n.size(); ++i)
+ {
+ word x = n[i];
+
+ if(x)
+ {
+ low_zero += ctz(x);
+ break;
+ }
+ else
+ low_zero += BOTAN_MP_WORD_BITS;
+ }
+ }
+
+ return low_zero;
+ }
+
+/*
+* Calculate the GCD
+*/
+BigInt gcd(const BigInt& a, const BigInt& b)
+ {
+ if(a.is_zero() || b.is_zero()) return 0;
+ if(a == 1 || b == 1) return 1;
+
+ BigInt x = a, y = b;
+ x.set_sign(BigInt::Positive);
+ y.set_sign(BigInt::Positive);
+ u32bit shift = std::min(low_zero_bits(x), low_zero_bits(y));
+
+ x >>= shift;
+ y >>= shift;
+
+ while(x.is_nonzero())
+ {
+ x >>= low_zero_bits(x);
+ y >>= low_zero_bits(y);
+ if(x >= y) { x -= y; x >>= 1; }
+ else { y -= x; y >>= 1; }
+ }
+
+ return (y << shift);
+ }
+
+/*
+* Calculate the LCM
+*/
+BigInt lcm(const BigInt& a, const BigInt& b)
+ {
+ return ((a * b) / gcd(a, b));
+ }
+
+/*
+* Find the Modular Inverse
+*/
+BigInt inverse_mod(const BigInt& n, const BigInt& mod)
+ {
+ if(mod.is_zero())
+ throw BigInt::DivideByZero();
+ if(mod.is_negative() || n.is_negative())
+ throw Invalid_Argument("inverse_mod: arguments must be non-negative");
+
+ if(n.is_zero() || (n.is_even() && mod.is_even()))
+ return 0;
+
+ BigInt x = mod, y = n, u = mod, v = n;
+ BigInt A = 1, B = 0, C = 0, D = 1;
+
+ while(u.is_nonzero())
+ {
+ u32bit zero_bits = low_zero_bits(u);
+ u >>= zero_bits;
+ for(u32bit i = 0; i != zero_bits; ++i)
+ {
+ if(A.is_odd() || B.is_odd())
+ { A += y; B -= x; }
+ A >>= 1; B >>= 1;
+ }
+
+ zero_bits = low_zero_bits(v);
+ v >>= zero_bits;
+ for(u32bit i = 0; i != zero_bits; ++i)
+ {
+ if(C.is_odd() || D.is_odd())
+ { C += y; D -= x; }
+ C >>= 1; D >>= 1;
+ }
+
+ if(u >= v) { u -= v; A -= C; B -= D; }
+ else { v -= u; C -= A; D -= B; }
+ }
+
+ if(v != 1)
+ return 0;
+
+ while(D.is_negative()) D += mod;
+ while(D >= mod) D -= mod;
+
+ return D;
+ }
+
+/*
+* Modular Exponentiation
+*/
+BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod)
+ {
+ Power_Mod pow_mod(mod);
+ pow_mod.set_base(base);
+ pow_mod.set_exponent(exp);
+ return pow_mod.execute();
+ }
+
+/*
+* Do simple tests of primality
+*/
+s32bit simple_primality_tests(const BigInt& n)
+ {
+ const s32bit NOT_PRIME = -1, UNKNOWN = 0, PRIME = 1;
+
+ if(n == 2)
+ return PRIME;
+ if(n <= 1 || n.is_even())
+ return NOT_PRIME;
+
+ if(n <= PRIMES[PRIME_TABLE_SIZE-1])
+ {
+ const word num = n.word_at(0);
+ for(u32bit i = 0; PRIMES[i]; ++i)
+ {
+ if(num == PRIMES[i]) return PRIME;
+ if(num < PRIMES[i]) return NOT_PRIME;
+ }
+ return NOT_PRIME;
+ }
+
+ u32bit check_first = std::min(n.bits() / 32, PRIME_PRODUCTS_TABLE_SIZE);
+ for(u32bit i = 0; i != check_first; ++i)
+ if(gcd(n, PRIME_PRODUCTS[i]) != 1)
+ return NOT_PRIME;
+
+ return UNKNOWN;
+ }
+
+/*
+* Fast check of primality
+*/
+bool check_prime(const BigInt& n, RandomNumberGenerator& rng)
+ {
+ return run_primality_tests(rng, n, 0);
+ }
+
+/*
+* Test for primality
+*/
+bool is_prime(const BigInt& n, RandomNumberGenerator& rng)
+ {
+ return run_primality_tests(rng, n, 1);
+ }
+
+/*
+* Verify primality
+*/
+bool verify_prime(const BigInt& n, RandomNumberGenerator& rng)
+ {
+ return run_primality_tests(rng, n, 2);
+ }
+
+/*
+* Verify primality
+*/
+bool run_primality_tests(RandomNumberGenerator& rng,
+ const BigInt& n, u32bit level)
+ {
+ s32bit simple_tests = simple_primality_tests(n);
+ if(simple_tests) return (simple_tests == 1) ? true : false;
+ return passes_mr_tests(rng, n, level);
+ }
+
+/*
+* Test for primaility using Miller-Rabin
+*/
+bool passes_mr_tests(RandomNumberGenerator& rng,
+ const BigInt& n, u32bit level)
+ {
+ const u32bit PREF_NONCE_BITS = 40;
+
+ if(level > 2)
+ level = 2;
+
+ MillerRabin_Test mr(n);
+
+ if(!mr.passes_test(2))
+ return false;
+
+ if(level == 0)
+ return true;
+
+ const u32bit NONCE_BITS = std::min(n.bits() - 1, PREF_NONCE_BITS);
+
+ const bool verify = (level == 2);
+
+ u32bit tests = miller_rabin_test_iterations(n.bits(), verify);
+
+ BigInt nonce;
+ for(u32bit i = 0; i != tests; ++i)
+ {
+ if(!verify && PRIMES[i] < (n-1))
+ nonce = PRIMES[i];
+ else
+ {
+ while(nonce < 2 || nonce >= (n-1))
+ nonce.randomize(rng, NONCE_BITS);
+ }
+
+ if(!mr.passes_test(nonce))
+ return false;
+ }
+ return true;
+ }
+
+/*
+* Miller-Rabin Test
+*/
+bool MillerRabin_Test::passes_test(const BigInt& a)
+ {
+ if(a < 2 || a >= n_minus_1)
+ throw Invalid_Argument("Bad size for nonce in Miller-Rabin test");
+
+ BigInt y = pow_mod(a);
+ if(y == 1 || y == n_minus_1)
+ return true;
+
+ for(u32bit i = 1; i != s; ++i)
+ {
+ y = reducer.square(y);
+
+ if(y == 1)
+ return false;
+ if(y == n_minus_1)
+ return true;
+ }
+ return false;
+ }
+
+/*
+* Miller-Rabin Constructor
+*/
+MillerRabin_Test::MillerRabin_Test(const BigInt& num)
+ {
+ if(num.is_even() || num < 3)
+ throw Invalid_Argument("MillerRabin_Test: Invalid number for testing");
+
+ n = num;
+ n_minus_1 = n - 1;
+ s = low_zero_bits(n_minus_1);
+ r = n_minus_1 >> s;
+
+ pow_mod = Fixed_Exponent_Power_Mod(r, n);
+ reducer = Modular_Reducer(n);
+ }
+
+}
diff --git a/botan/src/math/numbertheory/numthry.h b/botan/src/math/numbertheory/numthry.h
new file mode 100644
index 0000000..e4c0437
--- /dev/null
+++ b/botan/src/math/numbertheory/numthry.h
@@ -0,0 +1,120 @@
+/*
+* Number Theory Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NUMBER_THEORY_H__
+#define BOTAN_NUMBER_THEORY_H__
+
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Fused Arithmetic Operations
+*/
+BigInt BOTAN_DLL mul_add(const BigInt&, const BigInt&, const BigInt&);
+BigInt BOTAN_DLL sub_mul(const BigInt&, const BigInt&, const BigInt&);
+
+/*
+* Number Theory Functions
+*/
+inline BigInt abs(const BigInt& n) { return n.abs(); }
+
+void BOTAN_DLL divide(const BigInt&, const BigInt&, BigInt&, BigInt&);
+
+BigInt BOTAN_DLL gcd(const BigInt&, const BigInt&);
+BigInt BOTAN_DLL lcm(const BigInt&, const BigInt&);
+
+BigInt BOTAN_DLL square(const BigInt&);
+BigInt BOTAN_DLL inverse_mod(const BigInt&, const BigInt&);
+s32bit BOTAN_DLL jacobi(const BigInt&, const BigInt&);
+
+BigInt BOTAN_DLL power_mod(const BigInt&, const BigInt&, const BigInt&);
+
+/*
+* Compute the square root of x modulo a prime
+* using the Shanks-Tonnelli algorithm
+*/
+BigInt ressol(const BigInt& x, const BigInt& p);
+
+/*
+* Utility Functions
+*/
+u32bit BOTAN_DLL low_zero_bits(const BigInt&);
+
+/*
+* Primality Testing
+*/
+bool BOTAN_DLL check_prime(const BigInt&, RandomNumberGenerator&);
+bool BOTAN_DLL is_prime(const BigInt&, RandomNumberGenerator&);
+bool BOTAN_DLL verify_prime(const BigInt&, RandomNumberGenerator&);
+
+s32bit BOTAN_DLL simple_primality_tests(const BigInt&);
+
+bool BOTAN_DLL passes_mr_tests(RandomNumberGenerator&,
+ const BigInt&, u32bit = 1);
+
+bool BOTAN_DLL run_primality_tests(RandomNumberGenerator&,
+ const BigInt&, u32bit = 1);
+
+/*
+* Random Number Generation
+*/
+BigInt BOTAN_DLL random_prime(RandomNumberGenerator&,
+ u32bit bits, const BigInt& coprime = 1,
+ u32bit equiv = 1, u32bit equiv_mod = 2);
+
+BigInt BOTAN_DLL random_safe_prime(RandomNumberGenerator&,
+ u32bit);
+
+/*
+* DSA Parameter Generation
+*/
+class Algorithm_Factory;
+
+SecureVector<byte> BOTAN_DLL
+generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p, BigInt& q,
+ u32bit pbits, u32bit qbits);
+
+bool BOTAN_DLL
+generate_dsa_primes(RandomNumberGenerator& rng,
+ Algorithm_Factory& af,
+ BigInt& p_out, BigInt& q_out,
+ u32bit p_bits, u32bit q_bits,
+ const MemoryRegion<byte>& seed);
+
+/*
+* Prime Numbers
+*/
+const u32bit PRIME_TABLE_SIZE = 6541;
+const u32bit PRIME_PRODUCTS_TABLE_SIZE = 256;
+
+extern const u16bit BOTAN_DLL PRIMES[];
+extern const u64bit PRIME_PRODUCTS[];
+
+/*
+* Miller-Rabin Primality Tester
+*/
+class BOTAN_DLL MillerRabin_Test
+ {
+ public:
+ bool passes_test(const BigInt&);
+ MillerRabin_Test(const BigInt&);
+ private:
+ BigInt n, r, n_minus_1;
+ u32bit s;
+ Fixed_Exponent_Power_Mod pow_mod;
+ Modular_Reducer reducer;
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/numbertheory/pow_mod.cpp b/botan/src/math/numbertheory/pow_mod.cpp
new file mode 100644
index 0000000..fd9b8e9
--- /dev/null
+++ b/botan/src/math/numbertheory/pow_mod.cpp
@@ -0,0 +1,157 @@
+/*
+* Modular Exponentiation Proxy
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pow_mod.h>
+#include <botan/pk_engine.h>
+
+namespace Botan {
+
+/*
+* Power_Mod Constructor
+*/
+Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints)
+ {
+ core = 0;
+ set_modulus(n, hints);
+ }
+
+/*
+* Power_Mod Copy Constructor
+*/
+Power_Mod::Power_Mod(const Power_Mod& other)
+ {
+ core = 0;
+ if(other.core)
+ core = other.core->copy();
+ }
+
+/*
+* Power_Mod Assignment Operator
+*/
+Power_Mod& Power_Mod::operator=(const Power_Mod& other)
+ {
+ delete core;
+ core = 0;
+ if(other.core)
+ core = other.core->copy();
+ return (*this);
+ }
+
+/*
+* Power_Mod Destructor
+*/
+Power_Mod::~Power_Mod()
+ {
+ delete core;
+ }
+
+/*
+* Set the modulus
+*/
+void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const
+ {
+ delete core;
+ core = ((n == 0) ? 0 : Engine_Core::mod_exp(n, hints));
+ }
+
+/*
+* Set the base
+*/
+void Power_Mod::set_base(const BigInt& b) const
+ {
+ if(b.is_zero() || b.is_negative())
+ throw Invalid_Argument("Power_Mod::set_base: arg must be > 0");
+
+ if(!core)
+ throw Internal_Error("Power_Mod::set_base: core was NULL");
+ core->set_base(b);
+ }
+
+/*
+* Set the exponent
+*/
+void Power_Mod::set_exponent(const BigInt& e) const
+ {
+ if(e.is_negative())
+ throw Invalid_Argument("Power_Mod::set_exponent: arg must be > 0");
+
+ if(!core)
+ throw Internal_Error("Power_Mod::set_exponent: core was NULL");
+ core->set_exponent(e);
+ }
+
+/*
+* Compute the result
+*/
+BigInt Power_Mod::execute() const
+ {
+ if(!core)
+ throw Internal_Error("Power_Mod::execute: core was NULL");
+ return core->execute();
+ }
+
+namespace {
+
+/*
+* Choose potentially useful hints
+*/
+Power_Mod::Usage_Hints choose_base_hints(const BigInt& b, const BigInt& n)
+ {
+ if(b == 2)
+ return Power_Mod::Usage_Hints(Power_Mod::BASE_IS_2 |
+ Power_Mod::BASE_IS_SMALL);
+
+ const u32bit b_bits = b.bits();
+ const u32bit n_bits = n.bits();
+
+ if(b_bits < n_bits / 32)
+ return Power_Mod::BASE_IS_SMALL;
+ if(b_bits > n_bits / 4)
+ return Power_Mod::BASE_IS_LARGE;
+
+ return Power_Mod::NO_HINTS;
+ }
+
+/*
+* Choose potentially useful hints
+*/
+Power_Mod::Usage_Hints choose_exp_hints(const BigInt& e, const BigInt& n)
+ {
+ const u32bit e_bits = e.bits();
+ const u32bit n_bits = n.bits();
+
+ if(e_bits < n_bits / 32)
+ return Power_Mod::BASE_IS_SMALL;
+ if(e_bits > n_bits / 4)
+ return Power_Mod::BASE_IS_LARGE;
+ return Power_Mod::NO_HINTS;
+ }
+
+}
+
+/*
+* Fixed_Exponent_Power_Mod Constructor
+*/
+Fixed_Exponent_Power_Mod::Fixed_Exponent_Power_Mod(const BigInt& e,
+ const BigInt& n,
+ Usage_Hints hints) :
+ Power_Mod(n, Usage_Hints(hints | EXP_IS_FIXED | choose_exp_hints(e, n)))
+ {
+ set_exponent(e);
+ }
+
+/*
+* Fixed_Base_Power_Mod Constructor
+*/
+Fixed_Base_Power_Mod::Fixed_Base_Power_Mod(const BigInt& b, const BigInt& n,
+ Usage_Hints hints) :
+ Power_Mod(n, Usage_Hints(hints | BASE_IS_FIXED | choose_base_hints(b, n)))
+ {
+ set_base(b);
+ }
+
+}
diff --git a/botan/src/math/numbertheory/pow_mod.h b/botan/src/math/numbertheory/pow_mod.h
new file mode 100644
index 0000000..6952dcd
--- /dev/null
+++ b/botan/src/math/numbertheory/pow_mod.h
@@ -0,0 +1,93 @@
+/*
+* Modular Exponentiator
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POWER_MOD_H__
+#define BOTAN_POWER_MOD_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+/*
+* Modular Exponentiator Interface
+*/
+class BOTAN_DLL Modular_Exponentiator
+ {
+ public:
+ virtual void set_base(const BigInt&) = 0;
+ virtual void set_exponent(const BigInt&) = 0;
+ virtual BigInt execute() const = 0;
+ virtual Modular_Exponentiator* copy() const = 0;
+ virtual ~Modular_Exponentiator() {}
+ };
+
+/*
+* Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Power_Mod
+ {
+ public:
+ enum Usage_Hints {
+ NO_HINTS = 0x0000,
+
+ BASE_IS_FIXED = 0x0001,
+ BASE_IS_SMALL = 0x0002,
+ BASE_IS_LARGE = 0x0004,
+ BASE_IS_2 = 0x0008,
+
+ EXP_IS_FIXED = 0x0100,
+ EXP_IS_SMALL = 0x0200,
+ EXP_IS_LARGE = 0x0400
+ };
+
+ void set_modulus(const BigInt&, Usage_Hints = NO_HINTS) const;
+ void set_base(const BigInt&) const;
+ void set_exponent(const BigInt&) const;
+
+ BigInt execute() const;
+
+ Power_Mod& operator=(const Power_Mod&);
+
+ Power_Mod(const BigInt& = 0, Usage_Hints = NO_HINTS);
+ Power_Mod(const Power_Mod&);
+ ~Power_Mod();
+ private:
+ mutable Modular_Exponentiator* core;
+ Usage_Hints hints;
+ };
+
+/*
+* Fixed Exponent Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Fixed_Exponent_Power_Mod : public Power_Mod
+ {
+ public:
+ BigInt operator()(const BigInt& b) const
+ { set_base(b); return execute(); }
+
+ Fixed_Exponent_Power_Mod() {}
+ Fixed_Exponent_Power_Mod(const BigInt&, const BigInt&,
+ Usage_Hints = NO_HINTS);
+ };
+
+/*
+* Fixed Base Modular Exponentiator Proxy
+*/
+class BOTAN_DLL Fixed_Base_Power_Mod : public Power_Mod
+ {
+ public:
+ BigInt operator()(const BigInt& e) const
+ { set_exponent(e); return execute(); }
+
+ Fixed_Base_Power_Mod() {}
+ Fixed_Base_Power_Mod(const BigInt&, const BigInt&,
+ Usage_Hints = NO_HINTS);
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/numbertheory/powm_fw.cpp b/botan/src/math/numbertheory/powm_fw.cpp
new file mode 100644
index 0000000..b764ee7
--- /dev/null
+++ b/botan/src/math/numbertheory/powm_fw.cpp
@@ -0,0 +1,104 @@
+/*
+* Fixed Window Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_powm.h>
+#include <botan/numthry.h>
+#include <vector>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Try to choose a good window size
+*/
+u32bit choose_window_bits(u32bit exp_bits, u32bit,
+ Power_Mod::Usage_Hints hints)
+ {
+ static const u32bit wsize[][2] = {
+ { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 }
+ };
+
+ u32bit window_bits = 3;
+
+ if(exp_bits)
+ {
+ for(u32bit j = 0; wsize[j][0]; ++j)
+ {
+ if(exp_bits >= wsize[j][0])
+ {
+ window_bits += wsize[j][1];
+ break;
+ }
+ }
+ }
+
+ if(hints & Power_Mod::EXP_IS_FIXED)
+ window_bits += 2;
+ if(hints & Power_Mod::EXP_IS_LARGE)
+ window_bits += 2;
+ if(hints & Power_Mod::BASE_IS_FIXED)
+ ++window_bits;
+
+ return window_bits;
+ }
+
+}
+
+/*
+* Set the exponent
+*/
+void Fixed_Window_Exponentiator::set_exponent(const BigInt& e)
+ {
+ exp = e;
+ }
+
+/*
+* Set the base
+*/
+void Fixed_Window_Exponentiator::set_base(const BigInt& base)
+ {
+ window_bits = choose_window_bits(exp.bits(), base.bits(), hints);
+
+ g.resize((1 << window_bits) - 1);
+ g[0] = base;
+ for(u32bit j = 1; j != g.size(); ++j)
+ g[j] = reducer.multiply(g[j-1], g[0]);
+ }
+
+/*
+* Compute the result
+*/
+BigInt Fixed_Window_Exponentiator::execute() const
+ {
+ const u32bit exp_nibbles = (exp.bits() + window_bits - 1) / window_bits;
+
+ BigInt x = 1;
+ for(u32bit j = exp_nibbles; j > 0; --j)
+ {
+ for(u32bit k = 0; k != window_bits; ++k)
+ x = reducer.square(x);
+
+ u32bit nibble = exp.get_substring(window_bits*(j-1), window_bits);
+ if(nibble)
+ x = reducer.multiply(x, g[nibble-1]);
+ }
+ return x;
+ }
+
+/*
+* Fixed_Window_Exponentiator Constructor
+*/
+Fixed_Window_Exponentiator::Fixed_Window_Exponentiator(const BigInt& n,
+ Power_Mod::Usage_Hints hints)
+ {
+ reducer = Modular_Reducer(n);
+ this->hints = hints;
+ window_bits = 0;
+ }
+
+}
diff --git a/botan/src/math/numbertheory/powm_mnt.cpp b/botan/src/math/numbertheory/powm_mnt.cpp
new file mode 100644
index 0000000..e6d8cc3
--- /dev/null
+++ b/botan/src/math/numbertheory/powm_mnt.cpp
@@ -0,0 +1,180 @@
+/*
+* Montgomery Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/def_powm.h>
+#include <botan/numthry.h>
+#include <botan/mp_core.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Try to choose a good window size
+*/
+u32bit choose_window_bits(u32bit exp_bits, u32bit,
+ Power_Mod::Usage_Hints hints)
+ {
+ static const u32bit wsize[][2] = {
+ { 2048, 4 }, { 1024, 3 }, { 256, 2 }, { 128, 1 }, { 0, 0 }
+ };
+
+ u32bit window_bits = 1;
+
+ if(exp_bits)
+ {
+ for(u32bit j = 0; wsize[j][0]; ++j)
+ {
+ if(exp_bits >= wsize[j][0])
+ {
+ window_bits += wsize[j][1];
+ break;
+ }
+ }
+ }
+
+ if(hints & Power_Mod::BASE_IS_FIXED)
+ window_bits += 2;
+ if(hints & Power_Mod::EXP_IS_LARGE)
+ ++window_bits;
+
+ return window_bits;
+ }
+
+/*
+* Montgomery Reduction
+*/
+inline void montgomery_reduce(BigInt& out, MemoryRegion<word>& z_buf,
+ const BigInt& x_bn, u32bit x_size, word u)
+ {
+ const word* x = x_bn.data();
+ word* z = z_buf.begin();
+ u32bit z_size = z_buf.size();
+
+ bigint_monty_redc(z, z_size, x, x_size, u);
+
+ out.get_reg().set(z + x_size, x_size + 1);
+ }
+
+}
+
+/*
+* Set the exponent
+*/
+void Montgomery_Exponentiator::set_exponent(const BigInt& exp)
+ {
+ this->exp = exp;
+ exp_bits = exp.bits();
+ }
+
+/*
+* Set the base
+*/
+void Montgomery_Exponentiator::set_base(const BigInt& base)
+ {
+ window_bits = choose_window_bits(exp.bits(), base.bits(), hints);
+
+ g.resize((1 << window_bits) - 1);
+
+ SecureVector<word> z(2 * (mod_words + 1));
+ SecureVector<word> workspace(z.size());
+
+ g[0] = (base >= modulus) ? (base % modulus) : base;
+ bigint_mul(z.begin(), z.size(), workspace,
+ g[0].data(), g[0].size(), g[0].sig_words(),
+ R2.data(), R2.size(), R2.sig_words());
+
+ montgomery_reduce(g[0], z, modulus, mod_words, mod_prime);
+
+ const BigInt& x = g[0];
+ const u32bit x_sig = x.sig_words();
+
+ for(u32bit j = 1; j != g.size(); ++j)
+ {
+ const BigInt& y = g[j-1];
+ const u32bit y_sig = y.sig_words();
+
+ z.clear();
+ bigint_mul(z.begin(), z.size(), workspace,
+ x.data(), x.size(), x_sig,
+ y.data(), y.size(), y_sig);
+
+ montgomery_reduce(g[j], z, modulus, mod_words, mod_prime);
+ }
+ }
+
+/*
+* Compute the result
+*/
+BigInt Montgomery_Exponentiator::execute() const
+ {
+ const u32bit exp_nibbles = (exp_bits + window_bits - 1) / window_bits;
+
+ BigInt x = R_mod;
+ SecureVector<word> z(2 * (mod_words + 1));
+ SecureVector<word> workspace(2 * (mod_words + 1));
+
+ for(u32bit j = exp_nibbles; j > 0; --j)
+ {
+ for(u32bit k = 0; k != window_bits; ++k)
+ {
+ z.clear();
+ bigint_sqr(z.begin(), z.size(), workspace,
+ x.data(), x.size(), x.sig_words());
+
+ montgomery_reduce(x, z, modulus, mod_words, mod_prime);
+ }
+
+ u32bit nibble = exp.get_substring(window_bits*(j-1), window_bits);
+ if(nibble)
+ {
+ const BigInt& y = g[nibble-1];
+
+ z.clear();
+ bigint_mul(z.begin(), z.size(), workspace,
+ x.data(), x.size(), x.sig_words(),
+ y.data(), y.size(), y.sig_words());
+
+ montgomery_reduce(x, z, modulus, mod_words, mod_prime);
+ }
+ }
+
+ z.clear();
+ z.copy(x.data(), x.size());
+
+ montgomery_reduce(x, z, modulus, mod_words, mod_prime);
+ return x;
+ }
+
+/*
+* Montgomery_Exponentiator Constructor
+*/
+Montgomery_Exponentiator::Montgomery_Exponentiator(const BigInt& mod,
+ Power_Mod::Usage_Hints hints)
+ {
+ if(!mod.is_positive())
+ throw Exception("Montgomery_Exponentiator: modulus must be positive");
+ if(mod.is_even())
+ throw Exception("Montgomery_Exponentiator: modulus must be odd");
+
+ window_bits = 0;
+ this->hints = hints;
+ modulus = mod;
+
+ mod_words = modulus.sig_words();
+
+ BigInt mod_prime_bn(BigInt::Power2, MP_WORD_BITS);
+ mod_prime = (mod_prime_bn - inverse_mod(modulus, mod_prime_bn)).word_at(0);
+
+ R_mod = BigInt(BigInt::Power2, MP_WORD_BITS * mod_words);
+ R_mod %= modulus;
+
+ R2 = BigInt(BigInt::Power2, 2 * MP_WORD_BITS * mod_words);
+ R2 %= modulus;
+ }
+
+}
diff --git a/botan/src/math/numbertheory/primes.cpp b/botan/src/math/numbertheory/primes.cpp
new file mode 100644
index 0000000..a9c8ab5
--- /dev/null
+++ b/botan/src/math/numbertheory/primes.cpp
@@ -0,0 +1,676 @@
+/*
+* Small Primes Table
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+
+namespace Botan {
+
+const u16bit PRIMES[PRIME_TABLE_SIZE+1] = {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
+ 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
+ 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
+ 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197,
+ 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
+ 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
+ 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397,
+ 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
+ 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673,
+ 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+ 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
+ 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
+ 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
+ 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051,
+ 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123,
+ 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217,
+ 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
+ 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
+ 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543,
+ 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
+ 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697,
+ 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783,
+ 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873,
+ 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
+ 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039,
+ 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
+ 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221,
+ 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
+ 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381,
+ 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459,
+ 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557,
+ 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663,
+ 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719,
+ 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
+ 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897,
+ 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083,
+ 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191,
+ 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299,
+ 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361,
+ 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463,
+ 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
+ 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623,
+ 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
+ 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803,
+ 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
+ 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001,
+ 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079,
+ 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159,
+ 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
+ 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357,
+ 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
+ 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549,
+ 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
+ 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733,
+ 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
+ 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943,
+ 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
+ 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107,
+ 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227,
+ 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323,
+ 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419,
+ 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503,
+ 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591,
+ 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689,
+ 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
+ 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861,
+ 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981,
+ 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079,
+ 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173,
+ 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269,
+ 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343,
+ 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449,
+ 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
+ 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661,
+ 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
+ 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841,
+ 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949,
+ 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019,
+ 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129,
+ 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237,
+ 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
+ 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481,
+ 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549,
+ 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639,
+ 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841,
+ 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933,
+ 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059,
+ 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
+ 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243,
+ 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353,
+ 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447,
+ 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573,
+ 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669,
+ 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
+ 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837,
+ 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941,
+ 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041,
+ 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151,
+ 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239,
+ 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341,
+ 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431,
+ 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511,
+ 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629,
+ 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
+ 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817,
+ 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907,
+ 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039,
+10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139,
+10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, 10243,
+10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321,
+10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433,
+10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531,
+10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651,
+10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
+10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861,
+10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973,
+10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, 11083,
+11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, 11173,
+11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, 11287,
+11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399,
+11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, 11497,
+11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621,
+11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743,
+11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
+11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939,
+11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041,
+12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, 12143,
+12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251,
+12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347,
+12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, 12451,
+12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, 12539,
+12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619,
+12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721,
+12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
+12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941,
+12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033,
+13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147,
+13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241,
+13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, 13339,
+13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, 13463,
+13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, 13591,
+13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691,
+13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763,
+13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
+13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997,
+13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087,
+14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243,
+14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369,
+14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449,
+14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557,
+14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, 14657,
+14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
+14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843,
+14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
+14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077,
+15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173,
+15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, 15271,
+15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359,
+15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451,
+15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569,
+15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661,
+15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761,
+15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877,
+15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
+15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073,
+16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, 16189,
+16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, 16319,
+16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427,
+16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, 16547,
+16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651,
+16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759,
+16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889,
+16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987,
+16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
+17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203,
+17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327,
+17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, 17417,
+17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, 17497,
+17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609,
+17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, 17737,
+17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, 17851,
+17863, 17881, 17891, 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957,
+17959, 17971, 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049,
+18059, 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
+18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251,
+18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, 18341,
+18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, 18439, 18443,
+18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541,
+18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, 18691, 18701,
+18713, 18719, 18731, 18743, 18749, 18757, 18773, 18787, 18793, 18797, 18803,
+18839, 18859, 18869, 18899, 18911, 18913, 18917, 18919, 18947, 18959, 18973,
+18979, 19001, 19009, 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081,
+19087, 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213,
+19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
+19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427,
+19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, 19489,
+19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597,
+19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, 19727, 19739,
+19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843,
+19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961,
+19963, 19973, 19979, 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047,
+20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143,
+20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249,
+20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
+20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477,
+20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593,
+20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, 20717, 20719,
+20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, 20789, 20807, 20809,
+20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, 20929, 20939,
+20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023,
+21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149,
+21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247,
+21269, 21277, 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379,
+21383, 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
+21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569,
+21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, 21661,
+21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773,
+21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871,
+21881, 21893, 21911, 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003,
+22013, 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, 22091,
+22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, 22157, 22159, 22171,
+22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291,
+22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433,
+22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
+22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651,
+22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, 22741,
+22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, 22859, 22861,
+22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993,
+23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, 23059,
+23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173,
+23189, 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293,
+23297, 23311, 23321, 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417,
+23431, 23447, 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557,
+23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
+23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747,
+23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833,
+23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929,
+23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043,
+24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, 24107, 24109, 24113,
+24121, 24133, 24137, 24151, 24169, 24179, 24181, 24197, 24203, 24223, 24229,
+24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, 24371, 24373, 24379,
+24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499,
+24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631,
+24659, 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
+24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889,
+24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989,
+25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, 25121,
+25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, 25229, 25237,
+25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343,
+25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453,
+25457, 25463, 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583,
+25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673,
+25679, 25693, 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793,
+25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
+25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003,
+26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119,
+26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237,
+26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339,
+26347, 26357, 26371, 26387, 26393, 26399, 26407, 26417, 26423, 26431, 26437,
+26449, 26459, 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573,
+26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, 26687, 26693,
+26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777,
+26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881,
+26891, 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
+26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091,
+27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, 27241,
+27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, 27361, 27367,
+27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, 27487,
+27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631,
+27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743,
+27749, 27751, 27763, 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809,
+27817, 27823, 27827, 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941,
+27943, 27947, 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031,
+28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
+28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289,
+28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411,
+28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537,
+28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607,
+28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, 28669, 28687,
+28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, 28771, 28789, 28793,
+28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, 28909,
+28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027,
+29033, 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153,
+29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
+29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383,
+29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, 29473,
+29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599,
+29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741,
+29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867,
+29873, 29879, 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011,
+30013, 30029, 30047, 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113,
+30119, 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211,
+30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323,
+30341, 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
+30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577,
+30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703,
+30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, 30817, 30829,
+30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, 30893, 30911, 30931,
+30937, 30941, 30949, 30971, 30977, 30983, 31013, 31019, 31033, 31039, 31051,
+31063, 31069, 31079, 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153,
+31159, 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, 31247,
+31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333,
+31337, 31357, 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489,
+31511, 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
+31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723,
+31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, 31849,
+31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, 31991, 32003,
+32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, 32077, 32083, 32089,
+32099, 32117, 32119, 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203,
+32213, 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, 32321,
+32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, 32377, 32381, 32401,
+32411, 32413, 32423, 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503,
+32507, 32531, 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603,
+32609, 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
+32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 32833,
+32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 32941, 32957,
+32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 33029, 33037, 33049,
+33053, 33071, 33073, 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161,
+33179, 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289, 33301,
+33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353, 33359, 33377, 33391,
+33403, 33409, 33413, 33427, 33457, 33461, 33469, 33479, 33487, 33493, 33503,
+33521, 33529, 33533, 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599,
+33601, 33613, 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703,
+33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
+33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 33911,
+33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 34033, 34039,
+34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183,
+34211, 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283, 34297,
+34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361, 34367, 34369, 34381,
+34403, 34421, 34429, 34439, 34457, 34469, 34471, 34483, 34487, 34499, 34501,
+34511, 34513, 34519, 34537, 34543, 34549, 34583, 34589, 34591, 34603, 34607,
+34613, 34631, 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721,
+34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843,
+34847, 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
+34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 35089,
+35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201,
+35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317, 35323,
+35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, 35419, 35423, 35437,
+35447, 35449, 35461, 35491, 35507, 35509, 35521, 35527, 35531, 35533, 35537,
+35543, 35569, 35573, 35591, 35593, 35597, 35603, 35617, 35671, 35677, 35729,
+35731, 35747, 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837,
+35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951,
+35963, 35969, 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037,
+36061, 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
+36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293,
+36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, 36433,
+36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 36523, 36527, 36529,
+36541, 36551, 36559, 36563, 36571, 36583, 36587, 36599, 36607, 36629, 36637,
+36643, 36653, 36671, 36677, 36683, 36691, 36697, 36709, 36713, 36721, 36739,
+36749, 36761, 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833,
+36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919, 36923, 36929,
+36931, 36943, 36947, 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039,
+37049, 37057, 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181,
+37189, 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
+37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 37409,
+37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 37511, 37517,
+37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 37579, 37589, 37591,
+37607, 37619, 37633, 37643, 37649, 37657, 37663, 37691, 37693, 37699, 37717,
+37747, 37781, 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871,
+37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987, 37991, 37993,
+37997, 38011, 38039, 38047, 38053, 38069, 38083, 38113, 38119, 38149, 38153,
+38167, 38177, 38183, 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261,
+38273, 38281, 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351,
+38371, 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
+38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 38651,
+38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 38723, 38729,
+38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 38833, 38839, 38851,
+38861, 38867, 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959,
+38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079, 39089, 39097,
+39103, 39107, 39113, 39119, 39133, 39139, 39157, 39161, 39163, 39181, 39191,
+39199, 39209, 39217, 39227, 39229, 39233, 39239, 39241, 39251, 39293, 39301,
+39313, 39317, 39323, 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397,
+39409, 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521,
+39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
+39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 39779,
+39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 39863, 39869,
+39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989,
+40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099, 40111, 40123,
+40127, 40129, 40151, 40153, 40163, 40169, 40177, 40189, 40193, 40213, 40231,
+40237, 40241, 40253, 40277, 40283, 40289, 40343, 40351, 40357, 40361, 40387,
+40423, 40427, 40429, 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507,
+40519, 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627,
+40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771,
+40787, 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
+40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 40993,
+41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117,
+41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, 41201, 41203,
+41213, 41221, 41227, 41231, 41233, 41243, 41257, 41263, 41269, 41281, 41299,
+41333, 41341, 41351, 41357, 41381, 41387, 41389, 41399, 41411, 41413, 41443,
+41453, 41467, 41479, 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549,
+41579, 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641, 41647,
+41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771,
+41777, 41801, 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893,
+41897, 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
+41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083,
+42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 42193, 42197,
+42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 42293, 42299, 42307,
+42323, 42331, 42337, 42349, 42359, 42373, 42379, 42391, 42397, 42403, 42407,
+42409, 42433, 42437, 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487,
+42491, 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611, 42641,
+42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701, 42703, 42709, 42719,
+42727, 42737, 42743, 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829,
+42839, 42841, 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943,
+42953, 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
+43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 43201,
+43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 43321, 43331,
+43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 43457, 43481, 43487,
+43499, 43517, 43541, 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609,
+43613, 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717, 43721,
+43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793, 43801, 43853, 43867,
+43889, 43891, 43913, 43933, 43943, 43951, 43961, 43963, 43969, 43973, 43987,
+43991, 43997, 44017, 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087,
+44089, 44101, 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189,
+44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
+44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 44453,
+44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 44543, 44549,
+44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657,
+44683, 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773, 44777,
+44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867, 44879, 44887, 44893,
+44909, 44917, 44927, 44939, 44953, 44959, 44963, 44971, 44983, 44987, 45007,
+45013, 45053, 45061, 45077, 45083, 45119, 45121, 45127, 45131, 45137, 45139,
+45161, 45179, 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289,
+45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389,
+45403, 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
+45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 45659,
+45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767,
+45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869, 45887,
+45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, 46021, 46027, 46049,
+46051, 46061, 46073, 46091, 46093, 46099, 46103, 46133, 46141, 46147, 46153,
+46171, 46181, 46183, 46187, 46199, 46219, 46229, 46237, 46261, 46271, 46273,
+46279, 46301, 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411,
+46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511,
+46523, 46549, 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639,
+46643, 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
+46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853,
+46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, 47017,
+47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 47123, 47129, 47137,
+47143, 47147, 47149, 47161, 47189, 47207, 47221, 47237, 47251, 47269, 47279,
+47287, 47293, 47297, 47303, 47309, 47317, 47339, 47351, 47353, 47363, 47381,
+47387, 47389, 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501,
+47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581, 47591, 47599,
+47609, 47623, 47629, 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711,
+47713, 47717, 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809,
+47819, 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
+47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 48073,
+48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 48187, 48193,
+48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 48311, 48313, 48337,
+48341, 48353, 48371, 48383, 48397, 48407, 48409, 48413, 48437, 48449, 48463,
+48473, 48479, 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541,
+48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649, 48661, 48673,
+48677, 48679, 48731, 48733, 48751, 48757, 48761, 48767, 48779, 48781, 48787,
+48799, 48809, 48817, 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883,
+48889, 48907, 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031,
+49033, 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
+49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 49223,
+49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 49363, 49367,
+49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 49451, 49459, 49463,
+49477, 49481, 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597,
+49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681, 49697, 49711,
+49727, 49739, 49741, 49747, 49757, 49783, 49787, 49789, 49801, 49807, 49811,
+49823, 49831, 49843, 49853, 49871, 49877, 49891, 49919, 49921, 49927, 49937,
+49939, 49943, 49957, 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051,
+50053, 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131,
+50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273,
+50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 50383,
+50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 50513, 50527,
+50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647,
+50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773, 50777, 50789,
+50821, 50833, 50839, 50849, 50857, 50867, 50873, 50891, 50893, 50909, 50923,
+50929, 50951, 50957, 50969, 50971, 50989, 50993, 51001, 51031, 51043, 51047,
+51059, 51061, 51071, 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193,
+51197, 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287,
+51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419,
+51421, 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487,
+51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 51599,
+51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713,
+51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, 51827, 51829,
+51839, 51853, 51859, 51869, 51871, 51893, 51899, 51907, 51913, 51929, 51941,
+51949, 51971, 51973, 51977, 51991, 52009, 52021, 52027, 52051, 52057, 52067,
+52069, 52081, 52103, 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183,
+52189, 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291, 52301,
+52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457,
+52489, 52501, 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571,
+52579, 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709,
+52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817,
+52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 52937, 52951,
+52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 53047, 53051, 53069,
+53077, 53087, 53089, 53093, 53101, 53113, 53117, 53129, 53147, 53149, 53161,
+53171, 53173, 53189, 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279,
+53281, 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401, 53407,
+53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507, 53527, 53549, 53551,
+53569, 53591, 53593, 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639,
+53653, 53657, 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777,
+53783, 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
+53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 54001,
+54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 54133, 54139,
+54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 54277, 54287, 54293,
+54311, 54319, 54323, 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403,
+54409, 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497, 54499,
+54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563, 54577, 54581, 54583,
+54601, 54617, 54623, 54629, 54631, 54647, 54667, 54673, 54679, 54709, 54713,
+54721, 54727, 54751, 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851,
+54869, 54877, 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979,
+54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103,
+55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 55219,
+55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 55339, 55343,
+55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501,
+55511, 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621, 55631,
+55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691, 55697, 55711, 55717,
+55721, 55733, 55763, 55787, 55793, 55799, 55807, 55813, 55817, 55819, 55823,
+55829, 55837, 55843, 55849, 55871, 55889, 55897, 55901, 55903, 55921, 55927,
+55931, 55933, 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053,
+56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171,
+56179, 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299,
+56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 56437,
+56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519,
+56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629, 56633,
+56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, 56731, 56737, 56747,
+56767, 56773, 56779, 56783, 56807, 56809, 56813, 56821, 56827, 56843, 56857,
+56873, 56891, 56893, 56897, 56909, 56911, 56921, 56923, 56929, 56941, 56951,
+56957, 56963, 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073,
+57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173,
+57179, 57191, 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271,
+57283, 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389,
+57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557,
+57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, 57679,
+57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 57751, 57773, 57781,
+57787, 57791, 57793, 57803, 57809, 57829, 57839, 57847, 57853, 57859, 57881,
+57899, 57901, 57917, 57923, 57943, 57947, 57973, 57977, 57991, 58013, 58027,
+58031, 58043, 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129,
+58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207, 58211, 58217,
+58229, 58231, 58237, 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367,
+58369, 58379, 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451,
+58453, 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601,
+58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 58727,
+58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 58897, 58901,
+58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 58979, 58991, 58997,
+59009, 59011, 59021, 59023, 59029, 59051, 59053, 59063, 59069, 59077, 59083,
+59093, 59107, 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197,
+59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273, 59281, 59333,
+59341, 59351, 59357, 59359, 59369, 59377, 59387, 59393, 59399, 59407, 59417,
+59419, 59441, 59443, 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513,
+59539, 59557, 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651,
+59659, 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747,
+59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 59921,
+59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 60037, 60041,
+60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 60133, 60139, 60149,
+60161, 60167, 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289,
+60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397, 60413, 60427,
+60443, 60449, 60457, 60493, 60497, 60509, 60521, 60527, 60539, 60589, 60601,
+60607, 60611, 60617, 60623, 60631, 60637, 60647, 60649, 60659, 60661, 60679,
+60689, 60703, 60719, 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779,
+60793, 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917,
+60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043,
+61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 61211,
+61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 61339, 61343,
+61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471,
+61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553, 61559, 61561,
+61583, 61603, 61609, 61613, 61627, 61631, 61637, 61643, 61651, 61657, 61667,
+61673, 61681, 61687, 61703, 61717, 61723, 61729, 61751, 61757, 61781, 61813,
+61819, 61837, 61843, 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961,
+61967, 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053,
+62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171,
+62189, 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303,
+62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 62467,
+62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581,
+62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, 62683, 62687,
+62701, 62723, 62731, 62743, 62753, 62761, 62773, 62791, 62801, 62819, 62827,
+62851, 62861, 62869, 62873, 62897, 62903, 62921, 62927, 62929, 62939, 62969,
+62971, 62981, 62983, 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079,
+63097, 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211, 63241,
+63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353,
+63361, 63367, 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443,
+63463, 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559,
+63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649,
+63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 63727, 63737,
+63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 63823, 63839, 63841,
+63853, 63857, 63863, 63901, 63907, 63913, 63929, 63949, 63977, 63997, 64007,
+64013, 64019, 64033, 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151,
+64153, 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271, 64279,
+64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381, 64399, 64403, 64433,
+64439, 64451, 64453, 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579,
+64591, 64601, 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679,
+64693, 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
+64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 64951,
+64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 65071, 65089,
+65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 65167, 65171, 65173,
+65179, 65183, 65203, 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309,
+65323, 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419, 65423,
+65437, 65447, 65449, 65479, 65497, 65519, 65521, 0 };
+
+const u64bit PRIME_PRODUCTS[PRIME_PRODUCTS_TABLE_SIZE] = {
+(u64bit) 0xFF658BDE2F2A43DFULL, (u64bit) 0xFEEB94CD535119EDULL, (u64bit) 0xFA921839EC24DDD5ULL, (u64bit) 0xFDDA766C77E1E605ULL,
+(u64bit) 0xFF3024B0EB4EE333ULL, (u64bit) 0xFEEE350BBC92F4DFULL, (u64bit) 0xFFC724B7D011D01BULL, (u64bit) 0xFEED34B826C33B05ULL,
+(u64bit) 0xFE69D8DE3F85C6E3ULL, (u64bit) 0xFE3B48909250918FULL, (u64bit) 0xFF8EC0CE9C632429ULL, (u64bit) 0xFFD92A5C78226D6BULL,
+(u64bit) 0xFFB4BFB0C65133CFULL, (u64bit) 0xFE77113704902C57ULL, (u64bit) 0xFF8A21D222EA81FDULL, (u64bit) 0xFEDA1299661CF5ABULL,
+(u64bit) 0xFF4CE86187737D0DULL, (u64bit) 0xFFD26443A07F519DULL, (u64bit) 0xFFA817B7191D7967ULL, (u64bit) 0xFF00EDC142868873ULL,
+(u64bit) 0xFFB9C6D7F7A239B7ULL, (u64bit) 0xFFE76D3481E98E39ULL, (u64bit) 0xFF76D5432584120DULL, (u64bit) 0xFFAA499F071EC705ULL,
+(u64bit) 0xFEB5198F05722E59ULL, (u64bit) 0xFF7E0431CA41107FULL, (u64bit) 0xFFCFD52FEDDC928FULL, (u64bit) 0xFE0EA42537BC6ABFULL,
+(u64bit) 0xFF64937896876925ULL, (u64bit) 0xFC6FC87E811607D3ULL, (u64bit) 0xFFBF600E6CDD0F4FULL, (u64bit) 0xFF022700FE658243ULL,
+(u64bit) 0xFF2E21166779D6B9ULL, (u64bit) 0xFFC224624C665C33ULL, (u64bit) 0xFF1372F41FF177ADULL, (u64bit) 0xFF31E57E972D0C13ULL,
+(u64bit) 0xFFA891F866404D23ULL, (u64bit) 0xFF7BF13EF716E9A3ULL, (u64bit) 0xFE51CAFD9466E733ULL, (u64bit) 0xFDA1CF55F6D6336FULL,
+(u64bit) 0xFFAF6C040ED0950FULL, (u64bit) 0xFFAA1725F40BA269ULL, (u64bit) 0xFEC593BC3570BEEBULL, (u64bit) 0xFEE05B35B426F413ULL,
+(u64bit) 0xFFCA5209A08890F9ULL, (u64bit) 0xFFED8AF70EB0CC89ULL, (u64bit) 0xFF3F98E3E27860A5ULL, (u64bit) 0xFF92FECD017FF9F7ULL,
+(u64bit) 0xFEFA655B2609018FULL, (u64bit) 0xFFFC51D15AAC7B77ULL, (u64bit) 0xFEF5007E71420DB1ULL, (u64bit) 0xFFEC4784141332D1ULL,
+(u64bit) 0xFE8384ED4E1D21CDULL, (u64bit) 0xFFD3FF614D3ECC47ULL, (u64bit) 0xFFDE5166FD540313ULL, (u64bit) 0xFF5320ECED04B26FULL,
+(u64bit) 0xFF223980F122FF75ULL, (u64bit) 0xFF19C1F27CB1B4A5ULL, (u64bit) 0xFF0F1DFC9DA9523BULL, (u64bit) 0xFF82DE7B387F5427ULL,
+(u64bit) 0xFF9A026BA87314E3ULL, (u64bit) 0xFFAC7FF3ACE64E77ULL, (u64bit) 0xFF808EB2FD5873C3ULL, (u64bit) 0xFE983ED5BB363301ULL,
+(u64bit) 0xFF714856DB2CFE95ULL, (u64bit) 0xFF84E1510CF3EB9FULL, (u64bit) 0xFF29D04C1DA0B115ULL, (u64bit) 0xFFBCF3BF9433552FULL,
+(u64bit) 0xFF32203D58A4C473ULL, (u64bit) 0xFFF00910A15021C3ULL, (u64bit) 0xFDE93041F28240ADULL, (u64bit) 0xFFC518BCD81C03C5ULL,
+(u64bit) 0xFEF504CD8BB9CBDDULL, (u64bit) 0xFEB8FFBFFF116A6BULL, (u64bit) 0xFF7642E0785ADA23ULL, (u64bit) 0xFFECF068800FD50DULL,
+(u64bit) 0xFFD703577CA247A7ULL, (u64bit) 0xFF54C0ECAD2C9691ULL, (u64bit) 0xFFC031706B8C72F5ULL, (u64bit) 0xFFE59E5CA58BBDF5ULL,
+(u64bit) 0xFFF31FAFFD3B331DULL, (u64bit) 0xFF64DDF32349FF6DULL, (u64bit) 0xFFE38309D0BD4A51ULL, (u64bit) 0xFF8C934F76B3C737ULL,
+(u64bit) 0xFFDC80B4BAEAFC1FULL, (u64bit) 0xFFCC1FE4C856FBD9ULL, (u64bit) 0xFFDB5976DDF601FDULL, (u64bit) 0xFFD3DD25F424433DULL,
+(u64bit) 0xFFC00FA367E746C7ULL, (u64bit) 0xFFE08BF011CC854FULL, (u64bit) 0xFFC3F21982468F6DULL, (u64bit) 0xFFDA6C52478A76DFULL,
+(u64bit) 0xFFC67D95AADED363ULL, (u64bit) 0xFFD605D18C3AFC65ULL, (u64bit) 0xFFE828C9D698F1DFULL, (u64bit) 0xFFBE5098D83B7737ULL,
+(u64bit) 0xFF79EB34474ABFB9ULL, (u64bit) 0xFFD27AEED0786363ULL, (u64bit) 0xFFD0FE27B77C271FULL, (u64bit) 0xFFFBB6563BD065EFULL,
+(u64bit) 0xFFF3638F8635E1EBULL, (u64bit) 0xFFBE862C22C9F065ULL, (u64bit) 0xFF44712D8488A01DULL, (u64bit) 0xFF7EEC97F9913111ULL,
+(u64bit) 0xFFC23CC78CB12AB1ULL, (u64bit) 0xFFF390FE85F81D3DULL, (u64bit) 0xFFE8EA21A0FB9931ULL, (u64bit) 0xFFB9D42D17A93385ULL,
+(u64bit) 0xFFCDB63AB21E904DULL, (u64bit) 0xFF5EB7F2210D33DFULL, (u64bit) 0xFFE6F6C7BB60C9DFULL, (u64bit) 0xFFAD4CA8DC26D699ULL,
+(u64bit) 0xFF7BE75BD21DCA51ULL, (u64bit) 0xFEF89CE23CB61789ULL, (u64bit) 0xFF40ECA3CCA22CE5ULL, (u64bit) 0xF52BDF080F7ABA6FULL,
+(u64bit) 0xEC8F38C8B28E0493ULL, (u64bit) 0xE68E732A2ABED62FULL, (u64bit) 0xE21A13779E0CCDC7ULL, (u64bit) 0xD823C075C325191BULL,
+(u64bit) 0xD1B284C91EED248BULL, (u64bit) 0xCBA5A08068E8C1F7ULL, (u64bit) 0xC483EE5A2228985DULL, (u64bit) 0xBCAEE9F787AC75EBULL,
+(u64bit) 0xB782DAB1B77D3E09ULL, (u64bit) 0xB0D77226F15E387BULL, (u64bit) 0xAA2A8727D47941CDULL, (u64bit) 0xA4A45682E9CE533DULL,
+(u64bit) 0x9CAF15AF4CE7FCF7ULL, (u64bit) 0x94C051DD15537305ULL, (u64bit) 0x9006D2FBD933A297ULL, (u64bit) 0x8C4DED05F19B7399ULL,
+(u64bit) 0x884FD7A270AD1B1BULL, (u64bit) 0x83C687D33F238D4BULL, (u64bit) 0xFF62E2BAE50C6C16ULL, (u64bit) 0x7A59E1FD9D203DBBULL,
+(u64bit) 0x764F1DC07B0E442DULL, (u64bit) 0x72732FE1F2023153ULL, (u64bit) 0x6E373B550764872FULL, (u64bit) 0x680FFFD267C5F3FFULL,
+(u64bit) 0x6206BFEC14F1CFC5ULL, (u64bit) 0x5FA6F70CFD587265ULL, (u64bit) 0x5CC7A1B4F6DF9823ULL, (u64bit) 0x599291B29311407FULL,
+(u64bit) 0xFF3CEBD359B67EF9ULL, (u64bit) 0x51C573C14F289F6DULL, (u64bit) 0x4FA265B31B73C6DFULL, (u64bit) 0x4B3154ACBD077DEDULL,
+(u64bit) 0x4785C96B29A1E437ULL, (u64bit) 0x451F887F646CF763ULL, (u64bit) 0x429DC254C5490571ULL, (u64bit) 0x408410840EAE2883ULL,
+(u64bit) 0x3E12CC83606624F3ULL, (u64bit) 0x3A70D774B821DA71ULL, (u64bit) 0x37A21449A196A825ULL, (u64bit) 0x34C5D056E2278B81ULL,
+(u64bit) 0xFA0C6CAB29D8E297ULL, (u64bit) 0x2FA5AEC982A5972BULL, (u64bit) 0x2D6831749426068FULL, (u64bit) 0x2B7F876418155CA7ULL,
+(u64bit) 0x2A1B897ED2AB433DULL, (u64bit) 0x28C9430D0F92132FULL, (u64bit) 0x26DF879EBF12E103ULL, (u64bit) 0xFD2FAB4CA364D43BULL,
+(u64bit) 0x22B5B4FC40D4C35FULL, (u64bit) 0x209298AA84D7E6A1ULL, (u64bit) 0x1ED4B9F11445F1E7ULL, (u64bit) 0x1DC6D2DD416CC91DULL,
+(u64bit) 0x1C1517A52E37C3EFULL, (u64bit) 0x1A808916125AEF2FULL, (u64bit) 0x197A2FB2938FF13DULL, (u64bit) 0x1814AA6C087B561DULL,
+(u64bit) 0xFB3B173E72947609ULL, (u64bit) 0x1571187A8E3D4D6BULL, (u64bit) 0x13D306D29263C139ULL, (u64bit) 0xF8AEC6ADA137E865ULL,
+(u64bit) 0x123EA204BAB48731ULL, (u64bit) 0x11012099D202F297ULL, (u64bit) 0x10290E15797C21BDULL, (u64bit) 0x0F3AB38E679D6317ULL,
+(u64bit) 0xF50B5505D593FCF9ULL, (u64bit) 0xFF23754F7F2052B5ULL, (u64bit) 0x0CC52D96BC2E5A2DULL, (u64bit) 0x0BF80EAD87B228E5ULL,
+(u64bit) 0x0B59A623082C9171ULL, (u64bit) 0xF44E28B9221A433BULL, (u64bit) 0x09DB5CDD2505EABDULL, (u64bit) 0x09638C123BCAB351ULL,
+(u64bit) 0xFDB9AE6935254CD3ULL, (u64bit) 0xFFE30D7E4F02F163ULL, (u64bit) 0x07CF1FC053B9C61FULL, (u64bit) 0x0789244FF1705821ULL,
+(u64bit) 0x06FBD05649B0B9C7ULL, (u64bit) 0xEF9713EC6A0C250BULL, (u64bit) 0xF47691AD6AA9F0DBULL, (u64bit) 0xF2A8EB02CB08CA51ULL,
+(u64bit) 0xF9559D40380A20E1ULL, (u64bit) 0x04E15138A5B9BF43ULL, (u64bit) 0xEECD739EA48F3ABBULL, (u64bit) 0xF76E7E7530574E79ULL,
+(u64bit) 0xF8393D2E42D7D277ULL, (u64bit) 0xF666F9AD3A16D173ULL, (u64bit) 0xF403C629749F3ED5ULL, (u64bit) 0xFBD7EC45F220A473ULL,
+(u64bit) 0xFA8AFF7491B234FDULL, (u64bit) 0xFF471CE534D1F537ULL, (u64bit) 0xF4BEBFDD9C54CEC9ULL, (u64bit) 0xDD04722310A6CE9DULL,
+(u64bit) 0xFD8071236214FA05ULL, (u64bit) 0xFBCA07B399A482DDULL, (u64bit) 0xFD9642C104864C17ULL, (u64bit) 0xFA525105AADEFA39ULL,
+(u64bit) 0xF71122156406E645ULL, (u64bit) 0xFF415FDFD1247539ULL, (u64bit) 0xFB709936F52446AFULL, (u64bit) 0xFF7734CCB806CDA7ULL,
+(u64bit) 0xF801E9A88CD3D70DULL, (u64bit) 0xFC0C00AC9BCC5491ULL, (u64bit) 0xFF462CD8E52ED221ULL, (u64bit) 0xFC97426300FCE331ULL,
+(u64bit) 0xFEB3049C5E37A059ULL, (u64bit) 0xFFFC8AB1E05051CDULL, (u64bit) 0xFE5F4621F2D9FE63ULL, (u64bit) 0xFE931DB54FC5D521ULL,
+(u64bit) 0xFFDE43D960FE42A5ULL, (u64bit) 0xFFDBFAD1B802BDB5ULL, (u64bit) 0xFF23C485F6B7BF53ULL, (u64bit) 0xFFC98F169C8DF21BULL,
+(u64bit) 0xF1609D0E2E564D01ULL, (u64bit) 0xCB10B976C333834BULL, (u64bit) 0x9B52037A38DAB8F9ULL, (u64bit) 0x800E88FF5E929095ULL,
+(u64bit) 0x55A9AD1C21F5E173ULL, (u64bit) 0x3D1A64E4E555D699ULL, (u64bit) 0x2A5D1D73694F7B93ULL, (u64bit) 0x198F4260D8807623ULL,
+(u64bit) 0x140D45BB525C35EBULL, (u64bit) 0x102F4743FF914EEBULL, (u64bit) 0x0CB114936A734FBFULL, (u64bit) 0x096D97150B7B0A71ULL,
+(u64bit) 0x06F06B90B850C2E5ULL, (u64bit) 0x053B17A0D7F7386BULL, (u64bit) 0xE3AD1CE3C82FE6A5ULL, (u64bit) 0xDAE968B4B710E857ULL,
+(u64bit) 0xFA2DC15B2C96BE77ULL, (u64bit) 0xF1FF5F22AF135BD9ULL, (u64bit) 0xFC65C5CAAA878A13ULL, (u64bit) 0xFB9427EB08CF9C11ULL,
+(u64bit) 0xCCB12B6FEBFE285DULL, (u64bit) 0x5BAADA462B48F999ULL, (u64bit) 0x2E53167EC64B703BULL, (u64bit) 0x1264ED670CD61961ULL,
+(u64bit) 0x071F216A9AB74E2DULL, (u64bit) 0xEE26503C1266CE55ULL, (u64bit) 0x4C6004C7E404E4B5ULL, (u64bit) 0xCB649E41ECE95F85ULL
+};
+
+}
diff --git a/botan/src/math/numbertheory/reducer.cpp b/botan/src/math/numbertheory/reducer.cpp
new file mode 100644
index 0000000..fbd675e
--- /dev/null
+++ b/botan/src/math/numbertheory/reducer.cpp
@@ -0,0 +1,97 @@
+/*
+* Modular Reducer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/reducer.h>
+#include <botan/numthry.h>
+#include <botan/mp_core.h>
+
+namespace Botan {
+
+/*
+* Modular_Reducer Constructor
+*/
+Modular_Reducer::Modular_Reducer(const BigInt& mod)
+ {
+ if(mod <= 0)
+ throw Invalid_Argument("Modular_Reducer: modulus must be positive");
+
+ modulus = mod;
+ mod_words = modulus.sig_words();
+
+ modulus_2 = Botan::square(modulus);
+ mod2_words = modulus_2.sig_words();
+
+ mu = BigInt(BigInt::Power2, 2 * MP_WORD_BITS * mod_words) / modulus;
+ mu_words = mu.sig_words();
+ }
+
+/*
+* Barrett Reduction
+*/
+BigInt Modular_Reducer::reduce(const BigInt& x) const
+ {
+ if(mod_words == 0)
+ throw Invalid_State("Modular_Reducer: Never initalized");
+
+ BigInt t1 = x;
+ t1.set_sign(BigInt::Positive);
+
+ if(t1 < modulus)
+ {
+ if(x.is_negative() && t1.is_nonzero())
+ return modulus - t1;
+ return x;
+ }
+
+ if(t1 >= modulus_2)
+ return (x % modulus);
+
+ t1 >>= (MP_WORD_BITS * (mod_words - 1));
+ t1 *= mu;
+ t1 >>= (MP_WORD_BITS * (mod_words + 1));
+
+ t1 *= modulus;
+ t1.mask_bits(MP_WORD_BITS * (mod_words+1));
+
+ BigInt t2 = x;
+ t2.set_sign(BigInt::Positive);
+ t2.mask_bits(MP_WORD_BITS * (mod_words+1));
+
+ t1 = t2 - t1;
+
+ if(t1.is_negative())
+ {
+ BigInt b_to_k1(BigInt::Power2, MP_WORD_BITS * (mod_words+1));
+ t1 += b_to_k1;
+ }
+
+ while(t1 >= modulus)
+ t1 -= modulus;
+
+ if(x.is_negative() && t1.is_nonzero())
+ t1 = modulus - t1;
+
+ return t1;
+ }
+
+/*
+* Multiply, followed by a reduction
+*/
+BigInt Modular_Reducer::multiply(const BigInt& x, const BigInt& y) const
+ {
+ return reduce(x * y);
+ }
+
+/*
+* Square, followed by a reduction
+*/
+BigInt Modular_Reducer::square(const BigInt& x) const
+ {
+ return reduce(Botan::square(x));
+ }
+
+}
diff --git a/botan/src/math/numbertheory/reducer.h b/botan/src/math/numbertheory/reducer.h
new file mode 100644
index 0000000..d234e07
--- /dev/null
+++ b/botan/src/math/numbertheory/reducer.h
@@ -0,0 +1,36 @@
+/*
+* Modular Reducer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MODARITH_H__
+#define BOTAN_MODARITH_H__
+
+#include <botan/bigint.h>
+
+namespace Botan {
+
+/*
+* Modular Reducer
+*/
+class BOTAN_DLL Modular_Reducer
+ {
+ public:
+ BigInt multiply(const BigInt&, const BigInt&) const;
+ BigInt square(const BigInt&) const;
+ BigInt reduce(const BigInt&) const;
+
+ bool initialized() const { return (mod_words != 0); }
+
+ Modular_Reducer() { mod_words = 0; }
+ Modular_Reducer(const BigInt&);
+ private:
+ BigInt modulus, modulus_2, mu;
+ u32bit mod_words, mod2_words, mu_words;
+ };
+
+}
+
+#endif
diff --git a/botan/src/math/numbertheory/ressol.cpp b/botan/src/math/numbertheory/ressol.cpp
new file mode 100644
index 0000000..d51acb8
--- /dev/null
+++ b/botan/src/math/numbertheory/ressol.cpp
@@ -0,0 +1,82 @@
+/*
+* Shanks-Tonnelli (RESSOL)
+* (C) 2007-2008 Falko Strenzke, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/*
+* Shanks-Tonnelli algorithm
+*/
+BigInt ressol(const BigInt& a, const BigInt& p)
+ {
+ if(a < 0)
+ throw Invalid_Argument("ressol(): a to solve for must be positive");
+ if(p <= 1)
+ throw Invalid_Argument("ressol(): prime must be > 1");
+
+ if(a == 0)
+ return 0;
+ if(p == 2)
+ return a;
+
+ if(jacobi(a, p) != 1) // not a quadratic residue
+ return -BigInt(1);
+
+ if(p % 4 == 3)
+ return power_mod(a, ((p+1) >> 2), p);
+
+ u32bit s = low_zero_bits(p - 1);
+ BigInt q = p >> s;
+
+ q -= 1;
+ q >>= 1;
+
+ Modular_Reducer mod_p(p);
+
+ BigInt r = power_mod(a, q, p);
+ BigInt n = mod_p.multiply(a, mod_p.square(r));
+ r = mod_p.multiply(r, a);
+
+ if(n == 1)
+ return r;
+
+ // find random non quadratic residue z
+ BigInt z = 2;
+ while(jacobi(z, p) == 1) // while z quadratic residue
+ ++z;
+
+ BigInt c = power_mod(z, (q << 1) + 1, p);
+
+ while(n > 1)
+ {
+ q = n;
+
+ u32bit i = 0;
+ while(q != 1)
+ {
+ q = mod_p.square(q);
+ ++i;
+ }
+ u32bit t = s;
+
+ if(t <= i)
+ return -BigInt(1);
+
+ c = power_mod(c, BigInt(BigInt::Power2, t-i-1), p);
+ r = mod_p.multiply(r, c);
+ c = mod_p.square(c);
+ n = mod_p.multiply(n, c);
+ s = i;
+ }
+
+ return r;
+ }
+
+}
diff --git a/botan/src/modes/cbc/cbc.cpp b/botan/src/modes/cbc/cbc.cpp
new file mode 100644
index 0000000..f26d4d6
--- /dev/null
+++ b/botan/src/modes/cbc/cbc.cpp
@@ -0,0 +1,158 @@
+/*
+* CBC Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cbc.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* CBC Encryption Constructor
+*/
+CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE),
+ padder(pad)
+ {
+ if(!padder->valid_blocksize(BLOCK_SIZE))
+ throw Invalid_Block_Size(name(), padder->name());
+ }
+
+/*
+* CBC Encryption Constructor
+*/
+CBC_Encryption::CBC_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE),
+ padder(pad)
+ {
+ if(!padder->valid_blocksize(BLOCK_SIZE))
+ throw Invalid_Block_Size(name(), padder->name());
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Encrypt in CBC mode
+*/
+void CBC_Encryption::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit xored = std::min(BLOCK_SIZE - position, length);
+ xor_buf(state + position, input, xored);
+ input += xored;
+ length -= xored;
+ position += xored;
+ if(position == BLOCK_SIZE)
+ {
+ cipher->encrypt(state);
+ send(state, BLOCK_SIZE);
+ position = 0;
+ }
+ }
+ }
+
+/*
+* Finish encrypting in CBC mode
+*/
+void CBC_Encryption::end_msg()
+ {
+ SecureVector<byte> padding(BLOCK_SIZE);
+ padder->pad(padding, padding.size(), position);
+ write(padding, padder->pad_bytes(BLOCK_SIZE, position));
+ if(position != 0)
+ throw Exception(name() + ": Did not pad to full blocksize");
+ }
+
+/*
+* Return a CBC mode name
+*/
+std::string CBC_Encryption::name() const
+ {
+ return (cipher->name() + "/" + mode_name + "/" + padder->name());
+ }
+
+/*
+* CBC Decryption Constructor
+*/
+CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE),
+ padder(pad)
+ {
+ if(!padder->valid_blocksize(BLOCK_SIZE))
+ throw Invalid_Block_Size(name(), padder->name());
+ temp.create(BLOCK_SIZE);
+ }
+
+/*
+* CBC Decryption Constructor
+*/
+CBC_Decryption::CBC_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CBC", ciph->BLOCK_SIZE),
+ padder(pad)
+ {
+ if(!padder->valid_blocksize(BLOCK_SIZE))
+ throw Invalid_Block_Size(name(), padder->name());
+ temp.create(BLOCK_SIZE);
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Decrypt in CBC mode
+*/
+void CBC_Decryption::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ if(position == BLOCK_SIZE)
+ {
+ cipher->decrypt(buffer, temp);
+ xor_buf(temp, state, BLOCK_SIZE);
+ send(temp, BLOCK_SIZE);
+ state = buffer;
+ position = 0;
+ }
+ u32bit added = std::min(BLOCK_SIZE - position, length);
+ buffer.copy(position, input, added);
+ input += added;
+ length -= added;
+ position += added;
+ }
+ }
+
+/*
+* Finish decrypting in CBC mode
+*/
+void CBC_Decryption::end_msg()
+ {
+ if(position != BLOCK_SIZE)
+ throw Decoding_Error(name());
+ cipher->decrypt(buffer, temp);
+ xor_buf(temp, state, BLOCK_SIZE);
+ send(temp, padder->unpad(temp, BLOCK_SIZE));
+ state = buffer;
+ position = 0;
+ }
+
+/*
+* Return a CBC mode name
+*/
+std::string CBC_Decryption::name() const
+ {
+ return (cipher->name() + "/" + mode_name + "/" + padder->name());
+ }
+
+}
diff --git a/botan/src/modes/cbc/cbc.h b/botan/src/modes/cbc/cbc.h
new file mode 100644
index 0000000..a926ac1
--- /dev/null
+++ b/botan/src/modes/cbc/cbc.h
@@ -0,0 +1,55 @@
+/*
+* CBC Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_H__
+#define BOTAN_CBC_H__
+
+#include <botan/modebase.h>
+#include <botan/mode_pad.h>
+
+namespace Botan {
+
+/*
+* CBC Encryption
+*/
+class BOTAN_DLL CBC_Encryption : public BlockCipherMode
+ {
+ public:
+ CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*);
+ CBC_Encryption(BlockCipher*, BlockCipherModePaddingMethod*,
+ const SymmetricKey&, const InitializationVector&);
+
+ ~CBC_Encryption() { delete padder; }
+ private:
+ std::string name() const;
+ void write(const byte[], u32bit);
+ void end_msg();
+ const BlockCipherModePaddingMethod* padder;
+ };
+
+/*
+* CBC Decryption
+*/
+class BOTAN_DLL CBC_Decryption : public BlockCipherMode
+ {
+ public:
+ CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*);
+ CBC_Decryption(BlockCipher*, BlockCipherModePaddingMethod*,
+ const SymmetricKey&, const InitializationVector&);
+
+ ~CBC_Decryption() { delete padder; }
+ private:
+ std::string name() const;
+ void write(const byte[], u32bit);
+ void end_msg();
+ const BlockCipherModePaddingMethod* padder;
+ SecureVector<byte> temp;
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/cbc/info.txt b/botan/src/modes/cbc/info.txt
new file mode 100644
index 0000000..de81dcb
--- /dev/null
+++ b/botan/src/modes/cbc/info.txt
@@ -0,0 +1,14 @@
+realname "CBC block cipher mode"
+
+define CBC
+
+load_on auto
+
+<add>
+cbc.cpp
+cbc.h
+</add>
+
+<requires>
+mode_pad
+</requires>
diff --git a/botan/src/modes/cfb/cfb.cpp b/botan/src/modes/cfb/cfb.cpp
new file mode 100644
index 0000000..a126bd9
--- /dev/null
+++ b/botan/src/modes/cfb/cfb.cpp
@@ -0,0 +1,143 @@
+/*
+* CFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cfb.h>
+#include <botan/parsing.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Check the feedback size
+*/
+void check_feedback(u32bit BLOCK_SIZE, u32bit FEEDBACK_SIZE, u32bit bits,
+ const std::string& name)
+ {
+ if(FEEDBACK_SIZE == 0 || FEEDBACK_SIZE > BLOCK_SIZE || bits % 8 != 0)
+ throw Invalid_Argument(name + ": Invalid feedback size " +
+ to_string(bits));
+ }
+
+}
+
+/*
+* CFB Encryption Constructor
+*/
+CFB_Encryption::CFB_Encryption(BlockCipher* ciph,
+ u32bit fback_bits) :
+ BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1),
+ FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE)
+ {
+ check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
+ }
+
+/*
+* CFB Encryption Constructor
+*/
+CFB_Encryption::CFB_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit fback_bits) :
+ BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1),
+ FEEDBACK_SIZE(fback_bits ? fback_bits / 8: BLOCK_SIZE)
+ {
+ check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Encrypt data in CFB mode
+*/
+void CFB_Encryption::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit xored = std::min(FEEDBACK_SIZE - position, length);
+ xor_buf(buffer + position, input, xored);
+ send(buffer + position, xored);
+ input += xored;
+ length -= xored;
+ position += xored;
+ if(position == FEEDBACK_SIZE)
+ feedback();
+ }
+ }
+
+/*
+* Do the feedback
+*/
+void CFB_Encryption::feedback()
+ {
+ for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j)
+ state[j] = state[j + FEEDBACK_SIZE];
+ state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE);
+ cipher->encrypt(state, buffer);
+ position = 0;
+ }
+
+/*
+* CFB Decryption Constructor
+*/
+CFB_Decryption::CFB_Decryption(BlockCipher* ciph,
+ u32bit fback_bits) :
+ BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1),
+ FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE)
+ {
+ check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
+ }
+
+/*
+* CFB Decryption Constructor
+*/
+CFB_Decryption::CFB_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit fback_bits) :
+ BlockCipherMode(ciph, "CFB", ciph->BLOCK_SIZE, 1),
+ FEEDBACK_SIZE(fback_bits ? fback_bits / 8 : BLOCK_SIZE)
+ {
+ check_feedback(BLOCK_SIZE, FEEDBACK_SIZE, fback_bits, name());
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Decrypt data in CFB mode
+*/
+void CFB_Decryption::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit xored = std::min(FEEDBACK_SIZE - position, length);
+ xor_buf(buffer + position, input, xored);
+ send(buffer + position, xored);
+ buffer.copy(position, input, xored);
+ input += xored;
+ length -= xored;
+ position += xored;
+ if(position == FEEDBACK_SIZE)
+ feedback();
+ }
+ }
+
+/*
+* Do the feedback
+*/
+void CFB_Decryption::feedback()
+ {
+ for(u32bit j = 0; j != BLOCK_SIZE - FEEDBACK_SIZE; ++j)
+ state[j] = state[j + FEEDBACK_SIZE];
+ state.copy(BLOCK_SIZE - FEEDBACK_SIZE, buffer, FEEDBACK_SIZE);
+ cipher->encrypt(state, buffer);
+ position = 0;
+ }
+
+}
diff --git a/botan/src/modes/cfb/cfb.h b/botan/src/modes/cfb/cfb.h
new file mode 100644
index 0000000..7810c00
--- /dev/null
+++ b/botan/src/modes/cfb/cfb.h
@@ -0,0 +1,47 @@
+/*
+* CFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CFB_H__
+#define BOTAN_CFB_H__
+
+#include <botan/modebase.h>
+
+namespace Botan {
+
+/*
+* CFB Encryption
+*/
+class BOTAN_DLL CFB_Encryption : public BlockCipherMode
+ {
+ public:
+ CFB_Encryption(BlockCipher*, u32bit = 0);
+ CFB_Encryption(BlockCipher*, const SymmetricKey&,
+ const InitializationVector&, u32bit = 0);
+ private:
+ void write(const byte[], u32bit);
+ void feedback();
+ const u32bit FEEDBACK_SIZE;
+ };
+
+/*
+* CFB Decryption
+*/
+class BOTAN_DLL CFB_Decryption : public BlockCipherMode
+ {
+ public:
+ CFB_Decryption(BlockCipher*, u32bit = 0);
+ CFB_Decryption(BlockCipher*, const SymmetricKey&,
+ const InitializationVector&, u32bit = 0);
+ private:
+ void write(const byte[], u32bit);
+ void feedback();
+ const u32bit FEEDBACK_SIZE;
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/cfb/info.txt b/botan/src/modes/cfb/info.txt
new file mode 100644
index 0000000..d66df1e
--- /dev/null
+++ b/botan/src/modes/cfb/info.txt
@@ -0,0 +1,15 @@
+realname "CFB block cipher mode"
+
+define CFB
+
+load_on auto
+
+<add>
+cfb.cpp
+cfb.h
+</add>
+
+<requires>
+modes
+</requires>
+
diff --git a/botan/src/modes/ctr/ctr.cpp b/botan/src/modes/ctr/ctr.cpp
new file mode 100644
index 0000000..9eb42ec
--- /dev/null
+++ b/botan/src/modes/ctr/ctr.cpp
@@ -0,0 +1,75 @@
+/*
+* CTR Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ctr.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* CTR-BE Constructor
+*/
+CTR_BE::CTR_BE(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1)
+ {
+ }
+
+/*
+* CTR-BE Constructor
+*/
+CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1)
+ {
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* CTR-BE Encryption/Decryption
+*/
+void CTR_BE::write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(BLOCK_SIZE - position, length);
+ xor_buf(buffer + position, input, copied);
+ send(buffer + position, copied);
+ input += copied;
+ length -= copied;
+ position += copied;
+
+ if(position == BLOCK_SIZE)
+ increment_counter();
+
+ while(length >= BLOCK_SIZE)
+ {
+ xor_buf(buffer, input, BLOCK_SIZE);
+ send(buffer, BLOCK_SIZE);
+
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ increment_counter();
+ }
+
+ xor_buf(buffer + position, input, length);
+ send(buffer + position, length);
+ position += length;
+ }
+
+/*
+* Increment the counter and update the buffer
+*/
+void CTR_BE::increment_counter()
+ {
+ for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
+ if(++state[j])
+ break;
+ cipher->encrypt(state, buffer);
+ position = 0;
+ }
+
+}
diff --git a/botan/src/modes/ctr/ctr.h b/botan/src/modes/ctr/ctr.h
new file mode 100644
index 0000000..aa0db57
--- /dev/null
+++ b/botan/src/modes/ctr/ctr.h
@@ -0,0 +1,31 @@
+/*
+* CTR Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_COUNTER_MODE_H__
+#define BOTAN_COUNTER_MODE_H__
+
+#include <botan/modebase.h>
+#include <botan/modebase.h>
+
+namespace Botan {
+
+/*
+* CTR-BE Mode
+*/
+class BOTAN_DLL CTR_BE : public BlockCipherMode
+ {
+ public:
+ CTR_BE(BlockCipher*);
+ CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&);
+ private:
+ void write(const byte[], u32bit);
+ void increment_counter();
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/ctr/info.txt b/botan/src/modes/ctr/info.txt
new file mode 100644
index 0000000..cb291a2
--- /dev/null
+++ b/botan/src/modes/ctr/info.txt
@@ -0,0 +1,15 @@
+realname "CTR block cipher mode"
+
+define CTR
+
+load_on auto
+
+<add>
+ctr.cpp
+ctr.h
+</add>
+
+<requires>
+modes
+</requires>
+
diff --git a/botan/src/modes/cts/cts.cpp b/botan/src/modes/cts/cts.cpp
new file mode 100644
index 0000000..99f042f
--- /dev/null
+++ b/botan/src/modes/cts/cts.cpp
@@ -0,0 +1,134 @@
+/*
+* CTS Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cts.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Encrypt a block
+*/
+void CTS_Encryption::encrypt(const byte block[])
+ {
+ xor_buf(state, block, BLOCK_SIZE);
+ cipher->encrypt(state);
+ send(state, BLOCK_SIZE);
+ }
+
+/*
+* Encrypt in CTS mode
+*/
+void CTS_Encryption::write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(BUFFER_SIZE - position, length);
+ buffer.copy(position, input, copied);
+ length -= copied;
+ input += copied;
+ position += copied;
+
+ if(length == 0) return;
+
+ encrypt(buffer);
+ if(length > BLOCK_SIZE)
+ {
+ encrypt(buffer + BLOCK_SIZE);
+ while(length > 2*BLOCK_SIZE)
+ {
+ encrypt(input);
+ length -= BLOCK_SIZE;
+ input += BLOCK_SIZE;
+ }
+ position = 0;
+ }
+ else
+ {
+ copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
+ position = BLOCK_SIZE;
+ }
+ buffer.copy(position, input, length);
+ position += length;
+ }
+
+/*
+* Finish encrypting in CTS mode
+*/
+void CTS_Encryption::end_msg()
+ {
+ if(position < BLOCK_SIZE + 1)
+ throw Exception("CTS_Encryption: insufficient data to encrypt");
+ xor_buf(state, buffer, BLOCK_SIZE);
+ cipher->encrypt(state);
+ SecureVector<byte> cn = state;
+ clear_mem(buffer + position, BUFFER_SIZE - position);
+ encrypt(buffer + BLOCK_SIZE);
+ send(cn, position - BLOCK_SIZE);
+ }
+
+/*
+* Decrypt a block
+*/
+void CTS_Decryption::decrypt(const byte block[])
+ {
+ cipher->decrypt(block, temp);
+ xor_buf(temp, state, BLOCK_SIZE);
+ send(temp, BLOCK_SIZE);
+ state.copy(block, BLOCK_SIZE);
+ }
+
+/*
+* Decrypt in CTS mode
+*/
+void CTS_Decryption::write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(BUFFER_SIZE - position, length);
+ buffer.copy(position, input, copied);
+ length -= copied;
+ input += copied;
+ position += copied;
+
+ if(length == 0) return;
+
+ decrypt(buffer);
+ if(length > BLOCK_SIZE)
+ {
+ decrypt(buffer + BLOCK_SIZE);
+ while(length > 2*BLOCK_SIZE)
+ {
+ decrypt(input);
+ length -= BLOCK_SIZE;
+ input += BLOCK_SIZE;
+ }
+ position = 0;
+ }
+ else
+ {
+ copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
+ position = BLOCK_SIZE;
+ }
+ buffer.copy(position, input, length);
+ position += length;
+ }
+
+/*
+* Finish decrypting in CTS mode
+*/
+void CTS_Decryption::end_msg()
+ {
+ cipher->decrypt(buffer, temp);
+ xor_buf(temp, buffer + BLOCK_SIZE, position - BLOCK_SIZE);
+ SecureVector<byte> xn = temp;
+ copy_mem(buffer + position, xn + (position - BLOCK_SIZE),
+ BUFFER_SIZE - position);
+ cipher->decrypt(buffer + BLOCK_SIZE, temp);
+ xor_buf(temp, state, BLOCK_SIZE);
+ send(temp, BLOCK_SIZE);
+ send(xn, position - BLOCK_SIZE);
+ }
+
+}
diff --git a/botan/src/modes/cts/cts.h b/botan/src/modes/cts/cts.h
new file mode 100644
index 0000000..9b17203
--- /dev/null
+++ b/botan/src/modes/cts/cts.h
@@ -0,0 +1,60 @@
+/*
+* CTS Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CTS_H__
+#define BOTAN_CTS_H__
+
+#include <botan/modebase.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* CTS Encryption
+*/
+class BOTAN_DLL CTS_Encryption : public BlockCipherMode
+ {
+ public:
+ CTS_Encryption(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2) {}
+
+ CTS_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { set_key(key); set_iv(iv); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void encrypt(const byte[]);
+ };
+
+/*
+* CTS Decryption
+*/
+class BOTAN_DLL CTS_Decryption : public BlockCipherMode
+ {
+ public:
+ CTS_Decryption(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { temp.create(BLOCK_SIZE); }
+
+ CTS_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "CTS", ciph->BLOCK_SIZE, 0, 2)
+ { set_key(key); set_iv(iv); temp.create(BLOCK_SIZE); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void decrypt(const byte[]);
+ SecureVector<byte> temp;
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/cts/info.txt b/botan/src/modes/cts/info.txt
new file mode 100644
index 0000000..9eb16ad
--- /dev/null
+++ b/botan/src/modes/cts/info.txt
@@ -0,0 +1,14 @@
+realname "CTS block cipher mode"
+
+define CTS
+
+load_on auto
+
+<add>
+cts.cpp
+cts.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/modes/eax/eax.cpp b/botan/src/modes/eax/eax.cpp
new file mode 100644
index 0000000..67465a7
--- /dev/null
+++ b/botan/src/modes/eax/eax.cpp
@@ -0,0 +1,172 @@
+/*
+* EAX Mode Encryption
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eax.h>
+#include <botan/cmac.h>
+#include <botan/xor_buf.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EAX MAC-based PRF
+*/
+SecureVector<byte> eax_prf(byte tag, u32bit BLOCK_SIZE,
+ MessageAuthenticationCode* mac,
+ const byte in[], u32bit length)
+ {
+ for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j)
+ mac->update(0);
+ mac->update(tag);
+ mac->update(in, length);
+ return mac->final();
+ }
+
+}
+
+/*
+* EAX_Base Constructor
+*/
+EAX_Base::EAX_Base(BlockCipher* ciph,
+ u32bit tag_size) :
+ TAG_SIZE(tag_size ? tag_size / 8 : ciph->BLOCK_SIZE),
+ BLOCK_SIZE(ciph->BLOCK_SIZE)
+ {
+ cipher = ciph;
+ mac = new CMAC(cipher->clone());
+
+ if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > mac->OUTPUT_LENGTH)
+ throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size));
+
+ state.create(BLOCK_SIZE);
+ buffer.create(BLOCK_SIZE);
+ position = 0;
+ }
+
+/*
+* Check if a keylength is valid for EAX
+*/
+bool EAX_Base::valid_keylength(u32bit n) const
+ {
+ if(!cipher->valid_keylength(n))
+ return false;
+ if(!mac->valid_keylength(n))
+ return false;
+ return true;
+ }
+
+/*
+* Set the EAX key
+*/
+void EAX_Base::set_key(const SymmetricKey& key)
+ {
+ cipher->set_key(key);
+ mac->set_key(key);
+ header_mac = eax_prf(1, BLOCK_SIZE, mac, 0, 0);
+ }
+
+/*
+* Do setup at the start of each message
+*/
+void EAX_Base::start_msg()
+ {
+ for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j)
+ mac->update(0);
+ mac->update(2);
+ }
+
+/*
+* Set the EAX nonce
+*/
+void EAX_Base::set_iv(const InitializationVector& iv)
+ {
+ nonce_mac = eax_prf(0, BLOCK_SIZE, mac, iv.begin(), iv.length());
+ state = nonce_mac;
+ cipher->encrypt(state, buffer);
+ }
+
+/*
+* Set the EAX header
+*/
+void EAX_Base::set_header(const byte header[], u32bit length)
+ {
+ header_mac = eax_prf(1, BLOCK_SIZE, mac, header, length);
+ }
+
+/*
+* Return the name of this cipher mode
+*/
+std::string EAX_Base::name() const
+ {
+ return (cipher->name() + "/EAX");
+ }
+
+/*
+* Increment the counter and update the buffer
+*/
+void EAX_Base::increment_counter()
+ {
+ for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
+ if(++state[j])
+ break;
+ cipher->encrypt(state, buffer);
+ position = 0;
+ }
+
+/*
+* Encrypt in EAX mode
+*/
+void EAX_Encryption::write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(BLOCK_SIZE - position, length);
+ xor_buf(buffer + position, input, copied);
+ send(buffer + position, copied);
+ mac->update(buffer + position, copied);
+ input += copied;
+ length -= copied;
+ position += copied;
+
+ if(position == BLOCK_SIZE)
+ increment_counter();
+
+ while(length >= BLOCK_SIZE)
+ {
+ xor_buf(buffer, input, BLOCK_SIZE);
+ send(buffer, BLOCK_SIZE);
+ mac->update(buffer, BLOCK_SIZE);
+
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ increment_counter();
+ }
+
+ xor_buf(buffer + position, input, length);
+ send(buffer + position, length);
+ mac->update(buffer + position, length);
+ position += length;
+ }
+
+/*
+* Finish encrypting in EAX mode
+*/
+void EAX_Encryption::end_msg()
+ {
+ SecureVector<byte> data_mac = mac->final();
+ xor_buf(data_mac, nonce_mac, data_mac.size());
+ xor_buf(data_mac, header_mac, data_mac.size());
+
+ send(data_mac, TAG_SIZE);
+
+ state.clear();
+ buffer.clear();
+ position = 0;
+ }
+
+}
diff --git a/botan/src/modes/eax/eax.h b/botan/src/modes/eax/eax.h
new file mode 100644
index 0000000..1bb2e51
--- /dev/null
+++ b/botan/src/modes/eax/eax.h
@@ -0,0 +1,85 @@
+/*
+* EAX Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EAX_H__
+#define BOTAN_EAX_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/*
+* EAX Base Class
+*/
+class BOTAN_DLL EAX_Base : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey&);
+ void set_iv(const InitializationVector&);
+ void set_header(const byte[], u32bit);
+ std::string name() const;
+
+ bool valid_keylength(u32bit) const;
+
+ ~EAX_Base() { delete cipher; delete mac; }
+ protected:
+ EAX_Base(BlockCipher*, u32bit);
+ void start_msg();
+ void increment_counter();
+
+ const u32bit TAG_SIZE, BLOCK_SIZE;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+ SecureVector<byte> nonce_mac, header_mac, state, buffer;
+ u32bit position;
+ };
+
+/*
+* EAX Encryption
+*/
+class BOTAN_DLL EAX_Encryption : public EAX_Base
+ {
+ public:
+ EAX_Encryption(BlockCipher* ciph, u32bit tag_size = 0) :
+ EAX_Base(ciph, tag_size) {}
+
+ EAX_Encryption(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit tag_size) : EAX_Base(ciph, tag_size)
+ {
+ set_key(key);
+ set_iv(iv);
+ }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+/*
+* EAX Decryption
+*/
+class BOTAN_DLL EAX_Decryption : public EAX_Base
+ {
+ public:
+ EAX_Decryption(BlockCipher* ciph, u32bit tag_size = 0);
+
+ EAX_Decryption(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit tag_size = 0);
+ private:
+ void write(const byte[], u32bit);
+ void do_write(const byte[], u32bit);
+ void end_msg();
+ SecureVector<byte> queue;
+ u32bit queue_start, queue_end;
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/eax/eax_dec.cpp b/botan/src/modes/eax/eax_dec.cpp
new file mode 100644
index 0000000..b7e5795
--- /dev/null
+++ b/botan/src/modes/eax/eax_dec.cpp
@@ -0,0 +1,127 @@
+/*
+* EAX Mode Encryption
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eax.h>
+#include <botan/xor_buf.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* EAX_Decryption Constructor
+*/
+EAX_Decryption::EAX_Decryption(BlockCipher* ciph,
+ u32bit tag_size) :
+ EAX_Base(ciph, tag_size)
+ {
+ queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE);
+ queue_start = queue_end = 0;
+ }
+
+/*
+* EAX_Decryption Constructor
+*/
+EAX_Decryption::EAX_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ u32bit tag_size) :
+ EAX_Base(ciph, tag_size)
+ {
+ set_key(key);
+ set_iv(iv);
+ queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE);
+ queue_start = queue_end = 0;
+ }
+
+/*
+* Decrypt in EAX mode
+*/
+void EAX_Decryption::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ const u32bit copied = std::min(length, queue.size() - queue_end);
+
+ queue.copy(queue_end, input, copied);
+ input += copied;
+ length -= copied;
+ queue_end += copied;
+
+ SecureVector<byte> block_buf(cipher->BLOCK_SIZE);
+ while((queue_end - queue_start) > TAG_SIZE)
+ {
+ u32bit removed = (queue_end - queue_start) - TAG_SIZE;
+ do_write(queue + queue_start, removed);
+ queue_start += removed;
+ }
+
+ if(queue_start + TAG_SIZE == queue_end &&
+ queue_start >= queue.size() / 2)
+ {
+ SecureVector<byte> queue_data(TAG_SIZE);
+ queue_data.copy(queue + queue_start, TAG_SIZE);
+ queue.copy(queue_data, TAG_SIZE);
+ queue_start = 0;
+ queue_end = TAG_SIZE;
+ }
+ }
+ }
+
+/*
+* Decrypt in EAX mode
+*/
+void EAX_Decryption::do_write(const byte input[], u32bit length)
+ {
+ mac->update(input, length);
+
+ u32bit copied = std::min(BLOCK_SIZE - position, length);
+ xor_buf(buffer + position, input, copied);
+ send(buffer + position, copied);
+ input += copied;
+ length -= copied;
+ position += copied;
+
+ if(position == BLOCK_SIZE)
+ increment_counter();
+
+ while(length >= BLOCK_SIZE)
+ {
+ xor_buf(buffer, input, BLOCK_SIZE);
+ send(buffer, BLOCK_SIZE);
+
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ increment_counter();
+ }
+
+ xor_buf(buffer + position, input, length);
+ send(buffer + position, length);
+ position += length;
+ }
+
+/*
+* Finish decrypting in EAX mode
+*/
+void EAX_Decryption::end_msg()
+ {
+ if((queue_end - queue_start) != TAG_SIZE)
+ throw Integrity_Failure(name() + ": Message authentication failure");
+
+ SecureVector<byte> data_mac = mac->final();
+
+ for(u32bit j = 0; j != TAG_SIZE; ++j)
+ if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j]))
+ throw Integrity_Failure(name() + ": Message authentication failure");
+
+ state.clear();
+ buffer.clear();
+ position = 0;
+ queue_start = queue_end = 0;
+ }
+
+}
diff --git a/botan/src/modes/eax/info.txt b/botan/src/modes/eax/info.txt
new file mode 100644
index 0000000..d1fc7e0
--- /dev/null
+++ b/botan/src/modes/eax/info.txt
@@ -0,0 +1,18 @@
+realname "EAX block cipher mode"
+
+define EAX
+
+load_on auto
+
+<add>
+eax.cpp
+eax.h
+eax_dec.cpp
+</add>
+
+<requires>
+block
+cmac
+filters
+mac
+</requires>
diff --git a/botan/src/modes/ecb/ecb.cpp b/botan/src/modes/ecb/ecb.cpp
new file mode 100644
index 0000000..8da0a48
--- /dev/null
+++ b/botan/src/modes/ecb/ecb.cpp
@@ -0,0 +1,105 @@
+/*
+* ECB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecb.h>
+
+namespace Botan {
+
+/*
+* Verify the IV is not set
+*/
+bool ECB::valid_iv_size(u32bit iv_size) const
+ {
+ if(iv_size == 0)
+ return true;
+ return false;
+ }
+
+/*
+* Return an ECB mode name
+*/
+std::string ECB::name() const
+ {
+ return (cipher->name() + "/" + mode_name + "/" + padder->name());
+ }
+
+/*
+* Encrypt in ECB mode
+*/
+void ECB_Encryption::write(const byte input[], u32bit length)
+ {
+ buffer.copy(position, input, length);
+ if(position + length >= BLOCK_SIZE)
+ {
+ cipher->encrypt(buffer);
+ send(buffer, BLOCK_SIZE);
+ input += (BLOCK_SIZE - position);
+ length -= (BLOCK_SIZE - position);
+ while(length >= BLOCK_SIZE)
+ {
+ cipher->encrypt(input, buffer);
+ send(buffer, BLOCK_SIZE);
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ }
+ buffer.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Finish encrypting in ECB mode
+*/
+void ECB_Encryption::end_msg()
+ {
+ SecureVector<byte> padding(BLOCK_SIZE);
+ padder->pad(padding, padding.size(), position);
+ write(padding, padder->pad_bytes(BLOCK_SIZE, position));
+ if(position != 0)
+ throw Encoding_Error(name() + ": Did not pad to full blocksize");
+ }
+
+/*
+* Decrypt in ECB mode
+*/
+void ECB_Decryption::write(const byte input[], u32bit length)
+ {
+ buffer.copy(position, input, length);
+ if(position + length > BLOCK_SIZE)
+ {
+ cipher->decrypt(buffer);
+ send(buffer, BLOCK_SIZE);
+ input += (BLOCK_SIZE - position);
+ length -= (BLOCK_SIZE - position);
+ while(length > BLOCK_SIZE)
+ {
+ cipher->decrypt(input, buffer);
+ send(buffer, BLOCK_SIZE);
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ }
+ buffer.copy(input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Finish decrypting in ECB mode
+*/
+void ECB_Decryption::end_msg()
+ {
+ if(position != BLOCK_SIZE)
+ throw Decoding_Error(name());
+ cipher->decrypt(buffer);
+ send(buffer, padder->unpad(buffer, BLOCK_SIZE));
+ state = buffer;
+ position = 0;
+ }
+
+}
diff --git a/botan/src/modes/ecb/ecb.h b/botan/src/modes/ecb/ecb.h
new file mode 100644
index 0000000..5230f9b
--- /dev/null
+++ b/botan/src/modes/ecb/ecb.h
@@ -0,0 +1,73 @@
+/*
+* ECB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECB_H__
+#define BOTAN_ECB_H__
+
+#include <botan/modebase.h>
+#include <botan/mode_pad.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* ECB
+*/
+class BOTAN_DLL ECB : public BlockCipherMode
+ {
+ protected:
+ ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) :
+ BlockCipherMode(ciph, "ECB", 0), padder(pad) {}
+ ~ECB() { delete padder; }
+
+ std::string name() const;
+ BlockCipherModePaddingMethod* padder;
+ private:
+ bool valid_iv_size(u32bit) const;
+ };
+
+/*
+* ECB Encryption
+*/
+class BOTAN_DLL ECB_Encryption : public ECB
+ {
+ public:
+ ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ ECB(ciph, pad) {}
+
+ ECB_Encryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key) :
+ ECB(ciph, pad) { set_key(key); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+/*
+* ECB Decryption
+*/
+class BOTAN_DLL ECB_Decryption : public ECB
+ {
+ public:
+ ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad) :
+ ECB(ciph, pad) {}
+
+ ECB_Decryption(BlockCipher* ciph,
+ BlockCipherModePaddingMethod* pad,
+ const SymmetricKey& key) :
+ ECB(ciph, pad) { set_key(key); }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/ecb/info.txt b/botan/src/modes/ecb/info.txt
new file mode 100644
index 0000000..06b7b4f
--- /dev/null
+++ b/botan/src/modes/ecb/info.txt
@@ -0,0 +1,15 @@
+realname "ECB block cipher mode"
+
+define ECB
+
+load_on auto
+
+<add>
+ecb.cpp
+ecb.h
+</add>
+
+<requires>
+block
+mode_pad
+</requires>
diff --git a/botan/src/modes/info.txt b/botan/src/modes/info.txt
new file mode 100644
index 0000000..e089e74
--- /dev/null
+++ b/botan/src/modes/info.txt
@@ -0,0 +1,15 @@
+realname "Cipher Mode Base Class"
+
+define CIPHER_MODEBASE
+
+load_on auto
+
+<add>
+modebase.cpp
+modebase.h
+</add>
+
+<requires>
+block
+filters
+</requires>
diff --git a/botan/src/modes/mode_pad/info.txt b/botan/src/modes/mode_pad/info.txt
new file mode 100644
index 0000000..f22cf74
--- /dev/null
+++ b/botan/src/modes/mode_pad/info.txt
@@ -0,0 +1,10 @@
+realname "Cipher Mode Padding Method"
+
+define CIPHER_MODE_PADDING
+
+load_on auto
+
+<add>
+mode_pad.cpp
+mode_pad.h
+</add>
diff --git a/botan/src/modes/mode_pad/mode_pad.cpp b/botan/src/modes/mode_pad/mode_pad.cpp
new file mode 100644
index 0000000..b8badd7
--- /dev/null
+++ b/botan/src/modes/mode_pad/mode_pad.cpp
@@ -0,0 +1,128 @@
+/*
+* CBC Padding Methods
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mode_pad.h>
+#include <botan/exceptn.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*
+* Default amount of padding
+*/
+u32bit BlockCipherModePaddingMethod::pad_bytes(u32bit bs, u32bit pos) const
+ {
+ return (bs - pos);
+ }
+
+/*
+* Pad with PKCS #7 Method
+*/
+void PKCS7_Padding::pad(byte block[], u32bit size, u32bit position) const
+ {
+ for(u32bit j = 0; j != size; ++j)
+ block[j] = (size-position);
+ }
+
+/*
+* Unpad with PKCS #7 Method
+*/
+u32bit PKCS7_Padding::unpad(const byte block[], u32bit size) const
+ {
+ u32bit position = block[size-1];
+ if(position > size)
+ throw Decoding_Error(name());
+ for(u32bit j = size-position; j != size-1; ++j)
+ if(block[j] != position)
+ throw Decoding_Error(name());
+ return (size-position);
+ }
+
+/*
+* Query if the size is valid for this method
+*/
+bool PKCS7_Padding::valid_blocksize(u32bit size) const
+ {
+ if(size > 0 && size < 256)
+ return true;
+ else
+ return false;
+ }
+
+/*
+* Pad with ANSI X9.23 Method
+*/
+void ANSI_X923_Padding::pad(byte block[], u32bit size, u32bit position) const
+ {
+ for(u32bit j = 0; j != size-position; ++j)
+ block[j] = 0;
+ block[size-position-1] = (size-position);
+ }
+
+/*
+* Unpad with ANSI X9.23 Method
+*/
+u32bit ANSI_X923_Padding::unpad(const byte block[], u32bit size) const
+ {
+ u32bit position = block[size-1];
+ if(position > size)
+ throw Decoding_Error(name());
+ for(u32bit j = size-position; j != size-1; ++j)
+ if(block[j] != 0)
+ throw Decoding_Error(name());
+ return (size-position);
+ }
+
+/*
+* Query if the size is valid for this method
+*/
+bool ANSI_X923_Padding::valid_blocksize(u32bit size) const
+ {
+ if(size > 0 && size < 256)
+ return true;
+ else
+ return false;
+ }
+
+/*
+* Pad with One and Zeros Method
+*/
+void OneAndZeros_Padding::pad(byte block[], u32bit size, u32bit) const
+ {
+ block[0] = 0x80;
+ for(u32bit j = 1; j != size; ++j)
+ block[j] = 0x00;
+ }
+
+/*
+* Unpad with One and Zeros Method
+*/
+u32bit OneAndZeros_Padding::unpad(const byte block[], u32bit size) const
+ {
+ while(size)
+ {
+ if(block[size-1] == 0x80)
+ break;
+ if(block[size-1] != 0x00)
+ throw Decoding_Error(name());
+ size--;
+ }
+ if(!size)
+ throw Decoding_Error(name());
+ return (size-1);
+ }
+
+/*
+* Query if the size is valid for this method
+*/
+bool OneAndZeros_Padding::valid_blocksize(u32bit size) const
+ {
+ if(size) return true;
+ else return false;
+ }
+
+}
diff --git a/botan/src/modes/mode_pad/mode_pad.h b/botan/src/modes/mode_pad/mode_pad.h
new file mode 100644
index 0000000..a486d3c
--- /dev/null
+++ b/botan/src/modes/mode_pad/mode_pad.h
@@ -0,0 +1,120 @@
+/**
+* CBC Padding Methods
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_PADDING_H__
+#define BOTAN_CBC_PADDING_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Block Cipher Mode Padding Method
+* This class is pretty limited, it cannot deal well with
+* randomized padding methods, or any padding method that
+* wants to add more than one block. For instance, it should
+* be possible to define cipher text stealing mode as simply
+* a padding mode for CBC, which happens to consume the last
+* two block (and requires use of the block cipher).
+*/
+class BOTAN_DLL BlockCipherModePaddingMethod
+ {
+ public:
+ /**
+ * @param block output buffer
+ * @param size of the block
+ * @param current_position in the last block
+ */
+ virtual void pad(byte block[],
+ u32bit size,
+ u32bit current_position) const = 0;
+
+ /**
+ * @param block the last block
+ * @param size the of the block
+ */
+ virtual u32bit unpad(const byte block[],
+ u32bit size) const = 0;
+
+ /**
+ * @param block_size of the cipher
+ * @param position in the current block
+ * @return number of padding bytes that will be appended
+ */
+ virtual u32bit pad_bytes(u32bit block_size,
+ u32bit position) const;
+
+ /**
+ * @param block_size of the cipher
+ * @return valid block size for this padding mode
+ */
+ virtual bool valid_blocksize(u32bit block_size) const = 0;
+
+ /**
+ * @return name of the mode
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * virtual destructor
+ */
+ virtual ~BlockCipherModePaddingMethod() {}
+ };
+
+/**
+* PKCS#7 Padding
+*/
+class BOTAN_DLL PKCS7_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "PKCS7"; }
+ };
+
+/**
+* ANSI X9.23 Padding
+*/
+class BOTAN_DLL ANSI_X923_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "X9.23"; }
+ };
+
+/**
+* One And Zeros Padding
+*/
+class BOTAN_DLL OneAndZeros_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const;
+ u32bit unpad(const byte[], u32bit) const;
+ bool valid_blocksize(u32bit) const;
+ std::string name() const { return "OneAndZeros"; }
+ };
+
+/**
+* Null Padding
+*/
+class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod
+ {
+ public:
+ void pad(byte[], u32bit, u32bit) const { return; }
+ u32bit unpad(const byte[], u32bit size) const { return size; }
+ u32bit pad_bytes(u32bit, u32bit) const { return 0; }
+ bool valid_blocksize(u32bit) const { return true; }
+ std::string name() const { return "NoPadding"; }
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/modebase.cpp b/botan/src/modes/modebase.cpp
new file mode 100644
index 0000000..8293acc
--- /dev/null
+++ b/botan/src/modes/modebase.cpp
@@ -0,0 +1,54 @@
+/*
+* Block Cipher Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/modebase.h>
+
+namespace Botan {
+
+/*
+* Block Cipher Mode Constructor
+*/
+BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr,
+ const std::string& cipher_mode_name,
+ u32bit iv_size, u32bit iv_meth,
+ u32bit buf_mult) :
+ BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE),
+ IV_METHOD(iv_meth), mode_name(cipher_mode_name)
+ {
+ base_ptr = cipher = cipher_ptr;
+ buffer.create(BUFFER_SIZE);
+ state.create(iv_size);
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string BlockCipherMode::name() const
+ {
+ return (cipher->name() + "/" + mode_name);
+ }
+
+/*
+* Set the IV
+*/
+void BlockCipherMode::set_iv(const InitializationVector& new_iv)
+ {
+ if(new_iv.length() != state.size())
+ throw Invalid_IV_Length(name(), new_iv.length());
+
+ state = new_iv.bits_of();
+ buffer.clear();
+ position = 0;
+
+ if(IV_METHOD == 1)
+ cipher->encrypt(state, buffer);
+ else if(IV_METHOD == 2)
+ cipher->encrypt(state);
+ }
+
+}
diff --git a/botan/src/modes/modebase.h b/botan/src/modes/modebase.h
new file mode 100644
index 0000000..173fde5
--- /dev/null
+++ b/botan/src/modes/modebase.h
@@ -0,0 +1,39 @@
+/*
+* Block Cipher Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MODEBASE_H__
+#define BOTAN_MODEBASE_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* This class represents an abstract block cipher mode
+*/
+class BOTAN_DLL BlockCipherMode : public Keyed_Filter
+ {
+ public:
+ std::string name() const;
+
+ BlockCipherMode(BlockCipher*, const std::string&,
+ u32bit, u32bit = 0, u32bit = 1);
+
+ virtual ~BlockCipherMode() { delete cipher; }
+ protected:
+ void set_iv(const InitializationVector&);
+ const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD;
+ const std::string mode_name;
+ BlockCipher* cipher;
+ SecureVector<byte> buffer, state;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/ofb/info.txt b/botan/src/modes/ofb/info.txt
new file mode 100644
index 0000000..3cba415
--- /dev/null
+++ b/botan/src/modes/ofb/info.txt
@@ -0,0 +1,14 @@
+realname "OFB block cipher mode"
+
+define OFB
+
+load_on auto
+
+<add>
+ofb.cpp
+ofb.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/modes/ofb/ofb.cpp b/botan/src/modes/ofb/ofb.cpp
new file mode 100644
index 0000000..cb40fde
--- /dev/null
+++ b/botan/src/modes/ofb/ofb.cpp
@@ -0,0 +1,66 @@
+/*
+* OFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ofb.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* OFB Constructor
+*/
+OFB::OFB(BlockCipher* ciph) :
+ BlockCipherMode(ciph, "OFB", ciph->BLOCK_SIZE, 2)
+ {
+ }
+
+/*
+* OFB Constructor
+*/
+OFB::OFB(BlockCipher* ciph, const SymmetricKey& key,
+ const InitializationVector& iv) :
+ BlockCipherMode(ciph, "OFB", ciph->BLOCK_SIZE, 2)
+ {
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* OFB Encryption/Decryption
+*/
+void OFB::write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(BLOCK_SIZE - position, length);
+ xor_buf(buffer, input, state + position, copied);
+ send(buffer, copied);
+ input += copied;
+ length -= copied;
+ position += copied;
+
+ if(position == BLOCK_SIZE)
+ {
+ cipher->encrypt(state);
+ position = 0;
+ }
+
+ while(length >= BLOCK_SIZE)
+ {
+ xor_buf(buffer, input, state, BLOCK_SIZE);
+ send(buffer, BLOCK_SIZE);
+
+ input += BLOCK_SIZE;
+ length -= BLOCK_SIZE;
+ cipher->encrypt(state);
+ }
+
+ xor_buf(buffer, input, state + position, length);
+ send(buffer, length);
+ position += length;
+ }
+
+}
diff --git a/botan/src/modes/ofb/ofb.h b/botan/src/modes/ofb/ofb.h
new file mode 100644
index 0000000..a3aadc1
--- /dev/null
+++ b/botan/src/modes/ofb/ofb.h
@@ -0,0 +1,33 @@
+/*
+* OFB Mode
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OUTPUT_FEEDBACK_MODE_H__
+#define BOTAN_OUTPUT_FEEDBACK_MODE_H__
+
+#include <botan/modebase.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* OFB Mode
+*/
+class BOTAN_DLL OFB : public BlockCipherMode
+ {
+ public:
+ OFB(BlockCipher* cipher);
+
+ OFB(BlockCipher* cipher,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+ private:
+ void write(const byte[], u32bit);
+ };
+
+}
+
+#endif
diff --git a/botan/src/modes/xts/info.txt b/botan/src/modes/xts/info.txt
new file mode 100644
index 0000000..65c7df2
--- /dev/null
+++ b/botan/src/modes/xts/info.txt
@@ -0,0 +1,15 @@
+realname "XTS block cipher mode"
+
+define XTS
+
+load_on auto
+
+<add>
+xts.cpp
+xts.h
+</add>
+
+<requires>
+block
+filters
+</requires>
diff --git a/botan/src/modes/xts/xts.cpp b/botan/src/modes/xts/xts.cpp
new file mode 100644
index 0000000..8780ae1
--- /dev/null
+++ b/botan/src/modes/xts/xts.cpp
@@ -0,0 +1,344 @@
+/*
+* XTS Mode
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/xts.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+#include <stdexcept>
+
+namespace Botan {
+
+namespace {
+
+void poly_double(byte tweak[], u32bit size)
+ {
+ const byte polynomial = 0x87; // for 128 bit ciphers
+
+ byte carry = 0;
+ for(u32bit i = 0; i != size; ++i)
+ {
+ byte carry2 = (tweak[i] >> 7);
+ tweak[i] = (tweak[i] << 1) | carry;
+ carry = carry2;
+ }
+
+ if(carry)
+ tweak[0] ^= polynomial;
+ }
+
+}
+
+/*
+* XTS_Encryption constructor
+*/
+XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph)
+ {
+ if(cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
+ cipher2 = cipher->clone();
+ tweak.create(cipher->BLOCK_SIZE);
+ buffer.create(2 * cipher->BLOCK_SIZE);
+ position = 0;
+ }
+
+/*
+* XTS_Encryption constructor
+*/
+XTS_Encryption::XTS_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv) : cipher(ciph)
+ {
+ if(cipher->BLOCK_SIZE != 16)
+ throw std::invalid_argument("Bad cipher for XTS: " + cipher->name());
+
+ cipher2 = cipher->clone();
+ tweak.create(cipher->BLOCK_SIZE);
+ buffer.create(2 * cipher->BLOCK_SIZE);
+ position = 0;
+
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Return the name
+*/
+std::string XTS_Encryption::name() const
+ {
+ return (cipher->name() + "/XTS");
+ }
+
+/*
+* Set new tweak
+*/
+void XTS_Encryption::set_iv(const InitializationVector& iv)
+ {
+ if(iv.length() != tweak.size())
+ throw Invalid_IV_Length(name(), iv.length());
+
+ tweak = iv.bits_of();
+ cipher2->encrypt(tweak);
+ }
+
+void XTS_Encryption::set_key(const SymmetricKey& key)
+ {
+ u32bit key_half = key.length() / 2;
+
+ if(key.length() % 2 == 1 || !cipher->valid_keylength(key_half))
+ throw Invalid_Key_Length(name(), key.length());
+
+ cipher->set_key(key.begin(), key_half);
+ cipher2->set_key(key.begin() + key_half, key_half);
+ }
+
+void XTS_Encryption::encrypt(const byte block[])
+ {
+ /*
+ * We can always use the first 16 bytes of buffer as temp space,
+ * since either the input block is buffer (in which case this is
+ * just buffer ^= tweak) or it not, in which case we already read
+ * and used the data there and are processing new input. Kind of
+ * subtle/nasty, but saves allocating a distinct temp buf.
+ */
+
+ xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
+ cipher->encrypt(buffer);
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ poly_double(tweak, cipher->BLOCK_SIZE);
+
+ send(buffer, cipher->BLOCK_SIZE);
+ }
+
+/*
+* Encrypt in XTS mode
+*/
+void XTS_Encryption::write(const byte input[], u32bit length)
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ u32bit copied = std::min(buffer.size() - position, length);
+ buffer.copy(position, input, copied);
+ length -= copied;
+ input += copied;
+ position += copied;
+
+ if(length == 0) return;
+
+ encrypt(buffer);
+ if(length > BLOCK_SIZE)
+ {
+ encrypt(buffer + BLOCK_SIZE);
+ while(length > buffer.size())
+ {
+ encrypt(input);
+ length -= BLOCK_SIZE;
+ input += BLOCK_SIZE;
+ }
+ position = 0;
+ }
+ else
+ {
+ copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
+ position = BLOCK_SIZE;
+ }
+ buffer.copy(position, input, length);
+ position += length;
+ }
+
+/*
+* Finish encrypting in XTS mode
+*/
+void XTS_Encryption::end_msg()
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ if(position < BLOCK_SIZE)
+ throw Exception("XTS_Encryption: insufficient data to encrypt");
+ else if(position == BLOCK_SIZE)
+ {
+ encrypt(buffer);
+ }
+ else if(position == 2*BLOCK_SIZE)
+ {
+ encrypt(buffer);
+ encrypt(buffer + BLOCK_SIZE);
+ }
+ else
+ { // steal ciphertext
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+ cipher->encrypt(buffer);
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ poly_double(tweak, cipher->BLOCK_SIZE);
+
+ for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i)
+ std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]);
+
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+ cipher->encrypt(buffer);
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ send(buffer, position);
+ }
+
+ position = 0;
+ }
+
+/*
+* XTS_Decryption constructor
+*/
+XTS_Decryption::XTS_Decryption(BlockCipher* ciph)
+ {
+ cipher = ciph;
+ cipher2 = ciph->clone();
+ tweak.create(cipher->BLOCK_SIZE);
+ buffer.create(2 * cipher->BLOCK_SIZE);
+ position = 0;
+ }
+
+/*
+* XTS_Decryption constructor
+*/
+XTS_Decryption::XTS_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv)
+ {
+ cipher = ciph;
+ cipher2 = ciph->clone();
+ tweak.create(cipher->BLOCK_SIZE);
+ buffer.create(2 * cipher->BLOCK_SIZE);
+ position = 0;
+
+ set_key(key);
+ set_iv(iv);
+ }
+
+/*
+* Return the name
+*/
+std::string XTS_Decryption::name() const
+ {
+ return (cipher->name() + "/XTS");
+ }
+
+/*
+* Set new tweak
+*/
+void XTS_Decryption::set_iv(const InitializationVector& iv)
+ {
+ if(iv.length() != tweak.size())
+ throw Invalid_IV_Length(name(), iv.length());
+
+ tweak = iv.bits_of();
+ cipher2->encrypt(tweak);
+ }
+
+void XTS_Decryption::set_key(const SymmetricKey& key)
+ {
+ u32bit key_half = key.length() / 2;
+
+ if(key.length() % 2 == 1 || !cipher->valid_keylength(key_half))
+ throw Invalid_Key_Length(name(), key.length());
+
+ cipher->set_key(key.begin(), key_half);
+ cipher2->set_key(key.begin() + key_half, key_half);
+ }
+
+/*
+* Decrypt a block
+*/
+void XTS_Decryption::decrypt(const byte block[])
+ {
+ xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
+ cipher->decrypt(buffer);
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ poly_double(tweak, cipher->BLOCK_SIZE);
+
+ send(buffer, cipher->BLOCK_SIZE);
+ }
+
+/*
+* Decrypt in XTS mode
+*/
+void XTS_Decryption::write(const byte input[], u32bit length)
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ u32bit copied = std::min(buffer.size() - position, length);
+ buffer.copy(position, input, copied);
+ length -= copied;
+ input += copied;
+ position += copied;
+
+ if(length == 0) return;
+
+ decrypt(buffer);
+ if(length > BLOCK_SIZE)
+ {
+ decrypt(buffer + BLOCK_SIZE);
+ while(length > 2*BLOCK_SIZE)
+ {
+ decrypt(input);
+ length -= BLOCK_SIZE;
+ input += BLOCK_SIZE;
+ }
+ position = 0;
+ }
+ else
+ {
+ copy_mem(buffer.begin(), buffer + BLOCK_SIZE, BLOCK_SIZE);
+ position = BLOCK_SIZE;
+ }
+ buffer.copy(position, input, length);
+ position += length;
+ }
+
+/*
+* Finish decrypting in XTS mode
+*/
+void XTS_Decryption::end_msg()
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ if(position < BLOCK_SIZE)
+ throw Exception("XTS_Decryption: insufficient data to decrypt");
+ else if(position == BLOCK_SIZE)
+ {
+ decrypt(buffer);
+ }
+ else if(position == 2*BLOCK_SIZE)
+ {
+ decrypt(buffer);
+ decrypt(buffer + BLOCK_SIZE);
+ }
+ else
+ {
+ SecureVector<byte> tweak2 = tweak;
+
+ poly_double(tweak2, cipher->BLOCK_SIZE);
+
+ xor_buf(buffer, tweak2, cipher->BLOCK_SIZE);
+ cipher->decrypt(buffer);
+ xor_buf(buffer, tweak2, cipher->BLOCK_SIZE);
+
+ for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i)
+ std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]);
+
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+ cipher->decrypt(buffer);
+ xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
+
+ send(buffer, position);
+ }
+
+ position = 0;
+ }
+
+}
diff --git a/botan/src/modes/xts/xts.h b/botan/src/modes/xts/xts.h
new file mode 100644
index 0000000..0155817
--- /dev/null
+++ b/botan/src/modes/xts/xts.h
@@ -0,0 +1,76 @@
+/*
+* XTS mode, from IEEE P1619
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XTS_H__
+#define BOTAN_XTS_H__
+
+#include <botan/basefilt.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/*
+* XTS Encryption
+*/
+class BOTAN_DLL XTS_Encryption : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey& key);
+ void set_iv(const InitializationVector& iv);
+
+ std::string name() const;
+
+ XTS_Encryption(BlockCipher* ciph);
+
+ XTS_Encryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+
+ ~XTS_Encryption() { delete cipher; delete cipher2; }
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void encrypt(const byte block[]);
+
+ BlockCipher* cipher;
+ BlockCipher* cipher2;
+ SecureVector<byte> tweak;
+ SecureVector<byte> buffer;
+ u32bit position;
+ };
+
+/*
+* XTS Decryption
+*/
+class BOTAN_DLL XTS_Decryption : public Keyed_Filter
+ {
+ public:
+ void set_key(const SymmetricKey& key);
+ void set_iv(const InitializationVector& iv);
+
+ std::string name() const;
+
+ XTS_Decryption(BlockCipher* ciph);
+
+ XTS_Decryption(BlockCipher* ciph,
+ const SymmetricKey& key,
+ const InitializationVector& iv);
+ private:
+ void write(const byte[], u32bit);
+ void end_msg();
+ void decrypt(const byte[]);
+
+ BlockCipher* cipher;
+ BlockCipher* cipher2;
+ SecureVector<byte> tweak;
+ SecureVector<byte> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mutex/info.txt b/botan/src/mutex/info.txt
new file mode 100644
index 0000000..ff79bf7
--- /dev/null
+++ b/botan/src/mutex/info.txt
@@ -0,0 +1,9 @@
+realname "Mutex Wrappers"
+
+define MUTEX_WRAPPERS
+
+load_on auto
+
+<add>
+mutex.h
+</add>
diff --git a/botan/src/mutex/mutex.h b/botan/src/mutex/mutex.h
new file mode 100644
index 0000000..a04ff83
--- /dev/null
+++ b/botan/src/mutex/mutex.h
@@ -0,0 +1,56 @@
+/*
+* Mutex
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_H__
+#define BOTAN_MUTEX_H__
+
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+/*
+* Mutex Base Class
+*/
+class BOTAN_DLL Mutex
+ {
+ public:
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
+ virtual ~Mutex() {}
+ };
+
+/*
+* Mutex Factory
+*/
+class BOTAN_DLL Mutex_Factory
+ {
+ public:
+ virtual Mutex* make() = 0;
+ virtual ~Mutex_Factory() {}
+ };
+
+/*
+* Mutex Holding Class
+*/
+class BOTAN_DLL Mutex_Holder
+ {
+ public:
+ Mutex_Holder(Mutex* m) : mux(m)
+ {
+ if(!mux)
+ throw Invalid_Argument("Mutex_Holder: Argument was NULL");
+ mux->lock();
+ }
+
+ ~Mutex_Holder() { mux->unlock(); }
+ private:
+ Mutex* mux;
+ };
+
+}
+
+#endif
diff --git a/botan/src/mutex/noop_mutex/info.txt b/botan/src/mutex/noop_mutex/info.txt
new file mode 100644
index 0000000..1f49f5e
--- /dev/null
+++ b/botan/src/mutex/noop_mutex/info.txt
@@ -0,0 +1,10 @@
+realname "No-Op Mutex"
+
+load_on auto
+
+define MUTEX_NOOP
+
+<add>
+mux_noop.cpp
+mux_noop.h
+</add>
diff --git a/botan/src/mutex/noop_mutex/mux_noop.cpp b/botan/src/mutex/noop_mutex/mux_noop.cpp
new file mode 100644
index 0000000..5c45084
--- /dev/null
+++ b/botan/src/mutex/noop_mutex/mux_noop.cpp
@@ -0,0 +1,50 @@
+/*
+* No-Op Mutex Factory
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mux_noop.h>
+
+namespace Botan {
+
+/*
+* No-Op Mutex Factory
+*/
+Mutex* Noop_Mutex_Factory::make()
+ {
+ class Noop_Mutex : public Mutex
+ {
+ public:
+ class Mutex_State_Error : public Internal_Error
+ {
+ public:
+ Mutex_State_Error(const std::string& where) :
+ Internal_Error("Noop_Mutex::" + where + ": " +
+ "Mutex is already " + where + "ed") {}
+ };
+
+ void lock()
+ {
+ if(locked)
+ throw Mutex_State_Error("lock");
+ locked = true;
+ }
+
+ void unlock()
+ {
+ if(!locked)
+ throw Mutex_State_Error("unlock");
+ locked = false;
+ }
+
+ Noop_Mutex() { locked = false; }
+ private:
+ bool locked;
+ };
+
+ return new Noop_Mutex;
+ }
+
+}
diff --git a/botan/src/mutex/noop_mutex/mux_noop.h b/botan/src/mutex/noop_mutex/mux_noop.h
new file mode 100644
index 0000000..94201cb
--- /dev/null
+++ b/botan/src/mutex/noop_mutex/mux_noop.h
@@ -0,0 +1,26 @@
+/*
+* No-Op Mutex Factory
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NOOP_MUTEX_FACTORY_H__
+#define BOTAN_NOOP_MUTEX_FACTORY_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* No-Op Mutex Factory
+*/
+class BOTAN_DLL Noop_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/botan/src/mutex/pthreads/info.txt b/botan/src/mutex/pthreads/info.txt
new file mode 100644
index 0000000..f135dea
--- /dev/null
+++ b/botan/src/mutex/pthreads/info.txt
@@ -0,0 +1,30 @@
+realname "Pthread Mutex"
+
+define MUTEX_PTHREAD
+
+load_on auto
+
+<add>
+mux_pthr.cpp
+mux_pthr.h
+</add>
+
+<libs>
+all!qnx,freebsd,dragonfly,openbsd,netbsd -> pthread
+</libs>
+
+<os>
+aix
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
diff --git a/botan/src/mutex/pthreads/mux_pthr.cpp b/botan/src/mutex/pthreads/mux_pthr.cpp
new file mode 100644
index 0000000..9f1d981
--- /dev/null
+++ b/botan/src/mutex/pthreads/mux_pthr.cpp
@@ -0,0 +1,58 @@
+/*
+* Pthread Mutex
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mux_pthr.h>
+#include <botan/exceptn.h>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199506
+#endif
+
+#include <pthread.h>
+
+namespace Botan {
+
+/*
+* Pthread Mutex Factory
+*/
+Mutex* Pthread_Mutex_Factory::make()
+ {
+
+ class Pthread_Mutex : public Mutex
+ {
+ public:
+ void lock()
+ {
+ if(pthread_mutex_lock(&mutex) != 0)
+ throw Exception("Pthread_Mutex::lock: Error occured");
+ }
+
+ void unlock()
+ {
+ if(pthread_mutex_unlock(&mutex) != 0)
+ throw Exception("Pthread_Mutex::unlock: Error occured");
+ }
+
+ Pthread_Mutex()
+ {
+ if(pthread_mutex_init(&mutex, 0) != 0)
+ throw Exception("Pthread_Mutex: initialization failed");
+ }
+
+ ~Pthread_Mutex()
+ {
+ if(pthread_mutex_destroy(&mutex) != 0)
+ throw Invalid_State("~Pthread_Mutex: mutex is still locked");
+ }
+ private:
+ pthread_mutex_t mutex;
+ };
+
+ return new Pthread_Mutex();
+ }
+
+}
diff --git a/botan/src/mutex/pthreads/mux_pthr.h b/botan/src/mutex/pthreads/mux_pthr.h
new file mode 100644
index 0000000..1188539
--- /dev/null
+++ b/botan/src/mutex/pthreads/mux_pthr.h
@@ -0,0 +1,26 @@
+/*
+* Pthread Mutex
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_PTHREAD_H__
+#define BOTAN_MUTEX_PTHREAD_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* Pthread Mutex Factory
+*/
+class BOTAN_DLL Pthread_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/botan/src/mutex/qt_mutex/info.txt b/botan/src/mutex/qt_mutex/info.txt
new file mode 100644
index 0000000..a21108c
--- /dev/null
+++ b/botan/src/mutex/qt_mutex/info.txt
@@ -0,0 +1,18 @@
+realname "Qt Mutex"
+
+define MUTEX_QT
+
+note "You'll probably have to add -I/-L flags to the Makefile to find Qt"
+
+load_on request
+
+<add>
+mux_qt.cpp
+mux_qt.h
+</add>
+
+# I think we want to always use qt-mt, not qt -- not much point in supporting
+# mutexes in a single threaded application, after all.
+<libs>
+all -> qt-mt
+</libs>
diff --git a/botan/src/mutex/qt_mutex/mux_qt.cpp b/botan/src/mutex/qt_mutex/mux_qt.cpp
new file mode 100644
index 0000000..0f670c8
--- /dev/null
+++ b/botan/src/mutex/qt_mutex/mux_qt.cpp
@@ -0,0 +1,35 @@
+/*
+* Qt Thread Mutex
+* (C) 2004-2007 Justin Karneges
+* 2004-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mux_qt.h>
+#include <qmutex.h>
+
+#if !defined(QT_THREAD_SUPPORT)
+ #error Your version of Qt does not support threads or mutexes
+#endif
+
+namespace Botan {
+
+/*
+* Qt Mutex Factory
+*/
+Mutex* Qt_Mutex_Factory::make()
+ {
+ class Qt_Mutex : public Mutex
+ {
+ public:
+ void lock() { mutex.lock(); }
+ void unlock() { mutex.unlock(); }
+ private:
+ QMutex mutex;
+ };
+
+ return new Qt_Mutex();
+ }
+
+}
diff --git a/botan/src/mutex/qt_mutex/mux_qt.h b/botan/src/mutex/qt_mutex/mux_qt.h
new file mode 100644
index 0000000..5aed77f
--- /dev/null
+++ b/botan/src/mutex/qt_mutex/mux_qt.h
@@ -0,0 +1,27 @@
+/*
+* Qt Mutex
+* (C) 2004-2007 Justin Karneges
+* 2004-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_QT_H__
+#define BOTAN_MUTEX_QT_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* Qt Mutex
+*/
+class BOTAN_DLL Qt_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+
+}
+
+#endif
diff --git a/botan/src/mutex/win32_crit_section/info.txt b/botan/src/mutex/win32_crit_section/info.txt
new file mode 100644
index 0000000..a2d339c
--- /dev/null
+++ b/botan/src/mutex/win32_crit_section/info.txt
@@ -0,0 +1,17 @@
+realname "Win32 Mutex"
+
+define MUTEX_WIN32
+modset win32
+
+load_on auto
+
+<add>
+mux_win32.cpp
+mux_win32.h
+</add>
+
+<os>
+cygwin
+windows
+mingw
+</os>
diff --git a/botan/src/mutex/win32_crit_section/mux_win32.cpp b/botan/src/mutex/win32_crit_section/mux_win32.cpp
new file mode 100644
index 0000000..2a96789
--- /dev/null
+++ b/botan/src/mutex/win32_crit_section/mux_win32.cpp
@@ -0,0 +1,34 @@
+/*
+* Win32 Mutex
+* (C) 2006 Luca Piccarreta
+* 2006-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mux_win32.h>
+#include <windows.h>
+
+namespace Botan {
+
+/*
+* Win32 Mutex Factory
+*/
+Mutex* Win32_Mutex_Factory::make()
+ {
+ class Win32_Mutex : public Mutex
+ {
+ public:
+ void lock() { EnterCriticalSection(&mutex); }
+ void unlock() { LeaveCriticalSection(&mutex); }
+
+ Win32_Mutex() { InitializeCriticalSection(&mutex); }
+ ~Win32_Mutex() { DeleteCriticalSection(&mutex); }
+ private:
+ CRITICAL_SECTION mutex;
+ };
+
+ return new Win32_Mutex();
+ }
+
+}
diff --git a/botan/src/mutex/win32_crit_section/mux_win32.h b/botan/src/mutex/win32_crit_section/mux_win32.h
new file mode 100644
index 0000000..a91850e
--- /dev/null
+++ b/botan/src/mutex/win32_crit_section/mux_win32.h
@@ -0,0 +1,26 @@
+/*
+* Win32 Mutex
+* (C) 2006 Luca Piccarreta
+* 2006-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MUTEX_WIN32_H__
+#define BOTAN_MUTEX_WIN32_H__
+
+#include <botan/mutex.h>
+
+namespace Botan {
+
+/*
+* Win32 Mutex Factory
+*/
+class BOTAN_DLL Win32_Mutex_Factory : public Mutex_Factory
+ {
+ public:
+ Mutex* make();
+ };
+}
+
+#endif
diff --git a/botan/src/pbe/get_pbe.cpp b/botan/src/pbe/get_pbe.cpp
new file mode 100644
index 0000000..3217101
--- /dev/null
+++ b/botan/src/pbe/get_pbe.cpp
@@ -0,0 +1,130 @@
+/*
+* PBE Retrieval
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/get_pbe.h>
+#include <botan/oids.h>
+#include <botan/scan_name.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ #include <botan/pbes1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ #include <botan/pbes2.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get an encryption PBE, set new parameters
+*/
+PBE* get_pbe(const std::string& algo_spec)
+ {
+ SCAN_Name request(algo_spec);
+
+ const std::string pbe = request.algo_name();
+ std::string digest_name = request.arg(0);
+ const std::string cipher = request.arg(1);
+
+ std::vector<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);
+
+ const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
+ const std::string cipher_mode = cipher_spec[1];
+
+ if(cipher_mode != "CBC")
+ throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
+ if(!block_cipher)
+ throw Algorithm_Not_Found(cipher_algo);
+
+ const HashFunction* hash_function = af.prototype_hash_function(digest_name);
+ if(!hash_function)
+ throw Algorithm_Not_Found(digest_name);
+
+ if(request.arg_count() != 2)
+ throw Invalid_Algorithm_Name(algo_spec);
+
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ if(pbe == "PBE-PKCS5v15")
+ return new PBE_PKCS5v15(block_cipher->clone(),
+ hash_function->clone(),
+ ENCRYPTION);
+#endif
+
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ if(pbe == "PBE-PKCS5v20")
+ return new PBE_PKCS5v20(block_cipher->clone(),
+ hash_function->clone());
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*
+* Get a decryption PBE, decode parameters
+*/
+PBE* get_pbe(const OID& pbe_oid, DataSource& params)
+ {
+ SCAN_Name request(OIDS::lookup(pbe_oid));
+
+ const std::string pbe = request.algo_name();
+
+#if defined(BOTAN_HAS_PBE_PKCS_V15)
+ if(pbe == "PBE-PKCS5v15")
+ {
+ if(request.arg_count() != 2)
+ throw Invalid_Algorithm_Name(request.as_string());
+
+ std::string digest_name = request.arg(0);
+ const std::string cipher = request.arg(1);
+
+ std::vector<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);
+
+ const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
+ const std::string cipher_mode = cipher_spec[1];
+
+ if(cipher_mode != "CBC")
+ throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
+ if(!block_cipher)
+ throw Algorithm_Not_Found(cipher_algo);
+
+ const HashFunction* hash_function =
+ af.prototype_hash_function(digest_name);
+
+ if(!hash_function)
+ throw Algorithm_Not_Found(digest_name);
+
+ PBE* pbe = new PBE_PKCS5v15(block_cipher->clone(),
+ hash_function->clone(),
+ DECRYPTION);
+ pbe->decode_params(params);
+ return pbe;
+ }
+#endif
+
+#if defined(BOTAN_HAS_PBE_PKCS_V20)
+ if(pbe == "PBE-PKCS5v20")
+ return new PBE_PKCS5v20(params);
+#endif
+
+ throw Algorithm_Not_Found(pbe_oid.as_string());
+ }
+
+}
diff --git a/botan/src/pbe/get_pbe.h b/botan/src/pbe/get_pbe.h
new file mode 100644
index 0000000..04eda66
--- /dev/null
+++ b/botan/src/pbe/get_pbe.h
@@ -0,0 +1,33 @@
+/*
+* PBE Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOOKUP_PBE_H__
+#define BOTAN_LOOKUP_PBE_H__
+
+#include <botan/pbe.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Factory function for PBEs.
+* @param algo_spec the name of the PBE algorithm to retrieve
+* @return a pointer to a PBE with randomly created parameters
+*/
+BOTAN_DLL PBE* get_pbe(const std::string&);
+
+/**
+* Factory function for PBEs.
+* @param pbe_oid the oid of the desired PBE
+* @param params a DataSource providing the DER encoded parameters to use
+* @return a pointer to the PBE with the specified parameters
+*/
+BOTAN_DLL PBE* get_pbe(const OID&, DataSource&);
+
+}
+
+#endif
diff --git a/botan/src/pbe/info.txt b/botan/src/pbe/info.txt
new file mode 100644
index 0000000..c4210b2
--- /dev/null
+++ b/botan/src/pbe/info.txt
@@ -0,0 +1,16 @@
+realname "PBE Base"
+
+load_on dep
+
+define PASSWORD_BASED_ENCRYPTION
+
+<add>
+get_pbe.cpp
+get_pbe.h
+</add>
+
+<requires>
+filters
+libstate
+oid_lookup
+</requires>
diff --git a/botan/src/pbe/pbes1/info.txt b/botan/src/pbe/pbes1/info.txt
new file mode 100644
index 0000000..70c6bae
--- /dev/null
+++ b/botan/src/pbe/pbes1/info.txt
@@ -0,0 +1,19 @@
+realname "PKCS5 v1.5 PBE"
+
+define PBE_PKCS_V15
+
+load_on auto
+
+<add>
+pbes1.cpp
+pbes1.h
+</add>
+
+<requires>
+asn1
+block
+cbc
+filters
+hash
+pbkdf1
+</requires>
diff --git a/botan/src/pbe/pbes1/pbes1.cpp b/botan/src/pbe/pbes1/pbes1.cpp
new file mode 100644
index 0000000..21bd330
--- /dev/null
+++ b/botan/src/pbe/pbes1/pbes1.cpp
@@ -0,0 +1,184 @@
+/*
+* PKCS #5 PBES1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pbes1.h>
+#include <botan/pbkdf1.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/cbc.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Encrypt some bytes using PBES1
+*/
+void PBE_PKCS5v15::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit put = std::min(DEFAULT_BUFFERSIZE, length);
+ pipe.write(input, length);
+ flush_pipe(true);
+ length -= put;
+ }
+ }
+
+/*
+* Start encrypting with PBES1
+*/
+void PBE_PKCS5v15::start_msg()
+ {
+ if(direction == ENCRYPTION)
+ pipe.append(new CBC_Encryption(block_cipher->clone(),
+ new PKCS7_Padding,
+ key, iv));
+ else
+ pipe.append(new CBC_Decryption(block_cipher->clone(),
+ new PKCS7_Padding,
+ key, iv));
+
+ pipe.start_msg();
+ if(pipe.message_count() > 1)
+ pipe.set_default_msg(pipe.default_msg() + 1);
+ }
+
+/*
+* Finish encrypting with PBES1
+*/
+void PBE_PKCS5v15::end_msg()
+ {
+ pipe.end_msg();
+ flush_pipe(false);
+ pipe.reset();
+ }
+
+/*
+* Flush the pipe
+*/
+void PBE_PKCS5v15::flush_pipe(bool safe_to_skip)
+ {
+ if(safe_to_skip && pipe.remaining() < 64)
+ return;
+
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ send(buffer, got);
+ }
+ }
+
+/*
+* Set the passphrase to use
+*/
+void PBE_PKCS5v15::set_key(const std::string& passphrase)
+ {
+ PKCS5_PBKDF1 pbkdf(hash_function->clone());
+
+ pbkdf.set_iterations(iterations);
+ pbkdf.change_salt(salt, salt.size());
+ SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase);
+
+ key.set(key_and_iv.begin(), 8);
+ iv.set(key_and_iv.begin() + 8, 8);
+ }
+
+/*
+* Create a new set of PBES1 parameters
+*/
+void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng)
+ {
+ iterations = 2048;
+ salt.create(8);
+ rng.randomize(salt, salt.size());
+ }
+
+/*
+* Encode PKCS#5 PBES1 parameters
+*/
+MemoryVector<byte> PBE_PKCS5v15::encode_params() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(salt, OCTET_STRING)
+ .encode(iterations)
+ .end_cons()
+ .get_contents();
+ }
+
+/*
+* Decode PKCS#5 PBES1 parameters
+*/
+void PBE_PKCS5v15::decode_params(DataSource& source)
+ {
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(salt, OCTET_STRING)
+ .decode(iterations)
+ .verify_end()
+ .end_cons();
+
+ if(salt.size() != 8)
+ throw Decoding_Error("PBES1: Encoded salt is not 8 octets");
+ }
+
+/*
+* Return an OID for this PBES1 type
+*/
+OID PBE_PKCS5v15::get_oid() const
+ {
+ const OID base_pbes1_oid("1.2.840.113549.1.5");
+
+ const std::string cipher = block_cipher->name();
+ const std::string digest = hash_function->name();
+
+ if(cipher == "DES" && digest == "MD2")
+ return (base_pbes1_oid + 1);
+ else if(cipher == "DES" && digest == "MD5")
+ return (base_pbes1_oid + 3);
+ else if(cipher == "DES" && digest == "SHA-160")
+ return (base_pbes1_oid + 10);
+ else if(cipher == "RC2" && digest == "MD2")
+ return (base_pbes1_oid + 4);
+ else if(cipher == "RC2" && digest == "MD5")
+ return (base_pbes1_oid + 6);
+ else if(cipher == "RC2" && digest == "SHA-160")
+ return (base_pbes1_oid + 11);
+ else
+ throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options");
+ }
+
+/*
+* PKCS#5 v1.5 PBE Constructor
+*/
+PBE_PKCS5v15::PBE_PKCS5v15(BlockCipher* cipher,
+ HashFunction* hash,
+ Cipher_Dir dir) :
+ direction(dir), block_cipher(cipher), hash_function(hash)
+ {
+ if(cipher->name() != "DES" && cipher->name() != "RC2")
+ {
+ throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " +
+ cipher->name());
+ }
+
+ if(hash->name() != "MD2" && hash->name() != "MD5" &&
+ hash->name() != "SHA-160")
+ {
+ throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " +
+ hash->name());
+ }
+ }
+
+PBE_PKCS5v15::~PBE_PKCS5v15()
+ {
+ delete block_cipher;
+ delete hash_function;
+ }
+
+}
diff --git a/botan/src/pbe/pbes1/pbes1.h b/botan/src/pbe/pbes1/pbes1.h
new file mode 100644
index 0000000..2e1855d
--- /dev/null
+++ b/botan/src/pbe/pbes1/pbes1.h
@@ -0,0 +1,53 @@
+/*
+* PKCS #5 v1.5 PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_PKCS_V15_H__
+#define BOTAN_PBE_PKCS_V15_H__
+
+#include <botan/pbe.h>
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* PKCS#5 v1.5 PBE
+*/
+class BOTAN_DLL PBE_PKCS5v15 : public PBE
+ {
+ public:
+ void write(const byte[], u32bit);
+ void start_msg();
+ void end_msg();
+
+ PBE_PKCS5v15(BlockCipher* cipher,
+ HashFunction* hash,
+ Cipher_Dir);
+
+ ~PBE_PKCS5v15();
+ private:
+ void set_key(const std::string&);
+ void new_params(RandomNumberGenerator& rng);
+ MemoryVector<byte> encode_params() const;
+ void decode_params(DataSource&);
+ OID get_oid() const;
+
+ void flush_pipe(bool);
+
+ Cipher_Dir direction;
+ BlockCipher* block_cipher;
+ HashFunction* hash_function;
+
+ SecureVector<byte> salt, key, iv;
+ u32bit iterations;
+ Pipe pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pbe/pbes2/info.txt b/botan/src/pbe/pbes2/info.txt
new file mode 100644
index 0000000..cd37b1e
--- /dev/null
+++ b/botan/src/pbe/pbes2/info.txt
@@ -0,0 +1,23 @@
+realname "PKCS5 v2.0 PBE"
+
+define PBE_PKCS_V20
+
+load_on auto
+
+<add>
+pbes2.cpp
+pbes2.h
+</add>
+
+<requires>
+algo_factory
+asn1
+block
+cbc
+filters
+hash
+hmac
+libstate
+oid_lookup
+pbkdf2
+</requires>
diff --git a/botan/src/pbe/pbes2/pbes2.cpp b/botan/src/pbe/pbes2/pbes2.cpp
new file mode 100644
index 0000000..b7e2589
--- /dev/null
+++ b/botan/src/pbe/pbes2/pbes2.cpp
@@ -0,0 +1,239 @@
+/**
+* PKCS #5 PBES2
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pbes2.h>
+#include <botan/pbkdf2.h>
+#include <botan/hmac.h>
+#include <botan/cbc.h>
+#include <botan/algo_factory.h>
+#include <botan/libstate.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/asn1_obj.h>
+#include <botan/oids.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/**
+* Encrypt some bytes using PBES2
+*/
+void PBE_PKCS5v20::write(const byte input[], u32bit length)
+ {
+ while(length)
+ {
+ u32bit put = std::min(DEFAULT_BUFFERSIZE, length);
+ pipe.write(input, length);
+ flush_pipe(true);
+ length -= put;
+ }
+ }
+
+/**
+* Start encrypting with PBES2
+*/
+void PBE_PKCS5v20::start_msg()
+ {
+ if(direction == ENCRYPTION)
+ pipe.append(new CBC_Encryption(block_cipher->clone(),
+ new PKCS7_Padding,
+ key, iv));
+ else
+ pipe.append(new CBC_Decryption(block_cipher->clone(),
+ new PKCS7_Padding,
+ key, iv));
+
+ pipe.start_msg();
+ if(pipe.message_count() > 1)
+ pipe.set_default_msg(pipe.default_msg() + 1);
+ }
+
+/**
+* Finish encrypting with PBES2
+*/
+void PBE_PKCS5v20::end_msg()
+ {
+ pipe.end_msg();
+ flush_pipe(false);
+ pipe.reset();
+ }
+
+/**
+* Flush the pipe
+*/
+void PBE_PKCS5v20::flush_pipe(bool safe_to_skip)
+ {
+ if(safe_to_skip && pipe.remaining() < 64)
+ return;
+
+ SecureVector<byte> buffer(DEFAULT_BUFFERSIZE);
+ while(pipe.remaining())
+ {
+ u32bit got = pipe.read(buffer, buffer.size());
+ send(buffer, got);
+ }
+ }
+
+/**
+* Set the passphrase to use
+*/
+void PBE_PKCS5v20::set_key(const std::string& passphrase)
+ {
+ PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone()));
+
+ pbkdf.set_iterations(iterations);
+ pbkdf.change_salt(salt, salt.size());
+ key = pbkdf.derive_key(key_length, passphrase).bits_of();
+ }
+
+/**
+* Create a new set of PBES2 parameters
+*/
+void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng)
+ {
+ iterations = 2048;
+ key_length = block_cipher->MAXIMUM_KEYLENGTH;
+
+ salt.create(8);
+ rng.randomize(salt, salt.size());
+
+ iv.create(block_cipher->BLOCK_SIZE);
+ rng.randomize(iv, iv.size());
+ }
+
+/**
+* Encode PKCS#5 PBES2 parameters
+*/
+MemoryVector<byte> PBE_PKCS5v20::encode_params() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(
+ AlgorithmIdentifier("PKCS5.PBKDF2",
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(salt, OCTET_STRING)
+ .encode(iterations)
+ .encode(key_length)
+ .end_cons()
+ .get_contents()
+ )
+ )
+ .encode(
+ AlgorithmIdentifier(block_cipher->name() + "/CBC",
+ DER_Encoder()
+ .encode(iv, OCTET_STRING)
+ .get_contents()
+ )
+ )
+ .end_cons()
+ .get_contents();
+ }
+
+/**
+* Decode PKCS#5 PBES2 parameters
+*/
+void PBE_PKCS5v20::decode_params(DataSource& source)
+ {
+ AlgorithmIdentifier kdf_algo, enc_algo;
+
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(kdf_algo)
+ .decode(enc_algo)
+ .verify_end()
+ .end_cons();
+
+ if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2"))
+ {
+ BER_Decoder(kdf_algo.parameters)
+ .start_cons(SEQUENCE)
+ .decode(salt, OCTET_STRING)
+ .decode(iterations)
+ .decode_optional(key_length, INTEGER, UNIVERSAL)
+ .verify_end()
+ .end_cons();
+ }
+ else
+ throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " +
+ kdf_algo.oid.as_string());
+
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ std::string cipher = OIDS::lookup(enc_algo.oid);
+ std::vector<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
+
+ if(!known_cipher(cipher_spec[0]) || cipher_spec[1] != "CBC")
+ throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " +
+ cipher);
+
+ BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end();
+
+ block_cipher = af.make_block_cipher(cipher_spec[0]);
+ hash_function = af.make_hash_function("SHA-160");
+
+ if(key_length == 0)
+ key_length = block_cipher->MAXIMUM_KEYLENGTH;
+
+ if(salt.size() < 8)
+ throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small");
+ }
+
+/**
+* Return an OID for PBES2
+*/
+OID PBE_PKCS5v20::get_oid() const
+ {
+ return OIDS::lookup("PBE-PKCS5v20");
+ }
+
+/**
+* Check if this is a known PBES2 cipher
+*/
+bool PBE_PKCS5v20::known_cipher(const std::string& algo)
+ {
+ if(algo == "AES-128" || algo == "AES-192" || algo == "AES-256")
+ return true;
+ if(algo == "DES" || algo == "TripleDES")
+ return true;
+ return false;
+ }
+
+/**
+* PKCS#5 v2.0 PBE Constructor
+*/
+PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher,
+ HashFunction* digest) :
+ direction(ENCRYPTION), block_cipher(cipher), hash_function(digest)
+ {
+ if(!known_cipher(block_cipher->name()))
+ throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher " + cipher->name());
+ if(hash_function->name() != "SHA-160")
+ throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid digest " + digest->name());
+ }
+
+/**
+* PKCS#5 v2.0 PBE Constructor
+*/
+PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION)
+ {
+ hash_function = 0;
+ block_cipher = 0;
+ decode_params(params);
+ }
+
+PBE_PKCS5v20::~PBE_PKCS5v20()
+ {
+ delete hash_function;
+ delete block_cipher;
+ }
+
+}
diff --git a/botan/src/pbe/pbes2/pbes2.h b/botan/src/pbe/pbes2/pbes2.h
new file mode 100644
index 0000000..fc460a2
--- /dev/null
+++ b/botan/src/pbe/pbes2/pbes2.h
@@ -0,0 +1,53 @@
+/*
+* PKCS #5 v2.0 PBE
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBE_PKCS_v20_H__
+#define BOTAN_PBE_PKCS_v20_H__
+
+#include <botan/pbe.h>
+#include <botan/block_cipher.h>
+#include <botan/hash.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+/*
+* PKCS#5 v2.0 PBE
+*/
+class BOTAN_DLL PBE_PKCS5v20 : public PBE
+ {
+ public:
+ static bool known_cipher(const std::string&);
+
+ void write(const byte[], u32bit);
+ void start_msg();
+ void end_msg();
+
+ PBE_PKCS5v20(DataSource&);
+ PBE_PKCS5v20(BlockCipher*, HashFunction*);
+
+ ~PBE_PKCS5v20();
+ private:
+ void set_key(const std::string&);
+ void new_params(RandomNumberGenerator& rng);
+ MemoryVector<byte> encode_params() const;
+ void decode_params(DataSource&);
+ OID get_oid() const;
+
+ void flush_pipe(bool);
+
+ Cipher_Dir direction;
+ BlockCipher* block_cipher;
+ HashFunction* hash_function;
+ SecureVector<byte> salt, key, iv;
+ u32bit iterations, key_length;
+ Pipe pipe;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/eme.cpp b/botan/src/pk_pad/eme.cpp
new file mode 100644
index 0000000..74bba5a
--- /dev/null
+++ b/botan/src/pk_pad/eme.cpp
@@ -0,0 +1,50 @@
+/*
+* EME Base Class
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eme.h>
+
+namespace Botan {
+
+/*
+* Encode a message
+*/
+SecureVector<byte> EME::encode(const byte msg[], u32bit msg_len,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg_len, key_bits, rng);
+ }
+
+/*
+* Encode a message
+*/
+SecureVector<byte> EME::encode(const MemoryRegion<byte>& msg,
+ u32bit key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg.size(), key_bits, rng);
+ }
+
+/*
+* Decode a message
+*/
+SecureVector<byte> EME::decode(const byte msg[], u32bit msg_len,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg_len, key_bits);
+ }
+
+/*
+* Decode a message
+*/
+SecureVector<byte> EME::decode(const MemoryRegion<byte>& msg,
+ u32bit key_bits) const
+ {
+ return unpad(msg, msg.size(), key_bits);
+ }
+
+}
diff --git a/botan/src/pk_pad/eme.h b/botan/src/pk_pad/eme.h
new file mode 100644
index 0000000..321c1d0
--- /dev/null
+++ b/botan/src/pk_pad/eme.h
@@ -0,0 +1,42 @@
+/*
+* EME Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__
+#define BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Encoding Method for Encryption
+*/
+class BOTAN_DLL EME
+ {
+ public:
+ virtual u32bit maximum_input_size(u32bit) const = 0;
+
+ SecureVector<byte> encode(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> encode(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decode(const byte[], u32bit, u32bit) const;
+ SecureVector<byte> decode(const MemoryRegion<byte>&, u32bit) const;
+
+ virtual ~EME() {}
+ private:
+ virtual SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const = 0;
+
+ virtual SecureVector<byte> unpad(const byte[], u32bit, u32bit) const = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/eme1/eme1.cpp b/botan/src/pk_pad/eme1/eme1.cpp
new file mode 100644
index 0000000..13f68f8
--- /dev/null
+++ b/botan/src/pk_pad/eme1/eme1.cpp
@@ -0,0 +1,103 @@
+/*
+* EME1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eme1.h>
+#include <botan/mgf1.h>
+#include <memory>
+
+namespace Botan {
+
+/*
+* EME1 Pad Operation
+*/
+SecureVector<byte> EME1::pad(const byte in[], u32bit in_length,
+ u32bit key_length,
+ RandomNumberGenerator& rng) const
+ {
+ key_length /= 8;
+
+ if(in_length > key_length - 2*HASH_LENGTH - 1)
+ throw Exception("EME1: Input is too large");
+
+ SecureVector<byte> out(key_length);
+
+ out.clear();
+
+ rng.randomize(out, HASH_LENGTH);
+
+ out.copy(HASH_LENGTH, Phash, Phash.size());
+ out[out.size() - in_length - 1] = 0x01;
+ out.copy(out.size() - in_length, in, in_length);
+ mgf->mask(out, HASH_LENGTH, out + HASH_LENGTH, out.size() - HASH_LENGTH);
+ mgf->mask(out + HASH_LENGTH, out.size() - HASH_LENGTH, out, HASH_LENGTH);
+
+ return out;
+ }
+
+/*
+* EME1 Unpad Operation
+*/
+SecureVector<byte> EME1::unpad(const byte in[], u32bit in_length,
+ u32bit key_length) const
+ {
+ /*
+ Must be careful about error messages here; if an attacker can
+ distinguish them, it is easy to use the differences as an oracle to
+ find the secret key, as described in "A Chosen Ciphertext Attack on
+ RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in
+ PKCS #1 v2.0", James Manger, Crypto 2001
+ */
+
+ key_length /= 8;
+ if(in_length > key_length)
+ throw Decoding_Error("Invalid EME1 encoding");
+
+ SecureVector<byte> tmp(key_length);
+ tmp.copy(key_length - in_length, in, in_length);
+
+ mgf->mask(tmp + HASH_LENGTH, tmp.size() - HASH_LENGTH, tmp, HASH_LENGTH);
+ mgf->mask(tmp, HASH_LENGTH, tmp + HASH_LENGTH, tmp.size() - HASH_LENGTH);
+
+ for(u32bit j = 0; j != Phash.size(); ++j)
+ if(tmp[j+HASH_LENGTH] != Phash[j])
+ throw Decoding_Error("Invalid EME1 encoding");
+
+ for(u32bit j = HASH_LENGTH + Phash.size(); j != tmp.size(); ++j)
+ {
+ if(tmp[j] && tmp[j] != 0x01)
+ throw Decoding_Error("Invalid EME1 encoding");
+ if(tmp[j] && tmp[j] == 0x01)
+ {
+ SecureVector<byte> retval(tmp + j + 1, tmp.size() - j - 1);
+ return retval;
+ }
+ }
+ throw Decoding_Error("Invalid EME1 encoding");
+ }
+
+/*
+* Return the max input size for a given key size
+*/
+u32bit EME1::maximum_input_size(u32bit keybits) const
+ {
+ if(keybits / 8 > 2*HASH_LENGTH + 1)
+ return ((keybits / 8) - 2*HASH_LENGTH - 1);
+ else
+ return 0;
+ }
+
+/*
+* EME1 Constructor
+*/
+EME1::EME1(HashFunction* hash, const std::string& P) :
+ HASH_LENGTH(hash->OUTPUT_LENGTH)
+ {
+ Phash = hash->process(P);
+ mgf = new MGF1(hash);
+ }
+
+}
diff --git a/botan/src/pk_pad/eme1/eme1.h b/botan/src/pk_pad/eme1/eme1.h
new file mode 100644
index 0000000..4df5c5f
--- /dev/null
+++ b/botan/src/pk_pad/eme1/eme1.h
@@ -0,0 +1,45 @@
+/*
+* EME1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EME1_H__
+#define BOTAN_EME1_H__
+
+#include <botan/eme.h>
+#include <botan/kdf.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EME1
+*/
+class BOTAN_DLL EME1 : public EME
+ {
+ public:
+ u32bit maximum_input_size(u32bit) const;
+
+ /**
+ EME1 constructor. Hash will be deleted by ~EME1 (when mgf is deleted)
+
+ P is an optional label. Normally empty.
+ */
+ EME1(HashFunction* hash, const std::string& P = "");
+
+ ~EME1() { delete mgf; }
+ private:
+ SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> unpad(const byte[], u32bit, u32bit) const;
+
+ const u32bit HASH_LENGTH;
+ SecureVector<byte> Phash;
+ MGF* mgf;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/eme1/info.txt b/botan/src/pk_pad/eme1/info.txt
new file mode 100644
index 0000000..2f61265
--- /dev/null
+++ b/botan/src/pk_pad/eme1/info.txt
@@ -0,0 +1,16 @@
+realname "EME1"
+
+define EME1
+
+load_on auto
+
+<add>
+eme1.h
+eme1.cpp
+</add>
+
+<requires>
+hash
+kdf
+mgf1
+</requires>
diff --git a/botan/src/pk_pad/eme_pkcs/eme_pkcs.cpp b/botan/src/pk_pad/eme_pkcs/eme_pkcs.cpp
new file mode 100644
index 0000000..c2f9c91
--- /dev/null
+++ b/botan/src/pk_pad/eme_pkcs/eme_pkcs.cpp
@@ -0,0 +1,70 @@
+/*
+* PKCS1 EME
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eme_pkcs.h>
+
+namespace Botan {
+
+/*
+* PKCS1 Pad Operation
+*/
+SecureVector<byte> EME_PKCS1v15::pad(const byte in[], u32bit inlen,
+ u32bit olen,
+ RandomNumberGenerator& rng) const
+ {
+ olen /= 8;
+
+ if(olen < 10)
+ throw Encoding_Error("PKCS1: Output space too small");
+ if(inlen > olen - 10)
+ throw Encoding_Error("PKCS1: Input is too large");
+
+ SecureVector<byte> out(olen);
+
+ out[0] = 0x02;
+ for(u32bit j = 1; j != olen - inlen - 1; ++j)
+ while(out[j] == 0)
+ out[j] = rng.next_byte();
+ out.copy(olen - inlen, in, inlen);
+
+ return out;
+ }
+
+/*
+* PKCS1 Unpad Operation
+*/
+SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], u32bit inlen,
+ u32bit key_len) const
+ {
+ if(inlen != key_len / 8 || inlen < 10 || in[0] != 0x02)
+ throw Decoding_Error("PKCS1::unpad");
+
+ u32bit seperator = 0;
+ for(u32bit j = 0; j != inlen; ++j)
+ if(in[j] == 0)
+ {
+ seperator = j;
+ break;
+ }
+ if(seperator < 9)
+ throw Decoding_Error("PKCS1::unpad");
+
+ return SecureVector<byte>(in + seperator + 1, inlen - seperator - 1);
+ }
+
+/*
+* Return the max input size for a given key size
+*/
+u32bit EME_PKCS1v15::maximum_input_size(u32bit keybits) const
+ {
+ if(keybits / 8 > 10)
+ return ((keybits / 8) - 10);
+ else
+ return 0;
+ }
+
+}
diff --git a/botan/src/pk_pad/eme_pkcs/eme_pkcs.h b/botan/src/pk_pad/eme_pkcs/eme_pkcs.h
new file mode 100644
index 0000000..1aeedf5
--- /dev/null
+++ b/botan/src/pk_pad/eme_pkcs/eme_pkcs.h
@@ -0,0 +1,30 @@
+/*
+* EME PKCS#1 v1.5
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EME_PKCS1_H__
+#define BOTAN_EME_PKCS1_H__
+
+#include <botan/eme.h>
+
+namespace Botan {
+
+/*
+* EME_PKCS1v15
+*/
+class BOTAN_DLL EME_PKCS1v15 : public EME
+ {
+ public:
+ u32bit maximum_input_size(u32bit) const;
+ private:
+ SecureVector<byte> pad(const byte[], u32bit, u32bit,
+ RandomNumberGenerator&) const;
+ SecureVector<byte> unpad(const byte[], u32bit, u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/eme_pkcs/info.txt b/botan/src/pk_pad/eme_pkcs/info.txt
new file mode 100644
index 0000000..88d9caf
--- /dev/null
+++ b/botan/src/pk_pad/eme_pkcs/info.txt
@@ -0,0 +1,10 @@
+realname "PKCSv1 v1.5 EME"
+
+define EME_PKCS1v15
+
+load_on auto
+
+<add>
+eme_pkcs.h
+eme_pkcs.cpp
+</add>
diff --git a/botan/src/pk_pad/emsa.h b/botan/src/pk_pad/emsa.h
new file mode 100644
index 0000000..e2491e4
--- /dev/null
+++ b/botan/src/pk_pad/emsa.h
@@ -0,0 +1,36 @@
+/*
+* EMSA Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_EMSA_H__
+#define BOTAN_PUBKEY_EMSA_H__
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* Encoding Method for Signatures, Appendix
+*/
+class BOTAN_DLL EMSA
+ {
+ public:
+ virtual void update(const byte[], u32bit) = 0;
+ virtual SecureVector<byte> raw_data() = 0;
+
+ virtual SecureVector<byte> encoding_of(const MemoryRegion<byte>&,
+ u32bit,
+ RandomNumberGenerator& rng) = 0;
+
+ virtual bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw() = 0;
+ virtual ~EMSA() {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa1/emsa1.cpp b/botan/src/pk_pad/emsa1/emsa1.cpp
new file mode 100644
index 0000000..26d709c
--- /dev/null
+++ b/botan/src/pk_pad/emsa1/emsa1.cpp
@@ -0,0 +1,105 @@
+/*
+* EMSA1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa1.h>
+
+namespace Botan {
+
+namespace {
+
+SecureVector<byte> emsa1_encoding(const MemoryRegion<byte>& msg,
+ u32bit output_bits)
+ {
+ if(8*msg.size() <= output_bits)
+ return msg;
+
+ u32bit shift = 8*msg.size() - output_bits;
+
+ u32bit byte_shift = shift / 8, bit_shift = shift % 8;
+ SecureVector<byte> digest(msg.size() - byte_shift);
+
+ for(u32bit j = 0; j != msg.size() - byte_shift; ++j)
+ digest[j] = msg[j];
+
+ if(bit_shift)
+ {
+ byte carry = 0;
+ for(u32bit j = 0; j != digest.size(); ++j)
+ {
+ byte temp = digest[j];
+ digest[j] = (temp >> bit_shift) | carry;
+ carry = (temp << (8 - bit_shift));
+ }
+ }
+ return digest;
+ }
+
+}
+
+/*
+* EMSA1 Update Operation
+*/
+void EMSA1::update(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA1::raw_data()
+ {
+ return hash->final();
+ }
+
+/*
+* EMSA1 Encode Operation
+*/
+SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator&)
+ {
+ if(msg.size() != hash->OUTPUT_LENGTH)
+ throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
+ return emsa1_encoding(msg, output_bits);
+ }
+
+/*
+* EMSA1 Decode/Verify Operation
+*/
+bool EMSA1::verify(const MemoryRegion<byte>& coded,
+ const MemoryRegion<byte>& raw, u32bit key_bits) throw()
+ {
+ try {
+ if(raw.size() != hash->OUTPUT_LENGTH)
+ throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
+
+ SecureVector<byte> our_coding = emsa1_encoding(raw, key_bits);
+
+ if(our_coding == coded) return true;
+ if(our_coding[0] != 0) return false;
+ if(our_coding.size() <= coded.size()) return false;
+
+ u32bit offset = 0;
+ while(our_coding[offset] == 0 && offset < our_coding.size())
+ ++offset;
+ if(our_coding.size() - offset != coded.size())
+ return false;
+
+ for(u32bit j = 0; j != coded.size(); ++j)
+ if(coded[j] != our_coding[j+offset])
+ return false;
+
+ return true;
+ }
+ catch(Invalid_Argument)
+ {
+ return false;
+ }
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa1/emsa1.h b/botan/src/pk_pad/emsa1/emsa1.h
new file mode 100644
index 0000000..a5dac07
--- /dev/null
+++ b/botan/src/pk_pad/emsa1/emsa1.h
@@ -0,0 +1,41 @@
+/*
+* EMSA1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA1_H__
+#define BOTAN_EMSA1_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EMSA1
+*/
+class BOTAN_DLL EMSA1 : public EMSA
+ {
+ public:
+ EMSA1(HashFunction* h) : hash(h) {}
+ ~EMSA1() { delete hash; }
+ protected:
+ const HashFunction* hash_ptr() const { return hash; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa1/info.txt b/botan/src/pk_pad/emsa1/info.txt
new file mode 100644
index 0000000..086270b
--- /dev/null
+++ b/botan/src/pk_pad/emsa1/info.txt
@@ -0,0 +1,14 @@
+realname "EMSA1"
+
+define EMSA1
+
+load_on auto
+
+<add>
+emsa1.h
+emsa1.cpp
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp b/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp
new file mode 100644
index 0000000..212091e
--- /dev/null
+++ b/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.cpp
@@ -0,0 +1,29 @@
+/*
+* EMSA1 BSI
+* (C) 1999-2008 Jack Lloyd
+* 2008 Falko Strenzke, FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa1_bsi.h>
+
+namespace Botan {
+
+/*
+* EMSA1 BSI Encode Operation
+*/
+SecureVector<byte> EMSA1_BSI::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator&)
+ {
+ if(msg.size() != hash_ptr()->OUTPUT_LENGTH)
+ throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input");
+
+ if(8*msg.size() <= output_bits)
+ return msg;
+
+ throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded");
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.h b/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.h
new file mode 100644
index 0000000..ec86d40
--- /dev/null
+++ b/botan/src/pk_pad/emsa1_bsi/emsa1_bsi.h
@@ -0,0 +1,32 @@
+/*
+* EMSA1 BSI Variant
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA1_BSI_H__
+#define BOTAN_EMSA1_BSI_H__
+
+#include <botan/emsa1.h>
+
+namespace Botan {
+
+/**
+EMSA1_BSI is a variant of EMSA1 specified by the BSI. It accepts only
+hash values which are less or equal than the maximum key length. The
+implementation comes from InSiTo
+*/
+class BOTAN_DLL EMSA1_BSI : public EMSA1
+ {
+ public:
+ EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {}
+ private:
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa1_bsi/info.txt b/botan/src/pk_pad/emsa1_bsi/info.txt
new file mode 100644
index 0000000..14a9fd3
--- /dev/null
+++ b/botan/src/pk_pad/emsa1_bsi/info.txt
@@ -0,0 +1,14 @@
+realname "EMSA1 (BSI variant)"
+
+define EMSA1_BSI
+
+load_on auto
+
+<add>
+emsa1_bsi.h
+emsa1_bsi.cpp
+</add>
+
+<requires>
+emsa1
+</requires>
diff --git a/botan/src/pk_pad/emsa2/emsa2.cpp b/botan/src/pk_pad/emsa2/emsa2.cpp
new file mode 100644
index 0000000..aee3231
--- /dev/null
+++ b/botan/src/pk_pad/emsa2/emsa2.cpp
@@ -0,0 +1,112 @@
+/*
+* EMSA2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa2.h>
+#include <botan/hash_id.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EMSA2 Encode Operation
+*/
+SecureVector<byte> emsa2_encoding(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ const MemoryRegion<byte>& empty_hash,
+ byte hash_id)
+ {
+ const u32bit HASH_SIZE = empty_hash.size();
+
+ u32bit output_length = (output_bits + 1) / 8;
+
+ if(msg.size() != HASH_SIZE)
+ throw Encoding_Error("EMSA2::encoding_of: Bad input length");
+ if(output_length < HASH_SIZE + 4)
+ throw Encoding_Error("EMSA2::encoding_of: Output length is too small");
+
+ bool empty = true;
+ for(u32bit j = 0; j != HASH_SIZE; ++j)
+ if(empty_hash[j] != msg[j])
+ empty = false;
+
+ SecureVector<byte> output(output_length);
+
+ output[0] = (empty ? 0x4B : 0x6B);
+ output[output_length - 3 - HASH_SIZE] = 0xBA;
+ set_mem(output + 1, output_length - 4 - HASH_SIZE, 0xBB);
+ output.copy(output_length - (HASH_SIZE + 2), msg, msg.size());
+ output[output_length-2] = hash_id;
+ output[output_length-1] = 0xCC;
+
+ return output;
+ }
+
+}
+
+/*
+* EMSA2 Update Operation
+*/
+void EMSA2::update(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA2::raw_data()
+ {
+ return hash->final();
+ }
+
+/*
+* EMSA2 Encode Operation
+*/
+SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator&)
+ {
+ return emsa2_encoding(msg, output_bits, empty_hash, hash_id);
+ }
+
+/*
+* EMSA2 Verify Operation
+*/
+bool EMSA2::verify(const MemoryRegion<byte>& coded,
+ const MemoryRegion<byte>& raw,
+ u32bit key_bits) throw()
+ {
+ try
+ {
+ return (coded == emsa2_encoding(raw, key_bits,
+ empty_hash, hash_id));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+/*
+* EMSA2 Constructor
+*/
+EMSA2::EMSA2(HashFunction* hash_in) : hash(hash_in)
+ {
+ empty_hash = hash->final();
+
+ hash_id = ieee1363_hash_id(hash->name());
+
+ if(hash_id == 0)
+ {
+ std::string hashname = hash->name();
+ delete hash;
+ throw Encoding_Error("EMSA2 cannot be used with " + hashname);
+ }
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa2/emsa2.h b/botan/src/pk_pad/emsa2/emsa2.h
new file mode 100644
index 0000000..76888d1
--- /dev/null
+++ b/botan/src/pk_pad/emsa2/emsa2.h
@@ -0,0 +1,41 @@
+/*
+* EMSA2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA2_H__
+#define BOTAN_EMSA2_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* EMSA2
+*/
+class BOTAN_DLL EMSA2 : public EMSA
+ {
+ public:
+ EMSA2(HashFunction* hash);
+ ~EMSA2() { delete hash; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ SecureVector<byte> empty_hash;
+ HashFunction* hash;
+ byte hash_id;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa2/info.txt b/botan/src/pk_pad/emsa2/info.txt
new file mode 100644
index 0000000..1c8161c
--- /dev/null
+++ b/botan/src/pk_pad/emsa2/info.txt
@@ -0,0 +1,15 @@
+realname "EMSA2"
+
+define EMSA2
+
+load_on auto
+
+<add>
+emsa2.h
+emsa2.cpp
+</add>
+
+<requires>
+hash
+hash_id
+</requires>
diff --git a/botan/src/pk_pad/emsa3/emsa3.cpp b/botan/src/pk_pad/emsa3/emsa3.cpp
new file mode 100644
index 0000000..4d50abd
--- /dev/null
+++ b/botan/src/pk_pad/emsa3/emsa3.cpp
@@ -0,0 +1,152 @@
+/*
+* EMSA3 and EMSA3_Raw
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa3.h>
+#include <botan/hash_id.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* EMSA3 Encode Operation
+*/
+SecureVector<byte> emsa3_encoding(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ const byte hash_id[],
+ u32bit hash_id_length)
+ {
+ u32bit output_length = output_bits / 8;
+ if(output_length < hash_id_length + msg.size() + 10)
+ throw Encoding_Error("emsa3_encoding: Output length is too small");
+
+ SecureVector<byte> T(output_length);
+ const u32bit P_LENGTH = output_length - msg.size() - hash_id_length - 2;
+
+ T[0] = 0x01;
+ set_mem(T+1, P_LENGTH, 0xFF);
+ T[P_LENGTH+1] = 0x00;
+ T.copy(P_LENGTH+2, hash_id, hash_id_length);
+ T.copy(output_length-msg.size(), msg, msg.size());
+ return T;
+ }
+
+}
+
+/**
+* EMSA3 Update Operation
+*/
+void EMSA3::update(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/**
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA3::raw_data()
+ {
+ return hash->final();
+ }
+
+/**
+* EMSA3 Encode Operation
+*/
+SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator&)
+ {
+ if(msg.size() != hash->OUTPUT_LENGTH)
+ throw Encoding_Error("EMSA3::encoding_of: Bad input length");
+
+ return emsa3_encoding(msg, output_bits,
+ hash_id, hash_id.size());
+ }
+
+/**
+* Default signature decoding
+*/
+bool EMSA3::verify(const MemoryRegion<byte>& coded,
+ const MemoryRegion<byte>& raw,
+ u32bit key_bits) throw()
+ {
+ if(raw.size() != hash->OUTPUT_LENGTH)
+ return false;
+
+ try
+ {
+ return (coded == emsa3_encoding(raw, key_bits,
+ hash_id, hash_id.size()));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+/**
+* EMSA3 Constructor
+*/
+EMSA3::EMSA3(HashFunction* hash_in) : hash(hash_in)
+ {
+ hash_id = pkcs_hash_id(hash->name());
+ }
+
+/**
+* EMSA3 Destructor
+*/
+EMSA3::~EMSA3()
+ {
+ delete hash;
+ }
+
+/**
+* EMSA3_Raw Update Operation
+*/
+void EMSA3_Raw::update(const byte input[], u32bit length)
+ {
+ message.append(input, length);
+ }
+
+/**
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA3_Raw::raw_data()
+ {
+ SecureVector<byte> ret = message;
+ message.clear();
+ return ret;
+ }
+
+/**
+* EMSA3_Raw Encode Operation
+*/
+SecureVector<byte> EMSA3_Raw::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator&)
+ {
+ return emsa3_encoding(msg, output_bits, 0, 0);
+ }
+
+/**
+* Default signature decoding
+*/
+bool EMSA3_Raw::verify(const MemoryRegion<byte>& coded,
+ const MemoryRegion<byte>& raw,
+ u32bit key_bits) throw()
+ {
+ try
+ {
+ return (coded == emsa3_encoding(raw, key_bits, 0, 0));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa3/emsa3.h b/botan/src/pk_pad/emsa3/emsa3.h
new file mode 100644
index 0000000..301f214
--- /dev/null
+++ b/botan/src/pk_pad/emsa3/emsa3.h
@@ -0,0 +1,65 @@
+/*
+* EMSA3 and EMSA3_Raw
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA3_H__
+#define BOTAN_EMSA3_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* EMSA3
+* aka PKCS #1 v1.5 signature padding
+* aka PKCS #1 block type 1
+*/
+class BOTAN_DLL EMSA3 : public EMSA
+ {
+ public:
+ EMSA3(HashFunction*);
+ ~EMSA3();
+
+ void update(const byte[], u32bit);
+
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+ private:
+ HashFunction* hash;
+ SecureVector<byte> hash_id;
+ };
+
+/**
+* EMSA3_Raw which is EMSA3 without a hash or digest id (which
+* according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS
+* mechanism", something I have not confirmed)
+*/
+class BOTAN_DLL EMSA3_Raw : public EMSA
+ {
+ public:
+ void update(const byte[], u32bit);
+
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ private:
+ SecureVector<byte> message;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa3/info.txt b/botan/src/pk_pad/emsa3/info.txt
new file mode 100644
index 0000000..90e4b9b
--- /dev/null
+++ b/botan/src/pk_pad/emsa3/info.txt
@@ -0,0 +1,15 @@
+realname "EMSA3"
+
+define EMSA3
+
+load_on auto
+
+<add>
+emsa3.h
+emsa3.cpp
+</add>
+
+<requires>
+hash
+hash_id
+</requires>
diff --git a/botan/src/pk_pad/emsa4/emsa4.cpp b/botan/src/pk_pad/emsa4/emsa4.cpp
new file mode 100644
index 0000000..cff9a15
--- /dev/null
+++ b/botan/src/pk_pad/emsa4/emsa4.cpp
@@ -0,0 +1,143 @@
+/*
+* EMSA4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa4.h>
+#include <botan/mgf1.h>
+#include <botan/bit_ops.h>
+
+namespace Botan {
+
+/*
+* EMSA4 Update Operation
+*/
+void EMSA4::update(const byte input[], u32bit length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA4::raw_data()
+ {
+ return hash->final();
+ }
+
+/*
+* EMSA4 Encode Operation
+*/
+SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit output_bits,
+ RandomNumberGenerator& rng)
+ {
+ const u32bit HASH_SIZE = hash->OUTPUT_LENGTH;
+
+ if(msg.size() != HASH_SIZE)
+ throw Encoding_Error("EMSA4::encoding_of: Bad input length");
+ if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
+ throw Encoding_Error("EMSA4::encoding_of: Output length is too small");
+
+ const u32bit output_length = (output_bits + 7) / 8;
+
+ SecureVector<byte> salt(SALT_SIZE);
+ rng.randomize(salt, SALT_SIZE);
+
+ for(u32bit j = 0; j != 8; ++j)
+ hash->update(0);
+ hash->update(msg);
+ hash->update(salt, SALT_SIZE);
+ SecureVector<byte> H = hash->final();
+
+ SecureVector<byte> EM(output_length);
+
+ EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
+ EM.copy(output_length - 1 - HASH_SIZE - SALT_SIZE, salt, SALT_SIZE);
+ mgf->mask(H, HASH_SIZE, EM, output_length - HASH_SIZE - 1);
+ EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
+ EM.copy(output_length - 1 - HASH_SIZE, H, HASH_SIZE);
+ EM[output_length-1] = 0xBC;
+
+ return EM;
+ }
+
+/*
+* EMSA4 Decode/Verify Operation
+*/
+bool EMSA4::verify(const MemoryRegion<byte>& const_coded,
+ const MemoryRegion<byte>& raw, u32bit key_bits) throw()
+ {
+ const u32bit HASH_SIZE = hash->OUTPUT_LENGTH;
+ const u32bit KEY_BYTES = (key_bits + 7) / 8;
+
+ if(key_bits < 8*HASH_SIZE + 9)
+ return false;
+ if(raw.size() != HASH_SIZE)
+ return false;
+ if(const_coded.size() > KEY_BYTES)
+ return false;
+ if(const_coded[const_coded.size()-1] != 0xBC)
+ return false;
+
+ SecureVector<byte> coded = const_coded;
+ if(coded.size() < KEY_BYTES)
+ {
+ SecureVector<byte> temp(KEY_BYTES);
+ temp.copy(KEY_BYTES - coded.size(), coded, coded.size());
+ coded = temp;
+ }
+
+ const u32bit TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
+ if(TOP_BITS > 8 - high_bit(coded[0]))
+ return false;
+
+ SecureVector<byte> DB(coded.begin(), coded.size() - HASH_SIZE - 1);
+ SecureVector<byte> H(coded + coded.size() - HASH_SIZE - 1, HASH_SIZE);
+
+ mgf->mask(H, H.size(), DB, coded.size() - H.size() - 1);
+ DB[0] &= 0xFF >> TOP_BITS;
+
+ u32bit salt_offset = 0;
+ for(u32bit j = 0; j != DB.size(); ++j)
+ {
+ if(DB[j] == 0x01)
+ { salt_offset = j + 1; break; }
+ if(DB[j])
+ return false;
+ }
+ if(salt_offset == 0)
+ return false;
+
+ SecureVector<byte> salt(DB + salt_offset, DB.size() - salt_offset);
+
+ for(u32bit j = 0; j != 8; ++j)
+ hash->update(0);
+ hash->update(raw);
+ hash->update(salt);
+ SecureVector<byte> H2 = hash->final();
+
+ return (H == H2);
+ }
+
+/*
+* EMSA4 Constructor
+*/
+EMSA4::EMSA4(HashFunction* h) :
+ SALT_SIZE(h->OUTPUT_LENGTH), hash(h)
+ {
+ mgf = new MGF1(hash->clone());
+ }
+
+/*
+* EMSA4 Constructor
+*/
+EMSA4::EMSA4(HashFunction* h, u32bit salt_size) :
+ SALT_SIZE(salt_size), hash(h)
+ {
+ mgf = new MGF1(hash->clone());
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa4/emsa4.h b/botan/src/pk_pad/emsa4/emsa4.h
new file mode 100644
index 0000000..b716178
--- /dev/null
+++ b/botan/src/pk_pad/emsa4/emsa4.h
@@ -0,0 +1,43 @@
+/*
+* EMSA4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA4_H__
+#define BOTAN_EMSA4_H__
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* EMSA4
+*/
+class BOTAN_DLL EMSA4 : public EMSA
+ {
+ public:
+ EMSA4(HashFunction*);
+ EMSA4(HashFunction*, u32bit);
+
+ ~EMSA4() { delete hash; delete mgf; }
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator& rng);
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ u32bit SALT_SIZE;
+ HashFunction* hash;
+ const MGF* mgf;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa4/info.txt b/botan/src/pk_pad/emsa4/info.txt
new file mode 100644
index 0000000..29ef4e0
--- /dev/null
+++ b/botan/src/pk_pad/emsa4/info.txt
@@ -0,0 +1,16 @@
+realname "EMSA4"
+
+define EMSA4
+
+load_on auto
+
+<add>
+emsa4.h
+emsa4.cpp
+</add>
+
+<requires>
+hash
+kdf
+mgf1
+</requires>
diff --git a/botan/src/pk_pad/emsa_raw/emsa_raw.cpp b/botan/src/pk_pad/emsa_raw/emsa_raw.cpp
new file mode 100644
index 0000000..d5973ee
--- /dev/null
+++ b/botan/src/pk_pad/emsa_raw/emsa_raw.cpp
@@ -0,0 +1,50 @@
+/*
+* EMSA-Raw
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/emsa_raw.h>
+
+namespace Botan {
+
+/*
+* EMSA-Raw Encode Operation
+*/
+void EMSA_Raw::update(const byte input[], u32bit length)
+ {
+ message.append(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+SecureVector<byte> EMSA_Raw::raw_data()
+ {
+ SecureVector<byte> buf = message;
+ message.destroy();
+ return buf;
+ }
+
+/*
+* EMSA-Raw Encode Operation
+*/
+SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg,
+ u32bit,
+ RandomNumberGenerator&)
+ {
+ return msg;
+ }
+
+/*
+* EMSA-Raw Verify Operation
+*/
+bool EMSA_Raw::verify(const MemoryRegion<byte>& coded,
+ const MemoryRegion<byte>& raw,
+ u32bit) throw()
+ {
+ return (coded == raw);
+ }
+
+}
diff --git a/botan/src/pk_pad/emsa_raw/emsa_raw.h b/botan/src/pk_pad/emsa_raw/emsa_raw.h
new file mode 100644
index 0000000..1b0ad51
--- /dev/null
+++ b/botan/src/pk_pad/emsa_raw/emsa_raw.h
@@ -0,0 +1,34 @@
+/*
+* EMSA-Raw
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EMSA_RAW_H__
+#define BOTAN_EMSA_RAW_H__
+
+#include <botan/emsa.h>
+
+namespace Botan {
+
+/*
+* EMSA-Raw
+*/
+class BOTAN_DLL EMSA_Raw : public EMSA
+ {
+ private:
+ void update(const byte[], u32bit);
+ SecureVector<byte> raw_data();
+
+ SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit,
+ RandomNumberGenerator&);
+ bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&,
+ u32bit) throw();
+
+ SecureVector<byte> message;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/emsa_raw/info.txt b/botan/src/pk_pad/emsa_raw/info.txt
new file mode 100644
index 0000000..2a88d10
--- /dev/null
+++ b/botan/src/pk_pad/emsa_raw/info.txt
@@ -0,0 +1,10 @@
+realname "EMSA-Raw"
+
+define EMSA_RAW
+
+load_on auto
+
+<add>
+emsa_raw.h
+emsa_raw.cpp
+</add>
diff --git a/botan/src/pk_pad/hash_id/hash_id.cpp b/botan/src/pk_pad/hash_id/hash_id.cpp
new file mode 100644
index 0000000..c83ad87
--- /dev/null
+++ b/botan/src/pk_pad/hash_id/hash_id.cpp
@@ -0,0 +1,116 @@
+/*
+* Hash Function Identification
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hash_id.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace PKCS_IDS {
+
+const byte MD2_ID[] = {
+0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
+0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 };
+
+const byte MD5_ID[] = {
+0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
+0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
+
+const byte RIPEMD_128_ID[] = {
+0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
+0x02, 0x05, 0x00, 0x04, 0x14 };
+
+const byte RIPEMD_160_ID[] = {
+0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
+0x01, 0x05, 0x00, 0x04, 0x14 };
+
+const byte SHA_160_ID[] = {
+0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02,
+0x1A, 0x05, 0x00, 0x04, 0x14 };
+
+const byte SHA_224_ID[] = {
+0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C };
+
+const byte SHA_256_ID[] = {
+0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
+
+const byte SHA_384_ID[] = {
+0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 };
+
+const byte SHA_512_ID[] = {
+0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
+
+const byte TIGER_ID[] = {
+0x30, 0x29, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04,
+0x01, 0xDA, 0x47, 0x0C, 0x02, 0x05, 0x00, 0x04, 0x18 };
+
+}
+
+/**
+* @return HashID as specified by PKCS
+* For details see RFC 3447 section 9.2
+* http://tools.ietf.org/html/rfc3447#section-9.2
+*/
+MemoryVector<byte> pkcs_hash_id(const std::string& name)
+ {
+ MemoryVector<byte> out;
+
+ if(name == "Parallel(MD5,SHA-160)")
+ return out;
+
+ if(name == "MD2")
+ out.set(PKCS_IDS::MD2_ID, sizeof(PKCS_IDS::MD2_ID));
+ else if(name == "MD5")
+ out.set(PKCS_IDS::MD5_ID, sizeof(PKCS_IDS::MD5_ID));
+ else if(name == "RIPEMD-128")
+ out.set(PKCS_IDS::RIPEMD_128_ID, sizeof(PKCS_IDS::RIPEMD_128_ID));
+ else if(name == "RIPEMD-160")
+ out.set(PKCS_IDS::RIPEMD_160_ID, sizeof(PKCS_IDS::RIPEMD_160_ID));
+ else if(name == "SHA-160")
+ out.set(PKCS_IDS::SHA_160_ID, sizeof(PKCS_IDS::SHA_160_ID));
+ else if(name == "SHA-224")
+ out.set(PKCS_IDS::SHA_224_ID, sizeof(PKCS_IDS::SHA_224_ID));
+ else if(name == "SHA-256")
+ out.set(PKCS_IDS::SHA_256_ID, sizeof(PKCS_IDS::SHA_256_ID));
+ else if(name == "SHA-384")
+ out.set(PKCS_IDS::SHA_384_ID, sizeof(PKCS_IDS::SHA_384_ID));
+ else if(name == "SHA-512")
+ out.set(PKCS_IDS::SHA_512_ID, sizeof(PKCS_IDS::SHA_512_ID));
+ else if(name == "Tiger(24,3)")
+ out.set(PKCS_IDS::TIGER_ID, sizeof(PKCS_IDS::TIGER_ID));
+
+ if(out.size())
+ return out;
+
+ throw Invalid_Argument("No PKCS #1 identifier for " + name);
+ }
+
+/**
+* @return HashID as specified by IEEE 1363/X9.31
+*/
+byte ieee1363_hash_id(const std::string& name)
+ {
+ if(name == "SHA-160") return 0x33;
+
+ if(name == "SHA-224") return 0x38;
+ if(name == "SHA-256") return 0x34;
+ if(name == "SHA-384") return 0x36;
+ if(name == "SHA-512") return 0x35;
+
+ if(name == "RIPEMD-160") return 0x31;
+ if(name == "RIPEMD-128") return 0x32;
+
+ if(name == "Whirlpool") return 0x37;
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/pk_pad/hash_id/hash_id.h b/botan/src/pk_pad/hash_id/hash_id.h
new file mode 100644
index 0000000..847d910
--- /dev/null
+++ b/botan/src/pk_pad/hash_id/hash_id.h
@@ -0,0 +1,24 @@
+/*
+* Hash Function Identification
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HASHID_H__
+#define BOTAN_HASHID_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Return the values of various defined HashIDs
+*/
+BOTAN_DLL MemoryVector<byte> pkcs_hash_id(const std::string&);
+BOTAN_DLL byte ieee1363_hash_id(const std::string&);
+
+}
+
+#endif
diff --git a/botan/src/pk_pad/hash_id/info.txt b/botan/src/pk_pad/hash_id/info.txt
new file mode 100644
index 0000000..9354325
--- /dev/null
+++ b/botan/src/pk_pad/hash_id/info.txt
@@ -0,0 +1,14 @@
+realname "Hash Function Identifiers"
+
+define HASH_ID
+
+load_on auto
+
+<add>
+hash_id.cpp
+hash_id.h
+</add>
+
+<requires>
+alloc
+</requires>
diff --git a/botan/src/pk_pad/info.txt b/botan/src/pk_pad/info.txt
new file mode 100644
index 0000000..c281b15
--- /dev/null
+++ b/botan/src/pk_pad/info.txt
@@ -0,0 +1,16 @@
+realname "Public Key EME/EMSA Padding Modes"
+
+define PK_PADDING
+
+load_on auto
+
+<add>
+emsa.h
+eme.cpp
+eme.h
+</add>
+
+<requires>
+alloc
+rng
+</requires>
diff --git a/botan/src/pubkey/dh/dh.cpp b/botan/src/pubkey/dh/dh.cpp
new file mode 100644
index 0000000..0c9d02f
--- /dev/null
+++ b/botan/src/pubkey/dh/dh.cpp
@@ -0,0 +1,119 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dh.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*
+* DH_PublicKey Constructor
+*/
+DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*
+* Algorithm Specific X.509 Initialization Code
+*/
+void DH_PublicKey::X509_load_hook()
+ {
+ }
+
+/*
+* Return the maximum input size in bits
+*/
+u32bit DH_PublicKey::max_input_bits() const
+ {
+ return group_p().bits();
+ }
+
+/*
+* Return the public value for key agreement
+*/
+MemoryVector<byte> DH_PublicKey::public_value() const
+ {
+ return BigInt::encode_1363(y, group_p().bytes());
+ }
+
+/*
+* Create a DH private key
+*/
+DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ {
+ const BigInt& p = group_p();
+ x.randomize(rng, 2 * dl_work_factor(p.bits()));
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*
+* Algorithm Specific PKCS #8 Initialization Code
+*/
+void DH_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = DH_Core(rng, group, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* Return the public value for key agreement
+*/
+MemoryVector<byte> DH_PrivateKey::public_value() const
+ {
+ return DH_PublicKey::public_value();
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> DH_PrivateKey::derive_key(const byte w[],
+ u32bit w_len) const
+ {
+ return derive_key(BigInt::decode(w, w_len));
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> DH_PrivateKey::derive_key(const DH_PublicKey& key) const
+ {
+ return derive_key(key.get_y());
+ }
+
+/*
+* Derive a key
+*/
+SecureVector<byte> DH_PrivateKey::derive_key(const BigInt& w) const
+ {
+ const BigInt& p = group_p();
+ if(w <= 1 || w >= p-1)
+ throw Invalid_Argument(algo_name() + "::derive_key: Invalid key input");
+ return BigInt::encode_1363(core.agree(w), p.bytes());
+ }
+
+}
diff --git a/botan/src/pubkey/dh/dh.h b/botan/src/pubkey/dh/dh.h
new file mode 100644
index 0000000..fa558bc
--- /dev/null
+++ b/botan/src/pubkey/dh/dh.h
@@ -0,0 +1,80 @@
+/*
+* Diffie-Hellman
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DIFFIE_HELLMAN_H__
+#define BOTAN_DIFFIE_HELLMAN_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dh_core.h>
+
+namespace Botan {
+
+/**
+* This class represents Diffie-Hellman public keys.
+*/
+class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DH"; }
+
+ MemoryVector<byte> public_value() const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ /**
+ * Construct an uninitialized key. Use this constructor if you wish
+ * to decode an encoded key into the new instance.
+ */
+ DH_PublicKey() {}
+
+ /**
+ * Construct a public key with the specified parameters.
+ * @param grp the DL group to use in the key
+ * @param y the public value y
+ */
+ DH_PublicKey(const DL_Group& grp, const BigInt& y);
+ private:
+ void X509_load_hook();
+ };
+
+/**
+* This class represents Diffie-Hellman private keys.
+*/
+class BOTAN_DLL DH_PrivateKey : public DH_PublicKey,
+ public PK_Key_Agreement_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> derive_key(const byte other[], u32bit length) const;
+ SecureVector<byte> derive_key(const DH_PublicKey& other) const;
+ SecureVector<byte> derive_key(const BigInt& other) const;
+
+ MemoryVector<byte> public_value() const;
+
+ /**
+ * Construct an uninitialized key. Use this constructor if you wish
+ * to decode an encoded key into the new instance.
+ */
+ DH_PrivateKey() {}
+
+ /**
+ * Construct a private key with predetermined value.
+ * @param rng random number generator to use
+ * @param grp the group to be used in the key
+ * @param x the key's secret value (or if zero, generate a new key)
+ */
+ DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp,
+ const BigInt& x = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false);
+ DH_Core core;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dh/dh_core.cpp b/botan/src/pubkey/dh/dh_core.cpp
new file mode 100644
index 0000000..78a26a8
--- /dev/null
+++ b/botan/src/pubkey/dh/dh_core.cpp
@@ -0,0 +1,69 @@
+/*
+* PK Algorithm Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dh_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS;
+
+}
+
+/*
+* DH_Core Constructor
+*/
+DH_Core::DH_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& x)
+ {
+ op = Engine_Core::dh_op(group, x);
+
+ const BigInt& p = group.get_p();
+
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+
+ if(k != 0)
+ blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p);
+ }
+
+/*
+* DH_Core Copy Constructor
+*/
+DH_Core::DH_Core(const DH_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*
+* DH_Core Assignment Operator
+*/
+DH_Core& DH_Core::operator=(const DH_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*
+* DH Operation
+*/
+BigInt DH_Core::agree(const BigInt& i) const
+ {
+ return blinder.unblind(op->agree(blinder.blind(i)));
+ }
+
+}
diff --git a/botan/src/pubkey/dh/dh_core.h b/botan/src/pubkey/dh/dh_core.h
new file mode 100644
index 0000000..91b50a2
--- /dev/null
+++ b/botan/src/pubkey/dh/dh_core.h
@@ -0,0 +1,38 @@
+/*
+* DH Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DH_CORE_H__
+#define BOTAN_DH_CORE_H__
+
+#include <botan/dh_op.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/*
+* DH Core
+*/
+class BOTAN_DLL DH_Core
+ {
+ public:
+ BigInt agree(const BigInt&) const;
+
+ DH_Core& operator=(const DH_Core&);
+
+ DH_Core() { op = 0; }
+ DH_Core(const DH_Core&);
+ DH_Core(RandomNumberGenerator& rng,
+ const DL_Group&, const BigInt&);
+ ~DH_Core() { delete op; }
+ private:
+ DH_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dh/dh_op.h b/botan/src/pubkey/dh/dh_op.h
new file mode 100644
index 0000000..50f3d78
--- /dev/null
+++ b/botan/src/pubkey/dh/dh_op.h
@@ -0,0 +1,45 @@
+/*
+* DH Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DH_OPS_H__
+#define BOTAN_DH_OPS_H__
+
+#include <botan/dl_group.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+
+namespace Botan {
+
+/*
+* DH Operation Interface
+*/
+class BOTAN_DLL DH_Operation
+ {
+ public:
+ virtual BigInt agree(const BigInt&) const = 0;
+ virtual DH_Operation* clone() const = 0;
+ virtual ~DH_Operation() {}
+ };
+
+/*
+* Botan's Default DH Operation
+*/
+class BOTAN_DLL Default_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const { return powermod_x_p(i); }
+ DH_Operation* clone() const { return new Default_DH_Op(*this); }
+
+ Default_DH_Op(const DL_Group& group, const BigInt& x) :
+ powermod_x_p(x, group.get_p()) {}
+ private:
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dh/info.txt b/botan/src/pubkey/dh/info.txt
new file mode 100644
index 0000000..33af9a8
--- /dev/null
+++ b/botan/src/pubkey/dh/info.txt
@@ -0,0 +1,20 @@
+realname "Diffie-Hellman Key Agreement"
+
+define DIFFIE_HELLMAN
+
+load_on auto
+
+<add>
+dh.cpp
+dh.h
+dh_core.cpp
+dh_core.h
+dh_op.h
+</add>
+
+<requires>
+dl_algo
+dl_group
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/dl_algo/dl_algo.cpp b/botan/src/pubkey/dl_algo/dl_algo.cpp
new file mode 100644
index 0000000..8ce3446
--- /dev/null
+++ b/botan/src/pubkey/dl_algo/dl_algo.cpp
@@ -0,0 +1,167 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dl_algo.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/*
+* Return the X.509 public key encoder
+*/
+X509_Encoder* DL_Scheme_PublicKey::x509_encoder() const
+ {
+ class DL_Scheme_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ MemoryVector<byte> group =
+ key->group.DER_encode(key->group_format());
+
+ return AlgorithmIdentifier(key->get_oid(), group);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder().encode(key->y).get_contents();
+ }
+
+ DL_Scheme_Encoder(const DL_Scheme_PublicKey* k) : key(k) {}
+ private:
+ const DL_Scheme_PublicKey* key;
+ };
+
+ return new DL_Scheme_Encoder(this);
+ }
+
+/*
+* Return the X.509 public key decoder
+*/
+X509_Decoder* DL_Scheme_PublicKey::x509_decoder()
+ {
+ class DL_Scheme_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ DataSource_Memory source(alg_id.parameters);
+ key->group.BER_decode(source, key->group_format());
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits).decode(key->y);
+ key->X509_load_hook();
+ }
+
+ DL_Scheme_Decoder(DL_Scheme_PublicKey* k) : key(k) {}
+ private:
+ DL_Scheme_PublicKey* key;
+ };
+
+ return new DL_Scheme_Decoder(this);
+ }
+
+/*
+* Return the PKCS #8 private key encoder
+*/
+PKCS8_Encoder* DL_Scheme_PrivateKey::pkcs8_encoder() const
+ {
+ class DL_Scheme_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ MemoryVector<byte> group =
+ key->group.DER_encode(key->group_format());
+
+ return AlgorithmIdentifier(key->get_oid(), group);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder().encode(key->x).get_contents();
+ }
+
+ DL_Scheme_Encoder(const DL_Scheme_PrivateKey* k) : key(k) {}
+ private:
+ const DL_Scheme_PrivateKey* key;
+ };
+
+ return new DL_Scheme_Encoder(this);
+ }
+
+/*
+* Return the PKCS #8 private key decoder
+*/
+PKCS8_Decoder* DL_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng)
+ {
+ class DL_Scheme_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ DataSource_Memory source(alg_id.parameters);
+ key->group.BER_decode(source, key->group_format());
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits).decode(key->x);
+ key->PKCS8_load_hook(rng);
+ }
+
+ DL_Scheme_Decoder(DL_Scheme_PrivateKey* k, RandomNumberGenerator& r) :
+ key(k), rng(r) {}
+ private:
+ DL_Scheme_PrivateKey* key;
+ RandomNumberGenerator& rng;
+ };
+
+ return new DL_Scheme_Decoder(this, rng);
+ }
+
+/*
+* Check Public DL Parameters
+*/
+bool DL_Scheme_PublicKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(y < 2 || y >= group_p())
+ return false;
+ if(!group.verify_group(rng, strong))
+ return false;
+ return true;
+ }
+
+/*
+* Check DL Scheme Private Parameters
+*/
+bool DL_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ const BigInt& p = group_p();
+ const BigInt& g = group_g();
+
+ if(y < 2 || y >= p || x < 2 || x >= p)
+ return false;
+ if(!group.verify_group(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(y != power_mod(g, x, p))
+ return false;
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/dl_algo/dl_algo.h b/botan/src/pubkey/dl_algo/dl_algo.h
new file mode 100644
index 0000000..256ce96
--- /dev/null
+++ b/botan/src/pubkey/dl_algo/dl_algo.h
@@ -0,0 +1,116 @@
+/*
+* DL Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_ALGO_H__
+#define BOTAN_DL_ALGO_H__
+
+#include <botan/dl_group.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm (DL) public keys.
+*/
+class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the DL domain parameters of this key.
+ * @return the DL domain parameters of this key
+ */
+ const DL_Group& get_domain() const { return group; }
+
+ /**
+ * Get the public value y with y = g^x mod p where x is the secret key.
+ */
+ const BigInt& get_y() const { return y; }
+
+ /**
+ * Get the prime p of the underlying DL group.
+ * @return the prime p
+ */
+ const BigInt& group_p() const { return group.get_p(); }
+
+ /**
+ * Get the prime q of the underlying DL group.
+ * @return the prime q
+ */
+ const BigInt& group_q() const { return group.get_q(); }
+
+ /**
+ * Get the generator g of the underlying DL group.
+ * @return the generator g
+ */
+ const BigInt& group_g() const { return group.get_g(); }
+
+ /**
+ * Get the underlying groups encoding format.
+ * @return the encoding format
+ */
+ virtual DL_Group::Format group_format() const = 0;
+
+ /**
+ * Get an X509 encoder for this key.
+ * @return an encoder usable to encode this key.
+ */
+ X509_Encoder* x509_encoder() const;
+
+ /**
+ * Get an X509 decoder for this key.
+ * @return an decoder usable to decode a DL key and store the
+ * values in this instance.
+ */
+ X509_Decoder* x509_decoder();
+ protected:
+ BigInt y;
+ DL_Group group;
+ private:
+ virtual void X509_load_hook() {}
+ };
+
+/**
+* This class represents discrete logarithm (DL) private keys.
+*/
+class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the secret key x.
+ * @return the secret key
+ */
+ const BigInt& get_x() const { return x; }
+
+ /**
+ * Get an PKCS#8 encoder for this key.
+ * @return an encoder usable to encode this key.
+ */
+ PKCS8_Encoder* pkcs8_encoder() const;
+
+ /**
+ * Get an PKCS#8 decoder for this key.
+ * @param rng the rng to use
+ * @return an decoder usable to decode a DL key and store the
+ * values in this instance.
+ */
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator& rng);
+ protected:
+ BigInt x;
+ private:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false) {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dl_algo/info.txt b/botan/src/pubkey/dl_algo/info.txt
new file mode 100644
index 0000000..15a7751
--- /dev/null
+++ b/botan/src/pubkey/dl_algo/info.txt
@@ -0,0 +1,18 @@
+realname "Discrete Logarithm PK Algorithms"
+
+define DL_PUBLIC_KEY_FAMILY
+
+load_on auto
+
+<add>
+dl_algo.cpp
+dl_algo.h
+</add>
+
+<requires>
+asn1
+dl_group
+numbertheory
+pk_codecs
+rng
+</requires>
diff --git a/botan/src/pubkey/dl_group/dl_group.cpp b/botan/src/pubkey/dl_group/dl_group.cpp
new file mode 100644
index 0000000..81c5d5e
--- /dev/null
+++ b/botan/src/pubkey/dl_group/dl_group.cpp
@@ -0,0 +1,333 @@
+/*
+* Discrete Logarithm Parameters
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dl_group.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pipe.h>
+#include <botan/util.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group()
+ {
+ initialized = false;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const std::string& type)
+ {
+ std::string grp_contents = global_state().get("dl", type);
+
+ if(grp_contents == "")
+ throw Invalid_Argument("DL_Group: Unknown group " + type);
+
+ DataSource_Memory pem(grp_contents);
+ PEM_decode(pem);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ PrimeType type, u32bit pbits, u32bit qbits)
+ {
+ if(pbits < 512)
+ throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) +
+ " is too small");
+
+ if(type == Strong)
+ {
+ p = random_safe_prime(rng, pbits);
+ q = (p - 1) / 2;
+ g = 2;
+ }
+ else if(type == Prime_Subgroup || type == DSA_Kosherizer)
+ {
+ if(type == Prime_Subgroup)
+ {
+ if(!qbits)
+ qbits = 2 * dl_work_factor(pbits);
+
+ q = random_prime(rng, qbits);
+ BigInt X;
+ while(p.bits() != pbits || !is_prime(p, rng))
+ {
+ X.randomize(rng, pbits);
+ p = X - (X % (2*q) - 1);
+ }
+ }
+ else
+ {
+ qbits = qbits ? qbits : ((pbits == 1024) ? 160 : 256);
+ generate_dsa_primes(rng,
+ global_state().algorithm_factory(),
+ p, q, pbits, qbits);
+ }
+
+ g = make_dsa_generator(p, q);
+ }
+
+ initialized = true;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(RandomNumberGenerator& rng,
+ const MemoryRegion<byte>& seed, u32bit pbits, u32bit qbits)
+ {
+ if(!generate_dsa_primes(rng,
+ global_state().algorithm_factory(),
+ p, q, pbits, qbits, seed))
+ throw Invalid_Argument("DL_Group: The seed given does not "
+ "generate a DSA group");
+
+ g = make_dsa_generator(p, q);
+
+ initialized = true;
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p1, const BigInt& g1)
+ {
+ initialize(p1, 0, g1);
+ }
+
+/*
+* DL_Group Constructor
+*/
+DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1)
+ {
+ initialize(p1, q1, g1);
+ }
+
+/*
+* DL_Group Initializer
+*/
+void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1)
+ {
+ if(p1 < 3)
+ throw Invalid_Argument("DL_Group: Prime invalid");
+ if(g1 < 2 || g1 >= p1)
+ throw Invalid_Argument("DL_Group: Generator invalid");
+ if(q1 < 0 || q1 >= p1)
+ throw Invalid_Argument("DL_Group: Subgroup invalid");
+
+ p = p1;
+ g = g1;
+ q = q1;
+
+ initialized = true;
+ }
+
+/*
+* Verify that the group has been set
+*/
+void DL_Group::init_check() const
+ {
+ if(!initialized)
+ throw Invalid_State("DLP group cannot be used uninitialized");
+ }
+
+/*
+* Verify the parameters
+*/
+bool DL_Group::verify_group(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ init_check();
+
+ if(g < 2 || p < 3 || q < 0)
+ return false;
+ if((q != 0) && ((p - 1) % q != 0))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(!check_prime(p, rng))
+ return false;
+ if((q > 0) && !check_prime(q, rng))
+ return false;
+ return true;
+ }
+
+/*
+* Return the prime
+*/
+const BigInt& DL_Group::get_p() const
+ {
+ init_check();
+ return p;
+ }
+
+/*
+* Return the generator
+*/
+const BigInt& DL_Group::get_g() const
+ {
+ init_check();
+ return g;
+ }
+
+/*
+* Return the subgroup
+*/
+const BigInt& DL_Group::get_q() const
+ {
+ init_check();
+ if(q == 0)
+ throw Format_Error("DLP group has no q prime specified");
+ return q;
+ }
+
+/*
+* DER encode the parameters
+*/
+SecureVector<byte> DL_Group::DER_encode(Format format) const
+ {
+ init_check();
+
+ if((q == 0) && (format != PKCS_3))
+ throw Encoding_Error("The ANSI DL parameter formats require a subgroup");
+
+ if(format == ANSI_X9_57)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(q)
+ .encode(g)
+ .end_cons()
+ .get_contents();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .encode(q)
+ .end_cons()
+ .get_contents();
+ }
+ else if(format == PKCS_3)
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(p)
+ .encode(g)
+ .end_cons()
+ .get_contents();
+ }
+
+ throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ }
+
+/*
+* PEM encode the parameters
+*/
+std::string DL_Group::PEM_encode(Format format) const
+ {
+ SecureVector<byte> encoding = DER_encode(format);
+ if(format == PKCS_3)
+ return PEM_Code::encode(encoding, "DH PARAMETERS");
+ else if(format == ANSI_X9_57)
+ return PEM_Code::encode(encoding, "DSA PARAMETERS");
+ else if(format == ANSI_X9_42)
+ return PEM_Code::encode(encoding, "X942 DH PARAMETERS");
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+ }
+
+/*
+* Decode BER encoded parameters
+*/
+void DL_Group::BER_decode(DataSource& source, Format format)
+ {
+ BigInt new_p, new_q, new_g;
+
+ BER_Decoder decoder(source);
+ BER_Decoder ber = decoder.start_cons(SEQUENCE);
+
+ if(format == ANSI_X9_57)
+ {
+ ber.decode(new_p)
+ .decode(new_q)
+ .decode(new_g)
+ .verify_end();
+ }
+ else if(format == ANSI_X9_42)
+ {
+ ber.decode(new_p)
+ .decode(new_g)
+ .decode(new_q)
+ .discard_remaining();
+ }
+ else if(format == PKCS_3)
+ {
+ ber.decode(new_p)
+ .decode(new_g)
+ .discard_remaining();
+ }
+ else
+ throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
+
+ initialize(new_p, new_q, new_g);
+ }
+
+/*
+* Decode PEM encoded parameters
+*/
+void DL_Group::PEM_decode(DataSource& source)
+ {
+ std::string label;
+ DataSource_Memory ber(PEM_Code::decode(source, label));
+
+ if(label == "DH PARAMETERS")
+ BER_decode(ber, PKCS_3);
+ else if(label == "DSA PARAMETERS")
+ BER_decode(ber, ANSI_X9_57);
+ else if(label == "X942 DH PARAMETERS")
+ BER_decode(ber, ANSI_X9_42);
+ else
+ throw Decoding_Error("DL_Group: Invalid PEM label " + label);
+ }
+
+/*
+* Create a random DSA-style generator
+*/
+BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
+ {
+ BigInt g, e = (p - 1) / q;
+
+ for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
+ {
+ g = power_mod(PRIMES[j], e, p);
+ if(g != 1)
+ break;
+ }
+
+ if(g == 1)
+ throw Exception("DL_Group: Couldn't create a suitable generator");
+
+ return g;
+ }
+
+}
diff --git a/botan/src/pubkey/dl_group/dl_group.h b/botan/src/pubkey/dl_group/dl_group.h
new file mode 100644
index 0000000..a84a85f
--- /dev/null
+++ b/botan/src/pubkey/dl_group/dl_group.h
@@ -0,0 +1,162 @@
+/*
+* Discrete Logarithm Group
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DL_PARAM_H__
+#define BOTAN_DL_PARAM_H__
+
+#include <botan/bigint.h>
+#include <botan/data_src.h>
+
+namespace Botan {
+
+/**
+* This class represents discrete logarithm groups. It holds a prime p,
+* a prime q = (p-1)/2 and g = x^((p-1)/q) mod p.
+*/
+class BOTAN_DLL DL_Group
+ {
+ public:
+ /**
+ * Get the prime p.
+ * @return the prime p
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Get the prime q.
+ * @return the prime q
+ */
+ const BigInt& get_q() const;
+
+ /**
+ * Get the base g.
+ * @return the base g
+ */
+ const BigInt& get_g() const;
+
+ /**
+ * The DL group encoding format variants.
+ */
+ enum Format {
+ ANSI_X9_42,
+ ANSI_X9_57,
+ PKCS_3,
+
+ DSA_PARAMETERS = ANSI_X9_57,
+ DH_PARAMETERS = ANSI_X9_42,
+ X942_DH_PARAMETERS = ANSI_X9_42,
+ PKCS3_DH_PARAMETERS = PKCS_3
+ };
+
+ /**
+ * Determine the prime creation for DL groups.
+ */
+ enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
+
+ /**
+ * Perform validity checks on the group.
+ * @param rng the rng to use
+ * @param strong whether to perform stronger by lengthier tests
+ * @return true if the object is consistent, false otherwise
+ */
+ bool verify_group(RandomNumberGenerator& rng, bool strong) const;
+
+ /**
+ * Encode this group into a string using PEM encoding.
+ * @param format the encoding format
+ * @return the string holding the PEM encoded group
+ */
+ std::string PEM_encode(Format format) const;
+
+ /**
+ * Encode this group into a string using DER encoding.
+ * @param format the encoding format
+ * @return the string holding the DER encoded group
+ */
+ SecureVector<byte> DER_encode(Format format) const;
+
+ /**
+ * Decode a DER/BER encoded group into this instance.
+ * @param src a DataSource providing the encoded group
+ * @param format the format of the encoded group
+ */
+ void BER_decode(DataSource& src, Format format);
+
+ /**
+ * Decode a PEM encoded group into this instance.
+ * @param src a DataSource providing the encoded group
+ */
+ void PEM_decode(DataSource& src);
+
+ /**
+ * Construct a DL group with uninitialized internal value.
+ * Use this constructor is you wish to set the groups values
+ * from a DER or PEM encoded group.
+ */
+ DL_Group();
+
+ /**
+ * Construct a DL group that is registered in the configuration.
+ * @param name the name that is configured in the global configuration
+ * for the desired group. If no configuration file is specified,
+ * the default values from the file policy.cpp will be used. For instance,
+ * use "modp/ietf/768" as name.
+ */
+ DL_Group(const std::string& name);
+
+ /**
+ * Create a new group randomly.
+ * @param rng the random number generator to use
+ * @param type specifies how the creation of primes p and q shall
+ * be performed. If type=Strong, then p will be determined as a
+ * safe prime, and q will be chosen as (p-1)/2. If
+ * type=Prime_Subgroup and qbits = 0, then the size of q will be
+ * determined according to the estimated difficulty of the DL
+ * problem. If type=DSA_Kosherizer, DSA primes will be created.
+ * @param pbits the number of bits of p
+ * @param qbits the number of bits of q. Leave it as 0 to have
+ * the value determined according to pbits.
+ */
+ DL_Group(RandomNumberGenerator& rng, PrimeType type,
+ u32bit pbits, u32bit qbits = 0);
+
+ /**
+ * Create a DSA group with a given seed.
+ * @param rng the random number generator to use
+ * @param seed the seed to use to create the random primes
+ * @param pbits the desired bit size of the prime p
+ * @param qbits the desired bit size of the prime q.
+ */
+ DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed,
+ u32bit pbits = 1024, u32bit qbits = 0);
+
+ /**
+ * Create a DL group. The prime q will be determined according to p.
+ * @param p the prime p
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& g);
+
+ /**
+ * Create a DL group.
+ * @param p the prime p
+ * @param q the prime q
+ * @param g the base g
+ */
+ DL_Group(const BigInt& p, const BigInt& q, const BigInt& g);
+ private:
+ static BigInt make_dsa_generator(const BigInt&, const BigInt&);
+
+ void init_check() const;
+ void initialize(const BigInt&, const BigInt&, const BigInt&);
+ bool initialized;
+ BigInt p, q, g;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dl_group/info.txt b/botan/src/pubkey/dl_group/info.txt
new file mode 100644
index 0000000..6b9884a
--- /dev/null
+++ b/botan/src/pubkey/dl_group/info.txt
@@ -0,0 +1,19 @@
+realname "DL Group"
+
+load_on auto
+
+define DL_GROUP
+
+<add>
+dl_group.cpp
+dl_group.h
+</add>
+
+<requires>
+asn1
+bigint
+filters
+libstate
+numbertheory
+pem
+</requires>
diff --git a/botan/src/pubkey/dlies/dlies.cpp b/botan/src/pubkey/dlies/dlies.cpp
new file mode 100644
index 0000000..c441ed1
--- /dev/null
+++ b/botan/src/pubkey/dlies/dlies.cpp
@@ -0,0 +1,137 @@
+/*
+* DLIES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dlies.h>
+#include <botan/look_pk.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* DLIES_Encryptor Constructor
+*/
+DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& k,
+ KDF* kdf_obj,
+ MessageAuthenticationCode* mac_obj,
+ u32bit mac_kl) :
+ key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl)
+ {
+ }
+
+DLIES_Encryptor::~DLIES_Encryptor()
+ {
+ delete kdf;
+ delete mac;
+ }
+
+/*
+* DLIES Encryption
+*/
+SecureVector<byte> DLIES_Encryptor::enc(const byte in[], u32bit length,
+ RandomNumberGenerator&) const
+ {
+ if(length > maximum_input_size())
+ throw Invalid_Argument("DLIES: Plaintext too large");
+ if(other_key.is_empty())
+ throw Invalid_State("DLIES: The other key was never set");
+
+ MemoryVector<byte> v = key.public_value();
+
+ SecureVector<byte> out(v.size() + length + mac->OUTPUT_LENGTH);
+ out.copy(v, v.size());
+ out.copy(v.size(), in, length);
+
+ SecureVector<byte> vz(v, key.derive_key(other_key, other_key.size()));
+
+ const u32bit K_LENGTH = length + mac_keylen;
+ OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size());
+ if(K.length() != K_LENGTH)
+ throw Encoding_Error("DLIES: KDF did not provide sufficient output");
+ byte* C = out + v.size();
+
+ xor_buf(C, K.begin() + mac_keylen, length);
+ mac->set_key(K.begin(), mac_keylen);
+
+ mac->update(C, length);
+ for(u32bit j = 0; j != 8; ++j)
+ mac->update(0);
+
+ mac->final(C + length);
+
+ return out;
+ }
+
+/*
+* Set the other parties public key
+*/
+void DLIES_Encryptor::set_other_key(const MemoryRegion<byte>& ok)
+ {
+ other_key = ok;
+ }
+
+/*
+* Return the max size, in bytes, of a message
+*/
+u32bit DLIES_Encryptor::maximum_input_size() const
+ {
+ return 32;
+ }
+
+/*
+* DLIES_Decryptor Constructor
+*/
+DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& k,
+ KDF* kdf_obj,
+ MessageAuthenticationCode* mac_obj,
+ u32bit mac_kl) :
+ key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl)
+ {
+ }
+
+DLIES_Decryptor::~DLIES_Decryptor()
+ {
+ delete kdf;
+ delete mac;
+ }
+
+/*
+* DLIES Decryption
+*/
+SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], u32bit length) const
+ {
+ const u32bit public_len = key.public_value().size();
+
+ if(length < public_len + mac->OUTPUT_LENGTH)
+ throw Decoding_Error("DLIES decryption: ciphertext is too short");
+
+ const u32bit CIPHER_LEN = length - public_len - mac->OUTPUT_LENGTH;
+
+ SecureVector<byte> v(msg, public_len);
+ SecureVector<byte> C(msg + public_len, CIPHER_LEN);
+ SecureVector<byte> T(msg + public_len + CIPHER_LEN, mac->OUTPUT_LENGTH);
+
+ SecureVector<byte> vz(v, key.derive_key(v, v.size()));
+
+ const u32bit K_LENGTH = C.size() + mac_keylen;
+ OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size());
+ if(K.length() != K_LENGTH)
+ throw Encoding_Error("DLIES: KDF did not provide sufficient output");
+
+ mac->set_key(K.begin(), mac_keylen);
+ mac->update(C);
+ for(u32bit j = 0; j != 8; ++j)
+ mac->update(0);
+ SecureVector<byte> T2 = mac->final();
+ if(T != T2)
+ throw Integrity_Failure("DLIES: message authentication failed");
+
+ xor_buf(C, K.begin() + mac_keylen, C.size());
+
+ return C;
+ }
+
+}
diff --git a/botan/src/pubkey/dlies/dlies.h b/botan/src/pubkey/dlies/dlies.h
new file mode 100644
index 0000000..88a22b9
--- /dev/null
+++ b/botan/src/pubkey/dlies/dlies.h
@@ -0,0 +1,69 @@
+/*
+* DLIES
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DLIES_H__
+#define BOTAN_DLIES_H__
+
+#include <botan/pubkey.h>
+#include <botan/mac.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/*
+* DLIES Encryption
+*/
+class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor
+ {
+ public:
+ DLIES_Encryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ u32bit mac_key_len = 20);
+
+ ~DLIES_Encryptor();
+
+ void set_other_key(const MemoryRegion<byte>&);
+ private:
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+ u32bit maximum_input_size() const;
+
+ const PK_Key_Agreement_Key& key;
+ SecureVector<byte> other_key;
+
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ u32bit mac_keylen;
+ };
+
+/*
+* DLIES Decryption
+*/
+class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor
+ {
+ public:
+ DLIES_Decryptor(const PK_Key_Agreement_Key&,
+ KDF* kdf,
+ MessageAuthenticationCode* mac,
+ u32bit mac_key_len = 20);
+
+ ~DLIES_Decryptor();
+
+ private:
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Key_Agreement_Key& key;
+
+ KDF* kdf;
+ MessageAuthenticationCode* mac;
+ u32bit mac_keylen;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dlies/info.txt b/botan/src/pubkey/dlies/info.txt
new file mode 100644
index 0000000..5138aaf
--- /dev/null
+++ b/botan/src/pubkey/dlies/info.txt
@@ -0,0 +1,16 @@
+realname "DLIES"
+
+define DLIES
+
+load_on auto
+
+<add>
+dlies.cpp
+dlies.h
+</add>
+
+<requires>
+kdf
+libstate
+mac
+</requires>
diff --git a/botan/src/pubkey/dsa/dsa.cpp b/botan/src/pubkey/dsa/dsa.cpp
new file mode 100644
index 0000000..b0688ae
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa.cpp
@@ -0,0 +1,134 @@
+/*
+* DSA
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dsa.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+
+namespace Botan {
+
+/*
+* DSA_PublicKey Constructor
+*/
+DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*
+* Algorithm Specific X.509 Initialization Code
+*/
+void DSA_PublicKey::X509_load_hook()
+ {
+ core = DSA_Core(group, y);
+ }
+
+/*
+* DSA Verification Function
+*/
+bool DSA_PublicKey::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ return core.verify(msg, msg_len, sig, sig_len);
+ }
+
+/*
+* Return the maximum input size in bits
+*/
+u32bit DSA_PublicKey::max_input_bits() const
+ {
+ return group_q().bits();
+ }
+
+/*
+* Return the size of each portion of the sig
+*/
+u32bit DSA_PublicKey::message_part_size() const
+ {
+ return group_q().bytes();
+ }
+
+/*
+* Create a DSA private key
+*/
+DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ {
+ x = BigInt::random_integer(rng, 2, group_q() - 1);
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*
+* Algorithm Specific PKCS #8 Initialization Code
+*/
+void DSA_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ y = power_mod(group_g(), x, group_p());
+ core = DSA_Core(group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* DSA Signature Operation
+*/
+SecureVector<byte> DSA_PrivateKey::sign(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ const BigInt& q = group_q();
+
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ return core.sign(in, length, k);
+ }
+
+/*
+* Check Private DSA Parameters
+*/
+bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
+ return false;
+
+ if(!strong)
+ return true;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA1(SHA-1)"),
+ get_pk_verifier(*this, "EMSA1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/dsa/dsa.h b/botan/src/pubkey/dsa/dsa.h
new file mode 100644
index 0000000..4c9b708
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa.h
@@ -0,0 +1,62 @@
+/*
+* DSA
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_H__
+#define BOTAN_DSA_H__
+
+#include <botan/dl_algo.h>
+#include <botan/dsa_core.h>
+
+namespace Botan {
+
+/*
+* DSA Public Key
+*/
+class BOTAN_DLL DSA_PublicKey : public PK_Verifying_wo_MR_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "DSA"; }
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DSA_PublicKey() {}
+ DSA_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ DSA_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* DSA Private Key
+*/
+class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ DSA_PrivateKey() {}
+ DSA_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dsa/dsa_core.cpp b/botan/src/pubkey/dsa/dsa_core.cpp
new file mode 100644
index 0000000..e5a23a5
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa_core.cpp
@@ -0,0 +1,63 @@
+/*
+* DSA Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dsa_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* DSA_Core Constructor
+*/
+DSA_Core::DSA_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::dsa_op(group, y, x);
+ }
+
+/*
+* DSA_Core Copy Constructor
+*/
+DSA_Core::DSA_Core(const DSA_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*
+* DSA_Core Assignment Operator
+*/
+DSA_Core& DSA_Core::operator=(const DSA_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*
+* DSA Verification Operation
+*/
+bool DSA_Core::verify(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length) const
+ {
+ return op->verify(msg, msg_length, sig, sig_length);
+ }
+
+/*
+* DSA Signature Operation
+*/
+SecureVector<byte> DSA_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+}
diff --git a/botan/src/pubkey/dsa/dsa_core.h b/botan/src/pubkey/dsa/dsa_core.h
new file mode 100644
index 0000000..8bb1621
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa_core.h
@@ -0,0 +1,37 @@
+/*
+* DSA Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_CORE_H__
+#define BOTAN_DSA_CORE_H__
+
+#include <botan/dsa_op.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* DSA Core
+*/
+class BOTAN_DLL DSA_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+
+ DSA_Core& operator=(const DSA_Core&);
+
+ DSA_Core() { op = 0; }
+ DSA_Core(const DSA_Core&);
+ DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~DSA_Core() { delete op; }
+ private:
+ DSA_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dsa/dsa_op.cpp b/botan/src/pubkey/dsa/dsa_op.cpp
new file mode 100644
index 0000000..5b92144
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa_op.cpp
@@ -0,0 +1,73 @@
+/*
+* DSA Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dsa_op.h>
+
+namespace Botan {
+
+/*
+* Default_DSA_Op Constructor
+*/
+Default_DSA_Op::Default_DSA_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*
+* Default DSA Verify Operation
+*/
+bool Default_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const BigInt& q = group.get_q();
+
+ if(sig_len != 2*q.bytes() || msg_len > q.bytes())
+ return false;
+
+ BigInt r(sig, q.bytes());
+ BigInt s(sig + q.bytes(), q.bytes());
+ BigInt i(msg, msg_len);
+
+ if(r <= 0 || r >= q || s <= 0 || s >= q)
+ return false;
+
+ s = inverse_mod(s, q);
+ s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)),
+ powermod_y_p(mod_q.multiply(s, r)));
+
+ return (mod_q.reduce(s) == r);
+ }
+
+/*
+* Default DSA Sign Operation
+*/
+SecureVector<byte> Default_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_DSA_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+ BigInt i(in, length);
+
+ BigInt r = mod_q.reduce(powermod_g_p(k));
+ BigInt s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i));
+
+ if(r.is_zero() || s.is_zero())
+ throw Internal_Error("Default_DSA_Op::sign: r or s was zero");
+
+ SecureVector<byte> output(2*q.bytes());
+ r.binary_encode(output + (output.size() / 2 - r.bytes()));
+ s.binary_encode(output + (output.size() - s.bytes()));
+ return output;
+ }
+
+}
diff --git a/botan/src/pubkey/dsa/dsa_op.h b/botan/src/pubkey/dsa/dsa_op.h
new file mode 100644
index 0000000..0b112c6
--- /dev/null
+++ b/botan/src/pubkey/dsa/dsa_op.h
@@ -0,0 +1,53 @@
+/*
+* DSA Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DSA_OPS_H__
+#define BOTAN_DSA_OPS_H__
+
+#include <botan/numthry.h>
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* DSA Operation
+*/
+class BOTAN_DLL DSA_Operation
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual DSA_Operation* clone() const = 0;
+ virtual ~DSA_Operation() {}
+ };
+
+/*
+* Botan's Default DSA Operation
+*/
+class BOTAN_DLL Default_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new Default_DSA_Op(*this); }
+
+ Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/dsa/info.txt b/botan/src/pubkey/dsa/info.txt
new file mode 100644
index 0000000..c70e02d
--- /dev/null
+++ b/botan/src/pubkey/dsa/info.txt
@@ -0,0 +1,22 @@
+realname "DSA"
+
+define DSA
+
+load_on auto
+
+<add>
+dsa.cpp
+dsa.h
+dsa_core.cpp
+dsa_core.h
+dsa_op.cpp
+dsa_op.h
+</add>
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/ec_dompar/ec_dompar.cpp b/botan/src/pubkey/ec_dompar/ec_dompar.cpp
new file mode 100644
index 0000000..6cfcc06
--- /dev/null
+++ b/botan/src/pubkey/ec_dompar/ec_dompar.cpp
@@ -0,0 +1,573 @@
+
+#include <botan/ec_dompar.h>
+#include <botan/pubkey_enums.h>
+#include <botan/parsing.h>
+#include <botan/hex.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+namespace {
+
+std::vector<std::string> get_standard_domain_parameter(const std::string& oid)
+ {
+ // using a linear search here is pretty nasty... revisit
+
+ /* SEC2 */
+
+ if(oid == "1.3.132.0.6")
+ {
+ /* secp112r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xdb7c2abf62e35e668076bead208b"); //p
+ dom_par.push_back("0xDB7C2ABF62E35E668076BEAD2088"); // a
+ dom_par.push_back("0x659EF8BA043916EEDE8911702B22"); // b
+ dom_par.push_back("0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0ff77500"); // G
+ dom_par.push_back("0xDB7C2ABF62E35E7628DFAC6561C5"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.7")
+ {
+ /* secp112r2; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xdb7c2abf62e35e668076bead208b"); //p
+ dom_par.push_back("0x6127C24C05F38A0AAAF65C0EF02C"); // a
+ dom_par.push_back("0x51DEF1815DB5ED74FCC34C85D709"); // b
+ dom_par.push_back("044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97"); // G
+ dom_par.push_back("0x36DF0AAFD8B8D7597CA10520D04B"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.28")
+ {
+ /* secp128r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffdffffffffffffffffffffffff"); //p
+ dom_par.push_back("0xffffffFDffffffffffffffffffffffFC"); // a
+ dom_par.push_back("0xE87579C11079F43DD824993C2CEE5ED3"); // b
+ dom_par.push_back("04161ff7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83"); // G
+ dom_par.push_back("0xffffffFE0000000075A30D1B9038A115"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.29")
+ {
+ /* secp128r2; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffdffffffffffffffffffffffff"); //p
+ dom_par.push_back("0xD6031998D1B3BBFEBF59CC9BBff9AEE1"); // a
+ dom_par.push_back("0x5EEEFCA380D02919DC2C6558BB6D8A5D"); // b
+ dom_par.push_back("047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44"); // G
+ dom_par.push_back("0x3ffffffF7ffffffFBE0024720613B5A3"); // order
+ dom_par.push_back("4"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.9")
+ {
+ /* secp160k1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffac73"); //p
+ dom_par.push_back("0x0000000000000000000000000000000000000000"); // a
+ dom_par.push_back("0x0000000000000000000000000000000000000007"); // b
+ dom_par.push_back("043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE"); // G
+ dom_par.push_back("0x0100000000000000000001B8FA16DFAB9ACA16B6B3"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.30")
+ {
+ /* secp160r2; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffac73"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffFEffffAC70"); // a
+ dom_par.push_back("0xB4E134D3FB59EB8BAB57274904664D5AF50388BA"); // b
+ dom_par.push_back("0452DCB034293A117E1F4ff11B30F7199D3144CE6DFEAffEF2E331F296E071FA0DF9982CFEA7D43F2E"); // G
+ dom_par.push_back("0x0100000000000000000000351EE786A818F3A1A16B"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.31")
+ {
+ /* secp192k1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffffffffffeffffee37"); //p
+ dom_par.push_back("0x000000000000000000000000000000000000000000000000"); // a
+ dom_par.push_back("0x000000000000000000000000000000000000000000000003"); // b
+ dom_par.push_back("04DB4ff10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"); // G
+ dom_par.push_back("0xffffffffffffffffffffffFE26F2FC170F69466A74DEFD8D"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.32")
+ {
+ /* secp224k1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d"); //p
+ dom_par.push_back("0x00000000000000000000000000000000000000000000000000000000"); // a
+ dom_par.push_back("0x00000000000000000000000000000000000000000000000000000005"); // b
+ dom_par.push_back("04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"); // G
+ dom_par.push_back("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.33")
+ {
+ /* secp224r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xffffffffffffffffffffffffffffffff000000000000000000000001"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffFEffffffffffffffffffffffFE"); // a
+ dom_par.push_back("0xB4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355ffB4"); // b
+ dom_par.push_back("04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"); // G
+ dom_par.push_back("0xffffffffffffffffffffffffffff16A2E0B8F03E13DD29455C5C2A3D"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.10")
+ {
+ /* secp256k1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); //p
+ dom_par.push_back("0x0000000000000000000000000000000000000000000000000000000000000000"); // a
+ dom_par.push_back("0x0000000000000000000000000000000000000000000000000000000000000007"); // b
+ dom_par.push_back("0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); // G
+ dom_par.push_back("0xffffffffffffffffffffffffffffffFEBAAEDCE6AF48A03BBFD25E8CD0364141"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.34")
+ {
+ /* secp384r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFEffffffff0000000000000000ffffffFC"); // a
+ dom_par.push_back("0xB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"); // b
+ dom_par.push_back("04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"); // G
+ dom_par.push_back("0xffffffffffffffffffffffffffffffffffffffffffffffffC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.35")
+ {
+ /* secp521r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); //p
+ dom_par.push_back("0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC"); // a
+ dom_par.push_back("0x0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"); // b
+ dom_par.push_back("0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"); // G
+ dom_par.push_back("0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ /* NIS */
+
+ if(oid == "1.3.6.1.4.1.8301.3.1.2.9.0.38")
+ {
+ /* NIST curve P-521; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); //p
+ dom_par.push_back("0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFC"); // a
+ dom_par.push_back("0x051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"); // b
+ dom_par.push_back("0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"); // G
+ dom_par.push_back("0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ /* BrainPool */
+
+ if(oid == "1.3.36.3.3.2.8.1.1.1")
+ {
+ /* brainpoolP160r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xE95E4A5F737059DC60DFC7AD95B3D8139515620F"); //p
+ dom_par.push_back("0x340E7BE2A280EB74E2BE61BADA745D97E8F7C300"); // a
+ dom_par.push_back("0x1E589A8595423412134FAA2DBDEC95C8D8675E58"); // b
+ dom_par.push_back("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321"); // G
+ dom_par.push_back("0xE95E4A5F737059DC60DF5991D45029409E60FC09"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.3")
+ {
+ /* brainpoolP192r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xC302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297"); //p
+ dom_par.push_back("0x6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF"); // a
+ dom_par.push_back("0x469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9"); // b
+ dom_par.push_back("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F"); // G
+ dom_par.push_back("0xC302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.5")
+ {
+ /* brainpoolP224r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xD7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF"); //p
+ dom_par.push_back("0x68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43"); // a
+ dom_par.push_back("0x2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B"); // b
+ dom_par.push_back("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD"); // G
+ dom_par.push_back("0xD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.7")
+ {
+ /* brainpoolP256r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xA9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377"); //p
+ dom_par.push_back("0x7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9"); // a
+ dom_par.push_back("0x26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6"); // b
+ dom_par.push_back("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997"); // G
+ dom_par.push_back("0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.9")
+ {
+ /* brainpoolP320r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xD35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27"); //p
+ dom_par.push_back("0x3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4"); // a
+ dom_par.push_back("0x520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6"); // b
+ dom_par.push_back("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1"); // G
+ dom_par.push_back("0xD35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.11")
+ {
+ /* brainpoolP384r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53"); //p
+ dom_par.push_back("0x7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826"); // a
+ dom_par.push_back("0x4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11"); // b
+ dom_par.push_back("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315"); // G
+ dom_par.push_back("0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.36.3.3.2.8.1.1.13")
+ {
+ /* brainpoolP512r1; source: Flexiprovider */
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3"); //p
+ dom_par.push_back("0x7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA"); // a
+ dom_par.push_back("0x3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723"); // b
+ dom_par.push_back("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892"); // G
+ dom_par.push_back("0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069"); // order
+ dom_par.push_back("1"); // cofactor
+
+ return dom_par;
+ }
+
+ if(oid == "1.3.132.0.8")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xffffffffffffffffffffffffffffffff7fffffff"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffff7ffffffc"); // a
+ dom_par.push_back("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); // b
+ dom_par.push_back("024a96b5688ef573284664698968c38bb913cbfc82"); // G
+ dom_par.push_back("0x0100000000000000000001f4c8f927aed3ca752257"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ if(oid == "1.2.840.10045.3.1.1") // prime192v1 Flexiprovider
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffefffffffffffffffc"); // a
+ dom_par.push_back("0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"); // b
+ dom_par.push_back("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"); // G
+ dom_par.push_back("0xffffffffffffffffffffffff99def836146bc9b1b4d22831"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime192v2; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.2")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xffffffffffffffffffffffffffffffFeffffffffffffffFC"); // a
+ dom_par.push_back("0xcc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953"); // b
+ dom_par.push_back("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a"); // G
+ dom_par.push_back("0xfffffffffffffffffffffffe5fb1a724dc80418648d8dd31"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime192v3; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.3")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffeffffffffffffffff"); //p
+ dom_par.push_back("0xfffffffffffffffffffffffffffffffefffffffffffffffc"); // a
+ dom_par.push_back("0x22123dc2395a05caa7423daeccc94760a7d462256bd56916"); // b
+ dom_par.push_back("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896"); // G
+ dom_par.push_back("0xffffffffffffffffffffffff7a62d031c83f4294f640ec13"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime239v1; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.4")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7fffffffffff8000000000007ffffffffffc"); // a
+ dom_par.push_back("0x6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A"); // b
+ dom_par.push_back("020ffA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime239v2; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.5")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7ffFffffffff8000000000007ffFffffffFC"); // a
+ dom_par.push_back("0x617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C"); // b
+ dom_par.push_back("0238AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff800000CFA7E8594377D414C03821BC582063"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime239v3; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.6")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); //p
+ dom_par.push_back("0x7ffFffffffffffffffffffff7ffFffffffff8000000000007ffFffffffFC"); // a
+ dom_par.push_back("0x255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E"); // b
+ dom_par.push_back("036768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A"); // G
+ dom_par.push_back("0x7fffffffffffffffffffffff7fffff975DEB41B3A6057C3C432146526551"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ /* prime256v1; source: Flexiprovider */
+ if(oid == "1.2.840.10045.3.1.7")
+ {
+ std::vector<std::string> dom_par;
+ dom_par.push_back("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"); //p
+ dom_par.push_back("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffFC"); // a
+ dom_par.push_back("0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); // b
+ dom_par.push_back("036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"); // G
+ dom_par.push_back("0xffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551"); // order
+ dom_par.push_back("1"); // cofactor
+ return dom_par;
+ }
+
+ throw Invalid_Argument("No such ECC curve " + oid);
+ }
+
+EC_Domain_Params get_ec_dompar(const std::string& oid)
+ {
+ std::vector<std::string> dom_par = get_standard_domain_parameter(oid);
+
+ BigInt p(dom_par[0]); // give as 0x...
+ GFpElement a(p, BigInt(dom_par[1]));
+ GFpElement b(p, BigInt(dom_par[2]));
+
+ Pipe pipe(new Hex_Decoder);
+ pipe.process_msg(dom_par[3]);
+ SecureVector<byte> sv_g = pipe.read_all();
+
+ CurveGFp curve(a, b, p);
+ PointGFp G = OS2ECP ( sv_g, curve );
+ G.check_invariants();
+ BigInt order(dom_par[4]);
+ BigInt cofactor(dom_par[5]);
+ EC_Domain_Params result(curve, G, order, cofactor);
+ return result;
+ }
+
+}
+
+EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid)
+ {
+ EC_Domain_Params result = get_ec_dompar(oid);
+ result.m_oid = oid;
+ return result;
+ }
+
+EC_Domain_Params::EC_Domain_Params(const CurveGFp& curve, const PointGFp& base_point,
+ const BigInt& order, const BigInt& cofactor)
+ : m_curve(curve),
+ m_base_point(base_point),
+ m_order(order),
+ m_cofactor(cofactor),
+ m_oid("")
+ { }
+
+namespace {
+
+SecureVector<byte> encode_der_ec_dompar_explicit(EC_Domain_Params const& dom_pars)
+ {
+ u32bit ecpVers1 = 1;
+ OID curve_type_oid("1.2.840.10045.1.1");
+
+ DER_Encoder der;
+
+ der.start_cons(SEQUENCE)
+ .encode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .encode(curve_type_oid)
+ .encode(dom_pars.get_curve().get_p())
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(FE2OSP ( dom_pars.get_curve().get_a() ), OCTET_STRING)
+ .encode(FE2OSP ( dom_pars.get_curve().get_b() ), OCTET_STRING)
+ .end_cons()
+ .encode(EC2OSP ( dom_pars.get_base_point(), PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(dom_pars.get_order())
+ .encode(dom_pars.get_cofactor())
+ .end_cons();
+
+ return der.get_contents();
+ }
+
+EC_Domain_Params decode_ber_ec_dompar_explicit(SecureVector<byte> const& encoded)
+ {
+ BigInt ecpVers1(1);
+ OID curve_type_oid;
+ SecureVector<byte> sv_a;
+ SecureVector<byte> sv_b;
+ BigInt p;
+ SecureVector<byte> sv_base_point;
+ BigInt order;
+ BigInt cofactor;
+ BER_Decoder dec(encoded);
+ dec
+ .start_cons(SEQUENCE)
+ .decode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .decode(curve_type_oid)
+ .decode(p)
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .decode(sv_a, OCTET_STRING)
+ .decode(sv_b, OCTET_STRING)
+ .end_cons()
+ .decode(sv_base_point, OCTET_STRING)
+ .decode(order)
+ .decode(cofactor)
+ .verify_end()
+ .end_cons();
+ if(ecpVers1 != 1)
+ {
+ throw Decoding_Error("wrong ecpVers");
+ }
+ // Set the domain parameters
+ if(curve_type_oid.as_string() != "1.2.840.10045.1.1") // NOTE: hardcoded: prime field type
+ {
+ throw Decoding_Error("wrong curve type oid where prime field was expected");
+ }
+ GFpElement a(p,BigInt::decode(sv_a, sv_a.size()));
+ GFpElement b(p,BigInt::decode(sv_b, sv_b.size()));
+ CurveGFp curve(a,b,p);
+ PointGFp G = OS2ECP ( sv_base_point, curve );
+ G.check_invariants();
+ return EC_Domain_Params(curve, G, order, cofactor);
+ }
+
+} // end anonymous namespace
+
+SecureVector<byte> encode_der_ec_dompar(EC_Domain_Params const& dom_pars, EC_dompar_enc enc_type)
+ {
+ SecureVector<byte> result;
+
+ if(enc_type == ENC_EXPLICIT)
+ {
+ result = encode_der_ec_dompar_explicit(dom_pars);
+ }
+ else if(enc_type == ENC_OID)
+ {
+ OID dom_par_oid(dom_pars.get_oid());
+ result = DER_Encoder().encode(dom_par_oid).get_contents();
+ }
+ else if(enc_type == ENC_IMPLICITCA)
+ {
+ result = DER_Encoder().encode_null().get_contents();
+ }
+ else
+ {
+ throw Internal_Error("encountered illegal value for ec parameter encoding type");
+ }
+ return result;
+ }
+
+EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded)
+ {
+ BER_Decoder dec(encoded);
+ BER_Object obj = dec.get_next_object();
+ ASN1_Tag tag = obj.type_tag;
+ std::auto_ptr<EC_Domain_Params> p_result;
+
+ if(tag == OBJECT_ID)
+ {
+ OID dom_par_oid;
+ BER_Decoder(encoded).decode(dom_par_oid);
+ return EC_Domain_Params(get_ec_dompar(dom_par_oid.as_string()));
+ }
+ else if(tag == SEQUENCE)
+ return EC_Domain_Params(decode_ber_ec_dompar_explicit(encoded));
+ else if(tag == NULL_TAG)
+ throw Decoding_Error("cannot decode ECDSA parameters that are ImplicitCA");
+
+ throw Decoding_Error("encountered unexpected when trying to decode domain parameters");
+ }
+
+bool operator==(EC_Domain_Params const& lhs, EC_Domain_Params const& rhs)
+ {
+ return ((lhs.get_curve() == rhs.get_curve()) &&
+ (lhs.get_base_point() == rhs.get_base_point()) &&
+ (lhs.get_order() == rhs.get_order()) &&
+ (lhs.get_cofactor() == rhs.get_cofactor()));
+ }
+
+}
+
diff --git a/botan/src/pubkey/ec_dompar/ec_dompar.h b/botan/src/pubkey/ec_dompar/ec_dompar.h
new file mode 100644
index 0000000..47971d8
--- /dev/null
+++ b/botan/src/pubkey/ec_dompar/ec_dompar.h
@@ -0,0 +1,121 @@
+/*
+* ECDSA Domain Parameters
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_DOMAIN_PARAMETERS_H__
+#define BOTAN_ECC_DOMAIN_PARAMETERS_H__
+
+#include <botan/point_gfp.h>
+#include <botan/gfp_element.h>
+#include <botan/curve_gfp.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/alg_id.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/**
+* This class represents elliptic curce domain parameters
+*/
+class BOTAN_DLL EC_Domain_Params
+ {
+ public:
+
+ /**
+ * Construct Domain paramers from specified parameters
+ * @param curve elliptic curve
+ * @param base_point a base point
+ * @param order the order of the base point
+ * @param cofactor the cofactor
+ */
+ EC_Domain_Params(const CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor);
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const CurveGFp& get_curve() const
+ {
+ return m_curve;
+ }
+
+ /**
+ * Return domain parameter curve
+ * @result domain parameter curve
+ */
+ const PointGFp& get_base_point() const
+ {
+ return m_base_point;
+ }
+
+ /**
+ * Return the order of the base point
+ * @result order of the base point
+ */
+ const BigInt& get_order() const
+ {
+ return m_order;
+ }
+
+ /**
+ * Return the cofactor
+ * @result the cofactor
+ */
+ const BigInt& get_cofactor() const
+ {
+ return m_cofactor;
+ }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ std::string get_oid() const { return m_oid; }
+
+ private:
+ friend EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+ CurveGFp m_curve;
+ PointGFp m_base_point;
+ BigInt m_order;
+ BigInt m_cofactor;
+ std::string m_oid;
+ };
+
+bool operator==(EC_Domain_Params const& lhs, EC_Domain_Params const& rhs);
+
+inline bool operator!=(const EC_Domain_Params& lhs,
+ const EC_Domain_Params& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+enum EC_dompar_enc { ENC_EXPLICIT = 0, ENC_IMPLICITCA = 1, ENC_OID = 2 };
+
+SecureVector<byte> encode_der_ec_dompar(EC_Domain_Params const& dom_pars,
+ EC_dompar_enc enc_type);
+
+EC_Domain_Params decode_ber_ec_dompar(SecureVector<byte> const& encoded);
+
+/**
+* Factory function, the only way to obtain EC domain parameters with
+* an OID. The demanded OID has to be registered in the InSiTo
+* configuration. Consult the file ec_dompar.cpp for the default
+* configuration.
+* @param oid the oid of the demanded EC domain parameters
+* @result the EC domain parameters associated with the OID
+*/
+EC_Domain_Params get_EC_Dom_Pars_by_oid(std::string oid);
+
+}
+
+#endif
diff --git a/botan/src/pubkey/ec_dompar/info.txt b/botan/src/pubkey/ec_dompar/info.txt
new file mode 100644
index 0000000..2127837
--- /dev/null
+++ b/botan/src/pubkey/ec_dompar/info.txt
@@ -0,0 +1,18 @@
+realname "ECC Domain Parameters"
+
+define ECC_DOMAIN_PARAMATERS
+
+load_on auto
+
+<add>
+ec_dompar.cpp
+ec_dompar.h
+</add>
+
+<requires>
+asn1
+bigint
+filters
+gfpmath
+hex
+</requires>
diff --git a/botan/src/pubkey/ecc_key/ecc_key.cpp b/botan/src/pubkey/ecc_key/ecc_key.cpp
new file mode 100644
index 0000000..615efec
--- /dev/null
+++ b/botan/src/pubkey/ecc_key/ecc_key.cpp
@@ -0,0 +1,269 @@
+/*
+* ECC Key implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecc_key.h>
+#include <botan/x509_key.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/secmem.h>
+#include <botan/point_gfp.h>
+
+namespace Botan {
+
+/*
+* EC_PublicKey
+*/
+void EC_PublicKey::affirm_init() const // virtual
+ {
+ if((mp_dom_pars.get() == 0) || (mp_public_point.get() == 0))
+ throw Invalid_State("cannot use uninitialized EC_Key");
+ }
+
+const EC_Domain_Params& EC_PublicKey::domain_parameters() const
+ {
+ if(!mp_dom_pars.get())
+ throw Invalid_State("EC_PublicKey::domain_parameters(): "
+ "ec domain parameters are not yet set");
+
+ return *mp_dom_pars;
+ }
+
+const PointGFp& EC_PublicKey::public_point() const
+ {
+ if(!mp_public_point.get())
+ throw Invalid_State("EC_PublicKey::public_point(): public point not set");
+
+ return *mp_public_point;
+ }
+
+bool EC_PublicKey::domain_parameters_set()
+ {
+ return mp_dom_pars.get();
+ }
+
+void EC_PublicKey::X509_load_hook()
+ {
+ try
+ {
+ // the base point is checked to be on curve already when decoding it
+ affirm_init();
+ mp_public_point->check_invariants();
+ }
+ catch(Illegal_Point)
+ {
+ throw Decoding_Error("decoded public point was found not to lie on curve");
+ }
+ }
+
+X509_Encoder* EC_PublicKey::x509_encoder() const
+ {
+ class EC_Key_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ key->affirm_init();
+
+ SecureVector<byte> params =
+ encode_der_ec_dompar(key->domain_parameters(), key->m_param_enc);
+
+ return AlgorithmIdentifier(key->get_oid(), params);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ key->affirm_init();
+ return EC2OSP(*(key->mp_public_point), PointGFp::COMPRESSED);
+ }
+
+ EC_Key_Encoder(const EC_PublicKey* k): key(k) {}
+ private:
+ const EC_PublicKey* key;
+ };
+
+ return new EC_Key_Encoder(this);
+ }
+
+X509_Decoder* EC_PublicKey::x509_decoder()
+ {
+ class EC_Key_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ key->mp_dom_pars.reset(new EC_Domain_Params(decode_ber_ec_dompar(alg_id.parameters)));
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ key->mp_public_point.reset(
+ new PointGFp(
+ OS2ECP(bits, key->domain_parameters().get_curve())
+ ));
+
+ key->X509_load_hook();
+ }
+
+ EC_Key_Decoder(EC_PublicKey* k): key(k) {}
+ private:
+ EC_PublicKey* key;
+ };
+
+ return new EC_Key_Decoder(this);
+ }
+
+void EC_PublicKey::set_parameter_encoding(EC_dompar_enc type)
+ {
+ if((type != ENC_EXPLICIT) && (type != ENC_IMPLICITCA) && (type != ENC_OID))
+ throw Invalid_Argument("Invalid encoding type for EC-key object specified");
+
+ affirm_init();
+
+ if((type == ENC_OID) && (mp_dom_pars->get_oid() == ""))
+ throw Invalid_Argument("Invalid encoding type ENC_OID specified for "
+ "EC-key object whose corresponding domain "
+ "parameters are without oid");
+
+ m_param_enc = type;
+ }
+
+/********************************
+* EC_PrivateKey
+********************************/
+void EC_PrivateKey::affirm_init() const // virtual
+ {
+ if(m_private_value == 0)
+ throw Invalid_State("cannot use EC_PrivateKey when private key is uninitialized");
+
+ EC_PublicKey::affirm_init();
+ }
+
+const BigInt& EC_PrivateKey::private_value() const
+ {
+ if(m_private_value == 0)
+ throw Invalid_State("cannot use EC_PrivateKey when private key is uninitialized");
+
+ return m_private_value;
+ }
+
+/**
+* EC_PrivateKey generator
+**/
+void EC_PrivateKey::generate_private_key(RandomNumberGenerator& rng)
+ {
+ if(mp_dom_pars.get() == 0)
+ {
+ throw Invalid_State("cannot generate private key when domain parameters are not set");
+ }
+
+ BigInt tmp_private_value(0);
+ tmp_private_value = BigInt::random_integer(rng, 1, mp_dom_pars->get_order());
+ mp_public_point = std::auto_ptr<PointGFp>( new PointGFp (mp_dom_pars->get_base_point()));
+ mp_public_point->mult_this_secure(tmp_private_value,
+ mp_dom_pars->get_order(),
+ mp_dom_pars->get_order()-1);
+
+ //assert(mp_public_point.get() != 0);
+ tmp_private_value.swap(m_private_value);
+ }
+
+/**
+* Return the PKCS #8 public key encoder
+**/
+PKCS8_Encoder* EC_PrivateKey::pkcs8_encoder() const
+ {
+ class EC_Key_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ key->affirm_init();
+
+ SecureVector<byte> params =
+ encode_der_ec_dompar(key->domain_parameters(), ENC_EXPLICIT);
+
+ return AlgorithmIdentifier(key->get_oid(), params);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ key->affirm_init();
+ SecureVector<byte> octstr_secret =
+ BigInt::encode_1363(key->m_private_value, key->m_private_value.bytes());
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(BigInt(1))
+ .encode(octstr_secret, OCTET_STRING)
+ .end_cons()
+ .get_contents();
+ }
+
+ EC_Key_Encoder(const EC_PrivateKey* k): key(k) {}
+ private:
+ const EC_PrivateKey* key;
+ };
+
+ return new EC_Key_Encoder(this);
+ }
+
+/**
+* Return the PKCS #8 public key decoder
+*/
+PKCS8_Decoder* EC_PrivateKey::pkcs8_decoder(RandomNumberGenerator&)
+ {
+ class EC_Key_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier& alg_id)
+ {
+ key->mp_dom_pars.reset(new EC_Domain_Params(decode_ber_ec_dompar(alg_id.parameters)));
+ }
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ u32bit version;
+ SecureVector<byte> octstr_secret;
+
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(octstr_secret, OCTET_STRING)
+ .verify_end()
+ .end_cons();
+
+ key->m_private_value = BigInt::decode(octstr_secret, octstr_secret.size());
+
+ if(version != 1)
+ throw Decoding_Error("Wrong PKCS #1 key format version for EC key");
+
+ key->PKCS8_load_hook();
+ }
+
+ EC_Key_Decoder(EC_PrivateKey* k): key(k) {}
+ private:
+ EC_PrivateKey* key;
+ };
+
+ return new EC_Key_Decoder(this);
+ }
+
+void EC_PrivateKey::PKCS8_load_hook(bool)
+ {
+ // we cannot use affirm_init() here because mp_public_point might still be null
+ if(mp_dom_pars.get() == 0)
+ throw Invalid_State("attempt to set public point for an uninitialized key");
+
+ mp_public_point.reset(new PointGFp(m_private_value * mp_dom_pars->get_base_point()));
+ mp_public_point->check_invariants();
+ }
+
+}
diff --git a/botan/src/pubkey/ecc_key/ecc_key.h b/botan/src/pubkey/ecc_key/ecc_key.h
new file mode 100644
index 0000000..0ca9a0e
--- /dev/null
+++ b/botan/src/pubkey/ecc_key/ecc_key.h
@@ -0,0 +1,154 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H__
+#define BOTAN_ECC_PUBLIC_KEY_BASE_H__
+
+#include <botan/bigint.h>
+#include <botan/curve_gfp.h>
+#include <botan/pk_keys.h>
+#include <botan/ec_dompar.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract EC Public Keys. When encoding a key
+* via an encoder that can be accessed via the corresponding member
+* functions, the key will decide upon its internally stored encoding
+* information whether to encode itself with or without domain
+* parameters, or using the domain parameter oid. Furthermore, a public
+* key without domain parameters can be decoded. In that case, it
+* cannot be used for verification until its domain parameters are set
+* by calling the corresponding member function.
+*/
+class BOTAN_DLL EC_PublicKey : public virtual Public_Key
+ {
+ public:
+
+ /**
+ * Tells whether this key knows his own domain parameters.
+ * @result true if the domain parameters are set, false otherwise
+ */
+ bool domain_parameters_set();
+
+ /**
+ * Get the public point of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the public point of this key
+ */
+ const PointGFp& public_point() const;
+
+ /**
+ * Get the domain parameters of this key.
+ * @throw Invalid_State is thrown if the
+ * domain parameters of this point are not set
+ * @result the domain parameters of this key
+ */
+ const EC_Domain_Params& domain_parameters() const;
+
+ /**
+ * Set the domain parameter encoding to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_parameter_encoding(EC_dompar_enc enc);
+
+ /**
+ * Get the domain parameter encoding to be used when encoding this key.
+ * @result the encoding to use
+ */
+ inline int get_parameter_encoding() const
+ {
+ return m_param_enc;
+ }
+
+ //ctors
+ EC_PublicKey()
+ : m_param_enc(ENC_EXPLICIT)
+ {
+ //assert(mp_dom_pars.get() == 0);
+ //assert(mp_public_point.get() == 0);
+ }
+
+ /**
+ * Get an x509_encoder that can be used to encode this key.
+ * @result an x509_encoder for this key
+ */
+ X509_Encoder* x509_encoder() const;
+
+ /**
+ * Get an x509_decoder that can be used to decode a stored key into
+ * this key.
+ * @result an x509_decoder for this key
+ */
+ X509_Decoder* x509_decoder();
+
+ /**
+ * Make sure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ virtual ~EC_PublicKey() {}
+ protected:
+ virtual void X509_load_hook();
+
+ SecureVector<byte> m_enc_public_point; // stores the public point
+
+ std::auto_ptr<EC_Domain_Params> mp_dom_pars;
+ std::auto_ptr<PointGFp> mp_public_point;
+ EC_dompar_enc m_param_enc;
+ };
+
+/**
+* This abstract class represents general EC Private Keys
+*/
+class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key
+ {
+ public:
+
+ /**
+ * Get an PKCS#8 encoder that can be used to encoded this key.
+ * @result an PKCS#8 encoder for this key
+ */
+ PKCS8_Encoder* pkcs8_encoder() const;
+
+ /**
+ * Get an PKCS#8 decoder that can be used to decoded a stored key into
+ * this key.
+ * @result an PKCS#8 decoder for this key
+ */
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+
+ /**
+ * Get the private key value of this key object.
+ * @result the private key value of this key object
+ */
+ const BigInt& private_value() const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ virtual ~EC_PrivateKey() {}
+ protected:
+ virtual void PKCS8_load_hook(bool = false);
+ void generate_private_key(RandomNumberGenerator&);
+ BigInt m_private_value;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/ecc_key/info.txt b/botan/src/pubkey/ecc_key/info.txt
new file mode 100644
index 0000000..2a3c9a3
--- /dev/null
+++ b/botan/src/pubkey/ecc_key/info.txt
@@ -0,0 +1,20 @@
+realname "ECC Public Key"
+
+define ECC_PUBLIC_KEY_CRYPTO
+
+load_on auto
+
+<add>
+ecc_key.cpp
+ecc_key.h
+</add>
+
+<requires>
+alloc
+asn1
+bigint
+ec_dompar
+gfpmath
+numbertheory
+pk_codecs
+</requires>
diff --git a/botan/src/pubkey/ecdsa/ecdsa.cpp b/botan/src/pubkey/ecdsa/ecdsa.cpp
new file mode 100644
index 0000000..9640c63
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa.cpp
@@ -0,0 +1,230 @@
+/*
+* ECDSA implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecdsa.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/secmem.h>
+#include <botan/point_gfp.h>
+
+namespace Botan {
+
+ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& dom_pars)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_pars));
+ generate_private_key(rng);
+
+ try
+ {
+ mp_public_point->check_invariants();
+ }
+ catch(Illegal_Point& e)
+ {
+ throw Invalid_State("ECDSA key generation failed");
+ }
+
+ m_ecdsa_core = ECDSA_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+/*
+* ECDSA_PublicKey
+*/
+void ECDSA_PublicKey::affirm_init() const // virtual
+ {
+ EC_PublicKey::affirm_init();
+ }
+
+void ECDSA_PublicKey::set_domain_parameters(const EC_Domain_Params& dom_pars)
+ {
+ if(mp_dom_pars.get())
+ {
+ // they are already set, we must ensure that they are equal to the arg
+ if(dom_pars != *mp_dom_pars.get())
+ throw Invalid_Argument("EC_PublicKey::set_domain_parameters - cannot reset to a new value");
+
+ return;
+ }
+
+ if(m_enc_public_point.size() == 0)
+ throw Invalid_State("EC_PublicKey::set_domain_parameters(): encoded public point isn't set");
+
+ // now try to decode the public key ...
+ PointGFp tmp_pp(OS2ECP(m_enc_public_point, dom_pars.get_curve()));
+ try
+ {
+ tmp_pp.check_invariants();
+ }
+ catch(Illegal_Point e)
+ {
+ throw Invalid_State("EC_PublicKey::set_domain_parameters(): point does not lie on provided curve");
+ }
+
+ std::auto_ptr<EC_Domain_Params> p_tmp_pars(new EC_Domain_Params(dom_pars));
+ ECDSA_Core tmp_ecdsa_core(*p_tmp_pars, BigInt(0), tmp_pp);
+ mp_public_point.reset(new PointGFp(tmp_pp));
+ m_ecdsa_core = tmp_ecdsa_core;
+ mp_dom_pars = p_tmp_pars;
+ }
+
+void ECDSA_PublicKey::set_all_values(const ECDSA_PublicKey& other)
+ {
+ m_param_enc = other.m_param_enc;
+ m_ecdsa_core = other.m_ecdsa_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if(other.mp_dom_pars.get())
+ mp_dom_pars.reset(new EC_Domain_Params(other.domain_parameters()));
+
+ if(other.mp_public_point.get())
+ mp_public_point.reset(new PointGFp(other.public_point()));
+ }
+
+ECDSA_PublicKey::ECDSA_PublicKey(const ECDSA_PublicKey& other)
+ : Public_Key(),
+ EC_PublicKey(),
+ PK_Verifying_wo_MR_Key()
+ {
+ set_all_values(other);
+ }
+
+const ECDSA_PublicKey& ECDSA_PublicKey::operator=(const ECDSA_PublicKey& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+bool ECDSA_PublicKey::verify(const byte message[],
+ u32bit mess_len,
+ const byte signature[],
+ u32bit sig_len) const
+ {
+ affirm_init();
+
+ BigInt r, s;
+
+ BER_Decoder(signature, sig_len)
+ .start_cons(SEQUENCE)
+ .decode(r)
+ .decode(s)
+ .end_cons()
+ .verify_end();
+
+ u32bit enc_len = std::max(r.bytes(), s.bytes());
+
+ SecureVector<byte> sv_plain_sig;
+
+ sv_plain_sig.append(BigInt::encode_1363(r, enc_len));
+ sv_plain_sig.append(BigInt::encode_1363(s, enc_len));
+
+ return m_ecdsa_core.verify(sv_plain_sig, sv_plain_sig.size(),
+ message, mess_len);
+ }
+
+ECDSA_PublicKey::ECDSA_PublicKey(const EC_Domain_Params& dom_par,
+ const PointGFp& public_point)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_par));
+ mp_public_point = std::auto_ptr<PointGFp>(new PointGFp(public_point));
+ m_param_enc = ENC_EXPLICIT;
+ m_ecdsa_core = ECDSA_Core(*mp_dom_pars, BigInt(0), *mp_public_point);
+ }
+
+void ECDSA_PublicKey::X509_load_hook()
+ {
+ EC_PublicKey::X509_load_hook();
+ EC_PublicKey::affirm_init();
+ m_ecdsa_core = ECDSA_Core ( *mp_dom_pars, BigInt ( 0 ), *mp_public_point );
+ }
+
+u32bit ECDSA_PublicKey::max_input_bits() const
+ {
+ if(!mp_dom_pars.get())
+ {
+ throw Invalid_State("ECDSA_PublicKey::max_input_bits(): domain parameters not set");
+ }
+ return mp_dom_pars->get_order().bits();
+ }
+
+/*************************
+* ECDSA_PrivateKey
+*************************/
+void ECDSA_PrivateKey::affirm_init() const // virtual
+ {
+ EC_PrivateKey::affirm_init();
+ }
+
+void ECDSA_PrivateKey::PKCS8_load_hook(bool generated)
+ {
+ EC_PrivateKey::PKCS8_load_hook(generated);
+ EC_PrivateKey::affirm_init();
+ m_ecdsa_core = ECDSA_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+void ECDSA_PrivateKey::set_all_values(const ECDSA_PrivateKey& other)
+ {
+ m_private_value = other.m_private_value;
+ m_param_enc = other.m_param_enc;
+ m_ecdsa_core = other.m_ecdsa_core;
+ m_enc_public_point = other.m_enc_public_point;
+
+ if(other.mp_dom_pars.get())
+ mp_dom_pars.reset(new EC_Domain_Params(other.domain_parameters()));
+
+ if(other.mp_public_point.get())
+ mp_public_point.reset(new PointGFp(other.public_point()));
+ }
+
+ECDSA_PrivateKey::ECDSA_PrivateKey(ECDSA_PrivateKey const& other)
+ : Public_Key(),
+ EC_PublicKey(),
+ Private_Key(),
+ ECDSA_PublicKey(),
+ EC_PrivateKey(),
+ PK_Signing_Key()
+ {
+ set_all_values(other);
+ }
+
+
+const ECDSA_PrivateKey& ECDSA_PrivateKey::operator=(const ECDSA_PrivateKey& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+SecureVector<byte> ECDSA_PrivateKey::sign(const byte message[],
+ u32bit mess_len,
+ RandomNumberGenerator& rng) const
+ {
+ affirm_init();
+
+ SecureVector<byte> sv_sig = m_ecdsa_core.sign(message, mess_len, rng);
+
+ if(sv_sig.size() % 2 != 0)
+ throw Invalid_Argument("Erroneous length of signature");
+
+ u32bit rs_len = sv_sig.size() / 2;
+ SecureVector<byte> sv_r, sv_s;
+ sv_r.set(sv_sig.begin(), rs_len);
+ sv_s.set(&sv_sig[rs_len], rs_len);
+
+ BigInt r = BigInt::decode(sv_r, sv_r.size());
+ BigInt s = BigInt::decode(sv_s, sv_s.size());
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(r)
+ .encode(s)
+ .end_cons()
+ .get_contents();
+ }
+
+}
diff --git a/botan/src/pubkey/ecdsa/ecdsa.h b/botan/src/pubkey/ecdsa/ecdsa.h
new file mode 100644
index 0000000..3794457
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa.h
@@ -0,0 +1,145 @@
+/*
+* ECDSA
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_KEY_H__
+#define BOTAN_ECDSA_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/ecdsa_core.h>
+
+namespace Botan {
+
+/**
+* This class represents ECDSA Public Keys.
+*/
+class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey,
+ public PK_Verifying_wo_MR_Key
+ {
+ public:
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name ("ECDSA")
+ */
+ std::string algo_name() const { return "ECDSA"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @result the maximum number of input bits
+ */
+ u32bit max_input_bits() const;
+
+ /**
+ * Verify a message with this key.
+ * @param message the byte array containing the message
+ * @param mess_len the number of bytes in the message byte array
+ * @param signature the byte array containing the signature
+ * @param sig_len the number of bytes in the signature byte array
+ */
+ bool verify(const byte message[], u32bit mess_len,
+ const byte signature[], u32bit sig_len) const;
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECDSA_PublicKey() {}
+
+ /**
+ * Construct a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECDSA_PublicKey(const EC_Domain_Params& dom_par,
+ const PointGFp& public_point); // sets core
+
+ ECDSA_PublicKey const& operator=(const ECDSA_PublicKey& rhs);
+
+ ECDSA_PublicKey(const ECDSA_PublicKey& other);
+
+ /**
+ * Set the domain parameters of this key. This function has to be
+ * used when a key encoded without domain parameters was decoded into
+ * this key. Otherwise it will not be able to verify a signature.
+ * @param dom_pars the domain_parameters associated with this key
+ * @throw Invalid_Argument if the point was found not to be satisfying the
+ * curve equation of the provided domain parameters
+ * or if this key already has domain parameters set
+ * and these are differing from those given as the parameter
+ */
+ void set_domain_parameters(const EC_Domain_Params& dom_pars);
+
+ /**
+ * Ensure that the public point and domain parameters of this key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values(const ECDSA_PublicKey& other);
+
+ ECDSA_Core m_ecdsa_core;
+ };
+
+/**
+* This class represents ECDSA Private Keys
+*/
+class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
+ public EC_PrivateKey,
+ public PK_Signing_Key
+ {
+ public:
+ //ctors
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECDSA_PrivateKey() {}
+
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECDSA_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& domain);
+
+ ECDSA_PrivateKey(const ECDSA_PrivateKey& other);
+ ECDSA_PrivateKey const& operator=(const ECDSA_PrivateKey& rhs);
+
+ /**
+ * Sign a message with this key.
+ * @param message the byte array representing the message to be signed
+ * @param mess_len the length of the message byte array
+ * @result the signature
+ */
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ virtual void set_all_values(const ECDSA_PrivateKey& other);
+ private:
+ void PKCS8_load_hook(bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/ecdsa/ecdsa_core.cpp b/botan/src/pubkey/ecdsa/ecdsa_core.cpp
new file mode 100644
index 0000000..93808cc
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa_core.cpp
@@ -0,0 +1,55 @@
+/*
+* ECDSA Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecdsa_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* ECDSA Operation
+*/
+bool ECDSA_Core::verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const
+ {
+ //assert(op.get());
+ return op->verify(signature, sig_len, message, mess_len);
+ }
+
+SecureVector<byte> ECDSA_Core::sign(const byte message[],
+ u32bit mess_len,
+ RandomNumberGenerator& rng) const
+ {
+ //assert(op.get());
+ return op->sign(message, mess_len, rng);
+ }
+
+ECDSA_Core& ECDSA_Core::operator=(const ECDSA_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+ECDSA_Core::ECDSA_Core(const ECDSA_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+ECDSA_Core::ECDSA_Core(EC_Domain_Params const& dom_pars, const BigInt& priv_key, PointGFp const& pub_key)
+ {
+ op = Engine_Core::ecdsa_op(dom_pars, priv_key, pub_key);
+ }
+
+}
diff --git a/botan/src/pubkey/ecdsa/ecdsa_core.h b/botan/src/pubkey/ecdsa/ecdsa_core.h
new file mode 100644
index 0000000..ceccc94
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa_core.h
@@ -0,0 +1,47 @@
+/*
+* ECDSA Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_CORE_H__
+#define BOTAN_ECDSA_CORE_H__
+
+#include <botan/ecdsa_op.h>
+#include <botan/blinding.h>
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECDSA Core
+*/
+class BOTAN_DLL ECDSA_Core
+ {
+ public:
+ bool verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const;
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ ECDSA_Core& operator=(const ECDSA_Core&);
+
+ ECDSA_Core() { op = 0; }
+
+ ECDSA_Core(const ECDSA_Core&);
+
+ ECDSA_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+
+ ~ECDSA_Core() { delete op; }
+ private:
+ ECDSA_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/ecdsa/ecdsa_op.cpp b/botan/src/pubkey/ecdsa/ecdsa_op.cpp
new file mode 100644
index 0000000..986043e
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa_op.cpp
@@ -0,0 +1,129 @@
+/*
+* ECDSA Operation
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ecdsa_op.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+bool Default_ECDSA_Op::verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const
+ {
+ if(sig_len % 2 != 0)
+ throw Invalid_Argument("Erroneous length of signature");
+
+ //NOTE: it is not checked whether the public point is set
+ if(m_dom_pars.get_curve().get_p() == 0)
+ throw Internal_Error("domain parameters not set");
+
+ BigInt e(message, mess_len);
+
+ u32bit rs_len = sig_len/2;
+ SecureVector<byte> sv_r;
+ SecureVector<byte> sv_s;
+ sv_r.set(signature, rs_len);
+ sv_s.set(signature+rs_len, rs_len);
+ BigInt r = BigInt::decode ( sv_r, sv_r.size());
+ BigInt s = BigInt::decode (sv_s, sv_s.size());
+
+ if(r < 0 || r >= m_dom_pars.get_order())
+ throw Invalid_Argument("r in ECDSA signature has an illegal value");
+
+ if(s < 0 || s >= m_dom_pars.get_order())
+ throw Invalid_Argument("s in ECDSA signature has an illegal value");
+
+ BigInt w = inverse_mod(s, m_dom_pars.get_order());
+
+ PointGFp R = w*(e*m_dom_pars.get_base_point() + r*m_pub_key);
+ if(R.is_zero())
+ return false;
+
+ BigInt x = R.get_affine_x().get_value();
+ bool result = (x % m_dom_pars.get_order() == r);
+ return result;
+ }
+
+SecureVector<byte> Default_ECDSA_Op::sign(const byte message[],
+ u32bit mess_len,
+ RandomNumberGenerator& rng) const
+ {
+ if(m_priv_key == 0)
+ throw Internal_Error("Default_ECDSA_Op::sign(): no private key");
+
+ if(m_dom_pars.get_curve().get_p() == 0)
+ throw Internal_Error("Default_ECDSA_Op::sign(): domain parameters not set");
+
+ BigInt e(message, mess_len);
+
+ // generate k
+ BigInt k;
+ BigInt r(0);
+ const BigInt n(m_dom_pars.get_order());
+ while(r == 0)
+ {
+ k = BigInt::random_integer(rng, 1, n);
+
+ PointGFp k_times_P(m_dom_pars.get_base_point());
+ k_times_P.mult_this_secure(k, n, n-1);
+ k_times_P.check_invariants();
+ r = k_times_P.get_affine_x().get_value() % n;
+ }
+ BigInt k_inv = inverse_mod(k, n);
+
+ // use randomization against attacks on s:
+ // a = k_inv * (r*(d + x) + e) mod n
+ // b = k_inv * r * x mod n
+ // s = a - b mod n
+ // where x is a random integer
+
+#if defined(CMS_RAND)
+ BigInt x = BigInt::random_integer(0, n);
+ BigInt s = m_priv_key + x; // obscure the secret from the beginning
+ // all following operations thus are randomized
+ s *= r;
+ s += e;
+ s *= k_inv;
+ s %= n;
+
+ BigInt b = x; // again, start with the random number
+ b *= r;
+ b *= k_inv;
+ b %= n;
+ s -= b; // s = a - b
+ if(s <= 0) // s %= n
+ {
+ s += n;
+ }
+#else // CMS_RAND
+ // no countermeasure here
+ BigInt s(r);
+ s *= m_priv_key;
+ s += e;
+ s *= k_inv;
+ s %= n;
+
+#endif // CMS_RAND
+
+ SecureVector<byte> sv_r = BigInt::encode_1363 ( r, m_dom_pars.get_order().bytes() );
+ SecureVector<byte> sv_s = BigInt::encode_1363 ( s, m_dom_pars.get_order().bytes() );
+
+ SecureVector<byte> result(sv_r);
+ result.append(sv_s);
+ return result;
+ }
+
+Default_ECDSA_Op::Default_ECDSA_Op(const EC_Domain_Params& dom_pars, const BigInt& priv_key, const PointGFp& pub_key)
+ : m_dom_pars(dom_pars),
+ m_pub_key(pub_key),
+ m_priv_key(priv_key)
+ {
+
+ }
+
+}
+
diff --git a/botan/src/pubkey/ecdsa/ecdsa_op.h b/botan/src/pubkey/ecdsa/ecdsa_op.h
new file mode 100644
index 0000000..25831a9
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/ecdsa_op.h
@@ -0,0 +1,64 @@
+/*
+* ECDSA Operations
+* (C) 1999-2008 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECDSA_OPERATIONS_H__
+#define BOTAN_ECDSA_OPERATIONS_H__
+
+#include <botan/ec_dompar.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* ECDSA Operation
+*/
+class BOTAN_DLL ECDSA_Operation
+ {
+ public:
+ virtual bool verify(const byte sig[], u32bit sig_len,
+ const byte msg[], u32bit msg_len) const = 0;
+
+ virtual SecureVector<byte> sign(const byte message[],
+ u32bit mess_len,
+ RandomNumberGenerator&) const = 0;
+
+ virtual ECDSA_Operation* clone() const = 0;
+
+ virtual ~ECDSA_Operation() {}
+ };
+
+
+/*
+* Default ECDSA operation
+*/
+class BOTAN_DLL Default_ECDSA_Op : public ECDSA_Operation
+ {
+ public:
+ bool verify(const byte signature[], u32bit sig_len,
+ const byte message[], u32bit mess_len) const;
+
+ SecureVector<byte> sign(const byte message[], u32bit mess_len,
+ RandomNumberGenerator& rng) const;
+
+ ECDSA_Operation* clone() const
+ {
+ return new Default_ECDSA_Op(*this);
+ }
+
+ Default_ECDSA_Op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+ private:
+ EC_Domain_Params m_dom_pars;
+ PointGFp m_pub_key;
+ BigInt m_priv_key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/ecdsa/info.txt b/botan/src/pubkey/ecdsa/info.txt
new file mode 100644
index 0000000..743440f
--- /dev/null
+++ b/botan/src/pubkey/ecdsa/info.txt
@@ -0,0 +1,25 @@
+realname "ECDSA"
+
+define ECDSA
+
+load_on auto
+
+<add>
+ecdsa.cpp
+ecdsa.h
+ecdsa_core.cpp
+ecdsa_core.h
+ecdsa_op.cpp
+ecdsa_op.h
+</add>
+
+<requires>
+alloc
+asn1
+ec_dompar
+ecc_key
+gfpmath
+libstate
+numbertheory
+rng
+</requires>
diff --git a/botan/src/pubkey/eckaeg/eckaeg.cpp b/botan/src/pubkey/eckaeg/eckaeg.cpp
new file mode 100644
index 0000000..b8ff75d
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg.cpp
@@ -0,0 +1,152 @@
+/*
+* ECKAEG implemenation
+* (C) 2007 Manuel Hartl, FlexSecure GmbH
+* 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eckaeg.h>
+#include <botan/numthry.h>
+#include <botan/util.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/secmem.h>
+#include <botan/point_gfp.h>
+
+namespace Botan {
+
+/*********************************
+* ECKAEG_PublicKey
+*********************************/
+
+void ECKAEG_PublicKey::affirm_init() const // virtual
+ {
+ EC_PublicKey::affirm_init();
+ }
+
+void ECKAEG_PublicKey::set_all_values(ECKAEG_PublicKey const& other)
+ {
+ m_param_enc = other.m_param_enc;
+ m_eckaeg_core = other.m_eckaeg_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if(other.mp_dom_pars.get())
+ {
+ mp_dom_pars.reset(new EC_Domain_Params(*(other.mp_dom_pars)));
+ }
+ if(other.mp_public_point.get())
+ {
+ mp_public_point.reset(new PointGFp(*(other.mp_public_point)));
+ }
+ }
+
+ECKAEG_PublicKey::ECKAEG_PublicKey(ECKAEG_PublicKey const& other)
+ : Public_Key(),
+ EC_PublicKey()
+ {
+ set_all_values(other);
+ }
+
+ECKAEG_PublicKey const& ECKAEG_PublicKey::operator=(ECKAEG_PublicKey const& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+void ECKAEG_PublicKey::X509_load_hook()
+ {
+ EC_PublicKey::X509_load_hook();
+ EC_PublicKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, BigInt(0), *mp_public_point);
+ }
+
+ECKAEG_PublicKey::ECKAEG_PublicKey(EC_Domain_Params const& dom_par, PointGFp const& public_point)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_par));
+ mp_public_point = std::auto_ptr<PointGFp>(new PointGFp(public_point));
+ if(mp_public_point->get_curve() != mp_dom_pars->get_curve())
+ {
+ throw Invalid_Argument("ECKAEG_PublicKey(): curve of arg. point and curve of arg. domain parameters are different");
+ }
+ EC_PublicKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, BigInt(0), *mp_public_point);
+ }
+
+/*********************************
+* ECKAEG_PrivateKey
+*********************************/
+void ECKAEG_PrivateKey::affirm_init() const // virtual
+ {
+ EC_PrivateKey::affirm_init();
+ }
+
+void ECKAEG_PrivateKey::PKCS8_load_hook(bool generated)
+ {
+ EC_PrivateKey::PKCS8_load_hook(generated);
+ EC_PrivateKey::affirm_init();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+void ECKAEG_PrivateKey::set_all_values(ECKAEG_PrivateKey const& other)
+ {
+ m_private_value = other.m_private_value;
+ m_param_enc = other.m_param_enc;
+ m_eckaeg_core = other.m_eckaeg_core;
+ m_enc_public_point = other.m_enc_public_point;
+ if(other.mp_dom_pars.get())
+ {
+ mp_dom_pars.reset(new EC_Domain_Params(*(other.mp_dom_pars)));
+ }
+ if(other.mp_public_point.get())
+ {
+ mp_public_point.reset(new PointGFp(*(other.mp_public_point)));
+ }
+ }
+
+ECKAEG_PrivateKey::ECKAEG_PrivateKey(ECKAEG_PrivateKey const& other)
+ : Public_Key(),
+ EC_PublicKey(),
+ Private_Key(),
+ ECKAEG_PublicKey(),
+ EC_PrivateKey(),
+ PK_Key_Agreement_Key()
+ {
+ set_all_values(other);
+ }
+
+ECKAEG_PrivateKey const& ECKAEG_PrivateKey::operator= (ECKAEG_PrivateKey const& rhs)
+ {
+ set_all_values(rhs);
+ return *this;
+ }
+
+MemoryVector<byte> ECKAEG_PrivateKey::public_value() const
+ {
+ return EC2OSP(public_point(), PointGFp::UNCOMPRESSED);
+ }
+
+/**
+* Derive a key
+*/
+SecureVector<byte> ECKAEG_PrivateKey::derive_key(const byte key[],
+ u32bit key_len) const
+ {
+ MemoryVector<byte> key_x(key, key_len); // FIXME: nasty/slow
+ PointGFp point = OS2ECP(key_x, public_point().get_curve());
+
+ return m_eckaeg_core.agree(point);
+ }
+
+/**
+* Derive a key
+*/
+SecureVector<byte> ECKAEG_PrivateKey::derive_key(const ECKAEG_PublicKey& key) const
+ {
+ affirm_init();
+ key.affirm_init();
+
+ return m_eckaeg_core.agree(key.public_point());
+ }
+
+}
diff --git a/botan/src/pubkey/eckaeg/eckaeg.h b/botan/src/pubkey/eckaeg/eckaeg.h
new file mode 100644
index 0000000..31b6574
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg.h
@@ -0,0 +1,137 @@
+/*
+* ECKAEG
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* Manuel Hartl, FlexSecure GmbH
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_KEY_H__
+#define BOTAN_ECKAEG_KEY_H__
+
+#include <botan/ecc_key.h>
+#include <botan/eckaeg_core.h>
+
+namespace Botan {
+
+/**
+* This class represents ECKAEG Public Keys.
+*/
+class BOTAN_DLL ECKAEG_PublicKey : public virtual EC_PublicKey
+ {
+ public:
+
+ /**
+ * Default constructor. Use this one if you want to later fill
+ * this object with data from an encoded key.
+ */
+ ECKAEG_PublicKey() {}
+
+ /**
+ * Construct a public key from a given public point.
+ * @param dom_par the domain parameters associated with this key
+ * @param public_point the public point defining this key
+ */
+ ECKAEG_PublicKey(const EC_Domain_Params& dom_par,
+ const PointGFp& public_point);
+
+ /**
+ * Get this keys algorithm name.
+ * @result this keys algorithm name
+ */
+ std::string algo_name() const { return "ECKAEG"; }
+
+ /**
+ * Get the maximum number of bits allowed to be fed to this key.
+ * This is the bitlength of the order of the base point.
+
+ * @result the maximum number of input bits
+ */
+ u32bit max_input_bits() const
+ {
+ if(!mp_dom_pars.get())
+ throw Invalid_State("ECKAEG_PublicKey::max_input_bits(): domain parameters not set");
+
+ return mp_dom_pars->get_order().bits();
+ }
+
+ ECKAEG_PublicKey(ECKAEG_PublicKey const& other);
+ ECKAEG_PublicKey const& operator= (ECKAEG_PublicKey const& rhs);
+
+ /**
+ * Make sure that the public point and domain parameters of this
+ * key are set.
+ * @throw Invalid_State if either of the two data members is not set
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ void X509_load_hook();
+ virtual void set_all_values(const ECKAEG_PublicKey& other);
+
+ ECKAEG_Core m_eckaeg_core;
+ };
+
+/**
+* This class represents ECKAEG Private Keys.
+*/
+class BOTAN_DLL ECKAEG_PrivateKey : public ECKAEG_PublicKey,
+ public EC_PrivateKey,
+ public PK_Key_Agreement_Key
+ {
+ public:
+
+ /**
+ * Generate a new private key
+ * @param the domain parameters to used for this key
+ */
+ ECKAEG_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Domain_Params& dom_pars)
+ {
+ mp_dom_pars = std::auto_ptr<EC_Domain_Params>(new EC_Domain_Params(dom_pars));
+ generate_private_key(rng);
+ mp_public_point->check_invariants();
+ m_eckaeg_core = ECKAEG_Core(*mp_dom_pars, m_private_value, *mp_public_point);
+ }
+
+ /**
+ * Default constructor. Use this one if you want to later fill this object with data
+ * from an encoded key.
+ */
+ ECKAEG_PrivateKey() {}
+ ECKAEG_PrivateKey(ECKAEG_PrivateKey const& other);
+ ECKAEG_PrivateKey const& operator=(ECKAEG_PrivateKey const& rhs);
+
+ MemoryVector<byte> public_value() const;
+
+ void PKCS8_load_hook(bool = false);
+
+ /**
+ * Derive a shared key with the other partys public key.
+ * @param key the other partys public key
+ * @param key_len the other partys public key
+ */
+ SecureVector<byte> derive_key(const byte key[], u32bit key_len) const;
+
+ /**
+ * Derive a shared key with the other partys public key.
+ * @param other the other partys public key
+ */
+ SecureVector<byte> derive_key(const ECKAEG_PublicKey& other) const;
+
+ /**
+ * Make sure that the public key parts of this object are set
+ * (calls EC_PublicKey::affirm_init()) as well as the private key
+ * value.
+ * @throw Invalid_State if the above conditions are not satisfied
+ */
+ virtual void affirm_init() const;
+
+ protected:
+ virtual void set_all_values(const ECKAEG_PrivateKey& other);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/eckaeg/eckaeg_core.cpp b/botan/src/pubkey/eckaeg/eckaeg_core.cpp
new file mode 100644
index 0000000..dc89a87
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg_core.cpp
@@ -0,0 +1,59 @@
+/*
+* ECKAEG Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eckaeg_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* ECKAEG_Core Constructor
+*/
+ECKAEG_Core::ECKAEG_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ op = Engine_Core::eckaeg_op(dom_pars, priv_key, pub_key);
+ }
+
+/*
+* ECKAEG_Core Copy Constructor
+*/
+ECKAEG_Core::ECKAEG_Core(const ECKAEG_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*
+* ECKAEG_Core Assignment Operator
+*/
+ECKAEG_Core& ECKAEG_Core::operator=(const ECKAEG_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*
+* ECKAEG Operation
+*/
+SecureVector<byte> ECKAEG_Core::agree(const PointGFp& otherKey) const
+ {
+ //assert(op.get());
+ return op->agree(otherKey);
+ }
+
+}
diff --git a/botan/src/pubkey/eckaeg/eckaeg_core.h b/botan/src/pubkey/eckaeg/eckaeg_core.h
new file mode 100644
index 0000000..d632c94
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg_core.h
@@ -0,0 +1,44 @@
+/*
+* ECKAEG Core
+* (C) 1999-2007 Jack Lloyd
+* (C) 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_CORE_H__
+#define BOTAN_ECKAEG_CORE_H__
+
+#include <botan/eckaeg_op.h>
+#include <botan/blinding.h>
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECKAEG Core
+*/
+class BOTAN_DLL ECKAEG_Core
+ {
+ public:
+ SecureVector<byte> agree(const PointGFp&) const;
+
+ ECKAEG_Core& operator=(const ECKAEG_Core&);
+
+ ECKAEG_Core() { op = 0; }
+
+ ECKAEG_Core(const ECKAEG_Core&);
+
+ ECKAEG_Core(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ PointGFp const& pub_key);
+
+ ~ECKAEG_Core() { delete op; }
+ private:
+ ECKAEG_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/eckaeg/eckaeg_op.cpp b/botan/src/pubkey/eckaeg/eckaeg_op.cpp
new file mode 100644
index 0000000..0cb5c3d
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg_op.cpp
@@ -0,0 +1,36 @@
+/*
+* ECKAEG Operation
+* (C) 2007 FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/eckaeg_op.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+Default_ECKAEG_Op::Default_ECKAEG_Op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ : m_dom_pars(dom_pars),
+ m_pub_key(pub_key),
+ m_priv_key(priv_key)
+ {
+ }
+
+SecureVector<byte> Default_ECKAEG_Op::agree(const PointGFp& i) const
+ {
+ BigInt cofactor(m_dom_pars.get_cofactor());
+ BigInt n = m_dom_pars.get_order();
+ BigInt l(inverse_mod(cofactor,n)); // l=h^-1 mod n
+ PointGFp Q(cofactor*i); // q = h*Pb
+ PointGFp S(Q);
+ BigInt group_order = m_dom_pars.get_cofactor() * n;
+ S.mult_this_secure((m_priv_key*l)%n, group_order, n-1);
+ S.check_invariants();
+ return FE2OSP(S.get_affine_x()); // fe2os(xs)
+ }
+
+}
diff --git a/botan/src/pubkey/eckaeg/eckaeg_op.h b/botan/src/pubkey/eckaeg/eckaeg_op.h
new file mode 100644
index 0000000..27cf4f3
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/eckaeg_op.h
@@ -0,0 +1,49 @@
+/*
+* ECKAEG Operations
+* (C) 1999-2008 Jack Lloyd
+* 2007 FlexSecure GmbH
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ECKAEG_OPERATIONS_H__
+#define BOTAN_ECKAEG_OPERATIONS_H__
+
+#include <botan/ec_dompar.h>
+
+namespace Botan {
+
+/*
+* ECKAEG Operation
+*/
+class BOTAN_DLL ECKAEG_Operation
+ {
+ public:
+ virtual SecureVector<byte> agree(const PointGFp&) const = 0;
+ virtual ECKAEG_Operation* clone() const = 0;
+ virtual ~ECKAEG_Operation() {}
+ };
+
+/*
+* Default ECKAEG operation
+*/
+class BOTAN_DLL Default_ECKAEG_Op : public ECKAEG_Operation
+ {
+ public:
+ SecureVector<byte> agree(const PointGFp& i) const;
+
+ ECKAEG_Operation* clone() const { return new Default_ECKAEG_Op(*this); }
+
+ Default_ECKAEG_Op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+ private:
+ EC_Domain_Params m_dom_pars;
+ PointGFp m_pub_key;
+ BigInt m_priv_key;
+ };
+
+
+}
+
+#endif
diff --git a/botan/src/pubkey/eckaeg/info.txt b/botan/src/pubkey/eckaeg/info.txt
new file mode 100644
index 0000000..6b78f7d
--- /dev/null
+++ b/botan/src/pubkey/eckaeg/info.txt
@@ -0,0 +1,24 @@
+realname "ECKAEG"
+
+define ECKAEG
+
+load_on auto
+
+<add>
+eckaeg.cpp
+eckaeg.h
+eckaeg_core.cpp
+eckaeg_core.h
+eckaeg_op.cpp
+eckaeg_op.h
+</add>
+
+<requires>
+alloc
+asn1
+ec_dompar
+ecc_key
+gfpmath
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/elgamal/elg_core.cpp b/botan/src/pubkey/elgamal/elg_core.cpp
new file mode 100644
index 0000000..8b8c8f5
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elg_core.cpp
@@ -0,0 +1,97 @@
+/*
+* ElGamal Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/elg_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS;
+
+}
+
+/*
+* ELG_Core Constructor
+*/
+ELG_Core::ELG_Core(const DL_Group& group, const BigInt& y)
+ {
+ op = Engine_Core::elg_op(group, y, 0);
+ p_bytes = 0;
+ }
+
+/*
+* ELG_Core Constructor
+*/
+ELG_Core::ELG_Core(RandomNumberGenerator& rng,
+ const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::elg_op(group, y, x);
+
+ const BigInt& p = group.get_p();
+ p_bytes = p.bytes();
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS));
+ blinder = Blinder(k, power_mod(k, x, p), p);
+ }
+ }
+
+/*
+* ELG_Core Copy Constructor
+*/
+ELG_Core::ELG_Core(const ELG_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ }
+
+/*
+* ELG_Core Assignment Operator
+*/
+ELG_Core& ELG_Core::operator=(const ELG_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ p_bytes = core.p_bytes;
+ return (*this);
+ }
+
+/*
+* ElGamal Encrypt Operation
+*/
+SecureVector<byte> ELG_Core::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->encrypt(in, length, k);
+ }
+
+/*
+* ElGamal Decrypt Operation
+*/
+SecureVector<byte> ELG_Core::decrypt(const byte in[], u32bit length) const
+ {
+ if(length != 2*p_bytes)
+ throw Invalid_Argument("ELG_Core::decrypt: Invalid message");
+
+ BigInt a(in, p_bytes);
+ BigInt b(in + p_bytes, p_bytes);
+
+ return BigInt::encode(blinder.unblind(op->decrypt(blinder.blind(a), b)));
+ }
+
+}
diff --git a/botan/src/pubkey/elgamal/elg_core.h b/botan/src/pubkey/elgamal/elg_core.h
new file mode 100644
index 0000000..a7768a6
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elg_core.h
@@ -0,0 +1,44 @@
+/*
+* ElGamal Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_CORE_H__
+#define BOTAN_ELGAMAL_CORE_H__
+
+#include <botan/elg_op.h>
+#include <botan/blinding.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* ElGamal Core
+*/
+class BOTAN_DLL ELG_Core
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ ELG_Core& operator=(const ELG_Core&);
+
+ ELG_Core() { op = 0; }
+ ELG_Core(const ELG_Core&);
+
+ ELG_Core(const DL_Group&, const BigInt&);
+ ELG_Core(RandomNumberGenerator&, const DL_Group&,
+ const BigInt&, const BigInt&);
+
+ ~ELG_Core() { delete op; }
+ private:
+ ELG_Operation* op;
+ Blinder blinder;
+ u32bit p_bytes;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/elgamal/elg_op.cpp b/botan/src/pubkey/elgamal/elg_op.cpp
new file mode 100644
index 0000000..1e476ab
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elg_op.cpp
@@ -0,0 +1,56 @@
+/*
+* ElGamal Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/elg_op.h>
+
+namespace Botan {
+
+/*
+* Default_ELG_Op Constructor
+*/
+Default_ELG_Op::Default_ELG_Op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) : p(group.get_p())
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), p);
+ powermod_y_p = Fixed_Base_Power_Mod(y, p);
+ mod_p = Modular_Reducer(p);
+
+ if(x != 0)
+ powermod_x_p = Fixed_Exponent_Power_Mod(x, p);
+ }
+
+/*
+* Default ElGamal Encrypt Operation
+*/
+SecureVector<byte> Default_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ BigInt m(in, length);
+ if(m >= p)
+ throw Invalid_Argument("Default_ELG_Op::encrypt: Input is too large");
+
+ BigInt a = powermod_g_p(k);
+ BigInt b = mod_p.multiply(m, powermod_y_p(k));
+
+ SecureVector<byte> output(2*p.bytes());
+ a.binary_encode(output + (p.bytes() - a.bytes()));
+ b.binary_encode(output + output.size() / 2 + (p.bytes() - b.bytes()));
+ return output;
+ }
+
+/*
+* Default ElGamal Decrypt Operation
+*/
+BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const
+ {
+ if(a >= p || b >= p)
+ throw Invalid_Argument("Default_ELG_Op: Invalid message");
+
+ return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p));
+ }
+
+}
diff --git a/botan/src/pubkey/elgamal/elg_op.h b/botan/src/pubkey/elgamal/elg_op.h
new file mode 100644
index 0000000..39ed897
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elg_op.h
@@ -0,0 +1,52 @@
+/*
+* ElGamal Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_OPS_H__
+#define BOTAN_ELGAMAL_OPS_H__
+
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* ElGamal Operation
+*/
+class BOTAN_DLL ELG_Operation
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0;
+ virtual ELG_Operation* clone() const = 0;
+ virtual ~ELG_Operation() {}
+ };
+
+/*
+* Botan's Default ElGamal Operation
+*/
+class BOTAN_DLL Default_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new Default_ELG_Op(*this); }
+
+ Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt p;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Fixed_Exponent_Power_Mod powermod_x_p;
+ Modular_Reducer mod_p;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/elgamal/elgamal.cpp b/botan/src/pubkey/elgamal/elgamal.cpp
new file mode 100644
index 0000000..1f79df5
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elgamal.cpp
@@ -0,0 +1,124 @@
+/*
+* ElGamal
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/elgamal.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+#include <botan/util.h>
+
+namespace Botan {
+
+/*
+* ElGamal_PublicKey Constructor
+*/
+ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*
+* Algorithm Specific X.509 Initialization Code
+*/
+void ElGamal_PublicKey::X509_load_hook()
+ {
+ core = ELG_Core(group, y);
+ }
+
+/*
+* ElGamal Encryption Function
+*/
+SecureVector<byte>
+ElGamal_PublicKey::encrypt(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ BigInt k(rng, 2 * dl_work_factor(group_p().bits()));
+ return core.encrypt(in, length, k);
+ }
+
+/*
+* Return the maximum input size in bits
+*/
+u32bit ElGamal_PublicKey::max_input_bits() const
+ {
+ return (group_p().bits() - 1);
+ }
+
+/*
+* ElGamal_PrivateKey Constructor
+*/
+ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ {
+ x.randomize(rng, 2 * dl_work_factor(group_p().bits()));
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*
+* Algorithm Specific PKCS #8 Initialization Code
+*/
+void ElGamal_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = ELG_Core(rng, group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* ElGamal Decryption Function
+*/
+SecureVector<byte> ElGamal_PrivateKey::decrypt(const byte in[],
+ u32bit length) const
+ {
+ return core.decrypt(in, length);
+ }
+
+/*
+* Check Private ElGamal Parameters
+*/
+bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_encryptor(*this, "EME1(SHA-1)"),
+ get_pk_decryptor(*this, "EME1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/elgamal/elgamal.h b/botan/src/pubkey/elgamal/elgamal.h
new file mode 100644
index 0000000..93e640f
--- /dev/null
+++ b/botan/src/pubkey/elgamal/elgamal.h
@@ -0,0 +1,59 @@
+/*
+* ElGamal
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ELGAMAL_H__
+#define BOTAN_ELGAMAL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/elg_core.h>
+
+namespace Botan {
+
+/*
+* ElGamal Public Key
+*/
+class BOTAN_DLL ElGamal_PublicKey : public PK_Encrypting_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "ElGamal"; }
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+ u32bit max_input_bits() const;
+
+ ElGamal_PublicKey() {}
+ ElGamal_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ ELG_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* ElGamal Private Key
+*/
+class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey,
+ public PK_Decrypting_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ ElGamal_PrivateKey() {}
+ ElGamal_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/elgamal/info.txt b/botan/src/pubkey/elgamal/info.txt
new file mode 100644
index 0000000..d7ae614
--- /dev/null
+++ b/botan/src/pubkey/elgamal/info.txt
@@ -0,0 +1,22 @@
+realname "ElGamal"
+
+define ELGAMAL
+
+load_on auto
+
+<add>
+elgamal.cpp
+elgamal.h
+elg_core.cpp
+elg_core.h
+elg_op.cpp
+elg_op.h
+</add>
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/if_algo/if_algo.cpp b/botan/src/pubkey/if_algo/if_algo.cpp
new file mode 100644
index 0000000..556c86f
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_algo.cpp
@@ -0,0 +1,215 @@
+/*
+* IF Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/if_algo.h>
+#include <botan/numthry.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/*
+* Return the X.509 public key encoder
+*/
+X509_Encoder* IF_Scheme_PublicKey::x509_encoder() const
+ {
+ class IF_Scheme_Encoder : public X509_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ return AlgorithmIdentifier(key->get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(key->n)
+ .encode(key->e)
+ .end_cons()
+ .get_contents();
+ }
+
+ IF_Scheme_Encoder(const IF_Scheme_PublicKey* k) : key(k) {}
+ private:
+ const IF_Scheme_PublicKey* key;
+ };
+
+ return new IF_Scheme_Encoder(this);
+ }
+
+/*
+* Return the X.509 public key decoder
+*/
+X509_Decoder* IF_Scheme_PublicKey::x509_decoder()
+ {
+ class IF_Scheme_Decoder : public X509_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier&) {}
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(key->n)
+ .decode(key->e)
+ .verify_end()
+ .end_cons();
+
+ key->X509_load_hook();
+ }
+
+ IF_Scheme_Decoder(IF_Scheme_PublicKey* k) : key(k) {}
+ private:
+ IF_Scheme_PublicKey* key;
+ };
+
+ return new IF_Scheme_Decoder(this);
+ }
+
+/*
+* Return the PKCS #8 public key encoder
+*/
+PKCS8_Encoder* IF_Scheme_PrivateKey::pkcs8_encoder() const
+ {
+ class IF_Scheme_Encoder : public PKCS8_Encoder
+ {
+ public:
+ AlgorithmIdentifier alg_id() const
+ {
+ return AlgorithmIdentifier(key->get_oid(),
+ AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+ MemoryVector<byte> key_bits() const
+ {
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(static_cast<u32bit>(0))
+ .encode(key->n)
+ .encode(key->e)
+ .encode(key->d)
+ .encode(key->p)
+ .encode(key->q)
+ .encode(key->d1)
+ .encode(key->d2)
+ .encode(key->c)
+ .end_cons()
+ .get_contents();
+ }
+
+ IF_Scheme_Encoder(const IF_Scheme_PrivateKey* k) : key(k) {}
+ private:
+ const IF_Scheme_PrivateKey* key;
+ };
+
+ return new IF_Scheme_Encoder(this);
+ }
+
+/*
+* Return the PKCS #8 public key decoder
+*/
+PKCS8_Decoder* IF_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng)
+ {
+ class IF_Scheme_Decoder : public PKCS8_Decoder
+ {
+ public:
+ void alg_id(const AlgorithmIdentifier&) {}
+
+ void key_bits(const MemoryRegion<byte>& bits)
+ {
+ u32bit version;
+
+ BER_Decoder(bits)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(key->n)
+ .decode(key->e)
+ .decode(key->d)
+ .decode(key->p)
+ .decode(key->q)
+ .decode(key->d1)
+ .decode(key->d2)
+ .decode(key->c)
+ .end_cons();
+
+ if(version != 0)
+ throw Decoding_Error("Unknown PKCS #1 key format version");
+
+ key->PKCS8_load_hook(rng);
+ }
+
+ IF_Scheme_Decoder(IF_Scheme_PrivateKey* k, RandomNumberGenerator& r) :
+ key(k), rng(r) {}
+ private:
+ IF_Scheme_PrivateKey* key;
+ RandomNumberGenerator& rng;
+ };
+
+ return new IF_Scheme_Decoder(this, rng);
+ }
+
+/*
+* Algorithm Specific X.509 Initialization Code
+*/
+void IF_Scheme_PublicKey::X509_load_hook()
+ {
+ core = IF_Core(e, n);
+ }
+
+/*
+* Algorithm Specific PKCS #8 Initialization Code
+*/
+void IF_Scheme_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(n == 0) n = p * q;
+ if(d1 == 0) d1 = d % (p - 1);
+ if(d2 == 0) d2 = d % (q - 1);
+ if(c == 0) c = inverse_mod(q, p);
+
+ core = IF_Core(rng, e, n, d, p, q, d1, d2, c);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* Check IF Scheme Public Parameters
+*/
+bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const
+ {
+ if(n < 35 || n.is_even() || e < 2)
+ return false;
+ return true;
+ }
+
+/*
+* Check IF Scheme Private Parameters
+*/
+bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng,
+ bool strong) const
+ {
+ if(n < 35 || n.is_even() || e < 2 || d < 2 || p < 3 || q < 3 || p*q != n)
+ return false;
+
+ if(!strong)
+ return true;
+
+ if(d1 != d % (p - 1) || d2 != d % (q - 1) || c != inverse_mod(q, p))
+ return false;
+ if(!check_prime(p, rng) || !check_prime(q, rng))
+ return false;
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/if_algo/if_algo.h b/botan/src/pubkey/if_algo/if_algo.h
new file mode 100644
index 0000000..32a29be
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_algo.h
@@ -0,0 +1,85 @@
+/*
+* IF Scheme
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_ALGO_H__
+#define BOTAN_IF_ALGO_H__
+
+#include <botan/if_core.h>
+#include <botan/x509_key.h>
+#include <botan/pkcs8.h>
+
+namespace Botan {
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get n = p * q.
+ * @return n
+ */
+ const BigInt& get_n() const { return n; }
+
+ /**
+ * Get the public exponent used by the key.
+ * @return the public exponent
+ */
+ const BigInt& get_e() const { return e; }
+
+ u32bit max_input_bits() const { return (n.bits() - 1); }
+
+ X509_Encoder* x509_encoder() const;
+ X509_Decoder* x509_decoder();
+ protected:
+ virtual void X509_load_hook();
+ BigInt n, e;
+ IF_Core core;
+ };
+
+/**
+* This class represents public keys
+* of integer factorization based (IF) public key schemes.
+*/
+class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey,
+ public virtual Private_Key
+ {
+ public:
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Get the first prime p.
+ * @return the prime p
+ */
+ const BigInt& get_p() const { return p; }
+
+ /**
+ * Get the second prime q.
+ * @return the prime q
+ */
+ const BigInt& get_q() const { return q; }
+
+ /**
+ * Get d with exp * d = 1 mod (p - 1, q - 1).
+ * @return d
+ */
+ const BigInt& get_d() const { return d; }
+
+ PKCS8_Encoder* pkcs8_encoder() const;
+ PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&);
+ protected:
+ virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ BigInt d, p, q, d1, d2, c;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/if_algo/if_core.cpp b/botan/src/pubkey/if_algo/if_core.cpp
new file mode 100644
index 0000000..8cc6a81
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_core.cpp
@@ -0,0 +1,87 @@
+/*
+* IF Algorithm Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/if_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS;
+
+}
+
+/*
+* IF_Core Constructor
+*/
+IF_Core::IF_Core(const BigInt& e, const BigInt& n)
+ {
+ op = Engine_Core::if_op(e, n, 0, 0, 0, 0, 0, 0);
+ }
+
+
+/*
+* IF_Core Constructor
+*/
+IF_Core::IF_Core(RandomNumberGenerator& rng,
+ const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2, const BigInt& c)
+ {
+ op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c);
+
+ if(BLINDING_BITS)
+ {
+ BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS));
+ blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n);
+ }
+ }
+
+/*
+* IF_Core Copy Constructor
+*/
+IF_Core::IF_Core(const IF_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ }
+
+/*
+* IF_Core Assignment Operator
+*/
+IF_Core& IF_Core::operator=(const IF_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ blinder = core.blinder;
+ return (*this);
+ }
+
+/*
+* IF Public Operation
+*/
+BigInt IF_Core::public_op(const BigInt& i) const
+ {
+ return op->public_op(i);
+ }
+
+/*
+* IF Private Operation
+*/
+BigInt IF_Core::private_op(const BigInt& i) const
+ {
+ return blinder.unblind(op->private_op(blinder.blind(i)));
+ }
+
+}
diff --git a/botan/src/pubkey/if_algo/if_core.h b/botan/src/pubkey/if_algo/if_core.h
new file mode 100644
index 0000000..b7f4877
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_core.h
@@ -0,0 +1,45 @@
+/*
+* IF Algorithm Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_CORE_H__
+#define BOTAN_IF_CORE_H__
+
+#include <botan/if_op.h>
+#include <botan/blinding.h>
+
+namespace Botan {
+
+/*
+* IF Core
+*/
+class BOTAN_DLL IF_Core
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Core& operator=(const IF_Core&);
+
+ IF_Core() { op = 0; }
+ IF_Core(const IF_Core&);
+
+ IF_Core(const BigInt&, const BigInt&);
+
+ IF_Core(RandomNumberGenerator& rng,
+ const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&);
+
+ ~IF_Core() { delete op; }
+ private:
+ IF_Operation* op;
+ Blinder blinder;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/if_algo/if_op.cpp b/botan/src/pubkey/if_algo/if_op.cpp
new file mode 100644
index 0000000..27aef45
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_op.cpp
@@ -0,0 +1,47 @@
+/*
+* IF (RSA/RW) Operation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/if_op.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+/*
+* Default_IF_Op Constructor
+*/
+Default_IF_Op::Default_IF_Op(const BigInt& e, const BigInt& n, const BigInt&,
+ const BigInt& p, const BigInt& q,
+ const BigInt& d1, const BigInt& d2,
+ const BigInt& c)
+ {
+ powermod_e_n = Fixed_Exponent_Power_Mod(e, n);
+
+ if(d1 != 0 && d2 != 0 && p != 0 && q != 0)
+ {
+ powermod_d1_p = Fixed_Exponent_Power_Mod(d1, p);
+ powermod_d2_q = Fixed_Exponent_Power_Mod(d2, q);
+ reducer = Modular_Reducer(p);
+ this->c = c;
+ this->q = q;
+ }
+ }
+
+/*
+* Default IF Private Operation
+*/
+BigInt Default_IF_Op::private_op(const BigInt& i) const
+ {
+ if(q == 0)
+ throw Internal_Error("Default_IF_Op::private_op: No private key");
+
+ BigInt j1 = powermod_d1_p(i);
+ BigInt j2 = powermod_d2_q(i);
+ j1 = reducer.reduce(sub_mul(j1, j2, c));
+ return mul_add(j1, q, j2);
+ }
+
+}
diff --git a/botan/src/pubkey/if_algo/if_op.h b/botan/src/pubkey/if_algo/if_op.h
new file mode 100644
index 0000000..516902f
--- /dev/null
+++ b/botan/src/pubkey/if_algo/if_op.h
@@ -0,0 +1,52 @@
+/*
+* IF Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IF_OP_H__
+#define BOTAN_IF_OP_H__
+
+#include <botan/bigint.h>
+#include <botan/pow_mod.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/*
+* IF Operation
+*/
+class BOTAN_DLL IF_Operation
+ {
+ public:
+ virtual BigInt public_op(const BigInt&) const = 0;
+ virtual BigInt private_op(const BigInt&) const = 0;
+ virtual IF_Operation* clone() const = 0;
+ virtual ~IF_Operation() {}
+ };
+
+/*
+* Default IF Operation
+*/
+class BOTAN_DLL Default_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt& i) const
+ { return powermod_e_n(i); }
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new Default_IF_Op(*this); }
+
+ Default_IF_Op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+ private:
+ Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q;
+ Modular_Reducer reducer;
+ BigInt c, q;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/if_algo/info.txt b/botan/src/pubkey/if_algo/info.txt
new file mode 100644
index 0000000..d2142f4
--- /dev/null
+++ b/botan/src/pubkey/if_algo/info.txt
@@ -0,0 +1,22 @@
+realname "Integer Factorization Algorithms"
+
+define IF_PUBLIC_KEY_FAMILY
+
+load_on dep
+
+<add>
+if_algo.cpp
+if_algo.h
+if_core.cpp
+if_core.h
+if_op.cpp
+if_op.h
+</add>
+
+<requires>
+asn1
+bigint
+libstate
+numbertheory
+pk_codecs
+</requires>
diff --git a/botan/src/pubkey/info.txt b/botan/src/pubkey/info.txt
new file mode 100644
index 0000000..ee8da5b
--- /dev/null
+++ b/botan/src/pubkey/info.txt
@@ -0,0 +1,30 @@
+realname "Public Key Base"
+
+define PUBLIC_KEY_CRYPTO
+
+load_on auto
+
+<add>
+pk_algs.cpp
+pk_algs.h
+pk_filts.cpp
+pk_filts.h
+pk_keys.cpp
+pk_keys.h
+pubkey.cpp
+pubkey.h
+pubkey_enums.cpp
+pubkey_enums.h
+</add>
+
+<requires>
+alloc
+asn1
+bigint
+filters
+kdf
+oid_lookup
+pk_pad
+rng
+sym_algo
+</requires>
diff --git a/botan/src/pubkey/keypair/info.txt b/botan/src/pubkey/keypair/info.txt
new file mode 100644
index 0000000..9e75864
--- /dev/null
+++ b/botan/src/pubkey/keypair/info.txt
@@ -0,0 +1,14 @@
+realname "Keypair Testing"
+
+define KEYPAIR_TESTING
+
+load_on auto
+
+<add>
+keypair.cpp
+keypair.h
+</add>
+
+<requires>
+libstate
+</requires>
diff --git a/botan/src/pubkey/keypair/keypair.cpp b/botan/src/pubkey/keypair/keypair.cpp
new file mode 100644
index 0000000..486577f
--- /dev/null
+++ b/botan/src/pubkey/keypair/keypair.cpp
@@ -0,0 +1,73 @@
+/*
+* Keypair Checks
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+#include <memory>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/*
+* Check an encryption key pair for consistency
+*/
+void check_key(RandomNumberGenerator& rng,
+ PK_Encryptor* encryptor, PK_Decryptor* decryptor)
+ {
+ if(encryptor->maximum_input_size() == 0)
+ return;
+
+ std::auto_ptr<PK_Encryptor> enc(encryptor);
+ std::auto_ptr<PK_Decryptor> dec(decryptor);
+
+ SecureVector<byte> message(enc->maximum_input_size() - 1);
+ rng.randomize(message, message.size());
+
+ SecureVector<byte> ciphertext = enc->encrypt(message, rng);
+ if(ciphertext == message)
+ throw Self_Test_Failure("Encryption key pair consistency failure");
+
+ SecureVector<byte> message2 = dec->decrypt(ciphertext);
+ if(message != message2)
+ throw Self_Test_Failure("Encryption key pair consistency failure");
+ }
+
+/*
+* Check a signature key pair for consistency
+*/
+void check_key(RandomNumberGenerator& rng,
+ PK_Signer* signer, PK_Verifier* verifier)
+ {
+ std::auto_ptr<PK_Signer> sig(signer);
+ std::auto_ptr<PK_Verifier> ver(verifier);
+
+ SecureVector<byte> message(16);
+ rng.randomize(message, message.size());
+
+ SecureVector<byte> signature;
+
+ try
+ {
+ signature = sig->sign_message(message, rng);
+ }
+ catch(Encoding_Error)
+ {
+ return;
+ }
+
+ if(!ver->verify_message(message, signature))
+ throw Self_Test_Failure("Signature key pair consistency failure");
+
+ ++message[0];
+ if(ver->verify_message(message, signature))
+ throw Self_Test_Failure("Signature key pair consistency failure");
+ }
+
+}
+
+}
diff --git a/botan/src/pubkey/keypair/keypair.h b/botan/src/pubkey/keypair/keypair.h
new file mode 100644
index 0000000..b1d5c2d
--- /dev/null
+++ b/botan/src/pubkey/keypair/keypair.h
@@ -0,0 +1,47 @@
+/*
+* Keypair Checks
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_KEYPAIR_H__
+#define BOTAN_KEYPAIR_H__
+
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+namespace KeyPair {
+
+/**
+* Tests whether the specified encryptor and decryptor are related to each other,
+* i.e. whether encrypting with the encryptor and consecutive decryption leads to
+* the original plaintext.
+* @param rng the rng to use
+* @param enc the encryptor to test
+* @param dec the decryptor to test
+* @throw Self_Test_Failure if the arguments are not related to each other
+*/
+BOTAN_DLL void check_key(RandomNumberGenerator& rng,
+ PK_Encryptor* enc,
+ PK_Decryptor* dec);
+
+/**
+* Tests whether the specified signer and verifier are related to each other,
+* i.e. whether a signature created with the signer and can be
+* successfully verified with the verifier.
+* @param rng the rng to use
+* @param sig the signer to test
+* @param ver the verifier to test
+* @throw Self_Test_Failure if the arguments are not related to each other
+*/
+BOTAN_DLL void check_key(RandomNumberGenerator& rng,
+ PK_Signer* sig,
+ PK_Verifier* ver);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/pubkey/nr/info.txt b/botan/src/pubkey/nr/info.txt
new file mode 100644
index 0000000..c89820a
--- /dev/null
+++ b/botan/src/pubkey/nr/info.txt
@@ -0,0 +1,22 @@
+realname "Nyberg-Rueppel"
+
+define NYBERG_RUEPPEL
+
+load_on auto
+
+<add>
+nr.cpp
+nr.h
+nr_core.cpp
+nr_core.h
+nr_op.cpp
+nr_op.h
+</add>
+
+<requires>
+dl_algo
+dl_group
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/nr/nr.cpp b/botan/src/pubkey/nr/nr.cpp
new file mode 100644
index 0000000..ad4ae78
--- /dev/null
+++ b/botan/src/pubkey/nr/nr.cpp
@@ -0,0 +1,134 @@
+/*
+* Nyberg-Rueppel
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/nr.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+
+namespace Botan {
+
+/*
+* NR_PublicKey Constructor
+*/
+NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1)
+ {
+ group = grp;
+ y = y1;
+ X509_load_hook();
+ }
+
+/*
+* Algorithm Specific X.509 Initialization Code
+*/
+void NR_PublicKey::X509_load_hook()
+ {
+ core = NR_Core(group, y);
+ }
+
+/*
+* Nyberg-Rueppel Verification Function
+*/
+SecureVector<byte> NR_PublicKey::verify(const byte sig[], u32bit sig_len) const
+ {
+ return core.verify(sig, sig_len);
+ }
+
+/*
+* Return the maximum input size in bits
+*/
+u32bit NR_PublicKey::max_input_bits() const
+ {
+ return (group_q().bits() - 1);
+ }
+
+/*
+* Return the size of each portion of the sig
+*/
+u32bit NR_PublicKey::message_part_size() const
+ {
+ return group_q().bytes();
+ }
+
+/*
+* Create a NR private key
+*/
+NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng,
+ const DL_Group& grp,
+ const BigInt& x_arg)
+ {
+ group = grp;
+ x = x_arg;
+
+ if(x == 0)
+ {
+ x = BigInt::random_integer(rng, 2, group_q() - 1);
+ PKCS8_load_hook(rng, true);
+ }
+ else
+ PKCS8_load_hook(rng, false);
+ }
+
+/*
+* Algorithm Specific PKCS #8 Initialization Code
+*/
+void NR_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng,
+ bool generated)
+ {
+ if(y == 0)
+ y = power_mod(group_g(), x, group_p());
+ core = NR_Core(group, y, x);
+
+ if(generated)
+ gen_check(rng);
+ else
+ load_check(rng);
+ }
+
+/*
+* Nyberg-Rueppel Signature Operation
+*/
+SecureVector<byte> NR_PrivateKey::sign(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ const BigInt& q = group_q();
+
+ BigInt k;
+ do
+ k.randomize(rng, q.bits());
+ while(k >= q);
+
+ return core.sign(in, length, k);
+ }
+
+/*
+* Check Private Nyberg-Rueppel Parameters
+*/
+bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!DL_Scheme_PrivateKey::check_key(rng, strong) || x >= group_q())
+ return false;
+
+ if(!strong)
+ return true;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA1(SHA-1)"),
+ get_pk_verifier(*this, "EMSA1(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/nr/nr.h b/botan/src/pubkey/nr/nr.h
new file mode 100644
index 0000000..144c5ec
--- /dev/null
+++ b/botan/src/pubkey/nr/nr.h
@@ -0,0 +1,63 @@
+/*
+* Nyberg-Rueppel
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NYBERG_RUEPPEL_H__
+#define BOTAN_NYBERG_RUEPPEL_H__
+
+#include <botan/dl_algo.h>
+#include <botan/nr_core.h>
+
+namespace Botan {
+
+/*
+* Nyberg-Rueppel Public Key
+*/
+class BOTAN_DLL NR_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual DL_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "NR"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ u32bit max_input_bits() const;
+
+ DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; }
+ u32bit message_parts() const { return 2; }
+ u32bit message_part_size() const;
+
+ NR_PublicKey() {}
+ NR_PublicKey(const DL_Group&, const BigInt&);
+ protected:
+ NR_Core core;
+ private:
+ void X509_load_hook();
+ };
+
+/*
+* Nyberg-Rueppel Private Key
+*/
+class BOTAN_DLL NR_PrivateKey : public NR_PublicKey,
+ public PK_Signing_Key,
+ public virtual DL_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ NR_PrivateKey() {}
+
+ NR_PrivateKey(RandomNumberGenerator&, const DL_Group&,
+ const BigInt& = 0);
+ private:
+ void PKCS8_load_hook(RandomNumberGenerator&, bool = false);
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/nr/nr_core.cpp b/botan/src/pubkey/nr/nr_core.cpp
new file mode 100644
index 0000000..afa1115
--- /dev/null
+++ b/botan/src/pubkey/nr/nr_core.cpp
@@ -0,0 +1,62 @@
+/*
+* NR Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/nr_core.h>
+#include <botan/numthry.h>
+#include <botan/pk_engine.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* NR_Core Constructor
+*/
+NR_Core::NR_Core(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ op = Engine_Core::nr_op(group, y, x);
+ }
+
+/*
+* NR_Core Copy Constructor
+*/
+NR_Core::NR_Core(const NR_Core& core)
+ {
+ op = 0;
+ if(core.op)
+ op = core.op->clone();
+ }
+
+/*
+* NR_Core Assignment Operator
+*/
+NR_Core& NR_Core::operator=(const NR_Core& core)
+ {
+ delete op;
+ if(core.op)
+ op = core.op->clone();
+ return (*this);
+ }
+
+/*
+* NR Verification Operation
+*/
+SecureVector<byte> NR_Core::verify(const byte in[], u32bit length) const
+ {
+ return op->verify(in, length);
+ }
+
+/*
+* NR Signature Operation
+*/
+SecureVector<byte> NR_Core::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ return op->sign(in, length, k);
+ }
+
+}
diff --git a/botan/src/pubkey/nr/nr_core.h b/botan/src/pubkey/nr/nr_core.h
new file mode 100644
index 0000000..4837736
--- /dev/null
+++ b/botan/src/pubkey/nr/nr_core.h
@@ -0,0 +1,37 @@
+/*
+* NR Core
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NR_CORE_H__
+#define BOTAN_NR_CORE_H__
+
+#include <botan/nr_op.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* NR Core
+*/
+class BOTAN_DLL NR_Core
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ NR_Core& operator=(const NR_Core&);
+
+ NR_Core() { op = 0; }
+ NR_Core(const NR_Core&);
+ NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0);
+ ~NR_Core() { delete op; }
+ private:
+ NR_Operation* op;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/nr/nr_op.cpp b/botan/src/pubkey/nr/nr_op.cpp
new file mode 100644
index 0000000..b5efa3d
--- /dev/null
+++ b/botan/src/pubkey/nr/nr_op.cpp
@@ -0,0 +1,71 @@
+/*
+* NR Operations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/nr_op.h>
+
+namespace Botan {
+
+/*
+* Default_NR_Op Constructor
+*/
+Default_NR_Op::Default_NR_Op(const DL_Group& grp, const BigInt& y1,
+ const BigInt& x1) : x(x1), y(y1), group(grp)
+ {
+ powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p());
+ powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p());
+ mod_p = Modular_Reducer(group.get_p());
+ mod_q = Modular_Reducer(group.get_q());
+ }
+
+/*
+* Default NR Verify Operation
+*/
+SecureVector<byte> Default_NR_Op::verify(const byte in[], u32bit length) const
+ {
+ const BigInt& q = group.get_q();
+
+ if(length != 2*q.bytes())
+ return false;
+
+ BigInt c(in, q.bytes());
+ BigInt d(in + q.bytes(), q.bytes());
+
+ if(c.is_zero() || c >= q || d >= q)
+ throw Invalid_Argument("Default_NR_Op::verify: Invalid signature");
+
+ BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c));
+ return BigInt::encode(mod_q.reduce(c - i));
+ }
+
+/*
+* Default NR Sign Operation
+*/
+SecureVector<byte> Default_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k) const
+ {
+ if(x == 0)
+ throw Internal_Error("Default_NR_Op::sign: No private key");
+
+ const BigInt& q = group.get_q();
+
+ BigInt f(in, length);
+
+ if(f >= q)
+ throw Invalid_Argument("Default_NR_Op::sign: Input is out of range");
+
+ BigInt c = mod_q.reduce(powermod_g_p(k) + f);
+ if(c.is_zero())
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+ BigInt d = mod_q.reduce(k - x * c);
+
+ SecureVector<byte> output(2*q.bytes());
+ c.binary_encode(output + (output.size() / 2 - c.bytes()));
+ d.binary_encode(output + (output.size() - d.bytes()));
+ return output;
+ }
+
+}
diff --git a/botan/src/pubkey/nr/nr_op.h b/botan/src/pubkey/nr/nr_op.h
new file mode 100644
index 0000000..cba1465
--- /dev/null
+++ b/botan/src/pubkey/nr/nr_op.h
@@ -0,0 +1,53 @@
+/*
+* NR Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_NR_OPS_H__
+#define BOTAN_NR_OPS_H__
+
+#include <botan/pow_mod.h>
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/dl_group.h>
+
+namespace Botan {
+
+/*
+* NR Operation
+*/
+class BOTAN_DLL NR_Operation
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ const BigInt&) const = 0;
+ virtual NR_Operation* clone() const = 0;
+ virtual ~NR_Operation() {}
+ };
+
+/*
+* Botan's Default NR Operation
+*/
+class BOTAN_DLL Default_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new Default_NR_Op(*this); }
+
+ Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&);
+ private:
+ const BigInt x, y;
+ const DL_Group group;
+ Fixed_Base_Power_Mod powermod_g_p, powermod_y_p;
+ Modular_Reducer mod_p, mod_q;
+ };
+
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pk_algs.cpp b/botan/src/pubkey/pk_algs.cpp
new file mode 100644
index 0000000..99d7294
--- /dev/null
+++ b/botan/src/pubkey/pk_algs.cpp
@@ -0,0 +1,112 @@
+/*
+* PK Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pk_algs.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get an PK public key object
+*/
+Public_Key* get_public_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH") return new DH_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(alg_name == "NR") return new NR_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PublicKey;
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA") return new ECDSA_PublicKey;
+#endif
+
+ return 0;
+ }
+
+/*
+* Get an PK private key object
+*/
+Private_Key* get_private_key(const std::string& alg_name)
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(alg_name == "RSA") return new RSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(alg_name == "DSA") return new DSA_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(alg_name == "DH") return new DH_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(alg_name == "NR") return new NR_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(alg_name == "RW") return new RW_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_ELG)
+ if(alg_name == "ELG") return new ElGamal_PrivateKey;
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(alg_name == "ECDSA") return new ECDSA_PrivateKey;
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/botan/src/pubkey/pk_algs.h b/botan/src/pubkey/pk_algs.h
new file mode 100644
index 0000000..c41bf1a
--- /dev/null
+++ b/botan/src/pubkey/pk_algs.h
@@ -0,0 +1,31 @@
+/*
+* PK Key Factory
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_KEY_FACTORY_H__
+#define BOTAN_PK_KEY_FACTORY_H__
+
+#include <botan/pk_keys.h>
+
+namespace Botan {
+
+/**
+* Get an empty public key object.
+* @param name the name of the desired public key algorithm
+* @return the public key object
+*/
+BOTAN_DLL Public_Key* get_public_key(const std::string&);
+
+/**
+* Get an empty private key object.
+* @param name the name of the desired public key algorithm
+* @return the private key object
+*/
+BOTAN_DLL Private_Key* get_private_key(const std::string&);
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pk_codecs/info.txt b/botan/src/pubkey/pk_codecs/info.txt
new file mode 100644
index 0000000..96511a6
--- /dev/null
+++ b/botan/src/pubkey/pk_codecs/info.txt
@@ -0,0 +1,18 @@
+realname "PK codecs (PKCS8, X.509)"
+
+load_on auto
+
+<add>
+pkcs8.h
+pkcs8.cpp
+x509_key.h
+x509_key.cpp
+</add>
+
+<requires>
+asn1
+filters
+oid_lookup
+pbe
+pem
+</requires>
diff --git a/botan/src/pubkey/pk_codecs/pkcs8.cpp b/botan/src/pubkey/pk_codecs/pkcs8.cpp
new file mode 100644
index 0000000..8a464ec
--- /dev/null
+++ b/botan/src/pubkey/pk_codecs/pkcs8.cpp
@@ -0,0 +1,313 @@
+/*
+* PKCS #8
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pkcs8.h>
+#include <botan/get_pbe.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <memory>
+
+namespace Botan {
+
+namespace PKCS8 {
+
+namespace {
+
+/*
+* Get info from an EncryptedPrivateKeyInfo
+*/
+SecureVector<byte> PKCS8_extract(DataSource& source,
+ AlgorithmIdentifier& pbe_alg_id)
+ {
+ SecureVector<byte> key_data;
+
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(pbe_alg_id)
+ .decode(key_data, OCTET_STRING)
+ .verify_end();
+
+ return key_data;
+ }
+
+/*
+* PEM decode and/or decrypt a private key
+*/
+SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
+ AlgorithmIdentifier& pk_alg_id)
+ {
+ AlgorithmIdentifier pbe_alg_id;
+ SecureVector<byte> key_data, key;
+ bool is_encrypted = true;
+
+ try {
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ key_data = PKCS8_extract(source, pbe_alg_id);
+ else
+ {
+ std::string label;
+ key_data = PEM_Code::decode(source, label);
+ if(label == "PRIVATE KEY")
+ is_encrypted = false;
+ else if(label == "ENCRYPTED PRIVATE KEY")
+ {
+ DataSource_Memory key_source(key_data);
+ key_data = PKCS8_extract(key_source, pbe_alg_id);
+ }
+ else
+ throw PKCS8_Exception("Unknown PEM label " + label);
+ }
+
+ if(key_data.is_empty())
+ throw PKCS8_Exception("No key data found");
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ }
+
+ if(!is_encrypted)
+ key = key_data;
+
+ const u32bit MAX_TRIES = 3;
+
+ u32bit tries = 0;
+ while(true)
+ {
+ try {
+ if(MAX_TRIES && tries >= MAX_TRIES)
+ break;
+
+ if(is_encrypted)
+ {
+ DataSource_Memory params(pbe_alg_id.parameters);
+ std::auto_ptr<PBE> pbe(get_pbe(pbe_alg_id.oid, params));
+
+ User_Interface::UI_Result result = User_Interface::OK;
+ const std::string passphrase =
+ ui.get_passphrase("PKCS #8 private key", source.id(), result);
+
+ if(result == User_Interface::CANCEL_ACTION)
+ break;
+
+ pbe->set_key(passphrase);
+ Pipe decryptor(pbe.release());
+
+ decryptor.process_msg(key_data, key_data.size());
+ key = decryptor.read_all();
+ }
+
+ u32bit version;
+
+ BER_Decoder(key)
+ .start_cons(SEQUENCE)
+ .decode(version)
+ .decode(pk_alg_id)
+ .decode(key, OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+
+ if(version != 0)
+ throw Decoding_Error("PKCS #8: Unknown version number");
+
+ break;
+ }
+ catch(Decoding_Error)
+ {
+ ++tries;
+ }
+ }
+
+ if(key.is_empty())
+ throw Decoding_Error("PKCS #8 private key decoding failed");
+ return key;
+ }
+
+}
+
+/*
+* DER or PEM encode a PKCS #8 private key
+*/
+void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("PKCS8::encode: Key does not support encoding");
+
+ const u32bit PKCS8_VERSION = 0;
+
+ SecureVector<byte> contents =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
+ else
+ pipe.write(contents);
+ }
+
+/*
+* Encode and encrypt a PKCS #8 private key
+*/
+void encrypt_key(const Private_Key& key,
+ Pipe& pipe,
+ RandomNumberGenerator& rng,
+ const std::string& pass, const std::string& pbe_algo,
+ X509_Encoding encoding)
+ {
+ const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,TripleDES/CBC)";
+
+ Pipe raw_key;
+ raw_key.start_msg();
+ encode(key, raw_key, RAW_BER);
+ raw_key.end_msg();
+
+ std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
+
+ pbe->new_params(rng);
+ pbe->set_key(pass);
+
+ AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
+
+ Pipe key_encrytor(pbe.release());
+ key_encrytor.process_msg(raw_key);
+
+ SecureVector<byte> enc_key =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(pbe_algid)
+ .encode(key_encrytor.read_all(), OCTET_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
+ else
+ pipe.write(enc_key);
+ }
+
+/*
+* PEM encode a PKCS #8 private key
+*/
+std::string PEM_encode(const Private_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*
+* Encrypt and PEM encode a PKCS #8 private key
+*/
+std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo)
+ {
+ if(pass == "")
+ return PEM_encode(key);
+
+ Pipe pem;
+ pem.start_msg();
+ encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ AlgorithmIdentifier alg_id;
+ SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "" || alg_name == alg_id.oid.as_string())
+ throw PKCS8_Exception("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<Private_Key> key(get_private_key(alg_name));
+
+ if(!key.get())
+ throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support PKCS #8 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(pkcs8_key);
+
+ return key.release();
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui)
+ {
+ DataSource_Stream source(fsname, true);
+ return PKCS8::load_key(source, rng, ui);
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(source, rng, User_Interface(pass));
+ }
+
+/*
+* Extract a private key and return it
+*/
+Private_Key* load_key(const std::string& fsname,
+ RandomNumberGenerator& rng,
+ const std::string& pass)
+ {
+ return PKCS8::load_key(fsname, rng, User_Interface(pass));
+ }
+
+/*
+* Make a copy of this private key
+*/
+Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng)
+ {
+ Pipe bits;
+
+ bits.start_msg();
+ PKCS8::encode(key, bits);
+ bits.end_msg();
+
+ DataSource_Memory source(bits.read_all());
+ return PKCS8::load_key(source, rng);
+ }
+
+}
+
+}
diff --git a/botan/src/pubkey/pk_codecs/pkcs8.h b/botan/src/pubkey/pk_codecs/pkcs8.h
new file mode 100644
index 0000000..28008bd
--- /dev/null
+++ b/botan/src/pubkey/pk_codecs/pkcs8.h
@@ -0,0 +1,177 @@
+/*
+* PKCS #8
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PKCS8_H__
+#define BOTAN_PKCS8_H__
+
+#include <botan/x509_key.h>
+#include <botan/ui.h>
+
+namespace Botan {
+
+/**
+* PKCS #8 Private Key Encoder.
+*/
+class BOTAN_DLL PKCS8_Encoder
+ {
+ public:
+ /**
+ * Get the algorithm identifier associated with the scheme
+ * this encoders key is part of.
+ * @return the algorithm identifier
+ */
+ virtual AlgorithmIdentifier alg_id() const = 0;
+
+ /**
+ * Get the DER encoded key.
+ * @return the DER encoded key
+ */
+ // FIXME: Why not SecureVector?
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~PKCS8_Encoder() {}
+ };
+
+/*
+* PKCS #8 Private Key Decoder
+*/
+class BOTAN_DLL PKCS8_Decoder
+ {
+ public:
+ /**
+ * Set the algorithm identifier associated with the scheme
+ * this decoders key is part of.
+ * @param alg_id the algorithm identifier
+ */
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+
+ /**
+ * Set the DER encoded key.
+ * @param key the DER encoded key
+ */
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~PKCS8_Decoder() {}
+ };
+
+/**
+* PKCS #8 General Exception
+*/
+struct BOTAN_DLL PKCS8_Exception : public Decoding_Error
+ {
+ PKCS8_Exception(const std::string& error) :
+ Decoding_Error("PKCS #8: " + error) {}
+ };
+
+namespace PKCS8 {
+
+/**
+* Encode a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Private_Key& key, Pipe& pipe,
+ X509_Encoding enc = PEM);
+
+/**
+* Encode and encrypt a private key into a pipe.
+* @param key the private key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param pass the password to use for encryption
+* @param rng the rng to use
+* @param pbe_algo the name of the desired password-based encryption algorithm.
+* Provide an empty string to use the default PBE defined in the configuration
+* under base/default_pbe.
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encrypt_key(const Private_Key& key,
+ Pipe& pipe,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo = "",
+ X509_Encoding enc = PEM);
+
+
+/**
+* Get a string containing a PEM encoded private key.
+* @param key the key to encode
+* @return the encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key);
+
+/**
+* Get a string containing a PEM encoded private key, encrypting it with a
+* password.
+* @param key the key to encode
+* @param rng the rng to use
+* @param pass the password to use for encryption
+* @param pbe_algo the name of the desired password-based encryption algorithm.
+* Provide an empty string to use the default PBE defined in the configuration
+* under base/default_pbe.
+*/
+BOTAN_DLL std::string PEM_encode(const Private_Key& key,
+ RandomNumberGenerator& rng,
+ const std::string& pass,
+ const std::string& pbe_algo = "");
+
+/**
+* Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+
+/** Load a key from a data source.
+* @param source the data source providing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(DataSource& source,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param ui the user interface to be used for passphrase dialog
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const User_Interface& ui);
+
+/** Load a key from a file.
+* @param filename the path to the file containing the encoded key
+* @param rng the rng to use
+* @param pass the passphrase to decrypt the key. Provide an empty
+* string if the key is not encoded.
+* @return the loaded private key object
+*/
+BOTAN_DLL Private_Key* load_key(const std::string& filename,
+ RandomNumberGenerator& rng,
+ const std::string& pass = "");
+
+/**
+* Copy an existing encoded key object.
+* @param key the key to copy
+* @param rng the rng to use
+* @return the new copy of the key
+*/
+BOTAN_DLL Private_Key* copy_key(const Private_Key& key,
+ RandomNumberGenerator& rng);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pk_codecs/x509_key.cpp b/botan/src/pubkey/pk_codecs/x509_key.cpp
new file mode 100644
index 0000000..455e627
--- /dev/null
+++ b/botan/src/pubkey/pk_codecs/x509_key.cpp
@@ -0,0 +1,176 @@
+/*
+* X.509 Public Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x509_key.h>
+#include <botan/filters.h>
+#include <botan/asn1_obj.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/pk_algs.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+#include <memory>
+
+namespace Botan {
+
+namespace X509 {
+
+/*
+* DER or PEM encode a X.509 public key
+*/
+void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding)
+ {
+ std::auto_ptr<X509_Encoder> encoder(key.x509_encoder());
+ if(!encoder.get())
+ throw Encoding_Error("X509::encode: Key does not support encoding");
+
+ MemoryVector<byte> der =
+ DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(encoder->alg_id())
+ .encode(encoder->key_bits(), BIT_STRING)
+ .end_cons()
+ .get_contents();
+
+ if(encoding == PEM)
+ pipe.write(PEM_Code::encode(der, "PUBLIC KEY"));
+ else
+ pipe.write(der);
+ }
+
+/*
+* PEM encode a X.509 public key
+*/
+std::string PEM_encode(const Public_Key& key)
+ {
+ Pipe pem;
+ pem.start_msg();
+ encode(key, pem, PEM);
+ pem.end_msg();
+ return pem.read_all_as_string();
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(DataSource& source)
+ {
+ try {
+ AlgorithmIdentifier alg_id;
+ MemoryVector<byte> key_bits;
+
+ if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
+ {
+ BER_Decoder(source)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+ else
+ {
+ DataSource_Memory ber(
+ PEM_Code::decode_check_label(source, "PUBLIC KEY")
+ );
+
+ BER_Decoder(ber)
+ .start_cons(SEQUENCE)
+ .decode(alg_id)
+ .decode(key_bits, BIT_STRING)
+ .verify_end()
+ .end_cons();
+ }
+
+ if(key_bits.is_empty())
+ throw Decoding_Error("X.509 public key decoding failed");
+
+ const std::string alg_name = OIDS::lookup(alg_id.oid);
+ if(alg_name == "")
+ throw Decoding_Error("Unknown algorithm OID: " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<Public_Key> key_obj(get_public_key(alg_name));
+ if(!key_obj.get())
+ throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " +
+ alg_id.oid.as_string());
+
+ std::auto_ptr<X509_Decoder> decoder(key_obj->x509_decoder());
+
+ if(!decoder.get())
+ throw Decoding_Error("Key does not support X.509 decoding");
+
+ decoder->alg_id(alg_id);
+ decoder->key_bits(key_bits);
+
+ return key_obj.release();
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error("X.509 public key decoding failed");
+ }
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const std::string& fsname)
+ {
+ DataSource_Stream source(fsname, true);
+ return X509::load_key(source);
+ }
+
+/*
+* Extract a public key and return it
+*/
+Public_Key* load_key(const MemoryRegion<byte>& mem)
+ {
+ DataSource_Memory source(mem);
+ return X509::load_key(source);
+ }
+
+/*
+* Make a copy of this public key
+*/
+Public_Key* copy_key(const Public_Key& key)
+ {
+ Pipe bits;
+ bits.start_msg();
+ X509::encode(key, bits, RAW_BER);
+ bits.end_msg();
+ DataSource_Memory source(bits.read_all());
+ return X509::load_key(source);
+ }
+
+/*
+* Find the allowable key constraints
+*/
+Key_Constraints find_constraints(const Public_Key& pub_key,
+ Key_Constraints limits)
+ {
+ const Public_Key* key = &pub_key;
+ u32bit constraints = 0;
+
+ if(dynamic_cast<const PK_Encrypting_Key*>(key))
+ constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT;
+
+ if(dynamic_cast<const PK_Key_Agreement_Key*>(key))
+ constraints |= KEY_AGREEMENT;
+
+ if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) ||
+ dynamic_cast<const PK_Verifying_with_MR_Key*>(key))
+ constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION;
+
+ if(limits)
+ constraints &= limits;
+
+ return Key_Constraints(constraints);
+ }
+
+}
+
+}
diff --git a/botan/src/pubkey/pk_codecs/x509_key.h b/botan/src/pubkey/pk_codecs/x509_key.h
new file mode 100644
index 0000000..9404b7e
--- /dev/null
+++ b/botan/src/pubkey/pk_codecs/x509_key.h
@@ -0,0 +1,110 @@
+/*
+* X.509 Public Key
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X509_PUBLIC_KEY_H__
+#define BOTAN_X509_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+#include <botan/pubkey_enums.h>
+
+namespace Botan {
+
+/**
+* This class represents abstract X.509 public key encoders.
+*/
+class BOTAN_DLL X509_Encoder
+ {
+ public:
+ virtual AlgorithmIdentifier alg_id() const = 0;
+ virtual MemoryVector<byte> key_bits() const = 0;
+ virtual ~X509_Encoder() {}
+ };
+
+/**
+* This class represents abstract X.509 public key decoders.
+*/
+class BOTAN_DLL X509_Decoder
+ {
+ public:
+ virtual void alg_id(const AlgorithmIdentifier&) = 0;
+ virtual void key_bits(const MemoryRegion<byte>&) = 0;
+ virtual ~X509_Decoder() {}
+ };
+
+/**
+* This namespace contains functions for handling X509 objects.
+*/
+namespace X509 {
+
+/*
+* X.509 Public Key Encoding/Decoding
+*/
+
+/**
+* Encode a key into a pipe.
+* @param key the public key to encode
+* @param pipe the pipe to feed the encoded key into
+* @param enc the encoding type to use
+*/
+BOTAN_DLL void encode(const Public_Key& key, Pipe& pipe,
+ X509_Encoding enc = PEM);
+
+/**
+* PEM encode a public key into a string.
+* @param key the key to encode
+* @return the PEM encoded key
+*/
+BOTAN_DLL std::string PEM_encode(const Public_Key& key);
+
+/**
+* Create a public key from a data source.
+* @param source the source providing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(DataSource& source);
+
+/**
+* Create a public key from a string.
+* @param enc the string containing the PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const std::string& enc);
+
+/**
+* Create a public key from a memory region.
+* @param enc the memory region containing the DER or PEM encoded key
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* load_key(const MemoryRegion<byte>& enc);
+
+/**
+* Copy a key.
+* @param key the public key to copy
+* @return the new public key object
+*/
+BOTAN_DLL Public_Key* copy_key(const Public_Key& key);
+
+/**
+* Create the key constraints for a specific public key.
+* @param pub_key the public key from which the basic set of
+* constraints to be placed in the return value is derived
+* @param limits additional limits that will be incorporated into the
+* return value
+* @return the combination of key type specific constraints and
+* additional limits
+*/
+
+BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key,
+ Key_Constraints limits);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pk_filts.cpp b/botan/src/pubkey/pk_filts.cpp
new file mode 100644
index 0000000..18da9c1
--- /dev/null
+++ b/botan/src/pubkey/pk_filts.cpp
@@ -0,0 +1,115 @@
+/*
+* PK Filters
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pk_filts.h>
+
+namespace Botan {
+
+/*
+* Append to the buffer
+*/
+void PK_Encryptor_Filter::write(const byte input[], u32bit length)
+ {
+ buffer.append(input, length);
+ }
+
+/*
+* Encrypt the message
+*/
+void PK_Encryptor_Filter::end_msg()
+ {
+ send(cipher->encrypt(buffer, buffer.size(), rng));
+ buffer.destroy();
+ }
+
+/*
+* Append to the buffer
+*/
+void PK_Decryptor_Filter::write(const byte input[], u32bit length)
+ {
+ buffer.append(input, length);
+ }
+
+/*
+* Decrypt the message
+*/
+void PK_Decryptor_Filter::end_msg()
+ {
+ send(cipher->decrypt(buffer, buffer.size()));
+ buffer.destroy();
+ }
+
+/*
+* Add more data
+*/
+void PK_Signer_Filter::write(const byte input[], u32bit length)
+ {
+ signer->update(input, length);
+ }
+
+/*
+* Sign the message
+*/
+void PK_Signer_Filter::end_msg()
+ {
+ send(signer->signature(rng));
+ }
+
+/*
+* Add more data
+*/
+void PK_Verifier_Filter::write(const byte input[], u32bit length)
+ {
+ verifier->update(input, length);
+ }
+
+/*
+* Verify the message
+*/
+void PK_Verifier_Filter::end_msg()
+ {
+ if(signature.is_empty())
+ throw Exception("PK_Verifier_Filter: No signature to check against");
+ bool is_valid = verifier->check_signature(signature, signature.size());
+ send((is_valid ? 1 : 0));
+ }
+
+/*
+* Set the signature to check
+*/
+void PK_Verifier_Filter::set_signature(const byte sig[], u32bit length)
+ {
+ signature.set(sig, length);
+ }
+
+/*
+* Set the signature to check
+*/
+void PK_Verifier_Filter::set_signature(const MemoryRegion<byte>& sig)
+ {
+ signature = sig;
+ }
+
+/*
+* PK_Verifier_Filter Constructor
+*/
+PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v, const byte sig[],
+ u32bit length) :
+ verifier(v), signature(sig, length)
+ {
+ }
+
+/*
+* PK_Verifier_Filter Constructor
+*/
+PK_Verifier_Filter::PK_Verifier_Filter(PK_Verifier* v,
+ const MemoryRegion<byte>& sig) :
+ verifier(v), signature(sig)
+ {
+ }
+
+}
diff --git a/botan/src/pubkey/pk_filts.h b/botan/src/pubkey/pk_filts.h
new file mode 100644
index 0000000..8bf3fc2
--- /dev/null
+++ b/botan/src/pubkey/pk_filts.h
@@ -0,0 +1,91 @@
+/*
+* PK Filters
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_FILTERS_H__
+#define BOTAN_PK_FILTERS_H__
+
+#include <botan/filter.h>
+#include <botan/pubkey.h>
+
+namespace Botan {
+
+/*
+* PK_Encryptor Filter
+*/
+class BOTAN_DLL PK_Encryptor_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+ PK_Encryptor_Filter(PK_Encryptor* c,
+ RandomNumberGenerator& rng_ref) :
+ cipher(c), rng(rng_ref) {}
+ ~PK_Encryptor_Filter() { delete cipher; }
+ private:
+ PK_Encryptor* cipher;
+ RandomNumberGenerator& rng;
+ SecureVector<byte> buffer;
+ };
+
+/*
+* PK_Decryptor Filter
+*/
+class BOTAN_DLL PK_Decryptor_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+ PK_Decryptor_Filter(PK_Decryptor* c) : cipher(c) {}
+ ~PK_Decryptor_Filter() { delete cipher; }
+ private:
+ PK_Decryptor* cipher;
+ SecureVector<byte> buffer;
+ };
+
+/*
+* PK_Signer Filter
+*/
+class BOTAN_DLL PK_Signer_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ PK_Signer_Filter(PK_Signer* s,
+ RandomNumberGenerator& rng_ref) :
+ signer(s), rng(rng_ref) {}
+
+ ~PK_Signer_Filter() { delete signer; }
+ private:
+ PK_Signer* signer;
+ RandomNumberGenerator& rng;
+ };
+
+/*
+* PK_Verifier Filter
+*/
+class BOTAN_DLL PK_Verifier_Filter : public Filter
+ {
+ public:
+ void write(const byte[], u32bit);
+ void end_msg();
+
+ void set_signature(const byte[], u32bit);
+ void set_signature(const MemoryRegion<byte>&);
+
+ PK_Verifier_Filter(PK_Verifier* v) : verifier(v) {}
+ PK_Verifier_Filter(PK_Verifier*, const byte[], u32bit);
+ PK_Verifier_Filter(PK_Verifier*, const MemoryRegion<byte>&);
+ ~PK_Verifier_Filter() { delete verifier; }
+ private:
+ PK_Verifier* verifier;
+ SecureVector<byte> signature;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pk_keys.cpp b/botan/src/pubkey/pk_keys.cpp
new file mode 100644
index 0000000..b931585
--- /dev/null
+++ b/botan/src/pubkey/pk_keys.cpp
@@ -0,0 +1,54 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pk_keys.h>
+#include <botan/oids.h>
+
+namespace Botan {
+
+/*
+* Default OID access
+*/
+OID Public_Key::get_oid() const
+ {
+ try {
+ return OIDS::lookup(algo_name());
+ }
+ catch(Lookup_Error)
+ {
+ throw Lookup_Error("PK algo " + algo_name() + " has no defined OIDs");
+ }
+ }
+
+/*
+* Run checks on a loaded public key
+*/
+void Public_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD))
+ throw Invalid_Argument(algo_name() + ": Invalid public key");
+ }
+
+/*
+* Run checks on a loaded private key
+*/
+void Private_Key::load_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD))
+ throw Invalid_Argument(algo_name() + ": Invalid private key");
+ }
+
+/*
+* Run checks on a generated private key
+*/
+void Private_Key::gen_check(RandomNumberGenerator& rng) const
+ {
+ if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE))
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+}
diff --git a/botan/src/pubkey/pk_keys.h b/botan/src/pubkey/pk_keys.h
new file mode 100644
index 0000000..5b61257
--- /dev/null
+++ b/botan/src/pubkey/pk_keys.h
@@ -0,0 +1,180 @@
+/*
+* PK Key Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PK_KEYS_H__
+#define BOTAN_PK_KEYS_H__
+
+#include <botan/secmem.h>
+#include <botan/asn1_oid.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Public Key Base Class.
+*/
+class BOTAN_DLL Public_Key
+ {
+ public:
+ /**
+ * Get the name of the underlying public key scheme.
+ * @return the name of the public key scheme
+ */
+ virtual std::string algo_name() const = 0;
+
+ /**
+ * Get the OID of the underlying public key scheme.
+ * @return the OID of the public key scheme
+ */
+ virtual OID get_oid() const;
+
+ /**
+ * Test the key values for consistency.
+ * @param rng rng to use
+ * @param strong whether to perform strong and lengthy version
+ * of the test
+ * @return true if the test is passed
+ */
+ virtual bool check_key(RandomNumberGenerator&, bool) const
+ { return true; }
+
+ /**
+ * Find out the number of message parts supported by this scheme.
+ * @return the number of message parts
+ */
+ virtual u32bit message_parts() const { return 1; }
+
+ /**
+ * Find out the message part size supported by this scheme/key.
+ * @return the size of the message parts
+ */
+ virtual u32bit message_part_size() const { return 0; }
+
+ /**
+ * Get the maximum message size in bits supported by this public key.
+ * @return the maximum message in bits
+ */
+ virtual u32bit max_input_bits() const = 0;
+
+ /**
+ * Get an X509 encoder that can be used to encode this key in X509 format.
+ * @return an X509 encoder for this key
+ */
+ virtual class X509_Encoder* x509_encoder() const = 0;
+
+ /**
+ * Get an X509 decoder that can be used to set the values of this
+ * key based on an X509 encoded key object.
+ * @return an X509 decoder for this key
+ */
+ virtual class X509_Decoder* x509_decoder() = 0;
+
+ virtual ~Public_Key() {}
+ protected:
+ virtual void load_check(RandomNumberGenerator&) const;
+ };
+
+/**
+* Private Key Base Class
+*/
+class BOTAN_DLL Private_Key : public virtual Public_Key
+ {
+ public:
+ /**
+ * Get a PKCS#8 encoder that can be used to encode this key in
+ * PKCS#8 format.
+ * @return an PKCS#8 encoder for this key
+ */
+ virtual class PKCS8_Encoder* pkcs8_encoder() const
+ { return 0; }
+
+ /**
+ * Get an PKCS#8 decoder that can be used to set the values of this key
+ * based on an PKCS#8 encoded key object.
+ * @return an PKCS#8 decoder for this key
+ */
+ virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&)
+ { return 0; }
+ protected:
+ void load_check(RandomNumberGenerator&) const;
+ void gen_check(RandomNumberGenerator&) const;
+ };
+
+/**
+* PK Encrypting Key.
+*/
+class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ virtual ~PK_Encrypting_Key() {}
+ };
+
+/**
+* PK Decrypting Key
+*/
+class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0;
+ virtual ~PK_Decrypting_Key() {}
+ };
+
+/**
+* PK Signing Key
+*/
+class BOTAN_DLL PK_Signing_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const = 0;
+ virtual ~PK_Signing_Key() {}
+ };
+
+/**
+* PK Verifying Key, Message Recovery Version
+*/
+class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual SecureVector<byte> verify(const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_with_MR_Key() {}
+ };
+
+/**
+* PK Verifying Key, No Message Recovery Version
+*/
+class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key
+ {
+ public:
+ virtual bool verify(const byte[], u32bit,
+ const byte[], u32bit) const = 0;
+ virtual ~PK_Verifying_wo_MR_Key() {}
+ };
+
+/**
+* PK Secret Value Derivation Key
+*/
+class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key
+ {
+ public:
+ virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0;
+ virtual MemoryVector<byte> public_value() const = 0;
+ virtual ~PK_Key_Agreement_Key() {}
+ };
+
+/*
+* Typedefs
+*/
+typedef PK_Key_Agreement_Key PK_KA_Key;
+typedef Public_Key X509_PublicKey;
+typedef Private_Key PKCS8_PrivateKey;
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pubkey.cpp b/botan/src/pubkey/pubkey.cpp
new file mode 100644
index 0000000..4ddaa6f
--- /dev/null
+++ b/botan/src/pubkey/pubkey.cpp
@@ -0,0 +1,396 @@
+/*
+* Public Key Base
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pubkey.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/bigint.h>
+#include <botan/parsing.h>
+#include <botan/bit_ops.h>
+#include <memory>
+
+namespace Botan {
+
+/*
+* Encrypt a message
+*/
+SecureVector<byte> PK_Encryptor::encrypt(const byte in[], u32bit len,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in, len, rng);
+ }
+
+/*
+* Encrypt a message
+*/
+SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng) const
+ {
+ return enc(in.begin(), in.size(), rng);
+ }
+
+/*
+* Decrypt a message
+*/
+SecureVector<byte> PK_Decryptor::decrypt(const byte in[], u32bit len) const
+ {
+ return dec(in, len);
+ }
+
+/*
+* Decrypt a message
+*/
+SecureVector<byte> PK_Decryptor::decrypt(const MemoryRegion<byte>& in) const
+ {
+ return dec(in.begin(), in.size());
+ }
+
+/*
+* PK_Encryptor_MR_with_EME Constructor
+*/
+PK_Encryptor_MR_with_EME::PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& k,
+ EME* eme_obj) :
+ key(k), encoder(eme_obj)
+ {
+ }
+
+/*
+* Encrypt a message
+*/
+SecureVector<byte>
+PK_Encryptor_MR_with_EME::enc(const byte msg[],
+ u32bit length,
+ RandomNumberGenerator& rng) const
+ {
+ SecureVector<byte> message;
+ if(encoder)
+ message = encoder->encode(msg, length, key.max_input_bits(), rng);
+ else
+ message.set(msg, length);
+
+ if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits())
+ throw Exception("PK_Encryptor_MR_with_EME: Input is too large");
+
+ return key.encrypt(message, message.size(), rng);
+ }
+
+/*
+* Return the max size, in bytes, of a message
+*/
+u32bit PK_Encryptor_MR_with_EME::maximum_input_size() const
+ {
+ if(!encoder)
+ return (key.max_input_bits() / 8);
+ else
+ return encoder->maximum_input_size(key.max_input_bits());
+ }
+
+/*
+* PK_Decryptor_MR_with_EME Constructor
+*/
+PK_Decryptor_MR_with_EME::PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& k,
+ EME* eme_obj) :
+ key(k), encoder(eme_obj)
+ {
+ }
+
+/*
+* Decrypt a message
+*/
+SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[],
+ u32bit length) const
+ {
+ try {
+ SecureVector<byte> decrypted = key.decrypt(msg, length);
+ if(encoder)
+ return encoder->decode(decrypted, key.max_input_bits());
+ else
+ return decrypted;
+ }
+ catch(Invalid_Argument)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ catch(Decoding_Error)
+ {
+ throw Exception("PK_Decryptor_MR_with_EME: Input is invalid");
+ }
+ }
+
+/*
+* PK_Signer Constructor
+*/
+PK_Signer::PK_Signer(const PK_Signing_Key& k, EMSA* emsa_obj) :
+ key(k), emsa(emsa_obj)
+ {
+ sig_format = IEEE_1363;
+ }
+
+/*
+* Set the signature format
+*/
+void PK_Signer::set_output_format(Signature_Format format)
+ {
+ if(key.message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Signer: Cannot set the output format for " +
+ key.algo_name() + " keys");
+ sig_format = format;
+ }
+
+/*
+* Sign a message
+*/
+SecureVector<byte> PK_Signer::sign_message(const byte msg[], u32bit length,
+ RandomNumberGenerator& rng)
+ {
+ update(msg, length);
+ return signature(rng);
+ }
+
+/*
+* Sign a message
+*/
+SecureVector<byte> PK_Signer::sign_message(const MemoryRegion<byte>& msg,
+ RandomNumberGenerator& rng)
+ {
+ return sign_message(msg, msg.size(), rng);
+ }
+
+/*
+* Add more to the message to be signed
+*/
+void PK_Signer::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*
+* Add more to the message to be signed
+*/
+void PK_Signer::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*
+* Add more to the message to be signed
+*/
+void PK_Signer::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*
+* Create a signature
+*/
+SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(),
+ key.max_input_bits(),
+ rng);
+
+ SecureVector<byte> plain_sig = key.sign(encoded, encoded.size(), rng);
+
+ if(key.message_parts() == 1 || sig_format == IEEE_1363)
+ return plain_sig;
+
+ if(sig_format == DER_SEQUENCE)
+ {
+ if(plain_sig.size() % key.message_parts())
+ throw Encoding_Error("PK_Signer: strange signature size found");
+ const u32bit SIZE_OF_PART = plain_sig.size() / key.message_parts();
+
+ std::vector<BigInt> sig_parts(key.message_parts());
+ for(u32bit j = 0; j != sig_parts.size(); ++j)
+ sig_parts[j].binary_decode(plain_sig + SIZE_OF_PART*j, SIZE_OF_PART);
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode_list(sig_parts)
+ .end_cons()
+ .get_contents();
+ }
+ else
+ throw Encoding_Error("PK_Signer: Unknown signature format " +
+ to_string(sig_format));
+ }
+
+/*
+* PK_Verifier Constructor
+*/
+PK_Verifier::PK_Verifier(EMSA* emsa_obj)
+ {
+ emsa = emsa_obj;
+ sig_format = IEEE_1363;
+ }
+
+/*
+* PK_Verifier Destructor
+*/
+PK_Verifier::~PK_Verifier()
+ {
+ delete emsa;
+ }
+
+/*
+* Set the signature format
+*/
+void PK_Verifier::set_input_format(Signature_Format format)
+ {
+ if(key_message_parts() == 1 && format != IEEE_1363)
+ throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363");
+ sig_format = format;
+ }
+
+/*
+* Verify a message
+*/
+bool PK_Verifier::verify_message(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig)
+ {
+ return verify_message(msg, msg.size(), sig, sig.size());
+ }
+
+/*
+* Verify a message
+*/
+bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length)
+ {
+ update(msg, msg_length);
+ return check_signature(sig, sig_length);
+ }
+
+/*
+* Append to the message
+*/
+void PK_Verifier::update(const byte in[], u32bit length)
+ {
+ emsa->update(in, length);
+ }
+
+/*
+* Append to the message
+*/
+void PK_Verifier::update(byte in)
+ {
+ update(&in, 1);
+ }
+
+/*
+* Append to the message
+*/
+void PK_Verifier::update(const MemoryRegion<byte>& in)
+ {
+ update(in, in.size());
+ }
+
+/*
+* Check a signature
+*/
+bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig)
+ {
+ return check_signature(sig, sig.size());
+ }
+
+/*
+* Check a signature
+*/
+bool PK_Verifier::check_signature(const byte sig[], u32bit length)
+ {
+ try {
+ if(sig_format == IEEE_1363)
+ return validate_signature(emsa->raw_data(), sig, length);
+ else if(sig_format == DER_SEQUENCE)
+ {
+ BER_Decoder decoder(sig, length);
+ BER_Decoder ber_sig = decoder.start_cons(SEQUENCE);
+
+ u32bit count = 0;
+ SecureVector<byte> real_sig;
+ while(ber_sig.more_items())
+ {
+ BigInt sig_part;
+ ber_sig.decode(sig_part);
+ real_sig.append(BigInt::encode_1363(sig_part,
+ key_message_part_size()));
+ ++count;
+ }
+ if(count != key_message_parts())
+ throw Decoding_Error("PK_Verifier: signature size invalid");
+
+ return validate_signature(emsa->raw_data(),
+ real_sig, real_sig.size());
+ }
+ else
+ throw Decoding_Error("PK_Verifier: Unknown signature format " +
+ to_string(sig_format));
+ }
+ catch(Invalid_Argument) { return false; }
+ catch(Decoding_Error) { return false; }
+ }
+
+/*
+* Verify a signature
+*/
+bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ SecureVector<byte> output_of_key = key.verify(sig, sig_len);
+ return emsa->verify(output_of_key, msg, key.max_input_bits());
+ }
+
+/*
+* Verify a signature
+*/
+bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg,
+ const byte sig[], u32bit sig_len)
+ {
+ Null_RNG rng;
+
+ SecureVector<byte> encoded =
+ emsa->encoding_of(msg, key.max_input_bits(), rng);
+
+ return key.verify(encoded, encoded.size(), sig, sig_len);
+ }
+
+/*
+* PK_Key_Agreement Constructor
+*/
+PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& k,
+ KDF* kdf_obj) :
+ key(k), kdf(kdf_obj)
+ {
+ }
+
+/*
+* Perform Key Agreement Operation
+*/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len,
+ const byte in[], u32bit in_len,
+ const std::string& params) const
+ {
+ return derive_key(key_len, in, in_len,
+ reinterpret_cast<const byte*>(params.data()),
+ params.length());
+ }
+
+/*
+* Perform Key Agreement Operation
+*/
+SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, const byte in[],
+ u32bit in_len, const byte params[],
+ u32bit params_len) const
+ {
+ OctetString z = key.derive_key(in, in_len);
+ if(!kdf)
+ return z;
+
+ return kdf->derive_key(key_len, z.bits_of(), params, params_len);
+ }
+
+}
diff --git a/botan/src/pubkey/pubkey.h b/botan/src/pubkey/pubkey.h
new file mode 100644
index 0000000..c73a54d
--- /dev/null
+++ b/botan/src/pubkey/pubkey.h
@@ -0,0 +1,392 @@
+/*
+* Public Key Interface
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PUBKEY_H__
+#define BOTAN_PUBKEY_H__
+
+#include <botan/pk_keys.h>
+#include <botan/symkey.h>
+#include <botan/rng.h>
+#include <botan/eme.h>
+#include <botan/emsa.h>
+#include <botan/kdf.h>
+
+namespace Botan {
+
+/**
+* The two types of signature format supported by Botan.
+*/
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
+/**
+* Public Key Encryptor
+*/
+class BOTAN_DLL PK_Encryptor
+ {
+ public:
+
+ /**
+ * Encrypt a message.
+ * @param in the message as a byte array
+ * @param length the length of the above byte array
+ * @param rng the random number source to use
+ * @return the encrypted message
+ */
+ SecureVector<byte> encrypt(const byte in[], u32bit length,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Encrypt a message.
+ * @param in the message
+ * @param rng the random number source to use
+ * @return the encrypted message
+ */
+ SecureVector<byte> encrypt(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Return the maximum allowed message size in bytes.
+ * @return the maximum message size in bytes
+ */
+ virtual u32bit maximum_input_size() const = 0;
+
+ virtual ~PK_Encryptor() {}
+ private:
+ virtual SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator&) const = 0;
+ };
+
+/**
+* Public Key Decryptor
+*/
+class BOTAN_DLL PK_Decryptor
+ {
+ public:
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext as a byte array
+ * @param length the length of the above byte array
+ * @return the decrypted message
+ */
+ SecureVector<byte> decrypt(const byte in[], u32bit length) const;
+
+ /**
+ * Decrypt a ciphertext.
+ * @param in the ciphertext
+ * @return the decrypted message
+ */
+ SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const;
+
+ virtual ~PK_Decryptor() {}
+ private:
+ virtual SecureVector<byte> dec(const byte[], u32bit) const = 0;
+ };
+
+/**
+* Public Key Signer. Use the sign_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* generate the signature by finally calling signature().
+*/
+class BOTAN_DLL PK_Signer
+ {
+ public:
+ /**
+ * Sign a message.
+ * @param in the message to sign as a byte array
+ * @param length the length of the above byte array
+ * @param rng the rng to use
+ * @return the signature
+ */
+ SecureVector<byte> sign_message(const byte in[], u32bit length,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Sign a message.
+ * @param in the message to sign
+ * @param rng the rng to use
+ * @return the signature
+ */
+ SecureVector<byte> sign_message(const MemoryRegion<byte>& in,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Add a message part (single byte).
+ * @param the byte to add
+ */
+ void update(byte in);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const byte in[], u32bit length);
+
+ /**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const MemoryRegion<byte>& in);
+
+ /**
+ * Get the signature of the so far processed message (provided by the
+ * calls to update()).
+ * @param rng the rng to use
+ * @return the signature of the total message
+ */
+ SecureVector<byte> signature(RandomNumberGenerator& rng);
+
+ /**
+ * Set the output format of the signature.
+ * @param format the signature format to use
+ */
+ void set_output_format(Signature_Format format);
+
+ /**
+ * Construct a PK Signer.
+ * @param key the key to use inside this signer
+ * @param emsa the EMSA to use
+ * An example would be "EMSA1(SHA-224)".
+ */
+ PK_Signer(const PK_Signing_Key& key, EMSA* emsa);
+
+ ~PK_Signer() { delete emsa; }
+ private:
+ PK_Signer(const PK_Signer&);
+ PK_Signer& operator=(const PK_Signer&);
+
+ const PK_Signing_Key& key;
+ Signature_Format sig_format;
+ EMSA* emsa;
+ };
+
+/**
+* Public Key Verifier. Use the verify_message() functions for small
+* messages. Use multiple calls update() to process large messages and
+* verify the signature by finally calling check_signature().
+*/
+class BOTAN_DLL PK_Verifier
+ {
+ public:
+ /**
+ * Verify a signature.
+ * @param msg the message that the signature belongs to, as a byte array
+ * @param msg_length the length of the above byte array msg
+ * @param sig the signature as a byte array
+ * @param sig_length the length of the above byte array sig
+ * @return true if the signature is valid
+ */
+ bool verify_message(const byte msg[], u32bit msg_length,
+ const byte sig[], u32bit sig_length);
+ /**
+ * Verify a signature.
+ * @param msg the message that the signature belongs to
+ * @param sig the signature
+ * @return true if the signature is valid
+ */
+ bool verify_message(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig);
+
+ /**
+ * Add a message part (single byte) of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the byte to add
+ */
+ void update(byte msg_part);
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the new message part as a byte array
+ * @param length the length of the above byte array
+ */
+ void update(const byte msg_part[], u32bit length);
+
+ /**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ * @param msg_part the new message part
+ */
+ void update(const MemoryRegion<byte>& msg_part);
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified as a byte array
+ * @param length the length of the above byte array
+ * @return true if the signature is valid, false otherwise
+ */
+ bool check_signature(const byte sig[], u32bit length);
+
+ /**
+ * Check the signature of the buffered message, i.e. the one build
+ * by successive calls to update.
+ * @param sig the signature to be verified
+ * @return true if the signature is valid, false otherwise
+ */
+ bool check_signature(const MemoryRegion<byte>& sig);
+
+ /**
+ * Set the format of the signatures fed to this verifier.
+ * @param format the signature format to use
+ */
+ void set_input_format(Signature_Format format);
+
+ /**
+ * Construct a PK Verifier.
+ * @param emsa the EMSA to use
+ * An example would be new EMSA1(new SHA_224)
+ */
+ PK_Verifier(EMSA* emsa);
+
+ virtual ~PK_Verifier();
+ protected:
+ virtual bool validate_signature(const MemoryRegion<byte>&,
+ const byte[], u32bit) = 0;
+ virtual u32bit key_message_parts() const = 0;
+ virtual u32bit key_message_part_size() const = 0;
+
+ Signature_Format sig_format;
+ EMSA* emsa;
+ private:
+ PK_Verifier(const PK_Verifier&);
+ PK_Verifier& operator=(const PK_Verifier&);
+ };
+
+/*
+* Key Agreement
+*/
+class BOTAN_DLL PK_Key_Agreement
+ {
+ public:
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const std::string& = "") const;
+ SymmetricKey derive_key(u32bit, const byte[], u32bit,
+ const byte[], u32bit) const;
+
+ /**
+ * Construct a PK Key Agreement.
+ * @param key the key to use
+ * @param kdf the KDF to use
+ */
+ PK_Key_Agreement(const PK_Key_Agreement_Key& key, KDF* kdf);
+
+ ~PK_Key_Agreement() { delete kdf; }
+ private:
+ PK_Key_Agreement(const PK_Key_Agreement_Key&);
+ PK_Key_Agreement& operator=(const PK_Key_Agreement&);
+
+ const PK_Key_Agreement_Key& key;
+ KDF* kdf;
+ };
+
+/**
+* Encryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor
+ {
+ public:
+ u32bit maximum_input_size() const;
+
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the decryptor
+ * @param eme the EME to use
+ */
+ PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& key,
+ EME* eme);
+
+ ~PK_Encryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&);
+ PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&);
+
+ SecureVector<byte> enc(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ const PK_Encrypting_Key& key;
+ const EME* encoder;
+ };
+
+/**
+* Decryption with an MR algorithm and an EME.
+*/
+class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the encryptor
+ * @param eme the EME to use
+ */
+ PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& key,
+ EME* eme);
+
+ ~PK_Decryptor_MR_with_EME() { delete encoder; }
+ private:
+ PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&);
+ PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&);
+
+ SecureVector<byte> dec(const byte[], u32bit) const;
+
+ const PK_Decrypting_Key& key;
+ const EME* encoder;
+ };
+
+/**
+* Public Key Verifier with Message Recovery.
+*/
+class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the verifier
+ * @param emsa_name the name of the EMSA to use
+ */
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k,
+ EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {}
+
+ private:
+ PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&);
+ PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_with_MR_Key& key;
+ };
+
+/**
+* Public Key Verifier without Message Recovery
+*/
+class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier
+ {
+ public:
+ /**
+ * Construct an instance.
+ * @param key the key to use inside the verifier
+ * @param emsa_name the name of the EMSA to use
+ */
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k,
+ EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {}
+
+ private:
+ PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&);
+ PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&);
+
+ bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit);
+ u32bit key_message_parts() const { return key.message_parts(); }
+ u32bit key_message_part_size() const { return key.message_part_size(); }
+
+ const PK_Verifying_wo_MR_Key& key;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/pubkey_enums.cpp b/botan/src/pubkey/pubkey_enums.cpp
new file mode 100644
index 0000000..327107d
--- /dev/null
+++ b/botan/src/pubkey/pubkey_enums.cpp
@@ -0,0 +1,42 @@
+/*
+* KeyUsage
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pubkey_enums.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+namespace BER {
+
+/*
+* Decode a BER encoded KeyUsage
+*/
+void decode(BER_Decoder& source, Key_Constraints& key_usage)
+ {
+ BER_Object obj = source.get_next_object();
+
+ if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL)
+ throw BER_Bad_Tag("Bad tag for usage constraint",
+ obj.type_tag, obj.class_tag);
+ if(obj.value.size() != 2 && obj.value.size() != 3)
+ throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");
+ if(obj.value[0] >= 8)
+ throw BER_Decoding_Error("Invalid unused bits in usage constraint");
+
+ const byte mask = (0xFF << obj.value[0]);
+ obj.value[obj.value.size()-1] &= mask;
+
+ u16bit usage = 0;
+ for(u32bit j = 1; j != obj.value.size(); ++j)
+ usage = (obj.value[j] << 8) | usage;
+
+ key_usage = Key_Constraints(usage);
+ }
+
+}
+
+}
diff --git a/botan/src/pubkey/pubkey_enums.h b/botan/src/pubkey/pubkey_enums.h
new file mode 100644
index 0000000..53e319f
--- /dev/null
+++ b/botan/src/pubkey/pubkey_enums.h
@@ -0,0 +1,77 @@
+/*
+* Enumerations
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENUMS_H__
+#define BOTAN_ENUMS_H__
+
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+/**
+* X.509v3 Key Constraints.
+*/
+enum Key_Constraints {
+ NO_CONSTRAINTS = 0,
+ DIGITAL_SIGNATURE = 32768,
+ NON_REPUDIATION = 16384,
+ KEY_ENCIPHERMENT = 8192,
+ DATA_ENCIPHERMENT = 4096,
+ KEY_AGREEMENT = 2048,
+ KEY_CERT_SIGN = 1024,
+ CRL_SIGN = 512,
+ ENCIPHER_ONLY = 256,
+ DECIPHER_ONLY = 128
+};
+
+/**
+* BER Decoding Function for key constraints
+*/
+namespace BER {
+
+void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&);
+
+}
+
+/**
+* X.509v2 CRL Reason Code.
+*/
+enum CRL_Code {
+ UNSPECIFIED = 0,
+ KEY_COMPROMISE = 1,
+ CA_COMPROMISE = 2,
+ AFFILIATION_CHANGED = 3,
+ SUPERSEDED = 4,
+ CESSATION_OF_OPERATION = 5,
+ CERTIFICATE_HOLD = 6,
+ REMOVE_FROM_CRL = 8,
+ PRIVLEDGE_WITHDRAWN = 9,
+ AA_COMPROMISE = 10,
+
+ DELETE_CRL_ENTRY = 0xFF00,
+ OCSP_GOOD = 0xFF01,
+ OCSP_UNKNOWN = 0xFF02
+};
+
+/*
+* Various Other Enumerations
+*/
+
+/**
+* The two types of X509 encoding supported by Botan.
+*/
+enum X509_Encoding { RAW_BER, PEM };
+
+/**
+* Value to encode in case of no path limit in the X509
+* BasicConstraints extension.
+*/
+static const u32bit NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
+
+}
+
+#endif
diff --git a/botan/src/pubkey/rsa/info.txt b/botan/src/pubkey/rsa/info.txt
new file mode 100644
index 0000000..7729fd8
--- /dev/null
+++ b/botan/src/pubkey/rsa/info.txt
@@ -0,0 +1,17 @@
+realname "RSA"
+
+define RSA
+
+load_on auto
+
+<add>
+rsa.cpp
+rsa.h
+</add>
+
+<requires>
+if_algo
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/rsa/rsa.cpp b/botan/src/pubkey/rsa/rsa.cpp
new file mode 100644
index 0000000..83e6e1b
--- /dev/null
+++ b/botan/src/pubkey/rsa/rsa.cpp
@@ -0,0 +1,164 @@
+/*
+* RSA
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rsa.h>
+#include <botan/parsing.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+
+namespace Botan {
+
+/*
+* RSA_PublicKey Constructor
+*/
+RSA_PublicKey::RSA_PublicKey(const BigInt& mod, const BigInt& exp)
+ {
+ n = mod;
+ e = exp;
+ X509_load_hook();
+ }
+
+/*
+* RSA Public Operation
+*/
+BigInt RSA_PublicKey::public_op(const BigInt& i) const
+ {
+ if(i >= n)
+ throw Invalid_Argument(algo_name() + "::public_op: input is too large");
+ return core.public_op(i);
+ }
+
+/*
+* RSA Encryption Function
+*/
+SecureVector<byte> RSA_PublicKey::encrypt(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode_1363(public_op(i), n.bytes());
+ }
+
+/*
+* RSA Verification Function
+*/
+SecureVector<byte> RSA_PublicKey::verify(const byte in[], u32bit len) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode(public_op(i));
+ }
+
+/*
+* Create a RSA private key
+*/
+RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp)
+ {
+ if(bits < 512)
+ throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
+ to_string(bits) + " bits long");
+ if(exp < 3 || exp % 2 == 0)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ e = exp;
+ p = random_prime(rng, (bits + 1) / 2, e);
+ q = random_prime(rng, bits - p.bits(), e);
+ d = inverse_mod(e, lcm(p - 1, q - 1));
+
+ PKCS8_load_hook(rng, true);
+
+ if(n.bits() != bits)
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+/*
+* RSA_PrivateKey Constructor
+*/
+RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& prime1, const BigInt& prime2,
+ const BigInt& exp, const BigInt& d_exp,
+ const BigInt& mod)
+ {
+ p = prime1;
+ q = prime2;
+ e = exp;
+ d = d_exp;
+ n = mod;
+
+ if(d == 0)
+ d = inverse_mod(e, lcm(p - 1, q - 1));
+
+ PKCS8_load_hook(rng);
+ }
+
+/*
+* RSA Private Operation
+*/
+BigInt RSA_PrivateKey::private_op(const byte in[], u32bit length) const
+ {
+ BigInt i(in, length);
+ if(i >= n)
+ throw Invalid_Argument(algo_name() + "::private_op: input is too large");
+
+ BigInt r = core.private_op(i);
+ if(i != public_op(r))
+ throw Self_Test_Failure(algo_name() + " private operation check failed");
+ return r;
+ }
+
+/*
+* RSA Decryption Operation
+*/
+SecureVector<byte> RSA_PrivateKey::decrypt(const byte in[], u32bit len) const
+ {
+ return BigInt::encode(private_op(in, len));
+ }
+
+/*
+* RSA Signature Operation
+*/
+SecureVector<byte> RSA_PrivateKey::sign(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ return BigInt::encode_1363(private_op(in, len), n.bytes());
+ }
+
+/*
+* Check Private RSA Parameters
+*/
+bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!IF_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if((e * d) % lcm(p - 1, q - 1) != 1)
+ return false;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_encryptor(*this, "EME1(SHA-1)"),
+ get_pk_decryptor(*this, "EME1(SHA-1)")
+ );
+
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA4(SHA-1)"),
+ get_pk_verifier(*this, "EMSA4(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/rsa/rsa.h b/botan/src/pubkey/rsa/rsa.h
new file mode 100644
index 0000000..f07533a
--- /dev/null
+++ b/botan/src/pubkey/rsa/rsa.h
@@ -0,0 +1,88 @@
+/*
+* RSA
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RSA_H__
+#define BOTAN_RSA_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/**
+* RSA Public Key
+*/
+class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key,
+ public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RSA"; }
+
+ SecureVector<byte> encrypt(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RSA_PublicKey() {}
+ RSA_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/**
+* RSA Private Key class.
+*/
+class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey,
+ public PK_Decrypting_Key,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator&) const;
+
+ SecureVector<byte> decrypt(const byte[], u32bit) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ /**
+ * Default constructor, does not set any internal values. Use this
+ * constructor if you wish to decode a DER or PEM encoded key.
+ */
+ RSA_PrivateKey() {}
+
+ /**
+ * Construct a private key from the specified parameters.
+ * @param rng the random number generator to use
+ * @param prime1 the first prime
+ * @param prime2 the second prime
+ * @param exp the exponent
+ * @param d_exp if specified, this has to be d with
+ * exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to
+ * the constructor to calculate it.
+ * @param n if specified, this must be n = p * q. Leave it as 0
+ * if you wish to the constructor to calculate it.
+ */
+ RSA_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& p, const BigInt& q, const BigInt& e,
+ const BigInt& d = 0, const BigInt& n = 0);
+
+ /**
+ * Create a new private key with the specified bit length
+ * @param rng the random number generator to use
+ * @param bits the desired bit length of the private key
+ * @param exp the public exponent to be used
+ */
+ RSA_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp = 65537);
+ private:
+ BigInt private_op(const byte[], u32bit) const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/pubkey/rw/info.txt b/botan/src/pubkey/rw/info.txt
new file mode 100644
index 0000000..ada6c37
--- /dev/null
+++ b/botan/src/pubkey/rw/info.txt
@@ -0,0 +1,17 @@
+realname "Rabin-Williams"
+
+define RW
+
+load_on auto
+
+<add>
+rw.cpp
+rw.h
+</add>
+
+<requires>
+if_algo
+keypair
+libstate
+numbertheory
+</requires>
diff --git a/botan/src/pubkey/rw/rw.cpp b/botan/src/pubkey/rw/rw.cpp
new file mode 100644
index 0000000..def0ae6
--- /dev/null
+++ b/botan/src/pubkey/rw/rw.cpp
@@ -0,0 +1,148 @@
+/*
+* Rabin-Williams
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rw.h>
+#include <botan/numthry.h>
+#include <botan/keypair.h>
+#include <botan/look_pk.h>
+#include <botan/parsing.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* RW_PublicKey Constructor
+*/
+RW_PublicKey::RW_PublicKey(const BigInt& mod, const BigInt& exp)
+ {
+ n = mod;
+ e = exp;
+ X509_load_hook();
+ }
+
+/*
+* Rabin-Williams Public Operation
+*/
+BigInt RW_PublicKey::public_op(const BigInt& i) const
+ {
+ if((i > (n >> 1)) || i.is_negative())
+ throw Invalid_Argument(algo_name() + "::public_op: i > n / 2 || i < 0");
+
+ BigInt r = core.public_op(i);
+ if(r % 16 == 12) return r;
+ if(r % 8 == 6) return 2*r;
+
+ r = n - r;
+ if(r % 16 == 12) return r;
+ if(r % 8 == 6) return 2*r;
+
+ throw Invalid_Argument(algo_name() + "::public_op: Invalid input");
+ }
+
+/*
+* Rabin-Williams Verification Function
+*/
+SecureVector<byte> RW_PublicKey::verify(const byte in[], u32bit len) const
+ {
+ BigInt i(in, len);
+ return BigInt::encode(public_op(i));
+ }
+
+/*
+* Create a Rabin-Williams private key
+*/
+RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng,
+ u32bit bits, u32bit exp)
+ {
+ if(bits < 512)
+ throw Invalid_Argument(algo_name() + ": Can't make a key that is only " +
+ to_string(bits) + " bits long");
+ if(exp < 2 || exp % 2 == 1)
+ throw Invalid_Argument(algo_name() + ": Invalid encryption exponent");
+
+ e = exp;
+ p = random_prime(rng, (bits + 1) / 2, e / 2, 3, 4);
+ q = random_prime(rng, bits - p.bits(), e / 2, ((p % 8 == 3) ? 7 : 3), 8);
+ d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
+
+ PKCS8_load_hook(rng, true);
+
+ if(n.bits() != bits)
+ throw Self_Test_Failure(algo_name() + " private key generation failed");
+ }
+
+/*
+* RW_PrivateKey Constructor
+*/
+RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng,
+ const BigInt& prime1, const BigInt& prime2,
+ const BigInt& exp, const BigInt& d_exp,
+ const BigInt& mod)
+ {
+ p = prime1;
+ q = prime2;
+ e = exp;
+ d = d_exp;
+ n = mod;
+
+ if(d == 0)
+ d = inverse_mod(e, lcm(p - 1, q - 1) >> 1);
+
+ PKCS8_load_hook(rng);
+ }
+
+/*
+* Rabin-Williams Signature Operation
+*/
+SecureVector<byte> RW_PrivateKey::sign(const byte in[], u32bit len,
+ RandomNumberGenerator&) const
+ {
+ BigInt i(in, len);
+ if(i >= n || i % 16 != 12)
+ throw Invalid_Argument(algo_name() + "::sign: Invalid input");
+
+ BigInt r;
+ if(jacobi(i, n) == 1) r = core.private_op(i);
+ else r = core.private_op(i >> 1);
+
+ r = std::min(r, n - r);
+ if(i != public_op(r))
+ throw Self_Test_Failure(algo_name() + " private operation check failed");
+
+ return BigInt::encode_1363(r, n.bytes());
+ }
+
+/*
+* Check Private Rabin-Williams Parameters
+*/
+bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!IF_Scheme_PrivateKey::check_key(rng, strong))
+ return false;
+
+ if(!strong)
+ return true;
+
+ if((e * d) % (lcm(p - 1, q - 1) / 2) != 1)
+ return false;
+
+ try
+ {
+ KeyPair::check_key(rng,
+ get_pk_signer(*this, "EMSA2(SHA-1)"),
+ get_pk_verifier(*this, "EMSA2(SHA-1)")
+ );
+ }
+ catch(Self_Test_Failure)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/pubkey/rw/rw.h b/botan/src/pubkey/rw/rw.h
new file mode 100644
index 0000000..900e5eb
--- /dev/null
+++ b/botan/src/pubkey/rw/rw.h
@@ -0,0 +1,56 @@
+/*
+* Rabin-Williams
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RW_H__
+#define BOTAN_RW_H__
+
+#include <botan/if_algo.h>
+
+namespace Botan {
+
+/*
+* Rabin-Williams Public Key
+*/
+class BOTAN_DLL RW_PublicKey : public PK_Verifying_with_MR_Key,
+ public virtual IF_Scheme_PublicKey
+ {
+ public:
+ std::string algo_name() const { return "RW"; }
+
+ SecureVector<byte> verify(const byte[], u32bit) const;
+
+ RW_PublicKey() {}
+ RW_PublicKey(const BigInt&, const BigInt&);
+ protected:
+ BigInt public_op(const BigInt&) const;
+ };
+
+/*
+* Rabin-Williams Private Key
+*/
+class BOTAN_DLL RW_PrivateKey : public RW_PublicKey,
+ public PK_Signing_Key,
+ public IF_Scheme_PrivateKey
+ {
+ public:
+ SecureVector<byte> sign(const byte[], u32bit,
+ RandomNumberGenerator& rng) const;
+
+ bool check_key(RandomNumberGenerator& rng, bool) const;
+
+ RW_PrivateKey() {}
+
+ RW_PrivateKey(RandomNumberGenerator&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt& = 0, const BigInt& = 0);
+
+ RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2);
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/auto_rng/auto_rng.cpp b/botan/src/rng/auto_rng/auto_rng.cpp
new file mode 100644
index 0000000..8405170
--- /dev/null
+++ b/botan/src/rng/auto_rng/auto_rng.cpp
@@ -0,0 +1,158 @@
+/*
+* Auto Seeded RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/auto_rng.h>
+#include <botan/parsing.h>
+#include <botan/timer.h>
+#include <botan/hmac.h>
+#include <botan/sha2_32.h>
+#include <botan/sha2_64.h>
+
+#if defined(BOTAN_HAS_RANDPOOL)
+ #include <botan/randpool.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC_RNG)
+ #include <botan/hmac_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_X931_RNG)
+ #include <botan/x931_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ #include <botan/tm_hard.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ #include <botan/tm_posix.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_UNIX)
+ #include <botan/tm_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_WIN32)
+ #include <botan/tm_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ #include <botan/es_dev.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ #include <botan/es_egd.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ #include <botan/es_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ #include <botan/es_beos.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ #include <botan/es_capi.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ #include <botan/es_ftw.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/**
+* Add any known entropy sources to this RNG
+*/
+void add_entropy_sources(RandomNumberGenerator* rng)
+ {
+
+ // Add a high resolution timer, if available
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ rng->add_entropy_source(new Hardware_Timer);
+#elif defined(BOTAN_HAS_TIMER_POSIX)
+ rng->add_entropy_source(new POSIX_Timer);
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ rng->add_entropy_source(new Unix_Timer);
+#elif defined(BOTAN_HAS_TIMER_WIN32)
+ rng->add_entropy_source(new Win32_Timer);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ rng->add_entropy_source(
+ new Device_EntropySource(
+ split_on("/dev/urandom:/dev/random:/dev/srandom", ':')
+ )
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ rng->add_entropy_source(
+ new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
+ );
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ rng->add_entropy_source(new Win32_CAPI_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ rng->add_entropy_source(new FTW_EntropySource("/proc"));
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ rng->add_entropy_source(new Win32_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ rng->add_entropy_source(new BeOS_EntropySource);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ rng->add_entropy_source(
+ new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
+ );
+#endif
+ }
+
+}
+
+AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
+ {
+ rng = 0;
+
+#if defined(BOTAN_HAS_HMAC_RNG)
+ rng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
+#elif defined(BOTAN_HAS_RANDPOOL) && defined(BOTAN_HAS_AES)
+ rng = new Randpool(new AES_256, new HMAC(new SHA_256));
+#endif
+
+ if(!rng)
+ throw Algorithm_Not_Found("No usable RNG found enabled in build");
+
+ /* If X9.31 is available, use it to wrap the other RNG as a failsafe */
+#if defined(BOTAN_HAS_X931_RNG) && defined(BOTAN_HAS_AES)
+ rng = new ANSI_X931_RNG(new AES_256, rng);
+#endif
+
+ add_entropy_sources(rng);
+
+ rng->reseed(poll_bits);
+ }
+
+}
diff --git a/botan/src/rng/auto_rng/auto_rng.h b/botan/src/rng/auto_rng/auto_rng.h
new file mode 100644
index 0000000..f18f8e5
--- /dev/null
+++ b/botan/src/rng/auto_rng/auto_rng.h
@@ -0,0 +1,44 @@
+/*
+* Auto Seeded RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AUTO_SEEDING_RNG_H__
+#define BOTAN_AUTO_SEEDING_RNG_H__
+
+#include <botan/rng.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* RNG that attempts to seed itself
+*/
+class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte out[], u32bit len)
+ { rng->randomize(out, len); }
+ bool is_seeded() const
+ { return rng->is_seeded(); }
+ void clear() throw() { rng->clear(); }
+ std::string name() const
+ { return "AutoSeeded(" + rng->name() + ")"; }
+
+ void reseed(u32bit poll_bits = 256) { rng->reseed(poll_bits); }
+ void add_entropy_source(EntropySource* es)
+ { rng->add_entropy_source(es); }
+ void add_entropy(const byte in[], u32bit len)
+ { rng->add_entropy(in, len); }
+
+ AutoSeeded_RNG(u32bit poll_bits = 256);
+ ~AutoSeeded_RNG() { delete rng; }
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/auto_rng/info.txt b/botan/src/rng/auto_rng/info.txt
new file mode 100644
index 0000000..7d5d5dd
--- /dev/null
+++ b/botan/src/rng/auto_rng/info.txt
@@ -0,0 +1,16 @@
+realname "Auto-seeded Random Number Generator"
+
+define AUTO_SEEDING_RNG
+
+load_on auto
+
+<add>
+auto_rng.h
+auto_rng.cpp
+</add>
+
+<requires>
+hmac
+sha2
+timer
+</requires>
diff --git a/botan/src/rng/hmac_rng/hmac_rng.cpp b/botan/src/rng/hmac_rng/hmac_rng.cpp
new file mode 100644
index 0000000..113489d
--- /dev/null
+++ b/botan/src/rng/hmac_rng/hmac_rng.cpp
@@ -0,0 +1,223 @@
+/*
+* HMAC_RNG
+* (C) 2008-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hmac_rng.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+#include <botan/util.h>
+#include <botan/stl_util.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+void hmac_prf(MessageAuthenticationCode* prf,
+ MemoryRegion<byte>& K,
+ u32bit& counter,
+ const std::string& label)
+ {
+ prf->update(K, K.size());
+ prf->update(label);
+ for(u32bit i = 0; i != 4; ++i)
+ prf->update(get_byte(i, counter));
+ prf->final(K);
+
+ ++counter;
+ }
+
+}
+
+/**
+* Generate a buffer of random bytes
+*/
+void HMAC_RNG::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ /*
+ HMAC KDF as described in E-t-E, using a CTXinfo of "rng"
+ */
+ while(length)
+ {
+ hmac_prf(prf, K, counter, "rng");
+
+ const u32bit copied = std::min(K.size(), length);
+
+ copy_mem(out, K.begin(), copied);
+ out += copied;
+ length -= copied;
+ }
+ }
+
+/**
+* Reseed the internal state, also accepting user input to include
+*/
+void HMAC_RNG::reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit input_length)
+ {
+ /**
+ Using the terminology of E-t-E, XTR is the MAC function (normally
+ HMAC) seeded with XTS (below) and we form SKM, the key material, by
+ fast polling each source, and then slow polling as many as we think
+ we need (in the following loop), and feeding all of the poll
+ results, along with any optional user input, along with, finally,
+ feedback of the current PRK value, into the extractor function.
+ */
+
+ Entropy_Accumulator_BufferedComputation accum(*extractor, poll_bits);
+
+ if(!entropy_sources.empty())
+ {
+ u32bit poll_attempt = 0;
+
+ while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
+ {
+ entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
+ ++poll_attempt;
+ }
+ }
+
+ // And now add the user-provided input, if any
+ if(input_length)
+ accum.add(input, input_length, 1);
+
+ /*
+ It is necessary to feed forward poll data. Otherwise, a good poll
+ (collecting a large amount of conditional entropy) followed by a
+ bad one (collecting little) would be unsafe. Do this by generating
+ new PRF outputs using the previous key and feeding them into the
+ extractor function.
+
+ Cycle the RNG once (CTXinfo="rng"), then generate a new PRF output
+ using the CTXinfo "reseed". Provide these values as input to the
+ extractor function.
+ */
+ hmac_prf(prf, K, counter, "rng");
+ extractor->update(K); // K is the CTXinfo=rng PRF output
+
+ hmac_prf(prf, K, counter, "reseed");
+ extractor->update(K); // K is the CTXinfo=reseed PRF output
+
+ /* Now derive the new PRK using everything that has been fed into
+ the extractor, and set the PRF key to that */
+ prf->set_key(extractor->final());
+
+ // Now generate a new PRF output to use as the XTS extractor salt
+ hmac_prf(prf, K, counter, "xts");
+ extractor->set_key(K, K.size());
+
+ // Reset state
+ K.clear();
+ counter = 0;
+
+ if(input_length || accum.bits_collected() >= poll_bits)
+ seeded = true;
+ }
+
+/**
+* Reseed the internal state
+*/
+void HMAC_RNG::reseed(u32bit poll_bits)
+ {
+ reseed_with_input(poll_bits, 0, 0);
+ }
+
+/**
+* Add user-supplied entropy by reseeding and including this
+* input among the poll data
+*/
+void HMAC_RNG::add_entropy(const byte input[], u32bit length)
+ {
+ reseed_with_input(0, input, length);
+ }
+
+/**
+* Add another entropy source to the list
+*/
+void HMAC_RNG::add_entropy_source(EntropySource* src)
+ {
+ entropy_sources.push_back(src);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HMAC_RNG::clear() throw()
+ {
+ extractor->clear();
+ prf->clear();
+ K.clear();
+ counter = 0;
+ seeded = false;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string HMAC_RNG::name() const
+ {
+ return "HMAC_RNG(" + extractor->name() + "," + prf->name() + ")";
+ }
+
+/**
+* HMAC_RNG Constructor
+*/
+HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
+ MessageAuthenticationCode* prf_mac) :
+ extractor(extractor_mac), prf(prf_mac)
+ {
+ // First PRF inputs are all zero, as specified in section 2
+ K.create(prf->OUTPUT_LENGTH);
+ counter = 0;
+ seeded = false;
+
+ /*
+ Normally we want to feedback PRF output into the input to the
+ extractor function to ensure a single bad poll does not damage the
+ RNG, but obviously that is meaningless to do on the first poll.
+
+ We will want to use the PRF before we set the first key (in
+ reseed_with_input), and it is a pain to keep track if it is set or
+ not. Since the first time it doesn't matter anyway, just set it to
+ a constant: randomize() will not produce output unless is_seeded()
+ returns true, and that will only be the case if the estimated
+ entropy counter is high enough. That variable is only set when a
+ reseeding is performed.
+ */
+ std::string prf_key = "Botan HMAC_RNG PRF";
+ prf->set_key(reinterpret_cast<const byte*>(prf_key.c_str()),
+ prf_key.length());
+
+ /*
+ This will be used as the first XTS value when extracting input.
+ XTS values after this one are generated using the PRF.
+
+ If I understand the E-t-E paper correctly (specifically Section 4),
+ using this fixed extractor key is safe to do.
+ */
+ std::string xts = "Botan HMAC_RNG XTS";
+ extractor->set_key(reinterpret_cast<const byte*>(xts.c_str()),
+ xts.length());
+ }
+
+/**
+* HMAC_RNG Destructor
+*/
+HMAC_RNG::~HMAC_RNG()
+ {
+ delete extractor;
+ delete prf;
+
+ std::for_each(entropy_sources.begin(), entropy_sources.end(),
+ del_fun<EntropySource>());
+
+ counter = 0;
+ }
+
+}
diff --git a/botan/src/rng/hmac_rng/hmac_rng.h b/botan/src/rng/hmac_rng/hmac_rng.h
new file mode 100644
index 0000000..318e2a9
--- /dev/null
+++ b/botan/src/rng/hmac_rng/hmac_rng.h
@@ -0,0 +1,59 @@
+/*
+* HMAC RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_RNG_H__
+#define BOTAN_HMAC_RNG_H__
+
+#include <botan/mac.h>
+#include <botan/rng.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+HMAC_RNG - based on the design described in "On Extract-then-Expand
+Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk
+(henceforce, 'E-t-E')
+
+However it actually can be parameterized with any two MAC functions,
+not restricted to HMAC (this variation is also described in Krawczyk's
+paper), for instance one could use HMAC(SHA-512) as the extractor
+and CMAC(AES-256) as the PRF.
+*/
+class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte buf[], u32bit len);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte[], u32bit);
+
+ HMAC_RNG(MessageAuthenticationCode* extractor,
+ MessageAuthenticationCode* prf);
+
+ ~HMAC_RNG();
+ private:
+ void reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit length);
+
+ MessageAuthenticationCode* extractor;
+ MessageAuthenticationCode* prf;
+
+ std::vector<EntropySource*> entropy_sources;
+ bool seeded;
+
+ SecureVector<byte> K, io_buffer;
+ u32bit counter, source_index;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/hmac_rng/info.txt b/botan/src/rng/hmac_rng/info.txt
new file mode 100644
index 0000000..2c7f13e
--- /dev/null
+++ b/botan/src/rng/hmac_rng/info.txt
@@ -0,0 +1,14 @@
+realname "HMAC RNG"
+
+define HMAC_RNG
+
+load_on auto
+
+<add>
+hmac_rng.cpp
+hmac_rng.h
+</add>
+
+<requires>
+mac
+</requires>
diff --git a/botan/src/rng/info.txt b/botan/src/rng/info.txt
new file mode 100644
index 0000000..44a4166
--- /dev/null
+++ b/botan/src/rng/info.txt
@@ -0,0 +1,12 @@
+realname "Random Number Generators"
+
+load_on auto
+
+<add>
+rng.cpp
+rng.h
+</add>
+
+<requires>
+entropy
+</requires>
diff --git a/botan/src/rng/randpool/info.txt b/botan/src/rng/randpool/info.txt
new file mode 100644
index 0000000..cc7f615
--- /dev/null
+++ b/botan/src/rng/randpool/info.txt
@@ -0,0 +1,15 @@
+realname "Randpool RNG"
+
+define RANDPOOL
+
+load_on auto
+
+<add>
+randpool.cpp
+randpool.h
+</add>
+
+<requires>
+block
+mac
+</requires>
diff --git a/botan/src/rng/randpool/randpool.cpp b/botan/src/rng/randpool/randpool.cpp
new file mode 100644
index 0000000..4d7b92d
--- /dev/null
+++ b/botan/src/rng/randpool/randpool.cpp
@@ -0,0 +1,214 @@
+/*
+* Randpool
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/randpool.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+#include <botan/util.h>
+#include <botan/stl_util.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/**
+* PRF based on a MAC
+*/
+enum RANDPOOL_PRF_TAG {
+ CIPHER_KEY = 0,
+ MAC_KEY = 1,
+ GEN_OUTPUT = 2
+};
+
+}
+
+/**
+* Generate a buffer of random bytes
+*/
+void Randpool::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ update_buffer();
+ while(length)
+ {
+ const u32bit copied = std::min(length, buffer.size());
+ copy_mem(out, buffer.begin(), copied);
+ out += copied;
+ length -= copied;
+ update_buffer();
+ }
+ }
+
+/**
+* Refill the output buffer
+*/
+void Randpool::update_buffer()
+ {
+ const u64bit timestamp = system_time();
+
+ for(u32bit i = 0; i != counter.size(); ++i)
+ if(++counter[i])
+ break;
+ store_be(timestamp, counter + 4);
+
+ mac->update(static_cast<byte>(GEN_OUTPUT));
+ mac->update(counter, counter.size());
+ SecureVector<byte> mac_val = mac->final();
+
+ for(u32bit i = 0; i != mac_val.size(); ++i)
+ buffer[i % buffer.size()] ^= mac_val[i];
+ cipher->encrypt(buffer);
+
+ if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
+ mix_pool();
+ }
+
+/**
+* Mix the entropy pool
+*/
+void Randpool::mix_pool()
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ mac->update(static_cast<byte>(MAC_KEY));
+ mac->update(pool, pool.size());
+ mac->set_key(mac->final());
+
+ mac->update(static_cast<byte>(CIPHER_KEY));
+ mac->update(pool, pool.size());
+ cipher->set_key(mac->final());
+
+ xor_buf(pool, buffer, BLOCK_SIZE);
+ cipher->encrypt(pool);
+ for(u32bit i = 1; i != POOL_BLOCKS; ++i)
+ {
+ const byte* previous_block = pool + BLOCK_SIZE*(i-1);
+ byte* this_block = pool + BLOCK_SIZE*i;
+ xor_buf(this_block, previous_block, BLOCK_SIZE);
+ cipher->encrypt(this_block);
+ }
+
+ update_buffer();
+ }
+
+/**
+* Reseed the internal state
+*/
+void Randpool::reseed(u32bit poll_bits)
+ {
+ Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits);
+
+ if(!entropy_sources.empty())
+ {
+ u32bit poll_attempt = 0;
+
+ while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
+ {
+ entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
+ ++poll_attempt;
+ }
+ }
+
+ SecureVector<byte> mac_val = mac->final();
+
+ xor_buf(pool, mac_val, mac_val.size());
+ mix_pool();
+
+ if(accum.bits_collected() >= poll_bits)
+ seeded = true;
+ }
+
+/**
+* Add user-supplied entropy
+*/
+void Randpool::add_entropy(const byte input[], u32bit length)
+ {
+ SecureVector<byte> mac_val = mac->process(input, length);
+ xor_buf(pool, mac_val, mac_val.size());
+ mix_pool();
+
+ if(length)
+ seeded = true;
+ }
+
+/**
+* Add another entropy source to the list
+*/
+void Randpool::add_entropy_source(EntropySource* src)
+ {
+ entropy_sources.push_back(src);
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void Randpool::clear() throw()
+ {
+ cipher->clear();
+ mac->clear();
+ pool.clear();
+ buffer.clear();
+ counter.clear();
+ seeded = false;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string Randpool::name() const
+ {
+ return "Randpool(" + cipher->name() + "," + mac->name() + ")";
+ }
+
+/**
+* Randpool Constructor
+*/
+Randpool::Randpool(BlockCipher* cipher_in,
+ MessageAuthenticationCode* mac_in,
+ u32bit pool_blocks,
+ u32bit iter_before_reseed) :
+ ITERATIONS_BEFORE_RESEED(iter_before_reseed),
+ POOL_BLOCKS(pool_blocks),
+ cipher(cipher_in),
+ mac(mac_in)
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ const u32bit OUTPUT_LENGTH = mac->OUTPUT_LENGTH;
+
+ if(OUTPUT_LENGTH < BLOCK_SIZE ||
+ !cipher->valid_keylength(OUTPUT_LENGTH) ||
+ !mac->valid_keylength(OUTPUT_LENGTH))
+ {
+ std::string ciphername = cipher->name(), macname = mac->name();
+ delete cipher;
+ delete mac;
+ throw Internal_Error("Randpool: Invalid algorithm combination " +
+ ciphername + "/" + macname);
+ }
+
+ buffer.create(BLOCK_SIZE);
+ pool.create(POOL_BLOCKS * BLOCK_SIZE);
+ counter.create(12);
+ seeded = false;
+ }
+
+/**
+* Randpool Destructor
+*/
+Randpool::~Randpool()
+ {
+ delete cipher;
+ delete mac;
+
+ std::for_each(entropy_sources.begin(), entropy_sources.end(),
+ del_fun<EntropySource>());
+ }
+
+}
diff --git a/botan/src/rng/randpool/randpool.h b/botan/src/rng/randpool/randpool.h
new file mode 100644
index 0000000..b6a3add
--- /dev/null
+++ b/botan/src/rng/randpool/randpool.h
@@ -0,0 +1,53 @@
+/*
+* Randpool
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDPOOL_H__
+#define BOTAN_RANDPOOL_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+#include <botan/mac.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Randpool
+*/
+class BOTAN_DLL Randpool : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit bits_to_collect);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte input[], u32bit length);
+
+ Randpool(BlockCipher* cipher, MessageAuthenticationCode* mac,
+ u32bit pool_blocks = 32,
+ u32bit iterations_before_reseed = 128);
+
+ ~Randpool();
+ private:
+ void update_buffer();
+ void mix_pool();
+
+ u32bit ITERATIONS_BEFORE_RESEED, POOL_BLOCKS;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+
+ std::vector<EntropySource*> entropy_sources;
+ SecureVector<byte> pool, buffer, counter;
+ bool seeded;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/rng.cpp b/botan/src/rng/rng.cpp
new file mode 100644
index 0000000..aa9b73f
--- /dev/null
+++ b/botan/src/rng/rng.cpp
@@ -0,0 +1,38 @@
+/*
+* Random Number Generator Base
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ #include <botan/auto_rng.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get a single random byte
+*/
+byte RandomNumberGenerator::next_byte()
+ {
+ byte out;
+ this->randomize(&out, 1);
+ return out;
+ }
+
+/*
+* Create and seed a new RNG object
+*/
+RandomNumberGenerator* RandomNumberGenerator::make_rng()
+ {
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ return new AutoSeeded_RNG;
+#endif
+
+ throw Algorithm_Not_Found("RandomNumberGenerator::make_rng - no RNG found");
+ }
+
+}
diff --git a/botan/src/rng/rng.h b/botan/src/rng/rng.h
new file mode 100644
index 0000000..41904db
--- /dev/null
+++ b/botan/src/rng/rng.h
@@ -0,0 +1,103 @@
+/*
+* RandomNumberGenerator
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__
+#define BOTAN_RANDOM_NUMBER_GENERATOR_H__
+
+#include <botan/entropy_src.h>
+#include <botan/exceptn.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a random number (RNG) generator object.
+*/
+class BOTAN_DLL RandomNumberGenerator
+ {
+ public:
+ /**
+ * Create a seeded and active RNG object for general application use
+ */
+ static RandomNumberGenerator* make_rng();
+
+ /**
+ * Randomize a byte array.
+ * @param output the byte array to hold the random output.
+ * @param length the length of the byte array output.
+ */
+ virtual void randomize(byte output[], u32bit length) = 0;
+
+ /**
+ * Return a random byte
+ * @return random byte
+ */
+ byte next_byte();
+
+ /**
+ * Check whether this RNG is seeded.
+ * @return true if this RNG was already seeded, false otherwise.
+ */
+ virtual bool is_seeded() const { return true; }
+
+ /**
+ * Clear all internally held values of this RNG.
+ */
+ virtual void clear() throw() = 0;
+
+ /**
+ * Return the name of this object
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Seed this RNG using the entropy sources it contains.
+ * @param bits_to_collect is the number of bits of entropy to
+ attempt to gather from the entropy sources
+ */
+ virtual void reseed(u32bit bits_to_collect) = 0;
+
+ /**
+ * Add this entropy source to the RNG object
+ * @param source the entropy source which will be retained and used by RNG
+ */
+ virtual void add_entropy_source(EntropySource* source) = 0;
+
+ /**
+ * Add entropy to this RNG.
+ * @param in a byte array containg the entropy to be added
+ * @param length the length of the byte array in
+ */
+ virtual void add_entropy(const byte in[], u32bit length) = 0;
+
+ RandomNumberGenerator() {}
+ virtual ~RandomNumberGenerator() {}
+ private:
+ RandomNumberGenerator(const RandomNumberGenerator&) {}
+ RandomNumberGenerator& operator=(const RandomNumberGenerator&)
+ { return (*this); }
+ };
+
+/*
+* Null Random Number Generator
+*/
+class BOTAN_DLL Null_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit) { throw PRNG_Unseeded("Null_RNG"); }
+ void clear() throw() {}
+ std::string name() const { return "Null_RNG"; }
+
+ void reseed(u32bit) {}
+ bool is_seeded() const { return false; }
+ void add_entropy(const byte[], u32bit) {}
+ void add_entropy_source(EntropySource* es) { delete es; }
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/x931_rng/info.txt b/botan/src/rng/x931_rng/info.txt
new file mode 100644
index 0000000..633eb02
--- /dev/null
+++ b/botan/src/rng/x931_rng/info.txt
@@ -0,0 +1,14 @@
+realname "ANSI X9.31 PRNG"
+
+define X931_RNG
+
+load_on auto
+
+<add>
+x931_rng.cpp
+x931_rng.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/rng/x931_rng/x931_rng.cpp b/botan/src/rng/x931_rng/x931_rng.cpp
new file mode 100644
index 0000000..e239bce
--- /dev/null
+++ b/botan/src/rng/x931_rng/x931_rng.cpp
@@ -0,0 +1,154 @@
+/*
+* ANSI X9.31 RNG
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x931_rng.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/**
+* Generate a buffer of random bytes
+*/
+void ANSI_X931_RNG::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ while(length)
+ {
+ if(position == R.size())
+ update_buffer();
+
+ const u32bit copied = std::min(length, R.size() - position);
+
+ copy_mem(out, R + position, copied);
+ out += copied;
+ length -= copied;
+ position += copied;
+ }
+ }
+
+/**
+* Refill the internal state
+*/
+void ANSI_X931_RNG::update_buffer()
+ {
+ SecureVector<byte> DT(cipher->BLOCK_SIZE);
+
+ prng->randomize(DT, DT.size());
+ cipher->encrypt(DT);
+
+ xor_buf(R, V, DT, cipher->BLOCK_SIZE);
+ cipher->encrypt(R);
+
+ xor_buf(V, R, DT, cipher->BLOCK_SIZE);
+ cipher->encrypt(V);
+
+ position = 0;
+ }
+
+/**
+* Reset V and the cipher key with new values
+*/
+void ANSI_X931_RNG::rekey()
+ {
+ if(prng->is_seeded())
+ {
+ SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH);
+ prng->randomize(key, key.size());
+ cipher->set_key(key, key.size());
+
+ if(V.size() != cipher->BLOCK_SIZE)
+ V.create(cipher->BLOCK_SIZE);
+ prng->randomize(V, V.size());
+
+ update_buffer();
+ }
+ }
+
+/**
+* Reseed the internal state
+*/
+void ANSI_X931_RNG::reseed(u32bit poll_bits)
+ {
+ prng->reseed(poll_bits);
+ rekey();
+ }
+
+/**
+* Add a entropy source to the underlying PRNG
+*/
+void ANSI_X931_RNG::add_entropy_source(EntropySource* src)
+ {
+ prng->add_entropy_source(src);
+ }
+
+/**
+* Add some entropy to the underlying PRNG
+*/
+void ANSI_X931_RNG::add_entropy(const byte input[], u32bit length)
+ {
+ prng->add_entropy(input, length);
+ rekey();
+ }
+
+/**
+* Check if the the PRNG is seeded
+*/
+bool ANSI_X931_RNG::is_seeded() const
+ {
+ return V.has_items();
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void ANSI_X931_RNG::clear() throw()
+ {
+ cipher->clear();
+ prng->clear();
+ R.clear();
+ V.destroy();
+
+ position = 0;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string ANSI_X931_RNG::name() const
+ {
+ return "X9.31(" + cipher->name() + ")";
+ }
+
+/**
+* ANSI X931 RNG Constructor
+*/
+ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
+ RandomNumberGenerator* prng_in)
+ {
+ if(!prng_in || !cipher_in)
+ throw Invalid_Argument("ANSI_X931_RNG constructor: NULL arguments");
+
+ cipher = cipher_in;
+ prng = prng_in;
+
+ R.create(cipher->BLOCK_SIZE);
+ position = 0;
+ }
+
+/**
+* ANSI X931 RNG Destructor
+*/
+ANSI_X931_RNG::~ANSI_X931_RNG()
+ {
+ delete cipher;
+ delete prng;
+ }
+
+}
diff --git a/botan/src/rng/x931_rng/x931_rng.h b/botan/src/rng/x931_rng/x931_rng.h
new file mode 100644
index 0000000..44e9b44
--- /dev/null
+++ b/botan/src/rng/x931_rng/x931_rng.h
@@ -0,0 +1,45 @@
+/*
+* ANSI X9.31 RNG
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X931_RNG_H__
+#define BOTAN_ANSI_X931_RNG_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* ANSI X9.31 RNG
+*/
+class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const;
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource*);
+ void add_entropy(const byte[], u32bit);
+
+ ANSI_X931_RNG(BlockCipher*, RandomNumberGenerator*);
+ ~ANSI_X931_RNG();
+ private:
+ void rekey();
+ void update_buffer();
+
+ BlockCipher* cipher;
+ RandomNumberGenerator* prng;
+ SecureVector<byte> V, R;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/s2k/info.txt b/botan/src/s2k/info.txt
new file mode 100644
index 0000000..e603fd9
--- /dev/null
+++ b/botan/src/s2k/info.txt
@@ -0,0 +1,13 @@
+realname "String to Key Functions"
+
+load_on auto
+
+<add>
+s2k.cpp
+s2k.h
+</add>
+
+<requires>
+rng
+sym_algo
+</requires>
diff --git a/botan/src/s2k/pbkdf1/info.txt b/botan/src/s2k/pbkdf1/info.txt
new file mode 100644
index 0000000..4c5b275
--- /dev/null
+++ b/botan/src/s2k/pbkdf1/info.txt
@@ -0,0 +1,14 @@
+realname "Pbkdf1"
+
+define PBKDF1
+
+load_on auto
+
+<add>
+pbkdf1.cpp
+pbkdf1.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/s2k/pbkdf1/pbkdf1.cpp b/botan/src/s2k/pbkdf1/pbkdf1.cpp
new file mode 100644
index 0000000..04e3aa4
--- /dev/null
+++ b/botan/src/s2k/pbkdf1/pbkdf1.cpp
@@ -0,0 +1,55 @@
+/*
+* PBKDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pbkdf1.h>
+
+namespace Botan {
+
+/*
+* Return a PKCS#5 PBKDF1 derived key
+*/
+OctetString PKCS5_PBKDF1::derive(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
+ {
+ if(iterations == 0)
+ throw Invalid_Argument("PKCS#5 PBKDF1: Invalid iteration count");
+
+ if(key_len > hash->OUTPUT_LENGTH)
+ throw Exception("PKCS#5 PBKDF1: Requested output length too long");
+
+ hash->update(passphrase);
+ hash->update(salt, salt_size);
+ SecureVector<byte> key = hash->final();
+
+ for(u32bit j = 1; j != iterations; ++j)
+ {
+ hash->update(key);
+ hash->final(key);
+ }
+
+ return OctetString(key, std::min(key_len, key.size()));
+ }
+
+/*
+* Clone this type
+*/
+S2K* PKCS5_PBKDF1::clone() const
+ {
+ return new PKCS5_PBKDF1(hash->clone());
+ }
+
+/*
+* Return the name of this type
+*/
+std::string PKCS5_PBKDF1::name() const
+ {
+ return "PBKDF1(" + hash->name() + ")";
+ }
+
+}
diff --git a/botan/src/s2k/pbkdf1/pbkdf1.h b/botan/src/s2k/pbkdf1/pbkdf1.h
new file mode 100644
index 0000000..4e5cafd
--- /dev/null
+++ b/botan/src/s2k/pbkdf1/pbkdf1.h
@@ -0,0 +1,44 @@
+/*
+* PBKDF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBKDF1_H__
+#define BOTAN_PBKDF1_H__
+
+#include <botan/s2k.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* This class implements the PKCS #5 PBKDF1 functionality.
+*/
+class BOTAN_DLL PKCS5_PBKDF1 : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ /**
+ * Create a PKCS #5 instance using the specified hash function.
+ * @param hash a pointer to a hash function object to use
+ */
+ PKCS5_PBKDF1(HashFunction* hash_in) : hash(hash_in) {}
+
+ PKCS5_PBKDF1(const PKCS5_PBKDF1& other) :
+ S2K(), hash(other.hash->clone()) {}
+
+ ~PKCS5_PBKDF1() { delete hash; }
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/s2k/pbkdf2/info.txt b/botan/src/s2k/pbkdf2/info.txt
new file mode 100644
index 0000000..921aeb1
--- /dev/null
+++ b/botan/src/s2k/pbkdf2/info.txt
@@ -0,0 +1,14 @@
+realname "Pbkdf2"
+
+define PBKDF2
+
+load_on auto
+
+<add>
+pbkdf2.cpp
+pbkdf2.h
+</add>
+
+<requires>
+mac
+</requires>
diff --git a/botan/src/s2k/pbkdf2/pbkdf2.cpp b/botan/src/s2k/pbkdf2/pbkdf2.cpp
new file mode 100644
index 0000000..1de27c9
--- /dev/null
+++ b/botan/src/s2k/pbkdf2/pbkdf2.cpp
@@ -0,0 +1,82 @@
+/*
+* PBKDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pbkdf2.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Return a PKCS#5 PBKDF2 derived key
+*/
+OctetString PKCS5_PBKDF2::derive(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
+ {
+ if(iterations == 0)
+ throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count");
+
+ if(passphrase.length() == 0)
+ throw Invalid_Argument("PKCS#5 PBKDF2: Empty passphrase is invalid");
+
+ mac->set_key(reinterpret_cast<const byte*>(passphrase.data()),
+ passphrase.length());
+
+ SecureVector<byte> key(key_len);
+
+ byte* T = key.begin();
+
+ u32bit counter = 1;
+ while(key_len)
+ {
+ u32bit T_size = std::min(mac->OUTPUT_LENGTH, key_len);
+ SecureVector<byte> U(mac->OUTPUT_LENGTH);
+
+ mac->update(salt, salt_size);
+ for(u32bit j = 0; j != 4; ++j)
+ mac->update(get_byte(j, counter));
+ mac->final(U);
+ xor_buf(T, U, T_size);
+
+ for(u32bit j = 1; j != iterations; ++j)
+ {
+ mac->update(U);
+ mac->final(U);
+ xor_buf(T, U, T_size);
+ }
+
+ key_len -= T_size;
+ T += T_size;
+ ++counter;
+ }
+
+ return key;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string PKCS5_PBKDF2::name() const
+ {
+ return "PBKDF2(" + mac->name() + ")";
+ }
+
+S2K* PKCS5_PBKDF2::clone() const
+ {
+ return new PKCS5_PBKDF2(mac->clone());
+ }
+
+/*
+* PKCS5_PBKDF2 Constructor
+*/
+PKCS5_PBKDF2::PKCS5_PBKDF2(MessageAuthenticationCode* m) : mac(m) {}
+
+PKCS5_PBKDF2::~PKCS5_PBKDF2() { delete mac; }
+
+}
diff --git a/botan/src/s2k/pbkdf2/pbkdf2.h b/botan/src/s2k/pbkdf2/pbkdf2.h
new file mode 100644
index 0000000..7510338
--- /dev/null
+++ b/botan/src/s2k/pbkdf2/pbkdf2.h
@@ -0,0 +1,40 @@
+/*
+* PBKDF2
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PBKDF2_H__
+#define BOTAN_PBKDF2_H__
+
+#include <botan/s2k.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/**
+* This class implements the PKCS #5 PBKDF2 functionality.
+*/
+class BOTAN_DLL PKCS5_PBKDF2 : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ /**
+ * Create a PKCS #5 instance using the specified message auth code
+ * @param mac the MAC to use
+ */
+ PKCS5_PBKDF2(MessageAuthenticationCode* mac);
+ ~PKCS5_PBKDF2();
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ MessageAuthenticationCode* mac;
+ };
+
+}
+
+#endif
diff --git a/botan/src/s2k/pgps2k/info.txt b/botan/src/s2k/pgps2k/info.txt
new file mode 100644
index 0000000..14b75a0
--- /dev/null
+++ b/botan/src/s2k/pgps2k/info.txt
@@ -0,0 +1,14 @@
+realname "Pgps2k"
+
+define PGPS2K
+
+load_on auto
+
+<add>
+pgp_s2k.cpp
+pgp_s2k.h
+</add>
+
+<requires>
+hash
+</requires>
diff --git a/botan/src/s2k/pgps2k/pgp_s2k.cpp b/botan/src/s2k/pgps2k/pgp_s2k.cpp
new file mode 100644
index 0000000..86394d8
--- /dev/null
+++ b/botan/src/s2k/pgps2k/pgp_s2k.cpp
@@ -0,0 +1,74 @@
+/*
+* OpenPGP S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/pgp_s2k.h>
+#include <algorithm>
+#include <memory>
+
+namespace Botan {
+
+/*
+* Derive a key using the OpenPGP S2K algorithm
+*/
+OctetString OpenPGP_S2K::derive(u32bit key_len, const std::string& passphrase,
+ const byte salt_buf[], u32bit salt_size,
+ u32bit iterations) const
+ {
+ SecureVector<byte> key(key_len), hash_buf;
+
+ u32bit pass = 0, generated = 0,
+ total_size = passphrase.size() + salt_size;
+ u32bit to_hash = std::max(iterations, total_size);
+
+ hash->clear();
+ while(key_len > generated)
+ {
+ for(u32bit j = 0; j != pass; ++j)
+ hash->update(0);
+
+ u32bit left = to_hash;
+ while(left >= total_size)
+ {
+ hash->update(salt_buf, salt_size);
+ hash->update(passphrase);
+ left -= total_size;
+ }
+ if(left <= salt_size)
+ hash->update(salt_buf, left);
+ else
+ {
+ hash->update(salt_buf, salt_size);
+ left -= salt_size;
+ hash->update(reinterpret_cast<const byte*>(passphrase.data()), left);
+ }
+
+ hash_buf = hash->final();
+ key.copy(generated, hash_buf, hash->OUTPUT_LENGTH);
+ generated += hash->OUTPUT_LENGTH;
+ ++pass;
+ }
+
+ return key;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string OpenPGP_S2K::name() const
+ {
+ return "OpenPGP-S2K(" + hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+S2K* OpenPGP_S2K::clone() const
+ {
+ return new OpenPGP_S2K(hash->clone());
+ }
+
+}
diff --git a/botan/src/s2k/pgps2k/pgp_s2k.h b/botan/src/s2k/pgps2k/pgp_s2k.h
new file mode 100644
index 0000000..00e95f7
--- /dev/null
+++ b/botan/src/s2k/pgps2k/pgp_s2k.h
@@ -0,0 +1,36 @@
+/*
+* OpenPGP S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_OPENPGP_S2K_H__
+#define BOTAN_OPENPGP_S2K_H__
+
+#include <botan/s2k.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/*
+* OpenPGP S2K
+*/
+class BOTAN_DLL OpenPGP_S2K : public S2K
+ {
+ public:
+ std::string name() const;
+ S2K* clone() const;
+
+ OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
+ ~OpenPGP_S2K() { delete hash; }
+ private:
+ OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const;
+
+ HashFunction* hash;
+ };
+
+}
+
+#endif
diff --git a/botan/src/s2k/s2k.cpp b/botan/src/s2k/s2k.cpp
new file mode 100644
index 0000000..b8a8ef7
--- /dev/null
+++ b/botan/src/s2k/s2k.cpp
@@ -0,0 +1,55 @@
+/*
+* S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/s2k.h>
+
+namespace Botan {
+
+/*
+* Derive a key from a passphrase
+*/
+OctetString S2K::derive_key(u32bit key_len,
+ const std::string& passphrase) const
+ {
+ return derive(key_len, passphrase, salt, salt.size(), iterations());
+ }
+
+/*
+* Set the number of iterations
+*/
+void S2K::set_iterations(u32bit i)
+ {
+ iter = i;
+ }
+
+/*
+* Change the salt
+*/
+void S2K::change_salt(const byte new_salt[], u32bit length)
+ {
+ salt.set(new_salt, length);
+ }
+
+/*
+* Change the salt
+*/
+void S2K::change_salt(const MemoryRegion<byte>& new_salt)
+ {
+ change_salt(new_salt.begin(), new_salt.size());
+ }
+
+/*
+* Create a new random salt
+*/
+void S2K::new_random_salt(RandomNumberGenerator& rng,
+ u32bit length)
+ {
+ salt.create(length);
+ rng.randomize(salt, length);
+ }
+
+}
diff --git a/botan/src/s2k/s2k.h b/botan/src/s2k/s2k.h
new file mode 100644
index 0000000..7af9251
--- /dev/null
+++ b/botan/src/s2k/s2k.h
@@ -0,0 +1,102 @@
+/*
+* S2K
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_S2K_H__
+#define BOTAN_S2K_H__
+
+#include <botan/symkey.h>
+#include <botan/rng.h>
+
+namespace Botan {
+
+/*
+* S2K Interface
+*/
+class BOTAN_DLL S2K
+ {
+ public:
+ /**
+ * Create a copy of this object.
+ * @return an auto_ptr to a copy of this object
+ */
+ virtual S2K* clone() const = 0;
+
+ /**
+ * Get the algorithm name.
+ * @return the name of this S2K algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Clear this objects internal values.
+ */
+ virtual void clear() {}
+
+ /**
+ * Derive a key from a passphrase with this S2K object. It will use
+ * the salt value and number of iterations configured in this object.
+ * @param key_len the desired length of the key to produce
+ * @param passphrase the password to derive the key from
+ */
+ OctetString derive_key(u32bit key_len,
+ const std::string& passphrase) const;
+
+ /**
+ * Set the number of iterations for the one-way function during
+ * key generation.
+ * @param n the desired number of iterations
+ */
+ void set_iterations(u32bit n);
+
+ /**
+ * Set a new salt value.
+ * @param new_salt a byte array defining the new salt value
+ * @param len the length of the above byte array
+ */
+ void change_salt(const byte new_salt[], u32bit len);
+
+ /**
+ * Set a new salt value.
+ * @param new_salt the new salt value
+ */
+ void change_salt(const MemoryRegion<byte>& new_salt);
+
+ /**
+ * Create a new random salt value using the rng
+ * @param rng the random number generator to use
+ * @param len the desired length of the new salt value
+ */
+ void new_random_salt(RandomNumberGenerator& rng, u32bit len);
+
+ /**
+ * Get the number of iterations for the key derivation currently
+ * configured in this S2K object.
+ * @return the current number of iterations
+ */
+ u32bit iterations() const { return iter; }
+
+ /**
+ * Get the currently configured salt value of this S2K object.
+ * @return the current salt value
+ */
+ SecureVector<byte> current_salt() const { return salt; }
+
+ S2K() { iter = 0; }
+ virtual ~S2K() {}
+ private:
+ S2K(const S2K&) {}
+ S2K& operator=(const S2K&) { return (*this); }
+
+ virtual OctetString derive(u32bit, const std::string&,
+ const byte[], u32bit, u32bit) const = 0;
+ SecureVector<byte> salt;
+ u32bit iter;
+ };
+
+}
+
+#endif
diff --git a/botan/src/selftest/info.txt b/botan/src/selftest/info.txt
new file mode 100644
index 0000000..323a610
--- /dev/null
+++ b/botan/src/selftest/info.txt
@@ -0,0 +1,21 @@
+realname "Selftests"
+
+define SELFTESTS
+
+load_on auto
+
+<add>
+selftest.cpp
+selftest.h
+</add>
+
+<requires>
+algo_factory
+cbc
+cfb
+ctr
+ecb
+filters
+hmac
+ofb
+</requires>
diff --git a/botan/src/selftest/selftest.cpp b/botan/src/selftest/selftest.cpp
new file mode 100644
index 0000000..d644e86
--- /dev/null
+++ b/botan/src/selftest/selftest.cpp
@@ -0,0 +1,184 @@
+/*
+* Startup Self Tests
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/selftest.h>
+#include <botan/filters.h>
+#include <botan/ecb.h>
+#include <botan/cbc.h>
+#include <botan/cfb.h>
+#include <botan/ofb.h>
+#include <botan/ctr.h>
+#include <botan/hmac.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Perform a Known Answer Test
+*/
+void do_kat(const std::string& in, const std::string& out,
+ const std::string& algo_name, Filter* filter)
+ {
+ if(out.length())
+ {
+ Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder);
+ pipe.process_msg(in);
+
+ if(out != pipe.read_all_as_string())
+ throw Self_Test_Failure(algo_name + " startup test");
+ }
+ }
+
+/*
+* Perform a KAT for a cipher
+*/
+void cipher_kat(const BlockCipher* proto,
+ const std::string& key_str,
+ const std::string& iv_str,
+ const std::string& in,
+ const std::string& ecb_out,
+ const std::string& cbc_out,
+ const std::string& cfb_out,
+ const std::string& ofb_out,
+ const std::string& ctr_out)
+ {
+ SymmetricKey key(key_str);
+ InitializationVector iv(iv_str);
+
+ std::string name = proto->name();
+
+ do_kat(in, ecb_out, name + "/ECB",
+ new ECB_Encryption(proto->clone(), new Null_Padding, key));
+ do_kat(ecb_out, in, name + "/ECB",
+ new ECB_Decryption(proto->clone(), new Null_Padding, key));
+
+ do_kat(in, cbc_out, name + "/CBC",
+ new CBC_Encryption(proto->clone(), new Null_Padding, key, iv));
+ do_kat(cbc_out, in, name + "/CBC",
+ new CBC_Decryption(proto->clone(), new Null_Padding, key, iv));
+
+ do_kat(in, cfb_out, name + "/CFB",
+ new CFB_Encryption(proto->clone(), key, iv));
+ do_kat(cfb_out, in, name + "/CFB",
+ new CFB_Decryption(proto->clone(), key, iv));
+
+ do_kat(in, ofb_out, name + "/OFB", new OFB(proto->clone(), key, iv));
+
+ do_kat(in, ctr_out, name + "/CTR-BE",
+ new CTR_BE(proto->clone(), key, iv));
+ }
+
+}
+
+/*
+* Perform Self Tests
+*/
+bool passes_self_tests(Algorithm_Factory& af)
+ {
+ try
+ {
+ if(const BlockCipher* proto = af.prototype_block_cipher("DES"))
+ {
+ cipher_kat(proto,
+ "0123456789ABCDEF", "1234567890ABCDEF",
+ "4E6F77206973207468652074696D6520666F7220616C6C20",
+ "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53",
+ "E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6",
+ "F3096249C7F46E51A69E839B1A92F78403467133898EA622",
+ "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3",
+ "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75");
+ }
+
+ if(const BlockCipher* proto = af.prototype_block_cipher("TripleDES"))
+ {
+ cipher_kat(proto,
+ "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
+ "C141B5FCCD28DC8A",
+ "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
+ "64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
+ "6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
+ "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
+ "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
+ "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
+ }
+
+ if(const BlockCipher* proto = af.prototype_block_cipher("AES"))
+ {
+ cipher_kat(proto,
+ "2B7E151628AED2A6ABF7158809CF4F3C",
+ "000102030405060708090A0B0C0D0E0F",
+ "6BC1BEE22E409F96E93D7E117393172A"
+ "AE2D8A571E03AC9C9EB76FAC45AF8E51",
+ "3AD77BB40D7A3660A89ECAF32466EF97"
+ "F5D3D58503B9699DE785895A96FDBAAF",
+ "7649ABAC8119B246CEE98E9B12E9197D"
+ "5086CB9B507219EE95DB113A917678B2",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "7789508D16918F03F53C52DAC54ED825",
+ "3B3FD92EB72DAD20333449F8E83CFB4A"
+ "010C041999E03F36448624483E582D0E");
+ }
+
+ if(const HashFunction* proto = af.prototype_hash_function("SHA-1"))
+ {
+ do_kat("", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("616263", "A9993E364706816ABA3E25717850C26C9CD0D89D",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("6162636462636465636465666465666765666768666768696768696A"
+ "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
+ "84983E441C3BD26EBAAE4AA1F95129E5E54670F1",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("4869205468657265",
+ "B617318655057264E28BC0B6FB378C8EF146BE00",
+ "HMAC(" + proto->name() + ")",
+ new MAC_Filter(new HMAC(proto->clone()),
+ SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B")));
+ }
+
+ if(const HashFunction* proto = af.prototype_hash_function("SHA-256"))
+ {
+ do_kat("",
+ "E3B0C44298FC1C149AFBF4C8996FB924"
+ "27AE41E4649B934CA495991B7852B855",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("616263",
+ "BA7816BF8F01CFEA414140DE5DAE2223"
+ "B00361A396177A9CB410FF61F20015AD",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("6162636462636465636465666465666765666768666768696768696A"
+ "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071",
+ "248D6A61D20638B8E5C026930C3E6039"
+ "A33CE45964FF2167F6ECEDD419DB06C1",
+ proto->name(), new Hash_Filter(proto->clone()));
+
+ do_kat("4869205468657265",
+ "198A607EB44BFBC69903A0F1CF2BBDC5"
+ "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7",
+ "HMAC(" + proto->name() + ")",
+ new MAC_Filter(new HMAC(proto->clone()),
+ SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"
+ "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B")));
+ }
+ }
+ catch(std::exception)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/botan/src/selftest/selftest.h b/botan/src/selftest/selftest.h
new file mode 100644
index 0000000..9e36d22
--- /dev/null
+++ b/botan/src/selftest/selftest.h
@@ -0,0 +1,22 @@
+/*
+* Startup Self Test
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SELF_TESTS_H__
+#define BOTAN_SELF_TESTS_H__
+
+#include <botan/algo_factory.h>
+
+namespace Botan {
+
+/*
+* Self Tests
+*/
+BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af);
+
+}
+
+#endif
diff --git a/botan/src/src.pro b/botan/src/src.pro
new file mode 100644
index 0000000..08de10e
--- /dev/null
+++ b/botan/src/src.pro
@@ -0,0 +1,573 @@
+TEMPLATE = lib
+TARGET = Botan
+
+CONFIG += dll
+
+include(../../../../qtcreatorlibrary.pri)
+
+DEPENDPATH += .
+INCLUDEPATH += $$PWD $$PWD/../build $$PWD/../build/botan
+
+win32 {
+ win32-msvc* {
+ QMAKE_CXXFLAGS += -wd4251 -wd4290 -wd4250
+ DEFINES += BOTAN_DLL=__declspec(dllexport)
+ } else {
+ QMAKE_CFLAGS += -fpermissive -finline-functions -Wno-long-long
+ QMAKE_CXXFLAGS += -fpermissive -finline-functions -Wno-long-long
+ }
+ LIBS += -ladvapi32 -luser32
+}
+
+unix {
+ QMAKE_CFLAGS += -fPIC -ansi -fpermissive -finline-functions -Wno-long-long
+ QMAKE_CXXFLAGS += -fPIC -ansi -fpermissive -finline-functions -Wno-long-long
+ QMAKE_CXXFLAGS_HIDESYMS -= -fvisibility-inlines-hidden # for ubuntu 7.04
+}
+
+# Input
+HEADERS += algo_factory/algo_cache.h \
+ algo_factory/algo_factory.h \
+ alloc/allocate.h \
+ alloc/mem_pool/mem_pool.h \
+ alloc/secmem.h \
+ alloc/system_alloc/defalloc.h \
+ asn1/alg_id.h \
+ asn1/asn1_int.h \
+ asn1/asn1_obj.h \
+ asn1/asn1_oid.h \
+ asn1/ber_dec.h \
+ asn1/der_enc.h \
+ benchmark/benchmark.h \
+ block/aes/aes.h \
+ block/block_cipher.h \
+ block/blowfish/blowfish.h \
+ block/cast/cast128.h \
+ block/cast/cast256.h \
+ block/des/des.h \
+ block/des/desx.h \
+ block/gost_28147/gost_28147.h \
+ block/idea/idea.h \
+ block/kasumi/kasumi.h \
+ block/lion/lion.h \
+ block/lubyrack/lubyrack.h \
+ block/mars/mars.h \
+ block/misty1/misty1.h \
+ block/noekeon/noekeon.h \
+ block/rc2/rc2.h \
+ block/rc5/rc5.h \
+ block/rc6/rc6.h \
+ block/safer/safer_sk.h \
+ block/seed/seed.h \
+ block/serpent/serpent.h \
+ block/skipjack/skipjack.h \
+ block/square/square.h \
+ block/tea/tea.h \
+ block/twofish/twofish.h \
+ block/xtea/xtea.h \
+ cert/x509/certstor.h \
+ cert/x509/crl_ent.h \
+ cert/x509/pkcs10.h \
+ cert/x509/x509_ca.h \
+ cert/x509/x509_crl.h \
+ cert/x509/x509_ext.h \
+ cert/x509/x509_obj.h \
+ cert/x509/x509cert.h \
+ cert/x509/x509find.h \
+ cert/x509/x509self.h \
+ cert/x509/x509stor.h \
+ checksum/adler32/adler32.h \
+ checksum/crc24/crc24.h \
+ checksum/crc32/crc32.h \
+ cms/cms_dec.h \
+ cms/cms_enc.h \
+ codec/base64/base64.h \
+ codec/hex/hex.h \
+ codec/openpgp/openpgp.h \
+ codec/pem/pem.h \
+ cryptobox/cryptobox.h \
+ engine/def_engine/def_eng.h \
+ engine/engine.h \
+ entropy/entropy_src.h \
+ filters/basefilt.h \
+ filters/buf_filt.h \
+ filters/data_snk.h \
+ filters/data_src.h \
+ filters/filter.h \
+ filters/filters.h \
+ filters/out_buf.h \
+ filters/pbe.h \
+ filters/pipe.h \
+ filters/secqueue.h \
+ hash/fork256/fork256.h \
+ hash/gost_3411/gost_3411.h \
+ hash/has160/has160.h \
+ hash/hash.h \
+ hash/md2/md2.h \
+ hash/md4/md4.h \
+ hash/md5/md5.h \
+ hash/mdx_hash/mdx_hash.h \
+ hash/par_hash/par_hash.h \
+ hash/rmd128/rmd128.h \
+ hash/rmd160/rmd160.h \
+ hash/sha1/sha160.h \
+ hash/sha2/sha2_32.h \
+ hash/sha2/sha2_64.h \
+ hash/skein/skein_512.h \
+ hash/tiger/tiger.h \
+ hash/whirlpool/whrlpool.h \
+ kdf/kdf.h \
+ kdf/kdf1/kdf1.h \
+ kdf/kdf2/kdf2.h \
+ kdf/mgf1/mgf1.h \
+ kdf/ssl_prf/prf_ssl3.h \
+ kdf/tls_prf/prf_tls.h \
+ kdf/x942_prf/prf_x942.h \
+ libstate/botan.h \
+ libstate/init.h \
+ libstate/libstate.h \
+ libstate/look_pk.h \
+ libstate/lookup.h \
+ libstate/oid_lookup/oids.h \
+ libstate/pk_engine.h \
+ libstate/scan_name.h \
+ mac/cbc_mac/cbc_mac.h \
+ mac/cmac/cmac.h \
+ mac/hmac/hmac.h \
+ mac/mac.h \
+ mac/ssl3mac/ssl3_mac.h \
+ mac/x919_mac/x919_mac.h \
+ math/bigint/bigint.h \
+ math/bigint/divide.h \
+ math/bigint/mp_core.h \
+ math/bigint/mp_generic/mp_asm.h \
+ math/bigint/mp_generic/mp_asmi.h \
+ math/bigint/mp_types.h \
+ math/numbertheory/blinding.h \
+ math/numbertheory/def_powm.h \
+ math/numbertheory/numthry.h \
+ math/numbertheory/pow_mod.h \
+ math/numbertheory/reducer.h \
+ modes/cbc/cbc.h \
+ modes/cfb/cfb.h \
+ modes/ctr/ctr.h \
+ modes/cts/cts.h \
+ modes/eax/eax.h \
+ modes/ecb/ecb.h \
+ modes/mode_pad/mode_pad.h \
+ modes/modebase.h \
+ modes/ofb/ofb.h \
+ modes/xts/xts.h \
+ mutex/mutex.h \
+ mutex/noop_mutex/mux_noop.h \
+ pbe/get_pbe.h \
+ pbe/pbes1/pbes1.h \
+ pbe/pbes2/pbes2.h \
+ pk_pad/eme.h \
+ pk_pad/eme1/eme1.h \
+ pk_pad/eme_pkcs/eme_pkcs.h \
+ pk_pad/emsa.h \
+ pk_pad/emsa1/emsa1.h \
+ pk_pad/emsa1_bsi/emsa1_bsi.h \
+ pk_pad/emsa2/emsa2.h \
+ pk_pad/emsa3/emsa3.h \
+ pk_pad/emsa4/emsa4.h \
+ pk_pad/emsa_raw/emsa_raw.h \
+ pk_pad/hash_id/hash_id.h \
+ pubkey/dh/dh.h \
+ pubkey/dh/dh_core.h \
+ pubkey/dh/dh_op.h \
+ pubkey/dl_algo/dl_algo.h \
+ pubkey/dl_group/dl_group.h \
+ pubkey/dlies/dlies.h \
+ pubkey/dsa/dsa.h \
+ pubkey/dsa/dsa_core.h \
+ pubkey/dsa/dsa_op.h \
+ pubkey/elgamal/elg_core.h \
+ pubkey/elgamal/elg_op.h \
+ pubkey/elgamal/elgamal.h \
+ pubkey/if_algo/if_algo.h \
+ pubkey/if_algo/if_core.h \
+ pubkey/if_algo/if_op.h \
+ pubkey/keypair/keypair.h \
+ pubkey/nr/nr.h \
+ pubkey/nr/nr_core.h \
+ pubkey/nr/nr_op.h \
+ pubkey/pk_algs.h \
+ pubkey/pk_codecs/pkcs8.h \
+ pubkey/pk_codecs/x509_key.h \
+ pubkey/pk_filts.h \
+ pubkey/pk_keys.h \
+ pubkey/pubkey.h \
+ pubkey/pubkey_enums.h \
+ pubkey/rsa/rsa.h \
+ pubkey/rw/rw.h \
+ rng/auto_rng/auto_rng.h \
+ rng/hmac_rng/hmac_rng.h \
+ rng/randpool/randpool.h \
+ rng/rng.h \
+ rng/x931_rng/x931_rng.h \
+ s2k/pbkdf1/pbkdf1.h \
+ s2k/pbkdf2/pbkdf2.h \
+ s2k/pgps2k/pgp_s2k.h \
+ s2k/s2k.h \
+ selftest/selftest.h \
+ stream/arc4/arc4.h \
+ stream/salsa20/salsa20.h \
+ stream/stream_cipher.h \
+ stream/turing/turing.h \
+ stream/wid_wake/wid_wake.h \
+ sym_algo/sym_algo.h \
+ sym_algo/symkey.h \
+ timer/timer.h \
+ utils/bit_ops.h \
+ utils/bswap.h \
+ utils/buf_comp/buf_comp.h \
+ utils/charset.h \
+ utils/datastor/datastor.h \
+ utils/exceptn.h \
+ utils/loadstor.h \
+ utils/mem_ops.h \
+ utils/parsing.h \
+ utils/rotate.h \
+ utils/stl_util.h \
+ utils/types.h \
+ utils/ui.h \
+ utils/util.h \
+ utils/version.h \
+ utils/xor_buf.h
+
+win32 {
+ HEADERS += entropy/cryptoapi_rng/es_capi.h \
+ entropy/win32_stats/es_win32.h \
+ mutex/win32_crit_section/mux_win32.h \
+ timer/win32_query_perf_ctr/tm_win32.h
+}
+
+unix {
+ HEADERS += alloc/alloc_mmap/mmap_mem.h \
+ cert/cvc/cvc_ado.h \
+ cert/cvc/cvc_ca.h \
+ cert/cvc/cvc_cert.h \
+ cert/cvc/cvc_gen_cert.h \
+ cert/cvc/cvc_key.h \
+ cert/cvc/cvc_req.h \
+ cert/cvc/cvc_self.h \
+ cert/cvc/eac_asn_obj.h \
+ cert/cvc/eac_obj.h \
+ cert/cvc/ecdsa_sig.h \
+ cert/cvc/freestore.h \
+ cert/cvc/signed_obj.h \
+ entropy/dev_random/es_dev.h \
+ entropy/egd/es_egd.h \
+ entropy/proc_walk/es_ftw.h \
+ entropy/unix_procs/es_unix.h \
+ entropy/unix_procs/unix_cmd.h \
+ filters/fd_unix/fd_unix.h \
+ math/gfpmath/curve_gfp.h \
+ math/gfpmath/gfp_element.h \
+ math/gfpmath/gfp_modulus.h \
+ math/gfpmath/point_gfp.h \
+ mutex/pthreads/mux_pthr.h \
+ pubkey/ec_dompar/ec_dompar.h \
+ pubkey/ecc_key/ecc_key.h \
+ pubkey/ecdsa/ecdsa.h \
+ pubkey/ecdsa/ecdsa_core.h \
+ pubkey/ecdsa/ecdsa_op.h \
+ pubkey/eckaeg/eckaeg.h \
+ pubkey/eckaeg/eckaeg_core.h \
+ pubkey/eckaeg/eckaeg_op.h \
+ timer/gettimeofday/tm_unix.h
+}
+
+linux*-g++* {
+ HEADERS += timer/posix_rt/tm_posix.h
+}
+
+SOURCES += algo_factory/algo_factory.cpp \
+ algo_factory/prov_weight.cpp \
+ alloc/mem_pool/mem_pool.cpp \
+ alloc/system_alloc/defalloc.cpp \
+ asn1/alg_id.cpp \
+ asn1/asn1_alt.cpp \
+ asn1/asn1_att.cpp \
+ asn1/asn1_dn.cpp \
+ asn1/asn1_int.cpp \
+ asn1/asn1_oid.cpp \
+ asn1/asn1_str.cpp \
+ asn1/asn1_tm.cpp \
+ asn1/ber_dec.cpp \
+ asn1/der_enc.cpp \
+ benchmark/benchmark.cpp \
+ block/aes/aes.cpp \
+ block/aes/aes_tab.cpp \
+ block/blowfish/blfs_tab.cpp \
+ block/blowfish/blowfish.cpp \
+ block/cast/cast128.cpp \
+ block/cast/cast256.cpp \
+ block/cast/cast_tab.cpp \
+ block/des/des.cpp \
+ block/des/des_tab.cpp \
+ block/des/desx.cpp \
+ block/gost_28147/gost_28147.cpp \
+ block/idea/idea.cpp \
+ block/kasumi/kasumi.cpp \
+ block/lion/lion.cpp \
+ block/lubyrack/lubyrack.cpp \
+ block/mars/mars.cpp \
+ block/mars/mars_tab.cpp \
+ block/misty1/misty1.cpp \
+ block/noekeon/noekeon.cpp \
+ block/rc2/rc2.cpp \
+ block/rc5/rc5.cpp \
+ block/rc6/rc6.cpp \
+ block/safer/safe_tab.cpp \
+ block/safer/safer_sk.cpp \
+ block/seed/seed.cpp \
+ block/seed/seed_tab.cpp \
+ block/serpent/serpent.cpp \
+ block/skipjack/skipjack.cpp \
+ block/square/sqr_tab.cpp \
+ block/square/square.cpp \
+ block/tea/tea.cpp \
+ block/twofish/two_tab.cpp \
+ block/twofish/twofish.cpp \
+ block/xtea/xtea.cpp \
+ cert/x509/certstor.cpp \
+ cert/x509/crl_ent.cpp \
+ cert/x509/pkcs10.cpp \
+ cert/x509/x509_ca.cpp \
+ cert/x509/x509_crl.cpp \
+ cert/x509/x509_ext.cpp \
+ cert/x509/x509_obj.cpp \
+ cert/x509/x509cert.cpp \
+ cert/x509/x509find.cpp \
+ cert/x509/x509opt.cpp \
+ cert/x509/x509self.cpp \
+ cert/x509/x509stor.cpp \
+ checksum/adler32/adler32.cpp \
+ checksum/crc24/crc24.cpp \
+ checksum/crc32/crc32.cpp \
+ cms/cms_algo.cpp \
+ cms/cms_comp.cpp \
+ cms/cms_dalg.cpp \
+ cms/cms_dec.cpp \
+ cms/cms_ealg.cpp \
+ cms/cms_enc.cpp \
+ codec/base64/b64_char.cpp \
+ codec/base64/base64.cpp \
+ codec/hex/hex.cpp \
+ codec/hex/hex_char.cpp \
+ codec/openpgp/openpgp.cpp \
+ codec/pem/pem.cpp \
+ cryptobox/cryptobox.cpp \
+ engine/def_engine/def_mode.cpp \
+ engine/def_engine/def_pk_ops.cpp \
+ engine/def_engine/def_powm.cpp \
+ engine/def_engine/lookup_block.cpp \
+ engine/def_engine/lookup_hash.cpp \
+ engine/def_engine/lookup_mac.cpp \
+ engine/def_engine/lookup_stream.cpp \
+ filters/algo_filt.cpp \
+ filters/basefilt.cpp \
+ filters/buf_filt.cpp \
+ filters/data_snk.cpp \
+ filters/data_src.cpp \
+ filters/filter.cpp \
+ filters/out_buf.cpp \
+ filters/pipe.cpp \
+ filters/pipe_io.cpp \
+ filters/pipe_rw.cpp \
+ filters/secqueue.cpp \
+ hash/fork256/fork256.cpp \
+ hash/gost_3411/gost_3411.cpp \
+ hash/has160/has160.cpp \
+ hash/md2/md2.cpp \
+ hash/md4/md4.cpp \
+ hash/md5/md5.cpp \
+ hash/mdx_hash/mdx_hash.cpp \
+ hash/par_hash/par_hash.cpp \
+ hash/rmd128/rmd128.cpp \
+ hash/rmd160/rmd160.cpp \
+ hash/sha1/sha160.cpp \
+ hash/sha2/sha2_32.cpp \
+ hash/sha2/sha2_64.cpp \
+ hash/skein/skein_512.cpp \
+ hash/tiger/tig_tab.cpp \
+ hash/tiger/tiger.cpp \
+ hash/whirlpool/whrl_tab.cpp \
+ hash/whirlpool/whrlpool.cpp \
+ kdf/kdf.cpp \
+ kdf/kdf1/kdf1.cpp \
+ kdf/kdf2/kdf2.cpp \
+ kdf/mgf1/mgf1.cpp \
+ kdf/ssl_prf/prf_ssl3.cpp \
+ kdf/tls_prf/prf_tls.cpp \
+ kdf/x942_prf/prf_x942.cpp \
+ libstate/get_enc.cpp \
+ libstate/init.cpp \
+ libstate/libstate.cpp \
+ libstate/look_pk.cpp \
+ libstate/lookup.cpp \
+ libstate/oid_lookup/oids.cpp \
+ libstate/pk_engine.cpp \
+ libstate/policy.cpp \
+ libstate/scan_name.cpp \
+ mac/cbc_mac/cbc_mac.cpp \
+ mac/cmac/cmac.cpp \
+ mac/hmac/hmac.cpp \
+ mac/mac.cpp \
+ mac/ssl3mac/ssl3_mac.cpp \
+ mac/x919_mac/x919_mac.cpp \
+ math/bigint/big_code.cpp \
+ math/bigint/big_io.cpp \
+ math/bigint/big_ops2.cpp \
+ math/bigint/big_ops3.cpp \
+ math/bigint/big_rand.cpp \
+ math/bigint/bigint.cpp \
+ math/bigint/divide.cpp \
+ math/bigint/monty_generic/mp_monty.cpp \
+ math/bigint/mp_asm.cpp \
+ math/bigint/mp_comba.cpp \
+ math/bigint/mp_karat.cpp \
+ math/bigint/mp_misc.cpp \
+ math/bigint/mp_shift.cpp \
+ math/bigint/mulop_generic/mp_mulop.cpp \
+ math/numbertheory/blinding.cpp \
+ math/numbertheory/dsa_gen.cpp \
+ math/numbertheory/jacobi.cpp \
+ math/numbertheory/make_prm.cpp \
+ math/numbertheory/mp_numth.cpp \
+ math/numbertheory/numthry.cpp \
+ math/numbertheory/pow_mod.cpp \
+ math/numbertheory/powm_fw.cpp \
+ math/numbertheory/powm_mnt.cpp \
+ math/numbertheory/primes.cpp \
+ math/numbertheory/reducer.cpp \
+ math/numbertheory/ressol.cpp \
+ modes/cbc/cbc.cpp \
+ modes/cfb/cfb.cpp \
+ modes/ctr/ctr.cpp \
+ modes/cts/cts.cpp \
+ modes/eax/eax.cpp \
+ modes/eax/eax_dec.cpp \
+ modes/ecb/ecb.cpp \
+ modes/mode_pad/mode_pad.cpp \
+ modes/modebase.cpp \
+ modes/ofb/ofb.cpp \
+ modes/xts/xts.cpp \
+ mutex/noop_mutex/mux_noop.cpp \
+ pbe/get_pbe.cpp \
+ pbe/pbes1/pbes1.cpp \
+ pbe/pbes2/pbes2.cpp \
+ pk_pad/eme.cpp \
+ pk_pad/eme1/eme1.cpp \
+ pk_pad/eme_pkcs/eme_pkcs.cpp \
+ pk_pad/emsa1/emsa1.cpp \
+ pk_pad/emsa1_bsi/emsa1_bsi.cpp \
+ pk_pad/emsa2/emsa2.cpp \
+ pk_pad/emsa3/emsa3.cpp \
+ pk_pad/emsa4/emsa4.cpp \
+ pk_pad/emsa_raw/emsa_raw.cpp \
+ pk_pad/hash_id/hash_id.cpp \
+ pubkey/dh/dh.cpp \
+ pubkey/dh/dh_core.cpp \
+ pubkey/dl_algo/dl_algo.cpp \
+ pubkey/dl_group/dl_group.cpp \
+ pubkey/dlies/dlies.cpp \
+ pubkey/dsa/dsa.cpp \
+ pubkey/dsa/dsa_core.cpp \
+ pubkey/dsa/dsa_op.cpp \
+ pubkey/elgamal/elg_core.cpp \
+ pubkey/elgamal/elg_op.cpp \
+ pubkey/elgamal/elgamal.cpp \
+ pubkey/if_algo/if_algo.cpp \
+ pubkey/if_algo/if_core.cpp \
+ pubkey/if_algo/if_op.cpp \
+ pubkey/keypair/keypair.cpp \
+ pubkey/nr/nr.cpp \
+ pubkey/nr/nr_core.cpp \
+ pubkey/nr/nr_op.cpp \
+ pubkey/pk_algs.cpp \
+ pubkey/pk_codecs/pkcs8.cpp \
+ pubkey/pk_codecs/x509_key.cpp \
+ pubkey/pk_filts.cpp \
+ pubkey/pk_keys.cpp \
+ pubkey/pubkey.cpp \
+ pubkey/pubkey_enums.cpp \
+ pubkey/rsa/rsa.cpp \
+ pubkey/rw/rw.cpp \
+ rng/auto_rng/auto_rng.cpp \
+ rng/hmac_rng/hmac_rng.cpp \
+ rng/randpool/randpool.cpp \
+ rng/rng.cpp \
+ rng/x931_rng/x931_rng.cpp \
+ s2k/pbkdf1/pbkdf1.cpp \
+ s2k/pbkdf2/pbkdf2.cpp \
+ s2k/pgps2k/pgp_s2k.cpp \
+ s2k/s2k.cpp \
+ selftest/selftest.cpp \
+ stream/arc4/arc4.cpp \
+ stream/salsa20/salsa20.cpp \
+ stream/stream_cipher.cpp \
+ stream/turing/tur_tab.cpp \
+ stream/turing/turing.cpp \
+ stream/wid_wake/wid_wake.cpp \
+ sym_algo/symkey.cpp \
+ timer/timer.cpp \
+ utils/charset.cpp \
+ utils/datastor/datastor.cpp \
+ utils/exceptn.cpp \
+ utils/mlock.cpp \
+ utils/parsing.cpp \
+ utils/ui.cpp \
+ utils/util.cpp \
+ utils/version.cpp
+
+win32 {
+SOURCES += entropy/cryptoapi_rng/es_capi.cpp \
+ entropy/win32_stats/es_win32.cpp \
+ mutex/win32_crit_section/mux_win32.cpp \
+ timer/win32_query_perf_ctr/tm_win32.cpp
+}
+
+unix {
+ SOURCES += alloc/alloc_mmap/mmap_mem.cpp \
+ cert/cvc/asn1_eac_str.cpp \
+ cert/cvc/asn1_eac_tm.cpp \
+ cert/cvc/cvc_ado.cpp \
+ cert/cvc/cvc_ca.cpp \
+ cert/cvc/cvc_cert.cpp \
+ cert/cvc/cvc_req.cpp \
+ cert/cvc/cvc_self.cpp \
+ cert/cvc/ecdsa_sig.cpp \
+ cert/cvc/signed_obj.cpp \
+ entropy/dev_random/es_dev.cpp \
+ entropy/egd/es_egd.cpp \
+ entropy/proc_walk/es_ftw.cpp \
+ entropy/unix_procs/es_unix.cpp \
+ entropy/unix_procs/unix_cmd.cpp \
+ entropy/unix_procs/unix_src.cpp \
+ filters/fd_unix/fd_unix.cpp \
+ math/gfpmath/curve_gfp.cpp \
+ math/gfpmath/gfp_element.cpp \
+ math/gfpmath/point_gfp.cpp \
+ mutex/pthreads/mux_pthr.cpp \
+ pubkey/ec_dompar/ec_dompar.cpp \
+ pubkey/ecc_key/ecc_key.cpp \
+ pubkey/ecdsa/ecdsa.cpp \
+ pubkey/ecdsa/ecdsa_core.cpp \
+ pubkey/ecdsa/ecdsa_op.cpp \
+ pubkey/eckaeg/eckaeg.cpp \
+ pubkey/eckaeg/eckaeg_core.cpp \
+ pubkey/eckaeg/eckaeg_op.cpp \
+ timer/gettimeofday/tm_unix.cpp
+}
+
+linux*-g++* {
+ SOURCES += timer/posix_rt/tm_posix.cpp
+}
+
+linux*-g++* {
+ LIBS += -lrt
+}
diff --git a/botan/src/stream/arc4/arc4.cpp b/botan/src/stream/arc4/arc4.cpp
new file mode 100644
index 0000000..0f78f73
--- /dev/null
+++ b/botan/src/stream/arc4/arc4.cpp
@@ -0,0 +1,105 @@
+/*
+* ARC4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/arc4.h>
+#include <botan/xor_buf.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Combine cipher stream with message
+*/
+void ARC4::cipher(const byte in[], byte out[], u32bit length)
+ {
+ while(length >= buffer.size() - position)
+ {
+ xor_buf(out, in, buffer.begin() + position, buffer.size() - position);
+ length -= (buffer.size() - position);
+ in += (buffer.size() - position);
+ out += (buffer.size() - position);
+ generate();
+ }
+ xor_buf(out, in, buffer.begin() + position, length);
+ position += length;
+ }
+
+/*
+* Generate cipher stream
+*/
+void ARC4::generate()
+ {
+ u32bit SX, SY;
+ for(u32bit j = 0; j != buffer.size(); j += 4)
+ {
+ SX = state[X+1]; Y = (Y + SX) % 256; SY = state[Y];
+ state[X+1] = SY; state[Y] = SX;
+ buffer[j] = state[(SX + SY) % 256];
+
+ SX = state[X+2]; Y = (Y + SX) % 256; SY = state[Y];
+ state[X+2] = SY; state[Y] = SX;
+ buffer[j+1] = state[(SX + SY) % 256];
+
+ SX = state[X+3]; Y = (Y + SX) % 256; SY = state[Y];
+ state[X+3] = SY; state[Y] = SX;
+ buffer[j+2] = state[(SX + SY) % 256];
+
+ X = (X + 4) % 256;
+ SX = state[X]; Y = (Y + SX) % 256; SY = state[Y];
+ state[X] = SY; state[Y] = SX;
+ buffer[j+3] = state[(SX + SY) % 256];
+ }
+ position = 0;
+ }
+
+/*
+* ARC4 Key Schedule
+*/
+void ARC4::key_schedule(const byte key[], u32bit length)
+ {
+ clear();
+ for(u32bit j = 0; j != 256; ++j)
+ state[j] = j;
+ for(u32bit j = 0, state_index = 0; j != 256; ++j)
+ {
+ state_index = (state_index + key[j % length] + state[j]) % 256;
+ std::swap(state[j], state[state_index]);
+ }
+ for(u32bit j = 0; j <= SKIP; j += buffer.size())
+ generate();
+ position += (SKIP % buffer.size());
+ }
+
+/*
+* Return the name of this type
+*/
+std::string ARC4::name() const
+ {
+ if(SKIP == 0) return "ARC4";
+ if(SKIP == 256) return "MARK-4";
+ else return "RC4_skip(" + to_string(SKIP) + ")";
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void ARC4::clear() throw()
+ {
+ state.clear();
+ buffer.clear();
+ position = X = Y = 0;
+ }
+
+/*
+* ARC4 Constructor
+*/
+ARC4::ARC4(u32bit s) : StreamCipher(1, 256), SKIP(s)
+ {
+ clear();
+ }
+
+}
diff --git a/botan/src/stream/arc4/arc4.h b/botan/src/stream/arc4/arc4.h
new file mode 100644
index 0000000..aa2cea7
--- /dev/null
+++ b/botan/src/stream/arc4/arc4.h
@@ -0,0 +1,41 @@
+/*
+* ARC4
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ARC4_H__
+#define BOTAN_ARC4_H__
+
+#include <botan/stream_cipher.h>
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* ARC4
+*/
+class BOTAN_DLL ARC4 : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ StreamCipher* clone() const { return new ARC4(SKIP); }
+ ARC4(u32bit = 0);
+ ~ARC4() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void generate();
+
+ const u32bit SKIP;
+
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ SecureBuffer<u32bit, 256> state;
+ u32bit X, Y, position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/stream/arc4/info.txt b/botan/src/stream/arc4/info.txt
new file mode 100644
index 0000000..e4689cf
--- /dev/null
+++ b/botan/src/stream/arc4/info.txt
@@ -0,0 +1,14 @@
+realname "ARC4"
+
+define ARC4
+
+load_on auto
+
+<requires>
+stream
+</requires>
+
+<add>
+arc4.cpp
+arc4.h
+</add>
diff --git a/botan/src/stream/info.txt b/botan/src/stream/info.txt
new file mode 100644
index 0000000..295c737
--- /dev/null
+++ b/botan/src/stream/info.txt
@@ -0,0 +1,14 @@
+realname "Stream Ciphers"
+
+load_on auto
+
+define STREAM_CIPHER
+
+<add>
+stream_cipher.h
+stream_cipher.cpp
+</add>
+
+<requires>
+sym_algo
+</requires>
diff --git a/botan/src/stream/salsa20/info.txt b/botan/src/stream/salsa20/info.txt
new file mode 100644
index 0000000..db93830
--- /dev/null
+++ b/botan/src/stream/salsa20/info.txt
@@ -0,0 +1,14 @@
+realname "Salsa20"
+
+define SALSA20
+
+load_on auto
+
+<requires>
+stream
+</requires>
+
+<add>
+salsa20.cpp
+salsa20.h
+</add>
diff --git a/botan/src/stream/salsa20/salsa20.cpp b/botan/src/stream/salsa20/salsa20.cpp
new file mode 100644
index 0000000..7513779
--- /dev/null
+++ b/botan/src/stream/salsa20/salsa20.cpp
@@ -0,0 +1,217 @@
+/*
+* Salsa20
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/salsa20.h>
+#include <botan/mem_ops.h>
+#include <botan/xor_buf.h>
+#include <botan/loadstor.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Generate Salsa20 cipher stream
+*/
+void salsa20(byte output[64], const u32bit input[16])
+ {
+ u32bit x00 = input[0];
+ u32bit x01 = input[1];
+ u32bit x02 = input[2];
+ u32bit x03 = input[3];
+ u32bit x04 = input[4];
+ u32bit x05 = input[5];
+ u32bit x06 = input[6];
+ u32bit x07 = input[7];
+ u32bit x08 = input[8];
+ u32bit x09 = input[9];
+ u32bit x10 = input[10];
+ u32bit x11 = input[11];
+ u32bit x12 = input[12];
+ u32bit x13 = input[13];
+ u32bit x14 = input[14];
+ u32bit x15 = input[15];
+
+ for(u32bit i = 0; i != 10; ++i)
+ {
+ x04 ^= rotate_left(x00 + x12, 7);
+ x08 ^= rotate_left(x04 + x00, 9);
+ x12 ^= rotate_left(x08 + x04, 13);
+ x00 ^= rotate_left(x12 + x08, 18);
+ x09 ^= rotate_left(x05 + x01, 7);
+ x13 ^= rotate_left(x09 + x05, 9);
+ x01 ^= rotate_left(x13 + x09, 13);
+ x05 ^= rotate_left(x01 + x13, 18);
+ x14 ^= rotate_left(x10 + x06, 7);
+ x02 ^= rotate_left(x14 + x10, 9);
+ x06 ^= rotate_left(x02 + x14, 13);
+ x10 ^= rotate_left(x06 + x02, 18);
+ x03 ^= rotate_left(x15 + x11, 7);
+ x07 ^= rotate_left(x03 + x15, 9);
+ x11 ^= rotate_left(x07 + x03, 13);
+ x15 ^= rotate_left(x11 + x07, 18);
+
+ x01 ^= rotate_left(x00 + x03, 7);
+ x02 ^= rotate_left(x01 + x00, 9);
+ x03 ^= rotate_left(x02 + x01, 13);
+ x00 ^= rotate_left(x03 + x02, 18);
+ x06 ^= rotate_left(x05 + x04, 7);
+ x07 ^= rotate_left(x06 + x05, 9);
+ x04 ^= rotate_left(x07 + x06, 13);
+ x05 ^= rotate_left(x04 + x07, 18);
+ x11 ^= rotate_left(x10 + x09, 7);
+ x08 ^= rotate_left(x11 + x10, 9);
+ x09 ^= rotate_left(x08 + x11, 13);
+ x10 ^= rotate_left(x09 + x08, 18);
+ x12 ^= rotate_left(x15 + x14, 7);
+ x13 ^= rotate_left(x12 + x15, 9);
+ x14 ^= rotate_left(x13 + x12, 13);
+ x15 ^= rotate_left(x14 + x13, 18);
+ }
+
+ store_le(x00 + input[ 0], output + 4 * 0);
+ store_le(x01 + input[ 1], output + 4 * 1);
+ store_le(x02 + input[ 2], output + 4 * 2);
+ store_le(x03 + input[ 3], output + 4 * 3);
+ store_le(x04 + input[ 4], output + 4 * 4);
+ store_le(x05 + input[ 5], output + 4 * 5);
+ store_le(x06 + input[ 6], output + 4 * 6);
+ store_le(x07 + input[ 7], output + 4 * 7);
+ store_le(x08 + input[ 8], output + 4 * 8);
+ store_le(x09 + input[ 9], output + 4 * 9);
+ store_le(x10 + input[10], output + 4 * 10);
+ store_le(x11 + input[11], output + 4 * 11);
+ store_le(x12 + input[12], output + 4 * 12);
+ store_le(x13 + input[13], output + 4 * 13);
+ store_le(x14 + input[14], output + 4 * 14);
+ store_le(x15 + input[15], output + 4 * 15);
+ }
+
+}
+
+/*
+* Combine cipher stream with message
+*/
+void Salsa20::cipher(const byte in[], byte out[], u32bit length)
+ {
+ while(length >= buffer.size() - position)
+ {
+ xor_buf(out, in, buffer.begin() + position, buffer.size() - position);
+ length -= (buffer.size() - position);
+ in += (buffer.size() - position);
+ out += (buffer.size() - position);
+ salsa20(buffer.begin(), state);
+
+ ++state[8];
+ if(!state[8]) // if overflow in state[8]
+ ++state[9]; // carry to state[9]
+
+ position = 0;
+ }
+
+ xor_buf(out, in, buffer.begin() + position, length);
+
+ position += length;
+ }
+
+/*
+* Salsa20 Key Schedule
+*/
+void Salsa20::key_schedule(const byte key[], u32bit length)
+ {
+ static const u32bit TAU[] =
+ { 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 };
+
+ static const u32bit SIGMA[] =
+ { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
+
+ clear();
+
+ if(length == 16)
+ {
+ state[0] = TAU[0];
+ state[1] = load_le<u32bit>(key, 0);
+ state[2] = load_le<u32bit>(key, 1);
+ state[3] = load_le<u32bit>(key, 2);
+ state[4] = load_le<u32bit>(key, 3);
+ state[5] = TAU[1];
+ state[10] = TAU[2];
+ state[11] = load_le<u32bit>(key, 0);
+ state[12] = load_le<u32bit>(key, 1);
+ state[13] = load_le<u32bit>(key, 2);
+ state[14] = load_le<u32bit>(key, 3);
+ state[15] = TAU[3];
+ }
+ else if(length == 32)
+ {
+ state[0] = SIGMA[0];
+ state[1] = load_le<u32bit>(key, 0);
+ state[2] = load_le<u32bit>(key, 1);
+ state[3] = load_le<u32bit>(key, 2);
+ state[4] = load_le<u32bit>(key, 3);
+ state[5] = SIGMA[1];
+ state[10] = SIGMA[2];
+ state[11] = load_le<u32bit>(key, 4);
+ state[12] = load_le<u32bit>(key, 5);
+ state[13] = load_le<u32bit>(key, 6);
+ state[14] = load_le<u32bit>(key, 7);
+ state[15] = SIGMA[3];
+ }
+
+ const byte ZERO[8] = { 0 };
+ resync(ZERO, sizeof(ZERO));
+ }
+
+/*
+* Return the name of this type
+*/
+void Salsa20::resync(const byte iv[], u32bit length)
+ {
+ if(length != IV_LENGTH)
+ throw Invalid_IV_Length(name(), length);
+
+ state[6] = load_le<u32bit>(iv, 0);
+ state[7] = load_le<u32bit>(iv, 1);
+ state[8] = 0;
+ state[9] = 0;
+
+ salsa20(buffer.begin(), state);
+ ++state[8];
+ if(!state[8]) // if overflow in state[8]
+ ++state[9]; // carry to state[9]
+
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string Salsa20::name() const
+ {
+ return "Salsa20";
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Salsa20::clear() throw()
+ {
+ state.clear();
+ buffer.clear();
+ position = 0;
+ }
+
+/*
+* Salsa20 Constructor
+*/
+Salsa20::Salsa20() : StreamCipher(16, 32, 16, 8)
+ {
+ clear();
+ }
+
+}
diff --git a/botan/src/stream/salsa20/salsa20.h b/botan/src/stream/salsa20/salsa20.h
new file mode 100644
index 0000000..3dbfddb
--- /dev/null
+++ b/botan/src/stream/salsa20/salsa20.h
@@ -0,0 +1,41 @@
+/*
+* Salsa20
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SALSA20_H__
+#define BOTAN_SALSA20_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* Salsa20
+*/
+class BOTAN_DLL Salsa20 : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const;
+ StreamCipher* clone() const { return new Salsa20; }
+
+ void resync(const byte[], u32bit);
+
+ Salsa20();
+ ~Salsa20() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ SecureBuffer<u32bit, 16> state;
+
+ SecureBuffer<byte, 64> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/stream/stream_cipher.cpp b/botan/src/stream/stream_cipher.cpp
new file mode 100644
index 0000000..68bb5d4
--- /dev/null
+++ b/botan/src/stream/stream_cipher.cpp
@@ -0,0 +1,30 @@
+/**
+* Stream Cipher Default Implementation for IV and Seek
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* Default StreamCipher Resync Operation
+*/
+void StreamCipher::resync(const byte[], u32bit length)
+ {
+ if(length)
+ throw Exception("The stream cipher " + name() +
+ " does not support resyncronization");
+ }
+
+/*
+* Default StreamCipher Seek Operation
+*/
+void StreamCipher::seek(u32bit)
+ {
+ throw Exception("The stream cipher " + name() + " does not support seek()");
+ }
+
+}
diff --git a/botan/src/stream/stream_cipher.h b/botan/src/stream/stream_cipher.h
new file mode 100644
index 0000000..8ea3591
--- /dev/null
+++ b/botan/src/stream/stream_cipher.h
@@ -0,0 +1,92 @@
+/**
+* Stream Cipher
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_STREAM_CIPHER_H__
+#define BOTAN_STREAM_CIPHER_H__
+
+#include <botan/sym_algo.h>
+
+namespace Botan {
+
+/*
+* Stream Cipher
+*/
+class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
+ {
+ public:
+ const u32bit IV_LENGTH;
+
+ /**
+ * Encrypt a message.
+ * @param i the plaintext
+ * @param o the byte array to hold the output, i.e. the ciphertext
+ * @param len the length of both i and o
+ */
+ void encrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+
+ /**
+ * Decrypt a message.
+ * @param i the ciphertext to decrypt
+ * @param o the byte array to hold the output, i.e. the plaintext
+ * @param len the length of both i and o
+ */
+ void decrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); }
+
+ /**
+ * Encrypt a message.
+ * @param in the plaintext as input, after the function has
+ * returned it will hold the ciphertext
+
+ * @param len the length of in
+ */
+ void encrypt(byte in[], u32bit len) { cipher(in, in, len); }
+
+ /**
+ * Decrypt a message.
+ * @param in the ciphertext as input, after the function has
+ * returned it will hold the plaintext
+ * @param len the length of in
+ */
+ void decrypt(byte in[], u32bit len) { cipher(in, in, len); }
+
+ /**
+ * Resync the cipher using the IV
+ * @param iv the initialization vector
+ * @param iv_len the length of the IV in bytes
+ */
+ virtual void resync(const byte iv[], u32bit iv_len);
+
+ /**
+ * Seek ahead in the stream.
+ * @param len the length to seek ahead.
+ */
+ virtual void seek(u32bit len);
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual StreamCipher* clone() const = 0;
+
+ /**
+ * Zeroize internal state
+ */
+ virtual void clear() throw() = 0;
+
+ StreamCipher(u32bit key_min, u32bit key_max = 0,
+ u32bit key_mod = 1,
+ u32bit iv_len = 0) :
+ SymmetricAlgorithm(key_min, key_max, key_mod),
+ IV_LENGTH(iv_len) {}
+
+ virtual ~StreamCipher() {}
+ private:
+ virtual void cipher(const byte[], byte[], u32bit) = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/stream/turing/info.txt b/botan/src/stream/turing/info.txt
new file mode 100644
index 0000000..c251a0a
--- /dev/null
+++ b/botan/src/stream/turing/info.txt
@@ -0,0 +1,15 @@
+realname "Turing"
+
+define TURING
+
+load_on auto
+
+<requires>
+stream
+</requires>
+
+<add>
+tur_tab.cpp
+turing.cpp
+turing.h
+</add>
diff --git a/botan/src/stream/turing/tur_tab.cpp b/botan/src/stream/turing/tur_tab.cpp
new file mode 100644
index 0000000..a2edd5a
--- /dev/null
+++ b/botan/src/stream/turing/tur_tab.cpp
@@ -0,0 +1,81 @@
+/*
+* Tables for Turing
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/turing.h>
+
+namespace Botan {
+
+const byte Turing::SBOX[256] = {
+ 0x61, 0x51, 0xEB, 0x19, 0xB9, 0x5D, 0x60, 0x38, 0x7C, 0xB2, 0x06, 0x12,
+ 0xC4, 0x5B, 0x16, 0x3B, 0x2B, 0x18, 0x83, 0xB0, 0x7F, 0x75, 0xFA, 0xA0,
+ 0xE9, 0xDD, 0x6D, 0x7A, 0x6B, 0x68, 0x2D, 0x49, 0xB5, 0x1C, 0x90, 0xF7,
+ 0xED, 0x9F, 0xE8, 0xCE, 0xAE, 0x77, 0xC2, 0x13, 0xFD, 0xCD, 0x3E, 0xCF,
+ 0x37, 0x6A, 0xD4, 0xDB, 0x8E, 0x65, 0x1F, 0x1A, 0x87, 0xCB, 0x40, 0x15,
+ 0x88, 0x0D, 0x35, 0xB3, 0x11, 0x0F, 0xD0, 0x30, 0x48, 0xF9, 0xA8, 0xAC,
+ 0x85, 0x27, 0x0E, 0x8A, 0xE0, 0x50, 0x64, 0xA7, 0xCC, 0xE4, 0xF1, 0x98,
+ 0xFF, 0xA1, 0x04, 0xDA, 0xD5, 0xBC, 0x1B, 0xBB, 0xD1, 0xFE, 0x31, 0xCA,
+ 0xBA, 0xD9, 0x2E, 0xF3, 0x1D, 0x47, 0x4A, 0x3D, 0x71, 0x4C, 0xAB, 0x7D,
+ 0x8D, 0xC7, 0x59, 0xB8, 0xC1, 0x96, 0x1E, 0xFC, 0x44, 0xC8, 0x7B, 0xDC,
+ 0x5C, 0x78, 0x2A, 0x9D, 0xA5, 0xF0, 0x73, 0x22, 0x89, 0x05, 0xF4, 0x07,
+ 0x21, 0x52, 0xA6, 0x28, 0x9A, 0x92, 0x69, 0x8F, 0xC5, 0xC3, 0xF5, 0xE1,
+ 0xDE, 0xEC, 0x09, 0xF2, 0xD3, 0xAF, 0x34, 0x23, 0xAA, 0xDF, 0x7E, 0x82,
+ 0x29, 0xC0, 0x24, 0x14, 0x03, 0x32, 0x4E, 0x39, 0x6F, 0xC6, 0xB1, 0x9B,
+ 0xEA, 0x72, 0x79, 0x41, 0xD8, 0x26, 0x6C, 0x5E, 0x2C, 0xB4, 0xA2, 0x53,
+ 0x57, 0xE2, 0x9C, 0x86, 0x54, 0x95, 0xB6, 0x80, 0x8C, 0x36, 0x67, 0xBD,
+ 0x08, 0x93, 0x2F, 0x99, 0x5A, 0xF8, 0x3A, 0xD7, 0x56, 0x84, 0xD2, 0x01,
+ 0xF6, 0x66, 0x4D, 0x55, 0x8B, 0x0C, 0x0B, 0x46, 0xB7, 0x3C, 0x45, 0x91,
+ 0xA4, 0xE3, 0x70, 0xD6, 0xFB, 0xE6, 0x10, 0xA9, 0xC9, 0x00, 0x9E, 0xE7,
+ 0x4F, 0x76, 0x25, 0x3F, 0x5F, 0xA3, 0x33, 0x20, 0x02, 0xEF, 0x62, 0x74,
+ 0xEE, 0x17, 0x81, 0x42, 0x58, 0x0A, 0x4B, 0x63, 0xE5, 0xBE, 0x6E, 0xAD,
+ 0xBF, 0x43, 0x94, 0x97 };
+
+const u32bit Turing::Q_BOX[256] = {
+ 0x1FAA1887, 0x4E5E435C, 0x9165C042, 0x250E6EF4, 0x5957EE20, 0xD484FED3,
+ 0xA666C502, 0x7E54E8AE, 0xD12EE9D9, 0xFC1F38D4, 0x49829B5D, 0x1B5CDF3C,
+ 0x74864249, 0xDA2E3963, 0x28F4429F, 0xC8432C35, 0x4AF40325, 0x9FC0DD70,
+ 0xD8973DED, 0x1A02DC5E, 0xCD175B42, 0xF10012BF, 0x6694D78C, 0xACAAB26B,
+ 0x4EC11B9A, 0x3F168146, 0xC0EA8EC5, 0xB38AC28F, 0x1FED5C0F, 0xAAB4101C,
+ 0xEA2DB082, 0x470929E1, 0xE71843DE, 0x508299FC, 0xE72FBC4B, 0x2E3915DD,
+ 0x9FA803FA, 0x9546B2DE, 0x3C233342, 0x0FCEE7C3, 0x24D607EF, 0x8F97EBAB,
+ 0xF37F859B, 0xCD1F2E2F, 0xC25B71DA, 0x75E2269A, 0x1E39C3D1, 0xEDA56B36,
+ 0xF8C9DEF2, 0x46C9FC5F, 0x1827B3A3, 0x70A56DDF, 0x0D25B510, 0x000F85A7,
+ 0xB2E82E71, 0x68CB8816, 0x8F951E2A, 0x72F5F6AF, 0xE4CBC2B3, 0xD34FF55D,
+ 0x2E6B6214, 0x220B83E3, 0xD39EA6F5, 0x6FE041AF, 0x6B2F1F17, 0xAD3B99EE,
+ 0x16A65EC0, 0x757016C6, 0xBA7709A4, 0xB0326E01, 0xF4B280D9, 0x4BFB1418,
+ 0xD6AFF227, 0xFD548203, 0xF56B9D96, 0x6717A8C0, 0x00D5BF6E, 0x10EE7888,
+ 0xEDFCFE64, 0x1BA193CD, 0x4B0D0184, 0x89AE4930, 0x1C014F36, 0x82A87088,
+ 0x5EAD6C2A, 0xEF22C678, 0x31204DE7, 0xC9C2E759, 0xD200248E, 0x303B446B,
+ 0xB00D9FC2, 0x9914A895, 0x906CC3A1, 0x54FEF170, 0x34C19155, 0xE27B8A66,
+ 0x131B5E69, 0xC3A8623E, 0x27BDFA35, 0x97F068CC, 0xCA3A6ACD, 0x4B55E936,
+ 0x86602DB9, 0x51DF13C1, 0x390BB16D, 0x5A80B83C, 0x22B23763, 0x39D8A911,
+ 0x2CB6BC13, 0xBF5579D7, 0x6C5C2FA8, 0xA8F4196E, 0xBCDB5476, 0x6864A866,
+ 0x416E16AD, 0x897FC515, 0x956FEB3C, 0xF6C8A306, 0x216799D9, 0x171A9133,
+ 0x6C2466DD, 0x75EB5DCD, 0xDF118F50, 0xE4AFB226, 0x26B9CEF3, 0xADB36189,
+ 0x8A7A19B1, 0xE2C73084, 0xF77DED5C, 0x8B8BC58F, 0x06DDE421, 0xB41E47FB,
+ 0xB1CC715E, 0x68C0FF99, 0x5D122F0F, 0xA4D25184, 0x097A5E6C, 0x0CBF18BC,
+ 0xC2D7C6E0, 0x8BB7E420, 0xA11F523F, 0x35D9B8A2, 0x03DA1A6B, 0x06888C02,
+ 0x7DD1E354, 0x6BBA7D79, 0x32CC7753, 0xE52D9655, 0xA9829DA1, 0x301590A7,
+ 0x9BC1C149, 0x13537F1C, 0xD3779B69, 0x2D71F2B7, 0x183C58FA, 0xACDC4418,
+ 0x8D8C8C76, 0x2620D9F0, 0x71A80D4D, 0x7A74C473, 0x449410E9, 0xA20E4211,
+ 0xF9C8082B, 0x0A6B334A, 0xB5F68ED2, 0x8243CC1B, 0x453C0FF3, 0x9BE564A0,
+ 0x4FF55A4F, 0x8740F8E7, 0xCCA7F15F, 0xE300FE21, 0x786D37D6, 0xDFD506F1,
+ 0x8EE00973, 0x17BBDE36, 0x7A670FA8, 0x5C31AB9E, 0xD4DAB618, 0xCC1F52F5,
+ 0xE358EB4F, 0x19B9E343, 0x3A8D77DD, 0xCDB93DA6, 0x140FD52D, 0x395412F8,
+ 0x2BA63360, 0x37E53AD0, 0x80700F1C, 0x7624ED0B, 0x703DC1EC, 0xB7366795,
+ 0xD6549D15, 0x66CE46D7, 0xD17ABE76, 0xA448E0A0, 0x28F07C02, 0xC31249B7,
+ 0x6E9ED6BA, 0xEAA47F78, 0xBBCFFFBD, 0xC507CA84, 0xE965F4DA, 0x8E9F35DA,
+ 0x6AD2AA44, 0x577452AC, 0xB5D674A7, 0x5461A46A, 0x6763152A, 0x9C12B7AA,
+ 0x12615927, 0x7B4FB118, 0xC351758D, 0x7E81687B, 0x5F52F0B3, 0x2D4254ED,
+ 0xD4C77271, 0x0431ACAB, 0xBEF94AEC, 0xFEE994CD, 0x9C4D9E81, 0xED623730,
+ 0xCF8A21E8, 0x51917F0B, 0xA7A9B5D6, 0xB297ADF8, 0xEED30431, 0x68CAC921,
+ 0xF1B35D46, 0x7A430A36, 0x51194022, 0x9ABCA65E, 0x85EC70BA, 0x39AEA8CC,
+ 0x737BAE8B, 0x582924D5, 0x03098A5A, 0x92396B81, 0x18DE2522, 0x745C1CB8,
+ 0xA1B8FE1D, 0x5DB3C697, 0x29164F83, 0x97C16376, 0x8419224C, 0x21203B35,
+ 0x833AC0FE, 0xD966A19A, 0xAAF0B24F, 0x40FDA998, 0xE7D52D71, 0x390896A8,
+ 0xCEE6053F, 0xD0B0D300, 0xFF99CBCC, 0x065E3D40 };
+
+}
diff --git a/botan/src/stream/turing/turing.cpp b/botan/src/stream/turing/turing.cpp
new file mode 100644
index 0000000..b988568
--- /dev/null
+++ b/botan/src/stream/turing/turing.cpp
@@ -0,0 +1,307 @@
+/*
+* Turing
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/turing.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Perform an N-way PHT
+*/
+inline void PHT(MemoryRegion<u32bit>& buf)
+ {
+ u32bit sum = 0;
+ for(u32bit j = 0; j < buf.size() - 1; ++j)
+ sum += buf[j];
+ buf[buf.size()-1] += sum;
+ sum = buf[buf.size()-1];
+ for(u32bit j = 0; j < buf.size() - 1; ++j)
+ buf[j] += sum;
+ }
+
+}
+
+/*
+* Combine cipher stream with message
+*/
+void Turing::cipher(const byte in[], byte out[], u32bit length)
+ {
+ while(length >= buffer.size() - position)
+ {
+ xor_buf(out, in, buffer.begin() + position, buffer.size() - position);
+ length -= (buffer.size() - position);
+ in += (buffer.size() - position);
+ out += (buffer.size() - position);
+ generate();
+ }
+ xor_buf(out, in, buffer.begin() + position, length);
+ position += length;
+ }
+
+/*
+* Generate cipher stream
+*/
+void Turing::generate()
+ {
+ // Table for Turing's polynomial multiplication
+ static const u32bit MULT_TAB[256] = {
+ 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, 0x97AC41D1, 0x478702B6,
+ 0x7AFAC71F, 0xAAD18478, 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
+ 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, 0xC62A4993, 0x16010AF4,
+ 0x2B7CCF5D, 0xFB578C3A, 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
+ 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, 0x32938AAD, 0xE2B8C9CA,
+ 0xDFC50C63, 0x0FEE4F04, 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
+ 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, 0xA2411084, 0x726A53E3,
+ 0x4F17964A, 0x9F3CD52D, 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
+ 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, 0x90D29A29, 0x40F9D94E,
+ 0x7D841CE7, 0xADAF5F80, 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
+ 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, 0xCFA869D6, 0x1F832AB1,
+ 0x22FEEF18, 0xF2D5AC7F, 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
+ 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, 0x3B11AAE8, 0xEB3AE98F,
+ 0xD6472C26, 0x066C6F41, 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
+ 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, 0x6A97A2AA, 0xBABCE1CD,
+ 0x87C12464, 0x57EA6703, 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
+ 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, 0x9950BA6C, 0x497BF90B,
+ 0x74063CA2, 0xA42D7FC5, 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
+ 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, 0xC8D6B22E, 0x18FDF149,
+ 0x258034E0, 0xF5AB7787, 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
+ 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, 0x3C6F7110, 0xEC443277,
+ 0xD139F7DE, 0x0112B4B9, 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
+ 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, 0xB008500E, 0x60231369,
+ 0x5D5ED6C0, 0x8D7595A7, 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
+ 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, 0x829BDAA3, 0x52B099C4,
+ 0x6FCD5C6D, 0xBFE61F0A, 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
+ 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, 0x1249408A, 0xC26203ED,
+ 0xFF1FC644, 0x2F348523, 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
+ 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, 0xE6F083B4, 0x36DBC0D3,
+ 0x0BA6057A, 0xDB8D461D, 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
+ 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, 0xB7768BF6, 0x675DC891,
+ 0x5A200D38, 0x8A0B4E5F, 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
+ 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, 0x8B19FAE6, 0x5B32B981,
+ 0x664F7C28, 0xB6643F4F, 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
+ 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, 0xDA9FF2A4, 0x0AB4B1C3,
+ 0x37C9746A, 0xE7E2370D, 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
+ 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, 0x2E26319A, 0xFE0D72FD,
+ 0xC370B754, 0x135BF433, 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
+ 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, 0xBEF4ABB3, 0x6EDFE8D4,
+ 0x53A22D7D, 0x83896E1A, 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
+ 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, 0x8C67211E, 0x5C4C6279,
+ 0x6131A7D0, 0xB11AE4B7, 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
+ 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658 };
+
+ /*
+ I tried an implementation without precomputed LFSR offsets, since
+ I thought that might allow (especially on x86-64) the use of leal to
+ compute all the offsets.. However on my Core2 with GCC 4.3 it
+ turned out significantly slower (238 Mib/s, versus 300 Mib/s
+ with precomputed offsets)
+
+ I also tried using byte vs u32bit for the offset variable (since
+ x86 memory addressing modes can be odd), but it made things even
+ slower (186 Mib/s)
+ */
+ static const byte OFFSETS[221] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 14, 15, 16,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 2, 3, 4,
+ 10, 11, 12, 13, 14, 15, 16, 0, 1, 5, 7, 8, 9,
+ 15, 16, 0, 1, 2, 3, 4, 5, 6, 10, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 0, 1, 2,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 3, 5, 6, 7,
+ 13, 14, 15, 16, 0, 1, 2, 3, 4, 8, 10, 11, 12,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 15, 16, 0,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 3, 4, 5,
+ 11, 12, 13, 14, 15, 16, 0, 1, 2, 6, 8, 9, 10,
+ 16, 0, 1, 2, 3, 4, 5, 6, 7, 11, 13, 14, 15,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 1, 2, 3,
+ 9, 10, 11, 12, 13, 14, 15, 16, 0, 4, 6, 7, 8,
+ 14, 15, 16, 0, 1, 2, 3, 4, 5, 9, 11, 12, 13,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 16, 0, 1,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 2, 4, 5, 6,
+ 12, 13, 14, 15, 16, 0, 1, 2, 3, 7, 9, 10, 11 };
+
+ for(u32bit j = 0; j != 17; ++j)
+ {
+ const byte* R_off = OFFSETS + 13*j;
+
+ u32bit R0 = R[R_off[0]];
+ u32bit R1 = R[R_off[1]];
+ u32bit R2 = R[R_off[2]];
+ u32bit R3 = R[R_off[3]];
+ u32bit R4 = R[R_off[4]];
+
+ const u32bit R5 = R[R_off[5]];
+ const u32bit R6 = R[R_off[6]];
+ const u32bit R7 = R[R_off[7]];
+ const u32bit R8 = R[R_off[8]];
+ const u32bit R9 = R[R_off[9]];
+ const u32bit R10 = R[R_off[10]];
+ const u32bit R11 = R[R_off[11]];
+ const u32bit R12 = R[R_off[12]];
+
+ R[R_off[0]] = R0 = ((R0 << 8) ^ MULT_TAB[(R0 >> 24) & 0xFF]) ^ R11 ^ R4;
+
+ u32bit A = R0;
+ u32bit B = R10;
+ u32bit C = R7;
+ u32bit D = R2;
+ u32bit E = R1;
+
+ E += A + B + C + D;
+
+ A += E;
+ B += E;
+ C += E;
+ D += E;
+
+ A = S0[get_byte(0, A)] ^ S1[get_byte(1, A)] ^
+ S2[get_byte(2, A)] ^ S3[get_byte(3, A)];
+ B = S0[get_byte(1, B)] ^ S1[get_byte(2, B)] ^
+ S2[get_byte(3, B)] ^ S3[get_byte(0, B)];
+ C = S0[get_byte(2, C)] ^ S1[get_byte(3, C)] ^
+ S2[get_byte(0, C)] ^ S3[get_byte(1, C)];
+ D = S0[get_byte(3, D)] ^ S1[get_byte(0, D)] ^
+ S2[get_byte(1, D)] ^ S3[get_byte(2, D)];
+ E = S0[get_byte(0, E)] ^ S1[get_byte(1, E)] ^
+ S2[get_byte(2, E)] ^ S3[get_byte(3, E)];
+
+ E += A + B + C + D;
+
+ A += E;
+ B += E;
+ C += E;
+ D += E;
+
+ R[R_off[1]] = R1 = ((R1 << 8) ^ MULT_TAB[(R1 >> 24) & 0xFF]) ^ R12 ^ R5;
+ R[R_off[2]] = R2 = ((R2 << 8) ^ MULT_TAB[(R2 >> 24) & 0xFF]) ^ R0 ^ R6;
+ R[R_off[3]] = ((R3 << 8) ^ MULT_TAB[(R3 >> 24) & 0xFF]) ^ R1 ^ R7;
+
+ E += R4;
+
+ R[R_off[4]] = ((R4 << 8) ^ MULT_TAB[(R4 >> 24) & 0xFF]) ^ R2 ^ R8;
+
+ A += R1;
+ B += R12;
+ C += R9;
+ D += R5;
+
+ store_be(A, buffer + 20*j + 0);
+ store_be(B, buffer + 20*j + 4);
+ store_be(C, buffer + 20*j + 8);
+ store_be(D, buffer + 20*j + 12);
+ store_be(E, buffer + 20*j + 16);
+ }
+
+ position = 0;
+ }
+
+/*
+* Turing's byte mixing step
+*/
+u32bit Turing::fixedS(u32bit W)
+ {
+ for(u32bit j = 0; j != 4; ++j)
+ {
+ byte B = SBOX[get_byte(j, W)];
+ W ^= rotate_left(Q_BOX[B], j*8);
+ W &= rotate_right(0x00FFFFFF, j*8);
+ W |= B << (24-j*8);
+ }
+ return W;
+ }
+
+/*
+* Generate the expanded Turing Sbox tables
+*/
+void Turing::gen_sbox(MemoryRegion<u32bit>& S, u32bit which,
+ const MemoryRegion<u32bit>& K)
+ {
+ for(u32bit j = 0; j != 256; ++j)
+ {
+ u32bit W = 0, C = j;
+
+ for(u32bit k = 0; k < K.size(); ++k)
+ {
+ C = SBOX[get_byte(which, K[k]) ^ C];
+ W ^= rotate_left(Q_BOX[C], k + 8*which);
+ }
+ S[j] = (W & rotate_right(0x00FFFFFF, 8*which)) | (C << (24 - 8*which));
+ }
+ }
+
+/*
+* Turing Key Schedule
+*/
+void Turing::key_schedule(const byte key[], u32bit length)
+ {
+ K.create(length / 4);
+ for(u32bit j = 0; j != length; ++j)
+ K[j/4] = (K[j/4] << 8) + key[j];
+
+ for(u32bit j = 0; j != K.size(); ++j)
+ K[j] = fixedS(K[j]);
+
+ PHT(K);
+
+ gen_sbox(S0, 0, K);
+ gen_sbox(S1, 1, K);
+ gen_sbox(S2, 2, K);
+ gen_sbox(S3, 3, K);
+
+ resync(0, 0);
+ }
+
+/*
+* Resynchronization
+*/
+void Turing::resync(const byte iv[], u32bit length)
+ {
+ if(length % 4 != 0 || length > 16)
+ throw Invalid_IV_Length(name(), length);
+
+ SecureVector<u32bit> IV(length / 4);
+ for(u32bit j = 0; j != length; ++j)
+ IV[j/4] = (IV[j/4] << 8) + iv[j];
+
+ for(u32bit j = 0; j != IV.size(); ++j)
+ R[j] = IV[j] = fixedS(IV[j]);
+
+ for(u32bit j = 0; j != K.size(); ++j)
+ R[j+IV.size()] = K[j];
+
+ R[K.size() + IV.size()] = (0x010203 << 8) | (K.size() << 4) | IV.size();
+
+ for(u32bit j = K.size() + IV.size() + 1; j != 17; ++j)
+ {
+ const u32bit W = R[j-K.size()-IV.size()-1] + R[j-1];
+ R[j] = S0[get_byte(0, W)] ^ S1[get_byte(1, W)] ^
+ S2[get_byte(2, W)] ^ S3[get_byte(3, W)];
+ }
+
+ PHT(R);
+
+ generate();
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Turing::clear() throw()
+ {
+ S0.clear();
+ S1.clear();
+ S2.clear();
+ S3.clear();
+
+ buffer.clear();
+ position = 0;
+ }
+
+}
diff --git a/botan/src/stream/turing/turing.h b/botan/src/stream/turing/turing.h
new file mode 100644
index 0000000..d48c1d8
--- /dev/null
+++ b/botan/src/stream/turing/turing.h
@@ -0,0 +1,47 @@
+/*
+* Turing
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TURING_H__
+#define BOTAN_TURING_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* Turing
+*/
+class BOTAN_DLL Turing : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "Turing"; }
+ StreamCipher* clone() const { return new Turing; }
+ Turing() : StreamCipher(4, 32, 4) { position = 0; }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void resync(const byte[], u32bit);
+ void generate();
+
+ static u32bit fixedS(u32bit);
+ static void gen_sbox(MemoryRegion<u32bit>&, u32bit,
+ const MemoryRegion<u32bit>&);
+
+ static const u32bit Q_BOX[256];
+ static const byte SBOX[256];
+
+ SecureBuffer<u32bit, 256> S0, S1, S2, S3;
+ SecureBuffer<u32bit, 17> R;
+ SecureVector<u32bit> K;
+ SecureBuffer<byte, 340> buffer;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/stream/wid_wake/info.txt b/botan/src/stream/wid_wake/info.txt
new file mode 100644
index 0000000..9441641
--- /dev/null
+++ b/botan/src/stream/wid_wake/info.txt
@@ -0,0 +1,14 @@
+realname "WiderWake"
+
+define WID_WAKE
+
+load_on auto
+
+<requires>
+stream
+</requires>
+
+<add>
+wid_wake.cpp
+wid_wake.h
+</add>
diff --git a/botan/src/stream/wid_wake/wid_wake.cpp b/botan/src/stream/wid_wake/wid_wake.cpp
new file mode 100644
index 0000000..1dc0fd7
--- /dev/null
+++ b/botan/src/stream/wid_wake/wid_wake.cpp
@@ -0,0 +1,147 @@
+/*
+* WiderWake
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/wid_wake.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Combine cipher stream with message
+*/
+void WiderWake_41_BE::cipher(const byte in[], byte out[], u32bit length)
+ {
+ while(length >= buffer.size() - position)
+ {
+ xor_buf(out, in, buffer + position, buffer.size() - position);
+ length -= (buffer.size() - position);
+ in += (buffer.size() - position);
+ out += (buffer.size() - position);
+ generate(buffer.size());
+ }
+ xor_buf(out, in, buffer + position, length);
+ position += length;
+ }
+
+/*
+* Generate cipher stream
+*/
+void WiderWake_41_BE::generate(u32bit length)
+ {
+ u32bit R0 = state[0], R1 = state[1],
+ R2 = state[2], R3 = state[3],
+ R4 = state[4];
+
+ for(u32bit j = 0; j != length; j += 8)
+ {
+ u32bit R0a;
+
+ store_be(R3, buffer + j);
+
+ R0a = R4 + R3; R3 += R2; R2 += R1; R1 += R0;
+ R0a = (R0a >> 8) ^ T[(R0a & 0xFF)];
+ R1 = (R1 >> 8) ^ T[(R1 & 0xFF)];
+ R2 = (R2 >> 8) ^ T[(R2 & 0xFF)];
+ R3 = (R3 >> 8) ^ T[(R3 & 0xFF)];
+ R4 = R0; R0 = R0a;
+
+ store_be(R3, buffer + j + 4);
+
+ R0a = R4 + R3; R3 += R2; R2 += R1; R1 += R0;
+ R0a = (R0a >> 8) ^ T[(R0a & 0xFF)];
+ R1 = (R1 >> 8) ^ T[(R1 & 0xFF)];
+ R2 = (R2 >> 8) ^ T[(R2 & 0xFF)];
+ R3 = (R3 >> 8) ^ T[(R3 & 0xFF)];
+ R4 = R0; R0 = R0a;
+ }
+
+ state[0] = R0;
+ state[1] = R1;
+ state[2] = R2;
+ state[3] = R3;
+ state[4] = R4;
+
+ position = 0;
+ }
+
+/*
+* WiderWake Key Schedule
+*/
+void WiderWake_41_BE::key_schedule(const byte key[], u32bit)
+ {
+ for(u32bit j = 0; j != 4; ++j)
+ t_key[j] = load_be<u32bit>(key, j);
+
+ static const u32bit MAGIC[8] = {
+ 0x726A8F3B, 0xE69A3B5C, 0xD3C71FE5, 0xAB3C73D2,
+ 0x4D3A8EB3, 0x0396D6E8, 0x3D4C2F7A, 0x9EE27CF3 };
+
+ for(u32bit j = 0; j != 4; ++j)
+ T[j] = t_key[j];
+ for(u32bit j = 4; j != 256; ++j)
+ {
+ u32bit X = T[j-1] + T[j-4];
+ T[j] = (X >> 3) ^ MAGIC[X % 8];
+ }
+ for(u32bit j = 0; j != 23; ++j)
+ T[j] += T[j+89];
+
+ u32bit X = T[33];
+ u32bit Z = (T[59] | 0x01000001) & 0xFF7FFFFF;
+ for(u32bit j = 0; j != 256; ++j)
+ {
+ X = (X & 0xFF7FFFFF) + Z;
+ T[j] = (T[j] & 0x00FFFFFF) ^ X;
+ }
+ X = (T[X & 0xFF] ^ X) & 0xFF;
+ Z = T[0];
+ T[0] = T[X];
+ for(u32bit j = 1; j != 256; ++j)
+ {
+ T[X] = T[j];
+ X = (T[j ^ X] ^ X) & 0xFF;
+ T[j] = T[X];
+ }
+ T[X] = Z;
+
+ position = 0;
+ const byte iv[8] = { 0 };
+ resync(iv, 8);
+ }
+
+/*
+* Resynchronization
+*/
+void WiderWake_41_BE::resync(const byte iv[], u32bit length)
+ {
+ if(length != 8)
+ throw Invalid_IV_Length(name(), length);
+
+ for(u32bit j = 0; j != 4; ++j)
+ state[j] = t_key[j];
+ state[4] = load_be<u32bit>(iv, 0);
+ state[0] ^= state[4];
+ state[2] ^= load_be<u32bit>(iv, 1);
+
+ generate(8*4);
+ generate(buffer.size());
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void WiderWake_41_BE::clear() throw()
+ {
+ position = 0;
+ t_key.clear();
+ state.clear();
+ T.clear();
+ buffer.clear();
+ }
+
+}
diff --git a/botan/src/stream/wid_wake/wid_wake.h b/botan/src/stream/wid_wake/wid_wake.h
new file mode 100644
index 0000000..4720afd
--- /dev/null
+++ b/botan/src/stream/wid_wake/wid_wake.h
@@ -0,0 +1,41 @@
+/*
+* WiderWake
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WIDER_WAKE_H__
+#define BOTAN_WIDER_WAKE_H__
+
+#include <botan/stream_cipher.h>
+
+namespace Botan {
+
+/*
+* WiderWake4+1-BE
+*/
+class BOTAN_DLL WiderWake_41_BE : public StreamCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return "WiderWake4+1-BE"; }
+ StreamCipher* clone() const { return new WiderWake_41_BE; }
+ WiderWake_41_BE() : StreamCipher(16, 16, 1, 8) {}
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+ void resync(const byte[], u32bit);
+
+ void generate(u32bit);
+
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ SecureBuffer<u32bit, 256> T;
+ SecureBuffer<u32bit, 5> state;
+ SecureBuffer<u32bit, 4> t_key;
+ u32bit position;
+ };
+
+}
+
+#endif
diff --git a/botan/src/sym_algo/info.txt b/botan/src/sym_algo/info.txt
new file mode 100644
index 0000000..03804a9
--- /dev/null
+++ b/botan/src/sym_algo/info.txt
@@ -0,0 +1,16 @@
+realname "Symmetric Algorithms"
+
+load_on auto
+
+<add>
+sym_algo.h
+symkey.cpp
+symkey.h
+</add>
+
+<requires>
+alloc
+filters
+hex
+rng
+</requires>
diff --git a/botan/src/sym_algo/sym_algo.h b/botan/src/sym_algo/sym_algo.h
new file mode 100644
index 0000000..1c8b816
--- /dev/null
+++ b/botan/src/sym_algo/sym_algo.h
@@ -0,0 +1,101 @@
+/**
+* Symmetric Algorithm Base Class
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SYMMETRIC_ALGORITHM_H__
+#define BOTAN_SYMMETRIC_ALGORITHM_H__
+
+#include <botan/types.h>
+#include <botan/exceptn.h>
+#include <botan/symkey.h>
+
+namespace Botan {
+
+/**
+* This class represents a symmetric algorithm object.
+*/
+class BOTAN_DLL SymmetricAlgorithm
+ {
+ public:
+
+ /**
+ * The maximum allowed key length.
+ */
+ const u32bit MAXIMUM_KEYLENGTH;
+
+ /**
+ * The minimal allowed key length.
+ */
+ const u32bit MINIMUM_KEYLENGTH;
+
+ /**
+ * A valid keylength is a multiple of this value.
+ */
+ const u32bit KEYLENGTH_MULTIPLE;
+
+ /**
+ * The name of the algorithm.
+ * @return the name of the algorithm
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Set the symmetric key of this object.
+ * @param key the SymmetricKey to be set.
+ */
+ void set_key(const SymmetricKey& key) throw(Invalid_Key_Length)
+ { set_key(key.begin(), key.length()); }
+
+ /**
+ * Set the symmetric key of this object.
+ * @param key the to be set as a byte array.
+ * @param the length of the byte array.
+ */
+ void set_key(const byte key[], u32bit length) throw(Invalid_Key_Length)
+ {
+ if(!valid_keylength(length))
+ throw Invalid_Key_Length(name(), length);
+ key_schedule(key, length);
+ }
+
+ /**
+ * Check whether a given key length is valid for this algorithm.
+ * @param length the key length to be checked.
+ * @return true if the key length is valid.
+ */
+ bool valid_keylength(u32bit length) const
+ {
+ return ((length >= MINIMUM_KEYLENGTH) &&
+ (length <= MAXIMUM_KEYLENGTH) &&
+ (length % KEYLENGTH_MULTIPLE == 0));
+ }
+
+ /**
+ * Construct a SymmetricAlgorithm.
+ * @param key_min the minimum allowed key length
+ * @param key_max the maximum allowed key length
+ * @param key_mod any valid key length must be a multiple of this value
+ */
+ SymmetricAlgorithm(u32bit key_min, u32bit key_max, u32bit key_mod) :
+ MAXIMUM_KEYLENGTH(key_max ? key_max : key_min),
+ MINIMUM_KEYLENGTH(key_min),
+ KEYLENGTH_MULTIPLE(key_mod)
+ {}
+
+ virtual ~SymmetricAlgorithm() {}
+ private:
+ virtual void key_schedule(const byte[], u32bit) = 0;
+ };
+
+/**
+* The two possible directions for cipher filters, determining whether they
+* actually perform encryption or decryption.
+*/
+enum Cipher_Dir { ENCRYPTION, DECRYPTION };
+
+}
+
+#endif
diff --git a/botan/src/sym_algo/symkey.cpp b/botan/src/sym_algo/symkey.cpp
new file mode 100644
index 0000000..32dfe68
--- /dev/null
+++ b/botan/src/sym_algo/symkey.cpp
@@ -0,0 +1,141 @@
+/*
+* OctetString
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/symkey.h>
+#include <botan/xor_buf.h>
+#include <botan/rng.h>
+#include <botan/pipe.h>
+#include <botan/hex.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Create an OctetString from RNG output
+*/
+OctetString::OctetString(RandomNumberGenerator& rng,
+ u32bit length)
+ {
+ bits.create(length);
+ rng.randomize(bits, length);
+ }
+
+/*
+* Create an OctetString from a hex string
+*/
+void OctetString::change(const std::string& hex_string)
+ {
+ SecureVector<byte> hex;
+ for(u32bit j = 0; j != hex_string.length(); ++j)
+ if(Hex_Decoder::is_valid(hex_string[j]))
+ hex.append(hex_string[j]);
+
+ if(hex.size() % 2 != 0)
+ throw Invalid_Argument("OctetString: hex string must encode full bytes");
+ bits.create(hex.size() / 2);
+ for(u32bit j = 0; j != bits.size(); ++j)
+ bits[j] = Hex_Decoder::decode(hex.begin() + 2*j);
+ }
+
+/*
+* Create an OctetString from a byte string
+*/
+void OctetString::change(const byte in[], u32bit n)
+ {
+ bits.create(n);
+ bits.copy(in, n);
+ }
+
+/*
+* Set the parity of each key byte to odd
+*/
+void OctetString::set_odd_parity()
+ {
+ const byte ODD_PARITY[256] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B,
+ 0x0D, 0x0D, 0x0E, 0x0E, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, 0x20, 0x20, 0x23, 0x23,
+ 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B,
+ 0x3D, 0x3D, 0x3E, 0x3E, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, 0x51, 0x51, 0x52, 0x52,
+ 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B,
+ 0x6D, 0x6D, 0x6E, 0x6E, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, 0x80, 0x80, 0x83, 0x83,
+ 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F,
+ 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B,
+ 0x9D, 0x9D, 0x9E, 0x9E, 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7,
+ 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, 0xB0, 0xB0, 0xB3, 0xB3,
+ 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF,
+ 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB,
+ 0xCD, 0xCD, 0xCE, 0xCE, 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6,
+ 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE3, 0xE3,
+ 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF,
+ 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB,
+ 0xFD, 0xFD, 0xFE, 0xFE };
+
+ for(u32bit j = 0; j != bits.size(); ++j)
+ bits[j] = ODD_PARITY[bits[j]];
+ }
+
+/*
+* Hex encode an OctetString
+*/
+std::string OctetString::as_string() const
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(bits);
+ return pipe.read_all_as_string();
+ }
+
+/*
+* XOR Operation for OctetStrings
+*/
+OctetString& OctetString::operator^=(const OctetString& k)
+ {
+ if(&k == this) { bits.clear(); return (*this); }
+ xor_buf(bits.begin(), k.begin(), std::min(length(), k.length()));
+ return (*this);
+ }
+
+/*
+* Equality Operation for OctetStrings
+*/
+bool operator==(const OctetString& s1, const OctetString& s2)
+ {
+ return (s1.bits_of() == s2.bits_of());
+ }
+
+/*
+* Unequality Operation for OctetStrings
+*/
+bool operator!=(const OctetString& s1, const OctetString& s2)
+ {
+ return !(s1 == s2);
+ }
+
+/*
+* Append Operation for OctetStrings
+*/
+OctetString operator+(const OctetString& k1, const OctetString& k2)
+ {
+ return OctetString(SecureVector<byte>(k1.bits_of(), k2.bits_of()));
+ }
+
+/*
+* XOR Operation for OctetStrings
+*/
+OctetString operator^(const OctetString& k1, const OctetString& k2)
+ {
+ SecureVector<byte> ret(std::max(k1.length(), k2.length()));
+ ret.copy(k1.begin(), k1.length());
+ xor_buf(ret, k2.begin(), k2.length());
+ return OctetString(ret);
+ }
+
+}
diff --git a/botan/src/sym_algo/symkey.h b/botan/src/sym_algo/symkey.h
new file mode 100644
index 0000000..5504297
--- /dev/null
+++ b/botan/src/sym_algo/symkey.h
@@ -0,0 +1,62 @@
+/*
+* OctetString
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SYMKEY_H__
+#define BOTAN_SYMKEY_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Octet String
+*/
+class BOTAN_DLL OctetString
+ {
+ public:
+ u32bit length() const { return bits.size(); }
+ SecureVector<byte> bits_of() const { return bits; }
+
+ const byte* begin() const { return bits.begin(); }
+ const byte* end() const { return bits.end(); }
+
+ std::string as_string() const;
+
+ OctetString& operator^=(const OctetString&);
+
+ void set_odd_parity();
+
+ void change(const std::string&);
+ void change(const byte[], u32bit);
+ void change(const MemoryRegion<byte>& in) { bits = in; }
+
+ OctetString(class RandomNumberGenerator&, u32bit len);
+ OctetString(const std::string& str = "") { change(str); }
+ OctetString(const byte in[], u32bit len) { change(in, len); }
+ OctetString(const MemoryRegion<byte>& in) { change(in); }
+ private:
+ SecureVector<byte> bits;
+ };
+
+/*
+* Operations on Octet Strings
+*/
+BOTAN_DLL bool operator==(const OctetString&, const OctetString&);
+BOTAN_DLL bool operator!=(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator+(const OctetString&, const OctetString&);
+BOTAN_DLL OctetString operator^(const OctetString&, const OctetString&);
+
+/*
+* Alternate Names
+*/
+typedef OctetString SymmetricKey;
+typedef OctetString InitializationVector;
+
+}
+
+#endif
diff --git a/botan/src/timer/cpu_counter/info.txt b/botan/src/timer/cpu_counter/info.txt
new file mode 100644
index 0000000..025663a
--- /dev/null
+++ b/botan/src/timer/cpu_counter/info.txt
@@ -0,0 +1,36 @@
+realname "Hardware Timer"
+
+define TIMER_HARDWARE
+
+load_on asm_ok
+
+<add>
+tm_hard.cpp
+tm_hard.h
+</add>
+
+<cc>
+gcc
+</cc>
+
+<arch>
+# RDTSC: Pentium and up
+i586
+i686
+athlon
+pentium4
+pentium-m
+amd64
+
+ppc # PPC timebase register
+ppc64 # PPC timebase register
+alpha # rpcc
+sparc64 # %tick register
+ia64 # ar.itc
+s390x
+hppa
+</arch>
+
+<requires>
+timer
+</requires>
diff --git a/botan/src/timer/cpu_counter/tm_hard.cpp b/botan/src/timer/cpu_counter/tm_hard.cpp
new file mode 100644
index 0000000..9e31aee
--- /dev/null
+++ b/botan/src/timer/cpu_counter/tm_hard.cpp
@@ -0,0 +1,51 @@
+/*
+* Hardware Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tm_hard.h>
+
+namespace Botan {
+
+/*
+* Get the timestamp
+*/
+u64bit Hardware_Timer::clock() const
+ {
+ u64bit rtc = 0;
+
+#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+ u32bit rtc_low = 0, rtc_high = 0;
+ asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
+ rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low;
+
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC) || defined(BOTAN_TARGET_ARCH_IS_PPC64)
+ u32bit rtc_low = 0, rtc_high = 0;
+ asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low));
+ rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low;
+
+#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+ asm volatile("rpcc %0" : "=r" (rtc));
+
+#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64)
+ asm volatile("rd %%tick, %0" : "=r" (rtc));
+
+#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
+ asm volatile("mov %0=ar.itc" : "=r" (rtc));
+
+#elif defined(BOTAN_TARGET_ARCH_IS_S390X)
+ asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc");
+
+#elif defined(BOTAN_TARGET_ARCH_IS_HPPA)
+ asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only?
+
+#else
+ #error "Unsure how to access hardware timer on this system"
+#endif
+
+ return rtc;
+ }
+
+}
diff --git a/botan/src/timer/cpu_counter/tm_hard.h b/botan/src/timer/cpu_counter/tm_hard.h
new file mode 100644
index 0000000..2e338ec
--- /dev/null
+++ b/botan/src/timer/cpu_counter/tm_hard.h
@@ -0,0 +1,33 @@
+/*
+* Hardware Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_HARDWARE_H__
+#define BOTAN_TIMER_HARDWARE_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* Hardware Timer
+*/
+class BOTAN_DLL Hardware_Timer : public Timer
+ {
+ public:
+ /*
+ @todo: Add sync(Timer& wall_clock, bool milliseconds) which busy
+ loops using wall_clock and tries to guess the tick rate of the
+ hardware counter, allowing it to be used for benchmarks, etc
+ */
+
+ std::string name() const { return "Hardware Timer"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/timer/gettimeofday/info.txt b/botan/src/timer/gettimeofday/info.txt
new file mode 100644
index 0000000..a58e808
--- /dev/null
+++ b/botan/src/timer/gettimeofday/info.txt
@@ -0,0 +1,33 @@
+realname "Unix Timer"
+
+define TIMER_UNIX
+
+load_on auto
+modset unix,beos
+
+<add>
+tm_unix.cpp
+tm_unix.h
+</add>
+
+<os>
+aix
+beos
+cygwin
+darwin
+freebsd
+dragonfly
+hpux
+irix
+linux
+netbsd
+openbsd
+qnx
+solaris
+tru64
+</os>
+
+<requires>
+timer
+</requires>
+
diff --git a/botan/src/timer/gettimeofday/tm_unix.cpp b/botan/src/timer/gettimeofday/tm_unix.cpp
new file mode 100644
index 0000000..e32df71
--- /dev/null
+++ b/botan/src/timer/gettimeofday/tm_unix.cpp
@@ -0,0 +1,24 @@
+/*
+* Unix Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tm_unix.h>
+#include <botan/util.h>
+#include <sys/time.h>
+
+namespace Botan {
+
+/*
+* Get the timestamp
+*/
+u64bit Unix_Timer::clock() const
+ {
+ struct ::timeval tv;
+ ::gettimeofday(&tv, 0);
+ return combine_timers(tv.tv_sec, tv.tv_usec, 1000000);
+ }
+
+}
diff --git a/botan/src/timer/gettimeofday/tm_unix.h b/botan/src/timer/gettimeofday/tm_unix.h
new file mode 100644
index 0000000..c304dbb
--- /dev/null
+++ b/botan/src/timer/gettimeofday/tm_unix.h
@@ -0,0 +1,27 @@
+/*
+* Unix Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_UNIX_H__
+#define BOTAN_TIMER_UNIX_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* Unix Timer
+*/
+class BOTAN_DLL Unix_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "Unix gettimeofday"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/timer/info.txt b/botan/src/timer/info.txt
new file mode 100644
index 0000000..6408dca
--- /dev/null
+++ b/botan/src/timer/info.txt
@@ -0,0 +1,14 @@
+realname "Timer Base Class"
+
+define TIMER
+
+load_on auto
+
+<add>
+timer.cpp
+timer.h
+</add>
+
+<requires>
+rng
+</requires>
diff --git a/botan/src/timer/posix_rt/info.txt b/botan/src/timer/posix_rt/info.txt
new file mode 100644
index 0000000..fa530ea
--- /dev/null
+++ b/botan/src/timer/posix_rt/info.txt
@@ -0,0 +1,29 @@
+realname "POSIX Timer"
+
+define TIMER_POSIX
+
+load_on auto
+
+<add>
+tm_posix.cpp
+tm_posix.h
+</add>
+
+<libs>
+linux -> rt
+</libs>
+
+# The *BSDs put clock_gettime in sys/time.h, not time.h like POSIX says
+<os>
+cygwin
+linux
+#freebsd
+dragonfly
+#netbsd
+#openbsd
+</os>
+
+<requires>
+timer
+</requires>
+
diff --git a/botan/src/timer/posix_rt/tm_posix.cpp b/botan/src/timer/posix_rt/tm_posix.cpp
new file mode 100644
index 0000000..d356384
--- /dev/null
+++ b/botan/src/timer/posix_rt/tm_posix.cpp
@@ -0,0 +1,33 @@
+/*
+* POSIX Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tm_posix.h>
+#include <botan/util.h>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309
+#endif
+
+#include <time.h>
+
+#ifndef CLOCK_REALTIME
+ #define CLOCK_REALTIME 0
+#endif
+
+namespace Botan {
+
+/*
+* Get the timestamp
+*/
+u64bit POSIX_Timer::clock() const
+ {
+ struct ::timespec tv;
+ ::clock_gettime(CLOCK_REALTIME, &tv);
+ return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000);
+ }
+
+}
diff --git a/botan/src/timer/posix_rt/tm_posix.h b/botan/src/timer/posix_rt/tm_posix.h
new file mode 100644
index 0000000..8bedccf
--- /dev/null
+++ b/botan/src/timer/posix_rt/tm_posix.h
@@ -0,0 +1,27 @@
+/*
+* POSIX Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_POSIX_H__
+#define BOTAN_TIMER_POSIX_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* POSIX Timer
+*/
+class BOTAN_DLL POSIX_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "POSIX clock_gettime"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/timer/timer.cpp b/botan/src/timer/timer.cpp
new file mode 100644
index 0000000..035c217
--- /dev/null
+++ b/botan/src/timer/timer.cpp
@@ -0,0 +1,52 @@
+/**
+* Timestamp Functions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/timer.h>
+#include <botan/loadstor.h>
+#include <botan/util.h>
+#include <ctime>
+
+namespace Botan {
+
+/**
+* Get the system clock
+*/
+u64bit system_time()
+ {
+ return static_cast<u64bit>(std::time(0));
+ }
+
+/**
+* Read the clock and return the output
+*/
+void Timer::poll(Entropy_Accumulator& accum)
+ {
+ const u64bit clock_value = this->clock();
+ accum.add(clock_value, 0);
+ }
+
+/**
+* Combine a two time values into a single one
+*/
+u64bit Timer::combine_timers(u32bit seconds, u32bit parts, u32bit parts_hz)
+ {
+ static const u64bit NANOSECONDS_UNITS = 1000000000;
+
+ u64bit res = seconds * NANOSECONDS_UNITS;
+ res += parts * (NANOSECONDS_UNITS / parts_hz);
+ return res;
+ }
+
+/**
+* ANSI Clock
+*/
+u64bit ANSI_Clock_Timer::clock() const
+ {
+ return combine_timers(std::time(0), std::clock(), CLOCKS_PER_SEC);
+ }
+
+}
diff --git a/botan/src/timer/timer.h b/botan/src/timer/timer.h
new file mode 100644
index 0000000..b6e8ef4
--- /dev/null
+++ b/botan/src/timer/timer.h
@@ -0,0 +1,45 @@
+/**
+* Timestamp Functions
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMERS_H__
+#define BOTAN_TIMERS_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Timer Interface
+*/
+class BOTAN_DLL Timer : public EntropySource
+ {
+ public:
+ /**
+ @return nanoseconds resolution timestamp, unknown epoch
+ */
+ virtual u64bit clock() const = 0;
+
+ void poll(Entropy_Accumulator& accum);
+
+ virtual ~Timer() {}
+ protected:
+ static u64bit combine_timers(u32bit, u32bit, u32bit);
+ };
+
+/**
+* ANSI Clock Timer
+*/
+class BOTAN_DLL ANSI_Clock_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "ANSI clock"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/timer/win32_query_perf_ctr/info.txt b/botan/src/timer/win32_query_perf_ctr/info.txt
new file mode 100644
index 0000000..4bb1ddb
--- /dev/null
+++ b/botan/src/timer/win32_query_perf_ctr/info.txt
@@ -0,0 +1,26 @@
+realname "Win32 Timer"
+
+define TIMER_WIN32
+modset win32
+
+load_on auto
+
+<add>
+tm_win32.cpp
+tm_win32.h
+</add>
+
+<os>
+cygwin
+windows
+mingw
+</os>
+
+<libs>
+windows -> user32.lib
+</libs>
+
+<requires>
+timer
+</requires>
+
diff --git a/botan/src/timer/win32_query_perf_ctr/tm_win32.cpp b/botan/src/timer/win32_query_perf_ctr/tm_win32.cpp
new file mode 100644
index 0000000..6b878e6
--- /dev/null
+++ b/botan/src/timer/win32_query_perf_ctr/tm_win32.cpp
@@ -0,0 +1,23 @@
+/*
+* Win32 Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/tm_win32.h>
+#include <windows.h>
+
+namespace Botan {
+
+/*
+* Get the timestamp
+*/
+u64bit Win32_Timer::clock() const
+ {
+ LARGE_INTEGER tv;
+ ::QueryPerformanceCounter(&tv);
+ return tv.QuadPart;
+ }
+
+}
diff --git a/botan/src/timer/win32_query_perf_ctr/tm_win32.h b/botan/src/timer/win32_query_perf_ctr/tm_win32.h
new file mode 100644
index 0000000..5bcb720
--- /dev/null
+++ b/botan/src/timer/win32_query_perf_ctr/tm_win32.h
@@ -0,0 +1,27 @@
+/*
+* Win32 Timer
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TIMER_WIN32_H__
+#define BOTAN_TIMER_WIN32_H__
+
+#include <botan/timer.h>
+
+namespace Botan {
+
+/*
+* Win32 Timer
+*/
+class BOTAN_DLL Win32_Timer : public Timer
+ {
+ public:
+ std::string name() const { return "Win32 QueryPerformanceCounter"; }
+ u64bit clock() const;
+ };
+
+}
+
+#endif
diff --git a/botan/src/utils/asm_amd64/asm_macr.h b/botan/src/utils/asm_amd64/asm_macr.h
new file mode 100644
index 0000000..287fa3e
--- /dev/null
+++ b/botan/src/utils/asm_amd64/asm_macr.h
@@ -0,0 +1,127 @@
+/*
+* Assembly Macros
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AMD64_ASM_MACROS_H__
+#define BOTAN_AMD64_ASM_MACROS_H__
+
+/*
+* General/Global Macros
+*/
+#define ALIGN .p2align 4,,15
+
+#define START_LISTING(FILENAME) \
+ .file #FILENAME; \
+ .text; \
+ ALIGN;
+
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+/*
+* Function Definitions
+*/
+#define START_FUNCTION(func_name) \
+ ALIGN; \
+ .global func_name; \
+ .type func_name,@function; \
+func_name:
+
+#define END_FUNCTION(func_name) \
+ ret
+
+/*
+* Conditional Jumps
+*/
+#define JUMP_IF_ZERO(REG, LABEL) \
+ cmp IMM(0), REG; \
+ jz LABEL
+
+#define JUMP_IF_LT(REG, NUM, LABEL) \
+ cmp IMM(NUM), REG; \
+ jl LABEL
+
+/*
+* Register Names
+*/
+#define R0 %rax
+#define R1 %rbx
+#define R2 %rcx
+#define R2_32 %ecx
+#define R3 %rdx
+#define R3_32 %edx
+#define R4 %rsp
+#define R5 %rbp
+#define R6 %rsi
+#define R6_32 %esi
+#define R7 %rdi
+#define R8 %r8
+#define R9 %r9
+#define R9_32 %r9d
+#define R10 %r10
+#define R11 %r11
+#define R12 %r12
+#define R13 %r13
+#define R14 %r14
+#define R15 %r15
+#define R16 %r16
+
+#define ARG_1 R7
+#define ARG_2 R6
+#define ARG_2_32 R6_32
+#define ARG_3 R3
+#define ARG_3_32 R3_32
+#define ARG_4 R2
+#define ARG_4_32 R2_32
+#define ARG_5 R8
+#define ARG_6 R9
+#define ARG_6_32 R9_32
+
+#define TEMP_1 R10
+#define TEMP_2 R11
+#define TEMP_3 ARG_6
+#define TEMP_4 ARG_5
+#define TEMP_5 ARG_4
+#define TEMP_5_32 ARG_4_32
+#define TEMP_6 ARG_3
+#define TEMP_7 ARG_2
+#define TEMP_8 ARG_1
+#define TEMP_9 R0
+
+/*
+* Memory Access Operations
+*/
+#define ARRAY8(REG, NUM) 8*(NUM)(REG)
+#define ARRAY4(REG, NUM) 4*(NUM)(REG)
+
+#define ASSIGN(TO, FROM) mov FROM, TO
+
+/*
+* ALU Operations
+*/
+#define IMM(VAL) $VAL
+
+#define ADD(TO, FROM) add FROM, TO
+#define ADD_LAST_CARRY(REG) adc IMM(0), REG
+#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM))
+#define ADD_W_CARRY(TO1, TO2, FROM) add FROM, TO1; adc IMM(0), TO2;
+#define SUB_IMM(TO, NUM) sub IMM(NUM), TO
+#define MUL(REG) mul REG
+
+#define XOR(TO, FROM) xor FROM, TO
+#define AND(TO, FROM) and FROM, TO
+#define OR(TO, FROM) or FROM, TO
+#define NOT(REG) not REG
+#define ZEROIZE(REG) XOR(REG, REG)
+
+#define RETURN_VALUE_IS(V) ASSIGN(%rax, V)
+
+#define ROTL_IMM(REG, NUM) rol IMM(NUM), REG
+#define ROTR_IMM(REG, NUM) ror IMM(NUM), REG
+#define ADD3_IMM(TO, FROM, NUM) lea NUM(TO,FROM,1), TO
+
+#endif
diff --git a/botan/src/utils/asm_amd64/info.txt b/botan/src/utils/asm_amd64/info.txt
new file mode 100644
index 0000000..19035b5
--- /dev/null
+++ b/botan/src/utils/asm_amd64/info.txt
@@ -0,0 +1,16 @@
+realname "Assembler Macros (x86-64)"
+
+load_on dep
+
+<add>
+asm_macr.h
+</add>
+
+<arch>
+amd64
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/botan/src/utils/asm_ia32/asm_macr.h b/botan/src/utils/asm_ia32/asm_macr.h
new file mode 100644
index 0000000..2ea6951
--- /dev/null
+++ b/botan/src/utils/asm_ia32/asm_macr.h
@@ -0,0 +1,128 @@
+/*
+* Assembly Macros
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_IA32_ASM_MACROS_H__
+#define BOTAN_IA32_ASM_MACROS_H__
+
+/*
+* General/Global Macros
+*/
+#define ALIGN .p2align 4,,15
+
+#define START_LISTING(FILENAME) \
+ .file #FILENAME; \
+ .text; \
+ ALIGN;
+
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+/*
+* Function Definitions
+*/
+#define START_FUNCTION(func_name) \
+ ALIGN; \
+ .global func_name; \
+ .type func_name,@function; \
+func_name:
+
+#define END_FUNCTION(func_name) \
+ ret
+
+/*
+* Loop Control
+*/
+#define START_LOOP(LABEL) \
+ ALIGN; \
+ LABEL##_LOOP:
+
+#define LOOP_UNTIL_EQ(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jne LABEL##_LOOP
+
+#define LOOP_UNTIL_LT(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jge LABEL##_LOOP
+
+/*
+ Conditional Jumps
+*/
+#define JUMP_IF_ZERO(REG, LABEL) \
+ cmpl IMM(0), REG; \
+ jz LABEL
+
+#define JUMP_IF_LT(REG, NUM, LABEL) \
+ cmpl IMM(NUM), REG; \
+ jl LABEL
+
+/*
+* Register Names
+*/
+#define EAX %eax
+#define EBX %ebx
+#define ECX %ecx
+#define EDX %edx
+#define EBP %ebp
+#define EDI %edi
+#define ESI %esi
+#define ESP %esp
+
+/*
+* Memory Access Operations
+*/
+#define ARRAY1(REG, NUM) (NUM)(REG)
+#define ARRAY4(REG, NUM) 4*(NUM)(REG)
+#define ARRAY4_INDIRECT(BASE, OFFSET, NUM) 4*(NUM)(BASE,OFFSET,4)
+#define ARG(NUM) 4*(PUSHED) + ARRAY4(ESP, NUM)
+
+#define ASSIGN(TO, FROM) movl FROM, TO
+#define ASSIGN_BYTE(TO, FROM) movzbl FROM, TO
+
+#define PUSH(REG) pushl REG
+#define POP(REG) popl REG
+
+#define SPILL_REGS() \
+ PUSH(EBP) ; \
+ PUSH(EDI) ; \
+ PUSH(ESI) ; \
+ PUSH(EBX)
+
+#define RESTORE_REGS() \
+ POP(EBX) ; \
+ POP(ESI) ; \
+ POP(EDI) ; \
+ POP(EBP)
+
+/*
+* ALU Operations
+*/
+#define IMM(VAL) $VAL
+
+#define ADD(TO, FROM) addl FROM, TO
+#define ADD_IMM(TO, NUM) ADD(TO, IMM(NUM))
+#define ADD_W_CARRY(TO1, TO2, FROM) addl FROM, TO1; adcl IMM(0), TO2;
+#define SUB_IMM(TO, NUM) subl IMM(NUM), TO
+#define ADD2_IMM(TO, FROM, NUM) leal NUM(FROM), TO
+#define ADD3_IMM(TO, FROM, NUM) leal NUM(TO,FROM,1), TO
+#define MUL(REG) mull REG
+
+#define SHL_IMM(REG, SHIFT) shll IMM(SHIFT), REG
+#define SHR_IMM(REG, SHIFT) shrl IMM(SHIFT), REG
+#define SHL2_3(TO, FROM) leal 0(,FROM,8), TO
+
+#define XOR(TO, FROM) xorl FROM, TO
+#define AND(TO, FROM) andl FROM, TO
+#define OR(TO, FROM) orl FROM, TO
+#define NOT(REG) notl REG
+#define ZEROIZE(REG) XOR(REG, REG)
+
+#define ROTL_IMM(REG, NUM) roll IMM(NUM), REG
+#define ROTR_IMM(REG, NUM) rorl IMM(NUM), REG
+#define BSWAP(REG) bswapl REG
+
+#endif
diff --git a/botan/src/utils/asm_ia32/info.txt b/botan/src/utils/asm_ia32/info.txt
new file mode 100644
index 0000000..4340c35
--- /dev/null
+++ b/botan/src/utils/asm_ia32/info.txt
@@ -0,0 +1,16 @@
+realname "Assembler Macros (IA-32)"
+
+load_on dep
+
+<add>
+asm_macr.h
+</add>
+
+<arch>
+ia32
+</arch>
+
+<cc>
+gcc
+icc
+</cc>
diff --git a/botan/src/utils/bit_ops.h b/botan/src/utils/bit_ops.h
new file mode 100644
index 0000000..c02ec53
--- /dev/null
+++ b/botan/src/utils/bit_ops.h
@@ -0,0 +1,91 @@
+/*
+* Bit/Word Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BIT_OPS_H__
+#define BOTAN_BIT_OPS_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Return true iff arg is 2**n for some n > 0
+* T should be an unsigned integer type
+*/
+template<typename T>
+inline bool power_of_2(T arg)
+ {
+ return ((arg != 0 && arg != 1) && ((arg & (arg-1)) == 0));
+ }
+
+/*
+* Return the index of the highest set bit
+* T is an unsigned integer type
+*/
+template<typename T>
+inline u32bit high_bit(T n)
+ {
+ for(u32bit i = 8*sizeof(T); i > 0; --i)
+ if((n >> (i - 1)) & 0x01)
+ return i;
+ return 0;
+ }
+
+/*
+* Return the index of the lowest set bit
+*/
+template<typename T>
+inline u32bit low_bit(T n)
+ {
+ for(u32bit i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return (i + 1);
+ return 0;
+ }
+
+/*
+* Return the number of significant bytes in n
+*/
+template<typename T>
+inline u32bit significant_bytes(T n)
+ {
+ for(u32bit j = 0; j != sizeof(T); ++j)
+ if(get_byte(j, n))
+ return sizeof(T)-j;
+ return 0;
+ }
+
+/*
+* Return the Hamming weight of n
+*/
+template<typename T>
+inline u32bit hamming_weight(T n)
+ {
+ const byte NIBBLE_WEIGHTS[] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+ u32bit weight = 0;
+ for(u32bit i = 0; i != 2*sizeof(T); ++i)
+ weight += NIBBLE_WEIGHTS[(n >> (4*i)) & 0x0F];
+ return weight;
+ }
+
+/*
+* Count the trailing zero bits in n
+*/
+template<typename T>
+inline u32bit ctz(T n)
+ {
+ for(u32bit i = 0; i != 8*sizeof(T); ++i)
+ if((n >> i) & 0x01)
+ return i;
+ return 8*sizeof(T);
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/bswap.h b/botan/src/utils/bswap.h
new file mode 100644
index 0000000..ec1e814
--- /dev/null
+++ b/botan/src/utils/bswap.h
@@ -0,0 +1,62 @@
+/*
+* Byte Swapping Operations
+* (C) 1999-2008 Jack Lloyd
+* (C) 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BYTE_SWAP_H__
+#define BOTAN_BYTE_SWAP_H__
+
+#include <botan/types.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+/*
+* Byte Swapping Functions
+*/
+inline u16bit reverse_bytes(u16bit input)
+ {
+ return rotate_left(input, 8);
+ }
+
+inline u32bit reverse_bytes(u32bit input)
+ {
+#if BOTAN_USE_GCC_INLINE_ASM && \
+ (defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64))
+
+ /* GCC-style inline assembly for x86 or x86-64 */
+ asm("bswapl %0" : "=r" (input) : "0" (input));
+ return input;
+
+#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32)
+ /* Visual C++ inline asm for 32-bit x86, by Yves Jerschow */
+ __asm mov eax, input;
+ __asm bswap eax;
+
+#else
+ /* Generic implementation */
+ input = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8);
+ return rotate_left(input, 16);
+#endif
+ }
+
+inline u64bit reverse_bytes(u64bit input)
+ {
+#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64)
+ asm("bswapq %0" : "=r" (input) : "0" (input));
+ return input;
+#else
+ u32bit hi = ((input >> 40) & 0x00FF00FF) | ((input >> 24) & 0xFF00FF00);
+ u32bit lo = ((input & 0xFF00FF00) >> 8) | ((input & 0x00FF00FF) << 8);
+ hi = (hi << 16) | (hi >> 16);
+ lo = (lo << 16) | (lo >> 16);
+ return (static_cast<u64bit>(lo) << 32) | hi;
+#endif
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/buf_comp/buf_comp.h b/botan/src/utils/buf_comp/buf_comp.h
new file mode 100644
index 0000000..3f1e90b
--- /dev/null
+++ b/botan/src/utils/buf_comp/buf_comp.h
@@ -0,0 +1,126 @@
+/**
+* BufferedComputation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BUFFERED_COMPUTATION_H__
+#define BOTAN_BUFFERED_COMPUTATION_H__
+
+#include <botan/secmem.h>
+
+namespace Botan {
+
+/**
+* This class represents any kind of computation which
+* uses an internal state,
+* such as hash functions.
+*/
+class BOTAN_DLL BufferedComputation
+ {
+ public:
+
+ /**
+ * The length of the output of this function in bytes.
+ */
+ const u32bit OUTPUT_LENGTH;
+
+ /**
+ * Add new input to process.
+ * @param in the input to process as a byte array
+ * @param the length of the byte array
+ */
+ void update(const byte in[], u32bit length) { add_data(in, length); }
+
+ /**
+ * Add new input to process.
+ * @param in the input to process as a MemoryRegion
+ */
+ void update(const MemoryRegion<byte>& in) { add_data(in, in.size()); }
+
+ /**
+ * Add new input to process.
+ * @param str the input to process as a std::string. Will be interpreted
+ * as a byte array based on
+ * the strings encoding.
+ */
+ void update(const std::string& str)
+ {
+ add_data(reinterpret_cast<const byte*>(str.data()), str.size());
+ }
+
+ /**
+ * Process a single byte.
+ * @param in the byte to process
+ */
+ void update(byte in) { add_data(&in, 1); }
+
+ /**
+ * Complete the computation and retrieve the
+ * final result.
+ * @param out The byte array to be filled with the result.
+ * Must be of length OUTPUT_LENGTH.
+ */
+ void final(byte out[]) { final_result(out); }
+
+ /**
+ * Complete the computation and retrieve the
+ * final result.
+ * @return a SecureVector holding the result
+ */
+ SecureVector<byte> final()
+ {
+ SecureVector<byte> output(OUTPUT_LENGTH);
+ final_result(output);
+ return output;
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process as a byte array
+ * @param length the length of the byte array
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const byte in[], u32bit length)
+ {
+ add_data(in, length);
+ return final();
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const MemoryRegion<byte>& in)
+ {
+ add_data(in, in.size());
+ return final();
+ }
+
+ /**
+ * Update and finalize computation. Does the same as calling update()
+ * and final() consecutively.
+ * @param in the input to process as a string
+ * @result the result of the call to final()
+ */
+ SecureVector<byte> process(const std::string& in)
+ {
+ update(in);
+ return final();
+ }
+
+ BufferedComputation(u32bit out_len) : OUTPUT_LENGTH(out_len) {}
+ virtual ~BufferedComputation() {}
+ private:
+ BufferedComputation& operator=(const BufferedComputation&);
+ virtual void add_data(const byte[], u32bit) = 0;
+ virtual void final_result(byte[]) = 0;
+ };
+
+}
+
+#endif
diff --git a/botan/src/utils/buf_comp/info.txt b/botan/src/utils/buf_comp/info.txt
new file mode 100644
index 0000000..bcbbc23
--- /dev/null
+++ b/botan/src/utils/buf_comp/info.txt
@@ -0,0 +1,11 @@
+realname "Buffered Computation"
+
+load_on auto
+
+<add>
+buf_comp.h
+</add>
+
+<requires>
+alloc
+</requires>
diff --git a/botan/src/utils/charset.cpp b/botan/src/utils/charset.cpp
new file mode 100644
index 0000000..53125ca
--- /dev/null
+++ b/botan/src/utils/charset.cpp
@@ -0,0 +1,201 @@
+/*
+* Character Set Handling
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/charset.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <cctype>
+
+namespace Botan {
+
+namespace Charset {
+
+namespace {
+
+/*
+* Convert from UCS-2 to ISO 8859-1
+*/
+std::string ucs2_to_latin1(const std::string& ucs2)
+ {
+ if(ucs2.size() % 2 == 1)
+ throw Decoding_Error("UCS-2 string has an odd number of bytes");
+
+ std::string latin1;
+
+ for(u32bit j = 0; j != ucs2.size(); j += 2)
+ {
+ const byte c1 = ucs2[j];
+ const byte c2 = ucs2[j+1];
+
+ if(c1 != 0)
+ throw Decoding_Error("UCS-2 has non-Latin1 characters");
+
+ latin1 += static_cast<char>(c2);
+ }
+
+ return latin1;
+ }
+
+/*
+* Convert from UTF-8 to ISO 8859-1
+*/
+std::string utf8_to_latin1(const std::string& utf8)
+ {
+ std::string iso8859;
+
+ u32bit position = 0;
+ while(position != utf8.size())
+ {
+ const byte c1 = static_cast<byte>(utf8[position++]);
+
+ if(c1 <= 0x7F)
+ iso8859 += static_cast<char>(c1);
+ else if(c1 >= 0xC0 && c1 <= 0xC7)
+ {
+ if(position == utf8.size())
+ throw Decoding_Error("UTF-8: sequence truncated");
+
+ const byte c2 = static_cast<byte>(utf8[position++]);
+ const byte iso_char = ((c1 & 0x07) << 6) | (c2 & 0x3F);
+
+ if(iso_char <= 0x7F)
+ throw Decoding_Error("UTF-8: sequence longer than needed");
+
+ iso8859 += static_cast<char>(iso_char);
+ }
+ else
+ throw Decoding_Error("UTF-8: Unicode chars not in Latin1 used");
+ }
+
+ return iso8859;
+ }
+
+/*
+* Convert from ISO 8859-1 to UTF-8
+*/
+std::string latin1_to_utf8(const std::string& iso8859)
+ {
+ std::string utf8;
+ for(u32bit j = 0; j != iso8859.size(); ++j)
+ {
+ const byte c = static_cast<byte>(iso8859[j]);
+
+ if(c <= 0x7F)
+ utf8 += static_cast<char>(c);
+ else
+ {
+ utf8 += static_cast<char>((0xC0 | (c >> 6)));
+ utf8 += static_cast<char>((0x80 | (c & 0x3F)));
+ }
+ }
+ return utf8;
+ }
+
+}
+
+/*
+* Perform character set transcoding
+*/
+std::string transcode(const std::string& str,
+ Character_Set to, Character_Set from)
+ {
+ if(to == LOCAL_CHARSET)
+ to = LATIN1_CHARSET;
+ if(from == LOCAL_CHARSET)
+ from = LATIN1_CHARSET;
+
+ if(to == from)
+ return str;
+
+ if(from == LATIN1_CHARSET && to == UTF8_CHARSET)
+ return latin1_to_utf8(str);
+ if(from == UTF8_CHARSET && to == LATIN1_CHARSET)
+ return utf8_to_latin1(str);
+ if(from == UCS2_CHARSET && to == LATIN1_CHARSET)
+ return ucs2_to_latin1(str);
+
+ throw Invalid_Argument("Unknown transcoding operation from " +
+ to_string(from) + " to " + to_string(to));
+ }
+
+/*
+* Check if a character represents a digit
+*/
+bool is_digit(char c)
+ {
+ if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' ||
+ c == '5' || c == '6' || c == '7' || c == '8' || c == '9')
+ return true;
+ return false;
+ }
+
+/*
+* Check if a character represents whitespace
+*/
+bool is_space(char c)
+ {
+ if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ return true;
+ return false;
+ }
+
+/*
+* Convert a character to a digit
+*/
+byte char2digit(char c)
+ {
+ switch(c)
+ {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ }
+
+ throw Invalid_Argument("char2digit: Input is not a digit character");
+ }
+
+/*
+* Convert a digit to a character
+*/
+char digit2char(byte b)
+ {
+ switch(b)
+ {
+ case 0: return '0';
+ case 1: return '1';
+ case 2: return '2';
+ case 3: return '3';
+ case 4: return '4';
+ case 5: return '5';
+ case 6: return '6';
+ case 7: return '7';
+ case 8: return '8';
+ case 9: return '9';
+ }
+
+ throw Invalid_Argument("digit2char: Input is not a digit");
+ }
+
+/*
+* Case-insensitive character comparison
+*/
+bool caseless_cmp(char a, char b)
+ {
+ return (std::tolower(static_cast<unsigned char>(a)) ==
+ std::tolower(static_cast<unsigned char>(b)));
+ }
+
+}
+
+}
diff --git a/botan/src/utils/charset.h b/botan/src/utils/charset.h
new file mode 100644
index 0000000..eebb199
--- /dev/null
+++ b/botan/src/utils/charset.h
@@ -0,0 +1,44 @@
+/*
+* Character Set Handling
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CHARSET_H__
+#define BOTAN_CHARSET_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* The different charsets (nominally) supported by Botan.
+*/
+enum Character_Set {
+ LOCAL_CHARSET,
+ UCS2_CHARSET,
+ UTF8_CHARSET,
+ LATIN1_CHARSET
+};
+
+namespace Charset {
+
+/*
+* Character Set Handling
+*/
+std::string transcode(const std::string&, Character_Set, Character_Set);
+
+bool is_digit(char);
+bool is_space(char);
+bool caseless_cmp(char, char);
+
+byte char2digit(char);
+char digit2char(byte);
+
+}
+
+}
+
+#endif
diff --git a/botan/src/utils/datastor/datastor.cpp b/botan/src/utils/datastor/datastor.cpp
new file mode 100644
index 0000000..129dad9
--- /dev/null
+++ b/botan/src/utils/datastor/datastor.cpp
@@ -0,0 +1,172 @@
+/*
+* Data Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/datastor.h>
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+#include <botan/stl_util.h>
+#include <botan/filters.h>
+
+namespace Botan {
+
+/*
+* Default Matcher transform operation (identity)
+*/
+std::pair<std::string, std::string>
+Data_Store::Matcher::transform(const std::string& key,
+ const std::string& value) const
+ {
+ return std::make_pair(key, value);
+ }
+
+/*
+* Data_Store Equality Comparison
+*/
+bool Data_Store::operator==(const Data_Store& other) const
+ {
+ return (contents == other.contents);
+ }
+
+/*
+* Check if this key has at least one value
+*/
+bool Data_Store::has_value(const std::string& key) const
+ {
+ return (contents.lower_bound(key) != contents.end());
+ }
+
+/*
+* Search based on an arbitrary predicate
+*/
+std::multimap<std::string, std::string>
+Data_Store::search_with(const Matcher& matcher) const
+ {
+ std::multimap<std::string, std::string> out;
+
+ std::multimap<std::string, std::string>::const_iterator i =
+ contents.begin();
+
+ while(i != contents.end())
+ {
+ if(matcher(i->first, i->second))
+ out.insert(matcher.transform(i->first, i->second));
+ ++i;
+ }
+
+ return out;
+ }
+
+/*
+* Search based on key equality
+*/
+std::vector<std::string> Data_Store::get(const std::string& looking_for) const
+ {
+ typedef std::multimap<std::string, std::string>::const_iterator iter;
+
+ std::pair<iter, iter> range = contents.equal_range(looking_for);
+
+ std::vector<std::string> out;
+ for(iter i = range.first; i != range.second; ++i)
+ out.push_back(i->second);
+ return out;
+ }
+
+/*
+* Get a single atom
+*/
+std::string Data_Store::get1(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ throw Invalid_State("Data_Store::get1: Not values for " + key);
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1: More than one value for " + key);
+
+ return vals[0];
+ }
+
+/*
+* Get a single MemoryVector atom
+*/
+MemoryVector<byte>
+Data_Store::get1_memvec(const std::string& key) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_memvec: Multiple values for " +
+ key);
+
+ if(vals.empty())
+ return MemoryVector<byte>();
+
+ Pipe pipe(new Hex_Decoder(FULL_CHECK));
+ pipe.start_msg();
+ if(vals.size())
+ pipe.write(vals[0]);
+ pipe.end_msg();
+ return pipe.read_all();
+ }
+
+/*
+* Get a single u32bit atom
+*/
+u32bit Data_Store::get1_u32bit(const std::string& key,
+ u32bit default_val) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.empty())
+ return default_val;
+ else if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1_u32bit: Multiple values for " +
+ key);
+
+ return to_u32bit(vals[0]);
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, const std::string& val)
+ {
+ multimap_insert(contents, key, val);
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, u32bit val)
+ {
+ add(key, to_string(val));
+ }
+
+/*
+* Insert a single key and value
+*/
+void Data_Store::add(const std::string& key, const MemoryRegion<byte>& val)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(val);
+ add(key, pipe.read_all_as_string());
+ }
+
+/*
+* Insert a mapping of key/value pairs
+*/
+void Data_Store::add(const std::multimap<std::string, std::string>& in)
+ {
+ std::multimap<std::string, std::string>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ contents.insert(*i);
+ ++i;
+ }
+ }
+
+}
diff --git a/botan/src/utils/datastor/datastor.h b/botan/src/utils/datastor/datastor.h
new file mode 100644
index 0000000..7ee626f
--- /dev/null
+++ b/botan/src/utils/datastor/datastor.h
@@ -0,0 +1,61 @@
+/*
+* Data Store
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DATA_STORE_H__
+#define BOTAN_DATA_STORE_H__
+
+#include <botan/secmem.h>
+#include <utility>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Botan {
+
+/**
+* Data Store
+*/
+class BOTAN_DLL Data_Store
+ {
+ public:
+ class BOTAN_DLL Matcher
+ {
+ public:
+ virtual bool operator()(const std::string&,
+ const std::string&) const = 0;
+
+ virtual std::pair<std::string, std::string>
+ transform(const std::string&, const std::string&) const;
+
+ virtual ~Matcher() {}
+ };
+
+ bool operator==(const Data_Store&) const;
+
+ std::multimap<std::string, std::string>
+ search_with(const Matcher&) const;
+
+ std::vector<std::string> get(const std::string&) const;
+
+ std::string get1(const std::string&) const;
+
+ MemoryVector<byte> get1_memvec(const std::string&) const;
+ u32bit get1_u32bit(const std::string&, u32bit = 0) const;
+
+ bool has_value(const std::string&) const;
+
+ void add(const std::multimap<std::string, std::string>&);
+ void add(const std::string&, const std::string&);
+ void add(const std::string&, u32bit);
+ void add(const std::string&, const MemoryRegion<byte>&);
+ private:
+ std::multimap<std::string, std::string> contents;
+ };
+
+}
+
+#endif
diff --git a/botan/src/utils/datastor/info.txt b/botan/src/utils/datastor/info.txt
new file mode 100644
index 0000000..8c38a3a
--- /dev/null
+++ b/botan/src/utils/datastor/info.txt
@@ -0,0 +1,13 @@
+realname "Datastore"
+
+load_on auto
+
+<add>
+datastor.cpp
+datastor.h
+</add>
+
+<requires>
+alloc
+filters
+</requires>
diff --git a/botan/src/utils/exceptn.cpp b/botan/src/utils/exceptn.cpp
new file mode 100644
index 0000000..753d634
--- /dev/null
+++ b/botan/src/utils/exceptn.cpp
@@ -0,0 +1,62 @@
+/*
+* Exceptions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+* Constructor for Invalid_Key_Length
+*/
+Invalid_Key_Length::Invalid_Key_Length(const std::string& name, u32bit length)
+ {
+ set_msg(name + " cannot accept a key of length " + to_string(length));
+ }
+
+/*
+* Constructor for Invalid_Block_Size
+*/
+Invalid_Block_Size::Invalid_Block_Size(const std::string& mode,
+ const std::string& pad)
+ {
+ set_msg("Padding method " + pad + " cannot be used with " + mode);
+ }
+
+/*
+* Constructor for Invalid_IV_Length
+*/
+Invalid_IV_Length::Invalid_IV_Length(const std::string& mode, u32bit bad_len)
+ {
+ set_msg("IV length " + to_string(bad_len) + " is invalid for " + mode);
+ }
+
+/*
+* Constructor for Algorithm_Not_Found
+*/
+Algorithm_Not_Found::Algorithm_Not_Found(const std::string& name)
+ {
+ set_msg("Could not find any algorithm named \"" + name + "\"");
+ }
+
+/*
+* Constructor for Invalid_Algorithm_Name
+*/
+Invalid_Algorithm_Name::Invalid_Algorithm_Name(const std::string& name)
+ {
+ set_msg("Invalid algorithm name: " + name);
+ }
+
+/*
+* Constructor for Config_Error
+*/
+Config_Error::Config_Error(const std::string& err, u32bit line)
+ {
+ set_msg("Config error at line " + to_string(line) + ": " + err);
+ }
+
+}
diff --git a/botan/src/utils/exceptn.h b/botan/src/utils/exceptn.h
new file mode 100644
index 0000000..a55d842
--- /dev/null
+++ b/botan/src/utils/exceptn.h
@@ -0,0 +1,197 @@
+/*
+* Exceptions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_EXCEPTION_H__
+#define BOTAN_EXCEPTION_H__
+
+#include <botan/types.h>
+#include <exception>
+#include <string>
+
+namespace Botan {
+
+/*
+* Exception Base Class
+*/
+class BOTAN_DLL Exception : public std::exception
+ {
+ public:
+ const char* what() const throw() { return msg.c_str(); }
+ Exception(const std::string& m = "Unknown error") { set_msg(m); }
+ virtual ~Exception() throw() {}
+ protected:
+ void set_msg(const std::string& m) { msg = "Botan: " + m; }
+ private:
+ std::string msg;
+ };
+
+/*
+* Invalid_Argument Exception
+*/
+struct BOTAN_DLL Invalid_Argument : public Exception
+ {
+ Invalid_Argument(const std::string& err = "") : Exception(err) {}
+ };
+
+/*
+* Invalid_Key_Length Exception
+*/
+struct BOTAN_DLL Invalid_Key_Length : public Invalid_Argument
+ {
+ Invalid_Key_Length(const std::string&, u32bit);
+ };
+
+/*
+* Invalid_Block_Size Exception
+*/
+struct BOTAN_DLL Invalid_Block_Size : public Invalid_Argument
+ {
+ Invalid_Block_Size(const std::string&, const std::string&);
+ };
+
+/*
+* Invalid_IV_Length Exception
+*/
+struct BOTAN_DLL Invalid_IV_Length : public Invalid_Argument
+ {
+ Invalid_IV_Length(const std::string&, u32bit);
+ };
+
+/*
+* Invalid_State Exception
+*/
+struct BOTAN_DLL Invalid_State : public Exception
+ {
+ Invalid_State(const std::string& err) : Exception(err) {}
+ };
+
+/*
+* PRNG_Unseeded Exception
+*/
+struct BOTAN_DLL PRNG_Unseeded : public Invalid_State
+ {
+ PRNG_Unseeded(const std::string& algo) :
+ Invalid_State("PRNG not seeded: " + algo) {}
+ };
+
+/*
+* Policy_Violation Exception
+*/
+struct BOTAN_DLL Policy_Violation : public Invalid_State
+ {
+ Policy_Violation(const std::string& err) :
+ Invalid_State("Policy violation: " + err) {}
+ };
+
+/*
+* Lookup_Error Exception
+*/
+struct BOTAN_DLL Lookup_Error : public Exception
+ {
+ Lookup_Error(const std::string& err) : Exception(err) {}
+ };
+
+/*
+* Algorithm_Not_Found Exception
+*/
+struct BOTAN_DLL Algorithm_Not_Found : public Exception
+ {
+ Algorithm_Not_Found(const std::string&);
+ };
+
+/*
+* Format_Error Exception
+*/
+struct BOTAN_DLL Format_Error : public Exception
+ {
+ Format_Error(const std::string& err = "") : Exception(err) {}
+ };
+
+/*
+* Invalid_Algorithm_Name Exception
+*/
+struct BOTAN_DLL Invalid_Algorithm_Name : public Format_Error
+ {
+ Invalid_Algorithm_Name(const std::string&);
+ };
+
+/*
+* Encoding_Error Exception
+*/
+struct BOTAN_DLL Encoding_Error : public Format_Error
+ {
+ Encoding_Error(const std::string& name) :
+ Format_Error("Encoding error: " + name) {}
+ };
+
+/*
+* Decoding_Error Exception
+*/
+struct BOTAN_DLL Decoding_Error : public Format_Error
+ {
+ Decoding_Error(const std::string& name) :
+ Format_Error("Decoding error: " + name) {}
+ };
+
+/*
+* Invalid_OID Exception
+*/
+struct BOTAN_DLL Invalid_OID : public Decoding_Error
+ {
+ Invalid_OID(const std::string& oid) :
+ Decoding_Error("Invalid ASN.1 OID: " + oid) {}
+ };
+
+/*
+* Stream_IO_Error Exception
+*/
+struct BOTAN_DLL Stream_IO_Error : public Exception
+ {
+ Stream_IO_Error(const std::string& err) :
+ Exception("I/O error: " + err) {}
+ };
+
+/*
+* Configuration Error Exception
+*/
+struct BOTAN_DLL Config_Error : public Format_Error
+ {
+ Config_Error(const std::string& err) :
+ Format_Error("Config error: " + err) {}
+ Config_Error(const std::string&, u32bit);
+ };
+
+/*
+* Integrity Failure Exception
+*/
+struct BOTAN_DLL Integrity_Failure : public Exception
+ {
+ Integrity_Failure(const std::string& err) :
+ Exception("Integrity failure: " + err) {}
+ };
+
+/*
+* Internal_Error Exception
+*/
+struct BOTAN_DLL Internal_Error : public Exception
+ {
+ Internal_Error(const std::string& err) :
+ Exception("Internal error: " + err) {}
+ };
+
+/*
+* Self Test Failure Exception
+*/
+struct BOTAN_DLL Self_Test_Failure : public Internal_Error
+ {
+ Self_Test_Failure(const std::string& err) :
+ Internal_Error("Self test failed: " + err) {}
+ };
+
+}
+
+#endif
diff --git a/botan/src/utils/info.txt b/botan/src/utils/info.txt
new file mode 100644
index 0000000..ab50b88
--- /dev/null
+++ b/botan/src/utils/info.txt
@@ -0,0 +1,33 @@
+realname "Utility Functions"
+
+define UTIL_FUNCTIONS
+
+load_on always
+
+<libs>
+tru64 -> rt
+</libs>
+
+<add>
+bit_ops.h
+bswap.h
+charset.cpp
+charset.h
+exceptn.cpp
+exceptn.h
+loadstor.h
+mem_ops.h
+mlock.cpp
+parsing.cpp
+parsing.h
+rotate.h
+stl_util.h
+types.h
+ui.cpp
+ui.h
+util.cpp
+util.h
+version.cpp
+version.h
+xor_buf.h
+</add>
diff --git a/botan/src/utils/loadstor.h b/botan/src/utils/loadstor.h
new file mode 100644
index 0000000..77ed155
--- /dev/null
+++ b/botan/src/utils/loadstor.h
@@ -0,0 +1,281 @@
+/*
+* Load/Store Operators
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LOAD_STORE_H__
+#define BOTAN_LOAD_STORE_H__
+
+#include <botan/types.h>
+#include <botan/bswap.h>
+#include <botan/rotate.h>
+
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+
+#define BOTAN_ENDIAN_N2B(x) (x)
+#define BOTAN_ENDIAN_B2N(x) (x)
+
+#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
+
+#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+
+#define BOTAN_ENDIAN_N2L(x) (x)
+#define BOTAN_ENDIAN_L2N(x) (x)
+
+#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
+#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
+
+#endif
+
+#endif
+
+namespace Botan {
+
+/*
+* Byte Extraction Function
+*/
+template<typename T> inline byte get_byte(u32bit byte_num, T input)
+ {
+ return (input >> ((sizeof(T)-1-(byte_num&(sizeof(T)-1))) << 3));
+ }
+
+/*
+* Byte to Word Conversions
+*/
+inline u16bit make_u16bit(byte i0, byte i1)
+ {
+ return ((static_cast<u16bit>(i0) << 8) | i1);
+ }
+
+inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
+ {
+ return ((static_cast<u32bit>(i0) << 24) |
+ (static_cast<u32bit>(i1) << 16) |
+ (static_cast<u32bit>(i2) << 8) |
+ (static_cast<u32bit>(i3)));
+ }
+
+inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
+ byte i4, byte i5, byte i6, byte i7)
+ {
+ return ((static_cast<u64bit>(i0) << 56) |
+ (static_cast<u64bit>(i1) << 48) |
+ (static_cast<u64bit>(i2) << 40) |
+ (static_cast<u64bit>(i3) << 32) |
+ (static_cast<u64bit>(i4) << 24) |
+ (static_cast<u64bit>(i5) << 16) |
+ (static_cast<u64bit>(i6) << 8) |
+ (static_cast<u64bit>(i7)));
+ }
+
+/*
+* Endian-Specific Word Loading Operations
+*/
+template<typename T>
+inline T load_be(const byte in[], u32bit off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(u32bit j = 0; j != sizeof(T); j++)
+ out = (out << 8) | in[j];
+ return out;
+ }
+
+template<typename T>
+inline T load_le(const byte in[], u32bit off)
+ {
+ in += off * sizeof(T);
+ T out = 0;
+ for(u32bit j = 0; j != sizeof(T); j++)
+ out = (out << 8) | in[sizeof(T)-1-j];
+ return out;
+ }
+
+template<>
+inline u16bit load_be<u16bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[0], in[1]);
+#endif
+ }
+
+template<>
+inline u16bit load_le<u16bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
+#else
+ in += off * sizeof(u16bit);
+ return make_u16bit(in[1], in[0]);
+#endif
+ }
+
+template<>
+inline u32bit load_be<u32bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[0], in[1], in[2], in[3]);
+#endif
+ }
+
+template<>
+inline u32bit load_le<u32bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
+#else
+ in += off * sizeof(u32bit);
+ return make_u32bit(in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+template<>
+inline u64bit load_be<u64bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[0], in[1], in[2], in[3],
+ in[4], in[5], in[6], in[7]);
+#endif
+ }
+
+template<>
+inline u64bit load_le<u64bit>(const byte in[], u32bit off)
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
+#else
+ in += off * sizeof(u64bit);
+ return make_u64bit(in[7], in[6], in[5], in[4],
+ in[3], in[2], in[1], in[0]);
+#endif
+ }
+
+/*
+* Endian-Specific Word Storing Operations
+*/
+inline void store_be(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+#endif
+ }
+
+inline void store_le(u16bit in, byte out[2])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(1, in);
+ out[1] = get_byte(0, in);
+#endif
+ }
+
+inline void store_be(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+#endif
+ }
+
+inline void store_le(u32bit in, byte out[4])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(3, in);
+ out[1] = get_byte(2, in);
+ out[2] = get_byte(1, in);
+ out[3] = get_byte(0, in);
+#endif
+ }
+
+inline void store_be(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
+#else
+ out[0] = get_byte(0, in);
+ out[1] = get_byte(1, in);
+ out[2] = get_byte(2, in);
+ out[3] = get_byte(3, in);
+ out[4] = get_byte(4, in);
+ out[5] = get_byte(5, in);
+ out[6] = get_byte(6, in);
+ out[7] = get_byte(7, in);
+#endif
+ }
+
+inline void store_le(u64bit in, byte out[8])
+ {
+#if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
+#else
+ out[0] = get_byte(7, in);
+ out[1] = get_byte(6, in);
+ out[2] = get_byte(5, in);
+ out[3] = get_byte(4, in);
+ out[4] = get_byte(3, in);
+ out[5] = get_byte(2, in);
+ out[6] = get_byte(1, in);
+ out[7] = get_byte(0, in);
+#endif
+ }
+
+template<typename T>
+inline void store_le(byte out[], T a, T b)
+ {
+ store_le(a, out + (0 * sizeof(T)));
+ store_le(b, out + (1 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_be(byte out[], T a, T b)
+ {
+ store_be(a, out + (0 * sizeof(T)));
+ store_be(b, out + (1 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_le(byte out[], T a, T b, T c, T d)
+ {
+ store_le(a, out + (0 * sizeof(T)));
+ store_le(b, out + (1 * sizeof(T)));
+ store_le(c, out + (2 * sizeof(T)));
+ store_le(d, out + (3 * sizeof(T)));
+ }
+
+template<typename T>
+inline void store_be(byte out[], T a, T b, T c, T d)
+ {
+ store_be(a, out + (0 * sizeof(T)));
+ store_be(b, out + (1 * sizeof(T)));
+ store_be(c, out + (2 * sizeof(T)));
+ store_be(d, out + (3 * sizeof(T)));
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/mem_ops.h b/botan/src/utils/mem_ops.h
new file mode 100644
index 0000000..0fcf34b
--- /dev/null
+++ b/botan/src/utils/mem_ops.h
@@ -0,0 +1,40 @@
+/*
+* Memory Operations
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MEMORY_OPS_H__
+#define BOTAN_MEMORY_OPS_H__
+
+#include <botan/types.h>
+#include <cstring>
+
+namespace Botan {
+
+/*
+* Memory Manipulation Functions
+*/
+template<typename T> inline void copy_mem(T* out, const T* in, u32bit n)
+ { std::memmove(out, in, sizeof(T)*n); }
+
+template<typename T> inline void clear_mem(T* ptr, u32bit n)
+ { if(n) std::memset(ptr, 0, sizeof(T)*n); }
+
+template<typename T> inline void set_mem(T* ptr, u32bit n, byte val)
+ { std::memset(ptr, val, sizeof(T)*n); }
+
+template<typename T> inline bool same_mem(const T* p1, const T* p2, u32bit n)
+ {
+ bool is_same = true;
+
+ for(u32bit i = 0; i != n; ++i)
+ is_same &= (p1[i] == p2[i]);
+
+ return is_same;
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/mlock.cpp b/botan/src/utils/mlock.cpp
new file mode 100644
index 0000000..ea0da26
--- /dev/null
+++ b/botan/src/utils/mlock.cpp
@@ -0,0 +1,55 @@
+/*
+* Memory Locking Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/util.h>
+
+#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
+ #include <sys/types.h>
+ #include <sys/mman.h>
+#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
+ #include <windows.h>
+#endif
+
+namespace Botan {
+
+/*
+* Lock an area of memory into RAM
+*/
+#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) \
+ || defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
+bool lock_mem(void* ptr, u32bit bytes)
+#else
+bool lock_mem(void*, u32bit)
+#endif
+ {
+#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
+ return (mlock(ptr, bytes) == 0);
+#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
+ return (VirtualLock(ptr, bytes) != 0);
+#else
+ return false;
+#endif
+ }
+
+/*
+* Unlock a previously locked region of memory
+*/
+#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) \
+ || defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
+void unlock_mem(void* ptr, u32bit bytes)
+#else
+void unlock_mem(void*, u32bit)
+#endif
+ {
+#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
+ munlock(ptr, bytes);
+#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
+ VirtualUnlock(ptr, bytes);
+#endif
+ }
+
+}
diff --git a/botan/src/utils/parsing.cpp b/botan/src/utils/parsing.cpp
new file mode 100644
index 0000000..bdb9e79
--- /dev/null
+++ b/botan/src/utils/parsing.cpp
@@ -0,0 +1,288 @@
+/*
+* Parser Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+#include <botan/charset.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+/*
+* Convert a string into an integer
+*/
+u32bit to_u32bit(const std::string& number)
+ {
+ u32bit n = 0;
+
+ for(std::string::const_iterator j = number.begin(); j != number.end(); ++j)
+ {
+ const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10;
+
+ byte digit = Charset::char2digit(*j);
+
+ if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5))
+ throw Decoding_Error("to_u32bit: Integer overflow");
+ n *= 10;
+ n += digit;
+ }
+ return n;
+ }
+
+/*
+* Convert an integer into a string
+*/
+std::string to_string(u64bit n, u32bit min_len)
+ {
+ std::string lenstr;
+ if(n)
+ {
+ while(n > 0)
+ {
+ lenstr = Charset::digit2char(n % 10) + lenstr;
+ n /= 10;
+ }
+ }
+ else
+ lenstr = "0";
+
+ while(lenstr.size() < min_len)
+ lenstr = "0" + lenstr;
+
+ return lenstr;
+ }
+
+/*
+* Convert a string into a time duration
+*/
+u32bit timespec_to_u32bit(const std::string& timespec)
+ {
+ if(timespec == "")
+ return 0;
+
+ const char suffix = timespec[timespec.size()-1];
+ std::string value = timespec.substr(0, timespec.size()-1);
+
+ u32bit scale = 1;
+
+ if(Charset::is_digit(suffix))
+ value += suffix;
+ else if(suffix == 's')
+ scale = 1;
+ else if(suffix == 'm')
+ scale = 60;
+ else if(suffix == 'h')
+ scale = 60 * 60;
+ else if(suffix == 'd')
+ scale = 24 * 60 * 60;
+ else if(suffix == 'y')
+ scale = 365 * 24 * 60 * 60;
+ else
+ throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec);
+
+ return scale * to_u32bit(value);
+ }
+
+/*
+* Parse a SCAN-style algorithm name
+*/
+std::vector<std::string> parse_algorithm_name(const std::string& namex)
+ {
+ if(namex.find('(') == std::string::npos &&
+ namex.find(')') == std::string::npos)
+ return std::vector<std::string>(1, namex);
+
+ std::string name = namex, substring;
+ std::vector<std::string> elems;
+ u32bit level = 0;
+
+ elems.push_back(name.substr(0, name.find('(')));
+ name = name.substr(name.find('('));
+
+ for(std::string::const_iterator j = name.begin(); j != name.end(); ++j)
+ {
+ char c = *j;
+
+ if(c == '(')
+ ++level;
+ if(c == ')')
+ {
+ if(level == 1 && j == name.end() - 1)
+ {
+ if(elems.size() == 1)
+ elems.push_back(substring.substr(1));
+ else
+ elems.push_back(substring);
+ return elems;
+ }
+
+ if(level == 0 || (level == 1 && j != name.end() - 1))
+ throw Invalid_Algorithm_Name(namex);
+ --level;
+ }
+
+ if(c == ',' && level == 1)
+ {
+ if(elems.size() == 1)
+ elems.push_back(substring.substr(1));
+ else
+ elems.push_back(substring);
+ substring.clear();
+ }
+ else
+ substring += c;
+ }
+
+ if(substring != "")
+ throw Invalid_Algorithm_Name(namex);
+
+ return elems;
+ }
+
+/*
+* Split the string on slashes
+*/
+std::vector<std::string> split_on(const std::string& str, char delim)
+ {
+ std::vector<std::string> elems;
+ if(str == "") return elems;
+
+ std::string substr;
+ for(std::string::const_iterator j = str.begin(); j != str.end(); ++j)
+ {
+ if(*j == delim)
+ {
+ if(substr != "")
+ elems.push_back(substr);
+ substr.clear();
+ }
+ else
+ substr += *j;
+ }
+
+ if(substr == "")
+ throw Format_Error("Unable to split string: " + str);
+ elems.push_back(substr);
+
+ return elems;
+ }
+
+/*
+* Parse an ASN.1 OID string
+*/
+std::vector<u32bit> parse_asn1_oid(const std::string& oid)
+ {
+ std::string substring;
+ std::vector<u32bit> oid_elems;
+
+ for(std::string::const_iterator j = oid.begin(); j != oid.end(); ++j)
+ {
+ char c = *j;
+
+ if(c == '.')
+ {
+ if(substring == "")
+ throw Invalid_OID(oid);
+ oid_elems.push_back(to_u32bit(substring));
+ substring.clear();
+ }
+ else
+ substring += c;
+ }
+
+ if(substring == "")
+ throw Invalid_OID(oid);
+ oid_elems.push_back(to_u32bit(substring));
+
+ if(oid_elems.size() < 2)
+ throw Invalid_OID(oid);
+
+ return oid_elems;
+ }
+
+/*
+* X.500 String Comparison
+*/
+bool x500_name_cmp(const std::string& name1, const std::string& name2)
+ {
+ std::string::const_iterator p1 = name1.begin();
+ std::string::const_iterator p2 = name2.begin();
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ while(p1 != name1.end() && p2 != name2.end())
+ {
+ if(Charset::is_space(*p1))
+ {
+ if(!Charset::is_space(*p2))
+ return false;
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ if(p1 == name1.end() && p2 == name2.end())
+ return true;
+ }
+
+ if(!Charset::caseless_cmp(*p1, *p2))
+ return false;
+ ++p1;
+ ++p2;
+ }
+
+ while((p1 != name1.end()) && Charset::is_space(*p1)) ++p1;
+ while((p2 != name2.end()) && Charset::is_space(*p2)) ++p2;
+
+ if((p1 != name1.end()) || (p2 != name2.end()))
+ return false;
+ return true;
+ }
+
+/*
+* Convert a decimal-dotted string to binary IP
+*/
+u32bit string_to_ipv4(const std::string& str)
+ {
+ std::vector<std::string> parts = split_on(str, '.');
+
+ if(parts.size() != 4)
+ throw Decoding_Error("Invalid IP string " + str);
+
+ u32bit ip = 0;
+
+ for(size_t j = 0; j != parts.size(); j++)
+ {
+ u32bit octet = to_u32bit(parts[j]);
+
+ if(octet > 255)
+ throw Decoding_Error("Invalid IP string " + str);
+
+ ip = (ip << 8) | (octet & 0xFF);
+ }
+
+ return ip;
+ }
+
+/*
+* Convert an IP address to decimal-dotted string
+*/
+std::string ipv4_to_string(u32bit ip)
+ {
+ std::string str;
+
+ for(size_t j = 0; j != sizeof(ip); j++)
+ {
+ if(j)
+ str += ".";
+ str += to_string(get_byte(j, ip));
+ }
+
+ return str;
+ }
+
+}
diff --git a/botan/src/utils/parsing.h b/botan/src/utils/parsing.h
new file mode 100644
index 0000000..2c29d5b
--- /dev/null
+++ b/botan/src/utils/parsing.h
@@ -0,0 +1,41 @@
+/*
+* Parser Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PARSER_H__
+#define BOTAN_PARSER_H__
+
+#include <botan/types.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/*
+* String Parsing Functions
+*/
+BOTAN_DLL std::vector<std::string> parse_algorithm_name(const std::string&);
+BOTAN_DLL std::vector<std::string> split_on(const std::string&, char);
+BOTAN_DLL std::vector<u32bit> parse_asn1_oid(const std::string&);
+BOTAN_DLL bool x500_name_cmp(const std::string&, const std::string&);
+
+/*
+* String/Integer Conversions
+*/
+BOTAN_DLL std::string to_string(u64bit, u32bit = 0);
+BOTAN_DLL u32bit to_u32bit(const std::string&);
+
+BOTAN_DLL u32bit timespec_to_u32bit(const std::string& timespec);
+
+/*
+* String/Network Address Conversions
+*/
+BOTAN_DLL u32bit string_to_ipv4(const std::string&);
+BOTAN_DLL std::string ipv4_to_string(u32bit);
+
+}
+
+#endif
diff --git a/botan/src/utils/rotate.h b/botan/src/utils/rotate.h
new file mode 100644
index 0000000..c8f8d4a
--- /dev/null
+++ b/botan/src/utils/rotate.h
@@ -0,0 +1,30 @@
+/*
+* Word Rotation Operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_WORD_ROTATE_H__
+#define BOTAN_WORD_ROTATE_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Word Rotation Functions
+*/
+template<typename T> inline T rotate_left(T input, u32bit rot)
+ {
+ return static_cast<T>((input << rot) | (input >> (8*sizeof(T)-rot)));;
+ }
+
+template<typename T> inline T rotate_right(T input, u32bit rot)
+ {
+ return static_cast<T>((input >> rot) | (input << (8*sizeof(T)-rot)));
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/stl_util.h b/botan/src/utils/stl_util.h
new file mode 100644
index 0000000..18c8b14
--- /dev/null
+++ b/botan/src/utils/stl_util.h
@@ -0,0 +1,86 @@
+/*
+* STL Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_STL_UTIL_H__
+#define BOTAN_STL_UTIL_H__
+
+#include <map>
+
+namespace Botan {
+
+/*
+* Copy-on-Predicate Algorithm
+*/
+template<typename InputIterator, typename OutputIterator, typename Predicate>
+OutputIterator copy_if(InputIterator current, InputIterator end,
+ OutputIterator dest, Predicate copy_p)
+ {
+ while(current != end)
+ {
+ if(copy_p(*current))
+ *dest++ = *current;
+ ++current;
+ }
+ return dest;
+ }
+
+/*
+* Searching through a std::map
+*/
+template<typename K, typename V>
+inline V search_map(const std::map<K, V>& mapping,
+ const K& key,
+ const V& null_result = V())
+ {
+ typename std::map<K, V>::const_iterator i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return i->second;
+ }
+
+template<typename K, typename V, typename R>
+inline R search_map(const std::map<K, V>& mapping, const K& key,
+ const R& null_result, const R& found_result)
+ {
+ typename std::map<K, V>::const_iterator i = mapping.find(key);
+ if(i == mapping.end())
+ return null_result;
+ return found_result;
+ }
+
+/*
+* Function adaptor for delete operation
+*/
+template<class T>
+class del_fun : public std::unary_function<T, void>
+ {
+ public:
+ void operator()(T* ptr) { delete ptr; }
+ };
+
+/*
+* Delete the second half of a pair of objects
+*/
+template<typename Pair>
+void delete2nd(Pair& pair)
+ {
+ delete pair.second;
+ }
+
+/*
+* Insert a key/value pair into a multimap
+*/
+template<typename K, typename V>
+void multimap_insert(std::multimap<K, V>& multimap,
+ const K& key, const V& value)
+ {
+ multimap.insert(std::make_pair(key, value));
+ }
+
+}
+
+#endif
diff --git a/botan/src/utils/types.h b/botan/src/utils/types.h
new file mode 100644
index 0000000..304628d
--- /dev/null
+++ b/botan/src/utils/types.h
@@ -0,0 +1,42 @@
+/*
+* Low Level Types
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_TYPES_H__
+#define BOTAN_TYPES_H__
+
+#include <botan/build.h>
+
+namespace Botan {
+
+typedef unsigned char byte;
+typedef unsigned short u16bit;
+typedef unsigned int u32bit;
+
+typedef signed int s32bit;
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 u64bit;
+#elif defined(__KCC)
+ typedef unsigned __long_long u64bit;
+#elif defined(__GNUG__)
+ __extension__ typedef unsigned long long u64bit;
+#else
+ typedef unsigned long long u64bit;
+#endif
+
+static const u32bit DEFAULT_BUFFERSIZE = BOTAN_DEFAULT_BUFFER_SIZE;
+
+}
+
+namespace Botan_types {
+
+using Botan::byte;
+using Botan::u32bit;
+
+}
+
+#endif
diff --git a/botan/src/utils/ui.cpp b/botan/src/utils/ui.cpp
new file mode 100644
index 0000000..e6c3430
--- /dev/null
+++ b/botan/src/utils/ui.cpp
@@ -0,0 +1,36 @@
+/*
+* User Interface
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ui.h>
+
+namespace Botan {
+
+/*
+* Get a passphrase from the user
+*/
+std::string User_Interface::get_passphrase(const std::string&,
+ const std::string&,
+ UI_Result& action) const
+ {
+ action = OK;
+
+ if(!first_try)
+ action = CANCEL_ACTION;
+
+ return preset_passphrase;
+ }
+
+/*
+* User_Interface Constructor
+*/
+User_Interface::User_Interface(const std::string& preset) :
+ preset_passphrase(preset)
+ {
+ first_try = true;
+ }
+
+}
diff --git a/botan/src/utils/ui.h b/botan/src/utils/ui.h
new file mode 100644
index 0000000..fe62c60
--- /dev/null
+++ b/botan/src/utils/ui.h
@@ -0,0 +1,36 @@
+/*
+* User Interface
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UI_H__
+#define BOTAN_UI_H__
+
+#include <botan/build.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* User Interface
+*/
+class BOTAN_DLL User_Interface
+ {
+ public:
+ enum UI_Result { OK, CANCEL_ACTION };
+
+ virtual std::string get_passphrase(const std::string&,
+ const std::string&,
+ UI_Result&) const;
+ User_Interface(const std::string& = "");
+ virtual ~User_Interface() {}
+ protected:
+ std::string preset_passphrase;
+ mutable bool first_try;
+ };
+
+}
+
+#endif
diff --git a/botan/src/utils/util.cpp b/botan/src/utils/util.cpp
new file mode 100644
index 0000000..84dfd1a
--- /dev/null
+++ b/botan/src/utils/util.cpp
@@ -0,0 +1,68 @@
+/*
+* Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/util.h>
+#include <algorithm>
+#include <cmath>
+
+namespace Botan {
+
+/*
+* Round up n to multiple of align_to
+*/
+u32bit round_up(u32bit n, u32bit align_to)
+ {
+ if(n % align_to || n == 0)
+ n += align_to - (n % align_to);
+ return n;
+ }
+
+/*
+* Round down n to multiple of align_to
+*/
+u32bit round_down(u32bit n, u32bit align_to)
+ {
+ return (n - (n % align_to));
+ }
+
+/*
+* Choose the exponent size for a DL group
+*/
+u32bit dl_work_factor(u32bit bits)
+ {
+#if 0
+ /*
+ These values were taken from RFC 3526
+ */
+ if(bits <= 1536)
+ return 90;
+ else if(bits <= 2048)
+ return 110;
+ else if(bits <= 3072)
+ return 130;
+ else if(bits <= 4096)
+ return 150;
+ else if(bits <= 6144)
+ return 170;
+ else if(bits <= 8192)
+ return 190;
+ return 256;
+#else
+ const u32bit MIN_ESTIMATE = 64;
+
+ const double log_x = bits / 1.44;
+
+ const double strength =
+ 2.76 * std::pow(log_x, 1.0/3.0) * std::pow(std::log(log_x), 2.0/3.0);
+
+ if(strength > MIN_ESTIMATE)
+ return static_cast<u32bit>(strength);
+ return MIN_ESTIMATE;
+#endif
+ }
+
+}
diff --git a/botan/src/utils/util.h b/botan/src/utils/util.h
new file mode 100644
index 0000000..ac78673
--- /dev/null
+++ b/botan/src/utils/util.h
@@ -0,0 +1,39 @@
+/*
+* Utility Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_UTIL_H__
+#define BOTAN_UTIL_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/*
+* Time Access Functions
+*/
+BOTAN_DLL u64bit system_time();
+
+/*
+* Memory Locking Functions
+*/
+BOTAN_DLL bool lock_mem(void*, u32bit);
+BOTAN_DLL void unlock_mem(void*, u32bit);
+
+/*
+* Misc Utility Functions
+*/
+BOTAN_DLL u32bit round_up(u32bit, u32bit);
+BOTAN_DLL u32bit round_down(u32bit, u32bit);
+
+/*
+* Work Factor Estimates
+*/
+BOTAN_DLL u32bit dl_work_factor(u32bit);
+
+}
+
+#endif
diff --git a/botan/src/utils/version.cpp b/botan/src/utils/version.cpp
new file mode 100644
index 0000000..d540864
--- /dev/null
+++ b/botan/src/utils/version.cpp
@@ -0,0 +1,36 @@
+/*
+* Version Information
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/version.h>
+#include <botan/parsing.h>
+
+namespace Botan {
+
+/*
+ These are intentionally compiled rather than inlined, so an
+ application running against a shared library can test the true
+ version they are running against.
+*/
+
+/*
+* Return the version as a string
+*/
+std::string version_string()
+ {
+ return to_string(version_major()) + "." +
+ to_string(version_minor()) + "." +
+ to_string(version_patch());
+ }
+
+/*
+* Return parts of the version as integers
+*/
+u32bit version_major() { return BOTAN_VERSION_MAJOR; }
+u32bit version_minor() { return BOTAN_VERSION_MINOR; }
+u32bit version_patch() { return BOTAN_VERSION_PATCH; }
+
+}
diff --git a/botan/src/utils/version.h b/botan/src/utils/version.h
new file mode 100644
index 0000000..3cc44e8
--- /dev/null
+++ b/botan/src/utils/version.h
@@ -0,0 +1,61 @@
+/*
+* Version Information
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_VERSION_H__
+#define BOTAN_VERSION_H__
+
+#include <botan/types.h>
+#include <string>
+
+namespace Botan {
+
+/*
+* Get information describing the version
+*/
+
+/**
+* Get the version string identifying the version of Botan.
+* @return the version string
+*/
+BOTAN_DLL std::string version_string();
+
+/**
+* Get the major version number.
+* @return the major version number
+*/
+BOTAN_DLL u32bit version_major();
+
+/**
+* Get the minor version number.
+* @return the minor version number
+*/
+BOTAN_DLL u32bit version_minor();
+
+/**
+* Get the patch number.
+* @return the patch number
+*/
+BOTAN_DLL u32bit version_patch();
+
+/*
+* Macros for compile-time version checks
+*/
+#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+/**
+* Compare using BOTAN_VERSION_CODE_FOR, as in
+* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
+* # error "Botan version too old"
+* # endif
+*/
+#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \
+ BOTAN_VERSION_MINOR, \
+ BOTAN_VERSION_PATCH)
+
+}
+
+#endif
diff --git a/botan/src/utils/xor_buf.h b/botan/src/utils/xor_buf.h
new file mode 100644
index 0000000..39781f0
--- /dev/null
+++ b/botan/src/utils/xor_buf.h
@@ -0,0 +1,74 @@
+/**
+* XOR operations
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_XOR_BUF_H__
+#define BOTAN_XOR_BUF_H__
+
+#include <botan/types.h>
+
+namespace Botan {
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
+* @param out the input/output buffer
+* @param in the read-only input buffer
+* @param length the length of the buffers
+*/
+inline void xor_buf(byte out[], const byte in[], u32bit length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in);
+#else
+ out[0] ^= in[0]; out[1] ^= in[1];
+ out[2] ^= in[2]; out[3] ^= in[3];
+ out[4] ^= in[4]; out[5] ^= in[5];
+ out[6] ^= in[6]; out[7] ^= in[7];
+#endif
+
+ out += 8; in += 8; length -= 8;
+ }
+ for(u32bit j = 0; j != length; ++j)
+ out[j] ^= in[j];
+ }
+
+/**
+* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
+* @param out the output buffer
+* @param in the first input buffer
+* @param in2 the second output buffer
+* @param length the length of the three buffers
+*/
+inline void xor_buf(byte out[],
+ const byte in[],
+ const byte in2[],
+ u32bit length)
+ {
+ while(length >= 8)
+ {
+#if BOTAN_UNALIGNED_LOADSTOR_OK
+ *reinterpret_cast<u64bit*>(out) =
+ *reinterpret_cast<const u64bit*>(in) ^
+ *reinterpret_cast<const u64bit*>(in2);
+#else
+ out[0] = in[0] ^ in2[0]; out[1] = in[1] ^ in2[1];
+ out[2] = in[2] ^ in2[2]; out[3] = in[3] ^ in2[3];
+ out[4] = in[4] ^ in2[4]; out[5] = in[5] ^ in2[5];
+ out[6] = in[6] ^ in2[6]; out[7] = in[7] ^ in2[7];
+#endif
+
+ in += 8; in2 += 8; out += 8; length -= 8;
+ }
+
+ for(u32bit j = 0; j != length; ++j)
+ out[j] = in[j] ^ in2[j];
+ }
+
+}
+
+#endif
diff --git a/botan/wrappers/boost-python/botan/__init__.py b/botan/wrappers/boost-python/botan/__init__.py
new file mode 100644
index 0000000..9e136ed
--- /dev/null
+++ b/botan/wrappers/boost-python/botan/__init__.py
@@ -0,0 +1,27 @@
+from _botan import *
+
+# Initialize the library when the module is imported
+init = LibraryInitializer()
+
+class SymmetricKey(OctetString):
+ pass
+
+class InitializationVector(OctetString):
+ pass
+
+def Filter(name, key = None, iv = None, dir = None):
+ if key != None and iv != None and dir != None:
+ return make_filter(name, key, iv, dir)
+ elif key != None and dir != None:
+ return make_filter(name, key, dir)
+ elif key != None:
+ return make_filter(name, key)
+ else:
+ return make_filter(name)
+
+def Pipe(*filters):
+ pipe = PipeObj()
+ for filter in filters:
+ if filter:
+ pipe.append(filter)
+ return pipe
diff --git a/botan/wrappers/boost-python/nisttest.py b/botan/wrappers/boost-python/nisttest.py
new file mode 100644
index 0000000..f9fdb5f
--- /dev/null
+++ b/botan/wrappers/boost-python/nisttest.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+import sys, os, botan
+from os.path import join;
+
+def validate(ca_certs, certs, crls, ee_certs):
+ store = botan.X509_Store()
+ for cert in certs:
+ if cert not in ee_certs:
+ store.add_cert(botan.X509_Certificate(cert), cert in ca_certs)
+
+ for crl in crls:
+ r = store.add_crl(botan.X509_CRL(crl))
+ if r != botan.verify_result.verified:
+ return r
+
+ for ee in ee_certs:
+ r = store.validate(botan.X509_Certificate(ee))
+ if r != botan.verify_result.verified:
+ return r
+
+ return botan.verify_result.verified
+
+def run_test(files, rootdir, testname, expected):
+ crls = [join(rootdir,x) for x in files if x.endswith(".crl")]
+ certs = [join(rootdir,x) for x in files if x.endswith(".crt")]
+ end_entity = [x for x in certs if x.find("end.crt") != -1]
+ ca_certs = [x for x in certs if x.find("root.crt") != -1]
+
+ print "%s..." % testname,
+
+ result = validate(ca_certs, certs, crls, end_entity)
+ result = repr(result).replace('botan._botan.verify_result.', '')
+
+ if result != expected:
+ print "FAILED: got %s, expected %s" % (result, expected)
+ else:
+ print "passed"
+
+def main():
+ def load_results(file):
+ results = {}
+ for line in open(file, 'r'):
+ line = line[0:line.find('#')].strip()
+ if line:
+ test,result = line.split(' ')
+ results[test] = result
+ return results
+
+ results = load_results('results.txt')
+
+ for root, dirs, files in os.walk('../../checks/nist_tests/tests'):
+ if files:
+ thistest = root[root.rfind('/')+1:]
+ if thistest in results:
+ run_test(files, root, thistest, results[thistest])
+ else:
+ print "%s... skipping - no expected result set" % thistest
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/botan/wrappers/boost-python/results.txt b/botan/wrappers/boost-python/results.txt
new file mode 100644
index 0000000..7a38240
--- /dev/null
+++ b/botan/wrappers/boost-python/results.txt
@@ -0,0 +1,60 @@
+# This is the file of expected results for nisttest.py
+test01 verified
+test02 signature_error
+test03 signature_error
+test04 verified
+test05 cert_not_yet_valid
+test06 cert_not_yet_valid
+test07 verified
+test08 cert_not_yet_valid
+test09 cert_has_expired
+test10 cert_has_expired
+test11 cert_has_expired
+test12 verified
+test13 cert_issuer_not_found
+test14 cert_issuer_not_found
+test15 verified
+test16 verified
+test17 verified
+test18 verified
+# changed; should be no_revocation_data_available, but I don't want to
+# force people to use CRLs
+test19 verified
+test20 cert_is_revoked
+test21 cert_is_revoked
+test22 ca_cert_not_for_cert_issuer
+test23 ca_cert_not_for_cert_issuer
+test24 verified
+test25 ca_cert_not_for_cert_issuer
+test26 verified
+test27 verified
+test28 ca_cert_not_for_cert_issuer
+test29 ca_cert_not_for_cert_issuer
+test30 verified
+test31 ca_cert_not_for_crl_issuer
+test32 ca_cert_not_for_crl_issuer
+test33 verified
+test54 cert_chain_too_long
+test55 cert_chain_too_long
+test56 verified
+test57 verified
+test58 cert_chain_too_long
+test59 cert_chain_too_long
+test60 cert_chain_too_long
+test61 cert_chain_too_long
+test62 verified
+test63 verified
+test64 signature_error
+# changed; I have no idea why this test is supposed to fail
+test65 verified
+test66 crl_issuer_not_found
+# changed; one of the CRLs has an unknown creator, so we fail
+# prior to getting to the end-entity check
+test67 crl_issuer_not_found
+test68 cert_is_revoked
+test69 cert_is_revoked
+test70 cert_is_revoked
+test71 cert_is_revoked
+test72 crl_has_expired
+test73 crl_has_expired
+test74 verified
diff --git a/botan/wrappers/boost-python/rng_test.py b/botan/wrappers/boost-python/rng_test.py
new file mode 100644
index 0000000..06c79b8
--- /dev/null
+++ b/botan/wrappers/boost-python/rng_test.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+import botan
+
+rng = botan.RandomNumberGenerator()
+
+print "name", rng.name()
+
+rng.add_entropy("blah")
+
+print "random 16", rng.gen_random(16).encode("hex")
+print "random 32", rng.gen_random(32).encode("base64"),
+
+rng.reseed()
+
+for i in range(0, 10):
+ print rng.gen_random_byte(),
+print
+
+rng.add_entropy("blah")
+
+print "random 16", rng.gen_random(16).encode("hex")
diff --git a/botan/wrappers/boost-python/src/block.cpp b/botan/wrappers/boost-python/src/block.cpp
new file mode 100644
index 0000000..185b888
--- /dev/null
+++ b/botan/wrappers/boost-python/src/block.cpp
@@ -0,0 +1,152 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "python_botan.h"
+
+class Py_BlockCipher : public BlockCipher
+ {
+ public:
+ virtual std::string enc_str(const std::string&) const = 0;
+ virtual std::string dec_str(const std::string&) const = 0;
+ virtual void set_key_obj(const OctetString&) = 0;
+
+ void clear() throw() {}
+
+ void enc(const byte in[], byte out[]) const
+ {
+ string2binary(
+ enc_str(make_string(in, BLOCK_SIZE)),
+ out, BLOCK_SIZE);
+ }
+
+ void dec(const byte in[], byte out[]) const
+ {
+ string2binary(
+ dec_str(make_string(in, BLOCK_SIZE)),
+ out, BLOCK_SIZE);
+ }
+
+ void key(const byte key[], u32bit len)
+ {
+ set_key_obj(OctetString(key, len));
+ }
+
+ Py_BlockCipher(u32bit bs, u32bit kmin, u32bit kmax, u32bit kmod) :
+ BlockCipher(bs, kmin, kmax, kmod)
+ {
+ }
+ };
+
+std::string encrypt_string(BlockCipher* cipher, const std::string& in)
+ {
+ if(in.size() != cipher->BLOCK_SIZE)
+ throw Bad_Size(in.size(), cipher->BLOCK_SIZE);
+
+ SecureVector<byte> out(cipher->BLOCK_SIZE);
+ cipher->encrypt((const byte*)in.data(), out);
+ return make_string(out);
+ }
+
+std::string decrypt_string(BlockCipher* cipher, const std::string& in)
+ {
+ if(in.size() != cipher->BLOCK_SIZE)
+ throw Bad_Size(in.size(), cipher->BLOCK_SIZE);
+
+ SecureVector<byte> out(cipher->BLOCK_SIZE);
+ cipher->decrypt((const byte*)in.data(), out);
+ return make_string(out);
+ }
+
+class Wrapped_Block_Cipher : public BlockCipher
+ {
+ public:
+ void clear() throw() { cipher->clear(); }
+
+ void enc(const byte in[], byte out[]) const { cipher->encrypt(in, out); }
+ void dec(const byte in[], byte out[]) const { cipher->decrypt(in, out); }
+ void key(const byte key[], u32bit len) { cipher->set_key(key, len); }
+ std::string name() const { return cipher->name(); }
+ BlockCipher* clone() const { return cipher->clone(); }
+
+ Wrapped_Block_Cipher(python::object py_obj, BlockCipher* c) :
+ BlockCipher(c->BLOCK_SIZE, c->MINIMUM_KEYLENGTH,
+ c->MAXIMUM_KEYLENGTH, c->KEYLENGTH_MULTIPLE),
+ obj(py_obj), cipher(c) {}
+ private:
+ python::object obj;
+ BlockCipher* cipher;
+ };
+
+class Py_BlockCipher_Wrapper : public Py_BlockCipher,
+ public python::wrapper<Py_BlockCipher>
+ {
+ public:
+ BlockCipher* clone() const
+ {
+ python::object self = get_owner(this);
+ python::object py_clone = self.attr("__class__")();
+ BlockCipher* bc = python::extract<BlockCipher*>(py_clone);
+ return new Wrapped_Block_Cipher(py_clone, bc);
+ }
+
+ void clear() throw()
+ {
+ this->get_override("clear")();
+ }
+
+ std::string name() const
+ {
+ return this->get_override("name")();
+ }
+
+ std::string enc_str(const std::string& in) const
+ {
+ return this->get_override("encrypt")(in);
+ }
+
+ std::string dec_str(const std::string& in) const
+ {
+ return this->get_override("decrypt")(in);
+ }
+
+ void set_key_obj(const OctetString& key)
+ {
+ this->get_override("set_key")(key);
+ }
+
+ Py_BlockCipher_Wrapper(u32bit bs, u32bit kmin,
+ u32bit kmax, u32bit kmod) :
+ Py_BlockCipher(bs, kmin, kmax, kmod) {}
+ };
+
+void export_block_ciphers()
+ {
+ void (BlockCipher::*set_key_ptr)(const OctetString&) =
+ &BlockCipher::set_key;
+
+ python::class_<BlockCipher, boost::noncopyable>
+ ("BlockCipher", python::no_init)
+ .def("__init__", python::make_constructor(get_block_cipher))
+ .def_readonly("block_size", &BlockCipher::BLOCK_SIZE)
+ .def_readonly("keylength_min", &BlockCipher::MINIMUM_KEYLENGTH)
+ .def_readonly("keylength_max", &BlockCipher::MAXIMUM_KEYLENGTH)
+ .def_readonly("keylength_mod", &BlockCipher::KEYLENGTH_MULTIPLE)
+ .def("valid_keylength", &BlockCipher::valid_keylength)
+ .def("name", &BlockCipher::name)
+ .def("set_key", set_key_ptr)
+ .def("encrypt", encrypt_string)
+ .def("decrypt", decrypt_string);
+
+ python::class_<Py_BlockCipher_Wrapper, python::bases<BlockCipher>,
+ boost::noncopyable>
+ ("BlockCipherImpl", python::init<u32bit, u32bit, u32bit, u32bit>())
+ .def("name", python::pure_virtual(&Py_BlockCipher::name))
+ .def("encrypt", python::pure_virtual(&Py_BlockCipher::enc_str))
+ .def("decrypt", python::pure_virtual(&Py_BlockCipher::dec_str))
+ .def("set_key", python::pure_virtual(&Py_BlockCipher::set_key_obj));
+ }
diff --git a/botan/wrappers/boost-python/src/core.cpp b/botan/wrappers/boost-python/src/core.cpp
new file mode 100644
index 0000000..7ef2a99
--- /dev/null
+++ b/botan/wrappers/boost-python/src/core.cpp
@@ -0,0 +1,73 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+#include "python_botan.h"
+
+class Python_RandomNumberGenerator
+ {
+ public:
+ Python_RandomNumberGenerator()
+ { rng = RandomNumberGenerator::make_rng(); }
+ ~Python_RandomNumberGenerator() { delete rng; }
+
+ std::string name() const { return rng->name(); }
+
+ void reseed() { rng->reseed(); }
+
+ int gen_random_byte() { return rng->next_byte(); }
+
+ std::string gen_random(int n)
+ {
+ std::string s(n, 0);
+ rng->randomize(reinterpret_cast<byte*>(&s[0]), n);
+ return s;
+ }
+
+ void add_entropy(const std::string& in)
+ { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); }
+
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+BOOST_PYTHON_MODULE(_botan)
+ {
+ python::class_<LibraryInitializer>("LibraryInitializer")
+ .def(python::init< python::optional<std::string> >());
+
+ python::class_<Python_RandomNumberGenerator>("RandomNumberGenerator")
+ .def(python::init<>())
+ .def("__str__", &Python_RandomNumberGenerator::name)
+ .def("name", &Python_RandomNumberGenerator::name)
+ .def("reseed", &Python_RandomNumberGenerator::reseed)
+ .def("add_entropy", &Python_RandomNumberGenerator::add_entropy)
+ .def("gen_random_byte", &Python_RandomNumberGenerator::gen_random_byte)
+ .def("gen_random", &Python_RandomNumberGenerator::gen_random);
+
+ python::class_<OctetString>("OctetString")
+ .def(python::init< python::optional<std::string> >())
+ //.def(python::init< u32bit >())
+ .def("__str__", &OctetString::as_string)
+ .def("__len__", &OctetString::length);
+
+ python::enum_<Cipher_Dir>("cipher_dir")
+ .value("encryption", ENCRYPTION)
+ .value("decryption", DECRYPTION);
+
+ export_block_ciphers();
+ export_stream_ciphers();
+ export_hash_functions();
+ export_macs();
+
+ export_filters();
+ export_pk();
+ export_x509();
+ }
diff --git a/botan/wrappers/boost-python/src/filter.cpp b/botan/wrappers/boost-python/src/filter.cpp
new file mode 100644
index 0000000..830e090
--- /dev/null
+++ b/botan/wrappers/boost-python/src/filter.cpp
@@ -0,0 +1,176 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <boost/python.hpp>
+using namespace boost::python;
+
+#include <botan/pipe.h>
+#include <botan/lookup.h>
+using namespace Botan;
+
+class Py_Filter : public Filter
+ {
+ public:
+ virtual void write_str(const std::string&) = 0;
+
+ void write(const byte data[], u32bit length)
+ {
+ write_str(std::string((const char*)data, length));
+ }
+
+ void send_str(const std::string& str)
+ {
+ printf("Py_Filter::send_str\n");
+ send((const byte*)str.data(), str.length());
+ }
+ };
+
+class FilterWrapper : public Py_Filter, public wrapper<Py_Filter>
+ {
+ public:
+ void start_msg()
+ {
+ printf("wrapper start_msg\n");
+ if(override start_msg = this->get_override("start_msg"))
+ start_msg();
+ }
+
+ void end_msg()
+ {
+ printf("wrapper end_msg\n");
+ if(override end_msg = this->get_override("end_msg"))
+ end_msg();
+ }
+
+ void default_start_msg() {}
+ void default_end_msg() {}
+
+ virtual void write_str(const std::string& str)
+ {
+ printf("wrapper write\n");
+ this->get_override("write")(str);
+ }
+ };
+
+Filter* return_or_raise(Filter* filter, const std::string& name)
+ {
+ if(filter)
+ return filter;
+ throw Invalid_Argument("Filter " + name + " could not be found");
+ }
+
+Filter* make_filter1(const std::string& name)
+ {
+ Filter* filter = 0;
+
+ if(have_hash(name)) filter = new Hash_Filter(name);
+ else if(name == "Hex_Encoder") filter = new Hex_Encoder;
+ else if(name == "Hex_Decoder") filter = new Hex_Decoder;
+ else if(name == "Base64_Encoder") filter = new Base64_Encoder;
+ else if(name == "Base64_Decoder") filter = new Base64_Decoder;
+
+ return return_or_raise(filter, name);
+ }
+
+Filter* make_filter2(const std::string& name,
+ const SymmetricKey& key)
+ {
+ Filter* filter = 0;
+
+ if(have_mac(name))
+ filter = new MAC_Filter(name, key);
+ else if(have_stream_cipher(name))
+ filter = new StreamCipher_Filter(name, key);
+
+ return return_or_raise(filter, name);
+ }
+
+// FIXME: add new wrapper for Keyed_Filter here
+Filter* make_filter3(const std::string& name,
+ const SymmetricKey& key,
+ Cipher_Dir direction)
+ {
+ return return_or_raise(
+ get_cipher(name, key, direction),
+ name);
+ }
+
+Filter* make_filter4(const std::string& name,
+ const SymmetricKey& key,
+ const InitializationVector& iv,
+ Cipher_Dir direction)
+ {
+ return return_or_raise(
+ get_cipher(name, key, iv, direction),
+ name);
+ }
+
+void append_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+ {
+ pipe.append(filter.get());
+ filter.release();
+ }
+
+void prepend_filter(Pipe& pipe, std::auto_ptr<Filter> filter)
+ {
+ pipe.prepend(filter.get());
+ filter.release();
+ }
+
+void do_send(std::auto_ptr<FilterWrapper> filter, const std::string& data)
+ {
+ printf("Sending %s to %p\n", data.c_str(), filter.get());
+ filter->send_str(data);
+ }
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(rallas_ovls, read_all_as_string, 0, 1)
+
+void export_filters()
+ {
+ class_<Filter, std::auto_ptr<Filter>, boost::noncopyable>
+ ("__Internal_FilterObj", no_init);
+
+ def("make_filter", make_filter1,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter2,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter3,
+ return_value_policy<manage_new_object>());
+ def("make_filter", make_filter4,
+ return_value_policy<manage_new_object>());
+
+ // This might not work - Pipe will delete the filter, but Python
+ // might have allocated the space with malloc() or who-knows-what -> bad
+ class_<FilterWrapper, std::auto_ptr<FilterWrapper>,
+ bases<Filter>, boost::noncopyable>
+ ("FilterObj")
+ .def("write", pure_virtual(&Py_Filter::write_str))
+ .def("send", &do_send)
+ .def("start_msg", &Filter::start_msg, &FilterWrapper::default_start_msg)
+ .def("end_msg", &Filter::end_msg, &FilterWrapper::default_end_msg);
+
+ implicitly_convertible<std::auto_ptr<FilterWrapper>,
+ std::auto_ptr<Filter> >();
+
+ void (Pipe::*pipe_write_str)(const std::string&) = &Pipe::write;
+ void (Pipe::*pipe_process_str)(const std::string&) = &Pipe::process_msg;
+
+ class_<Pipe, boost::noncopyable>("PipeObj")
+ .def(init<>())
+ .def_readonly("LAST_MESSAGE", &Pipe::LAST_MESSAGE)
+ .def_readonly("DEFAULT_MESSAGE", &Pipe::DEFAULT_MESSAGE)
+ .add_property("default_msg", &Pipe::default_msg, &Pipe::set_default_msg)
+ .add_property("msg_count", &Pipe::message_count)
+ .def("append", append_filter)
+ .def("prepend", prepend_filter)
+ .def("reset", &Pipe::reset)
+ .def("pop", &Pipe::pop)
+ .def("end_of_data", &Pipe::end_of_data)
+ .def("start_msg", &Pipe::start_msg)
+ .def("end_msg", &Pipe::end_msg)
+ .def("write", pipe_write_str)
+ .def("process_msg", pipe_process_str)
+ .def("read_all", &Pipe::read_all_as_string, rallas_ovls());
+ }
diff --git a/botan/wrappers/boost-python/src/hash.cpp b/botan/wrappers/boost-python/src/hash.cpp
new file mode 100644
index 0000000..6ef1980
--- /dev/null
+++ b/botan/wrappers/boost-python/src/hash.cpp
@@ -0,0 +1,108 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "python_botan.h"
+
+class Py_HashFunction : public HashFunction
+ {
+ public:
+ virtual void hash_str(const std::string&) = 0;
+ virtual std::string final_str() = 0;
+
+ void clear() throw() {}
+
+ void add_data(const byte input[], u32bit length)
+ {
+ hash_str(make_string(input, length));
+ }
+
+ void final_result(byte output[])
+ {
+ string2binary(final_str(), output, OUTPUT_LENGTH);
+ }
+
+ Py_HashFunction(u32bit digest_size, u32bit block_size) :
+ HashFunction(digest_size, block_size) {}
+ };
+
+class Wrapped_HashFunction : public HashFunction
+ {
+ public:
+ void add_data(const byte in[], u32bit len) { hash->update(in, len); }
+ void final_result(byte out[]) { hash->final(out); }
+
+ void clear() throw() {}
+
+ std::string name() const { return hash->name(); }
+ HashFunction* clone() const { return hash->clone(); }
+
+ Wrapped_HashFunction(python::object py_obj, HashFunction* h) :
+ HashFunction(h->OUTPUT_LENGTH, h->HASH_BLOCK_SIZE),
+ obj(py_obj), hash(h) {}
+ private:
+ python::object obj;
+ HashFunction* hash;
+ };
+
+class Py_HashFunction_Wrapper : public Py_HashFunction,
+ public python::wrapper<Py_HashFunction>
+ {
+ public:
+ HashFunction* clone() const
+ {
+ python::object self = get_owner(this);
+ python::object py_clone = self.attr("__class__")();
+ HashFunction* hf = python::extract<HashFunction*>(py_clone);
+ return new Wrapped_HashFunction(py_clone, hf);
+ }
+
+ std::string name() const
+ {
+ return this->get_override("name")();
+ }
+
+ void hash_str(const std::string& in)
+ {
+ this->get_override("update")(in);
+ }
+
+ std::string final_str()
+ {
+ return this->get_override("final")();
+ }
+
+ Py_HashFunction_Wrapper(u32bit digest_size, u32bit block_size) :
+ Py_HashFunction(digest_size, block_size) {}
+ };
+
+std::string final_str(HashFunction* hash)
+ {
+ SecureVector<byte> digest = hash->final();
+ return std::string((const char*)digest.begin(), digest.size());
+ }
+
+void export_hash_functions()
+ {
+ void (HashFunction::*update_str)(const std::string&) =
+ &HashFunction::update;
+
+ python::class_<HashFunction, boost::noncopyable>
+ ("HashFunction", python::no_init)
+ .def("__init__", python::make_constructor(get_hash))
+ .def_readonly("digest_size", &HashFunction::OUTPUT_LENGTH)
+ .def("name", &HashFunction::name)
+ .def("update", update_str)
+ .def("final", final_str);
+
+ python::class_<Py_HashFunction_Wrapper, python::bases<HashFunction>,
+ boost::noncopyable>
+ ("HashFunctionImpl", python::init<u32bit, u32bit>())
+ .def("name", python::pure_virtual(&Py_HashFunction::name))
+ .def("update", python::pure_virtual(&Py_HashFunction::hash_str))
+ .def("final", python::pure_virtual(&Py_HashFunction::final_str));
+ }
diff --git a/botan/wrappers/boost-python/src/macs.cpp b/botan/wrappers/boost-python/src/macs.cpp
new file mode 100644
index 0000000..54a55af
--- /dev/null
+++ b/botan/wrappers/boost-python/src/macs.cpp
@@ -0,0 +1,59 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+class Py_MAC
+ {
+ public:
+ u32bit output_length() const { return mac->OUTPUT_LENGTH; }
+ u32bit keylength_min() const { return mac->MINIMUM_KEYLENGTH; }
+ u32bit keylength_max() const { return mac->MAXIMUM_KEYLENGTH; }
+ u32bit keylength_mod() const { return mac->KEYLENGTH_MULTIPLE; }
+ std::string name() const { return mac->name(); }
+ void clear() throw() { mac->clear(); }
+
+ void set_key(const OctetString& key) { mac->set_key(key); }
+
+ bool valid_keylength(u32bit kl) const
+ {
+ return mac->valid_keylength(kl);
+ }
+
+ void update(const std::string& in) { mac->update(in); }
+
+ std::string final()
+ {
+ SecureVector<byte> result = mac->final();
+ return std::string((const char*)result.begin(), result.size());
+ }
+
+ Py_MAC(const std::string& name)
+ {
+ mac = get_mac(name);
+ }
+ ~Py_MAC() { delete mac; }
+ private:
+ MessageAuthenticationCode* mac;
+ };
+
+void export_macs()
+ {
+ python::class_<Py_MAC>("MAC", python::init<std::string>())
+ .add_property("output_length", &Py_MAC::output_length)
+ .add_property("keylength_min", &Py_MAC::keylength_min)
+ .add_property("keylength_max", &Py_MAC::keylength_max)
+ .add_property("keylength_mod", &Py_MAC::keylength_mod)
+ .add_property("name", &Py_MAC::name)
+ .def("valid_keylength", &Py_MAC::valid_keylength)
+ .def("set_key", &Py_MAC::set_key)
+ .def("clear", &Py_MAC::clear)
+ .def("update", &Py_MAC::update)
+ .def("final", &Py_MAC::final);
+ }
diff --git a/botan/wrappers/boost-python/src/pk.cpp b/botan/wrappers/boost-python/src/pk.cpp
new file mode 100644
index 0000000..72d3294
--- /dev/null
+++ b/botan/wrappers/boost-python/src/pk.cpp
@@ -0,0 +1,125 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/dh.h>
+#include <botan/look_pk.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+std::string encode_pub(const Public_Key* key,
+ const std::string& type)
+ {
+ if(type == "DER")
+ {
+ Pipe pipe;
+ pipe.start_msg();
+ X509::encode(*key, pipe, RAW_BER);
+ pipe.end_msg();
+ return pipe.read_all_as_string();
+ }
+ else if(type == "PEM")
+ return X509::PEM_encode(*key);
+ else
+ throw Encoding_Error("Unknown key encoding method " + type);
+ }
+
+std::string encode_priv(const Private_Key* key,
+ const std::string& type)
+ {
+ if(type == "DER")
+ {
+ Pipe pipe;
+ PKCS8::encode(*key, pipe, RAW_BER);
+ return pipe.read_all_as_string();
+ }
+ else if(type == "PEM")
+ return PKCS8::PEM_encode(*key);
+ else
+ throw Encoding_Error("Unknown key encoding method " + type);
+ }
+
+/*
+Private_Key* load_priv(const std::string& file, const std::string& pass)
+ {
+ return PKCS8::load_key(file, pass);
+ }
+
+Public_Key* load_public(const std::string& file)
+ {
+ return X509::load_key(file);
+ }
+*/
+
+/*
+std::string encrypt_string(const PK_Encryptor* enc, const std::string& in)
+ {
+ SecureVector<byte> cipher = enc->encrypt((const byte*)in.data(), in.length());
+ return std::string((const char*)cipher.begin(), cipher.size());
+ }
+
+std::string decrypt_string(const PK_Decryptor* dec, const std::string& in)
+ {
+ SecureVector<byte> plain = dec->decrypt((const byte*)in.data(), in.length());
+ return std::string((const char*)plain.begin(), plain.size());
+ }
+*/
+
+void export_pk()
+ {
+ /*
+ python::def("private_key", load_priv,
+ python::return_value_policy<python::manage_new_object>());
+ python::def("public_key", load_public,
+ python::return_value_policy<python::manage_new_object>());
+ */
+
+ python::class_<Public_Key, boost::noncopyable>
+ ("Public_Key", python::no_init)
+ .add_property("name", &Public_Key::algo_name)
+ .add_property("max_input_bits", &Public_Key::max_input_bits)
+ .def("public_key", encode_pub);
+
+ python::class_<PK_Encrypting_Key, python::bases<Public_Key>, boost::noncopyable>
+ ("PK_Encrypting_Key", python::no_init);
+
+ python::class_<Private_Key, python::bases<Public_Key>, boost::noncopyable>
+ ("Private_Key", python::no_init)
+ .def("private_key", encode_priv);
+
+ python::class_<PK_Decrypting_Key, python::bases<Private_Key>, boost::noncopyable>
+ ("PK_Decrypting_Key", python::no_init);
+
+ python::class_<RSA_PublicKey, python::bases<PK_Encrypting_Key> >
+ ("RSA_PublicKey", python::no_init);
+
+ python::class_<DSA_PublicKey, python::bases<Public_Key> >
+ ("DSA_PublicKey", python::no_init);
+
+ /*
+ python::class_<RSA_PrivateKey, python::bases<RSA_PublicKey, PK_Decrypting_Key> >
+ ("RSA_PrivateKey", python::init<u32bit>());
+ */
+
+ /*
+ python::class_<PK_Encryptor, boost::noncopyable>
+ ("PK_Encryptor", python::no_init)
+ .def("__init__",
+ python::make_constructor(get_pk_encryptor,
+ python::with_custodian_and_ward_postcall<0, 1>()))
+ .def("max_input", &PK_Encryptor::maximum_input_size)
+ .def("encrypt", encrypt_string);
+ */
+
+ /*
+ python::class_<PK_Decryptor, boost::noncopyable>
+ ("PK_Decryptor", python::no_init)
+ .def("__init__", python::make_constructor(get_pk_decryptor))
+ .def("decrypt", decrypt_string);
+ */
+ }
diff --git a/botan/wrappers/boost-python/src/python_botan.h b/botan/wrappers/boost-python/src/python_botan.h
new file mode 100644
index 0000000..d0fd102
--- /dev/null
+++ b/botan/wrappers/boost-python/src/python_botan.h
@@ -0,0 +1,54 @@
+
+#ifndef BOTAN_BOOST_PYTHON_COMMON_H__
+#define BOTAN_BOOST_PYTHON_COMMON_H__
+
+#include <botan/base.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+
+extern void export_block_ciphers();
+extern void export_stream_ciphers();
+extern void export_hash_functions();
+extern void export_macs();
+extern void export_filters();
+extern void export_pk();
+extern void export_x509();
+
+class Bad_Size : public Exception
+ {
+ public:
+ Bad_Size(u32bit got, u32bit expected) :
+ Exception("Bad size detected in Python/C++ conversion layer: got " +
+ to_string(got) + " bytes, expected " + to_string(expected))
+ {}
+ };
+
+inline std::string make_string(const byte input[], u32bit length)
+ {
+ return std::string((const char*)input, length);
+ }
+
+inline std::string make_string(const MemoryRegion<byte>& in)
+ {
+ return make_string(in.begin(), in.size());
+ }
+
+inline void string2binary(const std::string& from, byte to[], u32bit expected)
+ {
+ if(from.size() != expected)
+ throw Bad_Size(from.size(), expected);
+ std::memcpy(to, from.data(), expected);
+ }
+
+template<typename T>
+inline python::object get_owner(T* me)
+ {
+ return python::object(
+ python::handle<>(
+ python::borrowed(python::detail::wrapper_base_::get_owner(*me))));
+ }
+
+#endif
diff --git a/botan/wrappers/boost-python/src/stream.cpp b/botan/wrappers/boost-python/src/stream.cpp
new file mode 100644
index 0000000..f94bd7f
--- /dev/null
+++ b/botan/wrappers/boost-python/src/stream.cpp
@@ -0,0 +1,54 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/botan.h>
+using namespace Botan;
+
+#include "python_botan.h"
+
+class Py_StreamCipher
+ {
+ public:
+ u32bit keylength_min() const { return cipher->MINIMUM_KEYLENGTH; }
+ u32bit keylength_max() const { return cipher->MAXIMUM_KEYLENGTH; }
+ u32bit keylength_mod() const { return cipher->KEYLENGTH_MULTIPLE; }
+
+ void set_key(const OctetString& key) { cipher->set_key(key); }
+ bool valid_keylength(u32bit kl) const
+ {
+ return cipher->valid_keylength(kl);
+ }
+
+ std::string name() const { return cipher->name(); }
+ void clear() throw() { cipher->clear(); }
+
+ std::string crypt(const std::string& in) const
+ {
+ SecureVector<byte> out(in.size());
+ cipher->encrypt((const byte*)in.data(), out.begin(), in.size());
+ return std::string((const char*)out.begin(), out.size());
+ }
+
+ Py_StreamCipher(const std::string& name)
+ {
+ cipher = get_stream_cipher(name);
+ }
+ ~Py_StreamCipher() { delete cipher; }
+ private:
+ StreamCipher* cipher;
+ };
+
+void export_stream_ciphers()
+ {
+ python::class_<Py_StreamCipher>("StreamCipher", python::init<std::string>())
+ .add_property("keylength_min", &Py_StreamCipher::keylength_min)
+ .add_property("keylength_max", &Py_StreamCipher::keylength_max)
+ .add_property("keylength_mod", &Py_StreamCipher::keylength_mod)
+ .add_property("name", &Py_StreamCipher::name)
+ .def("clear", &Py_StreamCipher::clear)
+ .def("valid_keylength", &Py_StreamCipher::valid_keylength)
+ .def("set_key", &Py_StreamCipher::set_key)
+ .def("crypt", &Py_StreamCipher::crypt);
+ }
diff --git a/botan/wrappers/boost-python/src/x509.cpp b/botan/wrappers/boost-python/src/x509.cpp
new file mode 100644
index 0000000..c37575f
--- /dev/null
+++ b/botan/wrappers/boost-python/src/x509.cpp
@@ -0,0 +1,140 @@
+/*************************************************
+* Boost.Python module definition *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/oids.h>
+#include <botan/pipe.h>
+#include <botan/filters.h>
+#include <botan/x509cert.h>
+#include <botan/x509_crl.h>
+#include <botan/x509stor.h>
+using namespace Botan;
+
+#include <boost/python.hpp>
+namespace python = boost::python;
+
+template<typename T>
+class vector_to_list
+ {
+ public:
+ static PyObject* convert(const std::vector<T>& in)
+ {
+ python::list out;
+ typename std::vector<T>::const_iterator i = in.begin();
+ while(i != in.end())
+ {
+ out.append(*i);
+ ++i;
+ }
+ return python::incref(out.ptr());
+ }
+
+ vector_to_list()
+ {
+ python::to_python_converter<std::vector<T>, vector_to_list<T> >();
+ }
+ };
+
+template<typename T>
+class memvec_to_hexstr
+ {
+ public:
+ static PyObject* convert(const T& in)
+ {
+ Pipe pipe(new Hex_Encoder);
+ pipe.process_msg(in);
+ std::string result = pipe.read_all_as_string();
+ return python::incref(python::str(result).ptr());
+ }
+
+ memvec_to_hexstr()
+ {
+ python::to_python_converter<T, memvec_to_hexstr<T> >();
+ }
+ };
+
+class X509_Store_Search_Wrap : public X509_Store::Search_Func,
+ public python::wrapper<X509_Store::Search_Func>
+ {
+ public:
+ bool match(const X509_Certificate& cert) const
+ {
+ return this->get_override("match")(cert);
+ }
+ };
+
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(add_cert_ols, add_cert, 1, 2)
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(validate_cert_ols, validate_cert, 1, 2)
+
+void export_x509()
+ {
+ vector_to_list<std::string>();
+ vector_to_list<X509_Certificate>();
+ memvec_to_hexstr<MemoryVector<byte> >();
+
+ python::class_<X509_Certificate>
+ ("X509_Certificate", python::init<std::string>())
+ .def(python::self == python::self)
+ .def(python::self != python::self)
+ .add_property("version", &X509_Certificate::x509_version)
+ .add_property("is_CA", &X509_Certificate::is_CA_cert)
+ .add_property("self_signed", &X509_Certificate::is_self_signed)
+ .add_property("pathlimit", &X509_Certificate::path_limit)
+ .add_property("as_pem", &X509_Object::PEM_encode)
+ .def("start_time", &X509_Certificate::start_time)
+ .def("end_time", &X509_Certificate::end_time)
+ .def("subject_info", &X509_Certificate::subject_info)
+ .def("issuer_info", &X509_Certificate::issuer_info)
+ .def("ex_constraints", &X509_Certificate::ex_constraints)
+ .def("policies", &X509_Certificate::policies)
+ .def("subject_key_id", &X509_Certificate::subject_key_id)
+ .def("authority_key_id", &X509_Certificate::authority_key_id);
+
+ python::class_<X509_CRL>
+ ("X509_CRL", python::init<std::string>())
+ .add_property("as_pem", &X509_Object::PEM_encode);
+
+ python::enum_<X509_Code>("verify_result")
+ .value("verified", VERIFIED)
+ .value("unknown_x509_error", UNKNOWN_X509_ERROR)
+ .value("cannot_establish_trust", CANNOT_ESTABLISH_TRUST)
+ .value("cert_chain_too_long", CERT_CHAIN_TOO_LONG)
+ .value("signature_error", SIGNATURE_ERROR)
+ .value("policy_error", POLICY_ERROR)
+ .value("invalid_usage", INVALID_USAGE)
+ .value("cert_format_error", CERT_FORMAT_ERROR)
+ .value("cert_issuer_not_found", CERT_ISSUER_NOT_FOUND)
+ .value("cert_not_yet_valid", CERT_NOT_YET_VALID)
+ .value("cert_has_expired", CERT_HAS_EXPIRED)
+ .value("cert_is_revoked", CERT_IS_REVOKED)
+ .value("crl_format_error", CRL_FORMAT_ERROR)
+ .value("crl_issuer_not_found", CRL_ISSUER_NOT_FOUND)
+ .value("crl_not_yet_valid", CRL_NOT_YET_VALID)
+ .value("crl_has_expired", CRL_HAS_EXPIRED)
+ .value("ca_cert_cannot_sign", CA_CERT_CANNOT_SIGN)
+ .value("ca_cert_not_for_cert_issuer", CA_CERT_NOT_FOR_CERT_ISSUER)
+ .value("ca_cert_not_for_crl_issuer", CA_CERT_NOT_FOR_CRL_ISSUER);
+
+ python::enum_<X509_Store::Cert_Usage>("cert_usage")
+ .value("any", X509_Store::ANY)
+ .value("tls_server", X509_Store::TLS_SERVER)
+ .value("tls_client", X509_Store::TLS_CLIENT)
+ .value("code_signing", X509_Store::CODE_SIGNING)
+ .value("email_protection", X509_Store::EMAIL_PROTECTION)
+ .value("time_stamping", X509_Store::TIME_STAMPING)
+ .value("crl_signing", X509_Store::CRL_SIGNING);
+
+ {
+ python::scope in_class =
+ python::class_<X509_Store>("X509_Store")
+ .def("add_cert", &X509_Store::add_cert, add_cert_ols())
+ .def("validate", &X509_Store::validate_cert, validate_cert_ols())
+ .def("get_certs", &X509_Store::get_certs)
+ .def("add_crl", &X509_Store::add_crl);
+
+ python::class_<X509_Store_Search_Wrap, boost::noncopyable>
+ ("Search_Func")
+ .def("match", python::pure_virtual(&X509_Store::Search_Func::match));
+ }
+ }
diff --git a/botan/wrappers/perl-xs/Botan.pm b/botan/wrappers/perl-xs/Botan.pm
new file mode 100644
index 0000000..ac4ad91
--- /dev/null
+++ b/botan/wrappers/perl-xs/Botan.pm
@@ -0,0 +1,117 @@
+package Botan;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD);
+
+require DynaLoader;
+require AutoLoader;
+use Carp;
+
+@ISA = qw(DynaLoader);
+$VERSION = '0.01';
+
+@EXPORT_OK = qw(
+ NONE
+ IGNORE_WS
+ FULL_CHECK
+);
+
+%EXPORT_TAGS = (
+ 'all' => [ @EXPORT_OK ],
+ 'decoder_checking' => [ qw(
+ NONE
+ IGNORE_WS
+ FULL_CHECK
+ )],
+
+);
+
+
+sub AUTOLOAD
+{
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname = $AUTOLOAD;
+ $constname =~ s/.*:://;
+ croak '& not defined' if $constname eq 'constant';
+# my $val = constant($constname, @_ ? $_[0] : 0);
+ my $val = constant($constname);
+ if ($! != 0) {
+ if ( $! =~ /Invalid/ )
+ {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else
+ {
+ croak "Your vendor has not defined Botan symbol $constname";
+ }
+ }
+ no strict 'refs';
+ *$AUTOLOAD = sub { $val };
+ goto &$AUTOLOAD;
+}
+
+
+bootstrap Botan $VERSION;
+
+# to setup inheritance...
+
+package Botan::Filter;
+use vars qw(@ISA);
+@ISA = qw();
+
+package Botan::Chain;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Fork;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Hex_Encoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Hex_Decoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Base64_Decoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+package Botan::Base64_Encoder;
+use vars qw(@ISA);
+@ISA = qw( Botan::Filter );
+
+
+package Botan;
+
+1;
+__END__
+
+=head1 NAME
+
+Botan - Perl extension for access to Botan ...
+
+=head1 SYNOPSIS
+
+ use Botan;
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Blah blah blah.
+
+=head1 AUTHOR
+
+Vaclav Ovsik <vaclav.ovsik@i.cz>
+
+=head1 SEE ALSO
+
+Bla
+
+=cut
diff --git a/botan/wrappers/perl-xs/Botan.xs b/botan/wrappers/perl-xs/Botan.xs
new file mode 100644
index 0000000..ded129d
--- /dev/null
+++ b/botan/wrappers/perl-xs/Botan.xs
@@ -0,0 +1,829 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <botan/asn1_obj.h>
+#include <botan/asn1_oid.h>
+#include <botan/base64.h>
+#include <botan/basefilt.h>
+#include <botan/hex.h>
+#include <botan/init.h>
+#include <botan/oids.h>
+#include <botan/x509cert.h>
+#include <botan/x509_ext.h>
+
+
+/* xsubpp converts ':' to '_' in typemap. We create our types without ':' */
+
+typedef Botan::ASN1_String Botan__ASN1_String;
+typedef Botan::AlgorithmIdentifier Botan__AlgorithmIdentifier;
+typedef Botan::AlternativeName Botan__AlternativeName;
+typedef Botan::Attribute Botan__Attribute;
+typedef Botan::Base64_Decoder Botan__Base64_Decoder;
+typedef Botan::Base64_Encoder Botan__Base64_Encoder;
+typedef Botan::Chain Botan__Chain;
+typedef Botan::Certificate_Extension Botan__Extension;
+typedef Botan::Filter Botan__Filter;
+typedef Botan::Fork Botan__Fork;
+typedef Botan::Hex_Decoder Botan__Hex_Decoder;
+typedef Botan::Hex_Encoder Botan__Hex_Encoder;
+typedef Botan::OID Botan__OID;
+typedef Botan::Pipe Botan__Pipe;
+typedef Botan::X509_Certificate Botan__X509_Certificate;
+typedef Botan::X509_DN Botan__X509_DN;
+typedef Botan::X509_Time Botan__X509_Time;
+typedef Botan::u32bit Botan__u32bit;
+
+
+/* Types to keep track of destruction C++ objects passed
+ * into other objects...
+ * An Botan object is deleted by his parent object into which is passed,
+ * e.g. some Filter is deleted when his Pipe is destructed. We must
+ * track this and not to delete object again in Perls destructor.
+ */
+
+class ObjectInfo
+{
+private:
+ I32 d_signature;
+ bool d_del;
+public:
+ static I32 const SIGNVAL = 0x696a626f;
+ ObjectInfo() : d_signature(SIGNVAL),
+ d_del(true) {};
+ ~ObjectInfo() {};
+ void set_delete(bool del = true) { d_del = del; };
+ void set_delete_no() { set_delete(false); };
+ void set_delete_yes() { set_delete(true); };
+ bool should_delete() const { return d_del; };
+};
+
+/* Constant object in initial state - template */
+
+ObjectInfo const oi_init;
+
+
+/* Botan library initializer ... */
+
+Botan::LibraryInitializer botan_init;
+
+
+
+/*============================================================================*/
+
+MODULE = Botan PACKAGE = Botan
+
+PROTOTYPES: ENABLE
+
+void
+constant(char *name)
+ CODE:
+ using namespace Botan;
+ errno = 0;
+ switch (name[0])
+ {
+ case 'F':
+ if ( strEQ(name, "FULL_CHECK") )
+ XSRETURN_IV( FULL_CHECK ); // Decoder_Checking enum
+ break;
+ case 'I':
+ if ( strEQ(name, "IGNORE_WS") )
+ XSRETURN_IV( IGNORE_WS ); // Decoder_Checking enum
+ break;
+ case 'N':
+ if ( strEQ(name, "NONE") )
+ XSRETURN_IV( NONE ); // Decoder_Checking enum
+ break;
+ }
+ errno = EINVAL;
+ XSRETURN_UNDEF;
+
+
+# =========================== Botan::Chain ==========================
+
+MODULE = Botan PACKAGE = Botan::Chain
+
+Botan__Chain *
+Botan__Chain::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
+ Botan__Filter *f1;
+ Botan__Filter *f2;
+ Botan__Filter *f3;
+ Botan__Filter *f4;
+ PREINIT:
+ ObjectInfo *f1_oi;
+ ObjectInfo *f2_oi;
+ ObjectInfo *f3_oi;
+ ObjectInfo *f4_oi;
+ CODE:
+ try {
+ RETVAL = new Botan__Chain(f1, f2, f3, f4);
+ if ( f1 ) f1_oi->set_delete_no();
+ if ( f2 ) f2_oi->set_delete_no();
+ if ( f3 ) f3_oi->set_delete_no();
+ if ( f4 ) f4_oi->set_delete_no();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Chain::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# =========================== Botan::Fork ==========================
+
+MODULE = Botan PACKAGE = Botan::Fork
+
+Botan__Fork *
+Botan__Fork::new(f1 = 0, f2 = 0, f3 = 0, f4 = 0)
+ Botan__Filter *f1;
+ Botan__Filter *f2;
+ Botan__Filter *f3;
+ Botan__Filter *f4;
+ PREINIT:
+ ObjectInfo *f1_oi;
+ ObjectInfo *f2_oi;
+ ObjectInfo *f3_oi;
+ ObjectInfo *f4_oi;
+ CODE:
+ try {
+ RETVAL = new Botan__Fork(f1, f2, f3, f4);
+ if ( f1 ) f1_oi->set_delete_no();
+ if ( f2 ) f2_oi->set_delete_no();
+ if ( f3 ) f3_oi->set_delete_no();
+ if ( f4 ) f4_oi->set_delete_no();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Fork::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Base64_Decoder ============================
+
+MODULE = Botan PACKAGE = Botan::Base64_Decoder
+
+Botan__Base64_Decoder *
+Botan__Base64_Decoder::new(checking = Botan::NONE)
+ int checking;
+ CODE:
+ try {
+ using namespace Botan;
+ RETVAL = new Base64_Decoder((Decoder_Checking)checking);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Base64_Decoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# =========================== Botan::Base64_Encoder ==========================
+
+MODULE = Botan PACKAGE = Botan::Base64_Encoder
+
+Botan__Base64_Encoder *
+Botan__Base64_Encoder::new(breaks = false, length = 72)
+ bool breaks;
+ Botan__u32bit length;
+ CODE:
+ try {
+ RETVAL = new Botan__Base64_Encoder(breaks, length);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Base64_Encoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Hex_Decoder ============================
+
+MODULE = Botan PACKAGE = Botan::Hex_Decoder
+
+Botan__Hex_Decoder *
+Botan__Hex_Decoder::new(checking = Botan::NONE)
+ int checking;
+ CODE:
+ try {
+ using namespace Botan;
+ RETVAL = new Hex_Decoder((Decoder_Checking)checking);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Hex_Decoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ============================ Botan::Hex_Encoder ============================
+
+MODULE = Botan PACKAGE = Botan::Hex_Encoder
+
+Botan__Hex_Encoder *
+Botan__Hex_Encoder::new(breaks = false, length = 72, lcase = false)
+ bool breaks;
+ Botan__u32bit length;
+ bool lcase;
+ CODE:
+ try {
+ using Botan::Hex_Encoder;
+ RETVAL = new Hex_Encoder(breaks, length,
+ lcase ? Hex_Encoder::Lowercase : Hex_Encoder::Uppercase);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Hex_Encoder::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ if ( THIS_oi->should_delete() )
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ================================ Botan::OID ================================
+
+MODULE = Botan PACKAGE = Botan::OID
+
+Botan__OID *
+Botan__OID::new(s)
+ char *s;
+ CODE:
+ try {
+ RETVAL = new Botan__OID(s);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__OID::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+char *
+Botan__OID::as_string()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->as_string().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+
+# ================================ Botan::OIDS ================================
+
+MODULE = Botan PACKAGE = Botan::OIDS
+
+void
+add_oid(oid, name)
+ Botan__OID *oid;
+ char *name;
+ CODE:
+ try {
+ Botan::OIDS::add_oid(*oid, name);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+char *
+lookup_by_oid(oid)
+ Botan__OID *oid;
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(Botan::OIDS::lookup(*oid).c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__OID *
+lookup_by_name(name)
+ char *name;
+ CODE:
+ try {
+ RETVAL = new Botan__OID(Botan::OIDS::lookup(name));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::OID";
+ OUTPUT:
+ RETVAL
+
+int
+have_oid(name)
+ char *name;
+ CODE:
+ try {
+ RETVAL = Botan::OIDS::have_oid(name);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+
+# ================================ Botan::Pipe ================================
+
+MODULE = Botan PACKAGE = Botan::Pipe
+
+Botan__Pipe *
+Botan__Pipe::new(...)
+ CODE:
+ for (I32 i = 1; i < items; i++)
+ {
+ if ( !sv_isobject(ST(i)) || (SvTYPE(SvRV(ST(i))) != SVt_PVMG) )
+ croak("Botan::Pipe::new() -- arg %u is not "
+ "a blessed SV reference", i +1);
+ if ( !sv_derived_from(ST(i), "Botan::Filter") )
+ croak("Botan::Pipe::new() -- arg %u is not "
+ "an object derived from Botan::Filter", i +1);
+ MAGIC *mg = mg_find(SvRV(ST(i)), '~');
+ if ( mg == 0
+ || mg->mg_len != sizeof(ObjectInfo)
+ || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL )
+ croak("Botan::Pipe::new() -- arg %u has no "
+ "valid private magic data (ObjectInfo)", i +1);
+ }
+ try {
+ RETVAL = new Botan__Pipe();
+ for (I32 i = 1; i < items; i++)
+ {
+ SV *osv = (SV *)SvRV(ST(i));
+ ObjectInfo *oi = (ObjectInfo *)(mg_find(osv, '~')->mg_ptr);
+ RETVAL->append((Botan__Filter *)(SvIV(osv)));
+ oi->set_delete_no();
+ }
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::DESTROY()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::write(s)
+ SV *s;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ STRLEN len;
+ char *ptr = SvPV(s, len);
+ try {
+ THIS->write((unsigned char *)ptr, len);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::process_msg(s)
+ SV *s;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ STRLEN len;
+ char *ptr = SvPV(s, len);
+ try {
+ THIS->process_msg((unsigned char *)ptr, len);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+Botan__u32bit
+Botan__Pipe::remaining(msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->remaining(msgno);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+SV *
+Botan__Pipe::read(len = 0xFFFFFFFF, msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit len;
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ if ( len > THIS->remaining(msgno) )
+ len = THIS->remaining(msgno);
+ RETVAL = NEWSV(0, len);
+ SvPOK_on(RETVAL);
+ if ( len > 0 )
+ SvCUR_set(RETVAL, THIS->read((unsigned char *)SvPVX(RETVAL),
+ len, msgno));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+SV *
+Botan__Pipe::peek(len = 0xFFFFFFFF, offset = 0, \
+ msgno = Botan::Pipe::DEFAULT_MESSAGE)
+ Botan__u32bit len;
+ Botan__u32bit offset;
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ if ( len > THIS->remaining(msgno) )
+ len = THIS->remaining(msgno);
+ RETVAL = NEWSV(0, len);
+ SvPOK_on(RETVAL);
+ if ( len > 0 )
+ SvCUR_set(RETVAL, THIS->peek((unsigned char *)SvPVX(RETVAL),
+ len, offset, msgno));
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__u32bit
+Botan__Pipe::default_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->default_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::set_default_msg(msgno)
+ Botan__u32bit msgno;
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->set_default_msg(msgno);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+Botan__u32bit
+Botan__Pipe::message_count()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->message_count();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+bool
+Botan__Pipe::end_of_data()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ RETVAL = THIS->end_of_data();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__Pipe::start_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->start_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::end_msg()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->end_msg();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+void
+Botan__Pipe::reset()
+ PREINIT:
+ ObjectInfo *THIS_oi;
+ CODE:
+ try {
+ THIS->reset();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+
+# ========================== Botan::X509_Certificate ==========================
+
+MODULE = Botan PACKAGE = Botan::X509_Certificate
+
+Botan__X509_Certificate *
+Botan__X509_Certificate::new(char *fn)
+ CODE:
+ try {
+ RETVAL = new Botan__X509_Certificate(fn);
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__X509_Certificate::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+unsigned int
+Botan__X509_Certificate::x509_version()
+ CODE:
+ try {
+ RETVAL = THIS->x509_version();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::start_time()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->start_time().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::end_time()
+ CODE:
+ try {
+ RETVAL = const_cast<char *>(THIS->end_time().c_str());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::subject_info(char *info)
+ CODE:
+ try {
+ std::vector<std::string> s = THIS->subject_info(info);
+
+ if(s.size() > 0)
+ RETVAL = const_cast<char *>(s[0].c_str());
+ else
+ RETVAL = "err";
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+char *
+Botan__X509_Certificate::issuer_info(char *info)
+ CODE:
+ try {
+ std::vector<std::string> s = THIS->subject_info(info);
+
+ if(s.size() > 0)
+ RETVAL = const_cast<char *>(s[0].c_str());
+ else
+ RETVAL = "err";
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+Botan__X509_DN *
+Botan__X509_Certificate::subject_dn()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN(THIS->subject_dn());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::X509_DN";
+ OUTPUT:
+ RETVAL
+
+Botan__X509_DN *
+Botan__X509_Certificate::issuer_dn()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN(THIS->issuer_dn());
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ char const * CLASS = "Botan::X509_DN";
+ OUTPUT:
+ RETVAL
+
+
+# ============================== Botan::X509_DN ==============================
+
+MODULE = Botan PACKAGE = Botan::X509_DN
+
+Botan__X509_DN *
+Botan__X509_DN::new()
+ CODE:
+ try {
+ RETVAL = new Botan__X509_DN();
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Botan__X509_DN::DESTROY()
+ CODE:
+ try {
+ delete THIS;
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+
+AV *
+Botan__X509_DN::get_attributes()
+ CODE:
+ try {
+ using namespace std;
+ using namespace Botan;
+
+ typedef multimap<OID, string>::const_iterator rdn_iter;
+
+ multimap<OID, string> const &atrmmap = THIS->get_attributes();
+ RETVAL = newAV();
+ for(rdn_iter i = atrmmap.begin(); i != atrmmap.end(); i++)
+ {
+ string const &atr = i->first.as_string();
+ string const &val = i->second;
+ av_push(RETVAL, newSVpvn(atr.c_str(), atr.length()));
+ av_push(RETVAL, newSVpvn(val.c_str(), val.length()));
+ }
+ }
+ catch (const std::exception &e) {
+ croak(e.what());
+ }
+ OUTPUT:
+ RETVAL
diff --git a/botan/wrappers/perl-xs/Changes b/botan/wrappers/perl-xs/Changes
new file mode 100644
index 0000000..5f32b0c
--- /dev/null
+++ b/botan/wrappers/perl-xs/Changes
@@ -0,0 +1,4 @@
+Revision history for Perl extension to Botan.
+
+0.01 Fri, 20 Feb 2004 15:10:50 +0100
+ - first version
diff --git a/botan/wrappers/perl-xs/MANIFEST b/botan/wrappers/perl-xs/MANIFEST
new file mode 100644
index 0000000..b9d8454
--- /dev/null
+++ b/botan/wrappers/perl-xs/MANIFEST
@@ -0,0 +1,15 @@
+Botan.pm
+Botan.xs
+Changes
+MANIFEST
+Makefile.PL
+data/ca.cert.der
+data/ca.cert.pem
+t/base64.t
+t/filt.t
+t/hex.t
+t/oid.t
+t/pipe.t
+t/testutl.pl
+t/x509cert.t
+typemap
diff --git a/botan/wrappers/perl-xs/data/ca.cert.der b/botan/wrappers/perl-xs/data/ca.cert.der
new file mode 100644
index 0000000..d6ed8ae
--- /dev/null
+++ b/botan/wrappers/perl-xs/data/ca.cert.der
Binary files differ
diff --git a/botan/wrappers/perl-xs/data/ca.cert.pem b/botan/wrappers/perl-xs/data/ca.cert.pem
new file mode 100644
index 0000000..012913b
--- /dev/null
+++ b/botan/wrappers/perl-xs/data/ca.cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi2gAwIBAgIBEjANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJDWjER
+MA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3QgcHJpbWFyeSBDQTEWMBQG
+CSqGSIb3DQEJARYHY2FAaS5jejAeFw0wMDA4MjAyMTQ4MDBaFw0wMjA4MTAyMTQ4
+MDBaME8xCzAJBgNVBAYTAkNaMREwDwYDVQQKEwhJQ1ogYS5zLjEVMBMGA1UEAxMM
+VGVzdCBzaWduIENBMRYwFAYJKoZIhvcNAQkBFgdjYUBpLmN6MIGfMA0GCSqGSIb3
+DQEBAQUAA4GNADCBiQKBgQCo2GReNqwU0/8bZZua5hgYaVHvD9QAmfILNXD25jRk
+C8lqe5m/GzbmftSUso5HyUy1t+qzvRDTmxK8uRn0P00Mqj9gjwF8PGQvZE/FrDF7
+rta9GCcH4n2GfQ0iexlhRZW44AfOD4HCgq38Z0bzBclsvUslBWe1AT+S5+chZ5Wb
+UwIDAQABo4GsMIGpMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLXqc1b1DOfGehii
+k4Z+/ih9BYZmMHoGA1UdIwRzMHGAFL7x2ToS4RDAbDJu4fHnzzGjfGmgoVakVDBS
+MQswCQYDVQQGEwJDWjERMA8GA1UEChMISUNaIGEucy4xGDAWBgNVBAMTD1Rlc3Qg
+cHJpbWFyeSBDQTEWMBQGCSqGSIb3DQEJARYHY2FAaS5jeoIBADANBgkqhkiG9w0B
+AQUFAAOBgQAKD9ku9kKXUGhSw8KuWJXTnEsIUzDtgmREBEUOtEvGfU45vogWN7ZL
+9fQZ1deywN4RJ4T5ZTTcCTPodOdG+IXLJ+uPn/m9iQ/D86c3GKS3yx4JNAn5PH1m
+qLsMYVjbFD2uREZQsqbg3RT6L1D8+oK0pN379u3bD6oJx/qa7+F4Jg==
+-----END CERTIFICATE-----
diff --git a/botan/wrappers/perl-xs/t/base64.t b/botan/wrappers/perl-xs/t/base64.t
new file mode 100644
index 0000000..f0973e1
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/base64.t
@@ -0,0 +1,273 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..24\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+require 't/testutl.pl';
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+# Data prep
+
+my $botan_lic_b64_garbage = <<'EOF';
+Q29weXJpZ2h0IChDKSAxOTk5LTIwMDQgVGhlIEJvdGFuIFByb2plY3QuIEFsbCBy__ì¹
+aWdodHMgcmVzZXJ2ZWQuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJj$$*:
+ZSBhbmQgYmluYXJ5IGZvcm1zLCBmb3IgYW55IHVzZSwgd2l0aCBvciB3aXRob3V0!@#$%^&*(
+Cm1vZGlmaWNhdGlvbiwgaXMgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZv[\]
+bGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMg'~`
+b2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBu()
+b3RpY2UsIHRoaXMKbGlzdCBvZiBjb25kaXRpb25zLCBhbmQgdGhlIGZvbGxvd2lu
+ZyBkaXNjbGFpbWVyLgoKMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3Jt
+IG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLAp0aGlz
+IGxpc3Qgb2YgY29uZGl0aW9ucywgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1l
+ciBpbiB0aGUgZG9jdW1lbnRhdGlvbgphbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHBy_,^
+b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KClRISVMgU09GVFdBUkUgSVMg{|}~~~~~
+UFJPVklERUQgQlkgVEhFIEFVVEhPUihTKSAiQVMgSVMiIEFORCBBTlkgRVhQUkVT~~~~~~~~
+UyBPUiBJTVBMSUVECldBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1J__:;
+VEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GCk1FUkNIQU5UQUJJTElU
+WSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsIEFSRSBESVND
+TEFJTUVELgoKSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUihTKSBPUiBDT05U
+UklCVVRPUihTKSBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsCklORElSRUNULCBJ
+TkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwg
+REFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVN
+RU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNF
+LApEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhP
+V0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GCkxJQUJJTElUWSwgV0hF
+VEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5D
+TFVESU5HIE5FR0xJR0VOQ0UKT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBX
+QVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRgpBRFZJ
+U0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4K
+EOF
+
+my $botan_lic_b64_ws = $botan_lic_b64_garbage;
+$botan_lic_b64_ws =~ s/[^A-Za-z0-9+\/= \n]//g;
+
+my $botan_lic_b64 = $botan_lic_b64_ws;
+$botan_lic_b64 =~ s/[ \n]//g;
+
+
+my $botan_lic = <<'EOF';
+Copyright (C) 1999-2004 The Botan Project. All rights reserved.
+
+Redistribution and use in source and binary forms, for any use, with or without
+modification, is permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions, and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
+
+IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+EOF
+
+
+# Decoder...
+
+my $f;
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::NONE); };
+print "not " if $@ || !defined $f;
+print "ok 2\n";
+
+my $dec;
+eval { $dec = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec;
+print "ok 3\n";
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::IGNORE_WS); };
+print "not " if $@ || !defined $f;
+print "ok 4\n";
+
+my $dec_is;
+eval { $dec_is = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_is;
+print "ok 5\n";
+
+eval { $f = Botan::Base64_Decoder->new(&Botan::FULL_CHECK); };
+print "not " if $@ || !defined $f;
+print "ok 6\n";
+
+my $dec_fc;
+eval { $dec_fc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_fc;
+print "ok 7\n";
+
+
+# Testing clean base64 input
+
+my $data;
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 8\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 9\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64);
+ $data = $dec_fc->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 10\n";
+
+
+# Testing base64 input with whitespaces
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64_ws);
+ $dec->set_default_msg(1);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 11\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64_ws);
+ $dec_is->set_default_msg(1);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 12\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64_ws);
+ $dec_fc->set_default_msg(1);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 13\n";
+
+
+# Testing base64 input with garbage
+
+undef $data;
+eval {
+ $dec->process_msg($botan_lic_b64_garbage);
+ $dec->set_default_msg(2);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $botan_lic;
+print "ok 14\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($botan_lic_b64_garbage);
+ $dec_is->set_default_msg(2);
+ $data = $dec_is->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 15\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($botan_lic_b64_garbage);
+ $dec_fc->set_default_msg(2);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 16\n";
+
+
+# Encoder...
+
+eval { $f = Botan::Base64_Encoder->new(); };
+print "not " if $@ || !defined $f;
+print "ok 17\n";
+
+my $enc;
+eval { $enc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc;
+print "ok 18\n";
+
+eval { $f = Botan::Base64_Encoder->new(1, 5); };
+print "not " if $@ || !defined $f;
+print "ok 19\n";
+
+my $enc2;
+eval { $enc2 = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc2;
+print "ok 20\n";
+
+undef $data;
+eval {
+ $enc->process_msg("Hello\n");
+ $data = $enc->read();
+};
+print "not " if $@ || $data ne "SGVsbG8K";
+print "ok 21\n";
+
+undef $data;
+eval {
+ $enc2->process_msg("Hello\n");
+ $data = $enc2->read();
+};
+print "not " if $@ || $data ne "SGVsb\nG8K\n";
+print "ok 22\n";
+
+
+# Encoder with decoder...
+
+my $p;
+eval {
+ $p = Botan::Pipe->new(
+ Botan::Base64_Encoder->new(),
+ Botan::Base64_Decoder->new(),
+ );
+};
+print "not " if $@ || !defined $p;
+print "ok 23\n";
+
+print "not " unless random_message_ok($p);
+print "ok 24\n";
diff --git a/botan/wrappers/perl-xs/t/filt.t b/botan/wrappers/perl-xs/t/filt.t
new file mode 100644
index 0000000..2a7b4c8
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/filt.t
@@ -0,0 +1,56 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..5\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $pipe = Botan::Pipe->new(Botan::Hex_Encoder->new());
+
+print "not " unless $pipe;
+print "ok 2\n";
+
+$pipe->process_msg('FOO');
+
+print "not " if $pipe->read() ne '464F4F';
+print "ok 3\n";
+
+$pipe = Botan::Pipe->new(Botan::Hex_Encoder->new(0, 0, 1));
+
+print "not " unless $pipe;
+print "ok 4\n";
+
+$pipe->process_msg('FOO');
+
+print "not " if $pipe->read() ne '464f4f';
+print "ok 5\n";
+
+
+
+
+
+
+#my $pipe = Botan::Pipe->new(Botan::Base64_Encoder->new());
+#$pipe->process_msg('FOO');
+#
+#print "not " if $pipe->read() ne 'Rk9P';
+#print "ok 4\n";
+
diff --git a/botan/wrappers/perl-xs/t/hex.t b/botan/wrappers/perl-xs/t/hex.t
new file mode 100644
index 0000000..6f447b2
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/hex.t
@@ -0,0 +1,256 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..24\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+require 't/testutl.pl';
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+# Data prep
+
+my ($hex, $hex_ws, $hex_garbage);
+while ( $_ = <DATA> )
+{
+ $hex_garbage .= $_;
+ s/[^[:xdigit:][:space:]]//g;
+ $hex_ws .= $_;
+ s/[^[:xdigit:]]//g;
+ $hex .= $_;
+}
+my $data_test = pack("H*", $hex);
+
+# Decoder...
+
+my $f;
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::NONE); };
+print "not " if $@ || !defined $f;
+print "ok 2\n";
+
+my $dec;
+eval { $dec = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec;
+print "ok 3\n";
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::IGNORE_WS); };
+print "not " if $@ || !defined $f;
+print "ok 4\n";
+
+my $dec_is;
+eval { $dec_is = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_is;
+print "ok 5\n";
+
+eval { $f = Botan::Hex_Decoder->new(&Botan::FULL_CHECK); };
+print "not " if $@ || !defined $f;
+print "ok 6\n";
+
+my $dec_fc;
+eval { $dec_fc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $dec_fc;
+print "ok 7\n";
+
+
+# Testing clean hexadecimal input
+
+my $data;
+
+undef $data;
+eval {
+ $dec->process_msg($hex);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 8\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 9\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex);
+ $data = $dec_fc->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 10\n";
+
+
+# Testing hexadecimal input with whitespaces
+
+undef $data;
+eval {
+ $dec->process_msg($hex_ws);
+ $dec->set_default_msg(1);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 11\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex_ws);
+ $dec_is->set_default_msg(1);
+ $data = $dec_is->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 12\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex_ws);
+ $dec_fc->set_default_msg(1);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 13\n";
+
+
+# Testing hexadecimal input with garbage
+
+undef $data;
+eval {
+ $dec->process_msg($hex_garbage);
+ $dec->set_default_msg(2);
+ $data = $dec->read();
+};
+
+print "not " if $@ || $data ne $data_test;
+print "ok 14\n";
+
+undef $data;
+eval {
+ $dec_is->process_msg($hex_garbage);
+ $dec_is->set_default_msg(2);
+ $data = $dec_is->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 15\n";
+
+undef $data;
+eval {
+ $dec_fc->process_msg($hex_garbage);
+ $dec_fc->set_default_msg(2);
+ $data = $dec_fc->read();
+};
+
+print "not " unless $@ && !defined $data;
+print "ok 16\n";
+
+
+# Encoder...
+
+eval { $f = Botan::Hex_Encoder->new(); };
+print "not " if $@ || !defined $f;
+print "ok 17\n";
+
+my $enc;
+eval { $enc = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc;
+print "ok 18\n";
+
+eval { $f = Botan::Hex_Encoder->new(1, 5, 1); };
+print "not " if $@ || !defined $f;
+print "ok 19\n";
+
+my $enc2;
+eval { $enc2 = Botan::Pipe->new($f); };
+print "not " if $@ || !defined $enc2;
+print "ok 20\n";
+
+undef $data;
+eval {
+ $enc->process_msg("Hello\n");
+ $data = $enc->read();
+};
+print "not " if $@ || $data ne "48656C6C6F0A";
+print "ok 21\n";
+
+undef $data;
+eval {
+ $enc2->process_msg("Hello\n");
+ $data = $enc2->read();
+};
+print "not " if $@ || $data ne "48656\nc6c6f\n0a\n";
+print "ok 22\n";
+
+
+# Encoder with decoder...
+
+my $p;
+eval {
+ $p = Botan::Pipe->new(
+ Botan::Hex_Encoder->new(),
+ Botan::Hex_Decoder->new(),
+ );
+};
+print "not " if $@ || !defined $p;
+print "ok 23\n";
+
+print "not " unless random_message_ok($p);
+print "ok 24\n";
+
+
+
+__DATA__
+cb13 4a4d 7522 1fd3 c6f6 7786 d04b 3043 ..JMu"....w..K..
+4552 4bcf 4d2b 9d71 0cfe 4d6a 1caf bcfd .RK.M+.q..Mj....
+8f91 6151 ff85 e900 7e6a bafc 15e9 ae51 ...Q....~j.....Q
+b14b 7210 bb40 5958 2b82 d49e b808 68a5 .Kr..@YX+.....h.
+7945 9dec f686 9b98 989e 826d 8088 6ee7 y..........m..n.
+d066 1eac 8c34 c461 bb54 7726 87ab d681 .........Tw&....
+a0be 52e5 1128 0cf2 759e cb2d e690 4ed9 ..R..(..u..-..N.
+7e88 bda7 2523 4a0f 185a 02b1 f898 fc41 ~...%#J..Z......
+dd48 fa87 945d 7611 b8c9 a50a 2de2 b670 .H...]v.....-..p
+0056 c8be 2cbb e7d0 1e70 4a3d 79f0 dce9 .V..,....pJ=y...
+b57f 154b 2b3a db73 f086 de11 9f3e 1641 ...K+:.s.....>..
+3a28 8b9b bb0f 682b 80db b791 89e0 62c0 :(....h+........
+7204 db97 5432 2eb0 a04e f38e 809f 7223 r...T....N....r#
+912e e552 1452 6dd2 e09f dd06 c715 7c1a ...R.Rm.......|.
+fe3d d6cc b6d0 a17a 27d7 4327 4e43 8af3 .=.....z'..'N...
+6eb5 e9f8 bfe9 34c3 6636 8243 358f 966d n..............m
+7d87 d17b 5c37 6acb 4972 f4ec 6806 bbde }..{\.j.Ir..h...
+2689 a019 a9e2 4101 7fe2 de72 bc03 eb5e &..........r...^
+b699 2d6b f8cd a08e 6e01 edfc a81a 94b6 ..-k....n.......
+9073 15fb efb2 c8d9 9f85 6633 85f1 e9d0 .s..............
+20ce 578b ab9d 2e51 b947 69bf fba5 82c6 .W....Q.Gi.....
+2ed0 dd36 d679 a399 7db3 8a0d cdef 0eda .....y..}.......
+e761 e7f1 5b17 3f67 0c83 215a eddf 9d2a ....[.?g..!Z...*
+5e70 0a77 c92e 94e1 a82b fd7c f10a 894f ^p.w.....+.|...O
+2955 f0e8 7398 f409 2040 b797 da03 a5a6 )U..s... @......
+7ba4 c3c9 2659 b9f7 6a56 e17a b481 983f {...&Y..jV.z...?
+00ed 3cc8 5a22 ad5c b6e0 3566 d717 35a6 ..<.Z".\........
+1523 4104 de63 477e fd24 68e5 e816 98df .#....G~.$h.....
+1747 417e db72 a76a be5b b9dc 3dfb 2d05 .G.~.r.j.[..=.-.
+d27f e597 eafc 9a29 15c5 792d 9c88 9aea .......)..y-....
+485e e431 96c3 7723 da6d 28b2 477a fd12 H^....w#.m(.Gz..
+e645 5dcd 7d5a d8b4 7acc 10b2 b41a e11d ..].}Z..z.......
diff --git a/botan/wrappers/perl-xs/t/oid.t b/botan/wrappers/perl-xs/t/oid.t
new file mode 100644
index 0000000..6620454
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/oid.t
@@ -0,0 +1,45 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..6\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+print "not " unless Botan::OIDS::have_oid('X520.CommonName');
+print "ok 2\n";
+
+my $oid_c = Botan::OID->new('2.5.4.3');
+print "not " if Botan::OIDS::lookup_by_oid($oid_c) ne 'X520.CommonName';
+print "ok 3\n";
+
+my $oid_x = Botan::OIDS::lookup_by_name('X520.CommonName');
+print "not " if $oid_x->as_string() ne '2.5.4.3';
+print "ok 4\n";
+
+my $oid_foo_num = '1.2.3.4.5.6.7.8.9.10.11.12.13.14.15';
+my $oid_foo = Botan::OID->new($oid_foo_num);
+print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne $oid_foo_num;
+print "ok 5\n";
+
+Botan::OIDS::add_oid($oid_foo, 'Zito.Foo');
+
+print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne 'Zito.Foo';
+print "ok 6\n";
diff --git a/botan/wrappers/perl-xs/t/pipe.t b/botan/wrappers/perl-xs/t/pipe.t
new file mode 100644
index 0000000..f850d85
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/pipe.t
@@ -0,0 +1,98 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..20\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $pipe = Botan::Pipe->new();
+
+print "not " unless $pipe;
+print "ok 2\n";
+
+$pipe->start_msg();
+$pipe->write('Hello world');
+$pipe->end_msg();
+
+print "not " if $pipe->message_count() != 1;
+print "ok 3\n";
+
+print "not " if $pipe->remaining() != 11;
+print "ok 4\n";
+
+print "not " if $pipe->end_of_data();
+print "ok 5\n";
+
+print "not " if $pipe->read() ne 'Hello world';
+print "ok 6\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 7\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 8\n";
+
+$pipe->process_msg('Hello world');
+
+print "not " if $pipe->message_count() != 2;
+print "ok 9\n";
+
+my $msg_num = $pipe->message_count() -1;
+
+print "not " if $pipe->read(5, $msg_num) ne 'Hello';
+print "ok 10\n";
+
+print "not " if $pipe->read(6, $msg_num) ne ' world';
+print "ok 11\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 12\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 13\n";
+
+$pipe->process_msg("The\0string\0with\0null\0chars\0");
+$msg_num = $pipe->message_count() -1;
+
+print "not " if $pipe->read(80, $msg_num) ne "The\0string\0with\0null\0chars\0";
+print "ok 14\n";
+
+$pipe->process_msg('FOO BAR');
+$pipe->set_default_msg($pipe->message_count() -1);
+
+print "not " if $pipe->peek(3) ne 'FOO';
+print "ok 15\n";
+
+print "not " if $pipe->peek(3, 4) ne 'BAR';
+print "ok 16\n";
+
+print "not " if $pipe->peek() ne 'FOO BAR';
+print "ok 17\n";
+
+print "not " if $pipe->read() ne 'FOO BAR';
+print "ok 18\n";
+
+print "not " if $pipe->remaining() != 0;
+print "ok 19\n";
+
+print "not " unless $pipe->end_of_data();
+print "ok 20\n";
+
diff --git a/botan/wrappers/perl-xs/t/testutl.pl b/botan/wrappers/perl-xs/t/testutl.pl
new file mode 100644
index 0000000..add6f6a
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/testutl.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+sub random_message_ok
+{
+ my ($pipe, $iter, $chunkmax) = @_;
+ $iter = 100 unless defined $iter;
+ $chunkmax = 300 unless defined $chunkmax;
+ eval {
+ my $input = '';
+ $pipe->start_msg();
+ for(my $i = 0; $i < $iter; $i++)
+ {
+ my $chunk = '';
+ my $chunklen = int(rand($chunkmax));
+ $chunk .= pack("C", int(rand(256))) while $chunklen--;
+ $input .= $chunk;
+ $pipe->write($chunk);
+ }
+ $pipe->end_msg();
+ my $msg_num = $pipe->message_count() -1;
+ my $output = $pipe->read(0xFFFFFFFF, $msg_num);
+ return $input eq $output;
+ };
+}
+
+1;
diff --git a/botan/wrappers/perl-xs/t/x509cert.t b/botan/wrappers/perl-xs/t/x509cert.t
new file mode 100644
index 0000000..2a943ae
--- /dev/null
+++ b/botan/wrappers/perl-xs/t/x509cert.t
@@ -0,0 +1,42 @@
+# vim: set ft=perl:
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..4\n"; }
+END { print "not ok 1\n" unless $loaded; }
+
+use Botan;
+
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+use strict;
+
+my $cert = Botan::X509_Certificate->new('data/ca.cert.der');
+
+print "not " if $cert->x509_version() != 3;
+print "ok 2\n";
+
+print "not " if $cert->start_time() ne '2000/8/20 21:48:00 UTC';
+print "ok 3\n";
+
+print "not " if $cert->end_time() ne '2002/8/10 21:48:00 UTC';
+print "ok 4\n";
+
+#my $subject = $cert->subject_dn()->get_attributes();
+#print STDERR "subject=", join(',', @{$subject}), "\n";
+#
+#my $issuer = $cert->issuer_dn()->get_attributes();
+#print STDERR "issuer=", join(',', @{$issuer}), "\n";
+#
diff --git a/botan/wrappers/perl-xs/typemap b/botan/wrappers/perl-xs/typemap
new file mode 100644
index 0000000..d7403d4
--- /dev/null
+++ b/botan/wrappers/perl-xs/typemap
@@ -0,0 +1,62 @@
+TYPEMAP
+
+Botan__ASN1_String * O_OBJECT
+Botan__AlgorithmIdentifier * O_OBJECT
+Botan__AlternativeName * O_OBJECT
+Botan__Attribute * O_OBJECT
+Botan__Base64_Decoder * O_EXTOBJECT
+Botan__Base64_Encoder * O_EXTOBJECT
+Botan__Chain * O_EXTOBJECT
+Botan__Extension * O_OBJECT
+Botan__Filter * O_EXTOBJECT
+Botan__Fork * O_EXTOBJECT
+Botan__Hex_Decoder * O_EXTOBJECT
+Botan__Hex_Encoder * O_EXTOBJECT
+Botan__OID * O_OBJECT
+Botan__Pipe * O_OBJECT
+Botan__X509_Certificate * O_OBJECT
+Botan__X509_DN * O_OBJECT
+Botan__X509_Time * O_OBJECT
+Botan__u32bit T_UV
+
+
+######################################################################
+OUTPUT
+
+# The Perl object is blessed into 'CLASS', which should be a
+# char* having the name of the package for the blessing.
+O_OBJECT
+ sv_setref_pv($arg, CLASS, (void*)$var);
+
+O_EXTOBJECT
+ sv_setref_pv($arg, CLASS, (void*)$var);
+ sv_magic(SvRV($arg), 0, '~', (char *)&oi_init, sizeof(oi_init));
+
+
+######################################################################
+INPUT
+
+O_OBJECT
+ if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+ $var = ($type)SvIV((SV*)SvRV( $arg ));
+ else
+ croak(\"${Package}::$func_name() -- \"
+ \"$var is not a blessed SV reference\");
+
+# The pointer variable "ObjectInfo *${var}_oi;" must be declared
+# in PREINIT section. I don't know how to emit this declaration safely here.
+O_EXTOBJECT
+ if ( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+ $var = ($type)SvIV((SV*)SvRV($arg));
+ else
+ croak(\"${Package}::$func_name() -- \"
+ \"$var is not a blessed SV reference\");
+ {
+ MAGIC *mg = mg_find(SvRV($arg), '~');
+ if ( mg == 0
+ || mg->mg_len != sizeof(ObjectInfo)
+ || *(I32 *)(mg->mg_ptr) != ObjectInfo::SIGNVAL )
+ croak(\"${Package}::$func_name() -- \"
+ \"private magic data for $var invalid\");
+ ${var}_oi = (ObjectInfo *)(mg->mg_ptr);
+ }
diff --git a/botan/wrappers/swig/base.cpp b/botan/wrappers/swig/base.cpp
new file mode 100644
index 0000000..448b3d4
--- /dev/null
+++ b/botan/wrappers/swig/base.cpp
@@ -0,0 +1,61 @@
+/*************************************************
+* SWIG Interface for basic Botan interface *
+* (C) 1999-2003 Jack Lloyd *
+*************************************************/
+
+#include "base.h"
+#include <botan/init.h>
+
+#include <stdio.h>
+
+/*************************************************
+* Initialize the library *
+*************************************************/
+LibraryInitializer::LibraryInitializer(const char* args)
+ {
+ Botan::Init::initialize(args);
+ }
+
+/*************************************************
+* Shut down the library *
+*************************************************/
+LibraryInitializer::~LibraryInitializer()
+ {
+ Botan::Init::deinitialize();
+ }
+
+/*************************************************
+* Create a SymmetricKey *
+*************************************************/
+SymmetricKey::SymmetricKey(const std::string& str)
+ {
+ key = new Botan::SymmetricKey(str);
+ printf("STR CON: %p %p\n", this, key);
+ }
+
+/*************************************************
+* Create a SymmetricKey *
+*************************************************/
+SymmetricKey::SymmetricKey(u32bit n)
+ {
+ key = new Botan::SymmetricKey(n);
+ printf("N CON: %p %p\n", this, key);
+ }
+
+/*************************************************
+* Destroy a SymmetricKey *
+*************************************************/
+SymmetricKey::~SymmetricKey()
+ {
+ printf("DESTR: %p %p\n", this, key);
+ delete key;
+ key = 0;
+ //printf("deleted\n");
+ }
+
+/*************************************************
+* Create an InitializationVector *
+*************************************************/
+InitializationVector::InitializationVector(const std::string& str) : iv(str)
+ {
+ }
diff --git a/botan/wrappers/swig/base.h b/botan/wrappers/swig/base.h
new file mode 100644
index 0000000..341a5c3
--- /dev/null
+++ b/botan/wrappers/swig/base.h
@@ -0,0 +1,102 @@
+/*************************************************
+* SWIG Interface for Botan *
+* (C) 1999-2003 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_WRAP_BASE_H__
+#define BOTAN_WRAP_BASE_H__
+
+#include <botan/pipe.h>
+
+#if !defined(SWIG)
+ #define OUTPUT
+ #define INOUT
+#endif
+
+/*************************************************
+* Typedefs *
+*************************************************/
+typedef unsigned char byte;
+typedef unsigned int u32bit;
+
+/*************************************************
+* Library Initalization/Shutdown Object *
+*************************************************/
+class LibraryInitializer
+ {
+ public:
+ LibraryInitializer(const char*);
+ ~LibraryInitializer();
+ };
+
+/*************************************************
+* Symmetric Key Object *
+*************************************************/
+class SymmetricKey
+ {
+ public:
+ std::string as_string() const { return key->as_string(); }
+ u32bit length() const { return key->length(); }
+ SymmetricKey(u32bit = 0);
+ SymmetricKey(const std::string&);
+ ~SymmetricKey();
+ private:
+ Botan::SymmetricKey* key;
+ };
+
+/*************************************************
+* Initialization Vector Object *
+*************************************************/
+class InitializationVector
+ {
+ public:
+ std::string as_string() const { return iv.as_string(); }
+ u32bit length() const { return iv.length(); }
+ InitializationVector(u32bit n = 0) { iv.change(n); }
+ InitializationVector(const std::string&);
+ private:
+ Botan::InitializationVector iv;
+ };
+
+/*************************************************
+* Filter Object *
+*************************************************/
+class Filter
+ {
+ public:
+ Filter(const char*);
+ //Filter(const char*, const SymmetricKey&);
+ //Filter(const char*, const SymmetricKey&, const InitializationVector&);
+ ~Filter();
+ private:
+ friend class Pipe;
+ Botan::Filter* filter;
+ bool pipe_owns;
+ };
+
+/*************************************************
+* Pipe Object *
+*************************************************/
+class Pipe
+ {
+ public:
+ static const u32bit DEFAULT_MESSAGE = 0xFFFFFFFF;
+
+ void write_file(const char*);
+ void write_string(const char*);
+
+ u32bit read(byte*, u32bit, u32bit = DEFAULT_MESSAGE);
+ std::string read_all_as_string(u32bit = DEFAULT_MESSAGE);
+
+ u32bit remaining(u32bit = DEFAULT_MESSAGE);
+
+ void start_msg();
+ void end_msg();
+
+ Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0);
+ ~Pipe();
+ private:
+ Botan::Pipe* pipe;
+ };
+
+#endif
diff --git a/botan/wrappers/swig/botan.swg b/botan/wrappers/swig/botan.swg
new file mode 100644
index 0000000..9088f42
--- /dev/null
+++ b/botan/wrappers/swig/botan.swg
@@ -0,0 +1,26 @@
+/*************************************************
+* SWIG Interface for Botan *
+*************************************************/
+%module botan
+
+%include "typemaps.i"
+%include "std_string.i"
+%include "exception.i"
+%include "constraints.i"
+%include "carrays.i"
+
+%{
+#include "base.h"
+%}
+
+%exception {
+ try {
+ $action
+ }
+ catch(std::exception& e)
+ {
+ SWIG_exception(SWIG_RuntimeError, e.what());
+ }
+}
+
+%include "base.h"
diff --git a/botan/wrappers/swig/doit.py b/botan/wrappers/swig/doit.py
new file mode 100644
index 0000000..a84623e
--- /dev/null
+++ b/botan/wrappers/swig/doit.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python2
+
+import botan
+
+def hash_it(hash, input):
+ f1 = botan.Filter("MD5")
+ f2 = botan.Filter("Hex_Encoder")
+ pipe = botan.Pipe(f1, f2)
+
+ pipe.start_msg()
+ pipe.write_string(input)
+ pipe.end_msg()
+
+ print pipe.remaining()
+
+ out = pipe.read(0)
+
+
+
+
+def main:
+ init = botan.LibraryInitializer
+
+ print hash_it("MD5", "foo")
+
+
+ key1 = botan.SymmetricKey("ABCD")
+ print key1.as_string()
+ key2 = botan.SymmetricKey(16)
+ print key2.as_string()
+
+ iv1 = botan.InitializationVector(8)
+ print iv1.as_string()
+
+
+ f3 = pipe.read(pipe.remaining())
+
+ size = pipe.remaining()
+ out = botan.byte_array(size)
+ pipe.read(out.cast,size)
+
+ for i in range (0,size):
+ print "%02X" % out[i]
+
+ print pipe.read_all_as_string()
+
+if __name__ == "__main__":
+ sys.exit(main())
+
diff --git a/botan/wrappers/swig/filter.cpp b/botan/wrappers/swig/filter.cpp
new file mode 100644
index 0000000..53ff0e6
--- /dev/null
+++ b/botan/wrappers/swig/filter.cpp
@@ -0,0 +1,39 @@
+/*************************************************
+* SWIG Interface for Filter Retrieval *
+* (C) 1999-2003 Jack Lloyd *
+*************************************************/
+
+#include "base.h"
+#include <botan/lookup.h>
+#include <botan/filters.h>
+
+/*************************************************
+* Filter Creation *
+*************************************************/
+Filter::Filter(const char* filt_string)
+ {
+ filter = 0;
+ pipe_owns = false;
+
+ /*
+ Fixme: This is all so totally wrong. It needs to have full argument
+ processing for everything, all that kind of crap.
+ */
+ const std::string filt_name = filt_string;
+
+ if(Botan::have_hash(filt_name))
+ filter = new Botan::Hash_Filter(filt_name);
+ else if(filt_name == "Hex_Encoder")
+ filter = new Botan::Hex_Encoder;
+ }
+
+/*************************************************
+* Filter Destruction *
+*************************************************/
+Filter::~Filter()
+ {
+ /*
+ if(!pipe_owns)
+ delete filter;
+ */
+ }
diff --git a/botan/wrappers/swig/pipe.cpp b/botan/wrappers/swig/pipe.cpp
new file mode 100644
index 0000000..0f35d5a
--- /dev/null
+++ b/botan/wrappers/swig/pipe.cpp
@@ -0,0 +1,89 @@
+/*************************************************
+* SWIG Interface for Botan Pipe API *
+* (C) 1999-2003 Jack Lloyd *
+*************************************************/
+
+#include "base.h"
+#include <botan/pipe.h>
+
+#include <stdio.h>
+
+/*************************************************
+* Write the contents of a file into a Pipe *
+*************************************************/
+void Pipe::write_file(const char* filename)
+ {
+ Botan::DataSource_Stream in(filename);
+ pipe->write(in);
+ }
+
+/*************************************************
+* Write the contents of a string into a Pipe *
+*************************************************/
+void Pipe::write_string(const char* string)
+ {
+ pipe->write(string);
+ }
+
+/*************************************************
+* Read the contents of a Pipe into a buffer *
+*************************************************/
+u32bit Pipe::read(byte* buf, u32bit length, u32bit msg)
+ {
+ printf("read %p %d\n", buf, length);
+ return 0;
+ //return pipe->read(buf, length, msg);
+ }
+
+/*************************************************
+* Read the contents of a Pipe as a string *
+*************************************************/
+std::string Pipe::read_all_as_string(u32bit msg)
+ {
+ return pipe->read_all_as_string(msg);
+ }
+
+/*************************************************
+* Find out how much stuff the Pipe still has *
+*************************************************/
+u32bit Pipe::remaining(u32bit msg)
+ {
+ return pipe->remaining();
+ }
+
+/*************************************************
+* Start a new message *
+*************************************************/
+void Pipe::start_msg()
+ {
+ pipe->start_msg();
+ }
+
+/*************************************************
+* End the current msessage *
+*************************************************/
+void Pipe::end_msg()
+ {
+ pipe->end_msg();
+ }
+
+/*************************************************
+* Create a new Pipe *
+*************************************************/
+Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
+ {
+ pipe = new Botan::Pipe();
+
+ if(f1) { pipe->append(f1->filter); f1->pipe_owns = true; }
+ if(f2) { pipe->append(f2->filter); f2->pipe_owns = true; }
+ if(f3) { pipe->append(f3->filter); f3->pipe_owns = true; }
+ if(f4) { pipe->append(f4->filter); f4->pipe_owns = true; }
+ }
+
+/*************************************************
+* Destroy this Pipe *
+*************************************************/
+Pipe::~Pipe()
+ {
+ delete pipe;
+ }
diff --git a/botan/wrappers/swig/pk.swg b/botan/wrappers/swig/pk.swg
new file mode 100644
index 0000000..8e03cf1
--- /dev/null
+++ b/botan/wrappers/swig/pk.swg
@@ -0,0 +1,8 @@
+%module botan
+
+%{
+#undef ANY
+#include "botan/pubkey.h"
+%}
+
+%include "botan/pubkey.h"
diff --git a/botan/wrappers/swig/readme.txt b/botan/wrappers/swig/readme.txt
new file mode 100644
index 0000000..a9965d9
--- /dev/null
+++ b/botan/wrappers/swig/readme.txt
@@ -0,0 +1,34 @@
+This is the beginning of an attempt to SWIG-ify Botan so it can be accessed by
+other languages. You should use the latest SWIG 1.3 release (I am currently
+using SWIG 1.3.19). Currently I am only testing this code with Python 2.2.1,
+since that is the language I am mainly interested in at this point. Feel free
+to send me patches so this is usable with Perl or whatever.
+
+I'm not attempting to make everything in Botan usable from a script -
+basically, I just want the parts that *I* want to use. Most things are not
+supported yet, and there are lots of bugs in the stuff that does exist. If
+there is something in particular that you would like to be able to use from a
+script, let me know (patches are good, too).
+
+Todo:
+ * Why does it seg fault if we don't create a LibraryInitializer. It should
+ throw an exception, like it does in C++. Maybe have it init Botan when the
+ module is loaded? That seems a lot cleaner/nicer, but I don't know how to
+ do it yet.
+ * Lots of problems with exceptions
+ * Use constraints to prevent bad args when possible
+ * Pipe/Filter
+ - Better argument processing for all filters
+ - Support for ciphers, MACs, etc
+ - Chain + Fork
+ - Support for append/prepend/pop/reset in Pipe?
+ * Public Key Crypto
+ - RSA
+ - DSA
+ - DH
+ - Generic X.509 and PKCS #8 stuff
+ * PKI
+ - X.509 certs + CRLs
+ - PKCS #10 requests
+ - X.509 stores
+ - X.509 CA
diff --git a/botan/wrappers/swig/tests/block.py b/botan/wrappers/swig/tests/block.py
new file mode 100644
index 0000000..593937c
--- /dev/null
+++ b/botan/wrappers/swig/tests/block.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+import botan, base64
+
+class MyCipher(botan.BlockCipher):
+ def __init__(self):
+ botan.BlockCipher.__init__(self, 16, 16, 32, 8)
+ def encrypt(self, val):
+ print "encrypt", val
+ return val.swapcase()
+ def decrypt(self, val):
+ print "decrypt", val
+ return val.swapcase()
+ def set_key(self, key):
+ print "set_key", key
+ def clone(self):
+ print "cloning"
+ return MyCipher()
+ def name(self):
+ print "naming"
+ return "MyCipher"
+
+cipher = botan.BlockCipher("AES-128")
+
+print cipher.block_size
+print cipher.keylength_min
+print cipher.keylength_max
+print cipher.keylength_mod
+print cipher.name()
+
+for kl in range(1, 128):
+ if cipher.valid_keylength(kl):
+ print "1",
+ else:
+ print "0",
+print
+key = botan.SymmetricKey(16)
+
+cipher.set_key(key)
+ciphertext = cipher.encrypt("ABCDEFGH12345678")
+print base64.b16encode(ciphertext)
+
+cipher2 = cipher.clone()
+cipher2.set_key(key)
+
+plaintext = cipher2.decrypt(ciphertext)
+print plaintext
+
+botan.get_info(cipher)
+
+mycipher = MyCipher()
+botan.get_info(mycipher)
diff --git a/botan/wrappers/swig/tests/block2.py b/botan/wrappers/swig/tests/block2.py
new file mode 100644
index 0000000..5faccaf
--- /dev/null
+++ b/botan/wrappers/swig/tests/block2.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+import botan, base64
+
+class MyCipher(botan.BlockCipherImpl):
+ def __init__(self):
+ botan.BlockCipherImpl.__init__(self, 8, 8, 16, 1)
+
+ def name(self):
+ return "MyCipher"
+
+ def encrypt(self, input):
+ return input.swapcase()
+
+ def decrypt(self, input):
+ return input.swapcase()
+
+ def set_key(self, key):
+ print "Got key",key
+
+def test(cipher):
+ print
+ print cipher
+ print "Testing", cipher.name()
+ print cipher.block_size
+ print cipher.keylength_min, cipher.keylength_max, cipher.keylength_mod
+ for i in range(1, 64):
+ if cipher.valid_keylength(i):
+ print "1",
+ else:
+ print "0",
+ print
+ cipher.set_key(botan.SymmetricKey(16))
+ ciphertext = cipher.encrypt("aBcDeFgH" * (cipher.block_size / 8))
+ print repr(ciphertext)
+ print cipher.decrypt(ciphertext)
+
+def main():
+ test(botan.BlockCipher("Blowfish"))
+ test(MyCipher())
+ test(botan.BlockCipher("AES"))
+
+if __name__ == "__main__":
+ main()
diff --git a/botan/wrappers/swig/tests/encrypt.py b/botan/wrappers/swig/tests/encrypt.py
new file mode 100644
index 0000000..c36bab4
--- /dev/null
+++ b/botan/wrappers/swig/tests/encrypt.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+import sys, botan
+
+def encrypt(input):
+ cipher_key = botan.SymmetricKey("AABB")
+ print cipher_key.length
+ cipher_key = botan.SymmetricKey("AABBCCDD")
+ print cipher_key.length
+
+ cipher = botan.Filter("ARC4", key = cipher_key)
+
+ pipe = botan.Pipe(cipher, botan.Filter("Hex_Encoder"))
+
+ pipe.start_msg()
+ pipe.write(input)
+ pipe.end_msg()
+
+ str = pipe.read_all()
+ print str
+ return str
+
+def decrypt(input):
+ pipe = botan.Pipe(botan.Filter("Hex_Decoder"),
+ botan.Filter("ARC4",
+ key = botan.SymmetricKey("AABBCCDD")))
+
+ pipe.process_msg(input)
+ return pipe.read_all()
+
+def main():
+ ciphertext = encrypt("hi chappy")
+ print ciphertext
+ print decrypt(ciphertext)
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/botan/wrappers/swig/tests/filter.py b/botan/wrappers/swig/tests/filter.py
new file mode 100644
index 0000000..42637ba
--- /dev/null
+++ b/botan/wrappers/swig/tests/filter.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+import sys, botan
+
+class MyFilter(botan.FilterObj):
+ def write(self, input):
+ print "MyFilter::write",input
+ self.send(input)
+ def start_msg(self):
+ print "MyFilter::start_msg"
+ def end_msg(self):
+ print "MyFilter::end_msg"
+ def __del__(self):
+ print "~MyFilter"
+
+def main():
+ filter = MyFilter()
+
+ pipe = botan.Pipe(botan.Filter("Hex_Encoder"), filter,
+ botan.Filter("Hex_Decoder"))
+ pipe.start_msg()
+ pipe.write("hi chappy")
+ pipe.end_msg()
+ print pipe.read_all()
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/botan/wrappers/swig/tests/hash.py b/botan/wrappers/swig/tests/hash.py
new file mode 100644
index 0000000..930b8c8
--- /dev/null
+++ b/botan/wrappers/swig/tests/hash.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+import botan, base64, md5
+
+class PyMD5(botan.HashFunctionImpl):
+ def name(self):
+ return "PyMD5"
+ def update(self, input):
+ self.md5.update(input)
+ def final(self):
+ output = self.md5.digest()
+ self.md5 = md5.new()
+ return output
+ def __init__(self):
+ botan.HashFunctionImpl.__init__(self, 16, 64)
+ self.md5 = md5.new()
+
+hash = botan.HashFunction("SHA-256")
+
+print hash.name()
+print hash.digest_size
+
+hash.update("hi")
+hash.update(" ")
+hash.update("chappy")
+print base64.b16encode(hash.final())
+
+hash2 = PyMD5()
+hash2.update("hi chappy")
+print base64.b16encode(hash2.final())
diff --git a/botan/wrappers/swig/tests/mac.py b/botan/wrappers/swig/tests/mac.py
new file mode 100644
index 0000000..6110b61
--- /dev/null
+++ b/botan/wrappers/swig/tests/mac.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+import botan, base64
+
+mac = botan.MAC("HMAC(SHA-512)")
+
+print mac.name
+print mac.output_length
+
+mac.set_key(botan.SymmetricKey("abcd"))
+mac.update("hi chappy")
+print base64.b16encode(mac.final())
diff --git a/botan/wrappers/swig/tests/pubkey.py b/botan/wrappers/swig/tests/pubkey.py
new file mode 100644
index 0000000..456c520
--- /dev/null
+++ b/botan/wrappers/swig/tests/pubkey.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+import botan
+
+key = botan.X509_PublicKey("rsapub.pem")
+print key
+print key.key_id()
+print key.max_input_bits
+print key.algo
+print key.oid
diff --git a/botan/wrappers/swig/tests/stream.py b/botan/wrappers/swig/tests/stream.py
new file mode 100644
index 0000000..59d3ffa
--- /dev/null
+++ b/botan/wrappers/swig/tests/stream.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+import botan, base64
+
+cipher = botan.StreamCipher("ARC4")
+
+print cipher.name
+
+key = botan.SymmetricKey(16)
+
+cipher.set_key(key)
+ciphertext = cipher.crypt("hi chappy")
+
+cipher.set_key(key)
+plaintext = cipher.crypt(ciphertext)
+
+print plaintext
diff --git a/botan/wrappers/swig/x509.swg b/botan/wrappers/swig/x509.swg
new file mode 100644
index 0000000..736d3a3
--- /dev/null
+++ b/botan/wrappers/swig/x509.swg
@@ -0,0 +1,9 @@
+%module botan
+
+class X509_Certificate
+ {
+ public:
+
+
+ private:
+ };
diff --git a/coreplugin/core_global.h b/coreplugin/core_global.h
new file mode 100644
index 0000000..56b4d49
--- /dev/null
+++ b/coreplugin/core_global.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CORE_GLOBAL_H
+#define CORE_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(CORE_LIBRARY)
+# define CORE_EXPORT Q_DECL_EXPORT
+#else
+# define CORE_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // CORE_GLOBAL_H
diff --git a/coreplugin/ssh/sftpchannel.cpp b/coreplugin/ssh/sftpchannel.cpp
new file mode 100644
index 0000000..4c94c4a
--- /dev/null
+++ b/coreplugin/ssh/sftpchannel.cpp
@@ -0,0 +1,899 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftpchannel.h"
+#include "sftpchannel_p.h"
+
+#include "sshdelayedsignal_p.h"
+#include "sshexception_p.h"
+#include "sshsendfacility_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QWeakPointer>
+
+namespace Core {
+
+namespace Internal {
+namespace {
+ const quint32 ProtocolVersion = 3;
+
+ QString errorMessage(const QString &serverMessage,
+ const QString &alternativeMessage)
+ {
+ return serverMessage.isEmpty() ? alternativeMessage : serverMessage;
+ }
+
+ QString errorMessage(const SftpStatusResponse &response,
+ const QString &alternativeMessage)
+ {
+ return response.status == SSH_FX_OK ? QString()
+ : errorMessage(response.errorString, alternativeMessage);
+ }
+} // anonymous namespace
+} // namespace Internal
+
+SftpChannel::SftpChannel(quint32 channelId,
+ Internal::SshSendFacility &sendFacility)
+ : d(new Internal::SftpChannelPrivate(channelId, sendFacility, this))
+{
+}
+
+SftpChannel::State SftpChannel::state() const
+{
+ switch (d->channelState()) {
+ case Internal::AbstractSshChannel::Inactive:
+ return Uninitialized;
+ case Internal::AbstractSshChannel::SessionRequested:
+ return Initializing;
+ case Internal::AbstractSshChannel::CloseRequested:
+ return Closing;
+ case Internal::AbstractSshChannel::Closed:
+ return Closed;
+ case Internal::AbstractSshChannel::SessionEstablished:
+ return d->m_sftpState == Internal::SftpChannelPrivate::Initialized
+ ? Initialized : Initializing;
+ default:
+ Q_ASSERT(!"Oh no, we forgot to handle a channel state!");
+ return Closed; // For the compiler.
+ }
+}
+
+void SftpChannel::initialize()
+{
+ d->requestSessionStart();
+ d->m_sftpState = Internal::SftpChannelPrivate::SubsystemRequested;
+}
+
+void SftpChannel::closeChannel()
+{
+ d->closeChannel();
+}
+
+SftpJobId SftpChannel::listDirectory(const QString &path)
+{
+ return d->createJob(Internal::SftpListDir::Ptr(
+ new Internal::SftpListDir(++d->m_nextJobId, path)));
+}
+
+SftpJobId SftpChannel::createDirectory(const QString &path)
+{
+ return d->createJob(Internal::SftpMakeDir::Ptr(
+ new Internal::SftpMakeDir(++d->m_nextJobId, path)));
+}
+
+SftpJobId SftpChannel::removeDirectory(const QString &path)
+{
+ return d->createJob(Internal::SftpRmDir::Ptr(
+ new Internal::SftpRmDir(++d->m_nextJobId, path)));
+}
+
+SftpJobId SftpChannel::removeFile(const QString &path)
+{
+ return d->createJob(Internal::SftpRm::Ptr(
+ new Internal::SftpRm(++d->m_nextJobId, path)));
+}
+
+SftpJobId SftpChannel::renameFileOrDirectory(const QString &oldPath,
+ const QString &newPath)
+{
+ return d->createJob(Internal::SftpRename::Ptr(
+ new Internal::SftpRename(++d->m_nextJobId, oldPath, newPath)));
+}
+
+SftpJobId SftpChannel::createFile(const QString &path, SftpOverwriteMode mode)
+{
+ return d->createJob(Internal::SftpCreateFile::Ptr(
+ new Internal::SftpCreateFile(++d->m_nextJobId, path, mode)));
+}
+
+SftpJobId SftpChannel::uploadFile(const QString &localFilePath,
+ const QString &remoteFilePath, SftpOverwriteMode mode)
+{
+ QSharedPointer<QFile> localFile(new QFile(localFilePath));
+ if (!localFile->open(QIODevice::ReadOnly))
+ return SftpInvalidJob;
+ return d->createJob(Internal::SftpUploadFile::Ptr(
+ new Internal::SftpUploadFile(++d->m_nextJobId, remoteFilePath, localFile, mode)));
+}
+
+SftpJobId SftpChannel::downloadFile(const QString &remoteFilePath,
+ const QString &localFilePath, SftpOverwriteMode mode)
+{
+ QSharedPointer<QFile> localFile(new QFile(localFilePath));
+ if (mode == SftpSkipExisting && localFile->exists())
+ return SftpInvalidJob;
+ QIODevice::OpenMode openMode = QIODevice::WriteOnly;
+ if (mode == SftpOverwriteExisting)
+ openMode |= QIODevice::Truncate;
+ else if (mode == SftpAppendToExisting)
+ openMode |= QIODevice::Append;
+ if (!localFile->open(openMode))
+ return SftpInvalidJob;
+ return d->createJob(Internal::SftpDownload::Ptr(
+ new Internal::SftpDownload(++d->m_nextJobId, remoteFilePath, localFile)));
+}
+
+SftpJobId SftpChannel::uploadDir(const QString &localDirPath,
+ const QString &remoteParentDirPath)
+{
+ if (state() != Initialized)
+ return SftpInvalidJob;
+ const QDir localDir(localDirPath);
+ if (!localDir.exists() || !localDir.isReadable())
+ return SftpInvalidJob;
+ const Internal::SftpUploadDir::Ptr uploadDirOp(
+ new Internal::SftpUploadDir(++d->m_nextJobId));
+ const QString remoteDirPath
+ = remoteParentDirPath + QLatin1Char('/') + localDir.dirName();
+ const Internal::SftpMakeDir::Ptr mkdirOp(
+ new Internal::SftpMakeDir(++d->m_nextJobId, remoteDirPath, uploadDirOp));
+ uploadDirOp->mkdirsInProgress.insert(mkdirOp,
+ Internal::SftpUploadDir::Dir(localDirPath, remoteDirPath));
+ d->createJob(mkdirOp);
+ return uploadDirOp->jobId;
+}
+
+SftpChannel::~SftpChannel()
+{
+ delete d;
+}
+
+
+namespace Internal {
+
+SftpChannelPrivate::SftpChannelPrivate(quint32 channelId,
+ SshSendFacility &sendFacility, SftpChannel *sftp)
+ : AbstractSshChannel(channelId, sendFacility),
+ m_nextJobId(0), m_sftpState(Inactive), m_sftp(sftp)
+{
+}
+
+SftpJobId SftpChannelPrivate::createJob(const AbstractSftpOperation::Ptr &job)
+{
+ if (m_sftp->state() != SftpChannel::Initialized)
+ return SftpInvalidJob;
+ m_jobs.insert(job->jobId, job);
+ sendData(job->initialPacket(m_outgoingPacket).rawData());
+ return job->jobId;
+}
+
+void SftpChannelPrivate::handleChannelSuccess()
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("sftp subsystem initialized");
+#endif
+ sendData(m_outgoingPacket.generateInit(ProtocolVersion).rawData());
+ m_sftpState = InitSent;
+}
+
+void SftpChannelPrivate::handleChannelFailure()
+{
+ if (m_sftpState != SubsystemRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_FAILURE packet.");
+ }
+ createDelayedInitFailedSignal(SSH_TR("Server could not start sftp subsystem."));
+ closeChannel();
+}
+
+void SftpChannelPrivate::handleChannelDataInternal(const QByteArray &data)
+{
+ m_incomingData += data;
+ m_incomingPacket.consumeData(m_incomingData);
+ while (m_incomingPacket.isComplete()) {
+ handleCurrentPacket();
+ m_incomingPacket.clear();
+ m_incomingPacket.consumeData(m_incomingData);
+ }
+}
+
+void SftpChannelPrivate::handleChannelExtendedDataInternal(quint32 type,
+ const QByteArray &data)
+{
+ qWarning("Unexpected extended data '%s' of type %d on SFTP channel.",
+ data.data(), type);
+}
+
+void SftpChannelPrivate::handleCurrentPacket()
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Handling SFTP packet of type %d", m_incomingPacket.type());
+#endif
+ switch (m_incomingPacket.type()) {
+ case SSH_FXP_VERSION:
+ handleServerVersion();
+ break;
+ case SSH_FXP_HANDLE:
+ handleHandle();
+ break;
+ case SSH_FXP_NAME:
+ handleName();
+ break;
+ case SSH_FXP_STATUS:
+ handleStatus();
+ break;
+ case SSH_FXP_DATA:
+ handleReadData();
+ break;
+ case SSH_FXP_ATTRS:
+ handleAttrs();
+ break;
+ default:
+ throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected packet.",
+ SSH_TR("Unexpected packet of type %d.").arg(m_incomingPacket.type()));
+ }
+}
+
+void SftpChannelPrivate::handleServerVersion()
+{
+ checkChannelActive();
+ if (m_sftpState != InitSent) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_VERSION packet.");
+ }
+
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("sftp init received");
+#endif
+ const quint32 serverVersion = m_incomingPacket.extractServerVersion();
+ if (serverVersion != ProtocolVersion) {
+ createDelayedInitFailedSignal(SSH_TR("Protocol version mismatch: Expected %1, got %2")
+ .arg(serverVersion).arg(ProtocolVersion));
+ closeChannel();
+ } else {
+ m_sftpState = Initialized;
+ createDelayedInitializedSignal();
+ }
+}
+
+void SftpChannelPrivate::handleHandle()
+{
+ const SftpHandleResponse &response = m_incomingPacket.asHandleResponse();
+ JobMap::Iterator it = lookupJob(response.requestId);
+ const QSharedPointer<AbstractSftpOperationWithHandle> job
+ = it.value().dynamicCast<AbstractSftpOperationWithHandle>();
+ if (job.isNull()) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_HANDLE packet.");
+ }
+ if (job->state != AbstractSftpOperationWithHandle::OpenRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_HANDLE packet.");
+ }
+ job->remoteHandle = response.handle;
+ job->state = AbstractSftpOperationWithHandle::Open;
+
+ switch (it.value()->type()) {
+ case AbstractSftpOperation::ListDir:
+ handleLsHandle(it);
+ break;
+ case AbstractSftpOperation::CreateFile:
+ handleCreateFileHandle(it);
+ break;
+ case AbstractSftpOperation::Download:
+ handleGetHandle(it);
+ break;
+ case AbstractSftpOperation::UploadFile:
+ handlePutHandle(it);
+ break;
+ default:
+ Q_ASSERT(!"Oh no, I forgot to handle an SFTP operation type!");
+ }
+}
+
+void SftpChannelPrivate::handleLsHandle(const JobMap::Iterator &it)
+{
+ SftpListDir::Ptr op = it.value().staticCast<SftpListDir>();
+ sendData(m_outgoingPacket.generateReadDir(op->remoteHandle,
+ op->jobId).rawData());
+}
+
+void SftpChannelPrivate::handleCreateFileHandle(const JobMap::Iterator &it)
+{
+ SftpCreateFile::Ptr op = it.value().staticCast<SftpCreateFile>();
+ sendData(m_outgoingPacket.generateCloseHandle(op->remoteHandle,
+ op->jobId).rawData());
+}
+
+void SftpChannelPrivate::handleGetHandle(const JobMap::Iterator &it)
+{
+ SftpDownload::Ptr op = it.value().staticCast<SftpDownload>();
+ sendData(m_outgoingPacket.generateFstat(op->remoteHandle,
+ op->jobId).rawData());
+ op->statRequested = true;
+}
+
+void SftpChannelPrivate::handlePutHandle(const JobMap::Iterator &it)
+{
+ SftpUploadFile::Ptr op = it.value().staticCast<SftpUploadFile>();
+ if (op->parentJob && op->parentJob->hasError)
+ sendTransferCloseHandle(op, it.key());
+
+ // OpenSSH does not implement the RFC's append functionality, so we
+ // have to emulate it.
+ if (op->mode == SftpAppendToExisting) {
+ sendData(m_outgoingPacket.generateFstat(op->remoteHandle,
+ op->jobId).rawData());
+ op->statRequested = true;
+ } else {
+ spawnWriteRequests(it);
+ }
+}
+
+void SftpChannelPrivate::handleStatus()
+{
+ const SftpStatusResponse &response = m_incomingPacket.asStatusResponse();
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("%s: status = %d", Q_FUNC_INFO, response.status);
+#endif
+ JobMap::Iterator it = lookupJob(response.requestId);
+ switch (it.value()->type()) {
+ case AbstractSftpOperation::ListDir:
+ handleLsStatus(it, response);
+ break;
+ case AbstractSftpOperation::Download:
+ handleGetStatus(it, response);
+ break;
+ case AbstractSftpOperation::UploadFile:
+ handlePutStatus(it, response);
+ break;
+ case AbstractSftpOperation::MakeDir:
+ handleMkdirStatus(it, response);
+ break;
+ case AbstractSftpOperation::RmDir:
+ case AbstractSftpOperation::Rm:
+ case AbstractSftpOperation::Rename:
+ case AbstractSftpOperation::CreateFile:
+ handleStatusGeneric(it, response);
+ break;
+ }
+}
+
+void SftpChannelPrivate::handleStatusGeneric(const JobMap::Iterator &it,
+ const SftpStatusResponse &response)
+{
+ AbstractSftpOperation::Ptr op = it.value();
+ const QString error = errorMessage(response, SSH_TR("Unknown error."));
+ createDelayedJobFinishedSignal(op->jobId, error);
+ m_jobs.erase(it);
+}
+
+void SftpChannelPrivate::handleMkdirStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response)
+{
+ SftpMakeDir::Ptr op = it.value().staticCast<SftpMakeDir>();
+ if (op->parentJob == SftpUploadDir::Ptr()) {
+ handleStatusGeneric(it, response);
+ return;
+ }
+ if (op->parentJob->hasError) {
+ m_jobs.erase(it);
+ return;
+ }
+
+ typedef QMap<SftpMakeDir::Ptr, SftpUploadDir::Dir>::Iterator DirIt;
+ DirIt dirIt = op->parentJob->mkdirsInProgress.find(op);
+ Q_ASSERT(dirIt != op->parentJob->mkdirsInProgress.end());
+ const QString &remoteDir = dirIt.value().remoteDir;
+ if (response.status == SSH_FX_OK) {
+ createDelayedDataAvailableSignal(op->parentJob->jobId,
+ SSH_TR("Created remote directory '%1'.").arg(remoteDir));
+ } else if (response.status == SSH_FX_FAILURE) {
+ createDelayedDataAvailableSignal(op->parentJob->jobId,
+ SSH_TR("Remote directory '%1' already exists.").arg(remoteDir));
+ } else {
+ op->parentJob->setError();
+ createDelayedJobFinishedSignal(op->parentJob->jobId,
+ SSH_TR("Error creating directory '%1': %2")
+ .arg(remoteDir, response.errorString));
+ m_jobs.erase(it);
+ return;
+ }
+
+ QDir localDir(dirIt.value().localDir);
+ const QFileInfoList &dirInfos
+ = localDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QFileInfo &dirInfo, dirInfos) {
+ const QString remoteSubDir = remoteDir + '/' + dirInfo.fileName();
+ const SftpMakeDir::Ptr mkdirOp(
+ new SftpMakeDir(++m_nextJobId, remoteSubDir, op->parentJob));
+ op->parentJob->mkdirsInProgress.insert(mkdirOp,
+ SftpUploadDir::Dir(dirInfo.absoluteFilePath(), remoteSubDir));
+ createJob(mkdirOp);
+ }
+
+ const QFileInfoList &fileInfos = localDir.entryInfoList(QDir::Files);
+ foreach (const QFileInfo &fileInfo, fileInfos) {
+ QSharedPointer<QFile> localFile(new QFile(fileInfo.absoluteFilePath()));
+ if (!localFile->open(QIODevice::ReadOnly)) {
+ op->parentJob->setError();
+ createDelayedJobFinishedSignal(op->parentJob->jobId,
+ SSH_TR("Could not open local file '%1': %2")
+ .arg(fileInfo.absoluteFilePath(), localFile->error()));
+ m_jobs.erase(it);
+ return;
+ }
+
+ const QString remoteFilePath = remoteDir + '/' + fileInfo.fileName();
+ SftpUploadFile::Ptr uploadFileOp(new SftpUploadFile(++m_nextJobId,
+ remoteFilePath, localFile, SftpOverwriteExisting, op->parentJob));
+ createJob(uploadFileOp);
+ op->parentJob->uploadsInProgress.append(uploadFileOp);
+ }
+
+ op->parentJob->mkdirsInProgress.erase(dirIt);
+ if (op->parentJob->mkdirsInProgress.isEmpty()
+ && op->parentJob->uploadsInProgress.isEmpty())
+ createDelayedJobFinishedSignal(op->parentJob->jobId);
+ m_jobs.erase(it);
+}
+
+void SftpChannelPrivate::handleLsStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response)
+{
+ SftpListDir::Ptr op = it.value().staticCast<SftpListDir>();
+ switch (op->state) {
+ case SftpListDir::OpenRequested:
+ createDelayedJobFinishedSignal(op->jobId, errorMessage(response.errorString,
+ SSH_TR("Remote directory could not be opened for reading.")));
+ m_jobs.erase(it);
+ break;
+ case SftpListDir::Open:
+ if (response.status != SSH_FX_EOF)
+ reportRequestError(op, errorMessage(response.errorString,
+ SSH_TR("Failed to list remote directory contents.")));
+ op->state = SftpListDir::CloseRequested;
+ sendData(m_outgoingPacket.generateCloseHandle(op->remoteHandle,
+ op->jobId).rawData());
+ break;
+ case SftpListDir::CloseRequested:
+ if (!op->hasError) {
+ const QString error = errorMessage(response,
+ SSH_TR("Failed to close remote directory."));
+ createDelayedJobFinishedSignal(op->jobId, error);
+ }
+ m_jobs.erase(it);
+ break;
+ default:
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_STATUS packet.");
+ }
+}
+
+void SftpChannelPrivate::handleGetStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response)
+{
+ SftpDownload::Ptr op = it.value().staticCast<SftpDownload>();
+ switch (op->state) {
+ case SftpDownload::OpenRequested:
+ createDelayedJobFinishedSignal(op->jobId,
+ errorMessage(response.errorString,
+ SSH_TR("Failed to open remote file for reading.")));
+ m_jobs.erase(it);
+ break;
+ case SftpDownload::Open:
+ if (op->statRequested) {
+ reportRequestError(op, errorMessage(response.errorString,
+ SSH_TR("Failed to stat remote file.")));
+ sendTransferCloseHandle(op, response.requestId);
+ } else {
+ if ((response.status != SSH_FX_EOF || response.requestId != op->eofId)
+ && !op->hasError)
+ reportRequestError(op, errorMessage(response.errorString,
+ SSH_TR("Failed to read remote file.")));
+ finishTransferRequest(it);
+ }
+ break;
+ case SftpDownload::CloseRequested:
+ Q_ASSERT(op->inFlightCount == 1);
+ if (!op->hasError) {
+ if (response.status == SSH_FX_OK)
+ createDelayedJobFinishedSignal(op->jobId);
+ else
+ reportRequestError(op, errorMessage(response.errorString,
+ SSH_TR("Failed to close remote file.")));
+ }
+ removeTransferRequest(it);
+ break;
+ default:
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_STATUS packet.");
+ }
+}
+
+void SftpChannelPrivate::handlePutStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response)
+{
+ SftpUploadFile::Ptr job = it.value().staticCast<SftpUploadFile>();
+ switch (job->state) {
+ case SftpUploadFile::OpenRequested: {
+ bool emitError = false;
+ if (job->parentJob) {
+ if (!job->parentJob->hasError) {
+ job->parentJob->setError();
+ emitError = true;
+ }
+ } else {
+ emitError = true;
+ }
+
+ if (emitError) {
+ createDelayedJobFinishedSignal(job->jobId,
+ errorMessage(response.errorString,
+ SSH_TR("Failed to open remote file for writing.")));
+ }
+ m_jobs.erase(it);
+ break;
+ }
+ case SftpUploadFile::Open:
+ if (job->hasError || (job->parentJob && job->parentJob->hasError)) {
+ job->hasError = true;
+ finishTransferRequest(it);
+ return;
+ }
+
+ if (response.status == SSH_FX_OK) {
+ sendWriteRequest(it);
+ } else {
+ if (job->parentJob)
+ job->parentJob->setError();
+ reportRequestError(job, errorMessage(response.errorString,
+ SSH_TR("Failed to write remote file.")));
+ finishTransferRequest(it);
+ }
+ break;
+ case SftpUploadFile::CloseRequested:
+ Q_ASSERT(job->inFlightCount == 1);
+ if (job->hasError || (job->parentJob && job->parentJob->hasError)) {
+ m_jobs.erase(it);
+ return;
+ }
+
+ if (response.status == SSH_FX_OK) {
+ if (job->parentJob) {
+ job->parentJob->uploadsInProgress.removeOne(job);
+ if (job->parentJob->mkdirsInProgress.isEmpty()
+ && job->parentJob->uploadsInProgress.isEmpty())
+ createDelayedJobFinishedSignal(job->parentJob->jobId);
+ } else {
+ createDelayedJobFinishedSignal(job->jobId);
+ }
+ } else {
+ const QString error = errorMessage(response.errorString,
+ SSH_TR("Failed to close remote file."));
+ if (job->parentJob) {
+ job->parentJob->setError();
+ createDelayedJobFinishedSignal(job->parentJob->jobId, error);
+ } else {
+ createDelayedJobFinishedSignal(job->jobId, error);
+ }
+ }
+ m_jobs.erase(it);
+ break;
+ default:
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_STATUS packet.");
+ }
+}
+
+void SftpChannelPrivate::handleName()
+{
+ const SftpNameResponse &response = m_incomingPacket.asNameResponse();
+ JobMap::Iterator it = lookupJob(response.requestId);
+ switch (it.value()->type()) {
+ case AbstractSftpOperation::ListDir: {
+ SftpListDir::Ptr op = it.value().staticCast<SftpListDir>();
+ if (op->state != SftpListDir::Open) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_NAME packet.");
+ }
+
+ for (int i = 0; i < response.files.count(); ++i) {
+ const SftpFile &file = response.files.at(i);
+ createDelayedDataAvailableSignal(op->jobId, file.fileName);
+ }
+ sendData(m_outgoingPacket.generateReadDir(op->remoteHandle,
+ op->jobId).rawData());
+ break;
+ }
+ default:
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_NAME packet.");
+ }
+}
+
+void SftpChannelPrivate::handleReadData()
+{
+ const SftpDataResponse &response = m_incomingPacket.asDataResponse();
+ JobMap::Iterator it = lookupJob(response.requestId);
+ if (it.value()->type() != AbstractSftpOperation::Download) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_DATA packet.");
+ }
+
+ SftpDownload::Ptr op = it.value().staticCast<SftpDownload>();
+ if (op->hasError) {
+ finishTransferRequest(it);
+ return;
+ }
+
+ if (!op->localFile->seek(op->offsets[response.requestId])) {
+ reportRequestError(op, op->localFile->errorString());
+ finishTransferRequest(it);
+ return;
+ }
+
+ if (op->localFile->write(response.data) != response.data.size()) {
+ reportRequestError(op, op->localFile->errorString());
+ finishTransferRequest(it);
+ return;
+ }
+
+ if (op->offset >= op->fileSize && op->fileSize != 0)
+ finishTransferRequest(it);
+ else
+ sendReadRequest(op, response.requestId);
+}
+
+void SftpChannelPrivate::handleAttrs()
+{
+ const SftpAttrsResponse &response = m_incomingPacket.asAttrsResponse();
+ JobMap::Iterator it = lookupJob(response.requestId);
+ AbstractSftpTransfer::Ptr transfer
+ = it.value().dynamicCast<AbstractSftpTransfer>();
+ if (!transfer || transfer->state != AbstractSftpTransfer::Open
+ || !transfer->statRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_FXP_ATTRS packet.");
+ }
+ Q_ASSERT(transfer->type() == AbstractSftpOperation::UploadFile
+ || transfer->type() == AbstractSftpOperation::Download);
+
+ if (transfer->type() == AbstractSftpOperation::Download) {
+ SftpDownload::Ptr op = transfer.staticCast<SftpDownload>();
+ if (response.attrs.sizePresent) {
+ op->fileSize = response.attrs.size;
+ } else {
+ op->fileSize = 0;
+ op->eofId = op->jobId;
+ }
+ op->statRequested = false;
+ spawnReadRequests(op);
+ } else {
+ SftpUploadFile::Ptr op = transfer.staticCast<SftpUploadFile>();
+ if (op->parentJob && op->parentJob->hasError) {
+ op->hasError = true;
+ sendTransferCloseHandle(op, op->jobId);
+ return;
+ }
+
+ if (response.attrs.sizePresent) {
+ op->offset = response.attrs.size;
+ spawnWriteRequests(it);
+ } else {
+ if (op->parentJob)
+ op->parentJob->setError();
+ reportRequestError(op, SSH_TR("Cannot append to remote file: "
+ "Server does not support file size attribute."));
+ sendTransferCloseHandle(op, op->jobId);
+ }
+ }
+}
+
+SftpChannelPrivate::JobMap::Iterator SftpChannelPrivate::lookupJob(SftpJobId id)
+{
+ JobMap::Iterator it = m_jobs.find(id);
+ if (it == m_jobs.end()) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid request id in SFTP packet.");
+ }
+ return it;
+}
+
+void SftpChannelPrivate::closeHook()
+{
+ createClosedSignal();
+}
+
+void SftpChannelPrivate::handleOpenSuccessInternal()
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("SFTP session started");
+#endif
+ m_sendFacility.sendSftpPacket(remoteChannel());
+ m_sftpState = SubsystemRequested;
+}
+
+void SftpChannelPrivate::handleOpenFailureInternal()
+{
+ if (channelState() != SessionRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
+ }
+ createDelayedInitFailedSignal(SSH_TR("Server could not start session."));
+}
+
+void SftpChannelPrivate::sendReadRequest(const SftpDownload::Ptr &job,
+ quint32 requestId)
+{
+ Q_ASSERT(job->eofId == SftpInvalidJob);
+ sendData(m_outgoingPacket.generateReadFile(job->remoteHandle, job->offset,
+ AbstractSftpPacket::MaxDataSize, requestId).rawData());
+ job->offsets[requestId] = job->offset;
+ job->offset += AbstractSftpPacket::MaxDataSize;
+ if (job->offset >= job->fileSize)
+ job->eofId = requestId;
+}
+
+void SftpChannelPrivate::reportRequestError(const AbstractSftpOperationWithHandle::Ptr &job,
+ const QString &error)
+{
+ createDelayedJobFinishedSignal(job->jobId, error);
+ job->hasError = true;
+}
+
+void SftpChannelPrivate::finishTransferRequest(const JobMap::Iterator &it)
+{
+ AbstractSftpTransfer::Ptr job = it.value().staticCast<AbstractSftpTransfer>();
+ if (job->inFlightCount == 1)
+ sendTransferCloseHandle(job, it.key());
+ else
+ removeTransferRequest(it);
+}
+
+void SftpChannelPrivate::sendTransferCloseHandle(const AbstractSftpTransfer::Ptr &job,
+ quint32 requestId)
+{
+ sendData(m_outgoingPacket.generateCloseHandle(job->remoteHandle,
+ requestId).rawData());
+ job->state = SftpDownload::CloseRequested;
+}
+
+void SftpChannelPrivate::removeTransferRequest(const JobMap::Iterator &it)
+{
+ --it.value().staticCast<AbstractSftpTransfer>()->inFlightCount;
+ m_jobs.erase(it);
+}
+
+void SftpChannelPrivate::sendWriteRequest(const JobMap::Iterator &it)
+{
+ SftpUploadFile::Ptr job = it.value().staticCast<SftpUploadFile>();
+ QByteArray data = job->localFile->read(AbstractSftpPacket::MaxDataSize);
+ if (job->localFile->error() != QFile::NoError) {
+ if (job->parentJob)
+ job->parentJob->setError();
+ reportRequestError(job, SSH_TR("Error reading local file: %1")
+ .arg(job->localFile->errorString()));
+ finishTransferRequest(it);
+ } else if (data.isEmpty()) {
+ finishTransferRequest(it);
+ } else {
+ sendData(m_outgoingPacket.generateWriteFile(job->remoteHandle,
+ job->offset, data, it.key()).rawData());
+ job->offset += AbstractSftpPacket::MaxDataSize;
+ }
+}
+
+void SftpChannelPrivate::spawnWriteRequests(const JobMap::Iterator &it)
+{
+ SftpUploadFile::Ptr op = it.value().staticCast<SftpUploadFile>();
+ op->calculateInFlightCount(AbstractSftpPacket::MaxDataSize);
+ sendWriteRequest(it);
+ for (int i = 1; !op->hasError && i < op->inFlightCount; ++i)
+ sendWriteRequest(m_jobs.insert(++m_nextJobId, op));
+}
+
+void SftpChannelPrivate::spawnReadRequests(const SftpDownload::Ptr &job)
+{
+ job->calculateInFlightCount(AbstractSftpPacket::MaxDataSize);
+ sendReadRequest(job, job->jobId);
+ for (int i = 1; i < job->inFlightCount; ++i) {
+ const quint32 requestId = ++m_nextJobId;
+ m_jobs.insert(requestId, job);
+ sendReadRequest(job, requestId);
+ }
+}
+
+void SftpChannelPrivate::createDelayedInitFailedSignal(const QString &reason)
+{
+ new SftpInitializationFailedSignal(this, QWeakPointer<SftpChannel>(m_sftp),
+ reason);
+}
+
+void SftpChannelPrivate::emitInitializationFailedSignal(const QString &reason)
+{
+ emit m_sftp->initializationFailed(reason);
+}
+
+void SftpChannelPrivate::createDelayedInitializedSignal()
+{
+ new SftpInitializedSignal(this, QWeakPointer<SftpChannel>(m_sftp));
+}
+
+void SftpChannelPrivate::emitInitialized()
+{
+ emit m_sftp->initialized();
+}
+
+void SftpChannelPrivate::createDelayedJobFinishedSignal(SftpJobId jobId,
+ const QString &error)
+{
+ new SftpJobFinishedSignal(this, QWeakPointer<SftpChannel>(m_sftp), jobId, error);
+}
+
+void SftpChannelPrivate::emitJobFinished(SftpJobId jobId, const QString &error)
+{
+ emit m_sftp->finished(jobId, error);
+}
+
+void SftpChannelPrivate::createDelayedDataAvailableSignal(SftpJobId jobId,
+ const QString &data)
+{
+ new SftpDataAvailableSignal(this, QWeakPointer<SftpChannel>(m_sftp), jobId, data);
+}
+
+void SftpChannelPrivate::emitDataAvailable(SftpJobId jobId, const QString &data)
+{
+ emit m_sftp->dataAvailable(jobId, data);
+}
+
+void SftpChannelPrivate::createClosedSignal()
+{
+ new SftpClosedSignal(this, QWeakPointer<SftpChannel>(m_sftp));
+}
+
+void SftpChannelPrivate::emitClosed()
+{
+ emit m_sftp->closed();
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sftpchannel.h b/coreplugin/ssh/sftpchannel.h
new file mode 100644
index 0000000..cbdc072
--- /dev/null
+++ b/coreplugin/ssh/sftpchannel.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTCHANNEL_H
+#define SFTCHANNEL_H
+
+#include "sftpdefs.h"
+#include "sftpincomingpacket_p.h"
+
+#include <coreplugin/core_global.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+namespace Core {
+
+namespace Internal {
+class SftpChannelPrivate;
+class SshChannelManager;
+class SshSendFacility;
+} // namespace Internal
+
+/*
+ * This class provides SFTP operations.
+ * Objects are created via SshConnection::createSftpChannel().
+ * The channel needs to be initialized with
+ * a call to initialize() and is closed via closeChannel(). After closing
+ * a channel, no more operations are possible. It cannot be re-opened
+ * using initialize(); use SshConnection::createSftpChannel() if you need
+ * a new one.
+ * After the initialized() signal has been emitted, operations can be started.
+ * All SFTP operations are asynchronous (non-blocking) and can be in-flight
+ * simultaneously (though callers must ensure that concurrently running jobs
+ * are independent of each other, e.g. they must not write to the same file).
+ * Operations are identified by their job id, which is returned by
+ * the respective member function. If the function can right away detect that
+ * the operation cannot succeed, it returns SftpInvalidJob. If an error occurs
+ * later, the finishedWithError() signal is emitted for the respective job.
+ * Note that directory names must not have a trailing slash.
+ */
+class CORE_EXPORT SftpChannel : public QObject
+{
+ Q_OBJECT
+
+ friend class Internal::SftpChannelPrivate;
+ friend class Internal::SshChannelManager;
+public:
+ typedef QSharedPointer<SftpChannel> Ptr;
+
+ enum State { Uninitialized, Initializing, Initialized, Closing, Closed };
+ State state() const;
+
+ void initialize();
+ void closeChannel();
+
+ SftpJobId listDirectory(const QString &dirPath);
+ SftpJobId createDirectory(const QString &dirPath);
+ SftpJobId removeDirectory(const QString &dirPath);
+ SftpJobId removeFile(const QString &filePath);
+ SftpJobId renameFileOrDirectory(const QString &oldPath,
+ const QString &newPath);
+ SftpJobId createFile(const QString &filePath, SftpOverwriteMode mode);
+ SftpJobId uploadFile(const QString &localFilePath,
+ const QString &remoteFilePath, SftpOverwriteMode mode);
+ SftpJobId downloadFile(const QString &remoteFilePath,
+ const QString &localFilePath, SftpOverwriteMode mode);
+ SftpJobId uploadDir(const QString &localDirPath,
+ const QString &remoteParentDirPath);
+
+ ~SftpChannel();
+
+signals:
+ void initialized();
+ void initializationFailed(const QString &reason);
+ void closed();
+
+ // error.isEmpty <=> finished successfully
+ void finished(Core::SftpJobId job, const QString &error = QString());
+
+ /*
+ * This signal is only emitted by the "List Directory" operation,
+ * one file at a time.
+ */
+ void dataAvailable(SftpJobId job, const QString &data);
+
+private:
+ SftpChannel(quint32 channelId, Internal::SshSendFacility &sendFacility);
+
+ Internal::SftpChannelPrivate *d;
+};
+
+} // namespace Core
+
+#endif // SFTPCHANNEL_H
diff --git a/coreplugin/ssh/sftpchannel_p.h b/coreplugin/ssh/sftpchannel_p.h
new file mode 100644
index 0000000..ec9c0fc
--- /dev/null
+++ b/coreplugin/ssh/sftpchannel_p.h
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTCHANNEL_P_H
+#define SFTCHANNEL_P_H
+
+#include "sftpdefs.h"
+#include "sftpincomingpacket_p.h"
+#include "sftpoperation_p.h"
+#include "sftpoutgoingpacket_p.h"
+#include "sshchannel_p.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QMap>
+
+namespace Core {
+class SftpChannel;
+namespace Internal {
+
+class SftpChannelPrivate : public AbstractSshChannel
+{
+ friend class Core::SftpChannel;
+public:
+
+ enum SftpState { Inactive, SubsystemRequested, InitSent, Initialized };
+
+ virtual void handleChannelSuccess();
+ virtual void handleChannelFailure();
+
+ virtual void closeHook();
+
+ void emitInitializationFailedSignal(const QString &reason);
+ void emitInitialized();
+ void emitJobFinished(SftpJobId jobId, const QString &error);
+ void emitDataAvailable(SftpJobId jobId, const QString &data);
+ void emitClosed();
+
+private:
+ typedef QMap<SftpJobId, AbstractSftpOperation::Ptr> JobMap;
+
+ SftpChannelPrivate(quint32 channelId, SshSendFacility &sendFacility,
+ SftpChannel *sftp);
+ SftpJobId createJob(const AbstractSftpOperation::Ptr &job);
+
+ virtual void handleOpenSuccessInternal();
+ virtual void handleOpenFailureInternal();
+ virtual void handleChannelDataInternal(const QByteArray &data);
+ virtual void handleChannelExtendedDataInternal(quint32 type,
+ const QByteArray &data);
+
+ void handleCurrentPacket();
+ void handleServerVersion();
+ void handleHandle();
+ void handleStatus();
+ void handleName();
+ void handleReadData();
+ void handleAttrs();
+
+ void handleStatusGeneric(const JobMap::Iterator &it,
+ const SftpStatusResponse &response);
+ void handleMkdirStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response);
+ void handleLsStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response);
+ void handleGetStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response);
+ void handlePutStatus(const JobMap::Iterator &it,
+ const SftpStatusResponse &response);
+
+ void handleLsHandle(const JobMap::Iterator &it);
+ void handleCreateFileHandle(const JobMap::Iterator &it);
+ void handleGetHandle(const JobMap::Iterator &it);
+ void handlePutHandle(const JobMap::Iterator &it);
+
+ void spawnReadRequests(const SftpDownload::Ptr &job);
+ void spawnWriteRequests(const JobMap::Iterator &it);
+ void sendReadRequest(const SftpDownload::Ptr &job, quint32 requestId);
+ void sendWriteRequest(const JobMap::Iterator &it);
+ void finishTransferRequest(const JobMap::Iterator &it);
+ void removeTransferRequest(const JobMap::Iterator &it);
+ void reportRequestError(const AbstractSftpOperationWithHandle::Ptr &job,
+ const QString &error);
+ void sendTransferCloseHandle(const AbstractSftpTransfer::Ptr &job,
+ quint32 requestId);
+
+ void createDelayedInitFailedSignal(const QString &reason);
+ void createDelayedInitializedSignal();
+ void createDelayedJobFinishedSignal(SftpJobId jobId,
+ const QString &error = QString());
+ void createDelayedDataAvailableSignal(SftpJobId jobId, const QString &data);
+ void createClosedSignal();
+
+ JobMap::Iterator lookupJob(SftpJobId id);
+ JobMap m_jobs;
+ SftpOutgoingPacket m_outgoingPacket;
+ SftpIncomingPacket m_incomingPacket;
+ QByteArray m_incomingData;
+ SftpJobId m_nextJobId;
+ SftpState m_sftpState;
+ SftpChannel *m_sftp;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SFTPCHANNEL_P_H
diff --git a/coreplugin/ssh/sftpdefs.cpp b/coreplugin/ssh/sftpdefs.cpp
new file mode 100644
index 0000000..6a2f6de
--- /dev/null
+++ b/coreplugin/ssh/sftpdefs.cpp
@@ -0,0 +1,32 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftpdefs.h"
+
+namespace Core { const SftpJobId SftpInvalidJob = 0; }
diff --git a/coreplugin/ssh/sftpdefs.h b/coreplugin/ssh/sftpdefs.h
new file mode 100644
index 0000000..5f59582
--- /dev/null
+++ b/coreplugin/ssh/sftpdefs.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTPDEFS_H
+#define SFTPDEFS_H
+
+#include <coreplugin/core_global.h>
+
+#include <QtCore/QtGlobal>
+
+namespace Core {
+
+typedef quint32 SftpJobId;
+CORE_EXPORT extern const SftpJobId SftpInvalidJob;
+
+enum SftpOverwriteMode {
+ SftpOverwriteExisting, SftpAppendToExisting, SftpSkipExisting
+};
+
+} // namespace Core
+
+#endif // SFTPDEFS_H
diff --git a/coreplugin/ssh/sftpincomingpacket.cpp b/coreplugin/ssh/sftpincomingpacket.cpp
new file mode 100644
index 0000000..804bdb2
--- /dev/null
+++ b/coreplugin/ssh/sftpincomingpacket.cpp
@@ -0,0 +1,230 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftpincomingpacket_p.h"
+
+#include "sshexception_p.h"
+#include "sshpacketparser_p.h"
+
+namespace Core {
+namespace Internal {
+
+namespace {
+ const int SSH_FILEXFER_ATTR_SIZE = 0x00000001;
+ const int SSH_FILEXFER_ATTR_UIDGID = 0x00000002;
+ const int SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004;
+ const int SSH_FILEXFER_ATTR_ACMODTIME = 0x00000008;
+ const int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000;
+} // anonymous namespace
+
+SftpIncomingPacket::SftpIncomingPacket() : m_length(0)
+{
+}
+
+void SftpIncomingPacket::consumeData(QByteArray &newData)
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("%s: current data size = %d, new data size = %d", Q_FUNC_INFO,
+ m_data.size(), newData.size());
+#endif
+
+ if (isComplete() || dataSize() + newData.size() < sizeof m_length)
+ return;
+
+ if (dataSize() < sizeof m_length) {
+ moveFirstBytes(m_data, newData, sizeof m_length - m_data.size());
+ m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
+ if (m_length < static_cast<quint32>(TypeOffset + 1)
+ || m_length > MaxPacketSize) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid length field in SFTP packet.");
+ }
+ }
+
+ moveFirstBytes(m_data, newData,
+ qMin<quint32>(m_length - dataSize() + 4, newData.size()));
+}
+
+void SftpIncomingPacket::moveFirstBytes(QByteArray &target, QByteArray &source,
+ int n)
+{
+ target.append(source.left(n));
+ source.remove(0, n);
+}
+
+bool SftpIncomingPacket::isComplete() const
+{
+ return m_length == dataSize() - 4;
+}
+
+void SftpIncomingPacket::clear()
+{
+ m_data.clear();
+ m_length = 0;
+}
+
+quint32 SftpIncomingPacket::extractServerVersion() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_VERSION);
+ try {
+ return SshPacketParser::asUint32(m_data, TypeOffset + 1);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_VERSION packet.");
+ }
+}
+
+SftpHandleResponse SftpIncomingPacket::asHandleResponse() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_HANDLE);
+ try {
+ SftpHandleResponse response;
+ quint32 offset = RequestIdOffset;
+ response.requestId = SshPacketParser::asUint32(m_data, &offset);
+ response.handle = SshPacketParser::asString(m_data, &offset);
+ return response;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_HANDLE packet");
+ }
+}
+
+SftpStatusResponse SftpIncomingPacket::asStatusResponse() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_STATUS);
+ try {
+ SftpStatusResponse response;
+ quint32 offset = RequestIdOffset;
+ response.requestId = SshPacketParser::asUint32(m_data, &offset);
+ response.status = static_cast<SftpStatusCode>(SshPacketParser::asUint32(m_data, &offset));
+ response.errorString = SshPacketParser::asUserString(m_data, &offset);
+ response.language = SshPacketParser::asString(m_data, &offset);
+ return response;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_STATUS packet.");
+ }
+}
+
+SftpNameResponse SftpIncomingPacket::asNameResponse() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_NAME);
+ try {
+ SftpNameResponse response;
+ quint32 offset = RequestIdOffset;
+ response.requestId = SshPacketParser::asUint32(m_data, &offset);
+ const quint32 count = SshPacketParser::asUint32(m_data, &offset);
+ for (quint32 i = 0; i < count; ++i)
+ response.files << asFile(offset);
+ return response;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_NAME packet.");
+ }
+}
+
+SftpDataResponse SftpIncomingPacket::asDataResponse() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_DATA);
+ try {
+ SftpDataResponse response;
+ quint32 offset = RequestIdOffset;
+ response.requestId = SshPacketParser::asUint32(m_data, &offset);
+ response.data = SshPacketParser::asString(m_data, &offset);
+ return response;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_DATA packet.");
+ }
+}
+
+SftpAttrsResponse SftpIncomingPacket::asAttrsResponse() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_FXP_ATTRS);
+ try {
+ SftpAttrsResponse response;
+ quint32 offset = RequestIdOffset;
+ response.requestId = SshPacketParser::asUint32(m_data, &offset);
+ response.attrs = asFileAttributes(offset);
+ return response;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_FXP_ATTRS packet.");
+ }
+}
+
+SftpFile SftpIncomingPacket::asFile(quint32 &offset) const
+{
+ SftpFile file;
+ file.fileName
+ = QString::fromUtf8(SshPacketParser::asString(m_data, &offset));
+ file.longName
+ = QString::fromUtf8(SshPacketParser::asString(m_data, &offset));
+ file.attributes = asFileAttributes(offset);
+ return file;
+}
+
+SftpFileAttributes SftpIncomingPacket::asFileAttributes(quint32 &offset) const
+{
+ SftpFileAttributes attributes;
+ const quint32 flags = SshPacketParser::asUint32(m_data, &offset);
+ attributes.sizePresent = flags & SSH_FILEXFER_ATTR_SIZE;
+ attributes.timesPresent = flags & SSH_FILEXFER_ATTR_ACMODTIME;
+ attributes.uidAndGidPresent = flags & SSH_FILEXFER_ATTR_UIDGID;
+ attributes.permissionsPresent = flags & SSH_FILEXFER_ATTR_PERMISSIONS;
+ if (attributes.sizePresent)
+ attributes.size = SshPacketParser::asUint64(m_data, &offset);
+ if (attributes.uidAndGidPresent) {
+ attributes.uid = SshPacketParser::asUint32(m_data, &offset);
+ attributes.gid = SshPacketParser::asUint32(m_data, &offset);
+ }
+ if (attributes.permissionsPresent)
+ attributes.permissions = SshPacketParser::asUint32(m_data, &offset);
+ if (attributes.timesPresent) {
+ attributes.atime = SshPacketParser::asUint32(m_data, &offset);
+ attributes.mtime = SshPacketParser::asUint32(m_data, &offset);
+ }
+ if (flags & SSH_FILEXFER_ATTR_EXTENDED) {
+ const quint32 count = SshPacketParser::asUint32(m_data, &offset);
+ for (quint32 i = 0; i < count; ++i) {
+ SshPacketParser::asString(m_data, &offset);
+ SshPacketParser::asString(m_data, &offset);
+ }
+ }
+ return attributes;
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sftpincomingpacket_p.h b/coreplugin/ssh/sftpincomingpacket_p.h
new file mode 100644
index 0000000..5a5b8d4
--- /dev/null
+++ b/coreplugin/ssh/sftpincomingpacket_p.h
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTPINCOMINGPACKET_P_H
+#define SFTPINCOMINGPACKET_P_H
+
+#include "sftppacket_p.h"
+
+namespace Core {
+namespace Internal {
+
+struct SftpHandleResponse {
+ quint32 requestId;
+ QByteArray handle;
+};
+
+struct SftpStatusResponse {
+ quint32 requestId;
+ SftpStatusCode status;
+ QString errorString;
+ QByteArray language;
+};
+
+struct SftpFileAttributes {
+ bool sizePresent;
+ bool timesPresent;
+ bool uidAndGidPresent;
+ bool permissionsPresent;
+ quint64 size;
+ quint32 uid;
+ quint32 gid;
+ quint32 permissions;
+ quint32 atime;
+ quint32 mtime;
+};
+
+struct SftpFile {
+ QString fileName;
+ QString longName; // Not present in later RFCs, so we don't expose this to the user.
+ SftpFileAttributes attributes;
+};
+
+struct SftpNameResponse {
+ quint32 requestId;
+ QList<SftpFile> files;
+};
+
+struct SftpDataResponse {
+ quint32 requestId;
+ QByteArray data;
+};
+
+struct SftpAttrsResponse {
+ quint32 requestId;
+ SftpFileAttributes attrs;
+};
+
+class SftpIncomingPacket : public AbstractSftpPacket
+{
+public:
+ SftpIncomingPacket();
+
+ void consumeData(QByteArray &data);
+ void clear();
+ bool isComplete() const;
+ quint32 extractServerVersion() const;
+ SftpHandleResponse asHandleResponse() const;
+ SftpStatusResponse asStatusResponse() const;
+ SftpNameResponse asNameResponse() const;
+ SftpDataResponse asDataResponse() const;
+ SftpAttrsResponse asAttrsResponse() const;
+
+private:
+ void moveFirstBytes(QByteArray &target, QByteArray &source, int n);
+
+ SftpFileAttributes asFileAttributes(quint32 &offset) const;
+ SftpFile asFile(quint32 &offset) const;
+
+ quint32 m_length;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SFTPINCOMINGPACKET_P_H
diff --git a/coreplugin/ssh/sftpoperation.cpp b/coreplugin/ssh/sftpoperation.cpp
new file mode 100644
index 0000000..0acdd1d
--- /dev/null
+++ b/coreplugin/ssh/sftpoperation.cpp
@@ -0,0 +1,183 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftpoperation_p.h"
+
+#include "sftpoutgoingpacket_p.h"
+
+#include <QtCore/QFile>
+
+namespace Core {
+namespace Internal {
+
+AbstractSftpOperation::AbstractSftpOperation(SftpJobId jobId) : jobId(jobId)
+{
+}
+
+AbstractSftpOperation::~AbstractSftpOperation() { }
+
+
+SftpMakeDir::SftpMakeDir(SftpJobId jobId, const QString &path,
+ const SftpUploadDir::Ptr &parentJob)
+ : AbstractSftpOperation(jobId), parentJob(parentJob), remoteDir(path)
+{
+}
+
+SftpOutgoingPacket &SftpMakeDir::initialPacket(SftpOutgoingPacket &packet)
+{
+ return packet.generateMkDir(remoteDir, jobId);
+}
+
+
+SftpRmDir::SftpRmDir(SftpJobId, const QString &path)
+ : AbstractSftpOperation(jobId), remoteDir(path)
+{
+}
+
+SftpOutgoingPacket &SftpRmDir::initialPacket(SftpOutgoingPacket &packet)
+{
+ return packet.generateRmDir(remoteDir, jobId);
+}
+
+
+SftpRm::SftpRm(SftpJobId jobId, const QString &path)
+ : AbstractSftpOperation(jobId), remoteFile(path) {}
+
+SftpOutgoingPacket &SftpRm::initialPacket(SftpOutgoingPacket &packet)
+{
+ return packet.generateRm(remoteFile, jobId);
+}
+
+
+SftpRename::SftpRename(SftpJobId jobId, const QString &oldPath,
+ const QString &newPath)
+ : AbstractSftpOperation(jobId), oldPath(oldPath), newPath(newPath)
+{
+}
+
+SftpOutgoingPacket &SftpRename::initialPacket(SftpOutgoingPacket &packet)
+{
+ return packet.generateRename(oldPath, newPath, jobId);
+}
+
+
+AbstractSftpOperationWithHandle::AbstractSftpOperationWithHandle(SftpJobId jobId,
+ const QString &remotePath)
+ : AbstractSftpOperation(jobId),
+ remotePath(remotePath), state(Inactive), hasError(false)
+{
+}
+
+AbstractSftpOperationWithHandle::~AbstractSftpOperationWithHandle() { }
+
+
+SftpListDir::SftpListDir(SftpJobId jobId, const QString &path)
+ : AbstractSftpOperationWithHandle(jobId, path)
+{
+}
+
+SftpOutgoingPacket &SftpListDir::initialPacket(SftpOutgoingPacket &packet)
+{
+ state = OpenRequested;
+ return packet.generateOpenDir(remotePath, jobId);
+}
+
+
+SftpCreateFile::SftpCreateFile(SftpJobId jobId, const QString &path,
+ SftpOverwriteMode mode)
+ : AbstractSftpOperationWithHandle(jobId, path), mode(mode)
+{
+}
+
+SftpOutgoingPacket & SftpCreateFile::initialPacket(SftpOutgoingPacket &packet)
+{
+ state = OpenRequested;
+ return packet.generateOpenFileForWriting(remotePath, mode, jobId);
+}
+
+
+const int AbstractSftpTransfer::MaxInFlightCount = 10; // Experimentally found to be enough.
+
+AbstractSftpTransfer::AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile)
+ : AbstractSftpOperationWithHandle(jobId, remotePath),
+ localFile(localFile), fileSize(0), offset(0), inFlightCount(0),
+ statRequested(false)
+{
+}
+
+AbstractSftpTransfer::~AbstractSftpTransfer() {}
+
+void AbstractSftpTransfer::calculateInFlightCount(quint32 chunkSize)
+{
+ if (fileSize == 0) {
+ inFlightCount = 1;
+ } else {
+ inFlightCount = fileSize / chunkSize;
+ if (fileSize % chunkSize)
+ ++inFlightCount;
+ if (inFlightCount > MaxInFlightCount)
+ inFlightCount = MaxInFlightCount;
+ }
+}
+
+
+SftpDownload::SftpDownload(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile)
+ : AbstractSftpTransfer(jobId, remotePath, localFile), eofId(SftpInvalidJob)
+{
+}
+
+SftpOutgoingPacket &SftpDownload::initialPacket(SftpOutgoingPacket &packet)
+{
+ state = OpenRequested;
+ return packet.generateOpenFileForReading(remotePath, jobId);
+}
+
+
+SftpUploadFile::SftpUploadFile(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile, SftpOverwriteMode mode,
+ const SftpUploadDir::Ptr &parentJob)
+ : AbstractSftpTransfer(jobId, remotePath, localFile),
+ parentJob(parentJob), mode(mode)
+{
+ fileSize = localFile->size();
+}
+
+SftpOutgoingPacket &SftpUploadFile::initialPacket(SftpOutgoingPacket &packet)
+{
+ state = OpenRequested;
+ return packet.generateOpenFileForWriting(remotePath, mode, jobId);
+}
+
+
+SftpUploadDir::~SftpUploadDir() {}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sftpoperation_p.h b/coreplugin/ssh/sftpoperation_p.h
new file mode 100644
index 0000000..c64d081
--- /dev/null
+++ b/coreplugin/ssh/sftpoperation_p.h
@@ -0,0 +1,228 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTPOPERATION_P_H
+#define SFTPOPERATION_P_H
+
+#include "sftpdefs.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QFile;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Internal {
+
+class SftpOutgoingPacket;
+
+struct AbstractSftpOperation
+{
+ typedef QSharedPointer<AbstractSftpOperation> Ptr;
+ enum Type {
+ ListDir, MakeDir, RmDir, Rm, Rename, CreateFile, Download, UploadFile
+ };
+
+ AbstractSftpOperation(SftpJobId jobId);
+ virtual ~AbstractSftpOperation();
+ virtual Type type() const=0;
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet)=0;
+
+ const SftpJobId jobId;
+
+private:
+ AbstractSftpOperation(const AbstractSftpOperation &);
+ AbstractSftpOperation &operator=(const AbstractSftpOperation &);
+};
+
+class SftpUploadDir;
+
+struct SftpMakeDir : public AbstractSftpOperation
+{
+ typedef QSharedPointer<SftpMakeDir> Ptr;
+
+ SftpMakeDir(SftpJobId jobId, const QString &path,
+ const QSharedPointer<SftpUploadDir> &parentJob = QSharedPointer<SftpUploadDir>());
+ virtual Type type() const { return MakeDir; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const QSharedPointer<SftpUploadDir> parentJob;
+ const QString remoteDir;
+};
+
+struct SftpRmDir : public AbstractSftpOperation
+{
+ typedef QSharedPointer<SftpRmDir> Ptr;
+
+ SftpRmDir(SftpJobId jobId, const QString &path);
+ virtual Type type() const { return RmDir; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const QString remoteDir;
+};
+
+struct SftpRm : public AbstractSftpOperation
+{
+ typedef QSharedPointer<SftpRm> Ptr;
+
+ SftpRm(SftpJobId jobId, const QString &path);
+ virtual Type type() const { return Rm; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const QString remoteFile;
+};
+
+struct SftpRename : public AbstractSftpOperation
+{
+ typedef QSharedPointer<SftpRename> Ptr;
+
+ SftpRename(SftpJobId jobId, const QString &oldPath, const QString &newPath);
+ virtual Type type() const { return Rename; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const QString oldPath;
+ const QString newPath;
+};
+
+
+struct AbstractSftpOperationWithHandle : public AbstractSftpOperation
+{
+ typedef QSharedPointer<AbstractSftpOperationWithHandle> Ptr;
+ enum State { Inactive, OpenRequested, Open, CloseRequested };
+
+ AbstractSftpOperationWithHandle(SftpJobId jobId, const QString &remotePath);
+ ~AbstractSftpOperationWithHandle();
+
+ const QString remotePath;
+ QByteArray remoteHandle;
+ State state;
+ bool hasError;
+};
+
+
+struct SftpListDir : public AbstractSftpOperationWithHandle
+{
+ typedef QSharedPointer<SftpListDir> Ptr;
+
+ SftpListDir(SftpJobId jobId, const QString &path);
+ virtual Type type() const { return ListDir; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+};
+
+
+struct SftpCreateFile : public AbstractSftpOperationWithHandle
+{
+ typedef QSharedPointer<SftpCreateFile> Ptr;
+
+ SftpCreateFile(SftpJobId jobId, const QString &path, SftpOverwriteMode mode);
+ virtual Type type() const { return CreateFile; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const SftpOverwriteMode mode;
+};
+
+struct AbstractSftpTransfer : public AbstractSftpOperationWithHandle
+{
+ typedef QSharedPointer<AbstractSftpTransfer> Ptr;
+
+ AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile);
+ ~AbstractSftpTransfer();
+ void calculateInFlightCount(quint32 chunkSize);
+
+ static const int MaxInFlightCount;
+
+ const QSharedPointer<QFile> localFile;
+ quint64 fileSize;
+ quint64 offset;
+ int inFlightCount;
+ bool statRequested;
+};
+
+struct SftpDownload : public AbstractSftpTransfer
+{
+ typedef QSharedPointer<SftpDownload> Ptr;
+ SftpDownload(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile);
+ virtual Type type() const { return Download; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ QMap<quint32, quint32> offsets;
+ SftpJobId eofId;
+};
+
+struct SftpUploadFile : public AbstractSftpTransfer
+{
+ typedef QSharedPointer<SftpUploadFile> Ptr;
+
+ SftpUploadFile(SftpJobId jobId, const QString &remotePath,
+ const QSharedPointer<QFile> &localFile, SftpOverwriteMode mode,
+ const QSharedPointer<SftpUploadDir> &parentJob = QSharedPointer<SftpUploadDir>());
+ virtual Type type() const { return UploadFile; }
+ virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
+
+ const QSharedPointer<SftpUploadDir> parentJob;
+ SftpOverwriteMode mode;
+};
+
+// Composite operation.
+struct SftpUploadDir
+{
+ typedef QSharedPointer<SftpUploadDir> Ptr;
+
+ struct Dir {
+ Dir(const QString &l, const QString &r) : localDir(l), remoteDir(r) {}
+ QString localDir;
+ QString remoteDir;
+ };
+
+ SftpUploadDir(SftpJobId jobId) : jobId(jobId), hasError(false) {}
+ ~SftpUploadDir();
+
+ void setError()
+ {
+ hasError = true;
+ uploadsInProgress.clear();
+ mkdirsInProgress.clear();
+ }
+
+ const SftpJobId jobId;
+ bool hasError;
+ QList<SftpUploadFile::Ptr> uploadsInProgress;
+ QMap<SftpMakeDir::Ptr, Dir> mkdirsInProgress;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SFTPOPERATION_P_H
diff --git a/coreplugin/ssh/sftpoutgoingpacket.cpp b/coreplugin/ssh/sftpoutgoingpacket.cpp
new file mode 100644
index 0000000..57fd854
--- /dev/null
+++ b/coreplugin/ssh/sftpoutgoingpacket.cpp
@@ -0,0 +1,202 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftpoutgoingpacket_p.h"
+
+#include "sshpacket_p.h"
+
+#include <QtCore/QtEndian>
+
+namespace Core {
+namespace Internal {
+
+namespace {
+ const quint32 DefaultAttributes = 0;
+ const quint32 SSH_FXF_READ = 0x00000001;
+ const quint32 SSH_FXF_WRITE = 0x00000002;
+ const quint32 SSH_FXF_APPEND = 0x00000004;
+ const quint32 SSH_FXF_CREAT = 0x00000008;
+ const quint32 SSH_FXF_TRUNC = 0x00000010;
+ const quint32 SSH_FXF_EXCL = 0x00000020;
+}
+
+SftpOutgoingPacket::SftpOutgoingPacket()
+{
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateInit(quint32 version)
+{
+ return init(SSH_FXP_INIT, 0).appendInt(version).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateOpenDir(const QString &path,
+ quint32 requestId)
+{
+ return init(SSH_FXP_OPENDIR, requestId).appendString(path).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateReadDir(const QByteArray &handle,
+ quint32 requestId)
+{
+ return init(SSH_FXP_READDIR, requestId).appendString(handle).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateCloseHandle(const QByteArray &handle,
+ quint32 requestId)
+{
+ return init(SSH_FXP_CLOSE, requestId).appendString(handle).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateMkDir(const QString &path,
+ quint32 requestId)
+{
+ return init(SSH_FXP_MKDIR, requestId).appendString(path)
+ .appendInt(DefaultAttributes).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateRmDir(const QString &path,
+ quint32 requestId)
+{
+ return init(SSH_FXP_RMDIR, requestId).appendString(path).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateRm(const QString &path,
+ quint32 requestId)
+{
+ return init(SSH_FXP_REMOVE, requestId).appendString(path).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateRename(const QString &oldPath,
+ const QString &newPath, quint32 requestId)
+{
+ return init(SSH_FXP_RENAME, requestId).appendString(oldPath)
+ .appendString(newPath).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFileForWriting(const QString &path,
+ SftpOverwriteMode mode, quint32 requestId)
+{
+ return generateOpenFile(path, Write, mode, requestId);
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFileForReading(const QString &path,
+ quint32 requestId)
+{
+ // Note: Overwrite mode is irrelevant and will be ignored.
+ return generateOpenFile(path, Read, SftpSkipExisting, requestId);
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateReadFile(const QByteArray &handle,
+ quint64 offset, quint32 length, quint32 requestId)
+{
+ return init(SSH_FXP_READ, requestId).appendString(handle).appendInt64(offset)
+ .appendInt(length).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateFstat(const QByteArray &handle,
+ quint32 requestId)
+{
+ return init(SSH_FXP_FSTAT, requestId).appendString(handle).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateWriteFile(const QByteArray &handle,
+ quint64 offset, const QByteArray &data, quint32 requestId)
+{
+ return init(SSH_FXP_WRITE, requestId).appendString(handle)
+ .appendInt64(offset).appendString(data).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFile(const QString &path,
+ OpenType openType, SftpOverwriteMode mode, quint32 requestId)
+{
+ quint32 pFlags;
+ switch (openType) {
+ case Read:
+ pFlags = SSH_FXF_READ;
+ break;
+ case Write:
+ pFlags = SSH_FXF_WRITE | SSH_FXF_CREAT;
+ switch (mode) {
+ case SftpOverwriteExisting: pFlags |= SSH_FXF_TRUNC; break;
+ case SftpAppendToExisting: pFlags |= SSH_FXF_APPEND; break;
+ case SftpSkipExisting: pFlags |= SSH_FXF_EXCL; break;
+ }
+ break;
+ }
+ return init(SSH_FXP_OPEN, requestId).appendString(path).appendInt(pFlags)
+ .appendInt(DefaultAttributes).finalize();
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::init(SftpPacketType type,
+ quint32 requestId)
+{
+ m_data.resize(TypeOffset + 1);
+ m_data[TypeOffset] = type;
+ if (type != SSH_FXP_INIT) {
+ appendInt(requestId);
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Generating SFTP packet of type %d with request id %u", type,
+ requestId);
+#endif
+ }
+ return *this;
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::appendInt(quint32 val)
+{
+ m_data.append(AbstractSshPacket::encodeInt(val));
+ return *this;
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::appendInt64(quint64 value)
+{
+ m_data.append(AbstractSshPacket::encodeInt(value));
+ return *this;
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::appendString(const QString &string)
+{
+ m_data.append(AbstractSshPacket::encodeString(string.toUtf8()));
+ return *this;
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::appendString(const QByteArray &string)
+{
+ m_data += AbstractSshPacket::encodeString(string);
+ return *this;
+}
+
+SftpOutgoingPacket &SftpOutgoingPacket::finalize()
+{
+ AbstractSshPacket::setLengthField(m_data);
+ return *this;
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sftpoutgoingpacket_p.h b/coreplugin/ssh/sftpoutgoingpacket_p.h
new file mode 100644
index 0000000..4f456e8
--- /dev/null
+++ b/coreplugin/ssh/sftpoutgoingpacket_p.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTPOUTGOINGPACKET_P_H
+#define SFTPOUTGOINGPACKET_P_H
+
+#include "sftppacket_p.h"
+#include "sftpdefs.h"
+
+namespace Core {
+namespace Internal {
+
+class SftpOutgoingPacket : public AbstractSftpPacket
+{
+public:
+ SftpOutgoingPacket();
+ SftpOutgoingPacket &generateInit(quint32 version);
+ SftpOutgoingPacket &generateOpenDir(const QString &path, quint32 requestId);
+ SftpOutgoingPacket &generateReadDir(const QByteArray &handle,
+ quint32 requestId);
+ SftpOutgoingPacket &generateCloseHandle(const QByteArray &handle,
+ quint32 requestId);
+ SftpOutgoingPacket &generateMkDir(const QString &path, quint32 requestId);
+ SftpOutgoingPacket &generateRmDir(const QString &path, quint32 requestId);
+ SftpOutgoingPacket &generateRm(const QString &path, quint32 requestId);
+ SftpOutgoingPacket &generateRename(const QString &oldPath,
+ const QString &newPath, quint32 requestId);
+ SftpOutgoingPacket &generateOpenFileForWriting(const QString &path,
+ SftpOverwriteMode mode, quint32 requestId);
+ SftpOutgoingPacket &generateOpenFileForReading(const QString &path,
+ quint32 requestId);
+ SftpOutgoingPacket &generateReadFile(const QByteArray &handle,
+ quint64 offset, quint32 length, quint32 requestId);
+ SftpOutgoingPacket &generateFstat(const QByteArray &handle,
+ quint32 requestId);
+ SftpOutgoingPacket &generateWriteFile(const QByteArray &handle,
+ quint64 offset, const QByteArray &data, quint32 requestId);
+
+private:
+ static QByteArray encodeString(const QString &string);
+
+ enum OpenType { Read, Write };
+ SftpOutgoingPacket &generateOpenFile(const QString &path, OpenType openType,
+ SftpOverwriteMode mode, quint32 requestId);
+
+ SftpOutgoingPacket &init(SftpPacketType type, quint32 requestId);
+ SftpOutgoingPacket &appendInt(quint32 value);
+ SftpOutgoingPacket &appendInt64(quint64 value);
+ SftpOutgoingPacket &appendString(const QString &string);
+ SftpOutgoingPacket &appendString(const QByteArray &string);
+ SftpOutgoingPacket &finalize();
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SFTPOUTGOINGPACKET_P_H
diff --git a/coreplugin/ssh/sftppacket.cpp b/coreplugin/ssh/sftppacket.cpp
new file mode 100644
index 0000000..0064bf3
--- /dev/null
+++ b/coreplugin/ssh/sftppacket.cpp
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sftppacket_p.h"
+
+#include "sshpacketparser_p.h"
+
+namespace Core {
+namespace Internal {
+
+const quint32 AbstractSftpPacket::MaxDataSize = 32768;
+const quint32 AbstractSftpPacket::MaxPacketSize = 34000;
+const int AbstractSftpPacket::TypeOffset = 4;
+const int AbstractSftpPacket::RequestIdOffset = TypeOffset + 1;
+const int AbstractSftpPacket::PayloadOffset = RequestIdOffset + 4;
+
+
+AbstractSftpPacket::AbstractSftpPacket()
+{
+}
+
+quint32 AbstractSftpPacket::requestId() const
+{
+ return SshPacketParser::asUint32(m_data, RequestIdOffset);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sftppacket_p.h b/coreplugin/ssh/sftppacket_p.h
new file mode 100644
index 0000000..aae1a15
--- /dev/null
+++ b/coreplugin/ssh/sftppacket_p.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SFTPPACKET_P_H
+#define SFTPPACKET_P_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+enum SftpPacketType {
+ SSH_FXP_INIT = 1,
+ SSH_FXP_VERSION = 2,
+ SSH_FXP_OPEN = 3,
+ SSH_FXP_CLOSE = 4,
+ SSH_FXP_READ = 5,
+ SSH_FXP_WRITE = 6,
+ SSH_FXP_LSTAT = 7,
+ SSH_FXP_FSTAT = 8,
+ SSH_FXP_SETSTAT = 9,
+ SSH_FXP_FSETSTAT = 10,
+ SSH_FXP_OPENDIR = 11,
+ SSH_FXP_READDIR = 12,
+ SSH_FXP_REMOVE = 13,
+ SSH_FXP_MKDIR = 14,
+ SSH_FXP_RMDIR = 15,
+ SSH_FXP_REALPATH = 16,
+ SSH_FXP_STAT = 17,
+ SSH_FXP_RENAME = 18,
+ SSH_FXP_READLINK = 19,
+ SSH_FXP_SYMLINK = 20, // Removed from later protocol versions. Try not to use.
+
+ SSH_FXP_STATUS = 101,
+ SSH_FXP_HANDLE = 102,
+ SSH_FXP_DATA = 103,
+ SSH_FXP_NAME = 104,
+ SSH_FXP_ATTRS = 105,
+
+ SSH_FXP_EXTENDED = 200,
+ SSH_FXP_EXTENDED_REPLY = 201
+};
+
+enum SftpStatusCode {
+ SSH_FX_OK = 0,
+ SSH_FX_EOF = 1,
+ SSH_FX_NO_SUCH_FILE = 2,
+ SSH_FX_PERMISSION_DENIED = 3,
+ SSH_FX_FAILURE = 4,
+ SSH_FX_BAD_MESSAGE = 5,
+ SSH_FX_NO_CONNECTION = 6,
+ SSH_FX_CONNECTION_LOST = 7,
+ SSH_FX_OP_UNSUPPORTED = 8
+};
+
+class AbstractSftpPacket
+{
+public:
+ AbstractSftpPacket();
+ quint32 requestId() const;
+ const QByteArray &rawData() const { return m_data; }
+ SftpPacketType type() const { return static_cast<SftpPacketType>(m_data.at(TypeOffset)); }
+
+ static const quint32 MaxDataSize; // "Pure" data size per read/writepacket.
+ static const quint32 MaxPacketSize;
+
+protected:
+ quint32 dataSize() const { return static_cast<quint32>(m_data.size()); }
+
+ static const int TypeOffset;
+ static const int RequestIdOffset;
+ static const int PayloadOffset;
+
+ QByteArray m_data;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SFTPPACKET_P_H
diff --git a/coreplugin/ssh/sshbotanconversions_p.h b/coreplugin/ssh/sshbotanconversions_p.h
new file mode 100644
index 0000000..0582977
--- /dev/null
+++ b/coreplugin/ssh/sshbotanconversions_p.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BYTEARRAYCONVERSIONS_P_H
+#define BYTEARRAYCONVERSIONS_P_H
+
+#include "sshcapabilities_p.h"
+
+#include <botan/rng.h>
+#include <botan/secmem.h>
+
+namespace Core {
+namespace Internal {
+
+inline const Botan::byte *convertByteArray(const QByteArray &a)
+{
+ return reinterpret_cast<const Botan::byte *>(a.constData());
+}
+
+inline Botan::byte *convertByteArray(QByteArray &a)
+{
+ return reinterpret_cast<Botan::byte *>(a.data());
+}
+
+inline QByteArray convertByteArray(const Botan::SecureVector<Botan::byte> &v)
+{
+ return QByteArray(reinterpret_cast<const char *>(v.begin()), v.size());
+}
+
+inline const char *botanKeyExchangeAlgoName(const QByteArray &rfcAlgoName)
+{
+ Q_ASSERT(rfcAlgoName == SshCapabilities::DiffieHellmanGroup1Sha1
+ || rfcAlgoName == SshCapabilities::DiffieHellmanGroup14Sha1);
+ return rfcAlgoName == SshCapabilities::DiffieHellmanGroup1Sha1
+ ? "modp/ietf/1024" : "modp/ietf/2048";
+}
+
+inline const char *botanCryptAlgoName(const QByteArray &rfcAlgoName)
+{
+ Q_ASSERT(rfcAlgoName == SshCapabilities::CryptAlgo3Des
+ || rfcAlgoName == SshCapabilities::CryptAlgoAes128);
+ return rfcAlgoName == SshCapabilities::CryptAlgo3Des
+ ? "TripleDES" : "AES-128";
+}
+
+inline const char *botanEmsaAlgoName(const QByteArray &rfcAlgoName)
+{
+ Q_ASSERT(rfcAlgoName == SshCapabilities::PubKeyDss
+ || rfcAlgoName == SshCapabilities::PubKeyRsa);
+ return rfcAlgoName == SshCapabilities::PubKeyDss
+ ? "EMSA1(SHA-1)" : "EMSA3(SHA-1)";
+}
+
+inline const char *botanSha1Name() { return "SHA-1"; }
+
+inline const char *botanHMacAlgoName(const QByteArray &rfcAlgoName)
+{
+ Q_ASSERT(rfcAlgoName == SshCapabilities::HMacSha1);
+ return botanSha1Name();
+}
+
+inline quint32 botanHMacKeyLen(const QByteArray &rfcAlgoName)
+{
+ Q_ASSERT(rfcAlgoName == SshCapabilities::HMacSha1);
+ return 20;
+}
+
+} // namespace Internal
+} // namespace Core
+
+#endif // BYTEARRAYCONVERSIONS_P_H
diff --git a/coreplugin/ssh/sshcapabilities.cpp b/coreplugin/ssh/sshcapabilities.cpp
new file mode 100644
index 0000000..56db394
--- /dev/null
+++ b/coreplugin/ssh/sshcapabilities.cpp
@@ -0,0 +1,103 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshcapabilities_p.h"
+
+#include "sshexception_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+namespace {
+ QByteArray listAsByteArray(const QList<QByteArray> &list)
+ {
+ QByteArray array;
+ foreach(const QByteArray &elem, list)
+ array += elem + ',';
+ if (!array.isEmpty())
+ array.remove(array.count() - 1, 1);
+ return array;
+ }
+} // anonymous namspace
+
+const QByteArray SshCapabilities::DiffieHellmanGroup1Sha1("diffie-hellman-group1-sha1");
+const QByteArray SshCapabilities::DiffieHellmanGroup14Sha1("diffie-hellman-group14-sha1");
+const QList<QByteArray> SshCapabilities::KeyExchangeMethods
+ = QList<QByteArray>() << SshCapabilities::DiffieHellmanGroup1Sha1
+ << SshCapabilities::DiffieHellmanGroup14Sha1;
+
+const QByteArray SshCapabilities::PubKeyDss("ssh-dss");
+const QByteArray SshCapabilities::PubKeyRsa("ssh-rsa");
+const QList<QByteArray> SshCapabilities::PublicKeyAlgorithms
+ = QList<QByteArray>() << SshCapabilities::PubKeyRsa
+ << SshCapabilities::PubKeyDss;
+
+const QByteArray SshCapabilities::CryptAlgo3Des("3des-cbc");
+const QByteArray SshCapabilities::CryptAlgoAes128("aes128-cbc");
+const QList<QByteArray> SshCapabilities::EncryptionAlgorithms
+ = QList<QByteArray>() << SshCapabilities::CryptAlgoAes128
+ << SshCapabilities::CryptAlgo3Des;
+
+const QByteArray SshCapabilities::HMacSha1("hmac-sha1");
+const QByteArray SshCapabilities::HMacSha196("hmac-sha1-96");
+const QList<QByteArray> SshCapabilities::MacAlgorithms
+ = QList<QByteArray>() /* << SshCapabilities::HMacSha196 */
+ << SshCapabilities::HMacSha1;
+
+const QList<QByteArray> SshCapabilities::CompressionAlgorithms
+ = QList<QByteArray>() << "none";
+
+const QByteArray SshCapabilities::SshConnectionService("ssh-connection");
+
+const QByteArray SshCapabilities::PublicKeyAuthMethod("publickey");
+const QByteArray SshCapabilities::PasswordAuthMethod("password");
+
+
+QByteArray SshCapabilities::findBestMatch(const QList<QByteArray> &myCapabilities,
+ const QList<QByteArray> &serverCapabilities)
+{
+ foreach (const QByteArray &myCapability, myCapabilities) {
+ if (serverCapabilities.contains(myCapability))
+ return myCapability;
+ }
+
+ throw SshServerException(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Server and client capabilities don't match.",
+ QCoreApplication::translate("SshConnection",
+ "Server and client capabilities don't match. "
+ "Client list was: %1.\nServer list was %2.")
+ .arg(listAsByteArray(myCapabilities).data())
+ .arg(listAsByteArray(serverCapabilities).data()));
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshcapabilities_p.h b/coreplugin/ssh/sshcapabilities_p.h
new file mode 100644
index 0000000..7c58c83
--- /dev/null
+++ b/coreplugin/ssh/sshcapabilities_p.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CAPABILITIES_P_H
+#define CAPABILITIES_P_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+
+namespace Core {
+namespace Internal {
+
+class SshCapabilities
+{
+public:
+ static const QByteArray DiffieHellmanGroup1Sha1;
+ static const QByteArray DiffieHellmanGroup14Sha1;
+ static const QList<QByteArray> KeyExchangeMethods;
+
+ static const QByteArray PubKeyDss;
+ static const QByteArray PubKeyRsa;
+ static const QList<QByteArray> PublicKeyAlgorithms;
+
+ static const QByteArray CryptAlgo3Des;
+ static const QByteArray CryptAlgoAes128;
+ static const QList<QByteArray> EncryptionAlgorithms;
+
+ static const QByteArray HMacSha1;
+ static const QByteArray HMacSha196;
+ static const QList<QByteArray> MacAlgorithms;
+
+ static const QList<QByteArray> CompressionAlgorithms;
+
+ static const QByteArray SshConnectionService;
+
+ static const QByteArray PublicKeyAuthMethod;
+ static const QByteArray PasswordAuthMethod;
+
+ static QByteArray findBestMatch(const QList<QByteArray> &myCapabilities,
+ const QList<QByteArray> &serverCapabilities);
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // CAPABILITIES_P_H
diff --git a/coreplugin/ssh/sshchannel.cpp b/coreplugin/ssh/sshchannel.cpp
new file mode 100644
index 0000000..6e1b9c4
--- /dev/null
+++ b/coreplugin/ssh/sshchannel.cpp
@@ -0,0 +1,244 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshchannel_p.h"
+
+#include "sshincomingpacket_p.h"
+#include "sshsendfacility_p.h"
+
+#include <botan/exceptn.h>
+
+namespace Core {
+namespace Internal {
+
+namespace {
+ const quint32 MinMaxPacketSize = 32768;
+ const quint32 MaxPacketSize = 16 * 1024 * 1024;
+ const quint32 InitialWindowSize = MaxPacketSize;
+ const quint32 NoChannel = 0xffffffffu;
+} // anonymous namespace
+
+AbstractSshChannel::AbstractSshChannel(quint32 channelId,
+ SshSendFacility &sendFacility)
+ : m_sendFacility(sendFacility), m_localChannel(channelId),
+ m_remoteChannel(NoChannel), m_localWindowSize(InitialWindowSize),
+ m_remoteWindowSize(0), m_state(Inactive)
+{
+}
+
+AbstractSshChannel::~AbstractSshChannel()
+{
+
+}
+
+void AbstractSshChannel::setChannelState(ChannelState state)
+{
+ m_state = state;
+ if (state == Closed)
+ closeHook();
+}
+
+void AbstractSshChannel::requestSessionStart()
+{
+ // Note: We are just being paranoid here about the Botan exceptions,
+ // which are extremely unlikely to happen, because if there was a problem
+ // with our cryptography stuff, it would have hit us before, on
+ // establishing the connection.
+ try {
+ m_sendFacility.sendSessionPacket(m_localChannel, InitialWindowSize,
+ MaxPacketSize);
+ setChannelState(SessionRequested);
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromAscii(e.what());
+ closeChannel();
+ }
+}
+
+void AbstractSshChannel::sendData(const QByteArray &data)
+{
+ try {
+ m_sendBuffer += data;
+ flushSendBuffer();
+ } catch (Botan::Exception &e) {
+ m_errorString = QString::fromAscii(e.what());
+ closeChannel();
+ }
+}
+
+void AbstractSshChannel::handleWindowAdjust(quint32 bytesToAdd)
+{
+ checkChannelActive();
+
+ const quint64 newValue = m_remoteWindowSize + bytesToAdd;
+ if (newValue > 0xffffffffu) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Illegal window size requested.");
+ }
+
+ m_remoteWindowSize = newValue;
+ flushSendBuffer();
+}
+
+void AbstractSshChannel::flushSendBuffer()
+{
+ const quint32 bytesToSend
+ = qMin<quint32>(m_remoteWindowSize, m_sendBuffer.size());
+ if (bytesToSend > 0) {
+ const QByteArray &data = m_sendBuffer.left(bytesToSend);
+ m_sendFacility.sendChannelDataPacket(m_remoteChannel, data);
+ m_sendBuffer.remove(0, bytesToSend);
+ m_remoteWindowSize -= bytesToSend;
+ }
+}
+
+void AbstractSshChannel::handleOpenSuccess(quint32 remoteChannelId,
+ quint32 remoteWindowSize, quint32 remoteMaxPacketSize)
+{
+ if (m_state != SessionRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet.");
+ }
+
+ if (remoteMaxPacketSize < MinMaxPacketSize) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Maximum packet size too low.");
+ }
+
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Channel opened. remote channel id: %u, remote window size: %u, "
+ "remote max packet size: %u",
+ remoteChannelId, remoteWindowSize, remoteMaxPacketSize);
+#endif
+ m_remoteChannel = remoteChannelId;
+ m_remoteWindowSize = remoteWindowSize;
+ m_remoteMaxPacketSize = remoteMaxPacketSize;
+ setChannelState(SessionEstablished);
+ handleOpenSuccessInternal();
+}
+
+void AbstractSshChannel::handleOpenFailure(const QString &reason)
+{
+ if (m_state != SessionRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
+ }
+
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Channel open request failed for channel %u", m_localChannel);
+#endif
+ m_errorString = reason;
+ handleOpenFailureInternal();
+}
+
+void AbstractSshChannel::handleChannelEof()
+{
+ if (m_state == Inactive || m_state == Closed) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_EOF message.");
+ }
+ m_localWindowSize = 0;
+}
+
+void AbstractSshChannel::handleChannelClose()
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Receiving CLOSE for channel %u", m_localChannel);
+#endif
+ if (channelState() == Inactive || channelState() == Closed) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_CLOSE message.");
+ }
+ closeChannel();
+ setChannelState(Closed);
+}
+
+void AbstractSshChannel::handleChannelData(const QByteArray &data)
+{
+ const int bytesToDeliver = handleChannelOrExtendedChannelData(data);
+ handleChannelDataInternal(bytesToDeliver == data.size()
+ ? data : data.left(bytesToDeliver));
+}
+
+void AbstractSshChannel::handleChannelExtendedData(quint32 type, const QByteArray &data)
+{
+ const int bytesToDeliver = handleChannelOrExtendedChannelData(data);
+ handleChannelExtendedDataInternal(type, bytesToDeliver == data.size()
+ ? data : data.left(bytesToDeliver));
+}
+
+void AbstractSshChannel::handleChannelRequest(const SshIncomingPacket &packet)
+{
+ qWarning("Ignoring unknown request type '%s'",
+ packet.extractChannelRequestType().data());
+}
+
+int AbstractSshChannel::handleChannelOrExtendedChannelData(const QByteArray &data)
+{
+ checkChannelActive();
+
+ const int bytesToDeliver = qMin<quint32>(data.size(), maxDataSize());
+ if (bytesToDeliver != data.size())
+ qWarning("Misbehaving server does not respect local window, clipping.");
+
+ m_localWindowSize -= bytesToDeliver;
+ if (m_localWindowSize < MaxPacketSize) {
+ m_localWindowSize += MaxPacketSize;
+ m_sendFacility.sendWindowAdjustPacket(m_remoteChannel,
+ MaxPacketSize);
+ }
+ return bytesToDeliver;
+}
+
+void AbstractSshChannel::closeChannel()
+{
+ if (m_state != CloseRequested && m_state != Closed) {
+ if (m_state == Inactive) {
+ setChannelState(Closed);
+ } else {
+ setChannelState(CloseRequested);
+ m_sendFacility.sendChannelEofPacket(m_remoteChannel);
+ m_sendFacility.sendChannelClosePacket(m_remoteChannel);
+ }
+ }
+}
+
+void AbstractSshChannel::checkChannelActive()
+{
+ if (channelState() == Inactive || channelState() == Closed)
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Channel not open.");
+}
+
+quint32 AbstractSshChannel::maxDataSize() const
+{
+ return qMin(m_localWindowSize, MaxPacketSize);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshchannel_p.h b/coreplugin/ssh/sshchannel_p.h
new file mode 100644
index 0000000..993357d
--- /dev/null
+++ b/coreplugin/ssh/sshchannel_p.h
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHCHANNEL_P_H
+#define SSHCHANNEL_P_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+class SshIncomingPacket;
+class SshSendFacility;
+
+class AbstractSshChannel
+{
+public:
+ enum ChannelState {
+ Inactive, SessionRequested, SessionEstablished, CloseRequested, Closed
+ };
+
+ ChannelState channelState() const { return m_state; }
+ void setChannelState(ChannelState state);
+
+ void setError(const QString &error) { m_errorString = error; }
+ QString errorString() const { return m_errorString; }
+
+ quint32 localChannelId() const { return m_localChannel; }
+ quint32 remoteChannel() const { return m_remoteChannel; }
+
+ virtual void handleChannelSuccess()=0;
+ virtual void handleChannelFailure()=0;
+ virtual void handleChannelRequest(const SshIncomingPacket &packet);
+
+ virtual void closeHook()=0;
+
+ void handleOpenSuccess(quint32 remoteChannelId, quint32 remoteWindowSize,
+ quint32 remoteMaxPacketSize);
+ void handleOpenFailure(const QString &reason);
+ void handleWindowAdjust(quint32 bytesToAdd);
+ void handleChannelEof();
+ void handleChannelClose();
+ void handleChannelData(const QByteArray &data);
+ void handleChannelExtendedData(quint32 type, const QByteArray &data);
+
+ void requestSessionStart();
+ void sendData(const QByteArray &data);
+ void closeChannel();
+
+ virtual ~AbstractSshChannel();
+
+protected:
+ AbstractSshChannel(quint32 channelId, SshSendFacility &sendFacility);
+
+ quint32 maxDataSize() const;
+ void checkChannelActive();
+
+ SshSendFacility &m_sendFacility;
+
+private:
+ virtual void handleOpenSuccessInternal()=0;
+ virtual void handleOpenFailureInternal()=0;
+ virtual void handleChannelDataInternal(const QByteArray &data)=0;
+ virtual void handleChannelExtendedDataInternal(quint32 type,
+ const QByteArray &data)=0;
+
+ void setState(ChannelState newState);
+ void flushSendBuffer();
+ int handleChannelOrExtendedChannelData(const QByteArray &data);
+
+ const quint32 m_localChannel;
+ quint32 m_remoteChannel;
+ quint32 m_localWindowSize;
+ quint32 m_remoteWindowSize;
+ quint32 m_remoteMaxPacketSize;
+ ChannelState m_state;
+ QByteArray m_sendBuffer;
+ QString m_errorString;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHCHANNEL_P_H
diff --git a/coreplugin/ssh/sshchannelmanager.cpp b/coreplugin/ssh/sshchannelmanager.cpp
new file mode 100644
index 0000000..c7d3113
--- /dev/null
+++ b/coreplugin/ssh/sshchannelmanager.cpp
@@ -0,0 +1,188 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshchannelmanager_p.h"
+
+#include "sftpchannel.h"
+#include "sftpchannel_p.h"
+#include "sshincomingpacket_p.h"
+#include "sshremoteprocess.h"
+#include "sshremoteprocess_p.h"
+#include "sshsendfacility_p.h"
+
+#include <QtCore/QList>
+
+namespace Core {
+namespace Internal {
+
+SshChannelManager::SshChannelManager(SshSendFacility &sendFacility)
+ : m_sendFacility(sendFacility), m_nextLocalChannelId(0)
+{
+}
+
+SshChannelManager::~SshChannelManager() {}
+
+void SshChannelManager::handleChannelRequest(const SshIncomingPacket &packet)
+{
+ lookupChannel(packet.extractRecipientChannel())
+ ->handleChannelRequest(packet);
+}
+
+void SshChannelManager::handleChannelOpen(const SshIncomingPacket &)
+{
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Server tried to open channel on client.");
+}
+
+void SshChannelManager::handleChannelOpenFailure(const SshIncomingPacket &packet)
+{
+ const SshChannelOpenFailure &failure = packet.extractChannelOpenFailure();
+ ChannelIterator it = lookupChannelAsIterator(failure.localChannel);
+ try {
+ it.value()->handleOpenFailure(failure.reasonString);
+ } catch (SshServerException &e) {
+ removeChannel(it);
+ throw e;
+ }
+ removeChannel(it);
+}
+
+void SshChannelManager::handleChannelOpenConfirmation(const SshIncomingPacket &packet)
+{
+ const SshChannelOpenConfirmation &confirmation
+ = packet.extractChannelOpenConfirmation();
+ lookupChannel(confirmation.localChannel)->handleOpenSuccess(confirmation.remoteChannel,
+ confirmation.remoteWindowSize, confirmation.remoteMaxPacketSize);
+}
+
+void SshChannelManager::handleChannelSuccess(const SshIncomingPacket &packet)
+{
+ lookupChannel(packet.extractRecipientChannel())->handleChannelSuccess();
+}
+
+void SshChannelManager::handleChannelFailure(const SshIncomingPacket &packet)
+{
+ lookupChannel(packet.extractRecipientChannel())->handleChannelFailure();
+}
+
+void SshChannelManager::handleChannelWindowAdjust(const SshIncomingPacket &packet)
+{
+ const SshChannelWindowAdjust adjust = packet.extractWindowAdjust();
+ lookupChannel(adjust.localChannel)->handleWindowAdjust(adjust.bytesToAdd);
+}
+
+void SshChannelManager::handleChannelData(const SshIncomingPacket &packet)
+{
+ const SshChannelData &data = packet.extractChannelData();
+ lookupChannel(data.localChannel)->handleChannelData(data.data);
+}
+
+void SshChannelManager::handleChannelExtendedData(const SshIncomingPacket &packet)
+{
+ const SshChannelExtendedData &data = packet.extractChannelExtendedData();
+ lookupChannel(data.localChannel)->handleChannelExtendedData(data.type, data.data);
+}
+
+void SshChannelManager::handleChannelEof(const SshIncomingPacket &packet)
+{
+ AbstractSshChannel * const channel
+ = lookupChannel(packet.extractRecipientChannel(), true);
+ if (channel)
+ channel->handleChannelEof();
+}
+
+void SshChannelManager::handleChannelClose(const SshIncomingPacket &packet)
+{
+ const quint32 channelId = packet.extractRecipientChannel();
+
+ ChannelIterator it = lookupChannelAsIterator(channelId, true);
+ if (it != m_channels.end()) {
+ it.value()->handleChannelClose();
+ removeChannel(it);
+ }
+}
+
+SshChannelManager::ChannelIterator SshChannelManager::lookupChannelAsIterator(quint32 channelId,
+ bool allowNotFound)
+{
+ ChannelIterator it = m_channels.find(channelId);
+ if (it == m_channels.end() && !allowNotFound) {
+ throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid channel id.",
+ SSH_TR("Invalid channel id %1").arg(channelId));
+ }
+ return it;
+}
+
+AbstractSshChannel *SshChannelManager::lookupChannel(quint32 channelId,
+ bool allowNotFound)
+{
+ ChannelIterator it = lookupChannelAsIterator(channelId, allowNotFound);
+ return it == m_channels.end() ? 0 : it.value();
+}
+
+Core::SshRemoteProcess::Ptr SshChannelManager::createRemoteProcess(const QByteArray &command)
+{
+ SshRemoteProcess::Ptr proc(new SshRemoteProcess(command, m_nextLocalChannelId++, m_sendFacility));
+ insertChannel(proc->d, proc);
+ return proc;
+}
+
+Core::SftpChannel::Ptr SshChannelManager::createSftpChannel()
+{
+ SftpChannel::Ptr sftp(new SftpChannel(m_nextLocalChannelId++, m_sendFacility));
+ insertChannel(sftp->d, sftp);
+ return sftp;
+}
+
+void SshChannelManager::insertChannel(AbstractSshChannel *priv,
+ const QSharedPointer<QObject> &pub)
+{
+ m_channels.insert(priv->localChannelId(), priv);
+ m_sessions.insert(priv, pub);
+}
+
+void SshChannelManager::closeAllChannels()
+{
+ for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it)
+ it.value()->closeChannel();
+ m_channels.clear();
+ m_sessions.clear();
+}
+
+void SshChannelManager::removeChannel(ChannelIterator it)
+{
+ Q_ASSERT(it != m_channels.end() && "Unexpected channel lookup failure.");
+ const int removeCount = m_sessions.remove(it.value());
+ Q_ASSERT(removeCount == 1 && "Session for channel not found.");
+ m_channels.erase(it);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshchannelmanager_p.h b/coreplugin/ssh/sshchannelmanager_p.h
new file mode 100644
index 0000000..fe62c00
--- /dev/null
+++ b/coreplugin/ssh/sshchannelmanager_p.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHCHANNELLAYER_P_H
+#define SSHCHANNELLAYER_P_H
+
+#include <QtCore/QHash>
+#include <QtCore/QSharedPointer>
+
+namespace Core {
+
+class SftpChannel;
+class SshRemoteProcess;
+
+namespace Internal {
+
+class AbstractSshChannel;
+class SshIncomingPacket;
+class SshSendFacility;
+
+class SshChannelManager
+{
+public:
+ SshChannelManager(SshSendFacility &sendFacility);
+ ~SshChannelManager();
+
+ QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
+ QSharedPointer<SftpChannel> createSftpChannel();
+ void closeAllChannels();
+
+ void handleChannelRequest(const SshIncomingPacket &packet);
+ void handleChannelOpen(const SshIncomingPacket &packet);
+ void handleChannelOpenFailure(const SshIncomingPacket &packet);
+ void handleChannelOpenConfirmation(const SshIncomingPacket &packet);
+ void handleChannelSuccess(const SshIncomingPacket &packet);
+ void handleChannelFailure(const SshIncomingPacket &packet);
+ void handleChannelWindowAdjust(const SshIncomingPacket &packet);
+ void handleChannelData(const SshIncomingPacket &packet);
+ void handleChannelExtendedData(const SshIncomingPacket &packet);
+ void handleChannelEof(const SshIncomingPacket &packet);
+ void handleChannelClose(const SshIncomingPacket &packet);
+
+private:
+ typedef QHash<quint32, AbstractSshChannel *>::Iterator ChannelIterator;
+
+ ChannelIterator lookupChannelAsIterator(quint32 channelId,
+ bool allowNotFound = false);
+ AbstractSshChannel *lookupChannel(quint32 channelId,
+ bool allowNotFound = false);
+ void removeChannel(ChannelIterator it);
+ void insertChannel(AbstractSshChannel *priv,
+ const QSharedPointer<QObject> &pub);
+
+ SshSendFacility &m_sendFacility;
+ QHash<quint32, AbstractSshChannel *> m_channels;
+ QHash<AbstractSshChannel *, QSharedPointer<QObject> > m_sessions;
+ quint32 m_nextLocalChannelId;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHCHANNELLAYER_P_H
diff --git a/coreplugin/ssh/sshconnection.cpp b/coreplugin/ssh/sshconnection.cpp
new file mode 100644
index 0000000..fbf63d7
--- /dev/null
+++ b/coreplugin/ssh/sshconnection.cpp
@@ -0,0 +1,561 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshconnection.h"
+#include "sshconnection_p.h"
+
+#include "sftpchannel.h"
+#include "sshcapabilities_p.h"
+#include "sshchannelmanager_p.h"
+#include "sshcryptofacility_p.h"
+#include "sshexception_p.h"
+#include "sshkeyexchange_p.h"
+
+#include <botan/exceptn.h>
+#include <botan/init.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QMutex>
+#include <QtNetwork/QTcpSocket>
+
+namespace Core {
+
+namespace {
+ const QByteArray ClientId("SSH-2.0-QtCreator\r\n");
+
+ bool staticInitializationsDone = false;
+ QMutex staticInitMutex;
+
+ void doStaticInitializationsIfNecessary()
+ {
+ if (!staticInitializationsDone) {
+ staticInitMutex.lock();
+ if (!staticInitializationsDone) {
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+ qRegisterMetaType<SshError>("SshError");
+ staticInitializationsDone = true;
+ }
+ staticInitMutex.unlock();
+ }
+ }
+}
+
+// TODO: Mechanism for checking the host key. First connection to host: save, later: compare
+
+SshConnection::Ptr SshConnection::create()
+{
+ doStaticInitializationsIfNecessary();
+ return Ptr(new SshConnection);
+}
+
+SshConnection::SshConnection() : d(new Internal::SshConnectionPrivate(this))
+{
+ connect(d, SIGNAL(connected()), this, SIGNAL(connected()),
+ Qt::QueuedConnection);
+ connect(d, SIGNAL(dataAvailable(QString)), this,
+ SIGNAL(dataAvailable(QString)), Qt::QueuedConnection);
+ connect(d, SIGNAL(disconnected()), this, SIGNAL(disconnected()),
+ Qt::QueuedConnection);
+ connect(d, SIGNAL(error(SshError)), this, SIGNAL(error(SshError)),
+ Qt::QueuedConnection);
+}
+
+void SshConnection::connectToHost(const SshConnectionParameters &serverInfo)
+{
+ d->connectToHost(serverInfo);
+}
+
+void SshConnection::disconnectFromHost()
+{
+ d->closeConnection(Internal::SSH_DISCONNECT_BY_APPLICATION, SshNoError, "",
+ QString());
+}
+
+SshConnection::State SshConnection::state() const
+{
+ switch (d->state()) {
+ case Internal::SocketUnconnected:
+ return Unconnected;
+ case Internal::ConnectionEstablished:
+ return Connected;
+ default:
+ return Connecting;
+ }
+}
+
+SshError SshConnection::errorState() const
+{
+ return d->error();
+}
+
+QString SshConnection::errorString() const
+{
+ return d->errorString();
+}
+
+SshConnectionParameters SshConnection::connectionParameters() const
+{
+ return d->m_connParams;
+}
+
+SshConnection::~SshConnection()
+{
+ disconnect();
+ disconnectFromHost();
+ delete d;
+}
+
+QSharedPointer<SshRemoteProcess> SshConnection::createRemoteProcess(const QByteArray &command)
+{
+ return state() == Connected
+ ? d->createRemoteProcess(command) : QSharedPointer<SshRemoteProcess>();
+}
+
+QSharedPointer<SftpChannel> SshConnection::createSftpChannel()
+{
+ return state() == Connected
+ ? d->createSftpChannel() : QSharedPointer<SftpChannel>();
+}
+
+
+namespace Internal {
+
+SshConnectionPrivate::SshConnectionPrivate(SshConnection *conn)
+ : m_socket(new QTcpSocket(this)), m_state(SocketUnconnected),
+ m_sendFacility(m_socket),
+ m_channelManager(new SshChannelManager(m_sendFacility)),
+ m_error(SshNoError), m_ignoreNextPacket(false), m_conn(conn)
+{
+ setupPacketHandlers();
+ connect(&m_timeoutTimer, SIGNAL(timeout()), this, SLOT(handleTimeout()));
+}
+
+SshConnectionPrivate::~SshConnectionPrivate()
+{
+ disconnect();
+}
+
+void SshConnectionPrivate::setupPacketHandlers()
+{
+ typedef SshConnectionPrivate This;
+
+ setupPacketHandler(SSH_MSG_KEXINIT, StateList() << SocketConnected,
+ &This::handleKeyExchangeInitPacket);
+ setupPacketHandler(SSH_MSG_KEXDH_REPLY, StateList() << KeyExchangeStarted,
+ &This::handleKeyExchangeReplyPacket);
+
+ setupPacketHandler(SSH_MSG_NEWKEYS, StateList() << KeyExchangeSuccess,
+ &This::handleNewKeysPacket);
+ setupPacketHandler(SSH_MSG_SERVICE_ACCEPT,
+ StateList() << UserAuthServiceRequested,
+ &This::handleServiceAcceptPacket);
+ setupPacketHandler(SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
+ StateList() << UserAuthRequested, &This::handlePasswordExpiredPacket);
+ setupPacketHandler(SSH_MSG_GLOBAL_REQUEST,
+ StateList() << ConnectionEstablished, &This::handleGlobalRequest);
+
+ const StateList authReqList = StateList() << UserAuthRequested;
+ setupPacketHandler(SSH_MSG_USERAUTH_BANNER, authReqList,
+ &This::handleUserAuthBannerPacket);
+ setupPacketHandler(SSH_MSG_USERAUTH_SUCCESS, authReqList,
+ &This::handleUserAuthSuccessPacket);
+ setupPacketHandler(SSH_MSG_USERAUTH_FAILURE, authReqList,
+ &This::handleUserAuthFailurePacket);
+
+ const StateList connectedList
+ = StateList() << ConnectionEstablished;
+ setupPacketHandler(SSH_MSG_CHANNEL_REQUEST, connectedList,
+ &This::handleChannelRequest);
+ setupPacketHandler(SSH_MSG_CHANNEL_OPEN, connectedList,
+ &This::handleChannelOpen);
+ setupPacketHandler(SSH_MSG_CHANNEL_OPEN_FAILURE, connectedList,
+ &This::handleChannelOpenFailure);
+ setupPacketHandler(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, connectedList,
+ &This::handleChannelOpenConfirmation);
+ setupPacketHandler(SSH_MSG_CHANNEL_SUCCESS, connectedList,
+ &This::handleChannelSuccess);
+ setupPacketHandler(SSH_MSG_CHANNEL_FAILURE, connectedList,
+ &This::handleChannelFailure);
+ setupPacketHandler(SSH_MSG_CHANNEL_WINDOW_ADJUST, connectedList,
+ &This::handleChannelWindowAdjust);
+ setupPacketHandler(SSH_MSG_CHANNEL_DATA, connectedList,
+ &This::handleChannelData);
+ setupPacketHandler(SSH_MSG_CHANNEL_EXTENDED_DATA, connectedList,
+ &This::handleChannelExtendedData);
+
+ const StateList connectedOrClosedList
+ = StateList() << SocketUnconnected << ConnectionEstablished;
+ setupPacketHandler(SSH_MSG_CHANNEL_EOF, connectedOrClosedList,
+ &This::handleChannelEof);
+ setupPacketHandler(SSH_MSG_CHANNEL_CLOSE, connectedOrClosedList,
+ &This::handleChannelClose);
+
+ setupPacketHandler(SSH_MSG_DISCONNECT, StateList() << SocketConnected
+ << KeyExchangeStarted << KeyExchangeSuccess
+ << UserAuthServiceRequested << UserAuthRequested
+ << ConnectionEstablished, &This::handleDisconnect);
+}
+
+void SshConnectionPrivate::setupPacketHandler(SshPacketType type,
+ const SshConnectionPrivate::StateList &states,
+ SshConnectionPrivate::PacketHandler handler)
+{
+ m_packetHandlers.insert(type, HandlerInStates(states, handler));
+}
+
+void SshConnectionPrivate::handleSocketConnected()
+{
+ m_state = SocketConnected;
+ sendData(ClientId);
+}
+
+void SshConnectionPrivate::handleIncomingData()
+{
+ if (m_state == SocketUnconnected)
+ return; // For stuff queued in the event loop after we've called closeConnection();
+
+ try {
+ m_incomingData += m_socket->readAll();
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("state = %d, remote data size = %d", m_state,
+ m_incomingData.count());
+#endif
+ if (m_state == SocketConnected)
+ handleServerId();
+ handlePackets();
+ } catch (SshServerException &e) {
+ closeConnection(e.error, SshProtocolError, e.errorStringServer,
+ tr("SSH Protocol error: %1").arg(e.errorStringUser));
+ } catch (SshClientException &e) {
+ closeConnection(SSH_DISCONNECT_BY_APPLICATION, e.error, "",
+ e.errorString);
+ } catch (Botan::Exception &e) {
+ closeConnection(SSH_DISCONNECT_BY_APPLICATION, SshInternalError, "",
+ tr("Botan exception: %1").arg(e.what()));
+ }
+}
+
+void SshConnectionPrivate::handleServerId()
+{
+ const int idOffset = m_incomingData.indexOf("SSH-");
+ if (idOffset == -1)
+ return;
+ m_incomingData.remove(0, idOffset);
+ if (m_incomingData.size() < 7)
+ return;
+ const QByteArray &version = m_incomingData.mid(4, 3);
+ if (version != "2.0") {
+ throw SshServerException(SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
+ "Invalid protocol version.",
+ tr("Invalid protocol version: Expected '2.0', got '%1'.")
+ .arg(SshPacketParser::asUserString(version)));
+ }
+ const int endOffset = m_incomingData.indexOf("\r\n");
+ if (endOffset == -1)
+ return;
+ if (m_incomingData.at(7) != '-') {
+ throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid server id.", tr("Invalid server id '%1'.")
+ .arg(SshPacketParser::asUserString(m_incomingData)));
+ }
+
+ m_keyExchange.reset(new SshKeyExchange(m_sendFacility));
+ m_keyExchange->sendKexInitPacket(m_incomingData.left(endOffset));
+ m_incomingData.remove(0, endOffset + 2);
+}
+
+void SshConnectionPrivate::handlePackets()
+{
+ m_incomingPacket.consumeData(m_incomingData);
+ while (m_incomingPacket.isComplete()) {
+ handleCurrentPacket();
+ m_incomingPacket.clear();
+ m_incomingPacket.consumeData(m_incomingData);
+ }
+}
+
+void SshConnectionPrivate::handleCurrentPacket()
+{
+ Q_ASSERT(m_incomingPacket.isComplete());
+ Q_ASSERT(m_state == KeyExchangeStarted || !m_ignoreNextPacket);
+
+ if (m_ignoreNextPacket) {
+ m_ignoreNextPacket = false;
+ return;
+ }
+
+ QHash<SshPacketType, HandlerInStates>::ConstIterator it
+ = m_packetHandlers.find(m_incomingPacket.type());
+ if (it == m_packetHandlers.end()) {
+ m_sendFacility.sendMsgUnimplementedPacket(m_incomingPacket.serverSeqNr());
+ return;
+ }
+ if (!it.value().first.contains(m_state)) {
+ throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected packet.", tr("Unexpected packet of type %1.")
+ .arg(m_incomingPacket.type()));
+ }
+ (this->*it.value().second)();
+}
+
+void SshConnectionPrivate::handleKeyExchangeInitPacket()
+{
+ // If the server sends a guessed packet, the guess must be wrong,
+ // because the algorithms we support requires us to initiate the
+ // key exchange.
+ if (m_keyExchange->sendDhInitPacket(m_incomingPacket))
+ m_ignoreNextPacket = true;
+ m_state = KeyExchangeStarted;
+}
+
+void SshConnectionPrivate::handleKeyExchangeReplyPacket()
+{
+ m_keyExchange->sendNewKeysPacket(m_incomingPacket,
+ ClientId.left(ClientId.size() - 2));
+ m_sendFacility.recreateKeys(*m_keyExchange);
+ m_state = KeyExchangeSuccess;
+}
+
+void SshConnectionPrivate::handleNewKeysPacket()
+{
+ m_incomingPacket.recreateKeys(*m_keyExchange);
+ m_keyExchange.reset();
+ m_sendFacility.sendUserAuthServiceRequestPacket();
+ m_state = UserAuthServiceRequested;
+}
+
+void SshConnectionPrivate::handleServiceAcceptPacket()
+{
+ if (m_connParams.authType == SshConnectionParameters::AuthByPwd) {
+ m_sendFacility.sendUserAuthByPwdRequestPacket(m_connParams.uname.toUtf8(),
+ SshCapabilities::SshConnectionService, m_connParams.pwd.toUtf8());
+ } else {
+ QFile privKeyFile(m_connParams.privateKeyFile);
+ bool couldOpen = privKeyFile.open(QIODevice::ReadOnly);
+ QByteArray contents;
+ if (couldOpen)
+ contents = privKeyFile.readAll();
+ if (!couldOpen || privKeyFile.error() != QFile::NoError) {
+ throw SshClientException(SshKeyFileError,
+ tr("Could not read private key file: %1")
+ .arg(privKeyFile.errorString()));
+ }
+
+ m_sendFacility.createAuthenticationKey(contents);
+ m_sendFacility.sendUserAuthByKeyRequestPacket(m_connParams.uname.toUtf8(),
+ SshCapabilities::SshConnectionService);
+ }
+ m_state = UserAuthRequested;
+}
+
+void SshConnectionPrivate::handlePasswordExpiredPacket()
+{
+ if (m_connParams.authType == SshConnectionParameters::AuthByKey) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Got SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, but did not use password.");
+ }
+
+ throw SshClientException(SshAuthenticationError, tr("Password expired."));
+}
+
+void SshConnectionPrivate::handleUserAuthBannerPacket()
+{
+ emit dataAvailable(m_incomingPacket.extractUserAuthBanner().message);
+}
+
+void SshConnectionPrivate::handleGlobalRequest()
+{
+ m_sendFacility.sendRequestFailurePacket();
+}
+
+void SshConnectionPrivate::handleUserAuthSuccessPacket()
+{
+ m_state = ConnectionEstablished;
+ m_timeoutTimer.stop();
+ emit connected();
+}
+
+void SshConnectionPrivate::handleUserAuthFailurePacket()
+{
+ const QString errorMsg = m_connParams.authType == SshConnectionParameters::AuthByPwd
+ ? tr("Server rejected password.") : tr("Server rejected key.");
+ throw SshClientException(SshAuthenticationError, errorMsg);
+}
+void SshConnectionPrivate::handleDebugPacket()
+{
+ const SshDebug &msg = m_incomingPacket.extractDebug();
+ if (msg.display)
+ emit dataAvailable(msg.message);
+}
+
+void SshConnectionPrivate::handleChannelRequest()
+{
+ m_channelManager->handleChannelRequest(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelOpen()
+{
+ m_channelManager->handleChannelOpen(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelOpenFailure()
+{
+ m_channelManager->handleChannelOpenFailure(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelOpenConfirmation()
+{
+ m_channelManager->handleChannelOpenConfirmation(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelSuccess()
+{
+ m_channelManager->handleChannelSuccess(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelFailure()
+{
+ m_channelManager->handleChannelFailure(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelWindowAdjust()
+{
+ m_channelManager->handleChannelWindowAdjust(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelData()
+{
+ m_channelManager->handleChannelData(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelExtendedData()
+{
+ m_channelManager->handleChannelExtendedData(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelEof()
+{
+ m_channelManager->handleChannelEof(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleChannelClose()
+{
+ m_channelManager->handleChannelClose(m_incomingPacket);
+}
+
+void SshConnectionPrivate::handleDisconnect()
+{
+ const SshDisconnect msg = m_incomingPacket.extractDisconnect();
+ throw SshServerException(SSH_DISCONNECT_CONNECTION_LOST,
+ "", tr("Server closed connection: %1").arg(msg.description));
+}
+
+void SshConnectionPrivate::sendData(const QByteArray &data)
+{
+ m_socket->write(data);
+}
+
+void SshConnectionPrivate::handleSocketDisconnected()
+{
+ closeConnection(SSH_DISCONNECT_CONNECTION_LOST, SshClosedByServerError,
+ "Connection closed unexpectedly.",
+ tr("Connection closed unexpectedly."));
+}
+
+void SshConnectionPrivate::handleSocketError()
+{
+ if (m_error == SshNoError) {
+ closeConnection(SSH_DISCONNECT_CONNECTION_LOST, SshSocketError,
+ "Network error", m_socket->errorString());
+ }
+}
+
+void SshConnectionPrivate::handleTimeout()
+{
+ if (m_state != ConnectionEstablished)
+ closeConnection(SSH_DISCONNECT_BY_APPLICATION, SshTimeoutError, "",
+ tr("Connection timed out."));
+}
+
+void SshConnectionPrivate::connectToHost(const SshConnectionParameters &serverInfo)
+{
+ m_incomingData.clear();
+ m_incomingPacket.reset();
+ m_sendFacility.reset();
+ m_error = SshNoError;
+ m_ignoreNextPacket = false;
+ m_errorString.clear();
+ connect(m_socket, SIGNAL(connected()), this, SLOT(handleSocketConnected()));
+ connect(m_socket, SIGNAL(readyRead()), this, SLOT(handleIncomingData()));
+ connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
+ SLOT(handleSocketError()));
+ connect(m_socket, SIGNAL(disconnected()), this,
+ SLOT(handleSocketDisconnected()));
+ this->m_connParams = serverInfo;
+ m_state = SocketConnecting;
+ m_timeoutTimer.start(m_connParams.timeout * 1000);
+ m_socket->connectToHost(serverInfo.host, serverInfo.port);
+}
+
+void SshConnectionPrivate::closeConnection(SshErrorCode sshError,
+ SshError userError, const QByteArray &serverErrorString,
+ const QString &userErrorString)
+{
+ // Prevent endless loops by recursive exceptions.
+ if (m_state == SocketUnconnected || m_error != SshNoError)
+ return;
+
+ m_error = userError;
+ m_errorString = userErrorString;
+ m_timeoutTimer.stop();
+ disconnect(m_socket, 0, this, 0);
+ try {
+ m_channelManager->closeAllChannels();
+ m_sendFacility.sendDisconnectPacket(sshError, serverErrorString);
+ } catch (Botan::Exception &) {} // Nothing sensible to be done here.
+ if (m_error != SshNoError)
+ emit error(userError);
+ if (m_state == ConnectionEstablished)
+ emit disconnected();
+ m_socket->disconnectFromHost();
+ m_state = SocketUnconnected;
+}
+
+QSharedPointer<SshRemoteProcess> SshConnectionPrivate::createRemoteProcess(const QByteArray &command)
+{
+ return m_channelManager->createRemoteProcess(command);
+}
+
+QSharedPointer<SftpChannel> SshConnectionPrivate::createSftpChannel()
+{
+ return m_channelManager->createSftpChannel();
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshconnection.h b/coreplugin/ssh/sshconnection.h
new file mode 100644
index 0000000..d863fd5
--- /dev/null
+++ b/coreplugin/ssh/sshconnection.h
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHCONNECTION_H
+#define SSHCONNECTION_H
+
+#include "ssherrors.h"
+
+#include <coreplugin/core_global.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+
+namespace Core {
+class SftpChannel;
+class SshRemoteProcess;
+
+namespace Internal {
+class SshConnectionPrivate;
+} // namespace Internal
+
+struct CORE_EXPORT SshConnectionParameters
+{
+ QString host;
+ QString uname;
+ QString pwd;
+ QString privateKeyFile;
+ int timeout;
+ enum AuthType { AuthByPwd, AuthByKey } authType;
+ quint16 port;
+};
+CORE_EXPORT inline bool operator==(const SshConnectionParameters &p1,
+ const SshConnectionParameters &p2)
+{
+ return p1.host == p2.host && p1.uname == p2.uname
+ && p1.authType == p2.authType
+ && (p1.authType == SshConnectionParameters::AuthByPwd ?
+ p1.pwd == p2.pwd : p1.privateKeyFile == p2.privateKeyFile)
+ && p1.timeout == p2.timeout && p1.port == p2.port;
+}
+
+
+/*
+ * This class provides an SSH connection, implementing protocol version 2.0
+ * It can spawn channels for remote execution and SFTP operations (version 3).
+ * It operates asynchronously (non-blocking) and is not thread-safe.
+ */
+class CORE_EXPORT SshConnection : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(SshConnection)
+public:
+ enum State { Unconnected, Connecting, Connected };
+ typedef QSharedPointer<SshConnection> Ptr;
+
+ static Ptr create();
+
+ void connectToHost(const SshConnectionParameters &serverInfo);
+ void disconnectFromHost();
+ State state() const;
+ SshError errorState() const;
+ QString errorString() const;
+ SshConnectionParameters connectionParameters() const;
+ ~SshConnection();
+
+ QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
+ QSharedPointer<SftpChannel> createSftpChannel();
+
+signals:
+ void connected();
+ void disconnected();
+ void dataAvailable(const QString &message);
+ void error(SshError);
+
+private:
+ SshConnection();
+
+ Internal::SshConnectionPrivate *d;
+};
+
+} // namespace Internal
+
+#endif // SSHCONNECTION_H
diff --git a/coreplugin/ssh/sshconnection_p.h b/coreplugin/ssh/sshconnection_p.h
new file mode 100644
index 0000000..c20ccf7
--- /dev/null
+++ b/coreplugin/ssh/sshconnection_p.h
@@ -0,0 +1,157 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHCONNECTION_P_H
+#define SSHCONNECTION_P_H
+
+#include "sshconnection.h"
+#include "sshexception_p.h"
+#include "sshincomingpacket_p.h"
+#include "sshremoteprocess.h"
+#include "sshsendfacility_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+class QTcpSocket;
+QT_END_NAMESPACE
+
+namespace Botan { class Exception; }
+
+namespace Core {
+class SftpChannel;
+
+namespace Internal {
+class SshChannelManager;
+
+// NOTE: When you add stuff here, don't forget to update m_packetHandlers.
+enum SshStateInternal {
+ SocketUnconnected, // initial and after disconnect
+ SocketConnecting, // After connectToHost()
+ SocketConnected, // After socket's connected() signal
+ KeyExchangeStarted, // After server's KEXINIT message
+ KeyExchangeSuccess, // After server's DH_REPLY message
+ UserAuthServiceRequested,
+ UserAuthRequested,
+
+ ConnectionEstablished // After service has been started
+ // ...
+};
+
+class SshConnectionPrivate : public QObject
+{
+ Q_OBJECT
+ friend class Core::SshConnection;
+public:
+ SshConnectionPrivate(SshConnection *conn);
+ ~SshConnectionPrivate();
+
+ void connectToHost(const SshConnectionParameters &serverInfo);
+ void closeConnection(SshErrorCode sshError, SshError userError,
+ const QByteArray &serverErrorString, const QString &userErrorString);
+ QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
+ QSharedPointer<SftpChannel> createSftpChannel();
+ SshStateInternal state() const { return m_state; }
+ SshError error() const { return m_error; }
+ QString errorString() const { return m_errorString; }
+
+signals:
+ void connected();
+ void disconnected();
+ void dataAvailable(const QString &message);
+ void error(SshError);
+
+private:
+ Q_SLOT void handleSocketConnected();
+ Q_SLOT void handleIncomingData();
+ Q_SLOT void handleSocketError();
+ Q_SLOT void handleSocketDisconnected();
+ Q_SLOT void handleTimeout();
+
+ void handleServerId();
+ void handlePackets();
+ void handleCurrentPacket();
+ void handleKeyExchangeInitPacket();
+ void handleKeyExchangeReplyPacket();
+ void handleNewKeysPacket();
+ void handleServiceAcceptPacket();
+ void handlePasswordExpiredPacket();
+ void handleUserAuthSuccessPacket();
+ void handleUserAuthFailurePacket();
+ void handleUserAuthBannerPacket();
+ void handleGlobalRequest();
+ void handleDebugPacket();
+ void handleChannelRequest();
+ void handleChannelOpen();
+ void handleChannelOpenFailure();
+ void handleChannelOpenConfirmation();
+ void handleChannelSuccess();
+ void handleChannelFailure();
+ void handleChannelWindowAdjust();
+ void handleChannelData();
+ void handleChannelExtendedData();
+ void handleChannelEof();
+ void handleChannelClose();
+ void handleDisconnect();
+
+ void sendData(const QByteArray &data);
+
+ typedef void (SshConnectionPrivate::*PacketHandler)();
+ typedef QList<SshStateInternal> StateList;
+ void setupPacketHandlers();
+ void setupPacketHandler(SshPacketType type, const StateList &states,
+ PacketHandler handler);
+
+ typedef QPair<StateList, PacketHandler> HandlerInStates;
+ QHash<SshPacketType, HandlerInStates> m_packetHandlers;
+
+ QTcpSocket *m_socket;
+ SshStateInternal m_state;
+ SshIncomingPacket m_incomingPacket;
+ SshSendFacility m_sendFacility;
+ QScopedPointer<SshChannelManager> m_channelManager;
+ SshConnectionParameters m_connParams;
+ QByteArray m_incomingData;
+ SshError m_error;
+ QString m_errorString;
+ QScopedPointer<SshKeyExchange> m_keyExchange;
+ QTimer m_timeoutTimer;
+ bool m_ignoreNextPacket;
+ SshConnection *m_conn;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHCONNECTION_P_H
diff --git a/coreplugin/ssh/sshcryptofacility.cpp b/coreplugin/ssh/sshcryptofacility.cpp
new file mode 100644
index 0000000..fd2fe32
--- /dev/null
+++ b/coreplugin/ssh/sshcryptofacility.cpp
@@ -0,0 +1,369 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshcryptofacility_p.h"
+
+#include "sshbotanconversions_p.h"
+#include "sshcapabilities_p.h"
+#include "sshexception_p.h"
+#include "sshkeyexchange_p.h"
+#include "sshpacket_p.h"
+
+#include <botan/ber_dec.h>
+#include <botan/botan.h>
+#include <botan/cbc.h>
+#include <botan/dsa.h>
+#include <botan/hash.h>
+#include <botan/hmac.h>
+#include <botan/look_pk.h>
+#include <botan/pipe.h>
+#include <botan/pkcs8.h>
+#include <botan/pubkey.h>
+#include <botan/rsa.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QList>
+
+#include <string>
+
+using namespace Botan;
+
+namespace Core {
+namespace Internal {
+
+SshAbstractCryptoFacility::SshAbstractCryptoFacility()
+ : m_cipherBlockSize(0), m_macLength(0)
+{
+}
+
+SshAbstractCryptoFacility::~SshAbstractCryptoFacility() {}
+
+void SshAbstractCryptoFacility::clearKeys()
+{
+ m_cipherBlockSize = 0;
+ m_macLength = 0;
+ m_sessionId.clear();
+ m_pipe.reset(0);
+ m_hMac.reset(0);
+}
+
+void SshAbstractCryptoFacility::recreateKeys(const SshKeyExchange &kex)
+{
+ checkInvariant();
+
+ if (m_sessionId.isEmpty())
+ m_sessionId = kex.h();
+ Algorithm_Factory &af = global_state().algorithm_factory();
+ const std::string &cryptAlgo = botanCryptAlgoName(cryptAlgoName(kex));
+ BlockCipher * const cipher = af.prototype_block_cipher(cryptAlgo)->clone();
+
+ m_cipherBlockSize = cipher->BLOCK_SIZE;
+ const QByteArray ivData = generateHash(kex, ivChar(), m_cipherBlockSize);
+ const InitializationVector iv(convertByteArray(ivData), m_cipherBlockSize);
+
+ const quint32 keySize = max_keylength_of(cryptAlgo);
+ const QByteArray cryptKeyData = generateHash(kex, keyChar(), keySize);
+ SymmetricKey cryptKey(convertByteArray(cryptKeyData), keySize);
+
+ BlockCipherMode * const cipherMode
+ = makeCipherMode(cipher, new Null_Padding, iv, cryptKey);
+ m_pipe.reset(new Pipe(cipherMode));
+
+ m_macLength = botanHMacKeyLen(hMacAlgoName(kex));
+ const QByteArray hMacKeyData = generateHash(kex, macChar(), macLength());
+ SymmetricKey hMacKey(convertByteArray(hMacKeyData), macLength());
+ const HashFunction * const hMacProto
+ = af.prototype_hash_function(botanHMacAlgoName(hMacAlgoName(kex)));
+ m_hMac.reset(new HMAC(hMacProto->clone()));
+ m_hMac->set_key(hMacKey);
+}
+
+void SshAbstractCryptoFacility::convert(QByteArray &data, quint32 offset,
+ quint32 dataSize) const
+{
+ Q_ASSERT(offset + dataSize <= static_cast<quint32>(data.size()));
+ checkInvariant();
+
+ // Session id empty => No key exchange has happened yet.
+ if (dataSize == 0 || m_sessionId.isEmpty())
+ return;
+
+ if (dataSize % cipherBlockSize() != 0) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid packet size");
+ }
+ m_pipe->process_msg(reinterpret_cast<const byte *>(data.constData()) + offset,
+ dataSize);
+ quint32 bytesRead = m_pipe->read(reinterpret_cast<byte *>(data.data()) + offset,
+ dataSize, m_pipe->message_count() - 1); // Can't use Pipe::LAST_MESSAGE because of a VC bug.
+ Q_ASSERT(bytesRead == dataSize);
+}
+
+QByteArray SshAbstractCryptoFacility::generateMac(const QByteArray &data,
+ quint32 dataSize) const
+{
+ return m_sessionId.isEmpty()
+ ? QByteArray()
+ : convertByteArray(m_hMac->process(reinterpret_cast<const byte *>(data.constData()),
+ dataSize));
+}
+
+QByteArray SshAbstractCryptoFacility::generateHash(const SshKeyExchange &kex,
+ char c, quint32 length)
+{
+ const QByteArray &k = kex.k();
+ const QByteArray &h = kex.h();
+ QByteArray data(k);
+ data.append(h).append(c).append(m_sessionId);
+ SecureVector<byte> key
+ = kex.hash()->process(convertByteArray(data), data.size());
+ while (key.size() < length) {
+ SecureVector<byte> tmpKey;
+ tmpKey.append(convertByteArray(k), k.size());
+ tmpKey.append(convertByteArray(h), h.size());
+ tmpKey.append(key);
+ key.append(kex.hash()->process(tmpKey));
+ }
+ return QByteArray(reinterpret_cast<const char *>(key.begin()), length);
+}
+
+void SshAbstractCryptoFacility::checkInvariant() const
+{
+ Q_ASSERT(m_sessionId.isEmpty() == !m_pipe);
+}
+
+
+const QByteArray SshEncryptionFacility::PrivKeyFileStartLineRsa("-----BEGIN RSA PRIVATE KEY-----");
+const QByteArray SshEncryptionFacility::PrivKeyFileStartLineDsa("-----BEGIN DSA PRIVATE KEY-----");
+const QByteArray SshEncryptionFacility::PrivKeyFileEndLineRsa("-----END RSA PRIVATE KEY-----");
+const QByteArray SshEncryptionFacility::PrivKeyFileEndLineDsa("-----END DSA PRIVATE KEY-----");
+
+QByteArray SshEncryptionFacility::cryptAlgoName(const SshKeyExchange &kex) const
+{
+ return kex.encryptionAlgo();
+}
+
+QByteArray SshEncryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
+{
+ return kex.hMacAlgoClientToServer();
+}
+
+BlockCipherMode *SshEncryptionFacility::makeCipherMode(BlockCipher *cipher,
+ BlockCipherModePaddingMethod *paddingMethod, const InitializationVector &iv,
+ const SymmetricKey &key)
+{
+ return new CBC_Encryption(cipher, paddingMethod, key, iv);
+}
+
+void SshEncryptionFacility::encrypt(QByteArray &data) const
+{
+ convert(data, 0, data.size());
+}
+
+void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFileContents)
+{
+ if (privKeyFileContents == m_cachedPrivKeyContents)
+ return;
+
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("%s: Key not cached, reading", Q_FUNC_INFO);
+#endif
+ QList<BigInt> pubKeyParams;
+ QList<BigInt> allKeyParams;
+ try {
+ createAuthenticationKeyFromPKCS8(privKeyFileContents, pubKeyParams,
+ allKeyParams);
+ } catch (Botan::Exception &) {
+ createAuthenticationKeyFromOpenSSL(privKeyFileContents, pubKeyParams,
+ allKeyParams);
+ }
+
+ foreach (const BigInt &b, allKeyParams) {
+ if (b.is_zero()) {
+ throw SshClientException(SshKeyFileError,
+ SSH_TR("Decoding of private key file failed."));
+ }
+ }
+
+ m_authPubKeyBlob = AbstractSshPacket::encodeString(m_authKeyAlgoName);
+ foreach (const BigInt &b, pubKeyParams)
+ m_authPubKeyBlob += AbstractSshPacket::encodeMpInt(b);
+ m_cachedPrivKeyContents = privKeyFileContents;
+}
+
+void SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
+ QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams)
+{
+ Pipe pipe;
+ pipe.process_msg(convertByteArray(privKeyFileContents),
+ privKeyFileContents.size());
+ Private_Key * const key = PKCS8::load_key(pipe, m_rng);
+ if (DSA_PrivateKey * const dsaKey = dynamic_cast<DSA_PrivateKey *>(key)) {
+ m_authKey.reset(dsaKey);
+ pubKeyParams << dsaKey->group_p() << dsaKey->group_q()
+ << dsaKey->group_g() << dsaKey->get_y();
+ allKeyParams << pubKeyParams << dsaKey->get_x();
+ } else if (RSA_PrivateKey * const rsaKey = dynamic_cast<RSA_PrivateKey *>(key)) {
+ m_authKey.reset(rsaKey);
+ pubKeyParams << rsaKey->get_e() << rsaKey->get_n();
+ allKeyParams << pubKeyParams << rsaKey->get_p() << rsaKey->get_q()
+ << rsaKey->get_d();
+ } else {
+ throw Botan::Exception();
+ }
+}
+
+void SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
+ QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams)
+{
+ bool syntaxOk = true;
+ QList<QByteArray> lines = privKeyFileContents.split('\n');
+ while (lines.last().isEmpty())
+ lines.removeLast();
+ if (lines.count() < 3) {
+ syntaxOk = false;
+ } else if (lines.first() == PrivKeyFileStartLineRsa) {
+ if (lines.last() != PrivKeyFileEndLineRsa)
+ syntaxOk =false;
+ else
+ m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
+ } else if (lines.first() == PrivKeyFileStartLineDsa) {
+ if (lines.last() != PrivKeyFileEndLineDsa)
+ syntaxOk = false;
+ else
+ m_authKeyAlgoName = SshCapabilities::PubKeyDss;
+ } else {
+ syntaxOk = false;
+ }
+ if (!syntaxOk) {
+ throw SshClientException(SshKeyFileError,
+ SSH_TR("Private key file has unexpected format."));
+ }
+
+ QByteArray privateKeyBlob;
+ for (int i = 1; i < lines.size() - 1; ++i)
+ privateKeyBlob += lines.at(i);
+ privateKeyBlob = QByteArray::fromBase64(privateKeyBlob);
+
+ BER_Decoder decoder(convertByteArray(privateKeyBlob),
+ privateKeyBlob.size());
+ BER_Decoder sequence = decoder.start_cons(SEQUENCE);
+ quint32 version;
+ sequence.decode (version);
+ if (version != 0) {
+ throw SshClientException(SshKeyFileError,
+ SSH_TR("Private key encoding has version %1, expected 0.")
+ .arg(version));
+ }
+
+ if (m_authKeyAlgoName == SshCapabilities::PubKeyDss) {
+ BigInt p, q, g, y, x;
+ sequence.decode (p).decode (q).decode (g).decode (y).decode (x);
+ DSA_PrivateKey * const dsaKey
+ = new DSA_PrivateKey(m_rng, DL_Group(p, q, g), x);
+ m_authKey.reset(dsaKey);
+ pubKeyParams << p << q << g << y;
+ allKeyParams << pubKeyParams << x;
+ } else {
+ BigInt p, q, e, d, n;
+ sequence.decode (n).decode (e).decode (d).decode (p).decode (q);
+ RSA_PrivateKey * const rsaKey
+ = new RSA_PrivateKey (m_rng, p, q, e, d, n);
+ m_authKey.reset(rsaKey);
+ pubKeyParams << e << n;
+ allKeyParams << pubKeyParams << p << q << d;
+ }
+
+ sequence.discard_remaining();
+ sequence.verify_end();
+}
+
+QByteArray SshEncryptionFacility::authenticationAlgorithmName() const
+{
+ Q_ASSERT(m_authKey);
+ return m_authKeyAlgoName;
+}
+
+QByteArray SshEncryptionFacility::authenticationKeySignature(const QByteArray &data) const
+{
+ Q_ASSERT(m_authKey);
+
+ QScopedPointer<PK_Signer> signer(get_pk_signer (*m_authKey,
+ botanEmsaAlgoName(m_authKeyAlgoName)));
+ QByteArray dataToSign = AbstractSshPacket::encodeString(sessionId()) + data;
+ QByteArray signature
+ = convertByteArray(signer->sign_message(convertByteArray(dataToSign),
+ dataToSign.size(), m_rng));
+ return AbstractSshPacket::encodeString(m_authKeyAlgoName)
+ + AbstractSshPacket::encodeString(signature);
+}
+
+QByteArray SshEncryptionFacility::getRandomNumbers(int count) const
+{
+ QByteArray data;
+ data.resize(count);
+ m_rng.randomize(convertByteArray(data), count);
+ return data;
+}
+
+SshEncryptionFacility::~SshEncryptionFacility() {}
+
+
+QByteArray SshDecryptionFacility::cryptAlgoName(const SshKeyExchange &kex) const
+{
+ return kex.decryptionAlgo();
+}
+
+QByteArray SshDecryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
+{
+ return kex.hMacAlgoServerToClient();
+}
+
+BlockCipherMode *SshDecryptionFacility::makeCipherMode(BlockCipher *cipher,
+ BlockCipherModePaddingMethod *paddingMethod, const InitializationVector &iv,
+ const SymmetricKey &key)
+{
+ return new CBC_Decryption(cipher, paddingMethod, key, iv);
+}
+
+void SshDecryptionFacility::decrypt(QByteArray &data, quint32 offset,
+ quint32 dataSize) const
+{
+ convert(data, offset, dataSize);
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Decrypted data:");
+ const char * const start = data.constData() + offset;
+ const char * const end = start + dataSize;
+ for (const char *c = start; c < end; ++c)
+ qDebug() << "'" << *c << "' (0x" << (static_cast<int>(*c) & 0xff) << ")";
+#endif
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshcryptofacility_p.h b/coreplugin/ssh/sshcryptofacility_p.h
new file mode 100644
index 0000000..f60e6d4
--- /dev/null
+++ b/coreplugin/ssh/sshcryptofacility_p.h
@@ -0,0 +1,154 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHABSTRACTCRYPTOFACILITY_P_H
+#define SSHABSTRACTCRYPTOFACILITY_P_H
+
+#include <botan/auto_rng.h>
+#include <botan/symkey.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QScopedPointer>
+
+namespace Botan {
+ class BigInt;
+ class BlockCipher;
+ class BlockCipherMode;
+ class BlockCipherModePaddingMethod;
+ class HashFunction;
+ class HMAC;
+ class Pipe;
+ class PK_Signing_Key;
+}
+
+namespace Core {
+namespace Internal {
+
+class SshKeyExchange;
+
+class SshAbstractCryptoFacility
+{
+public:
+ virtual ~SshAbstractCryptoFacility();
+
+ void clearKeys();
+ void recreateKeys(const SshKeyExchange &kex);
+ QByteArray generateMac(const QByteArray &data, quint32 dataSize) const;
+ quint32 cipherBlockSize() const { return m_cipherBlockSize; }
+ quint32 macLength() const { return m_macLength; }
+
+protected:
+ SshAbstractCryptoFacility();
+ void convert(QByteArray &data, quint32 offset, quint32 dataSize) const;
+ QByteArray sessionId() const { return m_sessionId; }
+
+private:
+ SshAbstractCryptoFacility(const SshAbstractCryptoFacility &);
+ SshAbstractCryptoFacility &operator=(const SshAbstractCryptoFacility &);
+
+ virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const=0;
+ virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const=0;
+ virtual Botan::BlockCipherMode *makeCipherMode(Botan::BlockCipher *cipher,
+ Botan::BlockCipherModePaddingMethod *paddingMethod,
+ const Botan::InitializationVector &iv,
+ const Botan::SymmetricKey &key)=0;
+ virtual char ivChar() const=0;
+ virtual char keyChar() const=0;
+ virtual char macChar() const=0;
+
+ QByteArray generateHash(const SshKeyExchange &kex, char c, quint32 length);
+ void checkInvariant() const;
+
+ QByteArray m_sessionId;
+ QScopedPointer<Botan::Pipe> m_pipe;
+ QScopedPointer<Botan::HMAC> m_hMac;
+ quint32 m_cipherBlockSize;
+ quint32 m_macLength;
+};
+
+class SshEncryptionFacility : public SshAbstractCryptoFacility
+{
+public:
+ void encrypt(QByteArray &data) const;
+
+ void createAuthenticationKey(const QByteArray &privKeyFileContents);
+ QByteArray authenticationAlgorithmName() const;
+ QByteArray authenticationPublicKey() const { return m_authPubKeyBlob; }
+ QByteArray authenticationKeySignature(const QByteArray &data) const;
+ QByteArray getRandomNumbers(int count) const;
+
+ ~SshEncryptionFacility();
+
+private:
+ virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const;
+ virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const;
+ virtual Botan::BlockCipherMode *makeCipherMode(Botan::BlockCipher *cipher,
+ Botan::BlockCipherModePaddingMethod *paddingMethod,
+ const Botan::InitializationVector &iv, const Botan::SymmetricKey &key);
+ virtual char ivChar() const { return 'A'; }
+ virtual char keyChar() const { return 'C'; }
+ virtual char macChar() const { return 'E'; }
+
+ void createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
+ QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams);
+ void createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
+ QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams);
+
+ static const QByteArray PrivKeyFileStartLineRsa;
+ static const QByteArray PrivKeyFileStartLineDsa;
+ static const QByteArray PrivKeyFileEndLineRsa;
+ static const QByteArray PrivKeyFileEndLineDsa;
+
+ QByteArray m_authKeyAlgoName;
+ QByteArray m_authPubKeyBlob;
+ QByteArray m_cachedPrivKeyContents;
+ QScopedPointer<Botan::PK_Signing_Key> m_authKey;
+ mutable Botan::AutoSeeded_RNG m_rng;
+};
+
+class SshDecryptionFacility : public SshAbstractCryptoFacility
+{
+public:
+ void decrypt(QByteArray &data, quint32 offset, quint32 dataSize) const;
+
+private:
+ virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const;
+ virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const;
+ virtual Botan::BlockCipherMode *makeCipherMode(Botan::BlockCipher *cipher,
+ Botan::BlockCipherModePaddingMethod *paddingMethod,
+ const Botan::InitializationVector &iv, const Botan::SymmetricKey &key);
+ virtual char ivChar() const { return 'B'; }
+ virtual char keyChar() const { return 'D'; }
+ virtual char macChar() const { return 'F'; }
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHABSTRACTCRYPTOFACILITY_P_H
diff --git a/coreplugin/ssh/sshdelayedsignal.cpp b/coreplugin/ssh/sshdelayedsignal.cpp
new file mode 100644
index 0000000..d35075b
--- /dev/null
+++ b/coreplugin/ssh/sshdelayedsignal.cpp
@@ -0,0 +1,165 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshdelayedsignal_p.h"
+
+#include "sftpchannel_p.h"
+#include "sshremoteprocess_p.h"
+
+#include <QtCore/QTimer>
+
+namespace Core {
+namespace Internal {
+
+SshDelayedSignal::SshDelayedSignal(const QWeakPointer<QObject> &checkObject)
+ : m_checkObject(checkObject)
+{
+ QTimer::singleShot(0, this, SLOT(handleTimeout()));
+}
+
+void SshDelayedSignal::handleTimeout()
+{
+ if (!m_checkObject.isNull())
+ emitSignal();
+ deleteLater();
+}
+
+
+SftpDelayedSignal::SftpDelayedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject)
+ : SshDelayedSignal(checkObject), m_privChannel(privChannel) {}
+
+
+SftpInitializationFailedSignal::SftpInitializationFailedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QString &reason)
+ : SftpDelayedSignal(privChannel, checkObject), m_reason(reason) {}
+
+void SftpInitializationFailedSignal::emitSignal()
+{
+ m_privChannel->emitInitializationFailedSignal(m_reason);
+}
+
+
+SftpInitializedSignal::SftpInitializedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject)
+ : SftpDelayedSignal(privChannel, checkObject) {}
+
+void SftpInitializedSignal::emitSignal()
+{
+ m_privChannel->emitInitialized();
+}
+
+
+SftpJobFinishedSignal::SftpJobFinishedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, SftpJobId jobId,
+ const QString &error)
+ : SftpDelayedSignal(privChannel, checkObject), m_jobId(jobId), m_error(error)
+{
+}
+
+void SftpJobFinishedSignal::emitSignal()
+{
+ m_privChannel->emitJobFinished(m_jobId, m_error);
+}
+
+
+SftpDataAvailableSignal::SftpDataAvailableSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, SftpJobId jobId,
+ const QString &data)
+ : SftpDelayedSignal(privChannel, checkObject), m_jobId(jobId), m_data(data) {}
+
+void SftpDataAvailableSignal::emitSignal()
+{
+ m_privChannel->emitDataAvailable(m_jobId, m_data);
+}
+
+
+SftpClosedSignal::SftpClosedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject)
+ : SftpDelayedSignal(privChannel, checkObject) {}
+
+void SftpClosedSignal::emitSignal()
+{
+ m_privChannel->emitClosed();
+}
+
+
+SshRemoteProcessDelayedSignal::SshRemoteProcessDelayedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject)
+ : SshDelayedSignal(checkObject), m_privChannel(privChannel) {}
+
+
+SshRemoteProcessStartedSignal::SshRemoteProcessStartedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject)
+ : SshRemoteProcessDelayedSignal(privChannel, checkObject) {}
+
+void SshRemoteProcessStartedSignal::emitSignal()
+{
+ m_privChannel->emitStartedSignal();
+}
+
+
+SshRemoteProcessOutputAvailableSignal::SshRemoteProcessOutputAvailableSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QByteArray &output)
+ : SshRemoteProcessDelayedSignal(privChannel, checkObject), m_output(output)
+{
+}
+
+void SshRemoteProcessOutputAvailableSignal::emitSignal()
+{
+ m_privChannel->emitOutputAvailableSignal(m_output);
+}
+
+
+SshRemoteProcessErrorOutputAvailableSignal::SshRemoteProcessErrorOutputAvailableSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QByteArray &output)
+ : SshRemoteProcessDelayedSignal(privChannel, checkObject), m_output(output)
+{
+}
+
+void SshRemoteProcessErrorOutputAvailableSignal::emitSignal()
+{
+ m_privChannel->emitErrorOutputAvailableSignal(m_output);
+}
+
+
+SshRemoteProcessClosedSignal::SshRemoteProcessClosedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, int exitStatus)
+ : SshRemoteProcessDelayedSignal(privChannel, checkObject),
+ m_exitStatus(exitStatus)
+{
+}
+
+void SshRemoteProcessClosedSignal::emitSignal()
+{
+ m_privChannel->emitClosedSignal(m_exitStatus);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshdelayedsignal_p.h b/coreplugin/ssh/sshdelayedsignal_p.h
new file mode 100644
index 0000000..09163fb
--- /dev/null
+++ b/coreplugin/ssh/sshdelayedsignal_p.h
@@ -0,0 +1,190 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHDELAYEDSIGNAL_P_H
+#define SSHDELAYEDSIGNAL_P_H
+
+#include "sftpdefs.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QWeakPointer>
+
+namespace Core {
+namespace Internal {
+class SftpChannelPrivate;
+class SshRemoteProcessPrivate;
+
+class SshDelayedSignal : public QObject
+{
+ Q_OBJECT
+public:
+ SshDelayedSignal(const QWeakPointer<QObject> &checkObject);
+
+private:
+ Q_SLOT void handleTimeout();
+ virtual void emitSignal()=0;
+
+ const QWeakPointer<QObject> m_checkObject;
+};
+
+
+class SftpDelayedSignal : public SshDelayedSignal
+{
+public:
+ SftpDelayedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject);
+
+protected:
+ SftpChannelPrivate * const m_privChannel;
+};
+
+class SftpInitializationFailedSignal : public SftpDelayedSignal
+{
+public:
+ SftpInitializationFailedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QString &reason);
+
+private:
+ virtual void emitSignal();
+
+ const QString m_reason;
+};
+
+class SftpInitializedSignal : public SftpDelayedSignal
+{
+public:
+ SftpInitializedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject);
+
+private:
+ virtual void emitSignal();
+};
+
+class SftpJobFinishedSignal : public SftpDelayedSignal
+{
+public:
+ SftpJobFinishedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, SftpJobId jobId,
+ const QString &error);
+
+private:
+ virtual void emitSignal();
+
+ const SftpJobId m_jobId;
+ const QString m_error;
+};
+
+class SftpDataAvailableSignal : public SftpDelayedSignal
+{
+public:
+ SftpDataAvailableSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, SftpJobId jobId,
+ const QString &data);
+
+private:
+ virtual void emitSignal();
+
+ const SftpJobId m_jobId;
+ const QString m_data;
+};
+
+class SftpClosedSignal : public SftpDelayedSignal
+{
+public:
+ SftpClosedSignal(SftpChannelPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject);
+
+private:
+ virtual void emitSignal();
+};
+
+
+class SshRemoteProcessDelayedSignal : public SshDelayedSignal
+{
+public:
+ SshRemoteProcessDelayedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject);
+
+protected:
+ SshRemoteProcessPrivate * const m_privChannel;
+};
+
+class SshRemoteProcessStartedSignal : public SshRemoteProcessDelayedSignal
+{
+public:
+ SshRemoteProcessStartedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject);
+
+private:
+ virtual void emitSignal();
+};
+
+class SshRemoteProcessOutputAvailableSignal
+ : public SshRemoteProcessDelayedSignal
+{
+public:
+ SshRemoteProcessOutputAvailableSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QByteArray &output);
+
+private:
+ virtual void emitSignal();
+
+ const QByteArray m_output;
+};
+
+class SshRemoteProcessErrorOutputAvailableSignal
+ : public SshRemoteProcessDelayedSignal
+{
+public:
+ SshRemoteProcessErrorOutputAvailableSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, const QByteArray &output);
+
+private:
+ virtual void emitSignal();
+
+ const QByteArray m_output;
+};
+
+class SshRemoteProcessClosedSignal : public SshRemoteProcessDelayedSignal
+{
+public:
+ SshRemoteProcessClosedSignal(SshRemoteProcessPrivate *privChannel,
+ const QWeakPointer<QObject> &checkObject, int exitStatus);
+
+private:
+ virtual void emitSignal();
+
+ const int m_exitStatus;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHDELAYEDSIGNAL_P_H
diff --git a/coreplugin/ssh/ssherrors.h b/coreplugin/ssh/ssherrors.h
new file mode 100644
index 0000000..01587ed
--- /dev/null
+++ b/coreplugin/ssh/ssherrors.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHERRORS_P_H
+#define SSHERRORS_P_H
+
+namespace Core {
+
+enum SshError {
+ SshNoError, SshSocketError, SshTimeoutError, SshProtocolError,
+ SshHostKeyError, SshKeyFileError, SshAuthenticationError,
+ SshClosedByServerError, SshInternalError
+};
+
+} // namespace Core
+
+#endif // SSHERRORS_P_H
diff --git a/coreplugin/ssh/sshexception_p.h b/coreplugin/ssh/sshexception_p.h
new file mode 100644
index 0000000..6812fab
--- /dev/null
+++ b/coreplugin/ssh/sshexception_p.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHEXCEPTION_P_H
+#define SSHEXCEPTION_P_H
+
+#include "ssherrors.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+enum SshErrorCode {
+ SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1,
+ SSH_DISCONNECT_PROTOCOL_ERROR = 2,
+ SSH_DISCONNECT_KEY_EXCHANGE_FAILED = 3,
+ SSH_DISCONNECT_RESERVED = 4,
+ SSH_DISCONNECT_MAC_ERROR = 5,
+ SSH_DISCONNECT_COMPRESSION_ERROR = 6,
+ SSH_DISCONNECT_SERVICE_NOT_AVAILABLE = 7,
+ SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8,
+ SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9,
+ SSH_DISCONNECT_CONNECTION_LOST = 10,
+ SSH_DISCONNECT_BY_APPLICATION = 11,
+ SSH_DISCONNECT_TOO_MANY_CONNECTIONS = 12,
+ SSH_DISCONNECT_AUTH_CANCELLED_BY_USER = 13,
+ SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14,
+ SSH_DISCONNECT_ILLEGAL_USER_NAME = 15
+};
+
+#define SSH_TR(string) QCoreApplication::translate("SshConnection", string)
+
+#define SSH_SERVER_EXCEPTION(error, errorString) \
+ SshServerException((error), (errorString), SSH_TR(errorString))
+
+struct SshServerException
+{
+ SshServerException(SshErrorCode error, const QByteArray &errorStringServer,
+ const QString &errorStringUser)
+ : error(error), errorStringServer(errorStringServer),
+ errorStringUser(errorStringUser) {}
+
+ const SshErrorCode error;
+ const QByteArray errorStringServer;
+ const QString errorStringUser;
+};
+
+struct SshClientException
+{
+ SshClientException(SshError error, const QString &errorString)
+ : error(error), errorString(errorString) {}
+
+ const SshError error;
+ const QString errorString;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHEXCEPTION_P_H
diff --git a/coreplugin/ssh/sshincomingpacket.cpp b/coreplugin/ssh/sshincomingpacket.cpp
new file mode 100644
index 0000000..fdc274b
--- /dev/null
+++ b/coreplugin/ssh/sshincomingpacket.cpp
@@ -0,0 +1,442 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshincomingpacket_p.h"
+
+#include "sshcapabilities_p.h"
+
+namespace Core {
+namespace Internal {
+
+const QByteArray SshIncomingPacket::ExitStatusType("exit-status");
+const QByteArray SshIncomingPacket::ExitSignalType("exit-signal");
+
+SshIncomingPacket::SshIncomingPacket() : m_serverSeqNr(0) { }
+
+quint32 SshIncomingPacket::cipherBlockSize() const
+{
+ return qMax(m_decrypter.cipherBlockSize(), 8U);
+}
+
+quint32 SshIncomingPacket::macLength() const
+{
+ return m_decrypter.macLength();
+}
+
+void SshIncomingPacket::recreateKeys(const SshKeyExchange &keyExchange)
+{
+ m_decrypter.recreateKeys(keyExchange);
+}
+
+void SshIncomingPacket::reset()
+{
+ clear();
+ m_serverSeqNr = 0;
+ m_decrypter.clearKeys();
+}
+
+void SshIncomingPacket::consumeData(QByteArray &newData)
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("%s: current data size = %d, new data size = %d",
+ Q_FUNC_INFO, m_data.size(), newData.size());
+#endif
+
+ if (isComplete() || newData.isEmpty())
+ return;
+
+ /*
+ * Until we have reached the minimum packet size, we cannot decrypt the
+ * length field.
+ */
+ const quint32 minSize = minPacketSize();
+ if (currentDataSize() < minSize) {
+ const int bytesToTake
+ = qMin<quint32>(minSize - currentDataSize(), newData.size());
+ moveFirstBytes(m_data, newData, bytesToTake);
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Took %d bytes from new data", bytesToTake);
+#endif
+ if (currentDataSize() < minSize)
+ return;
+ }
+
+ const int bytesToTake
+ = qMin<quint32>(length() + 4 + macLength() - currentDataSize(),
+ newData.size());
+ moveFirstBytes(m_data, newData, bytesToTake);
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Took %d bytes from new data", bytesToTake);
+#endif
+ if (isComplete()) {
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Message complete. Overall size: %u, payload size: %u",
+ m_data.size(), m_length - paddingLength() - 1);
+#endif
+ decrypt();
+ ++m_serverSeqNr;
+ }
+}
+
+void SshIncomingPacket::decrypt()
+{
+ Q_ASSERT(isComplete());
+ const quint32 netDataLength = length() + 4;
+ m_decrypter.decrypt(m_data, cipherBlockSize(),
+ netDataLength - cipherBlockSize());
+ const QByteArray &mac = m_data.mid(netDataLength, macLength());
+ if (mac != generateMac(m_decrypter, m_serverSeqNr)) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_MAC_ERROR,
+ "Message authentication failed.");
+ }
+}
+
+void SshIncomingPacket::moveFirstBytes(QByteArray &target, QByteArray &source,
+ int n)
+{
+ target.append(source.left(n));
+ source.remove(0, n);
+}
+
+SshKeyExchangeInit SshIncomingPacket::extractKeyExchangeInitData() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_KEXINIT);
+
+ SshKeyExchangeInit exchangeData;
+ try {
+ quint32 offset = TypeOffset + 1;
+ std::memcpy(exchangeData.cookie, &m_data.constData()[offset],
+ sizeof exchangeData.cookie);
+ offset += sizeof exchangeData.cookie;
+ exchangeData.keyAlgorithms
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.serverHostKeyAlgorithms
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.encryptionAlgorithmsClientToServer
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.encryptionAlgorithmsServerToClient
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.macAlgorithmsClientToServer
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.macAlgorithmsServerToClient
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.compressionAlgorithmsClientToServer
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.compressionAlgorithmsServerToClient
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.languagesClientToServer
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.languagesServerToClient
+ = SshPacketParser::asNameList(m_data, &offset);
+ exchangeData.firstKexPacketFollows
+ = SshPacketParser::asBool(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Key exchange failed: Server sent invalid SSH_MSG_KEXINIT packet.");
+ }
+ return exchangeData;
+}
+
+SshKeyExchangeReply SshIncomingPacket::extractKeyExchangeReply(const QByteArray &pubKeyAlgo) const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_KEXDH_REPLY);
+
+ try {
+ SshKeyExchangeReply replyData;
+ quint32 offset = TypeOffset + 1;
+ const quint32 k_sLength
+ = SshPacketParser::asUint32(m_data, &offset);
+ if (offset + k_sLength > currentDataSize())
+ throw SshPacketParseException();
+ replyData.k_s = m_data.mid(offset - 4, k_sLength + 4);
+ if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo)
+ throw SshPacketParseException();
+
+ // DSS: p and q, RSA: e and n
+ replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
+ replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
+
+ // g and y
+ if (pubKeyAlgo == SshCapabilities::PubKeyDss) {
+ replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
+ replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
+ }
+
+ replyData.f = SshPacketParser::asBigInt(m_data, &offset);
+ offset += 4;
+ if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo)
+ throw SshPacketParseException();
+ replyData.signatureBlob = SshPacketParser::asString(m_data, &offset);
+ return replyData;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Key exchange failed: "
+ "Server sent invalid SSH_MSG_KEXDH_REPLY packet.");
+ }
+}
+
+SshDisconnect SshIncomingPacket::extractDisconnect() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_DISCONNECT);
+
+ SshDisconnect msg;
+ try {
+ quint32 offset = TypeOffset + 1;
+ msg.reasonCode = SshPacketParser::asUint32(m_data, &offset);
+ msg.description = SshPacketParser::asUserString(m_data, &offset);
+ msg.language = SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_DISCONNECT.");
+ }
+
+ return msg;
+}
+
+SshUserAuthBanner SshIncomingPacket::extractUserAuthBanner() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_USERAUTH_BANNER);
+
+ try {
+ SshUserAuthBanner msg;
+ quint32 offset = TypeOffset + 1;
+ msg.message = SshPacketParser::asUserString(m_data, &offset);
+ msg.language = SshPacketParser::asString(m_data, &offset);
+ return msg;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_USERAUTH_BANNER.");
+ }
+}
+
+SshDebug SshIncomingPacket::extractDebug() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_DEBUG);
+
+ try {
+ SshDebug msg;
+ quint32 offset = TypeOffset + 1;
+ msg.display = SshPacketParser::asBool(m_data, &offset);
+ msg.message = SshPacketParser::asUserString(m_data, &offset);
+ msg.language = SshPacketParser::asString(m_data, &offset);
+ return msg;
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_USERAUTH_BANNER.");
+ }
+}
+
+SshChannelOpenFailure SshIncomingPacket::extractChannelOpenFailure() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_FAILURE);
+
+ SshChannelOpenFailure openFailure;
+ try {
+ quint32 offset = TypeOffset + 1;
+ openFailure.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ openFailure.reasonCode = SshPacketParser::asUint32(m_data, &offset);
+ openFailure.reasonString = SshPacketParser::asString(m_data, &offset);
+ openFailure.language = SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Server sent invalid SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
+ }
+ return openFailure;
+}
+
+SshChannelOpenConfirmation SshIncomingPacket::extractChannelOpenConfirmation() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+
+ SshChannelOpenConfirmation confirmation;
+ try {
+ quint32 offset = TypeOffset + 1;
+ confirmation.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ confirmation.remoteChannel = SshPacketParser::asUint32(m_data, &offset);
+ confirmation.remoteWindowSize = SshPacketParser::asUint32(m_data, &offset);
+ confirmation.remoteMaxPacketSize = SshPacketParser::asUint32(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Server sent invalid SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet.");
+ }
+ return confirmation;
+}
+
+SshChannelWindowAdjust SshIncomingPacket::extractWindowAdjust() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_WINDOW_ADJUST);
+
+ SshChannelWindowAdjust adjust;
+ try {
+ quint32 offset = TypeOffset + 1;
+ adjust.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ adjust.bytesToAdd = SshPacketParser::asUint32(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_WINDOW_ADJUST packet.");
+ }
+ return adjust;
+}
+
+SshChannelData SshIncomingPacket::extractChannelData() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_DATA);
+
+ SshChannelData data;
+ try {
+ quint32 offset = TypeOffset + 1;
+ data.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ data.data = SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_DATA packet.");
+ }
+ return data;
+}
+
+SshChannelExtendedData SshIncomingPacket::extractChannelExtendedData() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_EXTENDED_DATA);
+
+ SshChannelExtendedData data;
+ try {
+ quint32 offset = TypeOffset + 1;
+ data.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ data.type = SshPacketParser::asUint32(m_data, &offset);
+ data.data = SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_EXTENDED_DATA packet.");
+ }
+ return data;
+}
+
+SshChannelExitStatus SshIncomingPacket::extractChannelExitStatus() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
+
+ SshChannelExitStatus exitStatus;
+ try {
+ quint32 offset = TypeOffset + 1;
+ exitStatus.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ const QByteArray &type = SshPacketParser::asString(m_data, &offset);
+ Q_ASSERT(type == ExitStatusType);
+ if (SshPacketParser::asBool(m_data, &offset))
+ throw SshPacketParseException();
+ exitStatus.exitStatus = SshPacketParser::asUint32(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid exit-status packet.");
+ }
+ return exitStatus;
+}
+
+SshChannelExitSignal SshIncomingPacket::extractChannelExitSignal() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
+
+ SshChannelExitSignal exitSignal;
+ try {
+ quint32 offset = TypeOffset + 1;
+ exitSignal.localChannel = SshPacketParser::asUint32(m_data, &offset);
+ const QByteArray &type = SshPacketParser::asString(m_data, &offset);
+ Q_ASSERT(type == ExitSignalType);
+ if (SshPacketParser::asBool(m_data, &offset))
+ throw SshPacketParseException();
+ exitSignal.signal = SshPacketParser::asString(m_data, &offset);
+ exitSignal.coreDumped = SshPacketParser::asBool(m_data, &offset);
+ exitSignal.error = SshPacketParser::asUserString(m_data, &offset);
+ exitSignal.language = SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid exit-signal packet.");
+ }
+ return exitSignal;
+}
+
+quint32 SshIncomingPacket::extractRecipientChannel() const
+{
+ Q_ASSERT(isComplete());
+
+ try {
+ quint32 offset = TypeOffset + 1;
+ return SshPacketParser::asUint32(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Server sent invalid packet.");
+ }
+}
+
+QByteArray SshIncomingPacket::extractChannelRequestType() const
+{
+ Q_ASSERT(isComplete());
+ Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
+
+ try {
+ quint32 offset = TypeOffset + 1;
+ SshPacketParser::asUint32(m_data, &offset);
+ return SshPacketParser::asString(m_data, &offset);
+ } catch (SshPacketParseException &) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Invalid SSH_MSG_CHANNEL_REQUEST packet.");
+ }
+}
+
+void SshIncomingPacket::calculateLength() const
+{
+ Q_ASSERT(currentDataSize() >= minPacketSize());
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Length field before decryption: %d-%d-%d-%d", m_data.at(0) & 0xff,
+ m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff);
+#endif
+ m_decrypter.decrypt(m_data, 0, cipherBlockSize());
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Length field after decryption: %d-%d-%d-%d", m_data.at(0) & 0xff, m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff);
+ qDebug("message type = %d", m_data.at(TypeOffset));
+#endif
+ m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("decrypted length is %u", m_length);
+#endif
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshincomingpacket_p.h b/coreplugin/ssh/sshincomingpacket_p.h
new file mode 100644
index 0000000..9b10c8f
--- /dev/null
+++ b/coreplugin/ssh/sshincomingpacket_p.h
@@ -0,0 +1,186 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHINCOMINGPACKET_P_H
+#define SSHINCOMINGPACKET_P_H
+
+#include "sshpacket_p.h"
+
+#include "sshcryptofacility_p.h"
+#include "sshpacketparser_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+class SshKeyExchange;
+
+struct SshKeyExchangeInit
+{
+ char cookie[16];
+ SshNameList keyAlgorithms;
+ SshNameList serverHostKeyAlgorithms;
+ SshNameList encryptionAlgorithmsClientToServer;
+ SshNameList encryptionAlgorithmsServerToClient;
+ SshNameList macAlgorithmsClientToServer;
+ SshNameList macAlgorithmsServerToClient;
+ SshNameList compressionAlgorithmsClientToServer;
+ SshNameList compressionAlgorithmsServerToClient;
+ SshNameList languagesClientToServer;
+ SshNameList languagesServerToClient;
+ bool firstKexPacketFollows;
+};
+
+struct SshKeyExchangeReply
+{
+ QByteArray k_s;
+ QList<Botan::BigInt> parameters; // DSS: p, q, g, y. RSA: e, n.
+ Botan::BigInt f;
+ QByteArray signatureBlob;
+};
+
+struct SshDisconnect
+{
+ quint32 reasonCode;
+ QString description;
+ QByteArray language;
+};
+
+struct SshUserAuthBanner
+{
+ QString message;
+ QByteArray language;
+};
+
+struct SshDebug
+{
+ bool display;
+ QString message;
+ QByteArray language;
+};
+
+struct SshChannelOpenFailure
+{
+ quint32 localChannel;
+ quint32 reasonCode;
+ QString reasonString;
+ QByteArray language;
+};
+
+struct SshChannelOpenConfirmation
+{
+ quint32 localChannel;
+ quint32 remoteChannel;
+ quint32 remoteWindowSize;
+ quint32 remoteMaxPacketSize;
+};
+
+struct SshChannelWindowAdjust
+{
+ quint32 localChannel;
+ quint32 bytesToAdd;
+};
+
+struct SshChannelData
+{
+ quint32 localChannel;
+ QByteArray data;
+};
+
+struct SshChannelExtendedData
+{
+ quint32 localChannel;
+ quint32 type;
+ QByteArray data;
+};
+
+struct SshChannelExitStatus
+{
+ quint32 localChannel;
+ quint32 exitStatus;
+};
+
+struct SshChannelExitSignal
+{
+ quint32 localChannel;
+ QByteArray signal;
+ bool coreDumped;
+ QString error;
+ QByteArray language;
+};
+
+
+class SshIncomingPacket : public AbstractSshPacket
+{
+public:
+ SshIncomingPacket();
+
+ void consumeData(QByteArray &data);
+ void recreateKeys(const SshKeyExchange &keyExchange);
+ void reset();
+
+ SshKeyExchangeInit extractKeyExchangeInitData() const;
+ SshKeyExchangeReply extractKeyExchangeReply(const QByteArray &pubKeyAlgo) const;
+ SshDisconnect extractDisconnect() const;
+ SshUserAuthBanner extractUserAuthBanner() const;
+ SshDebug extractDebug() const;
+
+ SshChannelOpenFailure extractChannelOpenFailure() const;
+ SshChannelOpenConfirmation extractChannelOpenConfirmation() const;
+ SshChannelWindowAdjust extractWindowAdjust() const;
+ SshChannelData extractChannelData() const;
+ SshChannelExtendedData extractChannelExtendedData() const;
+ SshChannelExitStatus extractChannelExitStatus() const;
+ SshChannelExitSignal extractChannelExitSignal() const;
+ quint32 extractRecipientChannel() const;
+ QByteArray extractChannelRequestType() const;
+
+ quint32 serverSeqNr() const { return m_serverSeqNr; }
+
+ static const QByteArray ExitStatusType;
+ static const QByteArray ExitSignalType;
+
+private:
+ virtual quint32 cipherBlockSize() const;
+ virtual quint32 macLength() const;
+ virtual void calculateLength() const;
+
+ void decrypt();
+ void moveFirstBytes(QByteArray &target, QByteArray &source, int n);
+
+ quint32 m_serverSeqNr;
+ SshDecryptionFacility m_decrypter;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHINCOMINGPACKET_P_H
diff --git a/coreplugin/ssh/sshkeyexchange.cpp b/coreplugin/ssh/sshkeyexchange.cpp
new file mode 100644
index 0000000..7875d2e
--- /dev/null
+++ b/coreplugin/ssh/sshkeyexchange.cpp
@@ -0,0 +1,197 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshkeyexchange_p.h"
+
+#include "sshbotanconversions_p.h"
+#include "sshcapabilities_p.h"
+#include "sshsendfacility_p.h"
+#include "sshexception_p.h"
+#include "sshincomingpacket_p.h"
+
+#include <botan/botan.h>
+#include <botan/dsa.h>
+#include <botan/look_pk.h>
+#include <botan/pubkey.h>
+#include <botan/rsa.h>
+
+#include <string>
+
+using namespace Botan;
+
+namespace Core {
+namespace Internal {
+
+namespace {
+
+ // For debugging
+ void printNameList(const char *listName, const SshNameList &list)
+ {
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("%s:", listName);
+ foreach (const QByteArray &name, list.names)
+ qDebug("%s", name.constData());
+#else
+ Q_UNUSED(listName);
+ Q_UNUSED(list);
+#endif
+ }
+} // anonymous namespace
+
+SshKeyExchange::SshKeyExchange(SshSendFacility &sendFacility)
+ : m_sendFacility(sendFacility)
+{
+}
+
+SshKeyExchange::~SshKeyExchange() {}
+
+void SshKeyExchange::sendKexInitPacket(const QByteArray &serverId)
+{
+ m_serverId = serverId;
+ const AbstractSshPacket::Payload &payload
+ = m_sendFacility.sendKeyExchangeInitPacket();
+ m_clientKexInitPayload = QByteArray(payload.data, payload.size);
+}
+
+bool SshKeyExchange::sendDhInitPacket(const SshIncomingPacket &serverKexInit)
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("server requests key exchange");
+#endif
+ serverKexInit.printRawBytes();
+ SshKeyExchangeInit kexInitParams
+ = serverKexInit.extractKeyExchangeInitData();
+
+ printNameList("Key Algorithms", kexInitParams.keyAlgorithms);
+ printNameList("Server Host Key Algorithms", kexInitParams.serverHostKeyAlgorithms);
+ printNameList("Encryption algorithms client to server", kexInitParams.encryptionAlgorithmsClientToServer);
+ printNameList("Encryption algorithms server to client", kexInitParams.encryptionAlgorithmsServerToClient);
+ printNameList("MAC algorithms client to server", kexInitParams.macAlgorithmsClientToServer);
+ printNameList("MAC algorithms server to client", kexInitParams.macAlgorithmsServerToClient);
+ printNameList("Compression algorithms client to server", kexInitParams.compressionAlgorithmsClientToServer);
+ printNameList("Compression algorithms client to server", kexInitParams.compressionAlgorithmsClientToServer);
+ printNameList("Languages client to server", kexInitParams.languagesClientToServer);
+ printNameList("Languages server to client", kexInitParams.languagesServerToClient);
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("First packet follows: %d", kexInitParams.firstKexPacketFollows);
+#endif
+
+ const QByteArray &keyAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::KeyExchangeMethods,
+ kexInitParams.keyAlgorithms.names);
+ m_serverHostKeyAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::PublicKeyAlgorithms,
+ kexInitParams.serverHostKeyAlgorithms.names);
+ m_encryptionAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
+ kexInitParams.encryptionAlgorithmsClientToServer.names);
+ m_decryptionAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
+ kexInitParams.encryptionAlgorithmsServerToClient.names);
+ m_c2sHMacAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::MacAlgorithms,
+ kexInitParams.macAlgorithmsClientToServer.names);
+ m_s2cHMacAlgo
+ = SshCapabilities::findBestMatch(SshCapabilities::MacAlgorithms,
+ kexInitParams.macAlgorithmsServerToClient.names);
+ SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
+ kexInitParams.compressionAlgorithmsClientToServer.names);
+ SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
+ kexInitParams.compressionAlgorithmsServerToClient.names);
+
+ AutoSeeded_RNG rng;
+ m_dhKey.reset(new DH_PrivateKey(rng,
+ DL_Group(botanKeyExchangeAlgoName(keyAlgo))));
+
+ const AbstractSshPacket::Payload &payload = serverKexInit.payLoad();
+ m_serverKexInitPayload = QByteArray(payload.data, payload.size);
+ m_sendFacility.sendKeyDhInitPacket(m_dhKey->get_y());
+ return kexInitParams.firstKexPacketFollows;
+}
+
+void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
+ const QByteArray &clientId)
+{
+ const SshKeyExchangeReply &reply
+ = dhReply.extractKeyExchangeReply(m_serverHostKeyAlgo);
+ if (reply.f <= 0 || reply.f >= m_dhKey->group_p()) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Server sent invalid f.");
+ }
+
+ QByteArray concatenatedData = AbstractSshPacket::encodeString(clientId);
+ concatenatedData += AbstractSshPacket::encodeString(m_serverId);
+ concatenatedData += AbstractSshPacket::encodeString(m_clientKexInitPayload);
+ concatenatedData += AbstractSshPacket::encodeString(m_serverKexInitPayload);
+ concatenatedData += reply.k_s;
+ concatenatedData += AbstractSshPacket::encodeMpInt(m_dhKey->get_y());
+ concatenatedData += AbstractSshPacket::encodeMpInt(reply.f);
+ SymmetricKey k = m_dhKey->derive_key(reply.f);
+ m_k = AbstractSshPacket::encodeMpInt(BigInt(k.begin(), k.length()));
+ concatenatedData += m_k;
+
+ m_hash.reset(get_hash(botanSha1Name()));
+ const SecureVector<byte> &hashResult
+ = m_hash->process(convertByteArray(concatenatedData),
+ concatenatedData.size());
+ m_h = convertByteArray(hashResult);
+
+ QScopedPointer<Public_Key> sigKey;
+ QScopedPointer<PK_Verifier> verifier;
+ if (m_serverHostKeyAlgo == SshCapabilities::PubKeyDss) {
+ const DL_Group group(reply.parameters.at(0), reply.parameters.at(1),
+ reply.parameters.at(2));
+ DSA_PublicKey * const dsaKey
+ = new DSA_PublicKey(group, reply.parameters.at(3));
+ sigKey.reset(dsaKey);
+ verifier.reset(get_pk_verifier(*dsaKey,
+ botanEmsaAlgoName(SshCapabilities::PubKeyDss)));
+ } else if (m_serverHostKeyAlgo == SshCapabilities::PubKeyRsa) {
+ RSA_PublicKey * const rsaKey
+ = new RSA_PublicKey(reply.parameters.at(1), reply.parameters.at(0));
+ sigKey.reset(rsaKey);
+ verifier.reset(get_pk_verifier(*rsaKey,
+ botanEmsaAlgoName(SshCapabilities::PubKeyRsa)));
+ } else {
+ Q_ASSERT(!"Impossible: Neither DSS nor RSA!");
+ }
+ const byte * const botanH = convertByteArray(m_h);
+ const Botan::byte * const botanSig
+ = convertByteArray(reply.signatureBlob);
+ if (!verifier->verify_message(botanH, m_h.size(), botanSig,
+ reply.signatureBlob.size())) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Invalid signature in SSH_MSG_KEXDH_REPLY packet.");
+ }
+
+ m_sendFacility.sendNewKeysPacket();
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshkeyexchange_p.h b/coreplugin/ssh/sshkeyexchange_p.h
new file mode 100644
index 0000000..076f5be
--- /dev/null
+++ b/coreplugin/ssh/sshkeyexchange_p.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHKEYEXCHANGE_P_H
+#define SSHKEYEXCHANGE_P_H
+
+#include <botan/dh.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QScopedPointer>
+
+namespace Botan { class HashFunction; }
+
+namespace Core {
+namespace Internal {
+
+class SshSendFacility;
+class SshIncomingPacket;
+
+class SshKeyExchange
+{
+public:
+ SshKeyExchange(SshSendFacility &sendFacility);
+ ~SshKeyExchange();
+
+ void sendKexInitPacket(const QByteArray &serverId);
+
+ // Returns true <=> the server sends a guessed package.
+ bool sendDhInitPacket(const SshIncomingPacket &serverKexInit);
+
+ void sendNewKeysPacket(const SshIncomingPacket &dhReply,
+ const QByteArray &clientId);
+
+ QByteArray k() const { return m_k; }
+ QByteArray h() const { return m_h; }
+ Botan::HashFunction *hash() const { return m_hash.data(); }
+ QByteArray encryptionAlgo() const { return m_encryptionAlgo; }
+ QByteArray decryptionAlgo() const { return m_decryptionAlgo; }
+ QByteArray hMacAlgoClientToServer() const { return m_c2sHMacAlgo; }
+ QByteArray hMacAlgoServerToClient() const { return m_s2cHMacAlgo; }
+
+private:
+ QByteArray m_serverId;
+ QByteArray m_clientKexInitPayload;
+ QByteArray m_serverKexInitPayload;
+ QScopedPointer<Botan::DH_PrivateKey> m_dhKey;
+ QByteArray m_k;
+ QByteArray m_h;
+ QByteArray m_serverHostKeyAlgo;
+ QByteArray m_encryptionAlgo;
+ QByteArray m_decryptionAlgo;
+ QByteArray m_c2sHMacAlgo;
+ QByteArray m_s2cHMacAlgo;
+ QScopedPointer<Botan::HashFunction> m_hash;
+ SshSendFacility &m_sendFacility;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHKEYEXCHANGE_P_H
diff --git a/coreplugin/ssh/sshkeygenerator.cpp b/coreplugin/ssh/sshkeygenerator.cpp
new file mode 100644
index 0000000..976d009
--- /dev/null
+++ b/coreplugin/ssh/sshkeygenerator.cpp
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshkeygenerator.h"
+
+#include "sshbotanconversions_p.h"
+#include "sshcapabilities_p.h"
+#include "sshpacket_p.h"
+
+#include <botan/auto_rng.h>
+#include <botan/bigint.h>
+#include <botan/der_enc.h>
+#include <botan/dsa.h>
+#include <botan/pem.h>
+#include <botan/pkcs8.h>
+#include <botan/rsa.h>
+#include <botan/x509_key.h>
+
+#include <QtCore/QDateTime>
+
+namespace Core {
+
+using namespace Botan;
+using namespace Internal;
+
+SshKeyGenerator::SshKeyGenerator() { }
+
+bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format,
+ int keySize)
+{
+ try {
+ AutoSeeded_RNG rng;
+ KeyPtr key;
+ if (type == Rsa)
+ key = KeyPtr(new RSA_PrivateKey(rng, keySize));
+ else
+ key = KeyPtr(new DSA_PrivateKey(rng, DL_Group(rng, DL_Group::Strong,
+ keySize)));
+ return format == Pkcs8
+ ? generatePkcs8Keys(key) : generateOpenSslKeys(key, type);
+ } catch (Botan::Exception &e) {
+ m_error = tr("Error generating key: %1").arg(e.what());
+ return false;
+ }
+}
+
+bool SshKeyGenerator::generatePkcs8Keys(const KeyPtr &key)
+{
+ generatePkcs8Key(key, false);
+ generatePkcs8Key(key, true);
+ return true;
+}
+
+void SshKeyGenerator::generatePkcs8Key(const KeyPtr &key, bool privateKey)
+{
+ Pipe pipe;
+ pipe.start_msg();
+ QByteArray *keyData;
+ if (privateKey) {
+ PKCS8::encode(*key, pipe);
+ keyData = &m_privateKey;
+ } else {
+ X509::encode(*key, pipe);
+ keyData = &m_publicKey;
+ }
+ pipe.end_msg();
+ keyData->resize(pipe.remaining(pipe.message_count() - 1));
+ pipe.read(convertByteArray(*keyData), keyData->size(),
+ pipe.message_count() - 1);
+}
+
+bool SshKeyGenerator::generateOpenSslKeys(const KeyPtr &key, KeyType type)
+{
+ QList<BigInt> publicParams;
+ QList<BigInt> allParams;
+ QByteArray keyId;
+ if (type == Rsa) {
+ const QSharedPointer<RSA_PrivateKey> rsaKey
+ = key.dynamicCast<RSA_PrivateKey>();
+ publicParams << rsaKey->get_e() << rsaKey->get_n();
+ allParams << rsaKey->get_n() << rsaKey->get_e() << rsaKey->get_d()
+ << rsaKey->get_p() << rsaKey->get_q();
+ keyId = SshCapabilities::PubKeyRsa;
+ } else {
+ const QSharedPointer<DSA_PrivateKey> dsaKey
+ = key.dynamicCast<DSA_PrivateKey>();
+ publicParams << dsaKey->group_p() << dsaKey->group_q()
+ << dsaKey->group_g() << dsaKey->get_y();
+ allParams << publicParams << dsaKey->get_x();
+ keyId = SshCapabilities::PubKeyDss;
+ }
+
+ QByteArray publicKeyBlob = AbstractSshPacket::encodeString(keyId);
+ foreach (const BigInt &b, publicParams)
+ publicKeyBlob += AbstractSshPacket::encodeMpInt(b);
+ publicKeyBlob = publicKeyBlob.toBase64();
+ const QByteArray id = "QtCreator/"
+ + QDateTime::currentDateTime().toString(Qt::ISODate).toUtf8();
+ m_publicKey = keyId + ' ' + publicKeyBlob + ' ' + id;
+
+ DER_Encoder encoder;
+ encoder.start_cons(SEQUENCE).encode (0U);
+ foreach (const BigInt &b, allParams)
+ encoder.encode(b);
+ encoder.end_cons();
+ const char * const label
+ = type == Rsa ? "RSA PRIVATE KEY" : "DSA PRIVATE KEY";
+ m_privateKey
+ = QByteArray(PEM_Code::encode (encoder.get_contents(), label).c_str());
+ return true;
+}
+
+} // namespace Core
diff --git a/coreplugin/ssh/sshkeygenerator.h b/coreplugin/ssh/sshkeygenerator.h
new file mode 100644
index 0000000..ada0615
--- /dev/null
+++ b/coreplugin/ssh/sshkeygenerator.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHKEYGENERATOR_H
+#define SSHKEYGENERATOR_H
+
+#include <coreplugin/core_global.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QSharedPointer>
+
+namespace Botan {
+ class Private_Key;
+}
+
+namespace Core {
+
+class CORE_EXPORT SshKeyGenerator
+{
+ Q_DECLARE_TR_FUNCTIONS(SshKeyGenerator)
+public:
+ enum KeyType { Rsa, Dsa };
+ enum PrivateKeyFormat { Pkcs8, OpenSsl };
+
+ SshKeyGenerator();
+ bool generateKeys(KeyType type, PrivateKeyFormat format, int keySize);
+ QString error() const { return m_error; }
+ QByteArray privateKey() const { return m_privateKey; }
+ QByteArray publicKey() const { return m_publicKey; }
+ KeyType type() const { return m_type; }
+ PrivateKeyFormat format() const { return m_format; }
+
+private:
+ typedef QSharedPointer<Botan::Private_Key> KeyPtr;
+
+ bool generatePkcs8Keys(const KeyPtr &key);
+ void generatePkcs8Key(const KeyPtr &key, bool privateKey);
+ bool generateOpenSslKeys(const KeyPtr &key, KeyType type);
+
+ QString m_error;
+ QByteArray m_publicKey;
+ QByteArray m_privateKey;
+ KeyType m_type;
+ PrivateKeyFormat m_format;
+};
+
+} // namespace Core
+
+#endif // SSHKEYGENERATOR_H
diff --git a/coreplugin/ssh/sshoutgoingpacket.cpp b/coreplugin/ssh/sshoutgoingpacket.cpp
new file mode 100644
index 0000000..c6cf994
--- /dev/null
+++ b/coreplugin/ssh/sshoutgoingpacket.cpp
@@ -0,0 +1,284 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshoutgoingpacket_p.h"
+
+#include "sshcapabilities_p.h"
+#include "sshcryptofacility_p.h"
+
+#include <QtCore/QtEndian>
+
+namespace Core {
+namespace Internal {
+
+SshOutgoingPacket::SshOutgoingPacket(const SshEncryptionFacility &encrypter,
+ const quint32 &seqNr) : m_encrypter(encrypter), m_seqNr(seqNr)
+{
+}
+
+quint32 SshOutgoingPacket::cipherBlockSize() const
+{
+ return qMax(m_encrypter.cipherBlockSize(), 4U);
+}
+
+quint32 SshOutgoingPacket::macLength() const
+{
+ return m_encrypter.macLength();
+}
+
+void SshOutgoingPacket::generateKeyExchangeInitPacket()
+{
+ const QByteArray &supportedkeyExchangeMethods
+ = encodeNameList(SshCapabilities::KeyExchangeMethods);
+ const QByteArray &supportedPublicKeyAlgorithms
+ = encodeNameList(SshCapabilities::PublicKeyAlgorithms);
+ const QByteArray &supportedEncryptionAlgorithms
+ = encodeNameList(SshCapabilities::EncryptionAlgorithms);
+ const QByteArray &supportedMacAlgorithms
+ = encodeNameList(SshCapabilities::MacAlgorithms);
+ const QByteArray &supportedCompressionAlgorithms
+ = encodeNameList(SshCapabilities::CompressionAlgorithms);
+ const QByteArray &supportedLanguages = encodeNameList(QList<QByteArray>());
+
+ init(SSH_MSG_KEXINIT);
+ m_data += m_encrypter.getRandomNumbers(16);
+ m_data.append(supportedkeyExchangeMethods);
+ m_data.append(supportedPublicKeyAlgorithms);
+ m_data.append(supportedEncryptionAlgorithms)
+ .append(supportedEncryptionAlgorithms);
+ m_data.append(supportedMacAlgorithms).append(supportedMacAlgorithms);
+ m_data.append(supportedCompressionAlgorithms)
+ .append(supportedCompressionAlgorithms);
+ m_data.append(supportedLanguages).append(supportedLanguages);
+ appendBool(false); // No guessed packet.
+ m_data.append(QByteArray(4, 0)); // Reserved.
+ finalize();
+}
+
+void SshOutgoingPacket::generateKeyDhInitPacket(const Botan::BigInt &e)
+{
+ init(SSH_MSG_KEXDH_INIT).appendMpInt(e).finalize();
+}
+
+void SshOutgoingPacket::generateNewKeysPacket()
+{
+ init(SSH_MSG_NEWKEYS).finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthServiceRequestPacket()
+{
+ generateServiceRequest("ssh-userauth");
+}
+
+void SshOutgoingPacket::generateServiceRequest(const QByteArray &service)
+{
+ init(SSH_MSG_SERVICE_REQUEST).appendString(service).finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthByPwdRequestPacket(const QByteArray &user,
+ const QByteArray &service, const QByteArray &pwd)
+{
+ init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
+ .appendString("password").appendBool(false).appendString(pwd)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthByKeyRequestPacket(const QByteArray &user,
+ const QByteArray &service)
+{
+ init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
+ .appendString("publickey").appendBool(true)
+ .appendString(m_encrypter.authenticationAlgorithmName())
+ .appendString(m_encrypter.authenticationPublicKey());
+ const QByteArray &dataToSign = m_data.mid(PayloadOffset);
+ appendString(m_encrypter.authenticationKeySignature(dataToSign));
+ finalize();
+}
+
+void SshOutgoingPacket::generateRequestFailurePacket()
+{
+ init(SSH_MSG_REQUEST_FAILURE).finalize();
+}
+
+void SshOutgoingPacket::generateSessionPacket(quint32 channelId,
+ quint32 windowSize, quint32 maxPacketSize)
+{
+ init(SSH_MSG_CHANNEL_OPEN).appendString("session").appendInt(channelId)
+ .appendInt(windowSize).appendInt(maxPacketSize).finalize();
+}
+
+void SshOutgoingPacket::generateEnvPacket(quint32 remoteChannel,
+ const QByteArray &var, const QByteArray &value)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel).appendString("env")
+ .appendBool(false).appendString(var).appendString(value);
+}
+
+void SshOutgoingPacket::generateExecPacket(quint32 remoteChannel,
+ const QByteArray &command)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel).appendString("exec")
+ .appendBool(true).appendString(command).finalize();
+}
+
+void SshOutgoingPacket::generateSftpPacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel)
+ .appendString("subsystem").appendBool(true).appendString("sftp")
+ .finalize();
+}
+
+void SshOutgoingPacket::generateWindowAdjustPacket(quint32 remoteChannel,
+ quint32 bytesToAdd)
+{
+ init(SSH_MSG_CHANNEL_WINDOW_ADJUST).appendInt(remoteChannel)
+ .appendInt(bytesToAdd).finalize();
+}
+
+void SshOutgoingPacket::generateChannelDataPacket(quint32 remoteChannel,
+ const QByteArray &data)
+{
+ init(SSH_MSG_CHANNEL_DATA).appendInt(remoteChannel).appendString(data)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateChannelSignalPacket(quint32 remoteChannel,
+ const QByteArray &signalName)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel)
+ .appendString("signal").appendBool(false).appendString(signalName)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateChannelEofPacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_EOF).appendInt(remoteChannel).finalize();
+}
+
+void SshOutgoingPacket::generateChannelClosePacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_CLOSE).appendInt(remoteChannel).finalize();
+}
+
+void SshOutgoingPacket::generateDisconnectPacket(SshErrorCode reason,
+ const QByteArray &reasonString)
+{
+ init(SSH_MSG_DISCONNECT).appendInt(reason).appendString(reasonString)
+ .appendString(QByteArray()).finalize();
+}
+
+void SshOutgoingPacket::generateMsgUnimplementedPacket(quint32 serverSeqNr)
+{
+ init(SSH_MSG_UNIMPLEMENTED).appendInt(serverSeqNr).finalize();
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendInt(quint32 val)
+{
+ m_data.append(encodeInt(val));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendMpInt(const Botan::BigInt &number)
+{
+ m_data.append(encodeMpInt(number));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendBool(bool b)
+{
+ m_data += static_cast<char>(b);
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendString(const QByteArray &string)
+{
+ m_data.append(encodeString(string));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::init(SshPacketType type)
+{
+ m_data.resize(TypeOffset + 1);
+ m_data[TypeOffset] = type;
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::setPadding()
+{
+ m_data += m_encrypter.getRandomNumbers(MinPaddingLength);
+ int padLength = MinPaddingLength;
+ const int divisor = sizeDivisor();
+ const int mod = m_data.size() % divisor;
+ padLength += divisor - mod;
+ m_data += m_encrypter.getRandomNumbers(padLength - MinPaddingLength);
+ m_data[PaddingLengthOffset] = padLength;
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::encrypt()
+{
+ const QByteArray &mac
+ = generateMac(m_encrypter, m_seqNr);
+ m_encrypter.encrypt(m_data);
+ m_data += mac;
+ return *this;
+}
+
+void SshOutgoingPacket::finalize()
+{
+ setPadding();
+ setLengthField(m_data);
+ m_length = m_data.size() - 4;
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Encrypting packet of type %u", m_data.at(TypeOffset));
+#endif
+ encrypt();
+ Q_ASSERT(isComplete());
+}
+
+int SshOutgoingPacket::sizeDivisor() const
+{
+ return qMax(cipherBlockSize(), 8U);
+}
+
+QByteArray SshOutgoingPacket::encodeNameList(const QList<QByteArray> &list)
+{
+ QByteArray data;
+ data.resize(4);
+ for (int i = 0; i < list.count(); ++i) {
+ if (i > 0)
+ data.append(',');
+ data.append(list.at(i));
+ }
+ AbstractSshPacket::setLengthField(data);
+ return data;
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshoutgoingpacket_p.h b/coreplugin/ssh/sshoutgoingpacket_p.h
new file mode 100644
index 0000000..eb9c2f5
--- /dev/null
+++ b/coreplugin/ssh/sshoutgoingpacket_p.h
@@ -0,0 +1,98 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHOUTGOINGPACKET_P_H
+#define SSHOUTGOINGPACKET_P_H
+
+#include "sshpacket_p.h"
+
+namespace Core {
+namespace Internal {
+
+class SshEncryptionFacility;
+
+class SshOutgoingPacket : public AbstractSshPacket
+{
+public:
+ SshOutgoingPacket(const SshEncryptionFacility &encrypter,
+ const quint32 &seqNr);
+
+ void generateKeyExchangeInitPacket();
+ void generateKeyDhInitPacket(const Botan::BigInt &e);
+ void generateNewKeysPacket();
+ void generateDisconnectPacket(SshErrorCode reason,
+ const QByteArray &reasonString);
+ void generateMsgUnimplementedPacket(quint32 serverSeqNr);
+ void generateUserAuthServiceRequestPacket();
+ void generateUserAuthByPwdRequestPacket(const QByteArray &user,
+ const QByteArray &service, const QByteArray &pwd);
+ void generateUserAuthByKeyRequestPacket(const QByteArray &user,
+ const QByteArray &service);
+ void generateRequestFailurePacket();
+ void generateSessionPacket(quint32 channelId, quint32 windowSize,
+ quint32 maxPacketSize);
+ void generateEnvPacket(quint32 remoteChannel, const QByteArray &var,
+ const QByteArray &value);
+ void generateExecPacket(quint32 remoteChannel, const QByteArray &command);
+ void generateSftpPacket(quint32 remoteChannel);
+ void generateWindowAdjustPacket(quint32 remoteChannel, quint32 bytesToAdd);
+ void generateChannelDataPacket(quint32 remoteChannel,
+ const QByteArray &data);
+ void generateChannelSignalPacket(quint32 remoteChannel,
+ const QByteArray &signalName);
+ void generateChannelEofPacket(quint32 remoteChannel);
+ void generateChannelClosePacket(quint32 remoteChannel);
+
+private:
+ virtual quint32 cipherBlockSize() const;
+ virtual quint32 macLength() const;
+
+ static QByteArray encodeNameList(const QList<QByteArray> &list);
+
+ void generateServiceRequest(const QByteArray &service);
+
+ SshOutgoingPacket &init(SshPacketType type);
+ SshOutgoingPacket &setPadding();
+ SshOutgoingPacket &encrypt();
+ void finalize();
+
+ SshOutgoingPacket &appendInt(quint32 val);
+ SshOutgoingPacket &appendString(const QByteArray &string);
+ SshOutgoingPacket &appendMpInt(const Botan::BigInt &number);
+ SshOutgoingPacket &appendBool(bool b);
+ int sizeDivisor() const;
+
+ const SshEncryptionFacility &m_encrypter;
+ const quint32 &m_seqNr;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHOUTGOINGPACKET_P_H
diff --git a/coreplugin/ssh/sshpacket.cpp b/coreplugin/ssh/sshpacket.cpp
new file mode 100644
index 0000000..ff70509
--- /dev/null
+++ b/coreplugin/ssh/sshpacket.cpp
@@ -0,0 +1,167 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshpacket_p.h"
+
+#include "sshcapabilities_p.h"
+#include "sshcryptofacility_p.h"
+#include "sshexception_p.h"
+#include "sshpacketparser_p.h"
+
+#include <QtCore/QDebug>
+
+#include <cctype>
+
+namespace Core {
+namespace Internal {
+
+const quint32 AbstractSshPacket::PaddingLengthOffset = 4;
+const quint32 AbstractSshPacket::PayloadOffset = PaddingLengthOffset + 1;
+const quint32 AbstractSshPacket::TypeOffset = PayloadOffset;
+const quint32 AbstractSshPacket::MinPaddingLength = 4;
+
+namespace {
+
+ void printByteArray(const QByteArray &data)
+ {
+#ifdef CREATOR_SSH_DEBUG
+ for (int i = 0; i < data.count(); ++i)
+ qDebug() << std::hex << (static_cast<unsigned int>(data[i]) & 0xff) << " ";
+#else
+ Q_UNUSED(data);
+#endif
+ }
+} // anonymous namespace
+
+
+AbstractSshPacket::AbstractSshPacket() : m_length(0) { }
+AbstractSshPacket::~AbstractSshPacket() {}
+
+bool AbstractSshPacket::isComplete() const
+{
+ if (currentDataSize() < minPacketSize())
+ return false;
+ Q_ASSERT(4 + length() + macLength() >= currentDataSize());
+ return 4 + length() + macLength() == currentDataSize();
+}
+
+void AbstractSshPacket::clear()
+{
+ m_data.clear();
+ m_length = 0;
+}
+
+SshPacketType AbstractSshPacket::type() const
+{
+ Q_ASSERT(isComplete());
+ return static_cast<SshPacketType>(m_data.at(TypeOffset));
+}
+
+AbstractSshPacket::Payload AbstractSshPacket::payLoad() const
+{
+ Payload p;
+ p.data = m_data.constData() + PayloadOffset;
+ p.size = length() - paddingLength() - 1;
+ return p;
+}
+
+void AbstractSshPacket::printRawBytes() const
+{
+ printByteArray(m_data);
+}
+
+QByteArray AbstractSshPacket::encodeString(const QByteArray &string)
+{
+ QByteArray data;
+ data.resize(4);
+ data += string;
+ setLengthField(data);
+ return data;
+}
+
+QByteArray AbstractSshPacket::encodeMpInt(const Botan::BigInt &number)
+{
+ if (number.is_zero())
+ return QByteArray(4, 0);
+
+ int stringLength = number.bytes();
+ const bool positiveAndMsbSet = number.sign() == Botan::BigInt::Positive
+ && (number.byte_at(stringLength - 1) & 0x80);
+ if (positiveAndMsbSet)
+ ++stringLength;
+ QByteArray data;
+ data.resize(4 + stringLength);
+ int pos = 4;
+ if (positiveAndMsbSet)
+ data[pos++] = '\0';
+ number.binary_encode(reinterpret_cast<Botan::byte *>(data.data()) + pos);
+ setLengthField(data);
+ return data;
+}
+
+int AbstractSshPacket::paddingLength() const
+{
+ return m_data[PaddingLengthOffset];
+}
+
+quint32 AbstractSshPacket::length() const
+{
+ //Q_ASSERT(currentDataSize() >= minPacketSize());
+ if (m_length == 0)
+ calculateLength();
+ return m_length;
+}
+
+void AbstractSshPacket::calculateLength() const
+{
+ m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
+}
+
+QByteArray AbstractSshPacket::generateMac(const SshAbstractCryptoFacility &crypt,
+ quint32 seqNr) const
+{
+ const quint32 seqNrBe = qToBigEndian(seqNr);
+ QByteArray data(reinterpret_cast<const char *>(&seqNrBe), sizeof seqNrBe);
+ data += QByteArray(m_data.constData(), length() + 4);
+ return crypt.generateMac(data, data.size());
+}
+
+quint32 AbstractSshPacket::minPacketSize() const
+{
+ return qMax<quint32>(cipherBlockSize(), 16) + macLength();
+}
+
+void AbstractSshPacket::setLengthField(QByteArray &data)
+{
+ const quint32 length = qToBigEndian(data.size() - 4);
+ data.replace(0, 4, reinterpret_cast<const char *>(&length), 4);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshpacket_p.h b/coreplugin/ssh/sshpacket_p.h
new file mode 100644
index 0000000..7120f00
--- /dev/null
+++ b/coreplugin/ssh/sshpacket_p.h
@@ -0,0 +1,137 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHPACKET_P_H
+#define SSHPACKET_P_H
+
+#include "sshexception_p.h"
+
+#include <QtCore/QtEndian>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+
+#include <botan/bigint.h>
+
+namespace Core {
+namespace Internal {
+
+enum SshPacketType {
+ SSH_MSG_DISCONNECT = 1,
+ SSH_MSG_IGNORE = 2,
+ SSH_MSG_UNIMPLEMENTED = 3,
+ SSH_MSG_DEBUG = 4,
+ SSH_MSG_SERVICE_REQUEST = 5,
+ SSH_MSG_SERVICE_ACCEPT = 6,
+
+ SSH_MSG_KEXINIT = 20,
+ SSH_MSG_NEWKEYS = 21,
+ SSH_MSG_KEXDH_INIT = 30,
+ SSH_MSG_KEXDH_REPLY = 31,
+
+ SSH_MSG_USERAUTH_REQUEST = 50,
+ SSH_MSG_USERAUTH_FAILURE = 51,
+ SSH_MSG_USERAUTH_SUCCESS = 52,
+ SSH_MSG_USERAUTH_BANNER = 53,
+ SSH_MSG_USERAUTH_PK_OK = 60,
+ SSH_MSG_USERAUTH_PASSWD_CHANGEREQ = 60,
+
+ SSH_MSG_GLOBAL_REQUEST = 80,
+ SSH_MSG_REQUEST_SUCCESS = 81,
+ SSH_MSG_REQUEST_FAILURE = 82,
+
+ SSH_MSG_CHANNEL_OPEN = 90,
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91,
+ SSH_MSG_CHANNEL_OPEN_FAILURE = 92,
+ SSH_MSG_CHANNEL_WINDOW_ADJUST = 93,
+ SSH_MSG_CHANNEL_DATA = 94,
+ SSH_MSG_CHANNEL_EXTENDED_DATA = 95,
+ SSH_MSG_CHANNEL_EOF = 96,
+ SSH_MSG_CHANNEL_CLOSE = 97,
+ SSH_MSG_CHANNEL_REQUEST = 98,
+ SSH_MSG_CHANNEL_SUCCESS = 99,
+ SSH_MSG_CHANNEL_FAILURE = 100,
+};
+
+enum SshExtendedDataType { SSH_EXTENDED_DATA_STDERR = 1 };
+
+class SshAbstractCryptoFacility;
+
+class AbstractSshPacket
+{
+public:
+ virtual ~AbstractSshPacket();
+
+ void clear();
+ bool isComplete() const;
+ SshPacketType type() const;
+
+ static QByteArray encodeString(const QByteArray &string);
+ static QByteArray encodeMpInt(const Botan::BigInt &number);
+ template<typename T> static QByteArray encodeInt(T value)
+ {
+ const T valMsb = qToBigEndian(value);
+ return QByteArray(reinterpret_cast<const char *>(&valMsb), sizeof valMsb);
+ }
+
+ static void setLengthField(QByteArray &data);
+
+ void printRawBytes() const; // For Debugging.
+
+ const QByteArray &rawData() const { return m_data; }
+
+ struct Payload { const char *data; quint32 size; };
+ Payload payLoad() const;
+
+protected:
+ AbstractSshPacket();
+
+ virtual quint32 cipherBlockSize() const=0;
+ virtual quint32 macLength() const=0;
+ virtual void calculateLength() const;
+
+ quint32 length() const;
+ int paddingLength() const;
+ quint32 minPacketSize() const;
+ quint32 currentDataSize() const { return m_data.size(); }
+ QByteArray generateMac(const SshAbstractCryptoFacility &crypt,
+ quint32 seqNr) const;
+
+ static const quint32 PaddingLengthOffset;
+ static const quint32 PayloadOffset;
+ static const quint32 TypeOffset;
+ static const quint32 MinPaddingLength;
+
+ mutable QByteArray m_data;
+ mutable quint32 m_length;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHPACKET_P_H
diff --git a/coreplugin/ssh/sshpacketparser.cpp b/coreplugin/ssh/sshpacketparser.cpp
new file mode 100644
index 0000000..2f339c0
--- /dev/null
+++ b/coreplugin/ssh/sshpacketparser.cpp
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshpacketparser_p.h"
+
+#include <cctype>
+
+namespace Core {
+namespace Internal {
+
+namespace { quint32 size(const QByteArray &data) { return data.size(); } }
+
+QString SshPacketParser::asUserString(const QByteArray &rawString)
+{
+ QByteArray filteredString;
+ filteredString.resize(rawString.size());
+ for (int i = 0; i < rawString.size(); ++i) {
+ const char c = rawString.at(i);
+ filteredString[i]
+ = std::isprint(c) || c == '\n' || c == '\r' || c == '\t' ? c : '?';
+ }
+ return QString::fromUtf8(filteredString);
+}
+
+bool SshPacketParser::asBool(const QByteArray &data, quint32 offset)
+{
+ if (size(data) <= offset)
+ throw SshPacketParseException();
+ return data.at(offset);
+}
+
+bool SshPacketParser::asBool(const QByteArray &data, quint32 *offset)
+{
+ bool b = asBool(data, *offset);
+ ++(*offset);
+ return b;
+}
+
+
+quint32 SshPacketParser::asUint32(const QByteArray &data, quint32 offset)
+{
+ if (size(data) < offset + 4)
+ throw SshPacketParseException();
+ const quint32 value = ((data.at(offset) & 0xff) << 24)
+ + ((data.at(offset + 1) & 0xff) << 16)
+ + ((data.at(offset + 2) & 0xff) << 8) + (data.at(offset + 3) & 0xff);
+ return value;
+}
+
+quint32 SshPacketParser::asUint32(const QByteArray &data, quint32 *offset)
+{
+ const quint32 v = asUint32(data, *offset);
+ *offset += 4;
+ return v;
+}
+
+quint64 SshPacketParser::asUint64(const QByteArray &data, quint32 offset)
+{
+ if (size(data) < offset + 8)
+ throw SshPacketParseException();
+ const quint64 value = (static_cast<quint64>(data.at(offset) & 0xff) << 56)
+ + (static_cast<quint64>(data.at(offset + 1) & 0xff) << 48)
+ + (static_cast<quint64>(data.at(offset + 2) & 0xff) << 40)
+ + (static_cast<quint64>(data.at(offset + 3) & 0xff) << 32)
+ + ((data.at(offset + 4) & 0xff) << 24)
+ + ((data.at(offset + 5) & 0xff) << 16)
+ + ((data.at(offset + 6) & 0xff) << 8)
+ + (data.at(offset + 7) & 0xff);
+ return value;
+}
+
+quint64 SshPacketParser::asUint64(const QByteArray &data, quint32 *offset)
+{
+ const quint64 val = asUint64(data, *offset);
+ *offset += 8;
+ return val;
+}
+
+QByteArray SshPacketParser::asString(const QByteArray &data, quint32 *offset)
+{
+ const quint32 length = asUint32(data, offset);
+ if (size(data) < *offset + length)
+ throw SshPacketParseException();
+ const QByteArray &string = data.mid(*offset, length);
+ *offset += length;
+ return string;
+}
+
+QString SshPacketParser::asUserString(const QByteArray &data, quint32 *offset)
+{
+ return asUserString(asString(data, offset));
+}
+
+SshNameList SshPacketParser::asNameList(const QByteArray &data, quint32 *offset)
+{
+ const quint32 length = asUint32(data, offset);
+ const int listEndPos = *offset + length;
+ if (data.size() < listEndPos)
+ throw SshPacketParseException();
+ SshNameList names(length + 4);
+ int nextNameOffset = *offset;
+ int nextCommaOffset = data.indexOf(',', nextNameOffset);
+ while (nextNameOffset > 0 && nextNameOffset < listEndPos) {
+ const int stringEndPos = nextCommaOffset == -1
+ || nextCommaOffset > listEndPos ? listEndPos : nextCommaOffset;
+ names.names << QByteArray(data.constData() + nextNameOffset,
+ stringEndPos - nextNameOffset);
+ nextNameOffset = nextCommaOffset + 1;
+ nextCommaOffset = data.indexOf(',', nextNameOffset);
+ }
+ *offset += length;
+ return names;
+}
+
+Botan::BigInt SshPacketParser::asBigInt(const QByteArray &data, quint32 *offset)
+{
+ const quint32 length = asUint32(data, offset);
+ if (length == 0)
+ return Botan::BigInt();
+ const Botan::byte *numberStart
+ = reinterpret_cast<const Botan::byte *>(data.constData() + *offset);
+ *offset += length;
+ return Botan::BigInt::decode(numberStart, length);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshpacketparser_p.h b/coreplugin/ssh/sshpacketparser_p.h
new file mode 100644
index 0000000..253f256
--- /dev/null
+++ b/coreplugin/ssh/sshpacketparser_p.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHPACKETPARSER_P_H
+#define SSHPACKETPARSER_P_H
+
+#include <botan/bigint.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+namespace Core {
+namespace Internal {
+
+struct SshNameList
+{
+ SshNameList() : originalLength(0) {}
+ SshNameList(quint32 originalLength) : originalLength(originalLength) {}
+ quint32 originalLength;
+ QList<QByteArray> names;
+};
+
+class SshPacketParseException { };
+
+// This class's functions try to read a byte array at a certain offset
+// as the respective chunk of data as specified in the SSH RFCs.
+// If they succeed, they update the offset, so they can easily
+// be called in succession by client code.
+// For convenience, some have also versions that don't update the offset,
+// so they can be called with rvalues if the new value is not needed.
+// If they fail, they throw an SshPacketParseException.
+class SshPacketParser
+{
+public:
+ static bool asBool(const QByteArray &data, quint32 offset);
+ static bool asBool(const QByteArray &data, quint32 *offset);
+ static quint16 asUint16(const QByteArray &data, quint32 offset);
+ static quint16 asUint16(const QByteArray &data, quint32 *offset);
+ static quint64 asUint64(const QByteArray &data, quint32 offset);
+ static quint64 asUint64(const QByteArray &data, quint32 *offset);
+ static quint32 asUint32(const QByteArray &data, quint32 offset);
+ static quint32 asUint32(const QByteArray &data, quint32 *offset);
+ static QByteArray asString(const QByteArray &data, quint32 *offset);
+ static QString asUserString(const QByteArray &data, quint32 *offset);
+ static SshNameList asNameList(const QByteArray &data, quint32 *offset);
+ static Botan::BigInt asBigInt(const QByteArray &data, quint32 *offset);
+
+ static QString asUserString(const QByteArray &rawString);
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHPACKETPARSER_P_H
diff --git a/coreplugin/ssh/sshremoteprocess.cpp b/coreplugin/ssh/sshremoteprocess.cpp
new file mode 100644
index 0000000..c9566e9
--- /dev/null
+++ b/coreplugin/ssh/sshremoteprocess.cpp
@@ -0,0 +1,270 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshremoteprocess.h"
+#include "sshremoteprocess_p.h"
+
+#include "sshdelayedsignal_p.h"
+#include "sshincomingpacket_p.h"
+#include "sshsendfacility_p.h"
+
+#include <botan/exceptn.h>
+
+namespace Core {
+
+const QByteArray SshRemoteProcess::AbrtSignal("ABRT");
+const QByteArray SshRemoteProcess::AlrmSignal("ALRM");
+const QByteArray SshRemoteProcess::FpeSignal("FPE");
+const QByteArray SshRemoteProcess::HupSignal("HUP");
+const QByteArray SshRemoteProcess::IllSignal("ILL");
+const QByteArray SshRemoteProcess::IntSignal("INT");
+const QByteArray SshRemoteProcess::KillSignal("KILL");
+const QByteArray SshRemoteProcess::PipeSignal("PIPE");
+const QByteArray SshRemoteProcess::QuitSignal("QUIT");
+const QByteArray SshRemoteProcess::SegvSignal("SEGV");
+const QByteArray SshRemoteProcess::TermSignal("TERM");
+const QByteArray SshRemoteProcess::Usr1Signal("USR1");
+const QByteArray SshRemoteProcess::Usr2Signal("USR2");
+
+SshRemoteProcess::SshRemoteProcess(const QByteArray &command, quint32 channelId,
+ Internal::SshSendFacility &sendFacility)
+ : d(new Internal::SshRemoteProcessPrivate(command, channelId, sendFacility, this))
+{
+}
+
+SshRemoteProcess::~SshRemoteProcess()
+{
+ Q_ASSERT(d->channelState() == Internal::SshRemoteProcessPrivate::Inactive
+ || d->channelState() == Internal::SshRemoteProcessPrivate::CloseRequested
+ || d->channelState() == Internal::SshRemoteProcessPrivate::Closed);
+ delete d;
+}
+
+void SshRemoteProcess::addToEnvironment(const QByteArray &var, const QByteArray &value)
+{
+ if (d->channelState() == Internal::SshRemoteProcessPrivate::Inactive)
+ d->m_env << qMakePair(var, value); // Cached locally and sent on start()
+}
+
+void SshRemoteProcess::start()
+{
+ if (d->channelState() == Internal::SshRemoteProcessPrivate::Inactive) {
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("process start requested, channel id = %u", d->localChannelId());
+#endif
+ d->requestSessionStart();
+ }
+}
+
+void SshRemoteProcess::sendSignal(const QByteArray &signal)
+{
+ try {
+ if (isRunning())
+ d->m_sendFacility.sendChannelSignalPacket(d->remoteChannel(),
+ signal);
+ } catch (Botan::Exception &e) {
+ d->setError(QString::fromAscii(e.what()));
+ d->closeChannel();
+ }
+}
+
+void SshRemoteProcess::closeChannel()
+{
+ d->closeChannel();
+}
+
+void SshRemoteProcess::sendInput(const QByteArray &data)
+{
+ if (isRunning())
+ d->sendData(data);
+}
+
+bool SshRemoteProcess::isRunning() const
+{
+ return d->m_procState == Internal::SshRemoteProcessPrivate::Running;
+}
+
+QString SshRemoteProcess::errorString() const { return d->errorString(); }
+
+int SshRemoteProcess::exitCode() const { return d->m_exitCode; }
+
+QByteArray SshRemoteProcess::exitSignal() const { return d->m_signal; }
+
+namespace Internal {
+
+SshRemoteProcessPrivate::SshRemoteProcessPrivate(const QByteArray &command,
+ quint32 channelId, SshSendFacility &sendFacility, SshRemoteProcess *proc)
+ : AbstractSshChannel(channelId, sendFacility), m_procState(NotYetStarted),
+ m_wasRunning(false), m_exitCode(0), m_command(command), m_proc(proc)
+{
+}
+
+void SshRemoteProcessPrivate::setProcState(ProcessState newState)
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("channel: old state = %d,new state = %d", m_procState, newState);
+#endif
+ m_procState = newState;
+ if (newState == StartFailed) {
+ createClosedSignal(SshRemoteProcess::FailedToStart);
+ } else if (newState == Running) {
+ m_wasRunning = true;
+ createStartedSignal();
+ }
+}
+
+void SshRemoteProcessPrivate::closeHook()
+{
+ if (m_wasRunning) {
+ if (!m_signal.isEmpty())
+ createClosedSignal(SshRemoteProcess::KilledBySignal);
+ else
+ createClosedSignal(SshRemoteProcess::ExitedNormally);
+ }
+}
+
+void SshRemoteProcessPrivate::handleOpenSuccessInternal()
+{
+ foreach (const EnvVar &envVar, m_env) {
+ m_sendFacility.sendEnvPacket(remoteChannel(), envVar.first,
+ envVar.second);
+ }
+
+ m_sendFacility.sendExecPacket(remoteChannel(), m_command);
+ setProcState(ExecRequested);
+}
+
+void SshRemoteProcessPrivate::handleOpenFailureInternal()
+{
+ setProcState(StartFailed);
+}
+
+void SshRemoteProcessPrivate::handleChannelSuccess()
+{
+ if (m_procState != ExecRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_SUCCESS message.");
+ }
+ setProcState(Running);
+}
+
+void SshRemoteProcessPrivate::handleChannelFailure()
+{
+ if (m_procState != ExecRequested) {
+ throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Unexpected SSH_MSG_CHANNEL_FAILURE message.");
+ }
+
+ setProcState(StartFailed);
+ closeChannel();
+}
+
+void SshRemoteProcessPrivate::handleChannelDataInternal(const QByteArray &data)
+{
+ createOutputAvailableSignal(data);
+}
+
+void SshRemoteProcessPrivate::handleChannelExtendedDataInternal(quint32 type,
+ const QByteArray &data)
+{
+ if (type != SSH_EXTENDED_DATA_STDERR)
+ qWarning("Unknown extended data type %u", type);
+ else
+ createErrorOutputAvailableSignal(data);
+}
+
+void SshRemoteProcessPrivate::handleChannelRequest(const SshIncomingPacket &packet)
+{
+ checkChannelActive();
+ const QByteArray &requestType = packet.extractChannelRequestType();
+ if (requestType == SshIncomingPacket::ExitStatusType) {
+ const SshChannelExitStatus status = packet.extractChannelExitStatus();
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Process exiting with exit code %d", status.exitStatus);
+#endif
+ m_exitCode = status.exitStatus;
+ m_procState = Exited;
+ } else if (requestType == SshIncomingPacket::ExitSignalType) {
+ const SshChannelExitSignal &signal = packet.extractChannelExitSignal();
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Exit due to signal %s", signal.signal.data());
+#endif
+ setError(signal.error);
+ m_signal = signal.signal;
+ m_procState = Exited;
+ } else {
+ qWarning("Ignoring unknown request type '%s'", requestType.data());
+ }
+}
+
+void SshRemoteProcessPrivate::createStartedSignal()
+{
+ new SshRemoteProcessStartedSignal(this, QWeakPointer<SshRemoteProcess>(m_proc));
+}
+
+void SshRemoteProcessPrivate::emitStartedSignal()
+{
+ emit m_proc->started();
+}
+
+void SshRemoteProcessPrivate::createOutputAvailableSignal(const QByteArray &output)
+{
+ new SshRemoteProcessOutputAvailableSignal(this,
+ QWeakPointer<SshRemoteProcess>(m_proc), output);
+}
+
+void SshRemoteProcessPrivate::emitOutputAvailableSignal(const QByteArray &output)
+{
+ emit m_proc->outputAvailable(output);
+}
+
+void SshRemoteProcessPrivate::createErrorOutputAvailableSignal(const QByteArray &output)
+{
+ new SshRemoteProcessErrorOutputAvailableSignal(this,
+ QWeakPointer<SshRemoteProcess>(m_proc), output);
+}
+
+void SshRemoteProcessPrivate::emitErrorOutputAvailableSignal(const QByteArray &output)
+{
+ emit m_proc->errorOutputAvailable(output);
+}
+
+void SshRemoteProcessPrivate::createClosedSignal(int exitStatus)
+{
+ new SshRemoteProcessClosedSignal(this,
+ QWeakPointer<SshRemoteProcess>(m_proc), exitStatus);
+}
+
+void SshRemoteProcessPrivate::emitClosedSignal(int exitStatus)
+{
+ emit m_proc->closed(exitStatus);
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshremoteprocess.h b/coreplugin/ssh/sshremoteprocess.h
new file mode 100644
index 0000000..9418949
--- /dev/null
+++ b/coreplugin/ssh/sshremoteprocess.h
@@ -0,0 +1,130 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHREMOTECOMMAND_H
+#define SSHREMOTECOMMAND_H
+
+#include <coreplugin/core_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Internal {
+class SshChannelManager;
+class SshRemoteProcessPrivate;
+class SshSendFacility;
+} // namespace Internal
+
+
+/*
+ * This class implements an SSH channel for running a remote process.
+ * Objects are created via SshConnection::createRemoteProcess.
+ * The process is started via the start() member function.
+ * A closeChannel() function is provided, but rarely useful, because
+ * a) when the process ends, the channel is closed automatically, and
+ * b) closing a channel will not necessarily kill the remote process.
+ * Therefore, the only sensible use case for calling closeChannel() is to
+ * get rid of an SshRemoteProces object before the process is actually started.
+ * Note that the process does not have a terminal, so you can't use it
+ * for applications that require one.
+ */
+class CORE_EXPORT SshRemoteProcess : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(SshRemoteProcess)
+
+ friend class Internal::SshChannelManager;
+ friend class Internal::SshRemoteProcessPrivate;
+
+public:
+ typedef QSharedPointer<SshRemoteProcess> Ptr;
+ enum ExitStatus { FailedToStart, KilledBySignal, ExitedNormally };
+
+ static const QByteArray AbrtSignal;
+ static const QByteArray AlrmSignal;
+ static const QByteArray FpeSignal;
+ static const QByteArray HupSignal;
+ static const QByteArray IllSignal;
+ static const QByteArray IntSignal;
+ static const QByteArray KillSignal;
+ static const QByteArray PipeSignal;
+ static const QByteArray QuitSignal;
+ static const QByteArray SegvSignal;
+ static const QByteArray TermSignal;
+ static const QByteArray Usr1Signal;
+ static const QByteArray Usr2Signal;
+
+ ~SshRemoteProcess();
+
+ /*
+ * Note that this is of limited value in practice, because servers are
+ * usually configured to ignore such requests for security reasons.
+ */
+ void addToEnvironment(const QByteArray &var, const QByteArray &value);
+
+ void start();
+ void closeChannel();
+
+ bool isRunning() const;
+ QString errorString() const;
+ int exitCode() const;
+ QByteArray exitSignal() const;
+
+ // Note: This is ignored by the OpenSSH server.
+ void sendSignal(const QByteArray &signal);
+ void kill() { sendSignal(KillSignal); }
+
+ void sendInput(const QByteArray &data); // Should usually have a trailing newline.
+
+signals:
+ void started();
+ void outputAvailable(const QByteArray &output);
+ void errorOutputAvailable(const QByteArray &output);
+
+ /*
+ * Parameter is of type ExitStatus, but we use int because of
+ * signal/slot awkwardness (full namespace required).
+ */
+ void closed(int exitStatus);
+
+private:
+ SshRemoteProcess(const QByteArray &command, quint32 channelId,
+ Internal::SshSendFacility &sendFacility);
+
+ Internal::SshRemoteProcessPrivate *d;
+};
+
+} // namespace Core
+
+#endif // SSHREMOTECOMMAND_H
diff --git a/coreplugin/ssh/sshremoteprocess_p.h b/coreplugin/ssh/sshremoteprocess_p.h
new file mode 100644
index 0000000..951ca24
--- /dev/null
+++ b/coreplugin/ssh/sshremoteprocess_p.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHREMOTEPROCESS_P_H
+#define SSHREMOTEPROCESS_P_H
+
+#include "sshchannel_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QPair>
+
+namespace Core {
+class SshRemoteProcess;
+
+namespace Internal {
+class SshSendFacility;
+
+class SshRemoteProcessPrivate : public AbstractSshChannel
+{
+ friend class Core::SshRemoteProcess;
+public:
+ enum ProcessState {
+ NotYetStarted, ExecRequested, StartFailed,Running, Exited
+ };
+
+ virtual void handleChannelSuccess();
+ virtual void handleChannelFailure();
+
+ virtual void closeHook();
+
+ void emitStartedSignal();
+ void emitOutputAvailableSignal(const QByteArray &output);
+ void emitErrorOutputAvailableSignal(const QByteArray &output);
+ void emitClosedSignal(int exitStatus);
+
+private:
+ SshRemoteProcessPrivate(const QByteArray &command, quint32 channelId,
+ SshSendFacility &sendFacility, SshRemoteProcess *proc);
+
+ virtual void handleOpenSuccessInternal();
+ virtual void handleOpenFailureInternal();
+ virtual void handleChannelDataInternal(const QByteArray &data);
+ virtual void handleChannelExtendedDataInternal(quint32 type,
+ const QByteArray &data);
+ virtual void handleChannelRequest(const SshIncomingPacket &packet);
+
+ void setProcState(ProcessState newState);
+
+ void createStartedSignal();
+ void createOutputAvailableSignal(const QByteArray &output);
+ void createErrorOutputAvailableSignal(const QByteArray &output);
+ void createClosedSignal(int exitStatus);
+
+ ProcessState m_procState;
+ bool m_wasRunning;
+ QByteArray m_signal;
+ int m_exitCode;
+
+ const QByteArray m_command;
+
+ typedef QPair<QByteArray, QByteArray> EnvVar;
+ QList<EnvVar> m_env;
+
+ SshRemoteProcess *m_proc;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHREMOTEPROCESS_P_H
diff --git a/coreplugin/ssh/sshsendfacility.cpp b/coreplugin/ssh/sshsendfacility.cpp
new file mode 100644
index 0000000..3c793af
--- /dev/null
+++ b/coreplugin/ssh/sshsendfacility.cpp
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshsendfacility_p.h"
+
+#include "sshkeyexchange_p.h"
+#include "sshoutgoingpacket_p.h"
+
+#include <QtNetwork/QTcpSocket>
+
+namespace Core {
+namespace Internal {
+
+SshSendFacility::SshSendFacility(QTcpSocket *socket)
+ : m_clientSeqNr(0), m_socket(socket),
+ m_outgoingPacket(m_encrypter, m_clientSeqNr)
+{
+}
+
+void SshSendFacility::sendPacket()
+{
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Sending packet, client seq nr is %u", m_clientSeqNr);
+#endif
+ m_socket->write(m_outgoingPacket.rawData());
+ ++m_clientSeqNr;
+}
+
+void SshSendFacility::reset()
+{
+ m_clientSeqNr = 0;
+ m_encrypter.clearKeys();
+}
+
+void SshSendFacility::recreateKeys(const SshKeyExchange &keyExchange)
+{
+ m_encrypter.recreateKeys(keyExchange);
+}
+
+void SshSendFacility::createAuthenticationKey(const QByteArray &privKeyFileContents)
+{
+ m_encrypter.createAuthenticationKey(privKeyFileContents);
+}
+
+SshOutgoingPacket::Payload SshSendFacility::sendKeyExchangeInitPacket()
+{
+ m_outgoingPacket.generateKeyExchangeInitPacket();
+ sendPacket();
+ return m_outgoingPacket.payLoad();
+}
+
+void SshSendFacility::sendKeyDhInitPacket(const Botan::BigInt &e)
+{
+ m_outgoingPacket.generateKeyDhInitPacket(e);
+ sendPacket();
+}
+
+void SshSendFacility::sendNewKeysPacket()
+{
+ m_outgoingPacket.generateNewKeysPacket();
+ sendPacket();
+}
+
+void SshSendFacility::sendDisconnectPacket(SshErrorCode reason,
+ const QByteArray &reasonString)
+{
+ m_outgoingPacket.generateDisconnectPacket(reason, reasonString);
+ sendPacket();
+ }
+
+void SshSendFacility::sendMsgUnimplementedPacket(quint32 serverSeqNr)
+{
+ m_outgoingPacket.generateMsgUnimplementedPacket(serverSeqNr);
+ sendPacket();
+}
+
+void SshSendFacility::sendUserAuthServiceRequestPacket()
+{
+ m_outgoingPacket.generateUserAuthServiceRequestPacket();
+ sendPacket();
+}
+
+void SshSendFacility::sendUserAuthByPwdRequestPacket(const QByteArray &user,
+ const QByteArray &service, const QByteArray &pwd)
+{
+ m_outgoingPacket.generateUserAuthByPwdRequestPacket(user, service, pwd);
+ sendPacket();
+ }
+
+void SshSendFacility::sendUserAuthByKeyRequestPacket(const QByteArray &user,
+ const QByteArray &service)
+{
+ m_outgoingPacket.generateUserAuthByKeyRequestPacket(user, service);
+ sendPacket();
+}
+
+void SshSendFacility::sendRequestFailurePacket()
+{
+ m_outgoingPacket.generateRequestFailurePacket();
+ sendPacket();
+}
+
+void SshSendFacility::sendSessionPacket(quint32 channelId, quint32 windowSize,
+ quint32 maxPacketSize)
+{
+ m_outgoingPacket.generateSessionPacket(channelId, windowSize,
+ maxPacketSize);
+ sendPacket();
+}
+
+void SshSendFacility::sendEnvPacket(quint32 remoteChannel,
+ const QByteArray &var, const QByteArray &value)
+{
+ m_outgoingPacket.generateEnvPacket(remoteChannel, var, value);
+ sendPacket();
+}
+
+void SshSendFacility::sendExecPacket(quint32 remoteChannel,
+ const QByteArray &command)
+{
+ m_outgoingPacket.generateExecPacket(remoteChannel, command);
+ sendPacket();
+}
+
+void SshSendFacility::sendSftpPacket(quint32 remoteChannel)
+{
+ m_outgoingPacket.generateSftpPacket(remoteChannel);
+ sendPacket();
+}
+
+void SshSendFacility::sendWindowAdjustPacket(quint32 remoteChannel,
+ quint32 bytesToAdd)
+{
+ m_outgoingPacket.generateWindowAdjustPacket(remoteChannel, bytesToAdd);
+ sendPacket();
+}
+
+void SshSendFacility::sendChannelDataPacket(quint32 remoteChannel,
+ const QByteArray &data)
+{
+ m_outgoingPacket.generateChannelDataPacket(remoteChannel, data);
+ sendPacket();
+}
+
+void SshSendFacility::sendChannelSignalPacket(quint32 remoteChannel,
+ const QByteArray &signalName)
+{
+ m_outgoingPacket.generateChannelSignalPacket(remoteChannel, signalName);
+ sendPacket();
+}
+
+void SshSendFacility::sendChannelEofPacket(quint32 remoteChannel)
+{
+ m_outgoingPacket.generateChannelEofPacket(remoteChannel);
+ sendPacket();
+}
+
+void SshSendFacility::sendChannelClosePacket(quint32 remoteChannel)
+{
+ m_outgoingPacket.generateChannelClosePacket(remoteChannel);
+ sendPacket();
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/coreplugin/ssh/sshsendfacility_p.h b/coreplugin/ssh/sshsendfacility_p.h
new file mode 100644
index 0000000..6f1cdf7
--- /dev/null
+++ b/coreplugin/ssh/sshsendfacility_p.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef SSHCONNECTIONOUTSTATE_P_H
+#define SSHCONNECTIONOUTSTATE_P_H
+
+#include "sshcryptofacility_p.h"
+#include "sshoutgoingpacket_p.h"
+
+QT_BEGIN_NAMESPACE
+class QTcpSocket;
+QT_END_NAMESPACE
+
+
+namespace Core {
+namespace Internal {
+class SshKeyExchange;
+
+class SshSendFacility
+{
+public:
+ SshSendFacility(QTcpSocket *socket);
+ void reset();
+ void recreateKeys(const SshKeyExchange &keyExchange);
+ void createAuthenticationKey(const QByteArray &privKeyFileContents);
+
+ SshOutgoingPacket::Payload sendKeyExchangeInitPacket();
+ void sendKeyDhInitPacket(const Botan::BigInt &e);
+ void sendNewKeysPacket();
+ void sendDisconnectPacket(SshErrorCode reason,
+ const QByteArray &reasonString);
+ void sendMsgUnimplementedPacket(quint32 serverSeqNr);
+ void sendUserAuthServiceRequestPacket();
+ void sendUserAuthByPwdRequestPacket(const QByteArray &user,
+ const QByteArray &service, const QByteArray &pwd);
+ void sendUserAuthByKeyRequestPacket(const QByteArray &user,
+ const QByteArray &service);
+ void sendRequestFailurePacket();
+ void sendSessionPacket(quint32 channelId, quint32 windowSize,
+ quint32 maxPacketSize);
+ void sendEnvPacket(quint32 remoteChannel, const QByteArray &var,
+ const QByteArray &value);
+ void sendExecPacket(quint32 remoteChannel, const QByteArray &command);
+ void sendSftpPacket(quint32 remoteChannel);
+ void sendWindowAdjustPacket(quint32 remoteChannel, quint32 bytesToAdd);
+ void sendChannelDataPacket(quint32 remoteChannel, const QByteArray &data);
+ void sendChannelSignalPacket(quint32 remoteChannel,
+ const QByteArray &signalName);
+ void sendChannelEofPacket(quint32 remoteChannel);
+ void sendChannelClosePacket(quint32 remoteChannel);
+
+private:
+ void sendPacket();
+
+ quint32 m_clientSeqNr;
+ SshEncryptionFacility m_encrypter;
+ QTcpSocket *m_socket;
+ SshOutgoingPacket m_outgoingPacket;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // SSHCONNECTIONOUTSTATE_P_H
diff --git a/examples/cppsystemtest/cppsystemtest.pro b/examples/cppsystemtest/cppsystemtest.pro
index faeac4b..c04397f 100644
--- a/examples/cppsystemtest/cppsystemtest.pro
+++ b/examples/cppsystemtest/cppsystemtest.pro
@@ -6,6 +6,7 @@ VPATH+=$$PWD
INCLUDEPATH+=$$PWD
INCLUDEPATH+=$$SRCROOT/libqsystemtest
INCLUDEPATH+=$$SRCROOT/libqtuitest
+INCLUDEPATH+=$$SRCROOT
TARGET=mysystemtest
diff --git a/interpreter/interpreter.pro b/interpreter/interpreter.pro
index c91e4ee..4954f5f 100644
--- a/interpreter/interpreter.pro
+++ b/interpreter/interpreter.pro
@@ -16,6 +16,7 @@ DEFINES += QTUITESTRUNNER_TARGET
TEMPLATE=app
VPATH+=$$PWD
INCLUDEPATH+=$$PWD
+INCLUDEPATH+=$$SRCROOT
INCLUDEPATH+=$$SRCROOT/libqtuitest
INCLUDEPATH+=$$SRCROOT/libqsystemtest
QT+=script network
diff --git a/interpreter/qscriptsystemtest.cpp b/interpreter/qscriptsystemtest.cpp
index 134af57..0a041d6 100644
--- a/interpreter/qscriptsystemtest.cpp
+++ b/interpreter/qscriptsystemtest.cpp
@@ -856,8 +856,6 @@ void QScriptSystemTest::processMessage(const QTestMessage& message)
*/
void QScriptSystemTest::processCommandLine( int &argc, char *argv[] )
{
- qDebug() << "QScriptSytsemTest::processCommandLine()";
-
int offset = 0;
for (int i=1; i<argc; ++i) {
diff --git a/libqsystemtest/libqsystemtest.pro b/libqsystemtest/libqsystemtest.pro
index f0ff053..2bc22be 100644
--- a/libqsystemtest/libqsystemtest.pro
+++ b/libqsystemtest/libqsystemtest.pro
@@ -13,7 +13,8 @@ SEMI_PRIVATE_HEADERS += \
HEADERS +=\
gracefulquit.h \
qabstracttest.h \
- qsystemtest.h
+ qsystemtest.h \
+ testdevicecontrol.h
SOURCES +=\
gracefulquit.cpp \
@@ -22,11 +23,66 @@ SOURCES +=\
qtestverifydlg.cpp \
qsystemtest.cpp \
qsystemtest_p.cpp \
- qsystemtestmaster.cpp
+ qsystemtestmaster.cpp \
+ testdevicecontrol.cpp
+
+HEADERS +=\
+ ../coreplugin/ssh/sftpchannel.h \
+ ../coreplugin/ssh/sftpchannel_p.h \
+ ../coreplugin/ssh/sftpdefs.h \
+ ../coreplugin/ssh/sftpincomingpacket_p.h \
+ ../coreplugin/ssh/sftpoperation_p.h \
+ ../coreplugin/ssh/sftpoutgoingpacket_p.h \
+ ../coreplugin/ssh/sftppacket_p.h \
+ ../coreplugin/ssh/sshbotanconversions_p.h \
+ ../coreplugin/ssh/sshcapabilities_p.h \
+ ../coreplugin/ssh/sshchannel_p.h \
+ ../coreplugin/ssh/sshchannelmanager_p.h \
+ ../coreplugin/ssh/sshconnection.h \
+ ../coreplugin/ssh/sshconnection_p.h \
+ ../coreplugin/ssh/sshcryptofacility_p.h \
+ ../coreplugin/ssh/sshdelayedsignal_p.h \
+ ../coreplugin/ssh/ssherrors.h \
+ ../coreplugin/ssh/sshexception_p.h \
+ ../coreplugin/ssh/sshincomingpacket_p.h \
+ ../coreplugin/ssh/sshkeyexchange_p.h \
+ ../coreplugin/ssh/sshkeygenerator.h \
+ ../coreplugin/ssh/sshoutgoingpacket_p.h \
+ ../coreplugin/ssh/sshpacket_p.h \
+ ../coreplugin/ssh/sshpacketparser_p.h \
+ ../coreplugin/ssh/sshremoteprocess.h \
+ ../coreplugin/ssh/sshremoteprocess_p.h \
+ ../coreplugin/ssh/sshsendfacility_p.h
+
+SOURCES +=\
+ ../coreplugin/ssh/sftpchannel.cpp \
+ ../coreplugin/ssh/sftpdefs.cpp \
+ ../coreplugin/ssh/sftpincomingpacket.cpp \
+ ../coreplugin/ssh/sftpoperation.cpp \
+ ../coreplugin/ssh/sftpoutgoingpacket.cpp \
+ ../coreplugin/ssh/sftppacket.cpp \
+ ../coreplugin/ssh/sshcapabilities.cpp \
+ ../coreplugin/ssh/sshchannel.cpp \
+ ../coreplugin/ssh/sshchannelmanager.cpp \
+ ../coreplugin/ssh/sshconnection.cpp \
+ ../coreplugin/ssh/sshcryptofacility.cpp \
+ ../coreplugin/ssh/sshdelayedsignal.cpp \
+ ../coreplugin/ssh/sshincomingpacket.cpp \
+ ../coreplugin/ssh/sshkeyexchange.cpp \
+ ../coreplugin/ssh/sshkeygenerator.cpp \
+ ../coreplugin/ssh/sshoutgoingpacket.cpp \
+ ../coreplugin/ssh/sshpacket.cpp \
+ ../coreplugin/ssh/sshpacketparser.cpp \
+ ../coreplugin/ssh/sshremoteprocess.cpp \
+ ../coreplugin/ssh/sshsendfacility.cpp
+
+
VPATH+=$$PWD
INCLUDEPATH+=$$PWD
INCLUDEPATH+=$$SRCROOT
+INCLUDEPATH+=$$SRCROOT/botan/build
+INCLUDEPATH+=$$SRCROOT/coreplugin
DEPENDPATH+=$$SRCROOT
TEMPLATE=lib
@@ -36,6 +92,7 @@ HEADERS*=$$SEMI_PRIVATE_HEADERS $$PRIVATE_HEADERS
INCLUDEPATH+=$$SRCROOT/libqtuitest
CONFIG+=qtestlib
QT+=network
+LIBS+= -lBotan
unix:!symbian {
DESTDIR=$$BUILDROOT/lib
diff --git a/libqsystemtest/qabstracttest.cpp b/libqsystemtest/qabstracttest.cpp
index dc6f115..2353e6d 100644
--- a/libqsystemtest/qabstracttest.cpp
+++ b/libqsystemtest/qabstracttest.cpp
@@ -395,8 +395,6 @@ void QAbstractTest::printUsage( int argc, char* argv[] ) const
*/
void QAbstractTest::processCommandLine( int &argc, char* argv[] )
{
- qDebug() << "QAbstractTest::processCommandLine()";
-
int offset = 0;
for (int i = 1; i < argc; ++i) {
if ( !strcasecmp(argv[i], "-data") ) {
diff --git a/libqsystemtest/qsystemtest.cpp b/libqsystemtest/qsystemtest.cpp
index 7ae1ea3..945a6b2 100644
--- a/libqsystemtest/qsystemtest.cpp
+++ b/libqsystemtest/qsystemtest.cpp
@@ -2395,6 +2395,10 @@ void QSystemTest::startApplication( const QString &application, const QStringLis
} else {
// Running on device
+
+ if (!device_control)
+ device_control = new Qt4Test::TestDeviceControl(ssh_param);
+
QProcess proc;
if (!(flags & BackgroundCurrentApplication)) {
@@ -2445,11 +2449,12 @@ void QSystemTest::startApplication( const QString &application, const QStringLis
// testOutputPane()->append(reply);
#endif
- if (device_control)
+ if (device_control) {
device_control->runCustomCommand("run-standalone.sh " + application + " -style qtuitest", 3000, reply);
#ifdef QTCREATOR_QTEST
testOutputPane()->append(reply);
#endif
+ }
if (!connectToAut(timeout)) {
fail(QString("Could not connect to remote process '%1'.").arg(app));
@@ -2782,8 +2787,6 @@ void QSystemTest::expectApplicationClose( bool value )
*/
void QSystemTest::processCommandLine( int &argc, char *argv[] )
{
- qDebug() << "QSystemTest::processCommandLine()";
-
int offset = 0;
// Whenever we discover an option that 'we' understand, eat away the option (and its parameters) so that QTest doesn't get
@@ -2828,8 +2831,7 @@ void QSystemTest::processCommandLine( int &argc, char *argv[] )
argv[i+1] = 0;
++offset;
++i;
-
- qDebug() << "authost=" << ssh_param.host;
+ ssh_param.timeout = 20000;
} else if ( !strcasecmp(argv[i], "-username") ) {
char *given_arg = argv[i];
@@ -2853,11 +2855,14 @@ void QSystemTest::processCommandLine( int &argc, char *argv[] )
qFatal("Expected a password after %s", given_arg);
ssh_param.pwd = argv[i+1];
+ ssh_param.authType = Core::SshConnectionParameters::AuthByPwd;
argv[i+1] = 0;
++offset;
++i;
- } else if ( !strcasecmp(argv[i], "-private-key-file") ) {
+ ssh_param.privateKeyFile = "";
+
+ } else if ( !strcasecmp(argv[i], "-private-key") ) {
char *given_arg = argv[i];
argv[i] = 0;
@@ -2866,6 +2871,8 @@ void QSystemTest::processCommandLine( int &argc, char *argv[] )
qFatal("Expected a private key file after %s", given_arg);
ssh_param.privateKeyFile = argv[i+1];
+ ssh_param.pwd = "";
+ ssh_param.authType = Core::SshConnectionParameters::AuthByKey;
argv[i+1] = 0;
++offset;
++i;
diff --git a/libqsystemtest/qsystemtest.h b/libqsystemtest/qsystemtest.h
index 51ee1af..e3125b2 100644
--- a/libqsystemtest/qsystemtest.h
+++ b/libqsystemtest/qsystemtest.h
@@ -46,7 +46,7 @@
#include "qtestprotocol_p.h"
#include "qtestremote_p.h"
#include "recordevent_p.h"
-#include "testdevicecontrol.h"
+#include <testdevicecontrol.h>
#include <QStringList>
#include <QDir>
diff --git a/libqsystemtest/testdevicecontrol.cpp b/libqsystemtest/testdevicecontrol.cpp
new file mode 100644
index 0000000..344846d
--- /dev/null
+++ b/libqsystemtest/testdevicecontrol.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testdevicecontrol.h"
+
+#include <coreplugin/ssh/sshremoteprocess.h>
+
+#include <QDebug>
+#include <QRegExp>
+#include <QTime>
+#include <QApplication>
+#include <QTimer>
+
+using namespace Core;
+
+namespace Qt4Test {
+
+TestDeviceControl::TestDeviceControl( Core::SshConnectionParameters &sshParam )
+{
+ m_server = sshParam;
+ control_mode = Idle;
+}
+
+TestDeviceControl::~TestDeviceControl()
+{
+}
+
+bool TestDeviceControl::deviceConfiguration( QString &reply )
+{
+ runBlockingCommand( ConfigCheck, "", 10000);
+ reply = reply_txt;
+ return reply_ok;
+}
+
+bool TestDeviceControl::runCustomCommand( const QString &cmd, int timeout, QString &reply )
+{
+ runBlockingCommand( CustomCommand, cmd, timeout);
+ reply = reply_txt;
+ return reply_ok;
+}
+
+bool TestDeviceControl::runCustomBlockingCommand( const QString &cmd, int timeout, QString &reply )
+{
+ runBlockingCommand( CustomBlockingCommand, cmd, timeout);
+ reply = reply_txt;
+ return reply_ok;
+}
+
+void TestDeviceControl::runBlockingCommand( TestDeviceControlMode mode, const QString &cmd, int timeout)
+{
+ reply_txt = "";
+ reply_ok = true;
+ m_cmd = cmd;
+ control_mode = mode;
+ if (initConnection())
+ waitForCommandToFinish(timeout);
+ cleanupConnection();
+}
+
+bool TestDeviceControl::killApplication()
+{
+ if (m_testProcess) {
+ m_testProcess->kill();
+
+ QString reply;
+ if (!runCustomCommand( "killall testapp1", 1000, reply)) {
+ qDebug() << reply;
+ return false;
+ }
+ }
+ return true;
+}
+
+void TestDeviceControl::waitForCommandToFinish(int timeout)
+{
+ QTime t;
+ t.start();
+ while (t.elapsed() < 10000 && control_mode != Idle) {
+ qApp->processEvents();
+ }
+ if (control_mode != Idle) {
+ reply_ok = false;
+ reply_txt += "Command timed out";
+ }
+}
+
+bool TestDeviceControl::initConnection()
+{
+ if (m_testProcess) {
+ reply_ok = false;
+ reply_txt = "Process existed already";
+ return false;
+ }
+
+ reply_ok = true;
+ m_deviceTestOutput = "";
+ m_connection = SshConnection::create();
+ connect(m_connection.data(), SIGNAL(connected()),
+ this, SLOT(handleConnected()));
+ connect(m_connection.data(), SIGNAL(error(SshError)),
+ this, SLOT(handleConnectionError()));
+
+ m_connection->connectToHost(m_server);
+
+ return true;
+}
+
+void TestDeviceControl::handleConnected()
+{
+ if (!m_connection) {
+ reply_ok = false;
+ reply_txt += "Invalid connection\n";
+ return;
+ }
+
+ if (control_mode == ConfigCheck) {
+ QLatin1String sysInfoCmd("uname -rsm");
+ QLatin1String qtInfoCmd("dpkg -l |grep libqt "
+ "|sed 's/[[:space:]][[:space:]]*/ /g' "
+ "|cut -d ' ' -f 2,3 |sed 's/~.*//g'");
+ QString command(sysInfoCmd + " && " + qtInfoCmd);
+ m_testProcess = m_connection->createRemoteProcess(command.toUtf8());
+ } else if (control_mode == CustomCommand || control_mode == CustomBlockingCommand) {
+ m_testProcess = m_connection->createRemoteProcess(m_cmd.toUtf8());
+ }
+
+ connect(m_testProcess.data(), SIGNAL(closed(int)), this,
+ SLOT(handleProcessFinished(int)));
+ connect(m_testProcess.data(), SIGNAL(outputAvailable(QByteArray)), this,
+ SLOT(processSshOutput(QByteArray)));
+
+ m_testProcess->start();
+
+ if (control_mode == CustomCommand)
+ QTimer::singleShot(500,this,SLOT(cleanupConnection()));
+}
+
+void TestDeviceControl::handleConnectionError()
+{
+ reply_ok = false;
+
+ if (!m_connection) {
+ reply_txt += "Invalid connection\n";
+ } else {
+ reply_txt += tr("Could not connect to host: %1:%2 %3 %4\n%5\n")
+ .arg(m_server.host)
+ .arg(m_server.port)
+ .arg(m_server.uname)
+ .arg(m_server.pwd)
+ .arg(m_connection->errorString());
+ }
+ cleanupConnection();
+}
+
+void TestDeviceControl::handleProcessFinished(int exitStatus)
+{
+ Q_ASSERT(exitStatus == SshRemoteProcess::FailedToStart
+ || exitStatus == SshRemoteProcess::KilledBySignal
+ || exitStatus == SshRemoteProcess::ExitedNormally);
+
+ if (!m_testProcess) {
+ reply_ok = false;
+ reply_txt += "Invalid process\n";
+ return;
+ }
+
+ if (exitStatus != SshRemoteProcess::ExitedNormally
+ || m_testProcess->exitCode() != 0) {
+ reply_ok = false;
+ reply_txt += tr("Remote process failed: %1\n")
+ .arg(m_testProcess->errorString());
+ } else if (control_mode == ConfigCheck) {
+ const QString &output = parseOutput();
+ if (!m_qtVersionOk) {
+ reply_txt += tr("Qt version mismatch! "
+ " Expected Qt on device: 4.6.2 or later.\n");
+ }
+ reply_txt += output;
+ } else if (control_mode == CustomCommand || control_mode == CustomBlockingCommand) {
+ reply_txt += m_deviceTestOutput;
+ }
+
+ cleanupConnection();
+}
+
+void TestDeviceControl::cleanupConnection()
+{
+ if (m_testProcess)
+ disconnect(m_testProcess.data(), 0, this, 0);
+ if (m_connection)
+ disconnect(m_connection.data(), 0, this, 0);
+ control_mode = Idle;
+ m_testProcess.clear();
+ m_connection.clear();
+}
+
+void TestDeviceControl::processSshOutput(const QByteArray &output)
+{
+ m_deviceTestOutput.append(QString::fromUtf8(output));
+}
+
+QString TestDeviceControl::parseOutput()
+{
+ if (control_mode == ConfigCheck) {
+ m_qtVersionOk = false;
+
+ QString output;
+ const QRegExp unamePattern(QLatin1String("Linux (\\S+)\\s(\\S+)"));
+ int index = unamePattern.indexIn(m_deviceTestOutput);
+ if (index == -1) {
+ output = tr("Device configuration test failed: Unexpected output:\n%1")
+ .arg(m_deviceTestOutput);
+ return output;
+ }
+
+ output = tr("Hardware architecture: %1\n").arg(unamePattern.cap(2));
+ output.append(tr("Kernel version: %1\n").arg(unamePattern.cap(1)));
+ const QRegExp dkpgPattern(QLatin1String("libqt\\S+ (\\d)\\.(\\d)\\.(\\d)"));
+ index = dkpgPattern.indexIn(m_deviceTestOutput);
+ if (index == -1) {
+ output.append(tr("No Qt packages installed."));
+ return output;
+ }
+
+ output.append(tr("List of installed Qt packages:") + QLatin1Char('\n'));
+ do {
+ output.append(QLatin1Char('\t') + dkpgPattern.cap(0)
+ + QLatin1Char('\n'));
+ index = dkpgPattern.indexIn(m_deviceTestOutput, index + 1);
+ if (!m_qtVersionOk && QT_VERSION_CHECK(dkpgPattern.cap(1).toInt(),
+ dkpgPattern.cap(2).toInt(), dkpgPattern.cap(3).toInt()) >= 0x040602) {
+ m_qtVersionOk = true;
+ }
+ } while (index != -1);
+ return output;
+ }
+
+ return "";
+}
+
+} // namespace Qt4Test
diff --git a/libqsystemtest/testdevicecontrol.h b/libqsystemtest/testdevicecontrol.h
new file mode 100644
index 0000000..2969ab8
--- /dev/null
+++ b/libqsystemtest/testdevicecontrol.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of Qt Creator.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTDEVICECONTROL_H
+#define TESTDEVICECONTROL_H
+
+#include <coreplugin/ssh/sshconnection.h>
+
+#include <QtCore/QSharedPointer>
+#include <QHash>
+
+namespace Core {
+ class SshConnection;
+ class SshRemoteProcess;
+} // namespace Core
+
+namespace Qt4Test {
+
+/**
+ * A class that can communicate with a device, using a secure connection.
+ */
+class TestDeviceControl : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TestDeviceControl( Core::SshConnectionParameters &sshParam );
+ ~TestDeviceControl();
+
+ enum TestDeviceControlMode {Idle, ConfigCheck, CustomCommand, CustomBlockingCommand};
+
+ bool deviceConfiguration( QString &reply );
+ bool runCustomCommand( const QString &cmd, int timeout, QString &reply );
+ bool runCustomBlockingCommand( const QString &cmd, int timeout, QString &reply );
+
+// bool startApplication( const QString &application );
+ bool killApplication();
+
+private slots:
+ void cleanupConnection();
+
+ void processSshOutput(const QByteArray &output);
+ void handleConnected();
+ void handleConnectionError();
+ void handleProcessFinished(int exitStatus);
+
+private:
+ bool initConnection();
+ QString parseOutput();
+ void runBlockingCommand( TestDeviceControlMode mode, const QString &cmd, int timeout);
+ void waitForCommandToFinish(int timeout);
+
+ TestDeviceControlMode control_mode;
+
+ Core::SshConnectionParameters m_server;
+ QSharedPointer<Core::SshConnection> m_connection;
+ QSharedPointer<Core::SshRemoteProcess> m_testProcess;
+ QString m_deviceTestOutput;
+ bool m_qtVersionOk;
+
+ bool reply_ok;
+ QString reply_txt;
+ QString m_cmd;
+};
+
+} // namespace Qt4Test
+
+#endif // TESTDEVICECONTROL_H
diff --git a/mk_src_package b/mk_src_package
new file mode 100755
index 0000000..36c112e
--- /dev/null
+++ b/mk_src_package
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+
+my $pwd = $ENV{PWD};
+print "$pwd\n";
+
+if (! -e "$pwd/qtuitest.pro") {
+ die "Please run mk_src_package from root of the src tree\n";
+}
+
+system( "mkdir -p $pwd/coreplugin/ssh" );
+system( "mkdir -p $pwd/botan" );
+
+system( "cp $pwd/../creator-qtest/src/plugins/coreplugin/core_global.h $pwd/coreplugin");
+system( "cp -r $pwd/../creator-qtest/src/plugins/coreplugin/ssh $pwd/coreplugin");
+system( "cp -r $pwd/../creator-qtest/src/libs/3rdparty/botan $pwd");
diff --git a/qtuitest-for-creator.pro b/qtuitest-for-creator.pro
index bdd0fc9..b861e03 100644
--- a/qtuitest-for-creator.pro
+++ b/qtuitest-for-creator.pro
@@ -1,6 +1,7 @@
TEMPLATE=subdirs
-SUBDIRS=libqtuitest libqtslave plugins qtbindings libqsystemtest interpreter
+SUBDIRS+=libqtuitest libqtslave plugins qtbindings libqsystemtest interpreter
CONFIG+=ordered
!no_examples:SUBDIRS+=examples
!no_tests:SUBDIRS+=tests
+
diff --git a/qtuitest-host.pri b/qtuitest-host.pri
index 381e00e..0d80a8b 100644
--- a/qtuitest-host.pri
+++ b/qtuitest-host.pri
@@ -18,7 +18,6 @@ HEADERS +=\
RESOURCES += $$QTUITEST_SRC/interpreter/scripts.qrc
INCLUDEPATH += $$QTUITEST_SRC/libqsystemtest $$QTUITEST_SRC/interpreter $$QTUITEST_SRC $$QTUITEST_SRC/libqtuitest
-#VPATH+=$$PWD
# stuff to include libqsystemtest
FORMS +=\
@@ -34,7 +33,8 @@ SEMI_PRIVATE_HEADERS += \
HEADERS +=\
# $$QTUITEST_SRC/libqsystemtest/gracefulquit.h \
$$QTUITEST_SRC/libqsystemtest/qabstracttest.h \
- $$QTUITEST_SRC/libqsystemtest/qsystemtest.h
+ $$QTUITEST_SRC/libqsystemtest/qsystemtest.h \
+ $$QTUITEST_SRC/libqsystemtest/testdevicecontrol.h
SOURCES +=\
# $$QTUITEST_SRC/libqsystemtest/gracefulquit.cpp \
@@ -43,7 +43,8 @@ SOURCES +=\
$$QTUITEST_SRC/libqsystemtest/qtestverifydlg.cpp \
$$QTUITEST_SRC/libqsystemtest/qsystemtest.cpp \
$$QTUITEST_SRC/libqsystemtest/qsystemtest_p.cpp \
- $$QTUITEST_SRC/libqsystemtest/qsystemtestmaster.cpp
+ $$QTUITEST_SRC/libqsystemtest/qsystemtestmaster.cpp \
+ $$QTUITEST_SRC/libqsystemtest/testdevicecontrol.cpp
HEADERS*=$$SEMI_PRIVATE_HEADERS $$PRIVATE_HEADERS
diff --git a/qtuitest.pro b/qtuitest.pro
index c018f28..094590c 100644
--- a/qtuitest.pro
+++ b/qtuitest.pro
@@ -1,3 +1,11 @@
+TEMPLATE=subdirs
+CONFIG += ordered
+
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD/botan/build
+
+SUBDIRS += botan
+
include(qtuitest-for-creator.pro)
system(echo QMAKEFEATURES+=$$PWD/features >> $$OUT_PWD/.qmake.cache)
@@ -14,7 +22,6 @@ mac {
system(echo BUILDROOT='$$OUT_PWD' >> $$OUT_PWD/.qmake.cache)
}
-
symbian {
SUBDIRS-=qtbindings libqsystemtest interpreter
system(echo SRCROOT=$$PWD >> $$OUT_PWD/.qmake.cache)