aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mtn-ignore9
-rw-r--r--Attic/gtk/Makefile18
-rw-r--r--Attic/gtk/dsa.cpp566
-rw-r--r--Attic/gtk/gtk_ui.cpp79
-rw-r--r--Attic/gtk/gtk_ui.h27
-rw-r--r--Attic/gtk/readme.txt18
-rw-r--r--botan_version.py8
-rw-r--r--checks/check.cpp14
-rw-r--r--checks/cvc_tests.cpp18
-rw-r--r--checks/dolook.cpp4
-rw-r--r--checks/ec_tests.cpp36
-rw-r--r--checks/ecdh.cpp6
-rw-r--r--checks/ecdsa.cpp24
-rw-r--r--checks/nist_tests/Makefile6
-rw-r--r--checks/nist_tests/x509test.cpp93
-rw-r--r--checks/pk.cpp13
-rw-r--r--checks/pk_bench.cpp15
-rw-r--r--checks/validate.cpp2
-rw-r--r--checks/validate.dat652
-rw-r--r--checks/x509.cpp2
-rwxr-xr-xconfigure.py437
-rw-r--r--doc/_templates/layout.html9
-rw-r--r--doc/algos.txt90
-rw-r--r--doc/api.tex2964
-rw-r--r--doc/architecture.pdfbin463402 -> 0 bytes
-rw-r--r--doc/bigint.txt104
-rw-r--r--doc/build_log.txt231
-rw-r--r--doc/building.tex444
-rw-r--r--doc/building.txt433
-rw-r--r--doc/conf.py243
-rw-r--r--doc/contents.txt42
-rw-r--r--doc/credits.txt158
-rw-r--r--doc/download.txt100
-rw-r--r--doc/examples/GNUmakefile2
-rw-r--r--doc/examples/asn1.cpp86
-rw-r--r--doc/examples/bcrypt.cpp7
-rw-r--r--doc/examples/ca.cpp17
-rw-r--r--doc/examples/dh.cpp41
-rw-r--r--doc/examples/dsa_kgen.cpp42
-rw-r--r--doc/examples/dsa_sign.cpp14
-rw-r--r--doc/examples/dsa_ver.cpp49
-rw-r--r--doc/examples/eax.vec (renamed from doc/examples/eax_tv.txt)0
-rw-r--r--doc/examples/eax_test.cpp2
-rw-r--r--doc/examples/ecdsa.cpp2
-rw-r--r--doc/examples/fpe.cpp21
-rw-r--r--doc/examples/pkcs10.cpp23
-rwxr-xr-xdoc/examples/python/cipher.py (renamed from doc/python/cipher.py)0
-rwxr-xr-xdoc/examples/python/cryptobox.py (renamed from doc/python/cryptobox.py)0
-rwxr-xr-xdoc/examples/python/nisttest.py (renamed from doc/python/nisttest.py)2
-rw-r--r--doc/examples/python/results.vec (renamed from doc/python/results.txt)0
-rwxr-xr-xdoc/examples/python/rng_test.py (renamed from doc/python/rng_test.py)0
-rwxr-xr-xdoc/examples/python/rsa.py (renamed from doc/python/rsa.py)0
-rw-r--r--doc/examples/readme.txt77
-rw-r--r--doc/examples/rsa_kgen.cpp34
-rw-r--r--doc/examples/self_sig.cpp16
-rw-r--r--doc/examples/socket.h257
-rw-r--r--doc/examples/tls_client.cpp30
-rw-r--r--doc/examples/tls_server.cpp20
-rw-r--r--doc/examples/x509info.cpp35
-rw-r--r--doc/faq.txt209
-rw-r--r--doc/filters.txt780
-rw-r--r--doc/fips140.tex156
-rw-r--r--doc/firststep.txt107
-rw-r--r--doc/fpe.txt58
-rw-r--r--doc/indent.el16
-rw-r--r--doc/index.txt90
-rw-r--r--doc/insito_manual.pdfbin150405 -> 0 bytes
-rw-r--r--doc/internals.tex179
-rw-r--r--doc/kdf.txt37
-rw-r--r--doc/license.txt91
-rw-r--r--doc/log.txt3593
-rw-r--r--doc/lowlevel.txt236
-rw-r--r--doc/old_tutorial.tex880
-rw-r--r--doc/passhash.txt117
-rw-r--r--doc/pbkdf.txt76
-rw-r--r--doc/pgpkey.txt43
-rw-r--r--doc/pgpkeys.asc83
-rw-r--r--doc/pubkey.txt541
-rw-r--r--doc/python.tex68
-rw-r--r--doc/rng.txt129
-rwxr-xr-xdoc/scripts/comba.py65
-rwxr-xr-xdoc/scripts/combine_bmarks.pl120
-rwxr-xr-xdoc/scripts/dist.sh68
-rwxr-xr-xdoc/scripts/print_deps.py70
-rwxr-xr-xdoc/scripts/update_deps.py41
-rw-r--r--doc/secmem.txt81
-rw-r--r--doc/ssl.txt58
-rw-r--r--doc/support.txt19
-rw-r--r--doc/thanks.txt53
-rw-r--r--doc/tutorial.tex141
-rw-r--r--doc/users.txt111
-rw-r--r--doc/x509.txt527
-rw-r--r--readme.txt35
-rw-r--r--src/alloc/alloc_mmap/mmap_mem.cpp16
-rw-r--r--src/alloc/secmem.h7
-rw-r--r--src/asn1/alg_id.cpp12
-rw-r--r--src/block/aes/aes.cpp2
-rw-r--r--src/block/aes_ni/aes_ni.cpp (renamed from src/block/aes_intel/aes_intel.cpp)28
-rw-r--r--src/block/aes_ni/aes_ni.h (renamed from src/block/aes_intel/aes_intel.h)24
-rw-r--r--src/block/aes_ni/info.txt (renamed from src/block/aes_intel/info.txt)2
-rw-r--r--src/block/aes_ssse3/aes_ssse3.cpp58
-rw-r--r--src/block/des/des.cpp3
-rw-r--r--src/block/idea_sse2/idea_sse2.cpp28
-rw-r--r--src/block/noekeon_simd/info.txt2
-rw-r--r--src/block/noekeon_simd/noekeon_simd.cpp14
-rw-r--r--src/block/serpent/serpent.cpp3
-rw-r--r--src/block/serpent_simd/info.txt6
-rw-r--r--src/block/serpent_simd/serp_simd.cpp433
-rw-r--r--src/block/serpent_simd/serp_simd_sbox.h425
-rw-r--r--src/block/serpent_x86_32/info.txt (renamed from src/block/serpent_ia32/info.txt)6
-rw-r--r--src/block/serpent_x86_32/serp_x86_32.cpp (renamed from src/block/serpent_ia32/serp_ia32.cpp)22
-rw-r--r--src/block/serpent_x86_32/serp_x86_32.h (renamed from src/block/serpent_ia32/serp_ia32.h)12
-rw-r--r--src/block/serpent_x86_32/serp_x86_32_imp.S (renamed from src/block/serpent_ia32/serp_ia32_imp.S)22
-rw-r--r--src/block/square/square.cpp2
-rw-r--r--src/block/twofish/twofish.cpp3
-rw-r--r--src/block/xtea_simd/info.txt2
-rw-r--r--src/build-data/arch/arm.txt52
-rw-r--r--src/build-data/arch/hitachi-sh.txt7
-rw-r--r--src/build-data/arch/ppc32.txt (renamed from src/build-data/arch/ppc.txt)13
-rw-r--r--src/build-data/arch/ppc64.txt1
-rw-r--r--src/build-data/arch/sparc32.txt2
-rw-r--r--src/build-data/arch/sparc64.txt6
-rw-r--r--src/build-data/arch/superh.txt5
-rw-r--r--src/build-data/arch/x86_32.txt (renamed from src/build-data/arch/ia32.txt)11
-rw-r--r--src/build-data/arch/x86_64.txt (renamed from src/build-data/arch/amd64.txt)5
-rw-r--r--src/build-data/botan-config.in6
-rw-r--r--src/build-data/botan.doxy.in66
-rw-r--r--src/build-data/botan.pc.in4
-rw-r--r--src/build-data/buildh.in4
-rw-r--r--src/build-data/cc/bcc.txt1
-rw-r--r--src/build-data/cc/clang.txt9
-rw-r--r--src/build-data/cc/ekopath.txt7
-rw-r--r--src/build-data/cc/gcc.txt55
-rw-r--r--src/build-data/cc/icc.txt2
-rw-r--r--src/build-data/cc/msvc.txt4
-rw-r--r--src/build-data/cc/open64.txt2
-rw-r--r--src/build-data/cc/pgi.txt2
-rw-r--r--src/build-data/cc/sunstudio.txt10
-rw-r--r--src/build-data/innosetup.in6
-rw-r--r--src/build-data/makefile/nmake.in6
-rw-r--r--src/build-data/makefile/unix.in35
-rw-r--r--src/build-data/makefile/unix_shr.in50
-rw-r--r--src/build-data/os/beos.txt14
-rw-r--r--src/build-data/os/haiku.txt15
-rw-r--r--src/build-data/os/mingw.txt3
-rw-r--r--src/build-data/os/qnx.txt4
-rw-r--r--src/build-data/os/solaris.txt3
-rw-r--r--src/cert/cvc/cvc_self.cpp2
-rw-r--r--src/cert/cvc/info.txt2
-rw-r--r--src/cert/x509ca/x509_ca.cpp2
-rw-r--r--src/cert/x509cert/x509_ext.cpp15
-rw-r--r--src/cert/x509cert/x509cert.cpp8
-rw-r--r--src/cms/cms_algo.cpp2
-rw-r--r--src/cms/cms_dec.cpp4
-rw-r--r--src/cms/cms_enc.cpp2
-rw-r--r--src/cms/info.txt2
-rw-r--r--src/codec/base64/base64.cpp150
-rw-r--r--src/codec/base64/base64.h70
-rw-r--r--src/codec/hex/hex.cpp11
-rw-r--r--src/constructs/fpe_fe1/fpe_fe1.cpp (renamed from src/constructs/fpe/fpe.cpp)18
-rw-r--r--src/constructs/fpe_fe1/fpe_fe1.h (renamed from src/constructs/fpe/fpe.h)14
-rw-r--r--src/constructs/fpe_fe1/info.txt (renamed from src/constructs/fpe/info.txt)2
-rw-r--r--src/engine/aes_isa_eng/aes_isa_engine.cpp12
-rw-r--r--src/engine/asm_engine/asm_engine.cpp44
-rw-r--r--src/engine/asm_engine/asm_engine.h4
-rw-r--r--src/engine/simd_engine/info.txt4
-rw-r--r--src/entropy/beos_stats/es_beos.cpp2
-rw-r--r--src/entropy/beos_stats/info.txt4
-rw-r--r--src/entropy/dev_random/dev_random.cpp1
-rw-r--r--src/entropy/dev_random/info.txt4
-rw-r--r--src/entropy/egd/es_egd.cpp2
-rw-r--r--src/entropy/hres_timer/hres_timer.cpp4
-rw-r--r--src/entropy/unix_procs/info.txt4
-rw-r--r--src/entropy/unix_procs/unix_cmd.cpp1
-rw-r--r--src/filters/codec_filt/b64_filt.cpp137
-rw-r--r--src/filters/codec_filt/b64_filt.h10
-rw-r--r--src/filters/codec_filt/hex_filt.h4
-rw-r--r--src/filters/fd_unix/info.txt4
-rw-r--r--src/hash/bmw_512/bmw_512.cpp (renamed from src/hash/bmw/bmw_512.cpp)0
-rw-r--r--src/hash/bmw_512/bmw_512.h (renamed from src/hash/bmw/bmw_512.h)0
-rw-r--r--src/hash/bmw_512/info.txt (renamed from src/hash/bmw/info.txt)0
-rw-r--r--src/hash/md4_x86_32/info.txt (renamed from src/hash/md4_ia32/info.txt)6
-rw-r--r--src/hash/md4_x86_32/md4_x86_32.cpp (renamed from src/hash/md4_ia32/md4_ia32.cpp)12
-rw-r--r--src/hash/md4_x86_32/md4_x86_32.h (renamed from src/hash/md4_ia32/md4_ia32.h)10
-rw-r--r--src/hash/md4_x86_32/md4_x86_32_imp.S (renamed from src/hash/md4_ia32/md4_ia32_imp.S)10
-rw-r--r--src/hash/md5_x86_32/info.txt (renamed from src/hash/md5_ia32/info.txt)6
-rw-r--r--src/hash/md5_x86_32/md5_x86_32.cpp (renamed from src/hash/md5_ia32/md5_ia32.cpp)10
-rw-r--r--src/hash/md5_x86_32/md5_x86_32.h (renamed from src/hash/md5_ia32/md5_ia32.h)10
-rw-r--r--src/hash/md5_x86_32/md5_x86_32_imp.S (renamed from src/hash/md5_ia32/md5_ia32_imp.S)10
-rw-r--r--src/hash/sha1/sha160.cpp8
-rw-r--r--src/hash/sha1_ia32/sha1_ia32.h31
-rw-r--r--src/hash/sha1_sse2/sha1_sse2.cpp11
-rw-r--r--src/hash/sha1_x86_32/info.txt (renamed from src/hash/sha1_ia32/info.txt)6
-rw-r--r--src/hash/sha1_x86_32/sha1_x86_32.cpp (renamed from src/hash/sha1_ia32/sha1_ia32.cpp)10
-rw-r--r--src/hash/sha1_x86_32/sha1_x86_32.h31
-rw-r--r--src/hash/sha1_x86_32/sha1_x86_32_imp.S (renamed from src/hash/sha1_ia32/sha1_ia32_imp.S)14
-rw-r--r--src/hash/sha1_x86_64/info.txt (renamed from src/hash/sha1_amd64/info.txt)6
-rw-r--r--src/hash/sha1_x86_64/sha1_x86_64.cpp (renamed from src/hash/sha1_amd64/sha1_amd64.cpp)8
-rw-r--r--src/hash/sha1_x86_64/sha1_x86_64.h (renamed from src/hash/sha1_amd64/sha1_amd64.h)8
-rw-r--r--src/hash/sha1_x86_64/sha1_x86_64_imp.S (renamed from src/hash/sha1_amd64/sha1_amd64_imp.S)8
-rw-r--r--src/hash/sha2_32/sha2_32.cpp200
-rw-r--r--src/hash/sha2_32/sha2_32.h10
-rw-r--r--src/hash/sha2_64/sha2_64.cpp234
-rw-r--r--src/hash/sha2_64/sha2_64.h8
-rw-r--r--src/hash/skein/skein_512.cpp12
-rw-r--r--src/kdf/prf_ssl3/info.txt (renamed from src/kdf/ssl_prf/info.txt)0
-rw-r--r--src/kdf/prf_ssl3/prf_ssl3.cpp (renamed from src/kdf/ssl_prf/prf_ssl3.cpp)0
-rw-r--r--src/kdf/prf_ssl3/prf_ssl3.h (renamed from src/kdf/ssl_prf/prf_ssl3.h)0
-rw-r--r--src/kdf/prf_tls/info.txt (renamed from src/kdf/tls_prf/info.txt)0
-rw-r--r--src/kdf/prf_tls/prf_tls.cpp (renamed from src/kdf/tls_prf/prf_tls.cpp)0
-rw-r--r--src/kdf/prf_tls/prf_tls.h (renamed from src/kdf/tls_prf/prf_tls.h)0
-rw-r--r--src/kdf/prf_x942/info.txt (renamed from src/kdf/x942_prf/info.txt)0
-rw-r--r--src/kdf/prf_x942/prf_x942.cpp (renamed from src/kdf/x942_prf/prf_x942.cpp)0
-rw-r--r--src/kdf/prf_x942/prf_x942.h (renamed from src/kdf/x942_prf/prf_x942.h)0
-rw-r--r--src/libstate/lookup.cpp57
-rw-r--r--src/libstate/lookup.h30
-rw-r--r--src/math/bigint/bigint.cpp54
-rw-r--r--src/math/bigint/bigint.h7
-rw-r--r--src/math/ec_gfp/curve_gfp.h (renamed from src/math/numbertheory/curve_gfp.h)57
-rw-r--r--src/math/ec_gfp/info.txt16
-rw-r--r--src/math/ec_gfp/point_gfp.cpp (renamed from src/math/numbertheory/point_gfp.cpp)267
-rw-r--r--src/math/ec_gfp/point_gfp.h (renamed from src/math/numbertheory/point_gfp.h)54
-rw-r--r--src/math/mp/info.txt6
-rw-r--r--src/math/mp/monty_generic/info.txt5
-rw-r--r--src/math/mp/monty_generic/mp_monty.cpp72
-rw-r--r--src/math/mp/mp_asm.cpp3
-rw-r--r--src/math/mp/mp_asm64/info.txt3
-rw-r--r--src/math/mp/mp_core.h36
-rw-r--r--src/math/mp/mp_generic/mp_asm.h2
-rw-r--r--src/math/mp/mp_monty.cpp99
-rw-r--r--src/math/mp/mp_msvc64/info.txt2
-rw-r--r--src/math/mp/mp_mulop.cpp (renamed from src/math/mp/mulop_generic/mp_mulop.cpp)0
-rw-r--r--src/math/mp/mp_x86_32/info.txt (renamed from src/math/mp/mp_ia32/info.txt)2
-rw-r--r--src/math/mp/mp_x86_32/mp_asm.h (renamed from src/math/mp/mp_ia32/mp_asm.h)2
-rw-r--r--src/math/mp/mp_x86_32/mp_asmi.h (renamed from src/math/mp/mp_ia32/mp_asmi.h)0
-rw-r--r--src/math/mp/mp_x86_32_msvc/info.txt (renamed from src/math/mp/mp_ia32_msvc/info.txt)2
-rw-r--r--src/math/mp/mp_x86_32_msvc/mp_asmi.h (renamed from src/math/mp/mp_ia32_msvc/mp_asmi.h)0
-rw-r--r--src/math/mp/mp_x86_64/info.txt (renamed from src/math/mp/mp_amd64/info.txt)2
-rw-r--r--src/math/mp/mp_x86_64/mp_asm.h (renamed from src/math/mp/mp_amd64/mp_asm.h)4
-rw-r--r--src/math/mp/mp_x86_64/mp_asmi.h (renamed from src/math/mp/mp_amd64/mp_asmi.h)2
-rw-r--r--src/math/mp/mulop_generic/info.txt5
-rw-r--r--src/math/numbertheory/info.txt7
-rw-r--r--src/math/numbertheory/pow_mod.cpp7
-rw-r--r--src/math/numbertheory/powm_mnt.cpp58
-rw-r--r--src/math/numbertheory/reducer.cpp64
-rw-r--r--src/math/numbertheory/reducer.h4
-rw-r--r--src/passhash/bcrypt/bcrypt.cpp10
-rw-r--r--src/passhash/passhash9/passhash9.cpp13
-rw-r--r--src/passhash/passhash9/passhash9.h14
-rw-r--r--src/pk_pad/eme1/eme1.cpp59
-rw-r--r--src/pubkey/ec_group/ec_group.cpp (renamed from src/pubkey/ec_dompar/ec_dompar.cpp)26
-rw-r--r--src/pubkey/ec_group/ec_group.h (renamed from src/pubkey/ec_dompar/ec_dompar.h)23
-rw-r--r--src/pubkey/ec_group/info.txt (renamed from src/pubkey/ec_dompar/info.txt)7
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp36
-rw-r--r--src/pubkey/ecc_key/ecc_key.h26
-rw-r--r--src/pubkey/ecc_key/info.txt3
-rw-r--r--src/pubkey/ecdh/ecdh.h8
-rw-r--r--src/pubkey/ecdh/info.txt2
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp5
-rw-r--r--src/pubkey/ecdsa/ecdsa.h22
-rw-r--r--src/pubkey/ecdsa/info.txt2
-rw-r--r--src/pubkey/gost_3410/gost_3410.cpp14
-rw-r--r--src/pubkey/gost_3410/gost_3410.h16
-rw-r--r--src/pubkey/gost_3410/info.txt2
-rw-r--r--src/simd/info.txt (renamed from src/utils/simd_32/info.txt)7
-rw-r--r--src/simd/simd_32.h30
-rw-r--r--src/simd/simd_altivec/info.txt9
-rw-r--r--src/simd/simd_altivec/simd_altivec.h (renamed from src/utils/simd_32/simd_altivec.h)0
-rw-r--r--src/simd/simd_scalar/info.txt7
-rw-r--r--src/simd/simd_scalar/simd_scalar.h (renamed from src/utils/simd_32/simd_scalar.h)0
-rw-r--r--src/simd/simd_sse2/info.txt9
-rw-r--r--src/simd/simd_sse2/simd_sse2.h (renamed from src/utils/simd_32/simd_sse.h)6
-rw-r--r--src/ssl/hello.cpp5
-rw-r--r--src/ssl/info.txt10
-rw-r--r--src/ssl/rec_read.cpp4
-rw-r--r--src/ssl/socket.h46
-rw-r--r--src/ssl/tls_alerts.h2
-rw-r--r--src/ssl/tls_client.cpp8
-rw-r--r--src/ssl/tls_exceptn.h2
-rw-r--r--src/ssl/tls_handshake_hash.h2
-rw-r--r--src/ssl/tls_messages.h22
-rw-r--r--src/ssl/tls_record.h1
-rw-r--r--src/ssl/tls_server.cpp4
-rw-r--r--src/ssl/unix_socket/info.txt20
-rw-r--r--src/ssl/unix_socket/unx_sock.cpp206
-rw-r--r--src/ssl/unix_socket/unx_sock.h62
-rw-r--r--src/stream/ctr/ctr.cpp26
-rw-r--r--src/utils/asm_x86_32/asm_x86_32.h (renamed from src/utils/asm_ia32/asm_macr_ia32.h)6
-rw-r--r--src/utils/asm_x86_32/info.txt (renamed from src/utils/asm_ia32/info.txt)5
-rw-r--r--src/utils/asm_x86_64/asm_x86_64.h (renamed from src/utils/asm_amd64/asm_macr_amd64.h)6
-rw-r--r--src/utils/asm_x86_64/info.txt (renamed from src/utils/asm_amd64/info.txt)4
-rw-r--r--src/utils/bswap.h57
-rw-r--r--src/utils/cpuid.cpp21
-rw-r--r--src/utils/dyn_load/info.txt5
-rw-r--r--src/utils/mlock.cpp4
-rw-r--r--src/utils/simd_32/simd_32.h49
-rw-r--r--src/wrap/python/rsa.cpp18
297 files changed, 10503 insertions, 10663 deletions
diff --git a/.mtn-ignore b/.mtn-ignore
index 8be5a95a8..657db91fc 100644
--- a/.mtn-ignore
+++ b/.mtn-ignore
@@ -1,4 +1,7 @@
^Makefile.*$
+^libbotan.*\.so\..*
+^[a-z]+\.(exp|lib)$
+^[a-z]+\.(exe|dll)(\.manifest)?$
^botan-config$
^botan_all\.(cpp|h)$
^botan.pc$
@@ -9,13 +12,9 @@ callgrind.out.*
^checks/ecc_testdata/rsa_private.pkcs8.pem$
^checks/ecc_testdata/wo_dompar_private.pkcs8.pem$
^checks/nist_tests/x509test$
-^doc/botan.doxy$
-^doc/doxygen$
-^doc/[a-z]+\.(pdf|log|toc)$
+^doc/_static$
^doc/examples/.*\.pem$
^doc/examples/[a-z0-9_]+$
^src/wrap/perl-xs/Botan.(bs|c)$
^src/wrap/perl-xs/Makefile(\.old)?$
^src/wrap/perl-xs/.*blib$
-^[a-z]+\.(exe|dll)(\.manifest)?$
-^[a-z]+\.(exp|lib)$
diff --git a/Attic/gtk/Makefile b/Attic/gtk/Makefile
deleted file mode 100644
index 10e069bb3..000000000
--- a/Attic/gtk/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-
-LIBS=$(shell botan-config --libs) $(shell pkg-config --libs gtk+-2.0)
-IFLAGS=$(shell botan-config --cflags) $(shell pkg-config --cflags gtk+-2.0)
-
-CXX = g++
-CXXFLAGS = -Wall -W $(IFLAGS)
-
-dsa: gtk_ui.o dsa.o
- $(CXX) $^ $(LIBS) -o $@
-
-gtk_ui.o: gtk_ui.cpp gtk_ui.h
- $(CXX) $(CXXFLAGS) -c $< -o $@
-
-dsa.o: dsa.cpp gtk_ui.h
- $(CXX) $(CXXFLAGS) -c $< -o $@
-
-clean:
- rm -f dsa *.o
diff --git a/Attic/gtk/dsa.cpp b/Attic/gtk/dsa.cpp
deleted file mode 100644
index 2cd91b0e8..000000000
--- a/Attic/gtk/dsa.cpp
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- 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/pk_filts.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"
-
-static Botan::RandomNumberGenerator* rng = 0;
-
-/*
-* 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>[email protected]</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, *rng, 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)"), *rng
- ),
- 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);
- }
-
-#if 0
-/*
-* 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();
- }
-#endif
-
-/*
-* 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(*rng, Botan::DL_Group::DSA_Kosherizer, 1024);
- key = new Botan::DSA_PrivateKey(*rng, 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, *rng, 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;
-
- rng = new Botan::AutoSeeded_RNG;
-
- /* 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/Attic/gtk/gtk_ui.cpp b/Attic/gtk/gtk_ui.cpp
deleted file mode 100644
index d4e9cd238..000000000
--- a/Attic/gtk/gtk_ui.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-* GTK+ User Interface Source File
-*/
-
-#include "gtk_ui.h"
-#include <cstring>
-
-/*
-* 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;
- std::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/Attic/gtk/gtk_ui.h b/Attic/gtk/gtk_ui.h
deleted file mode 100644
index 065a4f76b..000000000
--- a/Attic/gtk/gtk_ui.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-* (C) 2006 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#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/Attic/gtk/readme.txt b/Attic/gtk/readme.txt
deleted file mode 100644
index 4f3691166..000000000
--- a/Attic/gtk/readme.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-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_version.py b/botan_version.py
new file mode 100644
index 000000000..a03dd9da7
--- /dev/null
+++ b/botan_version.py
@@ -0,0 +1,8 @@
+
+release_major = 1
+release_minor = 10
+release_patch = 0
+
+release_so_abi_rev = 0
+
+release_datestamp = 0
diff --git a/checks/check.cpp b/checks/check.cpp
index e32f57ed7..4fa1160ae 100644
--- a/checks/check.cpp
+++ b/checks/check.cpp
@@ -100,6 +100,20 @@ void test_types()
int main(int argc, char* argv[])
{
+ if(BOTAN_VERSION_MAJOR != version_major() ||
+ BOTAN_VERSION_MINOR != version_minor() ||
+ BOTAN_VERSION_PATCH != version_patch())
+ {
+ std::cout << "Warning: linked version ("
+ << version_major() << '.'
+ << version_minor() << '.'
+ << version_patch()
+ << ") does not match version built against ("
+ << BOTAN_VERSION_MAJOR << '.'
+ << BOTAN_VERSION_MINOR << '.'
+ << BOTAN_VERSION_PATCH << ")\n";
+ }
+
try
{
OptionParser opts("help|test|validate|dyn-load=|"
diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp
index ecaf0c71b..1197c2d30 100644
--- a/checks/cvc_tests.cpp
+++ b/checks/cvc_tests.cpp
@@ -90,7 +90,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
opts.hash_alg = "SHA-256";
// creating a non sense selfsigned cert w/o dom pars
- EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
+ EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
ECDSA_PrivateKey key(rng, dom_pars);
key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng);
@@ -200,7 +200,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng)
opts.hash_alg = "SHA-160";
// creating a non sense selfsigned cert w/o dom pars
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
ECDSA_PrivateKey key(rng, dom_pars);
key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng);
@@ -225,7 +225,7 @@ 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(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
//req_in.set_domain_parameters(dom_pars);
std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key());
ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
@@ -240,7 +240,7 @@ 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(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ EC_Group dom_pars(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);
}
@@ -255,7 +255,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng)
opts.hash_alg = "SHA-256";
// creating a non sense selfsigned cert w/o dom pars
- EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
+ EC_Group dom_pars(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(EC_DOMPAR_ENC_IMPLICITCA);
@@ -299,7 +299,7 @@ void test_cvc_ado_comparison(RandomNumberGenerator& rng)
opts.hash_alg = "SHA-224";
// creating a non sense selfsigned cert w/o dom pars
- EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
+ EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
ECDSA_PrivateKey req_key(rng, dom_pars);
req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
//EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
@@ -417,14 +417,14 @@ void test_copy_and_assignment(RandomNumberGenerator&)
CHECK(cert_in == cert_ass);
EAC1_1_ADO ado_in(TEST_DATA_DIR "/ado.cvcreq");
- //EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ //EC_Group dom_pars(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(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ //EC_Group dom_pars(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);
@@ -485,7 +485,7 @@ void test_cvc_chain(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
+ EC_Group dom_pars(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");
diff --git a/checks/dolook.cpp b/checks/dolook.cpp
index 1015f4240..a8e08a96b 100644
--- a/checks/dolook.cpp
+++ b/checks/dolook.cpp
@@ -55,6 +55,8 @@ using namespace Botan;
#include "common.h"
+namespace {
+
/* A weird little hack to fit PBKDF algorithms into the validation
* suite You probably wouldn't ever want to actually use the PBKDF
* algorithms like this, the raw PBKDF interface is more convenient
@@ -279,6 +281,8 @@ Filter* lookup_encoder(const std::string& algname)
return 0;
}
+}
+
Filter* lookup(const std::string& algname,
const std::vector<std::string>& params)
{
diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp
index ab9dfe3f8..e308a5291 100644
--- a/checks/ec_tests.cpp
+++ b/checks/ec_tests.cpp
@@ -5,12 +5,16 @@
*/
-#include <botan/build.h>
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_ECC_GROUP)
+
#include <botan/bigint.h>
#include <botan/numthry.h>
#include <botan/curve_gfp.h>
#include <botan/point_gfp.h>
-#include <botan/ecdsa.h>
+#include <botan/ec_group.h>
+#include <botan/reducer.h>
#include <botan/oids.h>
using namespace Botan;
@@ -22,6 +26,7 @@ using namespace Botan;
#include "validate.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"; }
@@ -38,7 +43,7 @@ PointGFp create_random_point(RandomNumberGenerator& rng,
{
const BigInt& p = curve.get_p();
- const Modular_Reducer& mod_p = curve.mod_p();
+ Modular_Reducer mod_p(p);
while(true)
{
@@ -172,7 +177,7 @@ void test_point_transformation ()
std::cout << "." << std::flush;
// get a vailid point
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
PointGFp p = dom_pars.get_base_point();
// get a copy
@@ -186,7 +191,7 @@ void test_point_mult ()
{
std::cout << "." << std::flush;
- EC_Domain_Params secp160r1(OIDS::lookup("secp160r1"));
+ EC_Group secp160r1(OIDS::lookup("secp160r1"));
const CurveGFp& curve = secp160r1.get_curve();
@@ -637,9 +642,9 @@ 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(OID("1.3.132.0.8"));
+ //EC_Group dom_pars = global_config().get_ec_dompar("1.3.132.0.8");
+ //EC_Group dom_pars("1.3.132.0.8");
+ EC_Group dom_pars(OID("1.3.132.0.8"));
PointGFp p = dom_pars.get_base_point();
//store point (to std::string)
@@ -724,7 +729,7 @@ void test_mult_by_order()
std::cout << "." << std::flush;
// generate point
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
PointGFp p = dom_pars.get_base_point();
PointGFp shouldBeZero = p * dom_pars.get_order();
@@ -735,7 +740,7 @@ void test_point_swap(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(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()));
@@ -756,7 +761,7 @@ void test_point_swap(RandomNumberGenerator& rng)
void test_mult_sec_mass(RandomNumberGenerator& rng)
{
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
for(int i = 0; i<50; i++)
{
std::cout << "." << std::flush;
@@ -775,7 +780,7 @@ void test_curve_cp_ctor()
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
CurveGFp curve(dom_pars.get_curve());
}
@@ -813,3 +818,10 @@ void do_ec_tests(RandomNumberGenerator& rng)
std::cout << std::endl;
}
+#else
+
+void do_ec_tests(Botan::RandomNumberGenerator& rng)
+ {
+ }
+
+#endif
diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp
index a63742f2f..c641796d6 100644
--- a/checks/ecdh.cpp
+++ b/checks/ecdh.cpp
@@ -33,7 +33,7 @@ void test_ecdh_normal_derivation(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
ECDH_PrivateKey private_a(rng, dom_pars);
@@ -65,7 +65,7 @@ void test_ecdh_some_dp(RandomNumberGenerator& rng)
std::cout << "." << std::flush;
OID oid(oids[i]);
- EC_Domain_Params dom_pars(oid);
+ EC_Group dom_pars(oid);
ECDH_PrivateKey private_a(rng, dom_pars);
ECDH_PrivateKey private_b(rng, dom_pars);
@@ -91,7 +91,7 @@ void test_ecdh_der_derivation(RandomNumberGenerator& rng)
for(u32bit i = 0; i< oids.size(); i++)
{
OID oid(oids[i]);
- EC_Domain_Params dom_pars(oid);
+ EC_Group dom_pars(oid);
ECDH_PrivateKey private_a(rng, dom_pars);
ECDH_PrivateKey private_b(rng, dom_pars);
diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp
index 346c0441c..3110bf0fe 100644
--- a/checks/ecdsa.cpp
+++ b/checks/ecdsa.cpp
@@ -48,7 +48,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8")); // secp160r1
+ EC_Group dom_pars(OID("1.3.132.0.8")); // secp160r1
// n = 0x0100000000000000000001f4c8f927aed3ca752257 (21 bytes)
// -> shouldn't work with SHA224 which outputs 28 bytes
@@ -137,7 +137,7 @@ void test_sign_then_ver(RandomNumberGenerator& rng)
{
std::cout << '.' << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
ECDSA_PrivateKey ecdsa(rng, dom_pars);
PK_Signer signer(ecdsa, "EMSA1(SHA-1)");
@@ -165,19 +165,19 @@ bool test_ec_sign(RandomNumberGenerator& rng)
try
{
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
ECDSA_PrivateKey priv_key(rng, dom_pars);
std::string pem_encoded_key = PKCS8::PEM_encode(priv_key);
PK_Signer signer(priv_key, "EMSA1(SHA-224)");
PK_Verifier verifier(priv_key, "EMSA1(SHA-224)");
- for(u32bit i = 0; i != 256; ++i)
- signer.update((byte)i);
+ for(size_t i = 0; i != 256; ++i)
+ signer.update(static_cast<byte>(i));
SecureVector<byte> sig = signer.signature(rng);
for(u32bit i = 0; i != 256; ++i)
- verifier.update((byte)i);
+ verifier.update(static_cast<byte>(i));
if(!verifier.check_signature(sig))
{
std::cout << "ECDSA self-test failed!";
@@ -186,7 +186,7 @@ bool test_ec_sign(RandomNumberGenerator& rng)
// now check valid signature, different input
for(u32bit i = 1; i != 256; ++i) //starting from 1
- verifier.update((byte)i);
+ verifier.update(static_cast<byte>(i));
if(verifier.check_signature(sig))
{
@@ -198,7 +198,7 @@ bool test_ec_sign(RandomNumberGenerator& rng)
sig[sig.size()/2]++;
for(u32bit i = 0; i != 256; ++i)
- verifier.update((byte)i);
+ verifier.update(static_cast<byte>(i));
if(verifier.check_signature(sig))
{
@@ -229,7 +229,7 @@ void test_create_pkcs8(RandomNumberGenerator& rng)
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(OID("1.3.132.0.8"));
+ EC_Group dom_pars(OID("1.3.132.0.8"));
ECDSA_PrivateKey key(rng, dom_pars);
// later used by other tests :(
@@ -246,7 +246,7 @@ void test_create_and_verify(RandomNumberGenerator& rng)
{
std::cout << "." << std::flush;
- EC_Domain_Params dom_pars(OID("1.3.132.0.8"));
+ EC_Group dom_pars(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);
@@ -281,7 +281,7 @@ void test_create_and_verify(RandomNumberGenerator& rng)
CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp);
PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve );
- EC_Domain_Params dom_params(curve, p_G, bi_order_g, BigInt(1));
+ EC_Group dom_params(curve, p_G, bi_order_g, BigInt(1));
if(!p_G.on_the_curve())
throw Internal_Error("Point not on the curve");
@@ -337,7 +337,7 @@ void test_curve_registry(RandomNumberGenerator& rng)
try
{
OID oid(oids[i]);
- EC_Domain_Params dom_pars(oid);
+ EC_Group dom_pars(oid);
ECDSA_PrivateKey ecdsa(rng, dom_pars);
PK_Signer signer(ecdsa, "EMSA1(SHA-1)");
diff --git a/checks/nist_tests/Makefile b/checks/nist_tests/Makefile
index 6d0ebb78f..3fcdf212b 100644
--- a/checks/nist_tests/Makefile
+++ b/checks/nist_tests/Makefile
@@ -1,10 +1,8 @@
-BOTAN_CONFIG=botan-config
-
CC=g++
FLAGS=-g -Os -W -Wall -ansi
-LDFLAGS=$(shell $(BOTAN_CONFIG) --libs)
-CFLAGS=$(shell $(BOTAN_CONFIG) --cflags)
+LDFLAGS=-L../.. -lbotan-1.9
+CFLAGS=-I../../build/include
x509test: x509test.cpp
$(CC) $(FLAGS) $(CFLAGS) x509test.cpp $(LDFLAGS) -o x509test
diff --git a/checks/nist_tests/x509test.cpp b/checks/nist_tests/x509test.cpp
index 7f4fe94ee..0c4c04029 100644
--- a/checks/nist_tests/x509test.cpp
+++ b/checks/nist_tests/x509test.cpp
@@ -1,7 +1,7 @@
/*
- 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.
+ 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>
@@ -18,10 +18,6 @@ using namespace Botan;
#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,
@@ -265,13 +261,14 @@ void populate_expected_results()
expected_results[33] = VERIFIED;
/*
- Policy tests: a little trickier because there are other inputs which
- affect the result.
+ 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:
+ 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 should 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
@@ -283,88 +280,28 @@ void populate_expected_results()
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[45] = EXPLICT_POLICY_REQUIRED;
+ //expected_results[46] = ACCEPT;
+ //expected_results[47] = EXPLICT_POLICY_REQUIRED;
+
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;
diff --git a/checks/pk.cpp b/checks/pk.cpp
index 18cbb9f70..e11578523 100644
--- a/checks/pk.cpp
+++ b/checks/pk.cpp
@@ -498,15 +498,16 @@ u32bit validate_dsa_sig(const std::string& algo,
}
u32bit validate_ecdsa_sig(const std::string& algo,
- const std::vector<std::string>& str)
+ const std::vector<std::string>& str,
+ RandomNumberGenerator& rng)
{
if(str.size() != 5)
throw std::runtime_error("Invalid input from pk_valid.dat");
#if defined(BOTAN_HAS_ECDSA)
- EC_Domain_Params group(OIDS::lookup(str[0]));
- ECDSA_PrivateKey ecdsa(group, to_bigint(str[1]));
+ EC_Group group(OIDS::lookup(str[0]));
+ ECDSA_PrivateKey ecdsa(rng, group, to_bigint(str[1]));
std::string emsa = algo.substr(6, std::string::npos);
@@ -529,7 +530,7 @@ u32bit validate_gost_ver(const std::string& algo,
#if defined(BOTAN_HAS_GOST_34_10_2001)
- EC_Domain_Params group(OIDS::lookup(str[0]));
+ EC_Group group(OIDS::lookup(str[0]));
PointGFp public_point = OS2ECP(hex_decode(str[1]), group.get_curve());
@@ -696,7 +697,7 @@ void do_pk_keygen_tests(RandomNumberGenerator& rng)
#define EC_KEY(TYPE, GROUP) \
{ \
- TYPE key(rng, EC_Domain_Params(OIDS::lookup(GROUP))); \
+ TYPE key(rng, EC_Group(OIDS::lookup(GROUP))); \
key.check_key(rng, true); \
validate_save_and_load(&key, rng); \
std::cout << '.' << std::flush; \
@@ -855,7 +856,7 @@ u32bit do_pk_validation_tests(const std::string& filename,
new_errors = validate_dsa_ver(algorithm, substr);
else if(algorithm.find("ECDSA/") == 0)
- new_errors = validate_ecdsa_sig(algorithm, substr);
+ new_errors = validate_ecdsa_sig(algorithm, substr, rng);
else if(algorithm.find("GOST_3410_VA/") == 0)
new_errors = validate_gost_ver(algorithm, substr);
diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp
index 8e7c35763..449ff7730 100644
--- a/checks/pk_bench.cpp
+++ b/checks/pk_bench.cpp
@@ -65,6 +65,9 @@ using namespace Botan;
#include <memory>
#include <set>
+#define BENCH_FAULT_PROT DISABLE_FAULT_PROTECTION
+//#define BENCH_FAULT_PROT ENABLE_FAULT_PROTECTION
+
namespace {
const char* ec_domains[] = {
@@ -305,7 +308,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng,
{
for(size_t j = 0; ec_domains[j]; j++)
{
- EC_Domain_Params params(OIDS::lookup(ec_domains[j]));
+ EC_Group params(ec_domains[j]);
const size_t pbits = params.get_curve().get_p().bits();
@@ -329,7 +332,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng,
ECDSA_PrivateKey key(rng, params);
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, DISABLE_FAULT_PROTECTION);
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
@@ -354,7 +357,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng,
{
for(size_t j = 0; ec_domains[j]; j++)
{
- EC_Domain_Params params(OIDS::lookup(ec_domains[j]));
+ EC_Group params(ec_domains[j]);
const size_t pbits = params.get_curve().get_p().bits();
@@ -371,7 +374,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng,
GOST_3410_PrivateKey key(rng, params);
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, DISABLE_FAULT_PROTECTION);
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
@@ -396,7 +399,7 @@ void benchmark_ecdh(RandomNumberGenerator& rng,
{
for(size_t j = 0; ec_domains[j]; j++)
{
- EC_Domain_Params params(OIDS::lookup(ec_domains[j]));
+ EC_Group params(ec_domains[j]);
size_t pbits = params.get_curve().get_p().bits();
@@ -478,7 +481,7 @@ void benchmark_dsa_nr(RandomNumberGenerator& rng,
algo_name = key.algo_name();
keygen_timer.stop();
- PK_Signer sig(key, padding, IEEE_1363, DISABLE_FAULT_PROTECTION);
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
PK_Verifier ver(key, padding);
benchmark_sig_ver(ver, sig, verify_timer,
diff --git a/checks/validate.cpp b/checks/validate.cpp
index 9acf73419..d79f9783a 100644
--- a/checks/validate.cpp
+++ b/checks/validate.cpp
@@ -239,7 +239,7 @@ bool test_passhash(RandomNumberGenerator& rng)
for(byte alg_id = 0; alg_id <= 2; ++alg_id)
{
- std::string gen_hash = generate_passhash9(input, alg_id, rng, 1);
+ std::string gen_hash = generate_passhash9(input, rng, 2, alg_id);
if(!check_passhash9(input, gen_hash))
return false;
diff --git a/checks/validate.dat b/checks/validate.dat
index a7744af9b..6f264ea74 100644
--- a/checks/validate.dat
+++ b/checks/validate.dat
@@ -4406,6 +4406,61 @@ D2FD8867D50D2DFE:0000000000000004:0101010101010101
0000000000000000:E2F5728F0995013C:1002911598100201
0000000000000000:1AEAC39A61F0A464:1002911698100101
+# Tests all sboxes
+01A1D6D039776742:690F5B0D9A26939B:7CA110454A1A6E57
+5CD54CA83DEF57DA:7A389D10354BD271:0131D9619DC1376E
+0248D43806F67172:868EBB51CAB4599A:07A1133E4A0B2686
+51454B582DDF440A:7178876E01F19B2A:3849674C2602319E
+42FD443059577FA2:AF37FB421F8C4095:04B915BA43FEB5B6
+059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE
+0756D8E0774761D2:0CD3DA020021DC09:0170F175468FB5E6
+762514B829BF486A:EA676B2CB7DB2B7A:43297FAD38E373FE
+3BDD119049372802:DFD64A815CAF1A0F:07A7137045DA2A16
+26955F6835AF609A:5C513C9C4886C088:04689104C2FD3B2F
+164D5E404F275232:0A2AEEAE3FF4AB77:37D06BB516CB7546
+6B056E18759F5CCA:EF1BF03E5DFA575A:1F08260D1AC2465E
+004BD6EF09176062:88BF0DB6D70DEE56:584023641ABA6176
+480D39006EE762F2:A1F9915541020B56:025816164629B007
+437540C8698F3CFA:6FBF1CAFCFFD0556:49793EBC79B3258F
+072D43A077075292:2F22E49BAB7CA1AC:4FB05E1515AB73A7
+02FE55778117F12A:5A6B612CC26CCE4A:49E95D6D4CA229BF
+1D9D5C5018F728C2:5F4C038ED12B2E41:018310DC409B26D6
+305532286D6F295A:63FAC0D034D9F793:1C587F1C13924FEF
+
+# Tests the permutation
+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:3107911598080140
+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
@@ -4693,6 +4748,8 @@ D6A025B07C037A6E1E0653E828FB9E3A3587CDDA5325D4DAA743D113D995D6AF
E07306086FA442A42B107F7F355359DD972BF070C0C71FF5C37FA7C259C7E039
[IDEA]
+7409000000000000:E18315C171B83765:ED1BCC9E9267925F3132BA3A8CF9B764
+
D53FABBF94FF8B5F:1D0CB2AF1654820A:729A27ED8F5C3E8BAF16560D14C90B43
848F836780938169:D7E0468226D0FC56:729A27ED8F5C3E8BAF16560D14C90B43
819440CA2065D112:264A8BBA66959075:729A27ED8F5C3E8BAF16560D14C90B43
@@ -4720,6 +4777,86 @@ FAE6D2BEAA96826E0A141E28323C4650050A0F14191E2328050A0F14191E2328:\
85DF52005608193D2F7DE750212FB7347B7314925DE59C097B7314925DE59C09:\
00010002000300040005000600070008
+C309000000000000A02A000000000000B03D000000000000C942000000000000\
+2B4C000000000000A04E0000000000009857000000000000C860000000000000\
+0063000000000000F2660000000000008698000000000000729D000000000000\
+34A000000000000023A500000000000010AE00000000000025AE000000000000\
+30D600000000000064DB000000000000BCE1000000000000F6E7000000000000\
+4AEC00000000000080F9000000000000E0FE00000000000061FF000000000000:\
+9C3C4F44BB50DF7367DAD70E6FED04E0AEB0344116C6E41F66A1A304E822132D\
+8AFCC1727259D93DD6E742EAEF2FD8C03EAD7890DC4EFACBB8776F3439A3DB1B\
+55D47DC6BC4A43349BA9E85FE178CD1ADBDD4E9D19CA1E7659341251586E1386\
+4A8C4E93A2616A0C18890A622452AD9FD09CB1A9CDC83ABF2FCFA325FA011731\
+9C924852D426132D05DA82EEBC3C261A6036C6477FBE3F65C40B8B02C2F9D8C8\
+B3084034AB3873CF22F20759C145ECCE92CE6B557D6DB959DA0B8AD4E0DFBCEA:\
+F2022315280960F16FD09741D13F693A
+
+7CC254F81BE8E78D765A2E63339FC99A66320DB73158A35A255D051758E95ED4\
+ABB2CDC69BB454110E827441213DDC8770E93EA141E1FC673E017E97EADC6B96\
+8F385C2AECB03BFB32AF3C54EC18DB5C021AFE43FBFAAA3AFB29D1E6053C7C94\
+75D8BE6189F95CBBA8990F95B1EBF1B305EFF700E9A13AE5CA0BCBD0484764BD\
+1F231EA81C7B64C514735AC55E4B79633B706424119E09DCAAD4ACF21B10AF3B\
+33CDE3504847155CBB6F2219BA9B7DF50BE11A1C7F23F829F8A41B13B5CA4EE8\
+983238E0794D3D34BC5F4E77FACB6C05AC86212BAA1A55A2BE70B5733B045CD3\
+3694B3AFE2F0E49E4F321549FD824EA90870D4B28A2954489A0ABCD50E18A844\
+AC5BF38E4CD72D9B0942E506C433AFCDA3847F2DADD47647DE321CEC4AC430F6\
+2023856CFBB20704F4EC0BB920BA86C33E05F1ECD96733B79950A3E314D3D934\
+F75EA0F210A8F6059401BEB4BC4478FA4969E623D01ADA696A7E4C7E5125B348\
+84533A94FB319990325744EE9BBCE9E525CF08F5E9E25E5360AAD2B2D085FA54\
+D835E8D466826498D9A8877565705A8A3F62802944DE7CA5894E5759D351ADAC\
+869580EC17E485F18C0C66F17CC07CBB22FCE466DA610B63AF62BC83B4692F3A\
+FFAF271693AC071FB86D11342D8DEF4F89D4B66335C1C7E4248367D8ED9612EC\
+453902D8E50AF89D7709D1A596C1F41F95AA82CA6C49AE90CD1668BAAC7AA6F2\
+B4A8CA99B2C2372ACB08CF61C9C3805E6E0328DA4CD76A19EDD2D3994C798B00\
+22569AD418D1FEE4D9CD45A391C601FFC92AD91501432FEE150287617C13629E\
+69FC7281CD7165A63EAB49CF714BCE3A75A74F76EA7E64FF81EB61FDFEC39B67\
+BF0DE98C7E4E32BDF97C8C6AC75BA43C02F4B2ED7216ECF3014DF000108B67CF\
+99505B179F8ED4980A6103D1BCA70DBE9BBFAB0ED59801D6E5F2D6F67D3EC516\
+8E212E2DAF02C6B963C98A1F7097DE0C56891A2B211B01070DD8FD8B16C2A1A4\
+E3CFD292D2984B3561D555D16C33DDC2BCF7EDDE13EFE520C7E2ABDDA44D8188\
+1C531AEEEB66244C3B791EA8ACFB6A68F3584606472B260E0DD2EBB21F6C3A3B\
+C0542AABBA4EF8F6C7169E731108DB0460220AA74D31B55B03A00D220D475DCD\
+9B877856D5704C9C86EA0F98F2EB9C530DA7FA5AD8B0B5DB50C2FD5D095A2AA5\
+E2A3FBB71347549A316332234ECE765B7571B64D216B28712E25CF3780F9DC62\
+9CD719B01E6D4A4FD17C731F4AE97BC05A310D7B9C36EDCA5BBC02DBB5DE3D52\
+B65702D4C44C2495C897B5128030D2DB61E056FD1643C871FFCA4DB5A88A075E\
+E10933A655573B1DEEF02F6E20024981E2A07FF8E34769E311B698B9419F1822\
+A84BC8FDA2041A90F449FE154B48962DE81525CB5C8FAE6D45462786E53FA98D\
+8A718A2C75A4BC6AEEBA7F39021567EA2B8CB6871B64F561AB1CE7905B901EE5:\
+9C142A22EDF81444F47272B80A037C169E304393537CECE8003BD80F7B054406\
+3B4A141F9A99D3C6820BAD98BECD914804F389EB2A50E1E2CF22161FC78B9366\
+0E07E2686E70AC0715299C4796F3559FDA802E61CB4ABBF42BAE516BD09FA410\
+085A0A92C6F32A3797D19808D3B3D049B605852E970E5A1B8031D3DC34B5A273\
+F54ED35E21D780204F4B3C512596237153BE9FAF74A44E9A9DCBE96D628AA58B\
+1E3363A94DF540230B38A1ACA440432640E5387D92F1CC1A16F8628A4CB6229F\
+513AB926300668CF97B27643C9C9D0C3030D0CDFBBCB69C3DB199E5D392A97A5\
+1DE6C9881AE5612A69FA0EA026F2F254B929201AFB3AFC8D977C3ED6E12F0118\
+92037D0F49B0144E07A0F0556F0BAC9B3F829C233265439AF711E0B5DD6EC813\
+FD51281E8AA6F031B096C64EE8F03E041FE4DC6B5441141F2D4A308CE8EA77C6\
+483E3CF565EC49CF27A0B13F28D3C63AD7FB6B3A96579D30C9D65F7BA86E56DA\
+6D14AF3C7D170CB5BF5F21C70C1771354DA2850CFF8D9250273828C1FE60C4AC\
+086049404E3D63E04935F03B057B4783B13CF49757A8B5ABB3D2E37E54B881D2\
+36F7DF7FE80E4AE33E9125F54AA96D96BFB15607F0800B215CBF9BB0F7E29080\
+D8504E9BC1F78256593B9565E5AA5FA22032A47041B453D1B154A8D24CD59CF9\
+AA6A8E55363F3DF2B6307ABA5134D67B0DF0AE4FE77F23BF7DF8504FE9DC7F32\
+A8562E2DF585E639847DD624E55B0D0DCCDA72D0F1E072D82D4BC135DC5F7F91\
+30956D401FAB1456527FE087A436C1511CDFEA58202D200E1817E360E8400AAE\
+83B073A63596B033D7E83C6CAB7FDD7069C3B1718EAF60B937CD2458255E68FC\
+D9514FD14AA6E27EC76E75F95F0A678A0F64D49C1B9B8F8DA56DDB8CE640FF6E\
+7195F4A679165F9996F3DDF992E3CB4ED9E9084AFC0038E4BEFB467CC8170AF8\
+F004082BBCB137BBD45C124BE8CEDC89DD565A24830889CE4B9781FC18803BDA\
+1A0A4EB70DA35887B02F18CFF9329E2B7C31B0F5F0648E0508379B52C8FF91CE\
+F939A040A8C20F2F27ED65553680729A2181B3B3C4AA02BFF8DF0A9228A87BBF\
+52B48F473D0F9070C76E4DB6F09FFDFEB629BD0E1944B7016AF34187E2985AEA\
+E30D6480A58F649A0C858E1F1458388A9E822A306AC1AA7465882DE78F242EF7\
+B0CB45D68A057F00D8609587922C8FAD6F1A7FFA34BF2175FC516730A61CF82C\
+6F866C978CC292BCC1F91E6AF1785FCDAA9A43A01E6AEE91E222F8AF8C989F2A\
+4C50B7A1D45BC15E11E5E6E6EF720506B8DF564648BEBFE272C0A77D41295865\
+108150CDB3620970A37DB94F1CC35E434DC33434D99871F6141EB57C9E648AD1\
+BF70E2B7FCEB81EA871DD92F19C366EA532CA4A7BEF9242128B7ADDD308B58FF\
+F5594CB4156A03C6A6ED3F27E8DB20FB2F4208422B7E9E0A4E63A0122560CFBC:\
+67C6697351FF4AEC29CDBAABF2FBE346
+
# Randomly generated by OpenSSL
A1F4C5FC0AF894FB:1F88AD254A1653CB:69E2F555209FCA21ED36E0243F043537
55E31A38B2C91116:8D57CB7AFB401E55:BC0ED7C4A90FE4760B3D971F0F2589F6
@@ -25242,6 +25379,521 @@ B7EC0258A9AF125F2DDC80B9877EFE0F372D9B832C786770A84EA1A07CB6E1A9\
2B7E151628AED2A6ABF7158809CF4F3C:\
F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF\
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\
+202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\
+404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\
+606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\
+808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\
+A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF:\
+900BF2352D973046F4128A1489F84DB204C552D2E59FFD58844B2BEA8DC04B46\
+B1212433EA1D3704673C45222C77D3D7CF7D21199BCC1464393853EA9FE5976D\
+D8612F828173D82EAB52C10A863FA549911F9B4CD0644766BDE8412F0458C620\
+EB63CD699CFFAEB948BBE360FDC541F0912B683B72A13306E0203F444E378458\
+164F461290E3F934DA40540945D8FB455EB86271F4D55DEBF1CEDEEA08B7917C\
+2247B1261C3710D949B678CDD4D5DE857A2BCD4751F2D4C49C75D52B33A0B761\
+943CF6258DB7C13C321F2E3C43C680CADA039E3F177B88C993464EBE82732229\
+784D929235FB7E4984F1DBC72A2E0431E7BD976A2CE09931DF2C80B7B7405E8D\
+AEF482E4AC7A0E33C52EBAD9C4F854A061B047F37CF70571FACB6D2CFE6EC0CC\
+64933965D74B871150214A009E998BB078E8799E1B43232F9709F1E5602D2DA4\
+D9725D2EA8557374809285A1B48D489FF3A8A50CDA1E0920035E6924272FA194\
+2022D71C9984278B4112253349D916B17FCB93A59FBC2641EEF4DFAD6FB83AEC\
+D25A6F55F06A95CEBA94557EE07220C51D0DE32969D70DF310B8DB0E7C8B65F9\
+5BB7B14098575CAA8EE472726FF5C87E31E94664FF009793D3230A528E9FE289\
+3210E01870D0B60B1C55A6C49079BC3D97EBA815ECB8DE148A000C310DC372C6\
+F0627EBB1F0CBDB36A79A9DDADACD157B561EFD24FD523067AD3E1DF7370DD78\
+19347C5FCDD7296BD9DD9D940C7956CB8A4ABA3359538474E81613E4BEB346B7\
+4F05C66BC19594C12920CBFC145ADEBBC0511E710A490708B6DF67D8F5C5A3A8\
+09C9C256CD3A4056019E04C27D773A08BFFF86C6F5E9663DE4369AA4612EA265\
+53F5DF2314A8FDFCA42B897B5EEE64FFBB16F67BB1BFB1E5408C850848978645\
+087CDF026C9D8CB24494E42867D5010B66DE211C5E10F92D6E88784E9F423958\
+D0E50E6F153FC9D7B07894D5888B3CD0AEAEA0ADDC058083E84EBE2CA55E4916\
+79BB9476674E8B2D01E17AB60DB86CFFE48AD3C171F427EB57247A5E34970EEE\
+3A4FD9D9FBE9C5F39D326D6FFA45398F822532B8620337EC1846184BB684478E\
+A59D803BFF5F55B4B15F3DEAA58FFB550AC480876DBB16C0FB72E0C224D2FA47\
+BE2A33736208E9DC38EE0E5D050596D692718D9CD90DE7CF9203A6D1FFCD5F09\
+AF6BAD40F006313C7916AFAB0D09220B9F6C7E020EC12D4982A809193EE65DB7\
+EC04B94F580DDF15D6349279FEB9679FC9083ECD1FB1D9B58E2F81D07E586573\
+AF0C61BAFC811BA0D15186F408760314724742143B1A01AA0038EE1BF4DBAF4E\
+85CCD3412B4F17629F069E6F4F24CFB28B4DAC1B7ADF3F2AB621B62D4239C842\
+5B93CB597D2C91FD9F4E3FFC6DD70CCFDF5CD8F42E29344B6D1ECFA073C853D7\
+EB1FCB34EFF9111D90557E15B438D8AEED879991167D04BDFFD42014BD12631A\
+D879A98BA029DF7441C7242F0FFC0EF25E36391EF4D151BE45C6D6DD10B5C591\
+AA039507BF3513BFB36BAC155564B9CA65DB8B2EB74E10C7371090C1DCB54B65\
+F9427E830CF1EC7B43FDD5E7AF72C8FDF19B709A41F9458A1A69D8FE8332442F\
+5D1326597B429D065F17005C90DCBA83833369AA2F8CFE860C7B25269049425B\
+1AAAEEBF873D32246A4EDDE5C42D88DDB5EA5DA95BF7DB2B97B3C37F4593D4F8\
+BDDD2EDA804337307E6C68952FD7FC0A55E2673C08F028522CBF7000CDA1E335\
+23AB0C607CB8361E95CBEB06025636D94E945CA9E911FEA1CB37728F76D2BF77\
+6875181EABEFD2841EA068EEAD02A945AA68FB64ECAC7EBFFA9EF739D534B7BC\
+06F9B57ECE9CB9CB8D7977128567293C51E79A8126669925214AB99577019512\
+A72A537429CF5B10FE5B39AA2566AFA490C6FA42916D414173BFAEE8BAA851A7\
+3D6E55D0A48A9F47BFE67EC5D27BCE42D7DE7BF52DCE4ACBED91C5E52414D09C\
+8119A3270709EFDF1AC93598EE5D3FD58436465C65C10FBC7E5E830B9E0131D0\
+A406777FC79362F660F8D9D173499326D8D87B1A64952688D72C83ABBC5528A7\
+8F57E38E54FF82CF826878D73F7F374284181D467CBC0C1CB980BC3CD3179542\
+663B35EBDCFC45F2810A2CD83F3E8EEE11C7550C3F105153886FD0228C4368DF\
+22B3483905C4EB8CB841626CBDB46010FF6FAD1783D518E9030E0D01C1A28470\
+9E56CBB29B18E269BF32CB310AF67FDE673AAAB9D5D05FF067650E9C2320BD29\
+4AF308F97547FA907561C6759957E19727BCB6AA81B0668AA891B524A44A9747\
+188806005F497B0F06C8F29277F0532CE48306CB2AB1F4AC69189E48E958CDB2\
+52BEAC88343FD10F61D1BF2DCD2347407C4F449738D29FDB3C40BCE2381154DB\
+9B3CB1241BC1E682EF2C7845ADEDBACE1DE98218F967C058CD6861CD66FAF98A\
+D2BFE088DB945EFA1A5EC31C63F4AF18A7E26DAB81333B2D1D1B64ADB0F0B628\
+941712AC56D651AAE05C5D4C5ACB7FA3AC16A1A3D22395B76371ACC9D4CC0472\
+59B1BD1659AB6987E4CBB363B2E2378D5CCB15C41ABE14B65B920F58356653E0\
+240181B2192107884699352634712003815BEB662F3D31F1EE213E43637738F9\
+DBDDA96524CBB76FF388C93CF540968D41CD79D6F575B47E8A4C8576A34D864F\
+CF15DE44929682C7024F5B96250449649697EE056F1FDA1A0D35953F03E88DC3\
+B35913024218DF877B75BECE027A2A7EF7C76BD650E0586D404934E344B8C737\
+6A601998294C196D0D221CCBB59AE05F7DED4E355B3FAF1D0C51DAA055F92544\
+0C272D41911D83AABEB3638316F1AFBF7BFFDAD1E800F296323AA33A7853644C\
+EBF3733BA2748DE7D37B9AF8A5A4C05B74211B359B0E6B518B10A012B4F71888\
+65AFDBAC2CE1D53B9F3E8F7F80BA15D11CF2967C42662FC4177D2E3C00D3DDCF\
+581B8FF5E6544F312AC52D93B7A0789C2DFB187E10EDEAB3BA6E74B9B685F1FC\
+924974A4D0302C89C6709CFDAFDD6B235AE0326D8E22D164390620DB012B85A8\
+1560896F2C085307D07F3470887541EB5ED2065261C87ACA522E83C2CA77D9A9\
+751DF6DE35EDF82E04F55CC9A50F5646254EFF10612AE8B5010B4F1886262666\
+B997005F452CDDAD9E7FA8185F64B601171879FDDE907F8C35F8F100B942FADC\
+0D9F4FD734B462866E42CFDDE56DE0539EF8F71F0AA72DCD8DAC6BB031B89C8F\
+0A88C051C5E4E28EA5E95A925A88611EFD7EBEBE524F60A9EA32A41FE3477709\
+1D401429EE7F185EE61DA6486CE491F09A97062BE1A357DF998775143C7D1FF3\
+3A1EA9041241495473661FDF3E908AC9F5811FF83EFD6E331FF17097109FC662\
+20B989428D078263FF696CA376663888819F3AC66F0BEBDC5EE5BD48C347C124\
+FF427A47C80B92761A90664BABFAAC275A3069B13890B79E9513A935823FB608\
+23D6C76A9F88DCE6A7C1F11E3DA5068F454AA317FCF92C4BDFF500A2BEA63BB7\
+D4939F4440AE335C1E165769C5D041B31873BECA28648D44DB6628FCC0705B5E\
+4CC838C1DC8022D9B890FCD54CBA42B372610E9CE351E5FDFBE46621768A30CF\
+70969FCB37C484B2595B5291FE7E8B597DE9986271AFCD2DEE3029DADD330FD5\
+EB38D7BB5276423DEBF31DFE3BB97E36D09FC62823060A0D2636CAB111C7C9D2\
+7DE3D2436996F6CBCDADA9BF7AD9B4EFF7EED2459DAAEE42AF414BDB2C799500\
+3B2DF8474EA76BF08870317EB29AC6B46D19DFB471A8FD58EEFD58BD4436C30E\
+4A695A30B83E53854AB12D4F0CB6290385570484CD78128782C55783E73DEDD0\
+EF8330690D2CCC67A6C3A5C0E5824A4C68ED1E9DE7C047C3A27D838677EC1CA6\
+4EA21D7F51BA404CDB61F09CE2F3CAE82E68BEF8EB0BFB6F51F1D711E68BC700\
+0C57170BCE6E6CB583CDD384B031552B471DA6E4AEDFC6E696EEA1D4E48CEAC0\
+8202D8C0626D957C1BA8D367C647C95BEC5C97448F0B0DED70E3DE200ECDBC2E\
+2BF76600E838C2D52DC2799C55ACD450C5C33089485F65219B57A09756792353\
+A80184B1FEBF9F40E7C31150C35BC9ACC208693A30594CEB60FE53D4EF4852AE\
+CEF9CD128A0DAC72A323396AE9DF8406223E554CDC0D3DD2EC641FB19094239D\
+186BBCBCDB685A5ECA4945C0FA7B2F0CF0D42ABA7F5983D5B765168197B0556A\
+235AC452CC42D59BB9F27D186E1640E447AA00E3005CF5FA24BC7CD4873CFB2A\
+A4B47528F9813E1881FECB1C072288D8CFA45E2D0C52F17C49E7D73040ED49F0\
+E71B427189A9A038D6F7039B7872A41E2C55E6A95834E9BECE5C70C18F89E270\
+A2D24286EF6C027DEAC450A852804BCFBA92DFD52E7900F7F3E4A957AA4D5943\
+90CD47ED3072961B5D024AA9EFE854E692D64F3CC3123EA52F49A6F61D2316A5\
+A17374EC9FF6F043076C07D597942D25BB0BA1BD71E971C42AA5CE9BB1751134\
+2A3EB35C6DCAF8DC36F762F8B1856E5E7BF492B8A6FA8F1D8AE461515462871B\
+255966F0F5BAA52E73CAAC894C2CB56320155D4E5DBCFA84A0FEE3082D92EBEA\
+98808406E736BE2EC8F41BBE90F07919682183DBB287D7004D2C2622C4FAFCAF\
+A19A766DA033DA12E4BDF7855A08759C9FC6CA0F61B6CF96C492CA8CC168B3CB\
+F7F587B53A7EF630B5374690000D9E7B84C3AE7832F4BBDC1943378F83007660\
+DC83CB4F05E7A93BC6EA39EAF13CAB2E61C852A60A343247CDCBFD757B247539\
+9051924A93731400EB91791C5E2DA5D03F43A39CCA44F3124DEC80D433AFBACE\
+19660D0D32BEC383C1567549C112CA8055D3A1A7811A7F4F036AAE719762F98A\
+3BD8CF5FB2D9673BC163ECCCC72328F13B03CC3C249C7AFA4041C0DC76E9A809\
+4462CB41E9711A6F5E50E5D5473143F1E9AEE421D6FD88FAC95BCD75E46E25D2\
+588F7E3D7489DEE5E7AFE73AB038D4C845A92B1C0C399B698F8E532AAC023CD1\
+489B986BE46B7DA2A4B76AA76DF5F7FE1F66C282AB30ACEF5A7FD59B71AE64DF\
+858D0E0425089290913B3C4CC82DF6219DE24ABC8703ED475D8373402EF46526\
+416F2ED77AFC236C4F3EA0DAA5AD9AB949B024F340C6F1505B399FA703B6464C\
+0098FAB1A3DEDAB5BE68C2FD030DEF738CD027FAE6CD4B03A2354D20ACE3F69B\
+EDBB90A5FFC390BFD90D53695CDC136B85FA6B9649CB4841C43D5C9F649E32C4\
+10419B5EADF4D26AC0D36006D3CF4677FDD2FBFAAE156F2DA1587FFE4CEA0392\
+AE804420E2FFED43935135F441CE90B7077D8E0B0F77706AAC6A9E23DCFE15F5\
+635A0A1E1A315D8AE0489BA6DD88A1C8EB29BEC076F2E95627CD12FF4D6784FE\
+F2DBA9F5BAC6F1895E5F15AE2E51A1D65B7835CCCA3B2AC7D4AFB05E00D21051\
+9F932D184340625647DE20BFB32329C238AC096CA68E159F90CEA319683F1C0D\
+9DE2380438BB4E6DCFD358AA655D0F78C9E93B23C0F1BF13C128587E65B23C7B\
+87350F1A5B8C37B5BB5971F4A160C9A7FC3E920F050353739B4C2523F1F628E8\
+B4988047EC59E13F120CC557E14EF259CB15BEBE470008D1C0BAB2B6B50AA6FA\
+379488B3553979BE4841441F971299C46BCEB73BCFF4ABE0B2B003C7E5C110FD\
+A68D63D264F95D5E9C194B4B869F420EB9B93531396512AFBB6FED334FDBFC97\
+2E9BA42F3E3D774A7C6F1685DC8805DA4E10A150D90E79828A600F242BC2B7FC\
+2EE22BE0EA362D687E6B2E4191C268EAB6189F58968CACA413F2E6D1A413E37A\
+C4E93E8A7C3E13D992D09E7025D48E21F658F54B2354A1182F1203C21F05831B\
+7B83308DC2A8F6F2E3C97592B252E66CDF43529068D9DC78465F66CA6B29AAD0\
+C3922947EA98CCE6630EB581FB75F421D59E36DE1F4BE9D7BEEA0C75218C574F\
+B70E5927162DF36AA1DDAE51428092B8A733C8D65E884FA48B6A4A6F2D386883\
+D3BE615EEC10B3488DE1D54908AFDBDA76CC54BC71A7131DA141ECFBBFAECA0C\
+193B83E8DE2ABCDA150629D8BD1706D16E4B2BBA4FB95A4DBD1B2E73071682B7\
+B38142699C998631B31F53DE66B0C3AF8C799FE21E617F49EACCBAD64B76EAA4\
+A21E7ECDCA1114B1C64C2B2A71B5BC764EC880E866AF3EC6E3801213341C998D\
+0F00B9AD7B7DEEF21C0033247DCE567FECF294B16DDDC3346725677442A6F6FE\
+C62627521EFACD02E16123623ECDF970493B9C8B9E10156A9B2439F03096B170\
+93E5DAC3C9048EAF05CE92B8C2FB2B671AB886E5988288914B5A8DAB05909181\
+A5F9142EC46D5FA71816CD944642D0568520EB87A4307FB4B608D4EAC1EBE88D\
+D52F6549895F732CB75D495F5F2325D2B0FFFE0FB702045188BA98D603E546F0\
+9F44BB40804F4670BA22F9D188F986F00FC2BE3BC29E0D387985F564599DB2B0\
+F9149BBA7225F00D6316455E2713E43E173A9418C5C4EAF5D3CF2CA4FDA77DE4\
+66ADAB5BF8A2FE395E9DCCDF040ACD903F13F1807817251B4844B12F7723627E\
+3B66211258BAC1F45B26AF3303D1BB55241BB4EE3EB9F00050AA44DE7A81AE55\
+01EC7ABF1A1692F3CE17267A1A83E6B870777C6249780B655008FF69C6EF3A32\
+AACC1E4A8CD2CD50115EABE08E4A085AD93351DA04E5AC71C5FB74FAD7864324\
+C070765C32ADF07071632767C5D0612B4B9407EBFC3141D6D8B202DFE164CB8F\
+7112E3AE5176AA55779441B1352CF4838395A65ED5261FCD8C596CBA3684A56D\
+C2FD5E440CACB2033C945E65EB9EC0E475A7CB3E67C8D5F627F506F6CB1D5A1F\
+26F75A395056A1D8D70420B13F63834201AAEA6C11CC6E55BDE40A0ACC75255D\
+06C5921A85D621B1C32434AE8CDA7925BED56718BA59CEE88896139381809548\
+A0AF81502DB88439A48999A3B40C6FA62EBFBBB1DCB03409C73CECC4509BC4F2\
+D45E7382D4AB7F69386FBE6377876D0D30D5F4DCC6BA7330987B48C977241094\
+2B114D6F0D46AE5F3FDDA09618BCD78F0D9972DDD71DAC9801CDEB80676BBB32\
+315888E008DA9471855C2B299927FFA73EB7A4754A2F9A80500629959830BC31\
+41A6A3FCF3F529DAF588B0C415A6D237145BC3475724072D543D78F69E1F1530\
+86ADC5E28B420A3B1B81E139CE9B81F532FF557DC23BDE406373B10F5C03E230\
+8C9F51D5E0150D6128A1BF82FFE1069849CDF84FDE7E3DF994608C5E0B242088\
+9408D8DEF8DFACF31B539D3429470785FEA4E5480AA0C93B5C8225901F3177DB\
+948DE7352882A9915B8D2332A85F16A4D1CB55EEF211E3190FB718D1D302A171\
+EB57C234A5B1E5A6A297E7AE4BC65752ECAA27412D2A6835BC69229E7593A23E\
+B1224E97419BA6A17BD77F9FDBE30BE2BCCF0BEACE22576C0570DBE4FC885192\
+C11998620066D8CD92DAFD200B3D483FB825523F490CA75971D066647A885543\
+6084B047C78D6581C1FBA6276B0A7729668B3B0D7D358FFB92332C57436F2F59\
+873A1CDD128AD11341B5F256251B61C90C365D5F0768F441562B3FCD9E27A713\
+06B7C940983560461889455560D32532DCF45E9DEE3E2B3C5514E249344B4DDF\
+105774935D5AAD836B04B5E979E61E3ED7909A8384CB0C866352E7A1C7068B73\
+68BEC60EAFB4A081E553F51B09C4CE8664964F64A4031CF8934382C0EBA040C0\
+F0B2D3C1F5F3ABC3D30785E53F5F081248CC7A6A3664BAD836C1E6CCC91BA1B0\
+37B4F0F2C43AEAF9F749268D47E11F7188BC7264960AE26DB142C9801D084E0B\
+691648AE83E85AD51A0A17081F978A434C82F6572AE0AF94B4A04A5686FF61AD\
+FDDF73E6FD22F6434F3FDA4F0B2A838DF375D3FF92C9192462E8CF44F43AF70F\
+154EFB12D84EBFE48264E55769E997D6F3D200E223DC104987B9786417F3296D\
+732FD45EC48033F00688F92C7B5CDCE46E4BC8064F499F9B06EFF82B70D6ECD8\
+C5A1EB5FFE1D6C605A54DC621D6544322911E827CE798CB0A8CE73C82F863F97\
+934CABBE2CBBB2D2A2A6EBD553E8A09D8B49D87F79F29E3161DFB3EF37D5D0D9\
+A93F7C13C2A75CEDB3E61121E85273545E85942EE1C6BCC698515CB8E88E76AD\
+57BBF0FC85B10F10883AC4682A86D29CDD56E5A63751D47F06673F7891CAC946\
+0B4AA9547DFAD60374AF982423D332BE9D7EF16759FB095A698B0DA5D7B51278\
+61A8B39911F717A212C17A9368D2C1E57CDA3032C61C56B84529677905B3E351\
+D71D06D46B8D69CFF8E10D175E084ABD4B36A0A3BA424F6641E917CA1B64A2FF\
+62C6AD6DDE35A51556FDCCCF5428892E8FA6DD45626AAA1551EC7D7E8A89CC86\
+3E5AFD53A0D01ECAFB2A6268B7E0370C376F7A724B1023FFD184D900AA2C909C\
+E156458C7F2504E32FE615A90DDF360C7F0B7708399AEA3BF3549A401BEE0CA1\
+FC0D22F1871967DFEB0B740FB93151B7EDD2D807DEFDE734BD1C22A19E1D0A01\
+01071A8DE3FF8007068E2E5CC43EB334055E292F88EA02D52B9771ABD3577B22\
+E7236AA3B511C5E914AEFAE9C5B015F8AD013C109849CB5150298FD56E9CCB1D\
+B84CE6A34219303322FBF38F9735414DFFE395ABFB19F1798894EDBD1FF77530\
+741933847484965C3E25509BD31E6E6DC247E9B17AF7EE350B00816DC1DD0EA4\
+4792C6EE83541153208E0104BE27F055335718B2BA1AAFAD3EC4D62B952ABEEA\
+D95B857EFA8F26AEA3E9FCB087A80D7DDF3BF29D63BEBF3A248A8D86A4C208BB\
+7A3EE0836869074438C418254BDFC5A2A04C5FB21606B21AF22BC2631A46BD55\
+5BE9803EF4330B9F6C8C7C93478819EE8D2A0C5651C0C5AFCE5F20EDF72DBE83\
+15E0BC8BDE40F09C80E760A804DB197977217F10BDABB3A14A23B30DBF3CDB2B\
+BE9DDB141A9B115D16CE0CEED99E120514BCBD0DDD934379B9C48016A0101512\
+84377FB6B8E08A703CA401CE018F61D6D516C83F95499943EA2C818E315769C2\
+A45172DD344ED15DA05D8AB1C32E4F2E7DE3ED5BD46E956878F266E27CBD65FD\
+775B13FBE330B01C31AC5C27C8DD30F0240F5B9C024A6984FB7131C8CA04A608\
+7091292D53AF14ADE0F2190E0F427029D0F27765BBD746DE5E2A9B8933DD0CC3\
+B1CD1126551378372AB4C16AC49ECCBB107F71D7DD4175ABB0DC477E1B4FCCC4\
+2F868D7D8D737BEC4B5CE078017352D36A45CBE6E9CB676ECB84F5703445D429\
+70D99F5744A008E21A6EB7A7A699C2435FC669DA5A8DE38BA98E6611DD8DE454\
+82273C7DF9702BB10D345B826518F38789E66C62E0465D3874209350890EBBC5\
+A3F8F132341CD58E7CC9E43B22C579BD938792C8B158ADA14D94F8179DC180CB\
+B0280A6101D7BF2D17C0557F920307155E8DF1D95AE124FF9B91F9F2B9D4CE3D\
+131D6DA313EDE0F09ACC122CAD8A296B5F806BFC2CBE5D8E526F020BC5BF5D5E\
+D4728F818210F5E2A570B534DC39890CCD1FC48AB7AF86888E9453F3607401CE\
+B4C22E3F960E7A8A5C80EBA5DD3717FC1224D190D4351E4944B4C23A949614D8\
+84D2AE59D989FD53302C83D66B26088C37EDC61207234F9B8EABEF6BF457BD61\
+EF4B77D198B7A56B00FA723B4CFBB6E2CB116DAB87DE542FACC26A8A9F2B841B\
+2F26B1C0B6D22172CD5C1AC70E5C5C1288BE1BB0EFC9F2EF68E0F88B8A6DD467\
+F8C21FD4AA5C467C5D2ADBE9A72BB6F44262BBF4D23525D0D2527A06D740BC2B\
+D45A3B8CB96CD66307242351D6B6A7C1B6E67C7A84E2FBF61AAB52E5701F51C4\
+480093AEB29168AF847B48254CF04D1418C77AE1680BC564C5DF597308AFFB21\
+1B3CAB194D8AD0427AF89E0B55F65C2827CA704BE1B854A819FF87E4A6DF735D\
+107422890DA141915D1687B56D2F1C5F007684331C7C17890E887390822AED10\
+377F271A36855DD8687D9F476F3B1642F1388F121814C474778291202B97333C\
+1AC5D6E1818FAD8AA2B9446840CC0D29EEDF118D53A15763ECCD692A0A92611B\
+CC49F3A50C03A4E7C39BF3C545D9B2C2A08D3CFECBFEEC8D846D325396CE3027\
+5629AA3914B7CDDB05959A5EDB2DC952B28ADEB6B16197DC22D0F6BEB17126A1\
+E2E0C66BE205E37E4AD7FEA34DCD7B406A87A155216009AC43AE89CB0C036433\
+D736F5D9F2FE2FA091C28781602A59EDF96127C31265144B20360BD64DBDE811\
+6E84A9E41F8259D9A6CB4E3368A646413FC23D76F55B4083F4420C1157A1D9B5\
+EFC27BDF72B1FCB6617BF40CD8FFD2FCD645284321390BBB6707CE8442ED8116\
+3CA30A924CC9B5BD8BADB02CD15847F1893A7E94F82C06C19BBEC9E46B769DC8\
+53A2B9EDB14BCE4BDE8C6EA26A9510B6A8ACC62DCD55DCCC73DD962BAB314CDC\
+65F9AE4BAA7FB4563CD38CFC6A6AA7A60E6D9C9FAAFADC55A8A207E9C2ECF21C\
+343ED29113DA4E6E2EBAD2ACB1DBDA9652EBF1D20E8FA79533670DE60CFE73BC\
+F469A8D89B5D6B2DCA831CEAB441F5540B4C4EDCEFD246478BD068FFDEB22F69\
+2DE4D814CEB4C105CA55AB82398D21CF7C2F992161B7D961F2FF91DE1C0ECA85\
+4036660BBB67071690C8E2DE999C809190D8DB16CCBDD971F4A0068F98129EDD\
+0453ED31BC5724BEC70FC5CC79373CF6FA5D87562456538735D50674863F219C\
+E5B3E61B1ED02564644DAE69BC0CEFD6302464042ED1CB8B741863FE00911729\
+A0FBDEEDDD00FCAD9A80C88077750ADFFDBD921E2DB19070A41444FFEC61DC8B\
+3D0221D336A5ED40A9C7BC7461AB8121CD4E9BEFB4755EEE92B8B3EDB2751D05\
+028E5279233A44E0D4A205BA1F864FD5A0115272B4B2C7AA8E8D3D202390DCE8\
+5A47DF27909DB1CB7BDC29DF6FEEDECCC6814068F0C87513AB975977C7563E41\
+F7E0FA1864F9CC9B5778F23A11B7D67D15E7D1711F2A6CFA4AA7DB1996B73259\
+F791BB8FA73C99CA04BD837C8E7235624E6AF48EA30391B32B55EC08DF2F25B5\
+4BF663871D439C57A9400E6973B723CEAC8D55E01BE30841061CDE175DDEF36A\
+E57DFD000B38155349703E2C9D10549890B7846C61ED62A6193AD3DE03A3F242\
+75DE3FEDFAF9C384B601F0C1213F46A90BE8E3B97EA11C31880C9F905221064E\
+6A7C297E300FFFBDFC0FC6A1C05ABB0D56F9918501E3EBBE84F986CFF4E94FBC\
+1E71B98B315026E4EAB1C22634EE50BEFE7426FF41ECD53152344EA558FA9E9E\
+CF80FF1C01335021C06BC46ADB15707A025CAC95D564016EEB1D192D93B94900\
+CB346169BB1A18F91D88266D312A4BF5F050801C60FC681E3ACF1B1364422E07\
+08120AF483A664D067273293687B3E321508D59BC60B78D0C9B46D3E4E5751ED\
+038C228899BB3CC32239E5AA653012C656423222F2D04C213A5DC78005B739FA\
+F522B17AED99542BD9B6543E4E9EC1A536667B484B412802F17704B99DC3246E\
+F9180A0FFA1C269F0BAFAF79B1BE323F3F2D045A979A46A6B45EC9609C8BF2DA\
+5BD40A2454D80DA1CFF9FA75965FFACEA20CB0F8ADC881EC8360F82BB297A657\
+0BE1F8FAF0F10AE84645591974F7C246338A45443AC2B9DD7B8151A6351A001F\
+520E4C6EEC800283609F16DA88396852BBD27C4FEA4EA0C2FAC4FB6B3A8E993F\
+6E91DD06D461828F687FBB061A57E118D5B6D8EE5CFC6D453D48DBAA7CDE2C4B\
+9CC226416A0B1D3B1BC6C1F429C481C187E0F6D022ED4110A7916D891E98600E\
+A01263FBFDE28265F924F1E95F7B68C95DB4DA20EE37171BBB05637A883637D5\
+36ECDD9D7B6D36C15E255C1C024CB26BF5092A631A29B78454FDA73029266284\
+9E7B83F71D419B099E31A2420699F4F37378AC5C1985194C44A6F38A2F0D2CDF:\
+FDCD25C05C5D2EEC19F325924BF2F7AB:\
+D3BFFE7D9A480362532B542007577EC6
+
[AES-192/CTR-BE]
6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\
30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\
diff --git a/checks/x509.cpp b/checks/x509.cpp
index 43d374411..8c6cd8187 100644
--- a/checks/x509.cpp
+++ b/checks/x509.cpp
@@ -159,7 +159,7 @@ void do_x509_tests(RandomNumberGenerator& rng)
/* Create user #2's key and cert request */
std::cout << '.' << std::flush;
#if defined(BOTAN_HAS_ECDSA)
- EC_Domain_Params ecc_domain(OID("1.2.840.10045.3.1.7"));
+ EC_Group ecc_domain(OID("1.2.840.10045.3.1.7"));
ECDSA_PrivateKey user2_key(rng, ecc_domain);
#else
RSA_PrivateKey user2_key(rng, 1024);
diff --git a/configure.py b/configure.py
index fee244592..50dc246db 100755
--- a/configure.py
+++ b/configure.py
@@ -6,7 +6,7 @@ Configuration program for botan (http://botan.randombit.net/)
Distributed under the terms of the Botan license
Tested with
- CPython 2.5, 2.6 - OK
+ CPython 2.5, 2.6, 2.7 - OK
Jython 2.5 - Target detection does not work (use --os and --cpu)
CPython 2.4 and earlier are not supported
@@ -29,9 +29,13 @@ import logging
import getpass
import time
import errno
+import optparse
-from optparse import (OptionParser, OptionGroup,
- IndentedHelpFormatter, SUPPRESS_HELP)
+# Avoid useless botan_version.pyc (Python 2.6 or higher)
+if 'dont_write_bytecode' in sys.__dict__:
+ sys.dont_write_bytecode = True
+
+import botan_version
def flatten(l):
return sum(l, [])
@@ -41,18 +45,14 @@ class BuildConfigurationInformation(object):
"""
Version information
"""
- version_major = 1
- version_minor = 9
- version_patch = 15
- version_so_patch = 15
- version_suffix = ''
+ version_major = botan_version.release_major
+ version_minor = botan_version.release_minor
+ version_patch = botan_version.release_patch
+ version_so_rev = botan_version.release_so_abi_rev
- version_datestamp = 0
+ version_datestamp = botan_version.release_datestamp
- 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)
+ version_string = '%d.%d.%d' % (version_major, version_minor, version_patch)
"""
Constructor
@@ -66,7 +66,9 @@ class BuildConfigurationInformation(object):
self.python_dir = os.path.join(options.src_dir, 'wrap', 'python')
- self.use_boost_python = options.boost_python
+ self.boost_python = options.boost_python
+
+ self.doc_output_dir = os.path.join(self.build_dir, 'docs')
self.pyobject_dir = os.path.join(self.build_dir, 'python')
@@ -75,9 +77,17 @@ class BuildConfigurationInformation(object):
self.internal_include_dir = os.path.join(self.botan_include_dir, 'internal')
self.sources = sorted(flatten([mod.sources() for mod in modules]))
- self.public_headers = sorted(flatten([m.public_headers() for m in modules]))
self.internal_headers = sorted(flatten([m.internal_headers() for m in modules]))
+ if options.via_amalgamation:
+ self.build_sources = ['botan_all.cpp']
+ self.build_internal_headers = []
+ else:
+ self.build_sources = self.sources
+ self.build_internal_headers = self.internal_headers
+
+ self.public_headers = sorted(flatten([m.public_headers() for m in modules]))
+
checks_dir = os.path.join(options.base_dir, 'checks')
self.check_sources = sorted(
@@ -89,30 +99,43 @@ class BuildConfigurationInformation(object):
for file in os.listdir(self.python_dir)
if file.endswith('.cpp')])
- def doc_files(self):
- docs = ['readme.txt']
+ self.manual_dir = os.path.join(self. doc_output_dir, 'manual')
+
+ def build_doc_commands():
+ yield '$(COPY) readme.txt %s' % (self.doc_output_dir)
+
+ if options.with_sphinx:
+ yield 'sphinx-build $(SPHINX_OPTS) -b html doc %s' % (
+ self.manual_dir)
+ else:
+ yield '$(COPY) doc/*.txt %s' % (self.manual_dir)
+
+ if options.with_doxygen:
+ yield 'doxygen %s/botan.doxy' % (self.build_dir)
+
+ self.build_doc_commands = '\n'.join(['\t' + s for s in build_doc_commands()])
+
+ def build_dirs():
+ yield self.checkobj_dir
+ yield self.libobj_dir
+ yield self.botan_include_dir
+ yield self.internal_include_dir
+ yield os.path.join(self.doc_output_dir, 'manual')
+ if options.with_doxygen:
+ yield os.path.join(self.doc_output_dir, 'doxygen')
- 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
+ if self.boost_python:
+ yield self.pyobject_dir
+
+ self.build_dirs = list(build_dirs())
def pkg_config_file(self):
return 'botan-%d.%d.pc' % (self.version_major,
self.version_minor)
- def build_dirs(self):
- dirs = [self.checkobj_dir,
- self.libobj_dir,
- self.botan_include_dir,
- self.internal_include_dir]
- if self.use_boost_python:
- dirs.append(self.pyobject_dir)
- return dirs
+ def config_shell_script(self):
+ return 'botan-config-%d.%d' % (self.version_major,
+ self.version_minor)
def username(self):
return getpass.getuser()
@@ -128,8 +151,8 @@ Handle command line options
"""
def process_command_line(args):
- parser = OptionParser(
- formatter = IndentedHelpFormatter(max_help_position = 50),
+ parser = optparse.OptionParser(
+ formatter = optparse.IndentedHelpFormatter(max_help_position = 50),
version = BuildConfigurationInformation.version_string)
parser.add_option('--verbose', action='store_true', default=False,
@@ -137,14 +160,21 @@ def process_command_line(args):
parser.add_option('--quiet', action='store_true', default=False,
help='Show only warnings and errors')
- target_group = OptionGroup(parser, 'Target options')
+ target_group = optparse.OptionGroup(parser, 'Target options')
- target_group.add_option('--cc', dest='compiler',
- help='set the desired build compiler')
- target_group.add_option('--os',
- help='set the target operating system')
target_group.add_option('--cpu',
help='set the target processor type/model')
+
+ target_group.add_option('--os',
+ help='set the target operating system')
+
+ target_group.add_option('--cc', dest='compiler',
+ help='set the desired build compiler')
+
+ target_group.add_option('--cc-bin', dest='compiler_binary',
+ metavar='BINARY',
+ help='set the name of the compiler binary')
+
target_group.add_option('--with-endian', metavar='ORDER', default=None,
help='override guess of CPU byte order')
@@ -155,7 +185,7 @@ def process_command_line(args):
target_group.add_option('--without-unaligned-mem',
dest='unaligned_mem', action='store_false',
- help=SUPPRESS_HELP)
+ help=optparse.SUPPRESS_HELP)
for isa_extn_name in ['SSE2', 'SSSE3', 'AltiVec', 'AES-NI', 'movbe']:
isa_extn = isa_extn_name.lower()
@@ -167,23 +197,23 @@ def process_command_line(args):
dest='enable_isa_extns')
target_group.add_option('--disable-%s' % (isa_extn),
- help=SUPPRESS_HELP,
+ help=optparse.SUPPRESS_HELP,
action='append_const',
const=isa_extn,
dest='disable_isa_extns')
- build_group = OptionGroup(parser, 'Build options')
+ build_group = optparse.OptionGroup(parser, 'Build options')
build_group.add_option('--enable-shared', dest='build_shared_lib',
action='store_true', default=True,
- help=SUPPRESS_HELP)
+ help=optparse.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)
+ help=optparse.SUPPRESS_HELP)
build_group.add_option('--disable-asm', dest='asm_ok',
action='store_false',
help='disallow use of assembler')
@@ -192,12 +222,20 @@ def process_command_line(args):
action='store_true', default=False,
help='enable debug build')
build_group.add_option('--disable-debug', dest='debug_build',
- action='store_false', help=SUPPRESS_HELP)
+ action='store_false', help=optparse.SUPPRESS_HELP)
+
+ build_group.add_option('--no-optimizations', dest='no_optimizations',
+ action='store_true', default=False,
+ help=optparse.SUPPRESS_HELP)
build_group.add_option('--gen-amalgamation', dest='gen_amalgamation',
default=False, action='store_true',
help='generate amalgamation files')
+ build_group.add_option('--via-amalgamation', dest='via_amalgamation',
+ default=False, action='store_true',
+ help='build via amalgamation')
+
build_group.add_option('--with-build-dir',
metavar='DIR', default='',
help='setup the build in DIR')
@@ -209,27 +247,47 @@ def process_command_line(args):
dest='local_config', metavar='FILE',
help='include the contents of FILE into build.h')
+ build_group.add_option('--distribution-info', metavar='STRING',
+ help='set distribution specific versioning',
+ default='unspecified')
+
+ build_group.add_option('--with-sphinx', action='store_true',
+ default=None,
+ help='Use Sphinx to generate HTML manual')
+
+ build_group.add_option('--without-sphinx', action='store_false',
+ dest='with_sphinx', help=optparse.SUPPRESS_HELP)
+
+ build_group.add_option('--with-visibility', action='store_true',
+ default=None, help=optparse.SUPPRESS_HELP)
+
+ build_group.add_option('--without-visibility', action='store_false',
+ dest='with_visibility', help=optparse.SUPPRESS_HELP)
+
+ build_group.add_option('--with-doxygen', action='store_true',
+ default=False,
+ help='Use Doxygen to generate HTML API docs')
+
+ build_group.add_option('--without-doxygen', action='store_false',
+ dest='with_doxygen', help=optparse.SUPPRESS_HELP)
+
build_group.add_option('--dumb-gcc', dest='dumb_gcc',
action='store_true', default=False,
- help=SUPPRESS_HELP)
+ help=optparse.SUPPRESS_HELP)
build_group.add_option('--maintainer-mode', dest='maintainer_mode',
action='store_true', default=False,
- help=SUPPRESS_HELP)
+ help=optparse.SUPPRESS_HELP)
build_group.add_option('--dirty-tree', dest='clean_build_tree',
action='store_false', default=True,
- help=SUPPRESS_HELP)
+ help=optparse.SUPPRESS_HELP)
build_group.add_option('--link-method',
default=None,
- help=SUPPRESS_HELP)
-
- build_group.add_option('--distribution-info', metavar='STRING',
- help='set distribution specific versioning',
- default='unspecified')
+ help=optparse.SUPPRESS_HELP)
- wrapper_group = OptionGroup(parser, 'Wrapper options')
+ wrapper_group = optparse.OptionGroup(parser, 'Wrapper options')
wrapper_group.add_option('--with-boost-python', dest='boost_python',
default=False, action='store_true',
@@ -238,14 +296,14 @@ def process_command_line(args):
wrapper_group.add_option('--without-boost-python',
dest='boost_python',
action='store_false',
- help=SUPPRESS_HELP)
+ help=optparse.SUPPRESS_HELP)
- wrapper_group.add_option('--use-python-version', dest='python_version',
+ wrapper_group.add_option('--with-python-version', dest='python_version',
metavar='N.M',
default='.'.join(map(str, sys.version_info[0:2])),
help='specify Python to build against (eg %default)')
- mods_group = OptionGroup(parser, 'Module selection')
+ mods_group = optparse.OptionGroup(parser, 'Module selection')
mods_group.add_option('--enable-modules', dest='enabled_modules',
metavar='MODS', action='append',
@@ -267,12 +325,12 @@ def process_command_line(args):
dest='enabled_modules')
mods_group.add_option('--without-%s' % (mod),
- help=SUPPRESS_HELP,
+ help=optparse.SUPPRESS_HELP,
action='append_const',
const=mod,
dest='disabled_modules')
- install_group = OptionGroup(parser, 'Installation options')
+ install_group = optparse.OptionGroup(parser, 'Installation options')
install_group.add_option('--prefix', metavar='DIR',
help='set the base install directory')
@@ -311,7 +369,7 @@ def process_command_line(args):
]
for opt in compat_with_autoconf_options:
- parser.add_option('--' + opt, help=SUPPRESS_HELP)
+ parser.add_option('--' + opt, help=optparse.SUPPRESS_HELP)
(options, args) = parser.parse_args(args)
@@ -443,8 +501,10 @@ class ModuleInfo(object):
lex_me_harder(infofile, self,
['source', 'header:internal', 'header:public',
- 'requires', 'os', 'arch', 'cc', 'libs'],
- { 'load_on': 'auto',
+ 'requires', 'os', 'arch', 'cc', 'libs',
+ 'comment'],
+ {
+ 'load_on': 'auto',
'define': None,
'need_isa': None,
'mp_bits': 0 })
@@ -493,6 +553,11 @@ class ModuleInfo(object):
self.mp_bits = int(self.mp_bits)
+ if self.comment != []:
+ self.comment = ' '.join(self.comment)
+ else:
+ self.comment = None
+
def sources(self):
return self.source
@@ -653,7 +718,8 @@ class CompilerInfo(object):
'lang_flags': '',
'warning_flags': '',
'maintainer_warning_flags': '',
- 'dll_import_flags': '',
+ 'visibility_build_flags': '',
+ 'visibility_attribute': '',
'ar_command': None,
'makefile_style': ''
})
@@ -680,6 +746,23 @@ class CompilerInfo(object):
del self.mach_opt
"""
+ Return the shared library build flags, if any
+ """
+ def gen_shared_flags(self, options):
+ def flag_builder():
+ if options.build_shared_lib:
+ yield self.shared_flags
+ if options.with_visibility:
+ yield self.visibility_build_flags
+
+ return ' '.join(list(flag_builder()))
+
+ def gen_visibility_attribute(self, options):
+ if options.build_shared_lib and options.with_visibility:
+ return self.visibility_attribute
+ return ''
+
+ """
Return the machine specific ABI flags
"""
def mach_abi_link_flags(self, osname, arch, submodel, debug_p):
@@ -719,13 +802,18 @@ class CompilerInfo(object):
"""
Return the flags for LIB_OPT
"""
- def library_opt_flags(self, debug_build):
- flags = self.lib_opt_flags
- if debug_build and self.debug_flags != '':
- flags += ' ' + self.debug_flags
- if not debug_build and self.no_debug_flags != '':
- flags += ' ' + self.no_debug_flags
- return flags
+ def library_opt_flags(self, options):
+ def gen_flags():
+ if options.debug_build:
+ yield self.debug_flags
+
+ if not options.no_optimizations:
+ yield self.lib_opt_flags
+
+ if not options.debug_build:
+ yield self.no_debug_flags
+
+ return (' '.join(gen_flags())).strip()
"""
Return the command needed to link a shared object
@@ -791,6 +879,12 @@ def canon_processor(archinfo, proc):
if re.search(match, proc) != None:
return (ainfo.basename, submodel)
+ logging.debug('Known CPU names: ' + ' '.join(
+ sorted(sum([[ainfo.basename] + \
+ ainfo.aliases + \
+ [x for (x,_) in ainfo.all_submodels()]
+ for ainfo in archinfo.values()], []))))
+
raise Exception('Unknown or unidentifiable processor "%s"' % (proc))
def guess_processor(archinfo):
@@ -859,13 +953,21 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
def objectfile_list(sources, obj_dir):
for src in sources:
- basename = os.path.basename(src)
+ (dir,file) = os.path.split(os.path.normpath(src))
+
+ if dir.startswith('src'):
+ parts = dir.split(os.sep)[1:]
+ if file == parts[-1] + '.cpp':
+ name = '_'.join(dir.split(os.sep)[1:]) + '.cpp'
+ else:
+ name = '_'.join(dir.split(os.sep)[1:]) + '_' + file
+ else:
+ name = file
for src_suffix in ['.cpp', '.S']:
- basename = basename.replace(src_suffix,
- '.' + osinfo.obj_suffix)
+ name = name.replace(src_suffix, '.' + osinfo.obj_suffix)
- yield os.path.join(obj_dir, basename)
+ yield os.path.join(obj_dir, name)
def choose_mp_bits():
@@ -904,11 +1006,6 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
return os.path.join(options.with_build_dir, path)
return path
- def only_if_shared(option):
- if options.build_shared_lib:
- return option
- return ''
-
def warning_flags(normal_flags,
maintainer_flags,
maintainer_mode):
@@ -920,14 +1017,13 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'version_major': build_config.version_major,
'version_minor': build_config.version_minor,
'version_patch': build_config.version_patch,
+ 'so_abi_rev': build_config.version_so_rev,
'version': build_config.version_string,
'distribution_info': options.distribution_info,
'version_datestamp': build_config.version_datestamp,
- 'so_version': build_config.soversion_string,
-
'timestamp': build_config.timestamp(),
'user': build_config.username(),
'hostname': build_config.hostname(),
@@ -942,8 +1038,10 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'includedir': options.includedir or osinfo.header_dir,
'docdir': options.docdir or osinfo.doc_dir,
- 'doc_src_dir': 'doc',
'build_dir': build_config.build_dir,
+ 'doc_output_dir': build_config.doc_output_dir,
+
+ 'build_doc_commands': build_config.build_doc_commands,
'python_dir': build_config.python_dir,
@@ -953,19 +1051,20 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'mp_bits': choose_mp_bits(),
- 'cc': cc.binary_name + cc.mach_abi_link_flags(
- options.os, options.arch, options.cpu, options.debug_build),
+ 'cc': (options.compiler_binary or cc.binary_name) +
+ cc.mach_abi_link_flags(options.os, options.arch,
+ options.cpu, options.debug_build),
- 'lib_opt': cc.library_opt_flags(options.debug_build),
+ 'lib_opt': cc.library_opt_flags(options),
'mach_opt': cc.mach_opts(options.arch, options.cpu),
- 'check_opt': cc.check_opt_flags,
+ 'check_opt': '' if options.no_optimizations else cc.check_opt_flags,
'lang_flags': cc.lang_flags + options.extra_flags,
'warn_flags': warning_flags(cc.warning_flags,
cc.maintainer_warning_flags,
options.maintainer_mode),
- 'shared_flags': only_if_shared(cc.shared_flags),
- 'dll_import_flags': only_if_shared(cc.dll_import_flags),
+ 'shared_flags': cc.gen_shared_flags(options),
+ 'visibility_attribute': cc.gen_visibility_attribute(options),
'so_link': cc.so_link_command_for(osinfo.basename),
@@ -983,7 +1082,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'include_files': makefile_list(build_config.public_headers),
'lib_objs': makefile_list(
- objectfile_list(build_config.sources,
+ objectfile_list(build_config.build_sources,
build_config.libobj_dir)),
'check_objs': makefile_list(
@@ -991,7 +1090,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
build_config.checkobj_dir)),
'lib_build_cmds': '\n'.join(
- build_commands(build_config.sources,
+ build_commands(build_config.build_sources,
build_config.libobj_dir, 'LIB')),
'check_build_cmds': '\n'.join(
@@ -1020,13 +1119,13 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
'so_suffix': osinfo.so_suffix,
'botan_config': prefix_with_build_dir(
- os.path.join(build_config.build_dir, 'botan-config')),
+ os.path.join(build_config.build_dir,
+ build_config.config_shell_script())),
+
'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(sorted([m.basename for m in modules])),
'python_version': options.python_version
@@ -1134,6 +1233,14 @@ def choose_modules_to_use(modules, archinfo, options):
logging.info('Skipping, %s - %s' % (
reason, ' '.join(disabled_mods)))
+ for mod in sorted(to_load):
+ if mod.startswith('mp_'):
+ logging.info('Using MP module ' + mod)
+ if mod.startswith('simd_') and mod != 'simd_engine':
+ logging.info('Using SIMD module ' + mod)
+ if modules[mod].comment:
+ logging.info('%s: %s' % (mod, modules[mod].comment))
+
logging.debug('Loading modules %s', ' '.join(sorted(to_load)))
return [modules[mod] for mod in to_load]
@@ -1258,7 +1365,7 @@ def setup_build(build_config, options, template_vars):
if e.errno != errno.ENOENT:
logging.error('Problem while removing build dir: %s' % (e))
- for dir in build_config.build_dirs():
+ for dir in build_config.build_dirs:
try:
os.makedirs(dir)
except OSError, e:
@@ -1281,7 +1388,7 @@ def setup_build(build_config, options, template_vars):
if options.os != 'windows':
yield (options.build_data, 'botan.pc.in', build_config.pkg_config_file())
- yield (options.build_data, 'botan-config.in', 'botan-config')
+ yield (options.build_data, 'botan-config.in', build_config.config_shell_script())
if options.os == 'windows':
yield (options.build_data, 'innosetup.in', 'botan.iss')
@@ -1320,7 +1427,7 @@ def setup_build(build_config, options, template_vars):
link_headers(build_config.public_headers, 'public',
build_config.botan_include_dir)
- link_headers(build_config.internal_headers, 'internal',
+ link_headers(build_config.build_internal_headers, 'internal',
build_config.internal_include_dir)
"""
@@ -1397,12 +1504,16 @@ def generate_amalgamation(build_config):
else:
match = std_include.search(line)
- if match:
+ if match and match.group(1) != 'functional':
self.all_std_includes.add(match.group(1))
else:
yield line
- botan_all_h = open('botan_all.h', 'w')
+ amalg_basename = 'botan_all'
+
+ header_name = '%s.h' % (amalg_basename)
+
+ botan_h = open(header_name, 'w')
pub_header_amalag = Amalgamation_Generator(build_config.public_headers)
@@ -1414,31 +1525,30 @@ def generate_amalgamation(build_config):
*/
""" % (build_config.version_string)
- botan_all_h.write(amalg_header)
+ botan_h.write(amalg_header)
- botan_all_h.write("""
+ botan_h.write("""
#ifndef BOTAN_AMALGAMATION_H__
#define BOTAN_AMALGAMATION_H__
""")
- botan_all_h.write(pub_header_amalag.header_includes)
- botan_all_h.write(pub_header_amalag.contents)
- botan_all_h.write("\n#endif\n")
+ botan_h.write(pub_header_amalag.header_includes)
+ botan_h.write(pub_header_amalag.contents)
+ botan_h.write("\n#endif\n")
internal_header_amalag = Amalgamation_Generator(
[s for s in build_config.internal_headers
if s.find('asm_macr_') == -1])
- botan_all_cpp = open('botan_all.cpp', 'w')
-
- botan_all_cpp.write(amalg_header)
+ botan_cpp = open('%s.cpp' % (amalg_basename), 'w')
- botan_all_cpp.write('#include "botan_all.h"\n')
+ botan_cpp.write(amalg_header)
- botan_all_cpp.write(internal_header_amalag.header_includes)
- botan_all_cpp.write(internal_header_amalag.contents)
+ botan_cpp.write('\n#include "%s"\n' % (header_name))
+ botan_cpp.write(internal_header_amalag.header_includes)
+ botan_cpp.write(internal_header_amalag.contents)
for src in build_config.sources:
if src.endswith('.S'):
@@ -1449,27 +1559,30 @@ def generate_amalgamation(build_config):
if botan_include.search(line):
continue
else:
- botan_all_cpp.write(line)
+ botan_cpp.write(line)
"""
-Finding a program by name
-code from http://stackoverflow.com/questions/377017/#377028
+Test for the existence of a program
"""
-def which(program):
- def have_exe(fpath):
- return os.path.exists(fpath) and os.access(fpath, os.X_OK)
-
- fpath, fname = os.path.split(program)
- if fpath:
- if have_exe(program):
- return program
- else:
- for path in os.environ['PATH'].split(os.pathsep):
- exe_file = os.path.join(path, program)
- if have_exe(exe_file):
- return exe_file
+def have_program(program):
+
+ def exe_test(path, program):
+ exe_file = os.path.join(path, program)
+
+ if os.path.exists(exe_file) and os.access(exe_file, os.X_OK):
+ logging.debug('Found program %s in %s' % (program, path))
+ return True
+ else:
+ return False
- return None
+ exe_suffixes = ['', '.exe']
+
+ for path in os.environ['PATH'].split(os.pathsep):
+ for suffix in exe_suffixes:
+ if exe_test(path, program + suffix):
+ return True
+
+ return False
"""
Main driver
@@ -1515,19 +1628,17 @@ def main(argv = None):
logging.debug("Converting '%s' to 'cygwin'", options.os)
options.os = 'cygwin'
- logging.info('Guessing target OS is %s (--os to set)' % (options.os))
+ logging.info('Guessing target OS is %s (use --os to set)' % (options.os))
if options.compiler is None:
if options.os == 'windows':
- if which('cl.exe') is not None:
- options.compiler = 'msvc'
- elif which('g++.exe') is not None:
+ if have_program('g++') and not have_program('cl'):
options.compiler = 'gcc'
else:
options.compiler = 'msvc'
else:
options.compiler = 'gcc'
- logging.info('Guessing to use compiler %s (--cc to set)' % (
+ logging.info('Guessing to use compiler %s (use --cc to set)' % (
options.compiler))
if options.compiler not in ccinfo:
@@ -1550,7 +1661,7 @@ def main(argv = None):
if options.cpu is None:
(options.arch, options.cpu) = guess_processor(archinfo)
- logging.info('Guessing target processor is a %s/%s (--cpu to set)' % (
+ logging.info('Guessing target processor is a %s/%s (use --cpu to set)' % (
options.arch, options.cpu))
else:
cpu_from_user = options.cpu
@@ -1561,45 +1672,73 @@ def main(argv = None):
logging.info('Target is %s-%s-%s-%s' % (
options.compiler, options.os, options.arch, options.cpu))
+ cc = ccinfo[options.compiler]
+
# Kind of a hack...
options.extra_flags = ''
if options.compiler == 'gcc':
+ def get_gcc_version(gcc_bin):
+ try:
+ gcc_version = ''.join(subprocess.Popen(
+ gcc_bin.split(' ') + ['-dumpversion'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).communicate()).strip()
+ logging.info('Detected gcc version %s' % (gcc_version))
+ return gcc_version
+ except OSError:
+ logging.warning('Could not execute %s for version check' % (gcc_bin))
+ return None
+
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 = get_gcc_version(options.compiler_binary or cc.binary_name)
- gcc_version = ''.join(subprocess.Popen(
- ['g++', '-dumpversion'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE).communicate()).strip()
+ if gcc_version:
- logging.info('Detected GCC version %s' % (gcc_version))
+ if not is_64bit_arch(options.arch) and not options.dumb_gcc:
+ matching_version = '(4\.[01234]\.)|(3\.[34]\.)|(2\.95\.[0-4])'
if re.search(matching_version, gcc_version):
options.dumb_gcc = True
- except OSError:
- logging.warning('Could not execute GCC for version check')
+
+ versions_without_tr1 = '(4\.0\.)|(3\.[0-4]\.)|(2\.95\.[0-4])'
+
+ if options.with_tr1 == None and \
+ re.search(versions_without_tr1, gcc_version):
+ logging.info('Disabling TR1 support for this gcc, too old')
+ options.with_tr1 = 'none'
+
+ versions_without_visibility = '(3\.[0-4]\.)|(2\.95\.[0-4])'
+ if options.with_visibility == None and \
+ re.search(versions_without_visibility, gcc_version):
+ logging.info('Disabling DSO visibility support for this gcc, too old')
+ options.with_visibility = False
if options.dumb_gcc is True:
logging.info('Setting -fpermissive to work around gcc bug')
options.extra_flags = ' -fpermissive'
+ if options.with_visibility is None:
+ options.with_visibility = True
+
+ if options.with_sphinx is None:
+ if have_program('sphinx-build'):
+ logging.info('Found sphinx-build, will use it ' +
+ '(use --without-sphinx to disable)')
+ options.with_sphinx = True
+
+ if options.via_amalgamation:
+ options.gen_amalgamation = True
+
if options.gen_amalgamation:
if options.asm_ok:
logging.info('Disabling assembly code, cannot use in amalgamation')
options.asm_ok = False
- for mod in ['sha1_sse2', 'serpent_simd']:
- if mod not in options.disabled_modules:
- logging.info('Disabling %s, cannot use in amalgamation' % (mod))
- options.disabled_modules.append(mod)
-
modules_to_use = choose_modules_to_use(modules,
archinfo[options.arch],
options)
@@ -1615,7 +1754,7 @@ def main(argv = None):
template_vars = create_template_vars(build_config, options,
modules_to_use,
- ccinfo[options.compiler],
+ cc,
archinfo[options.arch],
osinfo[options.os])
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
new file mode 100644
index 000000000..c907c7597
--- /dev/null
+++ b/doc/_templates/layout.html
@@ -0,0 +1,9 @@
+{% extends "!layout.html" %}
+
+{% block header %}
+ <div class="header-wrapper">
+ <div class="header">
+ <h1>{{ shorttitle|e }}</h1>
+ </div>
+ </div>
+{% endblock %}
diff --git a/doc/algos.txt b/doc/algos.txt
new file mode 100644
index 000000000..119b81a7f
--- /dev/null
+++ b/doc/algos.txt
@@ -0,0 +1,90 @@
+
+.. _algo_list:
+
+Algorithms
+========================================
+
+Supported Algorithms
+----------------------------------------
+
+Botan provides a number of different cryptographic algorithms and
+primitives, including:
+
+* Public key cryptography
+
+ * Encryption algorithms RSA, ElGamal, DLIES (padding schemes OAEP,
+ PKCS #1 v1.5)
+ * Signature algorithms RSA, DSA, ECDSA, GOST 34.10-2001,
+ Nyberg-Rueppel, Rabin-Williams (padding schemes PSS, PKCS #1 v1.5,
+ X9.31)
+ * Key agreement techniques Diffie-Hellman and ECDH
+
+* Hash functions
+
+ * NIST hashes: SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512
+ * RIPE hashes: RIPEMD-160 and RIPEMD-128
+ * SHA-3 candidates Skein-512, Keccak, and Blue Midnight Wish-512
+ * Other common hash functions Whirlpool and Tiger
+ * National standard hashes HAS-160 and GOST 34.11
+ * Obsolete or insecure hashes MD5, MD4, MD2
+ * Non-cryptographic checksums Adler32, CRC24, CRC32
+
+* Block ciphers
+
+ * AES (Rijndael) and AES candidates Serpent, Twofish, MARS, CAST-256, RC6
+ * DES, and variants 3DES and DESX
+ * National/telecom block ciphers SEED, KASUMI, MISTY1, GOST 28147, Skipjack
+ * Other block ciphers including Blowfish, CAST-128, IDEA, Noekeon,
+ TEA, XTEA, RC2, RC5, SAFER-SK, and Square
+ * Block cipher constructions Luby-Rackoff and Lion
+ * Block cipher modes ECB, CBC, CBC/CTS, CFB, OFB, CTR, XTS and
+ authenticated cipher mode EAX
+
+* Stream ciphers ARC4, Salsa20/XSalsa20, Turing, and WiderWake4+1
+
+* Authentication codes HMAC, CMAC (aka OMAC1), CBC-MAC, ANSI X9.19
+ DES-MAC, and the protocol-specific SSLv3 authentication code
+
+* Public Key Infrastructure
+
+ * X.509 certificates (including generating new self-signed and CA
+ certs) and CRLs
+ * Certificate path validation
+ * PKCS #10 certificate requests (creation and certificate issue)
+
+* Other cryptographic utility functions including
+
+ * Key derivation functions for passwords: PBKDF1 (PKCS #5 v1.5),
+ PBKDF2 (PKCS #5 v2.0), OpenPGP S2K (RFC 2440)
+ * General key derivation functions KDF1 and KDF2 from IEEE 1363
+ * PRFs from ANSI X9.42, SSL v3.0, TLS v1.0
+
+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 that
+will turn out to be more secure than the ones listed, but the
+algorithms listed here are (currently) thought to be safe.
+
+* Block ciphers: AES or Serpent in CBC, CTR, or XTS mode
+
+* Hash functions: SHA-256, SHA-512
+
+* MACs: HMAC with any recommended hash function
+
+* Public Key Encryption: RSA with "EME1(SHA-256)"
+
+* Public Key Signatures: RSA with EMSA4 and any recommended hash, or
+ DSA or ECDSA with "EMSA1(SHA-256)"
+
+* Key Agreement: Diffie-Hellman or ECDH, with "KDF2(SHA-256)"
diff --git a/doc/api.tex b/doc/api.tex
deleted file mode 100644
index 79c090c2a..000000000
--- a/doc/api.tex
+++ /dev/null
@@ -1,2964 +0,0 @@
-\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 Reference Manual}}
-\author{}
-\date{2010/06/14}
-
-\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{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 at least one and
-ideally all of these books before seriously using the library.
-
-\setlength{\parskip}{5pt}
-
-\noindent
-\textit{Cryptography Engineering}, Niels Ferguson, Bruce Schneier, and
-Tadayoshi Kohno; Wiley
-
-\noindent
-\textit{Security Engineering -- A Guide to Building Dependable
- Distributed Systems}, Ross Anderson; Wiley
-
-\noindent
-\textit{Handbook of Applied Cryptography}, Alfred J. Menezes,
-Paul C. Van Oorschot, and Scott A. Vanstone; CRC Press (available
-online at \url{http://www.cacr.math.uwaterloo.ca/hac/})
-
-\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. Given the choice
-between optimizing for 32-bit systems and 64-bit systems, Botan is
-written to prefer 64-bit, on the theory that where performance is a
-real concern, modern 64-bit processors are the obvious choice.
-
-Smaller handhelds, set-top boxes, and the bigger smart phones and smart
-cards, are also capable of using Botan. However, Botan uses a
-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 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 ask Botan
-if the algorithm exists, and if Botan says yes, ask the library to
-give them such an object for that algorithm.
-
-\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 \keyword{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 (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 if you wish to share a
-single object between threads.
-
-If you do not create a \type{LibraryInitializer} object, all library
-operations will fail, because it will be unable to do basic things
-like allocate memory or get random bits. You should never create more
-than one \type{LibraryInitializer}.
-
-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; in many C++ runtimes, these
-objects will be destroyed after main has returned.
-
-Botan's memory object classes (\type{MemoryRegion},
-\type{MemoryVector}, \type{SecureVector}) are extremely primitive, and
-meant only for secure storage of potentially sensitive data like
-keys. They do not meet the requirements for an STL container object
-and you should not try to use them with STL algorithms. For a
-general-purpose container, use \type{std::vector}.
-
-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. 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.
-
-Botan has about 40 filters that perform different operations on data.
-Here's code that uses one of them to encrypt a string with AES:
-
-\begin{verbatim}
- AutoSeeded_RNG rng,
- SymmetricKey key(rng, 16); // a random 128-bit key
- InitializationVector iv(rng, 16); // a random 128-bit IV
-
- // 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 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}() 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, 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 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. Make sure you're including the header \filename{lookup.h}, and
-then call \function{get\_cipher}. You will pass the return value
-directly into a \type{Pipe}. There are a couple different functions
-which do varying levels of initialization:
-
-\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}.
-
-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: ``AES-128/CBC'',
-``Blowfish/CTR-BE'', ``Serpent/XTS'', and ``AES-256/EAX''.
-
-``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 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 much the
-same in terms of dataflow - ach 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 the entire input as a
-single blob 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
-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. 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 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
-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. The filter should finish up with whatever computation it
-is 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.
-
-Additionally, if necessary, filters can define a constructor that
-takes any needed arguments, and a destructor to deal with deallocating
-memory, closing files, etc.
-
-\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<Public_Key> 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 three kinds of public key algorithms in Botan:
-ones based on integer factorization (RSA and Rabin-Williams), ones
-based on the discrete logarithm problem in the integers modulo a prime
-(DSA, Diffie-Hellman, Nyberg-Rueppel, and ElGamal), and ones based on
-the discrete logarithm problem in an elliptic curve (ECDSA, ECDH, GOST
-34.10). The systems based on discrete logarithms (in either regular
-integers or elliptic curves) use a group (a mathematical term), which
-can be shared among many keys. An elliptic curve group is represented
-by the class \type{EC\_Domain\_Params}, while a modulo-prime group is
-represented by a \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 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 necessary for security). To get an
-object that knows how to do padding, use the wrapper classes included
-in \filename{pubkey.h}. These take a key, along with a string that
-specifies 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).
-
-\begin{verbatim}
- // PKCS #1 v2.0 / IEEE 1363 compatible encryption
- PK_Encryptor_EME rsa_enc_pkcs1_v2(rsakey, "EME1(SHA-1)");
- // PKCS #1 v1.5 compatible encryption
- PK_Encryptor_EME rsa_enc_pkcs1_v15(rsakey, "PKCS1v15")
-
- // This object can decrypt things encrypted by rsa_
- PK_Decryptor_EME rsa_dec_pkcs1_v2(rsakey, "EME1(SHA-1)");
-
- // PKCS #1 v1.5 compatible signatures
- PK_Signer rsa_sign_pkcs1_v15(rsakey, "EMSA3(MD5)");
- PK_Verifier rsa_verify_pkcs1_v15(rsakey, "EMSA3(MD5)");
-
- // PKCS #1 v2.1 compatible signatures
- PK_Signer rsa_sign_pkcs1_v2(rsakey, "EMSA4(SHA-1)");
- PK_Verifier rsa_verify_pkcs1_v2(rsakey, "EMSA4(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. You
-can call \function{maximum\_input\_size} to find out the maximum size
-input (in bytes) that you can safely use with any particular key.
-
-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,
-ECDSA, GOST-34.11, 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. The Raw encoding 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, ECDSA, GOST-34.11, 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 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 KDF you're using, you \emph{might not} get back a key
-of the size you requested. 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 {
- MemoryVector<byte> BER_encode(const Public_Key& key);
- std::string PEM_encode(const Public_Key& out);
-
- Public_Key* load_key(DataSource& in);
- Public_Key* load_key(const SecureVector<byte>& buffer);
-}
-\end{verbatim}
-
-The function \function{X509::BER\_encode} will take any
-\type{Public\_Key} and return a standard binary structure representing
-the key which can be read by many other crypto libraries.
-
-The function \function{X509::PEM\_encode} does the same, but
-additionally formats it into a text format with headers and base64
-encoding. Using 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.
-
-For loading a public key, use 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 create~--~the others are simple wrapper functions that take
-either a filename or a memory buffer.
-
-Here's an example of loading a public key and then encrypting with it:
-
-\begin{verbatim}
- /* Might be RSA, might be ElGamal, might be ... */
- Public_Key* key = X509::load_key("pubkey.asc");
-
- /* This might throw an exception if the key doesn't support any
- encryption operations
- */
-
- PK_Encryptor_EME encryptor(*key, "EME1(SHA-1)");
-
- SecureVector<byte> ciphertext = encryptor.encrypt(msg, size_of_msg);
-\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 {
- SecureVector<byte> BER_encode(const Private_Key& key);
- std::string PEM_encode(const Private_Key& key);
-}
-\end{verbatim}
-
-These functions are similiar to the X.509 functions described
-previously. The only difference is that they take a
-\type{Private\_Key} object instead. 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
-store the whole thing into another structure. This method is
-definitely preferred, since otherwise the private key is
-unprotected. The algorithms and structures used here are standardized
-by PKCS \#5 and PKCS \#8, and can be read by many other crypto
-libraries.
-
-\begin{verbatim}
-namespace PKCS8 {
- SecureVector<byte> BER_encode(const Private_Key& key,
- RandomNumberGenerator& rng,
- const std::string& pass,
- const std::string& pbe_algo = "");
-
- std::string PEM_encode(const Private_Key& key,
- RandomNumberGenerator& rng,
- const std::string& pass,
- const std::string& pbe_algo = "");
-}
-\end{verbatim}
-
-There are three new arguments needed here to support the encryption
-process in addition to the private key itself. The first is a
-\type{RandomNumberGenerator}, which is needed for various purposes
-internally. The \arg{pass} argument is the passphrase that will be
-used to encrypt the key. Both of these are required. The final
-(optional) argument is \arg{pbe}; this specifies a particular password
-based encryption (or PBE) algorithm. If you don't specify a PBE,
-a compiled in default will be used; this should be fine.
-
-Last but not least, there are some functions that will load (and
-decrypt, if necessary) a PKCS \#8 private key:
-
-\begin{verbatim}
-namespace PKCS8 {
- Private_Key* load_key(
- DataSource& in,
- RandomNumberGenerator& rng,
- std::function<std::pair<bool, std::string> ()> get_passphrase);
-
- Private_Key* load_key(
- const std::string& filename,
- RandomNumberGenerator& rng,
- std::function<std::pair<bool, std::string> ()> get_passphrase);
-
- Private_Key* load_key(DataSource& in,
- RandomNumberGenerator& rng,
- std::string passphrase = "");
-
- Private_Key* 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 versions using \type{std::function} callbacks are
-how \function{load\_key} is implemented, and provides for much more
-flexibility. If you use the versions that take just a single
-passphrase, then if the passphrase passed in is not correct, then an
-exception is thrown and that is that. However, if you pass in a
-callback, then you can keep querying to the user until they get it
-right (or they cancel the action). The first return value of the
-callback is if the action should continue - if false,
-\function{load_key} will bail out. Otherwise, it will use the second
-return value as the supposed passphrase that was used to decrypt the
-key.
-
-If you know (or want to assume) the key is not encrypted, just ignore
-the passphrase/callback entirely, letting the third parameter default
-to an empty string. The call will fail if the key was encrypted.
-
-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} the object 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).
-
-\section{Certificate Handling}
-
-A certificate is a binding between some identifying information
-(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 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, 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{Public\_Key*}. 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, an organizational sub-unit name, 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 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
-likely never want to use). However, there are three very useful pieces
-of information that this extension might hold: an email address
-(``[email protected]''), a DNS name (``somehost.site2.com''), or a URI
-(``http://www.site3.com'').
-
-So, how to get the information? 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.
-
-\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). Every once in a while the
-CA will release a new 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 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}.
-
-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 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
-normally 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 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})
-
-This function will return \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 mostly undocumented) method for marking certificates for code
-signing.
-
-First, how does it know if a certificate is valid? 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 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 usually what you want; 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 perhaps 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 Private_Key& key);
-\end{verbatim}
-
-The private key is the private key corresponding to the public key in the
-CA's certificate.
-
-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. A request is vetted by humans (who somehow
-verify that the name in the request corresponds to the name of the
-entity 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. Never fear; empty CRLs, which revoke nothing at all, can
-be issued. 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. The library provides a utility function for this:
-
-\begin{verbatim}
-namespace X509 {
- X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
- const Private_Key& 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 Private_Key&);
-}
-\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}
-
-What is this \type{X509\_Cert\_Options} thing we've been passing
-around? It's a class representing 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 just 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.
-
-\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. The object will look and behave 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 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 copies its input.
-
-\subsection{Symmetrically Keyed Algorithms}
-
-Block ciphers, stream ciphers, and MACs are all keyed operations; to
-be useful, they have to be set to use a particular key, which is a
-randomly chosen string of bits of a specified length. The length
-required by any particular algorithm may vary, depending on both the
-algorithm specification and the implementation. You can query any
-botan object to find out what key length(s) it supports.
-
-To make this similarity in terms of keying 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 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 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}[],
- \type{byte} \arg{out}[]) const
-
-\noindent
-\type{void} \function{encrypt}(\type{byte} \arg{block}[]) 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}). Exactly one block will be
-encrypted; you can find out the block size of the cipher you are
-working with by calling the member function \function{block\_size}.
-\type{BlockCipher}s have similar functions \function{decrypt}, which
-perform the inverse operation.
-
-If you want to process multiple blocks in parallel, use
-\function{encrypt\_n} and \function{decrypt\_n}.
-
-\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{size\_t} \function{output\_length}()
-
-Return the size of the output of this function.
-
-\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}[])
-
-\noindent
-\type{SecureVector<byte>} \function{final}():
-
-Complete the hash/MAC calculation and place the result into \arg{out}.
-For the argument taking an array, exactly \function{output\_length}()
-bytes will be written. 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.
-
-There is also a pair of functions called \function{process}. They are
-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 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.
-
-\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 ethe 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 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
-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 entropy.
-
-\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.
-
-\begin{verbatim}
- std::string get_passphrase(const std::string& what,
- const std::string& source,
- UI_Result& result) const;
-\end{verbatim}
-
-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.
-
-\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 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 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 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. The CAPI RNG is usually a
-default software-based PRNG, but there are a few providers 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 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 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. 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 be used.
-
-\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 PBKDF
-algorithms, have a wide degree of applicability.
-
-\subsection{PBKDF Algorithms}
-
-There are various procedures (usually 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{pbkdf.h}. The main function is \function{derive\_key}, which
-takes a passphrase, a salt, an iteration count, and the desired length
-of the output key, and returns a key of that length, deterministically
-produced from the passphrase and salt. 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).
-
-The purpose of the iteration count is to make the algorithm take
-longer to compute the final key (reducing the speed of brute-force
-attacks of various kinds). Most standards recommend an iteration count
-of at least 10000. Currently defined PBKDF algorithms are
-``PBKDF1(digest)'', ``PBKDF2(digest)'', and ``OpenPGP-S2K(digest)'';
-you can retrieve any of these using the \function{get\_pbkdf}, found in
-\filename{lookup.h}. As of this writing, ``PBKDF2(SHA-256)'' with
-10000 iterations and a 16 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, 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{Password Hashing}
-
-Storing passwords for user authentication purposes in plaintext is the
-simplest but least secure method; when an attacker compromises the
-database in which the passwords are stored, they immediately gain
-access to all of them. Often passwords are reused among multiple
-services or machines, meaning once a password to a single service is
-known an attacker has a substantial head start on attacking other
-machines.
-
-The general approach is to store, instead of the password, the output
-of a one way function of the password. Upon receiving an
-authentication request, the authenticator can recompute the one way
-function and compare the value just computed with the one that was
-stored. If they match, then the authentication request succeeds. But
-when an attacker gains access to the database, they only have the
-output of the one way function, not the original password.
-
-Common hash functions such as SHA-256 are one way, but used alone they
-have problems for this purpose. What an attacker can do, upon gaining
-access to such a stored password database, is hash common dictionary
-words and other possible passwords, storing them in a list. Then he
-can search through his list; if a stored hash and an entry in his list
-match, then he has found the password. Even worse, this can happen
-\emph{offline}: an attacker can begin hashing common passwords days,
-months, or years before ever gaining access to the database. In
-addition, if two users choose the same password, the one way function
-output will be the same for both of them, which will be visible upon
-inspection of the database.
-
-There are two solutions to these problems: salting and
-iteration. Salting refers to including, along with the password, a
-randomly chosen value which perturbs the one way function. Salting can
-reduce the effectivness of offline dictionary generation (because for
-each potential password, an attacker would have to compute the one way
-function output for all possible salts - with a large enough salt,
-this can make the problem quite difficult). It also prevents the same
-password from producing the same output, as long as the salts do not
-collide. With a large salt (say 80 to 128 bits) this will be quite
-unlikely. Iteration refers to the general technique of forcing
-multiple one way function evaluations when computing the output, to
-slow down the operation. For instance if hashing a single password
-requires running SHA-256 100,000 times instead of just once, that will
-slow down user authentication by a factor of 100,000, but user
-authentication happens quite rarely, and usually there are more
-expensive operations that need to occur anyway (network and database
-I/O, etc). On the other hand, an attacker who is attempting to break a
-database full of stolen password hashes will be seriously
-inconvenienced by a factor of 100,000 slowdown; they will be able to
-only test at a rate of .0001\% of what they would without iterations
-(or, equivalently, will require 100,000 times as many zombie botnet
-hosts).
-
-There are many different ways of doing this password hashing
-operation, with common ones including Unix's crypt (which is based on
-DES) and OpenBSD's bcrypt (based on Blowfish). Other variants using
-MD5 or SHA-256 are also in use on various systems.
-
-Botan provides a technique called passhash9, in
-\filename{passhash9.h}, which is based on PBKDF2. Two functions are
-provided in this header, \function{generate\_passhash9} and
-\function{check\_passhash9}. The generate function takes the password
-to hash, a \type{RandomNumberGenerator}, and a work factor, which
-tells how many iterations to compute. The default work factor is 10
-(which means 100,000 iterations), but any non-zero value is accepted.
-The check function takes a password and a passhash9 output and checks
-if the password is the same as the one that was used to generate the
-passhash9 output, returning a boolean true (same) or false (not same).
-An example can be found in \filename{doc/examples/passhash.cpp}.
-
-Passhash9 currently uses HMAC(SHA-1) for the underlying PBKDF2
-psuedo-random function, but can be extended to use different
-algorithms in the future if necessary. For instance using a PRF based
-on Blowfish (a block cipher that requires 4 KiB of RAM for efficient
-execution) could be used to make hardware-based password cracking more
-expensive (this was one motivation for Blowfish's use in the bcrypt
-hashing scheme, in fact).
-
-\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.
-
-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}. Code needing
-to allocate or deallocate memory calls \function{get\_allocator},
-which returns a pointer to an allocator object. This pointer should
-not be freed: the caller does not own the allocator (it is shared
-among multiple allocatore users, and uses a mutex to serialize access
-internally if necessary). 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.
-
-\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 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 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.
-
-\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, CTR, or XTS 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 or ECDSA with ``EMSA1(SHA-256)''
-
- \item Key Agreement: Diffie-Hellman or ECDH, with ``KDF2(SHA-256)''
-\end{list}
-
-\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. 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. 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
-\end{list}
-
-\vskip .05in
-\noindent
-\textbf{Block Ciphers:} ``AES'' (and ``AES-128'', ``AES-192'', and
-``AES-256''), ``Blowfish'', ``CAST-128'', ``CAST-256'', ``DES'',
-``DESX'', ``TripleDES'', ``GOST-28147-89'', ``IDEA'', ``KASUMI'',
-``MARS'', ``MISTY1(ROUNDS)'', ``Noekeon'', ``RC2'', ``RC5(ROUNDS)'',
-``RC6'', ``SAFER-SK(ROUNDS)'', ``SEED'', ``Serpent'', ``Skipjack'',
-``Square'', ``TEA'', ``Twofish'', ``XTEA''
-
-\noindent
-\textbf{Stream Ciphers:} ``ARC4'', ``MARK4'', ``Salsa20'', ``Turing'',
-``WiderWake4+1-BE''
-
-\noindent
-\textbf{Hash Functions:} ``HAS-160'', ``GOST-34.11'',
-``MD2'', ``MD4'', ``MD5'', ``RIPEMD-128'', ``RIPEMD-160'',
-``SHA-160'', ``SHA-256'', ``SHA-384'', ``SHA-512'', ``Skein-512'',
-``Tiger(OUTSZ)'', ``Whirlpool''
-
-\noindent
-\textbf{MACs:} ``HMAC(HASH)'', ``CMAC(BLOCK)'', ``X9.19-MAC''
-
-\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{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 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-2010, Jack Lloyd
-
-Licensed under the same terms as the Botan source
-
-\end{document}
diff --git a/doc/architecture.pdf b/doc/architecture.pdf
deleted file mode 100644
index f0edc3fc1..000000000
--- a/doc/architecture.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/bigint.txt b/doc/bigint.txt
new file mode 100644
index 000000000..7eb884039
--- /dev/null
+++ b/doc/bigint.txt
@@ -0,0 +1,104 @@
+BigInt
+========================================
+
+``BigInt`` is Botan's implementation of a multiple-precision
+integer. Thanks to C++'s operator overloading features, using
+``BigInt`` is often quite similar to using a native integer type. The
+number of functions related to ``BigInt`` is quite large. You can find
+most of them in ``botan/bigint.h`` and ``botan/numthry.h``.
+
+.. note::
+
+ If you can, always use expressions of the form ``a += b`` over ``a =
+ a + b``. The difference can be *very* substantial, because the first
+ form prevents at least one needless memory allocation, and possibly
+ as many as three. This will be less of an issue once the library
+ adopts use of C++0x's rvalue references.
+
+Encoding Functions
+----------------------------------------
+
+These transform the normal representation of a ``BigInt`` into some
+other form, such as a decimal string:
+
+.. cpp:function:: SecureVector<byte> BigInt::encode(const BigInt& n, Encoding enc = Binary)
+
+ This function encodes the BigInt n into a memory
+ vector. ``Encoding`` is an enum that has values ``Binary``,
+ ``Octal``, ``Decimal``, and ``Hexadecimal``.
+
+.. cpp:function:: BigInt BigInt::decode(const MemoryRegion<byte>& vec, Encoding enc)
+
+ Decode the integer from ``vec`` using the encoding specified.
+
+These functions are static member functions, so they would be called
+like this::
+
+ BigInt n1 = ...; // some number
+ SecureVector<byte> n1_encoded = BigInt::encode(n1);
+ BigInt n2 = BigInt::decode(n1_encoded);
+ assert(n1 == n2);
+
+There are also C++-style I/O operators defined for use with
+``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.
+
+``BigInt`` has constructors that can create a ``BigInt`` from an
+unsigned integer or a string. You can also decode an array (a ``byte``
+pointer plus a length) into a ``BigInt`` using a constructor.
+
+Number Theory
+----------------------------------------
+
+Number theoretic functions available include:
+
+.. cpp:function:: BigInt gcd(BigInt x, BigInt y)
+
+ Returns the greatest common divisor of x and y
+
+.. cpp:function:: BigInt lcm(BigInt x, BigInt y)
+
+ Returns an integer z which is the smallest integer such that z % x
+ == 0 and z % y == 0
+
+.. cpp:function:: BigInt inverse_mod(BigInt x, BigInt m)
+
+ Returns the modular inverse of x modulo m, that is, an integer
+ y such that (x*y) % m == 1. If no such y exists, returns zero.
+
+.. cpp:function:: BigInt power_mod(BigInt b, BigInt x, BigInt m)
+
+ Returns b to the xth power modulo m. If you are doing many
+ exponentiations with a single fixed modulus, it is faster to use a
+ ``Power_Mod`` implementation.
+
+.. cpp:function:: BigInt ressol(BigInt x, BigInt p)
+
+ Returns the square root modulo a prime, that is, returns a number y
+ such that (y*y) % p == x. Returns -1 if no such integer exists.
+
+.. cpp:function:: bool quick_check_prime(BigInt n, RandomNumberGenerator& rng)
+
+.. cpp:function:: bool check_prime(BigInt n, RandomNumberGenerator& rng)
+
+.. cpp:function:: bool verify_prime(BigInt n, RandomNumberGenerator& rng)
+
+ Three variations on primality testing. All take an integer to test along with
+ a random number generator, and return true if the integer seems like it might
+ be prime; there is a chance that this function will return true even with
+ a composite number. The probability decreases with the amount of work performed,
+ so it is much less likely that ``verify_prime`` will return a false positive
+ than ``check_prime`` will.
+
+.. cpp:function BigInt random_prime(RandomNumberGenerator& rng, \
+ size_t bits, BigInt coprime = 1, size_t equiv = 1, size_t equiv_mod = 2)
+
+ Return a random prime number of ``bits`` bits long that is
+ relatively prime to ``coprime``, and equivalent to ``equiv`` modulo
+ ``equiv_mod``.
+
diff --git a/doc/build_log.txt b/doc/build_log.txt
new file mode 100644
index 000000000..2e92a6f90
--- /dev/null
+++ b/doc/build_log.txt
@@ -0,0 +1,231 @@
+
+Build Log
+========================================
+
+To report build results (successful or not), email the `development
+list <http://lists.randombit.net/mailman/listinfo/botan-devel/>`_ your
+results and relevant system information (OS versions, compiler name
+and version, CPU architecture and other hardware information,
+configuration settings).
+
+Debian reports the build results for 1.8 on `a number of platforms
+<http://buildd.debian.org/pkg.cgi?pkg=botan1.8>`_.
+
+=========== ======= =================== ======================== ============================ ========
+Date Version OS CPU Compiler Results
+=========== ======= =================== ======================== ============================ ========
+2011-05-09 1.9.17 Debian 6.0 Intel Atom D510 GCC 4.4.5 OK
+2010-05-09 1.9.17 Gentoo 10.0 PowerPC G5 GCC 4.4.5 OK
+2011-05-02 1.9.17 FreeBSD 8.2 x86-64 GCC 4.2.1 OK
+2011-04-25 1.9.16 Gentoo 10.0 Intel Core i7-860 Clang 2.9 Miscompiles SSE2 IDEA
+2011-04-23 1.9.16 Gentoo 10.0 Intel Core i7-860 Sun C++ 5.10 OK
+2011-04-22 1.9.16 Gentoo 10.0 Intel Core i7-860 Intel C++ 11.1 OK
+2011-04-15 1.9.16 Haiku R1-alpha2 x86 GCC 4.3.3 OK
+2011-04-15 1.9.16 Haiku R1-alpha2 x86 GCC 2.95.3 Can't compile
+2011-04-15 1.9.16 Windows 7 x86-64 Visual C++ 16.00.30319.01 OK
+2011-04-15 1.9.16 QNX 6.4.1 i386 GCC 4.3.3 OK
+2011-03-29 1.9.15 Gentoo 10.0 Intel Core i5-520M GCC 4.5.2 OK
+2011-03-21 1.9.15 Ark Linux x86-64 GCC 4.6.0-pre OK
+2011-03-21 1.9.15 Ark Linux x86-32 GCC 4.6.0-pre OK
+2011-03-21 1.9.15 Ark Linux ARM GCC 4.6.0-pre OK
+2011-03-18 1.9.14 Debian 6.0 Intel Atom D510 GCC 4.4.5 OK
+2011-03-01 1.9.14 OpenBSD 4.6 UltraSPARC IIIi GCC 4.2.4 OK
+2011-03-01 1.9.14 OpenBSD 4.7 i386 GCC 4.2.4 OK
+2011-03-01 1.9.14 Debian 6.0 Intel Madison IA-64 GCC 4.4.5 OK
+2011-03-01 1.9.14 Ubuntu 9.10 ARM Cortex-A8 GCC 4.4.1 OK
+2011-03-01 1.9.14 Debian 5.0 PowerPC G5/970 GCC 4.3.2 OK
+2011-03-01 1.9.14 Windows 7 x64 Intel Core i5-520M Visual C++ 15.00.30729.01 OK (32/64)
+2011-03-01 1.9.14 Gentoo 10.0 Intel Core i7-860 Open64 4.2.1 OK
+2011-03-01 1.9.14 Gentoo 10.0 Intel Core i7-860 Sun C++ 5.10 OK
+2011-03-01 1.9.14 Gentoo 10.0 Intel Core i7-860 Intel C++ 11.1 OK
+2011-03-01 1.9.14 Gentoo 10.0 Intel Core i7-860 GCC 4.5.2 OK
+2011-02-14 1.9.13 NetBSD 5.1 Intel Xeon P4 GNU GCC 4.1.3 OK
+2011-01-14 1.9.12 FreeBSD 8.1 x86-64 Clang 2.9 OK
+2010-11-29 1.9.11 Windows 7 x64 Intel Core i5-520M Visual C++ 15.00.30729.01 OK (32/64)
+2010-11-29 1.9.11 Gentoo 10.0 Intel Core i7-860 GNU GCC 4.1.2, 4.4.5, 4.5.1 OK
+2010-11-29 1.9.11 Debian 5.0 PowerPC G5/970 GCC 4.3.2 OK
+2010-11-29 1.9.11 Gentoo 10.0 Intel Core i7-860 Intel C++ 11.1 OK
+2010-11-29 1.9.11 Gentoo 10.0 Intel Core i7-860 Clang 2.8 Miscompiles SSE2 IDEA
+2010-11-29 1.9.11 Debian 5.0 (32 bit) UltraSPARC T1 Niagra GCC 4.3.2 OK
+2010-09-07 1.9.11 Gentoo 10.0 Intel Core i7-860 Sun C++ 5.10 OK
+2010-08-12 1.9.10 Debian 5.0 Xeon X5450 Harpertown GCC 4.3.2 OK
+2010-08-12 1.9.10 Ubuntu 9.04 Intel Atom N270 GCC 4.3.3 OK
+2010-08-12 1.9.10 Debian 5.0 Intel Prescott GCC 4.3.2 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 GCC 3.4.6 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 GCC 4.1.2 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 GCC 4.3.5 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 GCC 4.4.4 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 GCC 4.5.1 OK
+2010-08-08 1.9.10 Gentoo 10.0 Intel Core i7-860 Clang SVN Miscompiles Turing
+2010-07-27 1.9.9 Debian 5.0 AMD Magny-Cours GCC 4.3.2, 4.5.0 OK
+2010-06-16 1.9.8 Gentoo 10.0 Intel Core2 Q6600 Intel C++ 11.1 OK
+2010-06-16 1.9.8 Debian 5.0 (32 bit) UltraSPARC T1 Niagra GCC 4.3.2 OK
+2010-06-16 1.9.8 Debian 5.0 Intel Madison IA-64 GCC 4.3.2 OK
+2010-06-16 1.9.8 Gentoo 10.0 IBM POWER5+ GCC 4.1.2, 4.2.4, 4.3.2 OK
+2010-06-16 1.9.8 OpenBSD 4.6 UltraSPARC IIIi GCC 3.3.5, 4.2.4 OK
+2010-06-16 1.9.8 FreeBSD 8.0 AMD Opteron 252 GCC 4.2.1 OK
+2010-06-16 1.9.8 gNewSense MIPS Loongson-2 (64) GCC 4.3.2 OK
+2010-06-16 1.9.8 Ubuntu 9.10 ARM Cortex-A8 GCC 4.4.1 OK
+2010-06-11 1.9.8 Gentoo 10.0 Intel Core2 Q6600 GCC 3.4.6, 4.1.2 OK
+2010-06-11 1.9.8 Windows 7 x64 Intel Core i5-520M Visual C++ 15.00.30729.01 OK (32 and 64 bit)
+2010-06-11 1.9.8 Gentoo 10.0 Intel Core i5-520M GCC 4.5.0 OK
+2010-06-01 1.9.8 OpenBSD 4.7 i386 GCC 3.3.5 OK
+2010-05-03 1.9.7 Windows 7 x64 Intel Core i5-520M Visual C++ 15.00.30729.01 OK
+2010-04-27 1.9.7 Gentoo 10.0 PPC 970FX (G5) GCC 4.3.4 OK
+2010-04-27 1.9.7 Gentoo 10.0 Intel Core2 Q6600 GCC 4.4.3, 4.5.0 OK
+2010-03-18 1.9.4 Gentoo 10.0 Intel Core2 Q6600 GCC 4.4.3 OK
+2010-03-18 1.9.4 Debian 5.0 UltraSPARC II (64) GCC 4.3.2 OK
+2010-03-18 1.9.4 Gentoo 10.0 PowerPC G5 GCC 4.3.4 OK
+2010-03-18 1.9.4 Gentoo 10.0 IBM POWER5+ GCC 4.3.2 OK
+2010-03-15 1.9.4 Windows XP x86 Visual C++ 15.00.30729.01 OK
+2010-03-10 1.9.4 FreeBSD 8.0 AMD Opteron 252 GCC 4.2.1 OK, but missing includes
+2009-12-29 1.9.4 Debian 4.0 PowerPC G4 7455 GCC 4.1.2 OK
+2009-12-23 1.9.4 Debian 5.0 Xeon X5450 Harpertown GCC 4.3.2 OK
+2009-11-13 1.9.3 Debian 5.0 UltraSPARC II GCC 4.3.2 OK
+2009-11-10 1.9.2 Debian 4.0 PowerPC G4 GCC 4.1.2 OK
+2009-11-03 1.9.2 Debian Linux 4.0 AMD Opteron 8354 GCC 4.4.1 OK
+2009-10-27 1.9.2 Debian Linux 5.0 Xeon X5450 Harpertown GCC 4.3.2 OK
+2009-10-23 1.9.1 Gentoo Linux Intel Core2 Q6600 GCC 4.4.1, Intel C++ 11.1 OK
+2009-10-23 1.9.1 Gentoo Linux AMD Opteron 2212 GCC 4.3.4 OK
+2009-09-24 1.9.0 Debian 4.0 AMD Opteron 8354 GCC 4.1.2, 4.4.1 OK
+2010-07-01 1.8.9 OpenSUSE 10.3 Intel Core2 GCC 4.2.1 OK
+2010-06-22 1.8.9 Slackware 13.1 Intel E5400 (64) GCC 4.4.4 OK
+2010-06-22 1.8.9 Slackware 13.1 Pentium-M (32) GCC 4.4.4 OK
+2010-06-16 1.8.9 Debian 5.0 (32 bit) UltraSPARC T1 Niagra GCC 4.3.2 (GCC TR1) Crashes in GF(p) tests
+2010-03-18 1.8.8 Debian 5.0 UltraSPARC II (64) GCC 4.3.2 OK
+2008-10-23 1.8.7 Gentoo 2008.0 PPC 970FX (G5) GCC 4.3.4 OK
+2009-10-07 1.8.7 Debian GNU/Hurd 0.3 i686 GCC 4.3.4 OK
+2009-09-08 1.8.7 Gentoo 2008.0 Intel Core2 Q6600 GCC 4.4.1 OK
+2009-09-04 1.8.6 Gentoo 2008.0 PPC 970FX (G5) GCC 4.3.4 OK
+2009-08-13 1.8.6 Gentoo 2008.0 Intel Core2 Q6600 GCC 4.3.3 OK
+2009-08-13 1.8.6 Windows XP x86 Visual C++ 15.00.30729.01 OK (no TR1)
+2009-08-03 1.8.5 openSuSE 10.3 x86 GCC 4.2.1 OK
+2009-08-03 1.8.5 Gentoo 2008.0 Intel Core2 Q6600 Open64 4.2.1 BAD: Miscompiles several ciphers
+2009-07-31 1.8.5 Solaris 11 x86 Sun C++ 5.9 OK, but minor build problems
+2009-07-30 1.8.5 Gentoo 2006.1 UltraSPARC IIe (32) GCC 3.4.6 OK (no TR1)
+2009-07-25 1.8.5 Debian 4.0 AMD Opteron 2212 GCC 4.1.2 OK
+2009-07-23 1.8.5 Gentoo 2008.0 Marvel Feroceon 88FR131 GCC 4.1.2 OK
+2009-07-23 1.8.5 Debian 5.0 Intel Xscale 80219 GCC 4.3.2 OK
+2009-07-23 1.8.5 Debian 5.0 UltraSPARC II (64) GCC 4.3.2 OK
+2009-07-23 1.8.5 Debian 5.0 UltraSPARC II (32) GCC 4.3.2 BAD: bus error in GF(p)
+2009-07-23 1.8.5 Debian 5.0 UltraSPARC II (32) GCC 4.1.3 BAD: miscompiles BigInt code
+2009-07-23 1.8.5 Debian 4.0 PowerPC G4 GCC 4.1.2 OK
+2009-07-23 1.8.5 Debian 4.0 PowerPC G5 GCC 4.1.2 OK
+2009-07-23 1.8.5 Debian 5.0 Intel Madison IA-64 GCC 4.1.3, 4.3.2 OK
+2009-07-23 1.8.5 Debian 5.0 HP-PA PA8600 GCC 4.3.2 OK
+2009-07-23 1.8.5 Mandriva 2008.1 MIPS Loongson-2 (32) GCC 4.2.3 OK
+2009-07-23 1.8.5 gNewSense MIPS Loongson-2 (64) GCC 4.3.2 OK
+2009-07-21 1.8.5 Windows XP x86 Visual C++ 15.00.30729.01 OK (no TR1)
+2009-07-21 1.8.5 Gentoo 2008.0 Intel Core2 Q6600 GCC 4.1.2, 4.3.3 OK
+2009-07-21 1.8.5 Gentoo 2008.0 Intel Core2 Q6600 Intel C++ 10.1 20080801 OK
+2009-07-21 1.8.5 Gentoo 2008.0 AMD Opteron 2212 GCC 4.3.3 OK
+2009-07-21 1.8.5 Ubuntu 8.04 Intel Xeon X5492 GCC 4.2.4 OK
+2009-07-21 1.8.5 MacOS X 10.5.6 Intel Core 2 Duo T5600 GCC 4.0.1 OK
+2009-07-21 1.8.5 Solaris 10 AMD Opteron GCC 3.4.3 OK (no TR1)
+2008-07-11 1.8.3 Fedora 11 Intel Pentium E5200 GCC 4.4.0 OK
+2008-07-10 1.8.3 Gentoo 2008.0 PPC 970FX (G5) GCC 4.3.1 OK
+2008-07-10 1.8.3 Gentoo 2008.0 IBM POWER5+ GCC 4.2.2 OK
+2009-07-10 1.8.3 Gentoo 2008.0 AMD Opteron 2212 GCC 4.3.3 OK
+2009-07-10 1.8.3 Ubuntu 8.04 Intel Xeon X5492 GCC 4.2.4 OK
+2009-07-10 1.8.3 MacOS X 10.5.6 Intel Core 2 Duo T5600 GCC 4.0.1 OK
+2009-07-10 1.8.3 Debian 5.0.1 Intel Core 2 Duo T5600 GCC 4.3.2 OK
+2009-07-10 1.8.3 Fedora 10 Intel Core 2 Duo T5600 GCC 4.3.2 OK
+2009-07-10 1.8.3 Solaris 10 AMD Opteron GCC 3.4.3 OK (no TR1)
+2009-07-09 1.8.3 Gentoo 2008.0 Intel Core2 Q6600 Intel C++ 10.1 20080801 OK
+2009-07-02 1.8.3 Gentoo 2008.0 Intel Core2 Q6600 GCC 4.3.3 OK
+2009-07-02 1.8.3 FreeBSD 7.0 x86-64 GCC 4.2.1 OK
+2009-07-02 1.8.3 Windows XP x86 Visual C++ 15.00.30729.01 OK (no TR1)
+2008-12-27 1.8.0 Ubuntu 8.04 Pentium 4-M GCC 4.2.3 OK
+2008-12-14 1.8.0 FreeBSD 7.0 x86-64 GCC 4.2.1 OK
+2008-12-10 1.8.0 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.1.2, 4.2.4, 4.3.2 OK
+2008-12-05 1.7.24 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.1.2, 4.2.4, 4.3.2 OK
+2008-12-04 1.7.24 Gentoo 2007.0 Intel Core2 Q6600 Intel 10.1-20080801 OK
+2008-12-03 1.7.24 Solaris 10 x86 GCC 3.4.3 OK (small patch needed, fixed in 1.8.0)
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.1.2 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.2.4 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.3.2 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.4-20081017 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 (32) GCC 4.1.2, 4.2.4 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 (32) GCC 4.3.2 OK (with Boost 1.35 TR1)
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 (32) GCC 4.3.2 Crashes (with libstdc++ TR1)
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 9.1-20061101 OK
+2008-11-24 1.7.23 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1-20080801 OK
+2008-11-24 1.7.23 Fedora 8 STI Cell PPU GCC 4.1.2 OK
+2008-11-24 1.7.23 Fedora 8 STI Cell PPU IBM XLC for Cell 0.9 45 minute link. Miscompiles DES
+2008-11-24 1.7.23 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2, 4.2.2, 4.3.1 OK
+2008-11-24 1.7.23 Gentoo 2007.0 AMD Opteron 2212 GCC 3.3.6, 4.1.2, 4.3.2 OK (no TR1 with 3.3.6)
+2008-11-24 1.7.23 Windows XP x86 Visual C++ 15.00.30729.01 OK (no TR1)
+2008-11-09 1.7.20 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-11-09 1.7.20 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.3.2 OK
+2008-11-09 1.7.20 Windows XP x86 Visual C++ 15.00.30729.01 OK
+2008-11-06 1.7.19 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-11-06 1.7.19 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.1.2, 4.3.1 OK
+2008-11-06 1.7.19 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 9.1-20061101 OK
+2008-11-06 1.7.19 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1-20080801 OK
+2008-11-06 1.7.19 Windows XP x86 Visual C++ 15.00.30729.01 OK
+2008-11-03 1.7.19 FreeBSD 7.0 x86-64 GCC 4.2.1 OK
+2008-10-24 1.7.18 Gentoo 2007.0 IBM POWER5+ GCC 4.2.2, 4.3.1 OK
+2008-10-24 1.7.18 Fedora 8 STI Cell PPU GCC 4.1.2 OK
+2008-10-22 1.7.18 Windows XP Pentium 4-M GCC 3.4.5 (MinGW) OK
+2008-10-22 1.7.18 Windows XP Pentium 4-M Visual C++ 15.00.30729.01 OK
+2008-10-22 1.7.18 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-10-22 1.7.18 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.1.2, 4.2.4, 4.3.2 OK
+2008-10-22 1.7.18 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 9.1-20061101 OK
+2008-10-22 1.7.18 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1-20080801 OK
+2008-10-07 1.7.15 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-10-07 1.7.15 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.3.1 OK
+2008-09-30 1.7.14 Gentoo 2007.0 PPC 970FX (G5) GCC 4.3.1 OK
+2008-09-30 1.7.14 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-09-30 1.7.14 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.3.1 OK
+2008-09-30 1.7.14 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1.018 OK
+2008-09-30 1.7.14 Windows XP Pentium 4-M Visual C++ 15.00.30729.01 OK
+2008-09-30 1.7.14 Windows XP Pentium 4-M GCC 3.4.5 (MinGW) OK
+2008-09-18 1.7.12 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2, 4.2.2 OK
+2008-09-18 1.7.12 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.2.4, 4.3.1 OK
+2008-09-18 1.7.12 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1.018 OK
+2008-09-18 1.7.12 Windows XP Pentium 4-M Visual C++ 15.00.30729.01 OK
+2008-09-18 1.7.12 Windows XP Pentium 4-M GCC 3.4.5 (MinGW) OK
+2008-09-16 1.7.12 Fedora 7 STI Cell PPU GCC 4.1.2 OK
+2008-09-16 1.7.11 MacOS X 10.4 (32) Intel Core2 GCC 4.0.1 OK
+2008-09-11 1.7.11 Gentoo 2007.0 Intel Core2 Q6600 GCC 4.3.1 OK
+2008-09-11 1.7.11 Windows XP Pentium 4-M Visual C++ 15.00.30729.01 OK
+2008-09-08 1.7.9 Gentoo 2007.0 Intel Core2 Q6600 Intel C++ 10.1.018 OK
+2008-08-28 1.7.9 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2 OK
+2008-08-28 1.7.9 Gentoo 2007.0 IBM POWER5+ GCC 4.2.2 OK
+2008-08-28 1.7.9 Gentoo 2007.0 IBM POWER5+ GCC 4.3.1 OK
+2008-08-28 1.7.9 Gentoo STI Cell PPU GCC 4.1.2 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 GCC 4.1.2 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 GCC 4.2.4 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 GCC 4.3.1 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 GCC 4.4-20080822 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 Intel C++ 9.1-20061101 OK
+2008-08-27 1.7.9 Gentoo Intel Core2 Q6600 Intel C++ 10.1-20080602 OK
+2008-08-27 1.7.9 Windows XP Pentium 4-M Visual C++ 2008 OK
+2008-08-27 1.7.9 Windows XP Pentium 4-M GCC 3.4.5 (MinGW) OK
+2008-08-18 1.7.8 Ubuntu 8.04 Pentium 4-M GCC 4.2.3 OK
+2008-08-18 1.7.8 Windows XP Pentium 4-M Visual C++ 2008 OK
+2008-08-18 1.7.8 Windows XP Pentium 4-M GCC 3.4.5 (MinGW) OK
+2008-07-18 1.7.8 Gentoo IBM POWER5+ GCC 4.1.2 OK
+2008-07-15 1.7.8 Gentoo Intel Core2 Q6600 GCC 4.3.1 OK
+2008-07-06 1.7.7 Gentoo Intel Core2 Q6600 PGI 7.2 Miscompiles TEA, Turing, BigInt
+2008-06-28 1.7.7 Gentoo Pentium 4-M GCC 4.1.2 OK
+2008-06-28 1.7.7 Gentoo Intel Core2 Q6600 GCC 4.1.2, 4.2.4, 4.3.1 OK
+2008-06-28 1.7.7 Gentoo Intel Core2 Q6600 Intel C++ 10.1 OK
+2008-06-28 1.7.7 Gentoo IBM POWER5+ GCC 4.1.2, 4.2.2 OK
+2008-06-25 1.7.6 Gentoo IBM POWER5+ GCC 4.1.2, 4.2.2 OK
+2008-06-09 1.7.6 Gentoo PPC 970FX (G5) GCC 4.1.2 OK
+2008-05-14 1.7.6 Gentoo Intel Core2 Q6600 Intel C++ 9.1 Builds, but link problems
+2008-05-14 1.7.6 Gentoo Intel Core2 Q6600 GCC 4.2.3 OK
+2008-04-21 1.7.5 Gentoo STI Cell PPU GCC 4.1.2 OK
+2008-04-14 1.7.5 Debian Pentium 4 GCC 4.1.2 OK
+2008-04-13 1.7.5 Gentoo 2006.1 UltraSPARC II (32) GCC 3.4.6 OK
+2008-04-12 1.7.5 RHEL3 Pentium 4 Xeon GCC 3.2.3 OK
+2008-04-12 1.7.5 Gentoo Intel Core2 Q6600 Intel C++ 10.1 OK
+2008-04-12 1.7.5 Gentoo AMD Opteron 2212 GCC 4.1.2 OK
+2008-04-12 1.7.5 Gentoo Intel Core2 Q6600 GCC 4.2.3 OK
+2008-09-16 1.6.5 MacOS X 10.4 Intel Core2 (32) GCC 4.0.1 OK
+2008-08-28 1.6.5 Gentoo 2007.0 IBM POWER5+ GCC 4.1.2, 4.2.2, 4.3.1 OK
+2008-08-27 1.6.5 Gentoo Intel Core2 Q6600 GCC 4.3.1, 4.4-20080822 OK
+2008-08-18 1.6.4 Windows XP Pentium 4-M Visual C++ 2008 OK
+2008-07-02 1.6.4 Solaris 10 x86-64 Sun Forte 12 OK
+=========== ======= =================== ======================== ============================ ========
diff --git a/doc/building.tex b/doc/building.tex
deleted file mode 100644
index 7164f74eb..000000000
--- a/doc/building.tex
+++ /dev/null
@@ -1,444 +0,0 @@
-\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{[email protected]}}
-\date{2010-06-10}
-
-\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.py, which is a Python
-script. Python 2.5 or later is required. If you want to use the
-(incompatible) Python 3, you must first run the \texttt{2to3} script
-on it.
-
-\section{For the Impatient}
-
-\begin{verbatim}
-$ ./configure.py [--prefix=/some/directory]
-$ make
-$ make check
-$ 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 Python installed in an unusual
-spot, you might need to prefix the \texttt{configure.py} command with
-\texttt{python} or \texttt{/path/to/python}.
-
-\section{Building the Library}
-
-The first step is to run \filename{configure.py}, which is a Python
-script that creates various directories, config files, and a Makefile
-for building everything. The script requires at least Python 2.5; any
-later version of Python 2.x should also work. Python 3.1 will also
-work but requires an extra step, see the section ``Using Python 3.1'',
-later in this document.
-
-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|.
-
-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. 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 enabled. For instance on one system
-we might see lines like:
-
-\begin{verbatim}
- INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64
- INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats
- INFO: Skipping mod because compiler incompatible - mp_ia32_msvc
- INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib
-\end{verbatim}
-
-The ones that are 'loaded on request only' have to be explicitly asked
-for, because they rely on third party libraries which your system
-might not have. For instance to enable zlib support, add
-\verb|--with-zlib| to your invocation of \verb|configure.py|.
-
-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=zlib| and \verb|--disable-modules=rc5,idea|.
-Modules not listed on the command line will simply be loaded if needed
-or if configured to load by default. If you use \verb|--no-autoload|,
-only the most core modules will be included; you can then explicitly
-enable things that you want to use with enable-modules. This is useful
-for creating a minimal build targetted to a specific application.
-
-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}.
-
-\subsection{POSIX / Unix}
-
-The basic build procedure on Unix and Unix-like systems is:
-
-\begin{verbatim}
- $ ./configure.py [--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}
-
-On Unix systems the script will default to using GCC; use
-\texttt{--cc} if you want something else. For instance use
-\texttt{--cc=icc} for Intel C++ and \texttt{--cc=clang} for Clang.
-
-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.py}, like so:
-
-\verb|./configure.py --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{Mac OS X}
-
-In general the Unix instructions above should apply, however OS X does
-not support \texttt{LD\_LIBRARY\_PATH}. Thomas Keller suggests instead
-running \verb|install_name_tool| between building and running the
-self-test program:
-
-\begin{verbatim}
- $ VERSION=1.9.10
- $ install_name_tool -change $(otool -X -D libbotan-$VERSION.dylib) \
- $PWD/libbotan-$VERSION.dylib check
-\end{verbatim}
-
-\subsection{MS Windows}
-
-If you don't want to deal with building botan on Windows, check the
-website; commonly prebuilt Windows binaries with installers are
-available, especially for stable versions.
-
-You need to have a copy of Python installed, and have both Python and
-your chosen compiler in your path. Open a command shell (or the SDK
-shell), and run:
-
-\begin{verbatim}
- > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU]
- > nmake
- > nmake check # optional, but recommended
- > nmake install
-\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 versions of Windows support both methods, so
-this shouldn't be much of an issue anymore.
-
-By default the install target will be 'C:\textbackslash botan'; you
-can modify this with the \texttt{--prefix} option.
-
-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).
-
-\section{Trickier Things}
-
-\subsection{Modules Relying on Third Party Libraries}
-
-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. Most are loaded (or not) automatically as
-necessary, but some require external libraries are thus must be
-enabled at build time; these include:
-
-\newcommand{\mod}[2]{\textbf{#1}: #2}
-
-\begin{list}{$\cdot$}
- \item \mod{bzip2}{Enables an application to perform bzip2
- compression and decompression using the library. Available on any
- system that has bzip2. To enable, use option \texttt{--with-bzip2}}
-
- \item \mod{zlib}{Enables an application to perform zlib compression
- and decompression using the library. Available on any system that
- has zlib. To enable, use option \texttt{--with-zlib}}
-
- \item \mod{gnump}{An engine that uses GNU MP to speed up PK
- operations. GNU MP 4.1 or later is required. To enable, use
- option \texttt{--with-gnump}}
-
- \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. Note that, unlike GNU MP, OpenSSL's versions are not
- always faster than the versions built into botan. To enable, use
- option \texttt{--with-openssl}}
-
-\end{list}
-
-\subsection{Amalgamation}
-
-You can also configure Botan to be built using only a single source
-file; this is quite convenient if you plan to embed the library into
-another application. To do so, run \filename{configure.py} with
-whatever arguments you would ordinarily use, along with the option
-\texttt{--gen-amalgamation}. This will create two (rather large)
-files, \filename{botan\_all.h} and \filename{botan\_all.cpp}.
-
-Whenever you would have included a botan header, you can then include
-\filename{botan\_all.h}, and include \filename{botan\_all.cpp} along
-with the rest of the source files in your build. If you want to be
-able to easily switch between amalgamated and non-amalgamated versions
-(for instance to take advantage of prepackaged versions of botan on
-operating systems that support it), you can instead ignore
-\filename{botan\_all.h} and use the headers from
-\filename{build/include} as normal.
-
-\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{Using Python 3.1}
-
-The versions of Python begininning with 3 are (intentionally)
-incompatible with the (currently more common) 2.x series. If you want
-to use Python 3.1 to set up the build, you'll have to use the
-\texttt{2to3} program (included in the Python distribution) on the
-script; this will convert the script to the Python 3.x dialect:
-
-\begin{verbatim}
- $ python ./configure.py
- File "configure.py", line 860
- except KeyError, e:
- ^
-SyntaxError: invalid syntax
- $ # incompatible python version, let's fix it
- $ 2to3 -w configure.py
-[...]
-RefactoringTool: Files that were modified:
-RefactoringTool: configure.py
- $ python ./configure.py
-[...]
-\end{verbatim}
-
-\subsection{Local Configuration}
-
-You may want to do something peculiar with the configuration; to
-support this there is a flag to \filename{configure.py} 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.
-
-\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.
-
-\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.9 --modversion
-1.9.8
-$ pkg-config botan-1.9 --cflags
--I/usr/local/include
-$ pkg-config botan-1.9 --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.
-
-\section{Language Wrappers}
-
-\subsection{Building the Python wrappers}
-
-The Python wrappers for Botan use Boost.Python, so you must have Boost
-installed. To build the wrappers, add the flag
-
-\verb|--with-boost-python|
-
-to \verb|configure.py|. This will create a second makefile,
-\verb|Makefile.python|, with instructions for building the Python
-module. After building the library, execute
-
-\begin{verbatim}
-$ make -f Makefile.python
-\end{verbatim}
-
-to build the module. Currently only Unix systems are supported, and
-the Makefile assumes that the version of Python you want to build
-against is the same one you used to run \verb|configure.py|.
-
-To install the module, use the \verb|install| target.
-
-Examples of using the Python module can be seen in \filename{doc/python}
-
-\subsection{Building the Perl XS wrappers}
-
-To build the Perl XS wrappers, change your directory to
-\filename{src/wrap/perl-xs} and run \verb|perl Makefile.PL|, then run
-\verb|make| to build the module and \verb|make test| to run the test
-suite.
-
-\begin{verbatim}
-$ perl Makefile.PL
-Checking if your kit is complete...
-Looks good
-Writing Makefile for Botan
-$ make
-cp Botan.pm blib/lib/Botan.pm
-AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan)
-/usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...]
-g++ -c -Wno-write-strings -fexceptions -g [...]
-Running Mkbootstrap for Botan ()
-chmod 644 Botan.bs
-rm -f blib/arch/auto/Botan/Botan.so
-g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \
- -lbotan -lbz2 -lpthread -lrt -lz \
-
-chmod 755 blib/arch/auto/Botan/Botan.so
-cp Botan.bs blib/arch/auto/Botan/Botan.bs
-chmod 644 blib/arch/auto/Botan/Botan.bs
-Manifying blib/man3/Botan.3pm
-$ make test
-PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...]
-t/base64......ok
-t/filt........ok
-t/hex.........ok
-t/oid.........ok
-t/pipe........ok
-t/x509cert....ok
-All tests successful.
-Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU)
-\end{verbatim}
-
-\end{document}
diff --git a/doc/building.txt b/doc/building.txt
new file mode 100644
index 000000000..9e7be79a3
--- /dev/null
+++ b/doc/building.txt
@@ -0,0 +1,433 @@
+
+Building The Library
+=================================
+
+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.py, which is a `Python
+<http://www.python.org>`_ script. Python 2.5 or later is required.
+
+For the impatient, this works for most systems::
+
+ $ ./configure.py [--prefix=/some/directory]
+ $ make
+ $ make check
+ $ make install
+
+Or using ``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 Python installed in an unusual spot, you
+might need to prefix the ``configure.py`` command with ``python`` or
+``/path/to/python``::
+
+ $ python ./configure.py [arguments]
+
+Configuring the Build
+---------------------------------
+
+The first step is to run ``configure.py``, which is a Python script
+that creates various directories, config files, and a Makefile for
+building everything. The script requires at least Python 2.5; any
+later version of Python 2.x should also work. Python 3.1 will also
+work but requires an extra step; see :ref:`configure_with_python3` for
+details.
+
+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 ``--cc``,
+``--os``, and ``--cpu``.
+
+You can pass basically anything reasonable with ``--cpu``: the script
+knows about a large number of different architectures, their
+sub-models, and common aliases for them. 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 enabled. For instance on one system
+we might see lines like::
+
+ INFO: Skipping, by request only - bzip2 gnump openssl qt_mutex zlib
+ INFO: Skipping, incompatible CPU - aes_intel aes_ssse3 asm_x86_64 mp_asm64 mp_x86_64 sha1_x86_64
+ INFO: Skipping, incompatible OS - beos_stats cryptoapi_rng win32_crit_section win32_stats
+ INFO: Skipping, incompatible compiler - mp_msvc64 mp_x86_32_msvc
+
+The ones that are 'loaded on request only' have to be explicitly asked
+for, because they rely on third party libraries which your system
+might not have. For instance to enable zlib support, add
+``--with-zlib`` to your invocation of ``configure.py``.
+
+You can control which algorithms and modules are built using the
+options ``--enable-modules=MODS`` and ``--disable-modules=MODS``, for
+instance ``--enable-modules=zlib`` and ``--disable-modules=rc5,idea``.
+Modules not listed on the command line will simply be loaded if needed
+or if configured to load by default. If you use ``--no-autoload``,
+only the most core modules will be included; you can then explicitly
+enable things that you want to use with ``--enable-modules``. This is
+useful for creating a minimal build targeting to a specific
+application, especially in conjunction with the amalgamation option;
+see :ref:`amalgamation`.
+
+For instance::
+
+ $ ./configure.py --no-autoload --enable-modules=rsa,ecdsa,eme1,emsa1,emsa4
+
+will set up a build that only includes RSA, ECDSA, and some padding
+modes, along with their dependencies. A small subset of core features,
+including AES, SHA-2, HMAC, and the multiple precision integer
+library, are always loaded.
+
+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
+``--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
+``src/build-data/makefile``.
+
+On Unix
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The basic build procedure on Unix and Unix-like systems is::
+
+ $ ./configure.py [--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
+
+On Unix systems the script will default to using GCC; use
+``--cc`` if you want something else. For instance use
+``--cc=icc`` for Intel C++ and ``--cc=clang`` for Clang.
+
+The ``make install`` target has a default directory in which it
+will install Botan (typically ``/usr/local``). You can override
+this by using the ``--prefix`` argument to
+``configure.py``, like so:
+
+``./configure.py --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
+``/etc/ld.so.conf`` and run ``ldconfig`` (as root) in
+order for new shared libraries to be picked up by the linker. An
+alternative is to set your ``LD_LIBRARY_PATH`` shell variable
+to include the directory that the Botan libraries were installed into.
+
+On Mac OS X
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In general the Unix instructions above should apply, however OS X does
+not support ``LD_LIBRARY_PATH``. Thomas Keller suggests instead
+running ``install_name_tool`` between building and running the
+self-test program::
+
+ $ VERSION=1.10.0 # or whatever the current version is
+ $ install_name_tool -change $(otool -X -D libbotan-$VERSION.dylib) \
+ $PWD/libbotan-$VERSION.dylib check
+
+On MS Windows
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you don't want to deal with building botan on Windows, check the
+website; commonly prebuilt Windows binaries with installers are
+available, especially for stable versions.
+
+You need to have a copy of Python installed, and have both Python and
+your chosen compiler in your path. Open a command shell (or the SDK
+shell), and run::
+
+ > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU]
+ > nmake
+ > nmake check # optional, but recommended
+ > nmake install
+
+For Win95 pre OSR2, the ``cryptoapi_rng`` module will not work,
+because CryptoAPI didn't exist. And all versions of NT4 lack the
+ToolHelp32 interface, which is how ``win32_stats`` does its slow
+polls, so a version of the library built with that module will not
+load under NT4. Later versions of Windows support both methods, so
+this shouldn't be much of an issue anymore.
+
+By default the install target will be ``C:\botan``; you can modify
+this with the ``--prefix`` option.
+
+When building your applications, all you have to do is tell the
+compiler to look for both include files and library files in
+``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).
+
+Other Build-Related Tasks
+----------------------------------------
+
+.. _amalgamation:
+
+The Amalgamation Build
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can also configure Botan to be built using only a single source
+file; this is quite convenient if you plan to embed the library into
+another application. To do so, run ``configure.py`` with whatever
+arguments you would ordinarily use, along with the option
+``--gen-amalgamation``. This will create two (rather large) files,
+``botan_all.h`` and ``botan_all.cpp``.
+
+Whenever you would have included a botan header, you can then include
+``botan_all.h``, and include ``botan_all.cpp`` along with the rest of
+the source files in your build. If you want to be able to easily
+switch between amalgamated and non-amalgamated versions (for instance
+to take advantage of prepackaged versions of botan on operating
+systems that support it), you can instead ignore ``botan_all.h`` and
+use the headers from ``build/include`` as normal.
+
+You can also build the library as normal but using the amalgamation
+instead of the individual source files using ``--via-amalgamation``.
+This is essentially a very simple form of link time optimization;
+because the entire library source is visible to the compiler, it has
+more opportunities for interprocedural optimizations.
+
+Modules Relying on Third Party Libraries
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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. Most are loaded (or not) automatically as
+necessary, but some require external libraries are thus must be
+enabled at build time; these include:
+
+ - ``--with-bzip2`` enables the filters providing bzip2 compression
+ and decompression. Requires the bzip2 development libraries to be
+ installed.
+
+ - ``--with-zlib`` enables the filters providing zlib compression
+ and decompression. Requires the zlib development libraries to be
+ installed.
+
+ - ``--with-gnump`` adds an alternative engine for public key
+ cryptography that uses the GNU MP library. GNU MP 4.1 or later is
+ required.
+
+ - ``--with-openssl`` adds an engine that uses OpenSSL for some public
+ key operations and ciphers/hashes. OpenSSL 0.9.7 or later is
+ required. Note that OpenSSL's versions are not always faster than
+ the versions built into botan.
+
+Multiple Builds
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It may be useful to run multiple builds with different
+configurations. Specify ``--build-dir=<dir>`` to set up a build
+environment in a different directory.
+
+
+.. _configure_with_python3:
+
+Configuring the Build With Python 3.1
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The versions of Python beginning with 3 are (intentionally)
+incompatible with the (currently more common) 2.x series. If you want
+to use Python 3.1 to set up the build, you'll have to use the
+``2to3`` program (included in the Python distribution) on the
+script; this will convert the script to the Python 3.x dialect::
+
+ $ python ./configure.py
+ File "configure.py", line 860
+ except KeyError, e:
+ ^
+ SyntaxError: invalid syntax
+ $ # incompatible python version, let's fix it
+ $ 2to3 -w configure.py
+ [...]
+ RefactoringTool: Files that were modified:
+ RefactoringTool: configure.py
+ $ python ./configure.py
+ [...]
+
+Setting Distribution Info
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The build allows you to set some information about what distribution
+this build of the library comes from. It is particularly relevant to
+people packaging the library for wider distribution, to signify what
+distribution this build is from. Applications can test this value by
+checking the string value of the macro ``BOTAN_DISTRIBUTION_INFO``. It
+can be set using the ``--distribution-info`` flag to ``configure.py``,
+and otherwise defaults to "unspecified". For instance, a `Gentoo
+<http://www.gentoo.org>`_ ebuild might set it with
+``--distribution-info="Gentoo ${PVR}"`` where ``${PVR}`` is an ebuild
+variable automatically set to a combination of the library and ebuild
+versions.
+
+Local Configuration Settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You may want to do something peculiar with the configuration; to
+support this there is a flag to ``configure.py`` called
+``--with-local-config=<file>``. The contents of the file are
+inserted into ``build/build.h`` which is (indirectly) included
+into every Botan header and source file.
+
+Configuration Parameters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are some configuration parameters which you may want to tweak
+before building the library. These can be found in ``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 ``build/build.h`` are macros which let applications
+check which features are included in the current version of the
+library. All of them begin with ``BOTAN_HAS_``. For example, if
+``BOTAN_HAS_BLOWFISH`` is defined, then an application can include
+``<botan/blowfish.h>`` and use the Blowfish class.
+
+``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. Normally this defaults to either 32 or 64, depending
+on the processor. Unless you are building for a 8 or 16-bit CPU, this
+isn't worth messing with.
+
+``BOTAN_VECTOR_OVER_ALLOCATE``: The memory container ``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 *really* want to reduce memory usage, set it to 0. Otherwise, the
+default should be perfectly fine.
+
+``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
+purposes.
+
+Building Applications
+----------------------------------------
+
+Unix
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Botan usually links in several different system libraries (such as
+``librt`` and ``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 *is* linked against?
+
+The answer is to ask the ``botan-config`` script. This
+basically solves the same problem all the other ``*-config``
+scripts solve, and in basically the same manner.
+
+There are 4 options:
+
+``--prefix[=DIR]``: If no argument, print the prefix where Botan
+is installed (such as ``/opt`` or ``/usr/local``). If an
+argument is specified, other options given with the same command will
+execute as if Botan as actually installed at ``DIR`` and not
+where it really is; or at least where ``botan-config`` thinks
+it really is. I should mention that it
+
+``--version``: Print the Botan version number.
+
+``--cflags``: Print options that should be passed to the compiler
+whenever a C++ file is compiled. Typically this is used for setting
+include paths.
+
+``--libs``: Print options for which libraries to link to (this includes
+``-lbotan``).
+
+Your ``Makefile`` can run ``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 ``pkg-config``,
+namespaced by the major and minor versions. So it can be used,
+for instance, as::
+
+ $ pkg-config botan-1.10 --modversion
+ 1.10.0
+ $ pkg-config botan-1.10 --cflags
+ -I/usr/local/include
+ $ pkg-config botan-1.10 --libs
+ -L/usr/local/lib -lbotan -lm -lbz2 -lpthread -lrt
+
+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.
+
+Language Wrappers
+----------------------------------------
+
+Building the Python wrappers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Python wrappers for Botan use Boost.Python, so you must have Boost
+installed. To build the wrappers, pass the flag
+``--with-boost-python`` to ``configure.py``. This will create a second
+makefile, ``Makefile.python``, with instructions for building the
+Python module. After building the library, execute::
+
+ $ make -f Makefile.python
+
+to build the module. Currently only Unix systems are supported, and
+the Makefile assumes that the version of Python you want to build
+against is the same one you used to run ``configure.py``.
+
+To install the module, use the ``install`` target.
+
+Examples of using the Python module can be seen in
+``doc/examples/python``
+
+Building the Perl XS wrappers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To build the Perl XS wrappers, change your directory to
+``src/wrap/perl-xs`` and run ``perl Makefile.PL``, then run
+``make`` to build the module and ``make test`` to run the test
+suite::
+
+ $ perl Makefile.PL
+ Checking if your kit is complete...
+ Looks good
+ Writing Makefile for Botan
+ $ make
+ cp Botan.pm blib/lib/Botan.pm
+ AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan)
+ /usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...]
+ g++ -c -Wno-write-strings -fexceptions -g [...]
+ Running Mkbootstrap for Botan ()
+ chmod 644 Botan.bs
+ rm -f blib/arch/auto/Botan/Botan.so
+ g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \
+ -lbotan -lbz2 -lpthread -lrt -lz \
+
+ chmod 755 blib/arch/auto/Botan/Botan.so
+ cp Botan.bs blib/arch/auto/Botan/Botan.bs
+ chmod 644 blib/arch/auto/Botan/Botan.bs
+ Manifying blib/man3/Botan.3pm
+ $ make test
+ PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...]
+ t/base64......ok
+ t/filt........ok
+ t/hex.........ok
+ t/oid.........ok
+ t/pipe........ok
+ t/x509cert....ok
+ All tests successful.
+ Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU)
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 000000000..65f40314a
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+#
+# botan documentation build configuration file, created by
+# sphinx-quickstart on Sun Apr 3 11:41:06 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+sys.path.insert(0, os.pardir)
+
+# Avoid useless botan_version.pyc (Python 2.6 or higher)
+if 'dont_write_bytecode' in sys.__dict__:
+ sys.dont_write_bytecode = True
+
+import botan_version
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.0'
+
+"""
+Assert that we are running under Sphinx 1.0.7 or later. Earlier
+versions have bugs in the C++ domain that cause crashes. And
+needs_sphinx only allows us to assert needing a particular major/minor
+version.
+"""
+def check_sphinx_version():
+ import sphinx
+
+ version = map(int, sphinx.__version__.split('.'))
+ if version[0] == 1 and version[1] == 0 and version[2] < 7:
+ # Exit rather than throwing to avoid a confusing backtrace
+ print "This Sphinx is too old - upgrade to at least 1.0.7"
+ import sys
+ sys.exit(1)
+
+check_sphinx_version()
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.txt'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'contents'
+
+# General information about the project.
+project = u'botan'
+copyright = u'2000-2011, Jack Lloyd'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '%d.%d' % (botan_version.release_major, botan_version.release_minor)
+# The full version, including alpha/beta/rc tags.
+release = '%d.%d.%d' % (botan_version.release_major,
+ botan_version.release_minor,
+ botan_version.release_patch)
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%Y-%m-%d'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = False
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+highlight_language = 'cpp'
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'agogo'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+html_theme_options = {
+ 'linkcolor': 'blue',
+ 'headerlinkcolor': 'blue',
+ 'headercolor1': 'darkblue',
+ 'headercolor2': 'darkblue',
+ 'textalign': 'left'
+ }
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+html_title = 'Botan'
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'botandoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('contents', 'botan.tex', u'botan Reference Manual',
+ u'Jack Lloyd', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
diff --git a/doc/contents.txt b/doc/contents.txt
new file mode 100644
index 000000000..633625e14
--- /dev/null
+++ b/doc/contents.txt
@@ -0,0 +1,42 @@
+
+Contents
+=================================
+
+.. toctree::
+ :maxdepth: 2
+
+ index
+ building
+ firststep
+ filters
+ pubkey
+ x509
+ ssl
+ bigint
+ lowlevel
+ secmem
+ kdf
+ pbkdf
+ passhash
+ rng
+ fpe
+
+.. toctree::
+ :hidden:
+
+ license
+ credits
+ faq
+ users
+ support
+ download
+ pgpkey
+ algos
+ log
+ build_log
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/doc/credits.txt b/doc/credits.txt
index fde877e7b..076498756 100644
--- a/doc/credits.txt
+++ b/doc/credits.txt
@@ -1,78 +1,80 @@
-This is at least a partial credits-file of people that have
-contributed to the Botan project. It is sorted by name and formatted
-to allow easy grepping and beautification by scripts. The fields are:
-name (N), email (E), web-address (W), PGP key ID and fingerprint (P),
-description (D), and snail-mail address (S).
-
-Thanks,
- Jack Lloyd
-----------
-
-N: Charles Brockman
-W: http://www.securitygenetics.com/
-D: documentation editing
-S: Oregon, USA
-
-N: Martin Doering
-D: GF(p) arithmetic
-
-N: Olivier de Gaalon
-D: SQLite encryption codec (src/wrap/sqlite)
-
-N: Matthew Gregan
-D: Binary file I/O support, allocator fixes
-
-N: Hany Greiss
-D: Windows porting
-
-N: Manuel Hartl
-W: http://www.flexsecure.de/
-D: ECDSA, ECDH
-
-N: Yves Jerschow
-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
-D: Bzip2 compression module
-S: Colorado, USA
-
-N: Justin Karneges
-D: Qt support modules (mutexes and types), X.509 API design
-
-N: Jack Lloyd
-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
-D: GP(p) arithmetic
-
-N: Vaclav Ovsik
-D: Perl XS module (src/wrap/perl-xs)
-
-N: Luca Piccarreta
-D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
-S: Italy
-
-N: Falko Strenzke
-W: http://www.flexsecure.de/
-D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm
-S: Darmstadt, Germany
+
+Credits
+========================================
+
+This is at least a partial credits-file of people that have contributed
+to botan. It is sorted by name and formatted to allow easy grepping
+and beautification by scripts. The fields are name (N), email (E),
+web-address (W), PGP key ID and fingerprint (P), description (D), and
+snail-mail address (S).
+
+::
+
+ N: Charles Brockman
+ W: http://www.securitygenetics.com/
+ D: documentation editing
+ S: Oregon, USA
+
+ N: Martin Doering
+ D: GF(p) arithmetic
+
+ N: Olivier de Gaalon
+ D: SQLite encryption codec (src/wrap/sqlite)
+
+ N: Matthew Gregan
+ D: Binary file I/O support, allocator fixes
+
+ N: Hany Greiss
+ D: Windows porting
+
+ N: Manuel Hartl
+ W: http://www.flexsecure.de/
+ D: ECDSA, ECDH
+
+ N: Yves Jerschow
+ 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
+ D: Bzip2 compression module
+ S: Colorado, USA
+
+ N: Justin Karneges
+ D: Qt support modules (mutexes and types), X.509 API design
+
+ N: Jack Lloyd
+ 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 and Windows DLL support in general
+
+ N: Christoph Ludwig
+ D: GP(p) arithmetic
+
+ N: Vaclav Ovsik
+ D: Perl XS module (src/wrap/perl-xs)
+
+ N: Luca Piccarreta
+ D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
+ S: Italy
+
+ N: Falko Strenzke
+ W: http://www.flexsecure.de/
+ D: GF(p) arithmetic, CVC, Shanks-Tonelli algorithm
+ S: Darmstadt, Germany
diff --git a/doc/download.txt b/doc/download.txt
new file mode 100644
index 000000000..7d189d10a
--- /dev/null
+++ b/doc/download.txt
@@ -0,0 +1,100 @@
+
+Getting The Latest Sources
+========================================
+
+All releases are signed with a :doc:`PGP key <pgpkey>`.
+
+Unsure which release you want? Check the :ref:`FAQ <devel_vs_stable>`.
+
+.. only:: not website
+
+ .. note::
+
+ If you are viewing this documentation offline, a more recent
+ release `may be available <http://botan.randombit.net/download.html>`_
+
+Current Stable Release (1.10)
+----------------------------------------
+
+The current stable release is `1.10.0
+<http://botan.randombit.net/news/releases/1_10_0.html>`_ which was
+released on ?.
+
+Sources:
+
+`1.10.0 tar/gz <http://botan.randombit.net/files/Botan-1.10.0.tgz>`_
+(`1.10.0 tar/gz sig <http://botan.randombit.net/files/Botan-1.10.0.tgz.asc>`_),
+
+`1.10.0 tar/bzip <http://botan.randombit.net/files/Botan-1.10.0.tbz>`_
+(`1.10.0 tar/bzip sig <http://botan.randombit.net/files/Botan-1.10.0.tbz.asc>`_)
+
+Windows binary installer for use with Visual C++ 2010:
+
+`1.10.0 x86-32 installer
+<http://botan.randombit.net/files/win32/botan-1.10.0_win32.exe>`_
+
+`1.10.0 x86-64 installer
+<http://botan.randombit.net/files/win32/botan-1.10.0_win64.exe>`_
+
+Previous Stable Release (1.8)
+----------------------------------------
+
+The previous stable release is `1.8.11
+<http://botan.randombit.net/news/releases/1_8_11.html>`_ which was
+released on 2010-11-02.
+
+Sources:
+
+`1.8.11 tar/gz <http://botan.randombit.net/files/Botan-1.8.11.tgz>`_
+(`1.8.11 tar/gz sig <http://botan.randombit.net/files/Botan-1.8.11.tgz.asc>`_),
+
+`1.8.11 tar/bzip <http://botan.randombit.net/files/Botan-1.8.11.tbz>`_
+(`1.8.11 tar/bzip sig <http://botan.randombit.net/files/Botan-1.8.11.tbz.asc>`_)
+
+Windows binary installer for use with Visual C++ 2008:
+
+`1.8.11 x86-32 installer
+<http://botan.randombit.net/files/win32/botan-1.8.11_win32.exe>`_
+
+`1.8.11 x86-64 installer
+<http://botan.randombit.net/files/win32/botan-1.8.11_win64.exe>`_
+
+Accessing Version Control
+----------------------------------------
+
+Botan's development occurs using a distributed version control system
+called `Monotone <http://www.monotone.ca>`_.
+
+The main branch of development occurs on the branch named
+``net.randombit.botan``; this is probably the branch you want. To
+download that branch and set up a new workspace, run::
+
+ $ mtn db init --db=botan.mtn
+ $ mtn pull --db=botan.mtn randombit.net 'net.randombit.botan'
+ [...]
+ $ mtn checkout --db=botan.mtn --branch=net.randombit.botan
+ [...]
+
+By default the ``checkout`` command will place the workspace in a directory
+with the same name as the branch you are checking out. If you want a
+different directory name, just include it after the ``--branch`` option (you
+can also rename this directory at any time).
+
+If this is the first time you've connected to the server, Monotone
+will print::
+
+ mtn: first time connecting to server randombit.net
+ mtn: I'll assume it's really them, but you might want to double-check
+ mtn: their key's fingerprint: 8c0b868f2247215c63c96983b1c8ca0f0f0cfd9a
+
+The fingerprint shown above was the correct one as of September 21, 2010.
+
+To pull further changes, from anywhere in the workspace run these commands::
+
+ $ mtn pull
+ [...]
+ $ mtn update
+ [summary of changes]
+
+The ``mtn update`` command will give you a summary of which files changed;
+to view the full changelog, run ``mtn log``.
diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile
index a96e8d65d..6238512dc 100644
--- a/doc/examples/GNUmakefile
+++ b/doc/examples/GNUmakefile
@@ -3,7 +3,7 @@ BOTAN_CONFIG = botan-config
CXX = g++-4.5-20091112
CFLAGS = -O2 -ansi -std=c++0x -W -Wall -I../../build/include
-LIBS = -L../.. -lbotan
+LIBS = -L../.. -lbotan-1.10
SRCS=$(wildcard *.cpp)
diff --git a/doc/examples/asn1.cpp b/doc/examples/asn1.cpp
index 11e283a64..866e57d75 100644
--- a/doc/examples/asn1.cpp
+++ b/doc/examples/asn1.cpp
@@ -1,37 +1,3 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
- 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
-*/
-
-// 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>
@@ -45,8 +11,18 @@ using namespace Botan;
#include <stdio.h>
#include <ctype.h>
-void decode(BER_Decoder&, u32bit);
-void emit(const std::string&, u32bit, u32bit, const std::string& = "");
+// 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
+
+void decode(BER_Decoder&, size_t);
+void emit(const std::string&, size_t, size_t, const std::string& = "");
std::string type_name(ASN1_Tag);
int main(int argc, char* argv[])
@@ -57,7 +33,7 @@ int main(int argc, char* argv[])
return 1;
}
- Botan::LibraryInitializer init;
+ LibraryInitializer init;
try {
DataSource_Stream in(argv[1]);
@@ -83,7 +59,7 @@ int main(int argc, char* argv[])
return 0;
}
-void decode(BER_Decoder& decoder, u32bit level)
+void decode(BER_Decoder& decoder, size_t level)
{
BER_Object obj = decoder.get_next_object();
@@ -91,7 +67,7 @@ void decode(BER_Decoder& decoder, u32bit level)
{
const ASN1_Tag type_tag = obj.type_tag;
const ASN1_Tag class_tag = obj.class_tag;
- const u32bit length = obj.value.size();
+ const size_t length = obj.value.size();
/* hack to insert the tag+length back in front of the stuff now
that we've gotten the type info */
@@ -142,8 +118,8 @@ void decode(BER_Decoder& decoder, u32bit level)
{
bool not_text = false;
- for(u32bit j = 0; j != bits.size(); j++)
- if(!isgraph(bits[j]) && !isspace(bits[j]))
+ for(size_t i = 0; i != bits.size(); ++i)
+ if(!isgraph(bits[i]) && !isspace(bits[i]))
not_text = true;
Pipe pipe(((not_text) ? new Hex_Encoder : 0));
@@ -176,8 +152,8 @@ void decode(BER_Decoder& decoder, u32bit level)
rep = BigInt::encode(number, BigInt::Hexadecimal);
std::string str;
- for(u32bit j = 0; j != rep.size(); j++)
- str += (char)rep[j];
+ for(size_t i = 0; i != rep.size(); ++i)
+ str += (char)rep[i];
emit(type_name(type_tag), level, length, str);
}
@@ -198,8 +174,8 @@ void decode(BER_Decoder& decoder, u32bit level)
data.decode(bits, type_tag);
bool not_text = false;
- for(u32bit j = 0; j != bits.size(); j++)
- if(!isgraph(bits[j]) && !isspace(bits[j]))
+ for(size_t i = 0; i != bits.size(); ++i)
+ if(!isgraph(bits[i]) && !isspace(bits[i]))
not_text = true;
Pipe pipe(((not_text) ? new Hex_Encoder : 0));
@@ -213,14 +189,14 @@ void decode(BER_Decoder& decoder, u32bit level)
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));
+ for(size_t i = 0; i != bits.size(); ++i)
+ for(size_t j = 0; j != 8; ++j)
+ bit_set.push_back((bool)((bits[bits.size()-i-1] >> (7-j)) & 1));
std::string bit_str;
- for(u32bit j = 0; j != bit_set.size(); j++)
+ for(size_t i = 0; i != bit_set.size(); ++i)
{
- bool the_bit = bit_set[bit_set.size()-j-1];
+ bool the_bit = bit_set[bit_set.size()-i-1];
if(!the_bit && bit_str.size() == 0)
continue;
@@ -260,15 +236,15 @@ void decode(BER_Decoder& decoder, u32bit level)
}
}
-void emit(const std::string& type, u32bit level, u32bit length,
+void emit(const std::string& type, size_t level, size_t length,
const std::string& value)
{
- const u32bit LIMIT = 128;
- const u32bit BIN_LIMIT = 64;
+ const size_t LIMIT = 128;
+ const size_t BIN_LIMIT = 64;
int written = 0;
- written += printf(" d=%2d, l=%4d: ", level, length);
- for(u32bit j = INITIAL_LEVEL; j != level; j++)
+ written += printf(" d=%2d, l=%4d: ", (int)level, (int)length);
+ for(size_t i = INITIAL_LEVEL; i != level; ++i)
written += printf(" ");
written += printf("%s ", type.c_str());
diff --git a/doc/examples/bcrypt.cpp b/doc/examples/bcrypt.cpp
index 27a98cf33..4154b26ad 100644
--- a/doc/examples/bcrypt.cpp
+++ b/doc/examples/bcrypt.cpp
@@ -1,10 +1,3 @@
-/*
-* Bcrypt example
-* (C) 2011 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
#include <botan/botan.h>
#include <botan/bcrypt.h>
#include <iostream>
diff --git a/doc/examples/ca.cpp b/doc/examples/ca.cpp
index 25a3b5a03..6fd2eb15b 100644
--- a/doc/examples/ca.cpp
+++ b/doc/examples/ca.cpp
@@ -1,20 +1,3 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
- 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
-*/
-
#include <botan/botan.h>
#include <botan/x509_ca.h>
using namespace Botan;
diff --git a/doc/examples/dh.cpp b/doc/examples/dh.cpp
index 652c7b136..8d163303a 100644
--- a/doc/examples/dh.cpp
+++ b/doc/examples/dh.cpp
@@ -1,9 +1,3 @@
-/*
-* (C) 2009-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
#include <botan/botan.h>
#include <botan/dh.h>
#include <botan/pubkey.h>
@@ -14,41 +8,36 @@ using namespace Botan;
int main()
{
- Botan::LibraryInitializer init;
-
try
{
+ LibraryInitializer init;
+
AutoSeeded_RNG rng;
// Alice and Bob agree on a DH domain to use
- DL_Group shared_domain("modp/ietf/1024");
+ DL_Group shared_domain("modp/ietf/2048");
- // Alice creates a DH key and sends (the public part) to Bob
+ // Alice creates a DH key
DH_PrivateKey private_a(rng, shared_domain);
- // Alice sends to Bob her public key:
- MemoryVector<byte> public_a = private_a.public_value();
-
// Bob creates a key with a matching group
DH_PrivateKey private_b(rng, shared_domain);
+ // Alice sends to Bob her public key and a session parameter
+ MemoryVector<byte> public_a = private_a.public_value();
+ const std::string session_param =
+ "Alice and Bob's shared session parameter";
+
// Bob sends his public key to Alice
MemoryVector<byte> public_b = private_b.public_value();
- PK_Key_Agreement ka1(private_a, "KDF2(SHA-1)");
- PK_Key_Agreement ka2(private_b, "KDF2(SHA-1)");
-
- /*
- * Preferably, include some salt or parameter that binds this key
- * generation to the current session (for instance a session
- * identifier, if guaranteed unique, would be a good choice). Or
- * anything else that both sides can agree on that will never
- * repeat.
- */
- const std::string ka_salt = "alice and bob agree on a key";
+ // Now Alice performs the key agreement operation
+ PK_Key_Agreement ka_alice(private_a, "KDF2(SHA-256)");
+ SymmetricKey alice_key = ka_alice.derive_key(32, public_b, session_param);
- SymmetricKey alice_key = ka1.derive_key(32, public_b, ka_salt);
- SymmetricKey bob_key = ka2.derive_key(32, public_a, ka_salt);
+ // Bob does the same:
+ PK_Key_Agreement ka_bob(private_b, "KDF2(SHA-256)");
+ SymmetricKey bob_key = ka_bob.derive_key(32, public_a, session_param);
if(alice_key == bob_key)
{
diff --git a/doc/examples/dsa_kgen.cpp b/doc/examples/dsa_kgen.cpp
index fe3157370..fc5b7b501 100644
--- a/doc/examples/dsa_kgen.cpp
+++ b/doc/examples/dsa_kgen.cpp
@@ -1,13 +1,3 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*
-* 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.
-*/
-
#include <iostream>
#include <fstream>
#include <string>
@@ -20,24 +10,24 @@ using namespace Botan;
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
{
+ if(argc != 1 && argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [passphrase]" << std::endl;
+ return 1;
+ }
+
+ std::ofstream priv("dsapriv.pem");
+ std::ofstream pub("dsapub.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ Botan::LibraryInitializer init;
+
AutoSeeded_RNG rng;
DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256);
diff --git a/doc/examples/dsa_sign.cpp b/doc/examples/dsa_sign.cpp
index 5f02c0dc1..3511eacfa 100644
--- a/doc/examples/dsa_sign.cpp
+++ b/doc/examples/dsa_sign.cpp
@@ -1,10 +1,3 @@
-/*
-* DSA signature generation example
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
#include <iostream>
#include <iomanip>
#include <fstream>
@@ -14,6 +7,7 @@
#include <botan/botan.h>
#include <botan/pubkey.h>
#include <botan/dsa.h>
+#include <botan/base64.h>
using namespace Botan;
const std::string SUFFIX = ".sig";
@@ -66,12 +60,10 @@ int main(int argc, char* argv[])
DataSource_Stream in(message);
byte buf[4096] = { 0 };
- while(u32bit got = in.read(buf, sizeof(buf)))
+ while(size_t 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;
+ sigfile << base64_encode(signer.signature(rng)) << "\n";
}
catch(std::exception& e)
{
diff --git a/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp
index a666259c1..9cb85740e 100644
--- a/doc/examples/dsa_ver.cpp
+++ b/doc/examples/dsa_ver.cpp
@@ -1,18 +1,3 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
-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: take the IEEE 1363
-signature format, encoded into base64 with a trailing newline.
-*/
-
#include <iostream>
#include <iomanip>
#include <fstream>
@@ -45,28 +30,30 @@ int main(int argc, char* argv[])
return 1;
}
- Botan::LibraryInitializer init;
- std::ifstream message(argv[2], std::ios::binary);
- if(!message)
- {
- std::cout << "Couldn't read the message file." << std::endl;
- return 1;
- }
+ try {
+ Botan::LibraryInitializer init;
- std::ifstream sigfile(argv[3]);
- if(!sigfile)
- {
- std::cout << "Couldn't read the signature file." << std::endl;
- return 1;
- }
+ std::ifstream message(argv[2], std::ios::binary);
+ 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";
@@ -79,10 +66,10 @@ int main(int argc, char* argv[])
DataSource_Stream in(message);
byte buf[4096] = { 0 };
- while(u32bit got = in.read(buf, sizeof(buf)))
+ while(size_t got = in.read(buf, sizeof(buf)))
ver.update(buf, got);
- bool ok = ver.check_signature(sig);
+ const bool ok = ver.check_signature(sig);
if(ok)
std::cout << "Signature verified\n";
diff --git a/doc/examples/eax_tv.txt b/doc/examples/eax.vec
index 95cd7c1ab..95cd7c1ab 100644
--- a/doc/examples/eax_tv.txt
+++ b/doc/examples/eax.vec
diff --git a/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp
index 32311800d..b43861132 100644
--- a/doc/examples/eax_test.cpp
+++ b/doc/examples/eax_test.cpp
@@ -236,7 +236,7 @@ void run_tests(std::istream& in)
int main()
{
- std::ifstream in("eax_tv.txt");
+ std::ifstream in("eax.vec");
Botan::LibraryInitializer init;
diff --git a/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp
index df1e1b93a..1607107eb 100644
--- a/doc/examples/ecdsa.cpp
+++ b/doc/examples/ecdsa.cpp
@@ -21,7 +21,7 @@ int main()
{
AutoSeeded_RNG rng;
- EC_Domain_Params params("1.3.132.0.8");
+ EC_Domain_Params params("secp160r1");
ECDSA_PrivateKey ecdsa(rng, params);
diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp
index 9b18d4879..029a761e7 100644
--- a/doc/examples/fpe.cpp
+++ b/doc/examples/fpe.cpp
@@ -1,17 +1,6 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
-* Encrypt credit cards numbers with valid checksums into other credit
-* card numbers with valid checksums using format preserving encryption.
-*/
-
-#include <botan/fpe.h>
+#include <botan/botan.h>
+#include <botan/fpe_fe1.h>
#include <botan/sha160.h>
-#include <botan/init.h>
using namespace Botan;
@@ -81,7 +70,7 @@ u64bit encrypt_cc_number(u64bit cc_number,
u64bit cc_ranked = cc_rank(cc_number);
- BigInt c = fpe_encrypt(n, cc_ranked, key, sha1(acct_name));
+ BigInt c = FPE::fe1_encrypt(n, cc_ranked, key, sha1(acct_name));
if(c.bits() > 50)
throw std::runtime_error("FPE produced a number too large");
@@ -100,7 +89,7 @@ u64bit decrypt_cc_number(u64bit enc_cc,
u64bit cc_ranked = cc_rank(enc_cc);
- BigInt c = fpe_decrypt(n, cc_ranked, key, sha1(acct_name));
+ BigInt c = FPE::fe1_decrypt(n, cc_ranked, key, sha1(acct_name));
if(c.bits() > 50)
throw std::runtime_error("FPE produced a number too large");
@@ -130,7 +119,7 @@ int main(int argc, char* argv[])
std::cout << "Input was: " << cc_number << ' '
<< luhn_check(cc_number) << '\n';
- /**
+ /*
* In practice something like PBKDF2 with a salt and high iteration
* count would be a good idea.
*/
diff --git a/doc/examples/pkcs10.cpp b/doc/examples/pkcs10.cpp
index 3f5ec8e05..b5ad1d1dd 100644
--- a/doc/examples/pkcs10.cpp
+++ b/doc/examples/pkcs10.cpp
@@ -1,9 +1,3 @@
-/*
-* (C) 2003 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
#include <botan/init.h>
#include <botan/auto_rng.h>
#include <botan/x509self.h>
@@ -31,9 +25,6 @@ int main(int argc, char* argv[])
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]);
@@ -45,18 +36,8 @@ int main(int argc, char* argv[])
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 = "[email protected]";
-
- PKCS10_Request req = X509::create_cert_req(opts, priv_key, "SHA-1", rng);
+ PKCS10_Request req = X509::create_cert_req(opts, priv_key,
+ "SHA-256", rng);
std::ofstream req_file("req.pem");
req_file << req.PEM_encode();
diff --git a/doc/python/cipher.py b/doc/examples/python/cipher.py
index 1be2759ae..1be2759ae 100755
--- a/doc/python/cipher.py
+++ b/doc/examples/python/cipher.py
diff --git a/doc/python/cryptobox.py b/doc/examples/python/cryptobox.py
index f76ed6bc3..f76ed6bc3 100755
--- a/doc/python/cryptobox.py
+++ b/doc/examples/python/cryptobox.py
diff --git a/doc/python/nisttest.py b/doc/examples/python/nisttest.py
index 3ea8fda0f..1260b1226 100755
--- a/doc/python/nisttest.py
+++ b/doc/examples/python/nisttest.py
@@ -47,7 +47,7 @@ def main():
results[test] = result
return results
- results = load_results('results.txt')
+ results = load_results('results.vec')
for root, dirs, files in os.walk('../../checks/nist_tests/tests'):
if files:
diff --git a/doc/python/results.txt b/doc/examples/python/results.vec
index 7a3824001..7a3824001 100644
--- a/doc/python/results.txt
+++ b/doc/examples/python/results.vec
diff --git a/doc/python/rng_test.py b/doc/examples/python/rng_test.py
index 06c79b84e..06c79b84e 100755
--- a/doc/python/rng_test.py
+++ b/doc/examples/python/rng_test.py
diff --git a/doc/python/rsa.py b/doc/examples/python/rsa.py
index 8ca95ff8b..8ca95ff8b 100755
--- a/doc/python/rsa.py
+++ b/doc/examples/python/rsa.py
diff --git a/doc/examples/readme.txt b/doc/examples/readme.txt
deleted file mode 100644
index fb6a03ddf..000000000
--- a/doc/examples/readme.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-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, PBKDF 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/doc/examples/rsa_kgen.cpp b/doc/examples/rsa_kgen.cpp
index f4566263b..a1f0fe71d 100644
--- a/doc/examples/rsa_kgen.cpp
+++ b/doc/examples/rsa_kgen.cpp
@@ -1,15 +1,3 @@
-/*
-* (C) 2002 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
-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).
-*/
-
#include <iostream>
#include <fstream>
#include <string>
@@ -29,25 +17,25 @@ int main(int argc, char* argv[])
return 1;
}
- u32bit bits = std::atoi(argv[1]);
+ const size_t bits = std::atoi(argv[1]);
if(bits < 1024 || bits > 16384)
{
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
{
+ 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;
+ }
+
AutoSeeded_RNG rng;
RSA_PrivateKey key(rng, bits);
diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp
index 6710cfb51..64b778b71 100644
--- a/doc/examples/self_sig.cpp
+++ b/doc/examples/self_sig.cpp
@@ -1,17 +1,3 @@
-/*
-* (C) 2003 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
-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.
-*/
-
#include <botan/botan.h>
#include <botan/x509self.h>
#include <botan/rsa.h>
@@ -49,7 +35,7 @@ int main(int argc, char* argv[])
{
AutoSeeded_RNG rng;
- RSA_PrivateKey key(rng, 1024);
+ RSA_PrivateKey key(rng, 2048);
std::ofstream priv_key("private.pem");
priv_key << PKCS8::PEM_encode(key, rng, argv[1]);
diff --git a/doc/examples/socket.h b/doc/examples/socket.h
new file mode 100644
index 000000000..f7ce98fea
--- /dev/null
+++ b/doc/examples/socket.h
@@ -0,0 +1,257 @@
+/*
+* Unix Socket
+* (C) 2004-2010 Jack Lloyd
+*
+* Released under the terms of the Botan license
+*/
+
+#ifndef SOCKET_WRAPPER_H__
+#define SOCKET_WRAPPER_H__
+
+#include <stdexcept>
+
+#if defined(_MSC_VER)
+ #define SOCKET_IS_WINSOCK 1
+#endif
+
+#if !defined(SOCKET_IS_WINSOCK)
+ #define SOCKET_IS_WINSOCK 0
+#endif
+
+#if SOCKET_IS_WINSOCK
+ #include <winsock.h>
+
+ typedef SOCKET socket_t;
+ const socket_t invalid_socket = INVALID_SOCKET;
+ #define socket_error_code WSAGetLastError()
+ typedef int ssize_t;
+
+ class SocketInitializer
+ {
+ public:
+ SocketInitializer()
+ {
+ WSADATA wsadata;
+ WSAStartup(MAKEWORD(2, 2), &wsadata);
+ }
+
+ ~SocketInitializer()
+ {
+ WSACleanup();
+ }
+ };
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/time.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+ typedef int socket_t;
+ const socket_t invalid_socket = -1;
+ #define socket_error_code errno
+ #define closesocket close
+
+ class SocketInitializer {};
+#endif
+
+#if !defined(MSG_NOSIGNAL)
+ #define MSG_NOSIGNAL 0
+#endif
+
+#include <string.h>
+
+class Socket
+ {
+ public:
+ size_t read(unsigned char[], size_t);
+ void write(const unsigned char[], size_t);
+
+ std::string peer_id() const { return peer; }
+
+ void close()
+ {
+ if(sockfd != invalid_socket)
+ {
+ if(::closesocket(sockfd) != 0)
+ throw std::runtime_error("Socket::close failed");
+ sockfd = invalid_socket;
+ }
+ }
+
+ Socket(socket_t fd, const std::string& peer_id = "") :
+ peer(peer_id), sockfd(fd)
+ {
+ }
+
+ Socket(const std::string&, unsigned short);
+ ~Socket() { close(); }
+ private:
+ std::string peer;
+ socket_t sockfd;
+ };
+
+class Server_Socket
+ {
+ public:
+ /**
+ * Accept a new connection
+ */
+ Socket* accept()
+ {
+ socket_t retval = ::accept(sockfd, 0, 0);
+ if(retval == invalid_socket)
+ throw std::runtime_error("Server_Socket: accept failed");
+ return new Socket(retval);
+ }
+
+ void close()
+ {
+ if(sockfd != invalid_socket)
+ {
+ if(::closesocket(sockfd) != 0)
+ throw std::runtime_error("Server_Socket::close failed");
+ sockfd = invalid_socket;
+ }
+ }
+
+ Server_Socket(unsigned short);
+ ~Server_Socket() { close(); }
+ private:
+ socket_t sockfd;
+ };
+
+/**
+* Unix Socket Constructor
+*/
+Socket::Socket(const std::string& host, unsigned short port) : peer(host)
+ {
+ sockfd = invalid_socket;
+
+ hostent* host_addr = ::gethostbyname(host.c_str());
+
+ if(host_addr == 0)
+ throw std::runtime_error("Socket: gethostbyname failed for " + host);
+ if(host_addr->h_addrtype != AF_INET) // FIXME
+ throw std::runtime_error("Socket: " + host + " has IPv6 address");
+
+ socket_t fd = ::socket(PF_INET, SOCK_STREAM, 0);
+ if(fd == invalid_socket)
+ throw std::runtime_error("Socket: Unable to acquire socket");
+
+ sockaddr_in socket_info;
+ ::memset(&socket_info, 0, sizeof(socket_info));
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_port = htons(port);
+
+ ::memcpy(&socket_info.sin_addr,
+ host_addr->h_addr,
+ host_addr->h_length);
+
+ socket_info.sin_addr = *(struct in_addr*)host_addr->h_addr; // FIXME
+
+ if(::connect(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
+ {
+ ::closesocket(fd);
+ throw std::runtime_error("Socket: connect failed");
+ }
+
+ sockfd = fd;
+ }
+
+/**
+* Read from a Unix socket
+*/
+size_t Socket::read(unsigned char buf[], size_t length)
+ {
+ if(sockfd == invalid_socket)
+ throw std::runtime_error("Socket::read: Socket not connected");
+
+ size_t got = 0;
+
+ while(length)
+ {
+ ssize_t this_time = ::recv(sockfd, (char*)buf + got,
+ length, MSG_NOSIGNAL);
+
+ if(this_time == 0)
+ break;
+
+ if(this_time == -1)
+ {
+ if(socket_error_code == EINTR)
+ this_time = 0;
+ else
+ throw std::runtime_error("Socket::read: Socket read failed");
+ }
+
+ got += this_time;
+ length -= this_time;
+ }
+ return got;
+ }
+
+/**
+* Write to a Unix socket
+*/
+void Socket::write(const unsigned char buf[], size_t length)
+ {
+ if(sockfd == invalid_socket)
+ throw std::runtime_error("Socket::write: Socket not connected");
+
+ size_t offset = 0;
+ while(length)
+ {
+ ssize_t sent = ::send(sockfd, (const char*)buf + offset,
+ length, MSG_NOSIGNAL);
+
+ if(sent == -1)
+ {
+ if(socket_error_code == EINTR)
+ sent = 0;
+ else
+ throw std::runtime_error("Socket::write: Socket write failed");
+ }
+
+ offset += sent;
+ length -= sent;
+ }
+ }
+
+/**
+* Unix Server Socket Constructor
+*/
+Server_Socket::Server_Socket(unsigned short port)
+ {
+ sockfd = invalid_socket;
+
+ socket_t fd = ::socket(PF_INET, SOCK_STREAM, 0);
+ if(fd == invalid_socket)
+ throw std::runtime_error("Server_Socket: Unable to acquire socket");
+
+ sockaddr_in socket_info;
+ ::memset(&socket_info, 0, sizeof(socket_info));
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_port = htons(port);
+
+ // FIXME: support limiting listeners
+ socket_info.sin_addr.s_addr = INADDR_ANY;
+
+ if(::bind(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
+ {
+ ::closesocket(fd);
+ throw std::runtime_error("Server_Socket: bind failed");
+ }
+
+ if(::listen(fd, 100) != 0) // FIXME: totally arbitrary
+ {
+ ::closesocket(fd);
+ throw std::runtime_error("Server_Socket: listen failed");
+ }
+
+ sockfd = fd;
+ }
+
+#endif
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index 10ead20cc..cedfe1ca8 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -1,12 +1,6 @@
-/*
-* (C) 2008 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/init.h>
+#include <botan/botan.h>
#include <botan/tls_client.h>
-#include <botan/unx_sock.h>
+#include "socket.h"
using namespace Botan;
@@ -41,23 +35,24 @@ int main(int argc, char* argv[])
try
{
- LibraryInitializer init;
+ LibraryInitializer botan_init;
std::string host = argv[1];
u32bit port = argc == 3 ? Botan::to_u32bit(argv[2]) : 443;
printf("Connecting to %s:%d...\n", host.c_str(), port);
- Unix_Socket sock(argv[1], port);
+ SocketInitializer socket_init;
+
+ Socket sock(argv[1], port);
- std::auto_ptr<Botan::RandomNumberGenerator> rng(
- Botan::RandomNumberGenerator::make_rng());
+ AutoSeeded_RNG rng;
Client_TLS_Policy policy;
TLS_Client tls(std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2),
std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
- policy, *rng);
+ policy, rng);
printf("Handshake extablished...\n");
@@ -68,17 +63,18 @@ int main(int argc, char* argv[])
std::string http_command = "GET / HTTP/1.0\r\n\r\n";
#endif
- tls.write((const byte*)http_command.c_str(), http_command.length());
+ tls.write((const Botan::byte*)http_command.c_str(),
+ http_command.length());
- u32bit total_got = 0;
+ size_t total_got = 0;
while(true)
{
if(tls.is_closed())
break;
- byte buf[16+1] = { 0 };
- u32bit got = tls.read(buf, sizeof(buf)-1);
+ Botan::byte buf[128+1] = { 0 };
+ size_t got = tls.read(buf, sizeof(buf)-1);
printf("%s", buf);
fflush(0);
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index da13953f8..153b26d04 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -1,17 +1,12 @@
-/*
-* (C) 2008-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
#include <botan/botan.h>
#include <botan/tls_server.h>
-#include <botan/unx_sock.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
#include <botan/x509self.h>
+#include "socket.h"
+
using namespace Botan;
#include <stdio.h>
@@ -34,9 +29,9 @@ class Server_TLS_Policy : public TLS_Policy
return true;
}
};
+
int main(int argc, char* argv[])
{
-
int port = 4433;
if(argc == 2)
@@ -44,7 +39,8 @@ int main(int argc, char* argv[])
try
{
- LibraryInitializer init;
+ LibraryInitializer botan_init;
+ SocketInitializer socket_init;
AutoSeeded_RNG rng;
@@ -57,7 +53,7 @@ int main(int argc, char* argv[])
X509_Certificate cert =
X509::create_self_signed_cert(options, key, "SHA-1", rng);
- Unix_Server_Socket listener(port);
+ Server_Socket listener(port);
Server_TLS_Policy policy;
@@ -86,12 +82,12 @@ int main(int argc, char* argv[])
printf("Writing some text\n");
char msg[] = "Foo\nBar\nBaz\nQuux\n";
- tls.write((const byte*)msg, strlen(msg));
+ tls.write((const Botan::byte*)msg, strlen(msg));
printf("Now trying a read...\n");
char buf[1024] = { 0 };
- u32bit got = tls.read((byte*)buf, sizeof(buf)-1);
+ u32bit got = tls.read((Botan::byte*)buf, sizeof(buf)-1);
printf("%d: '%s'\n", got, buf);
tls.close();
diff --git a/doc/examples/x509info.cpp b/doc/examples/x509info.cpp
deleted file mode 100644
index b22b4ebd8..000000000
--- a/doc/examples/x509info.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-* Read an X.509 certificate, and print various things about it
-* (C) 2003 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/botan.h>
-#include <botan/x509cert.h>
-using namespace Botan;
-
-#include <iostream>
-
-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 << cert.to_string();
- }
- catch(std::exception& e)
- {
- std::cout << e.what() << std::endl;
- return 1;
- }
- return 0;
- }
diff --git a/doc/faq.txt b/doc/faq.txt
new file mode 100644
index 000000000..4ff5457bb
--- /dev/null
+++ b/doc/faq.txt
@@ -0,0 +1,209 @@
+
+Frequently Asked Questions
+========================================
+
+What is this thing?
+----------------------------------------
+
+Botan is a library written in C++ which provides a fairly high level
+and C++-ish interface to a number of different crypto algorithms. In
+addition to the bare algorithms there is also support for number of
+standards and de-facto standards like X.509v3 certificates, and
+various useful constructs like format-preserving encryption, all or
+nothing transforms, and secret splitting.
+
+.. _devel_vs_stable:
+
+Which release should I use?
+----------------------------------------
+
+The library is normally released along two different trees, termed
+stable and development. The stable tree is a branch off the main line,
+and typically only sees bug fixes; almost all new development occurs
+in the unstable/development releases. The primary issue is not
+stability of the program (bugs of course do occur, and are more likely
+to occur in code that is more in flux), but rather stability of API
+and ABI. In particular, you should not expect any level of ABI
+stability between releases on the development branch, and API changes
+may be made without notice. Feel free to send comments on API changes,
+or API problems, to the list.
+
+If you don't want to have to worry about tracking a moving target, and
+just want something that works, you'll probably prefer using the
+stable releases. If you want to get the latest features, the
+development releases are the obvious choice.
+
+If you want to ship a binary that is usable out of the box on a Linux
+distro that ships botan, you'll probably want to match versions with
+that distro; as of this writing most ship with 1.8.
+
+If you're building an application that will embed botan into it
+(without relying on a shared library), you want to use an amalgamation
+build, which basically turns botan into a single header and a single
+source file which you can easily include in your existing application
+build. In this case you can pick which ever tree you prefer.
+
+The self-test program can't locate the library
+-----------------------------------------------
+
+Are you sure either the current working directory ('.') or the
+directory botan is building into are in the dynamic library path? On
+many Unix systems this is controlled by the ``LD_LIBRARY_PATH``
+variable. You can add the currently directory to the list of
+directories to search with this Bourne shell command::
+
+ $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
+
+If you install the library into a well known location like
+``/usr/local/lib``, then probably no particular
+``LD_LIBRARY_PATH`` needs to be set.
+
+My program aborts with any message
+----------------------------------------
+
+Does your main function wrap all code inside a try/catch block? If an
+exception is thrown and is not caught, many C++ runtimes simply crash
+the process without providing any sort of diagnostic.
+
+Is the library thread-safe?
+----------------------------------------
+
+Yes, botan is thread safe. However, because mutual exclusion depends
+on OS specific code, you must load a module to help. POSIX threads and
+Win32 critical sections are both supported out of the box, other
+thread libraries are very easy to add. To enable thread safe
+operation, include "thread_safe" in the string you pass to
+``Botan::LibraryInitializer`` constructor. If for whatever reason a
+working mutex implementation cannot be found, LibraryInitializer will
+throw an exception rather than continue operating in a bad state.
+
+How do I load this key generated by OpenSSL into botan?
+--------------------------------------------------------
+
+The encrypted key format used by the ``openssl`` command line tool is
+undocumented and apparently specific to OpenSSL. The easiest approach
+is to convert it to the (standard) PKCS #8 format, using::
+
+ openssl pkcs8 -topk8 -in my_key.pem
+
+Add ``-nocrypt`` to the command line if you want the resulting PKCS #8
+file to be unencrypted, otherwise it will ask you for a new password
+to use.
+
+For unencrypted keys, you can also manually decode the parameters
+using the existing PEM and BER support; see `this post
+<http://lists.randombit.net/pipermail/botan-devel/2010-June/001156.html>`_
+to the dev list for an example.
+
+Is botan FIPS 140 certified?
+----------------------------------------
+
+No version of botan has been certified under FIPS 140. This is
+unlikely to happen unless/until an organization is willing to fund and
+shepherd the validation process, which typically requires several
+months and many thousands of dollars.
+
+Is this thing safe to use?
+----------------------------------------
+
+The primary author/maintainer (Jack Lloyd) has 5+ years of experience
+reviewing code for security flaws, and has additionally performed
+several FIPS 140 validations of hardware and software crypto
+implementations. However the library has never undergone an
+*impartial* third-party security review, and thus it is entirely
+possible/probable that a number of exploitable flaws remain in the
+source. (If your company is interested in handling such a review,
+please contact the maintainers).
+
+There has been one known security flaw. Between versions 0.7.8
+(released Feb 2002) and 1.3.7 (released Dec 2003), the ``es_unix``
+module, which runs Unix programs to gather entropy for seeding a
+random number generator, ran programs by invoking the ``popen``
+library function with commands with no leading directory names. This
+means setuid or setgid programs that used this entropy source could be
+tricked into executing arbitrary programs via manipulation of the PATH
+variable. Later versions will only search through specific (presumed
+safe) directories like ``/usr/bin``; the list of directories to search
+can be controlled by the application.
+
+Is botan vulnerable to timing attacks?
+----------------------------------------
+
+Botan's public key implementations do make some attempt to defend
+against timing attacks; random blinding is used to protect all RSA,
+Rabin-Williams, ElGamal, and Diffie-Hellman private key operations.
+
+Public key algorithms implemented using the Chinese Remainder Theorem
+(RSA and Rabin-Williams) are subject to a catastrophic failure: if a
+computational error (either induced by an attacker or merely
+accidental) occurs during the private key operation, the private key
+can be revealed. Other, more subtle, fault attacks are possible against
+other schemes. For this reason, private key operations are checked
+for consistency with the public key - if the results are not
+consistent, then an exception is thrown indicating an error has
+occurred rather than release information that might compromise the
+key.
+
+AES implementations are usually quite vulnerable to timing attacks.
+The table based implementation of AES included in botan uses small
+tables in the first and last rounds which makes such attacks somewhat
+more difficult. Alternate implementations of AES using SSSE3 and
+AES-NI instruction sets are also included, and run in constant time,
+but of course require a processor that supports these instruction
+sets.
+
+I think I've found a security flaw. What should I do?
+------------------------------------------------------------
+
+You can do any combination of:
+
+* Contact the current lead maintainer personally; currently
+ `Jack Lloyd <http://www.randombit.net>`_
+ (`personal PGP key` <http://www.randombit.net/pgpgkey.html`_)
+
+* Email the `development list
+ <http://lists.randombit.net/mailman/listinfo/botan-devel>`_
+
+* File a bug in `Bugzilla <http://bugs.randombit.net/>`_
+
+Does botan support SSL/TLS, SSH, S/MIME, OpenPGP...
+------------------------------------------------------------
+
+Support for SSL/TLS is included in version 1.9.4 and later. Currently
+SSLv3 and TLS 1.0 and 1.1 are supported.
+
+`NetSieben SSH <http://netsieben.com/products/ssh/>`_ is an open
+source SSHv2 implementation that uses botan.
+
+A preliminary and very incomplete implementation of CMS (the crypto
+layer underlying S/MIME) is included in ``src/cms``, but it needs a
+lot of love and attention before being truly useful.
+
+There is currently no support for OpenPGP.
+
+Will it work on my platform XYZ??
+----------------------------------------
+
+The most common stumbling block is a compiler that is buggy or can't
+handle modern C++ (specifically, C++98). Check out the `build list
+<http://botan.randombit.net/builds.html>`_ for a sense of which
+platforms are actively being tested.
+
+I'm not feeling this, what can I use instead?
+------------------------------------------------------------
+
+* `Crypto++ <http://www.cryptopp.com/>`_ is another C++ crypto
+ library. Its API is more heavily based on templates and in general
+ has a very different design philosophy from botan - so if you feel
+ botan's API is not a good match, you may well like Crypto++.
+
+* `OpenSSL <http://www.openssl.org>`_ is written in C and mostly
+ targeted to being an SSL/TLS implementation but there is a lot of
+ other stuff in there as well.
+
+* `XySSL <http://www.ohloh.net/projects/xyssl>`_ is a C library
+ providing a very small footprint crypto library and SSL
+ implementation.
+
+* `Adam Shostack <http://www.homeport.org/~adam/crypto/>`_ maintains a
+ (somewhat out of date) list of open source crypto libraries.
diff --git a/doc/filters.txt b/doc/filters.txt
new file mode 100644
index 000000000..2355005aa
--- /dev/null
+++ b/doc/filters.txt
@@ -0,0 +1,780 @@
+
+Information Flow: Pipes and Filters
+========================================
+
+Many common uses of cryptography involve processing one or more
+streams of data. 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 *filters* in Botan. A set of filters are created and 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.
+
+Here is an example that uses a pipe to base64 encode some strings::
+
+ 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"
+
+Bytestreams in the pipe are grouped into messages; blocks of data that
+are processed in an identical fashion (ie, with the same sequence of
+filter operations). Messages are delimited by calls to ``start_msg``
+and ``end_msg``. Each message in a pipe has its own identifier, which
+currently is an integer that increments up from zero.
+
+The ``Base64_Encoder`` was allocated using ``new``; but where was it
+deallocated? When a filter object is passed to a ``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 ``Pipe`` without changing the ``Pipe``
+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 *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
+``Pipe`` between each message, by adding or removing filters;
+functions that let you do this are documented in the Pipe API section.
+
+Botan has about 40 filters that perform different operations on data.
+Here's code that uses one of them to encrypt a string with AES::
+
+ AutoSeeded_RNG rng,
+ SymmetricKey key(rng, 16); // a random 128-bit key
+ InitializationVector iv(rng, 16); // a random 128-bit IV
+
+ // 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 };
+ size_t got_out = pipe.read(c2, sizeof(c2), 1);
+ // use c2[0...got_out]
+
+Note the use of ``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
+``AutoSeeded_RNG`` is preferable.
+
+``Pipe`` also has convenience methods for dealing with
+``std::iostream``. Here is an example of those, using the
+``Bzip_Compression`` filter (included as a module; if you have bzlib
+available, check the build instructions for how to enable it) to
+compress a file::
+
+ 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;
+
+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 ``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::
+
+ 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();
+
+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
+``DataSink_Stream``. Anything written to a ``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 to the sink filter, which will immediately write it to the
+stream; if you were to call ``pipe.read_all()`` after
+``pipe.end_msg()``, you'd get an empty vector out. This is
+particularly useful for cases where you are processing a large amount
+of data, as it means you don't have to store everything in memory at
+once.
+
+Here's an example using two computational filters::
+
+ 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;
+
+You can read from a pipe while you are still writing to it, which
+allows you to bound the amount of memory that is in use at any one
+time. A common idiom for this is::
+
+ pipe.start_msg();
+ SecureBuffer<byte, 4096> buffer;
+ while(infile.good())
+ {
+ infile.read((char*)&buffer[0], buffer.size());
+ const size_t got_from_infile = infile.gcount();
+ pipe.write(buffer, got_from_infile);
+
+ if(infile.eof())
+ pipe.end_msg();
+
+ while(pipe.remaining() > 0)
+ {
+ const size_t buffered = pipe.read(buffer, buffer.size());
+ outfile.write((const char*)&buffer[0], buffered);
+ }
+ }
+ if(infile.bad() || (infile.fail() && !infile.eof()))
+ throw Some_Exception();
+
+Fork
+---------------------------------
+
+It is 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
+``Fork`` comes in. ``Fork`` is a filter that takes input and passes it
+on to *one or more* filters that are attached to it. ``Fork`` changes
+the nature of the pipe system completely: instead of being a linked
+list, it becomes a tree or acyclic graph.
+
+Each 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 pipe, then you start a new one with a fork that has three
+paths of filter's inside it, you add three new messages to the
+pipe. The data you put into the pipe is duplicated and sent
+into each set of filter and the eventual output is placed into a
+dedicated message slot in the pipe.
+
+Messages in the pipe are allocated in a depth-first manner. This is only
+interesting if you are using more than one fork in a single pipe.
+As an example, consider the following::
+
+ Pipe pipe(new Fork(
+ new Fork(
+ new Base64_Encoder,
+ new Fork(
+ NULL,
+ new Base64_Encoder
+ )
+ ),
+ new Hex_Encoder
+ )
+ );
+
+In this case, message 0 will be the output of the first
+``Base64_Encoder``, message 1 will be a copy of the input (see below
+for how fork interprets NULL pointers), message 2 will be the output
+of the second ``Base64_Encoder``, and message 3 will be the output of
+the ``Hex_Encoder``. 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 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::
+
+ // 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, // this message gets ciphertext
+ 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();
+
+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 filters that are attached to the pipe after the fork are
+implicitly attached onto the first branch created by the fork. For
+example, let's say you created this pipe::
+
+ Pipe pipe(new Fork(new Hash_Filter("SHA-256"),
+ new Hash_Filter("SHA-512")),
+ new Hex_Encoder);
+
+And then called ``start_msg``, inserted some data, then
+``end_msg``. Then ``pipe`` would contain two messages. The first one
+(message number 0) would contain the SHA-256 sum of the input in hex
+encoded form, and the other would contain the SHA-512 sum of the input
+in raw binary. In many situations you'll want to perform a sequence of
+operations on multiple branches of the fork; in which case, use
+the filter described in :ref:`chain`.
+
+.. _chain:
+
+Chain
+---------------------------------
+
+A ``Chain`` filter creates a chain of filters 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 ``Fork`` constructor.
+
+You can call ``Chain``'s constructor with up to four ``Filter``
+pointers (they will be added in order), or with an array of filter
+pointers and a ``size_t`` that tells ``Chain`` how many filters 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 implicit
+passthrough the other version used::
+
+ Pipe pipe(new Fork(
+ new Chain(new Hash_Filter("SHA-256"), new Hex_Encoder),
+ new Hash_Filter("SHA-512")
+ )
+ );
+
+Sources and Sinks
+----------------------------------------
+
+Data Sources
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A ``DataSource`` is a simple abstraction for a thing that stores
+bytes. This type is used heavily in the areas of the API related to
+ASN.1 encoding/decoding. The following types are ``DataSource``:
+``Pipe``, ``SecureQueue``, and a couple of special purpose ones:
+``DataSource_Memory`` and ``DataSource_Stream``.
+
+You can create a ``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 ``DataSource_Stream`` is probably more useful than the memory based
+one. Its constructors take either a ``std::istream`` or a
+``std::string``. If it's a stream, the data source will use the
+``istream`` to satisfy read requests (this is particularly useful to
+use with ``std::cin``). If the string version is used, it will attempt
+to open up a file with that name and read from it.
+
+Data Sinks
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A ``DataSink`` (in ``data_snk.h``) is a ``Filter`` that takes
+arbitrary amounts of input, and produces no output. This means it's
+doing something with the data outside the realm of what
+``Filter``/``Pipe`` can handle, for example, writing it to a file
+(which is what the ``DataSink_Stream`` does). There is no need for
+``DataSink``s that write to a ``std::string`` or memory buffer,
+because ``Pipe`` can handle that by itself.
+
+Here's a quick example of using a ``DataSink``, which encrypts
+``in.txt`` and sends the output to ``out.txt``. There is
+no explicit output operation; the writing of ``out.txt`` is
+implicit::
+
+ DataSource_Stream in("in.txt");
+ Pipe pipe(get_cipher("AES-128/CTR-BE", key, iv),
+ new DataSink_Stream("out.txt"));
+ pipe.process_msg(in);
+
+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 be used.
+
+The Pipe API
+---------------------------------
+
+Initializing Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, ``Pipe`` will do nothing at all; any input placed into the
+``Pipe`` will be read back unchanged. Obviously, this has limited
+utility, and presumably you want to use one or more filters to somehow
+process the data. First, you can choose a set of filters to initialize
+the ``Pipe`` via the constructor. You can pass it either a set of up
+to four filter pointers, or a pre-defined array and a length::
+
+ 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);
+
+This is by far the most common way to initialize a ``Pipe``. However,
+occasionally a more flexible initialization strategy is necessary;
+this is supported by 4 member functions. These functions may only be
+used while the pipe in question is not in use; that is, either before
+calling ``start_msg``, or after ``end_msg`` has been called (and no
+new calls to ``start_msg`` have been made yet).
+
+.. cpp:function:: void Pipe::prepend(Filter* filter)
+
+ Calling ``prepend`` will put the passed filter first in the list of
+ transformations. For example, if you prepend a filter implementing
+ encryption, and the pipe already had a filter that hex encoded the
+ input, then the next message processed would be first encrypted,
+ and *then* hex encoded.
+
+.. cpp:function:: void Pipe::append(Filter* filter)
+
+ Like ``prepend``, but places the filter at the end of the message
+ flow. This doesn't always do what you expect if there is a fork.
+
+.. cpp:function:: void Pipe::pop()
+
+ Removes the first filter in the flow.
+
+.. cpp:function:: void Pipe::reset()
+
+ Removes all the filters that the pipe currently holds - it is reset
+ to an empty/no-op state. Any data that is being retained by the
+ pipe is retained after a ``reset``, and ``reset`` does not affect
+ message numbers (discussed later).
+
+Giving Data to a Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Input to a ``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).
+
+.. cpp:function:: void Pipe::start_msg()
+
+ Starts a new message; if a message was already running, an exception is
+ thrown. After this function returns, you can call ``write``.
+
+.. cpp:function:: void Pipe::write(const byte* input, size_t length)
+
+.. cpp:function:: void Pipe::write(const MemoryRegion<byte>& input)
+
+.. cpp:function:: void Pipe::write(const std::string& input)
+
+.. cpp:function:: void Pipe::write(DataSource& input)
+
+.. cpp:function:: void Pipe::write(byte input)
+
+ All versions of ``write`` write the input into the filter sequence.
+ If a message is not currently active, an exception is thrown.
+
+.. cpp:function:: void Pipe::end_msg()
+
+ End the currently active message
+
+Sometimes, you may want to do only a single write per message. In this
+case, you can use the ``process_msg`` series of functions, which start
+a message, write their argument into the pipe, and then end the
+message. In this case you would not make any explicit calls to
+``start_msg``/``end_msg``.
+
+Pipes can also be used with the ``>>`` operator, and will accept a
+``std::istream``, or on Unix systems with the ``fd_unix`` module, a
+Unix file descriptor. In either case, the entire contents of the file
+will be read into the pipe.
+
+Getting Output from a Pipe
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Retrieving the processed data from a pipe is a bit more complicated,
+for various reasons. The pipe will separate each message into a
+separate buffer, and you have to retrieve data from each message
+independently. Each of the reader functions has a final parameter that
+specifies what message to read from. If this parameter is set to
+``Pipe::DEFAULT_MESSAGE``, it will read the current default message
+(``DEFAULT_MESSAGE`` is also the default value of this parameter).
+
+Functions in ``Pipe`` related to reading include:
+
+.. cpp:function:: size_t Pipe::read(byte* out, size_t len)
+
+ Reads up to ``len`` bytes into ``out``, and returns the number of
+ bytes actually read.
+
+.. cpp:function:: size_t Pipe::peek(byte* out, size_t len)
+
+ Acts exactly like `read`, except the data is not actually read; the
+ next read will return the same data.
+
+.. cpp:function:: SecureVector<byte> Pipe::read_all()
+
+ Reads the entire message into a buffer and returns it
+
+.. cpp:function:: std::string Pipe::read_all_as_string()
+
+ Like ``read_all``, but it returns the data as a ``std::string``.
+ No encoding is done; if the message contains raw binary, so will
+ the string.
+
+.. cpp:function:: size_t Pipe::remaining()
+
+ Returns how many bytes are left in the message
+
+.. cpp:function:: Pipe::message_id Pipe::default_msg()
+
+ Returns the current default message number
+
+.. cpp:function:: Pipe::message_id Pipe::message_count()
+
+ Returns the total number of messages currently in the pipe
+
+.. cpp:function:: Pipe::set_default_msg(Pipe::message_id msgno)
+
+ Sets the default message number (which must be a valid message
+ number for that pipe). The ability to set the default message number
+ is particularly important in the case of using the file output
+ operations (``<<`` with a ``std::ostream`` or Unix file descriptor),
+ because there is no way to specify the message explicitly when using
+ the output operator.
+
+Pipe I/O for Unix File Descriptors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is a minor feature, but it comes in handy sometimes. In all
+installations of the library, Botan's ``Pipe`` object overloads the
+``<<`` and ``>>`` 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 ``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 ``hash_fd`` example, included in the Botan distribution.
+
+Filter Catalog
+---------------------------------
+
+This section documents most of the useful filters included in the
+library.
+
+Keyed Filters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A few sections ago, it was mentioned that ``Pipe`` can process
+multiple messages, treating each of them 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 ``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, ``set_key`` and ``set_iv``. Calling
+``set_key`` will set (or reset) the key used by the algorithm. Setting
+the IV only makes sense in certain algorithms -- a call to ``set_iv``
+on an object that doesn't support IVs will cause an exception. You
+must call ``set_key`` *before* calling ``set_iv``.
+
+Here's a example::
+
+ Keyed_Filter *aes, *hmac;
+ Pipe pipe(new Base64_Decoder,
+ // Note the assignments to the cast and hmac variables
+ aes = get_cipher("AES-128/CBC", aes_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();
+
+ aes->set_key(aes_key2);
+ aes->set_iv(iv2);
+ hmac->set_key(mac_key2);
+
+ pipe.start_msg();
+ // use pipe for some other things
+ pipe.end_msg();
+
+There are some requirements to using ``Keyed_Filter`` that you must
+follow. If you call ``set_key`` or ``set_iv`` on a filter that is
+owned by a ``Pipe``, you must do so while the ``Pipe`` is
+"unlocked". This refers to the times when no messages are being
+processed by ``Pipe`` -- either before ``Pipe``'s ``start_msg`` is
+called, or after ``end_msg`` is called (and no new call to
+``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 *first*.
+
+Cipher Filters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Getting a hold of a ``Filter`` implementing a cipher is very
+easy. Make sure you're including the header ``lookup.h``, and
+then call ``get_cipher``. You will pass the return value
+directly into a ``Pipe``. There are a couple different functions
+which do varying levels of initialization:
+
+.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
+ SymmetricKey key, InitializationVector iv, Cipher_Dir dir)
+
+.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
+ SymmetricKey key, Cipher_Dir 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 cipher spec that does want a IV, and you use the version
+that doesn't take one, an exception will be thrown. The ``dir``
+argument can be either ``ENCRYPTION`` or ``DECRYPTION``.
+
+The cipher_spec is a string that specifies what cipher is to be
+used. The general syntax for "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 "cipher_spec arguments are: "AES-128/CBC",
+"Blowfish/CTR-BE", "Serpent/XTS", and "AES-256/EAX".
+
+"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.
+
+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
+``end_msg`` is called, at which time they complete the hash or MAC and
+send that as output.
+
+These filters 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.
+
+.. cpp:function:: Hash_Filter::Hash_Filter(std::string hash, size_t outlen = 0)
+
+ This constructor creates a filter that hashes its input with
+ ``hash``. When ``end_msg`` is called on the owning pipe, the hash is
+ completed and the digest is sent on to the next filter in the
+ pipeline. The parameter ``outlen`` specifies how many bytes of the
+ hash output will be passed along to the next filter when ``end_msg``
+ is called. By default, it will pass the entire hash.
+
+ Examples of names for ``Hash_Filter`` are "SHA-1" and "Whirlpool".
+
+.. cpp:function:: MAC_Filter::MAC_Filter(std::string mac, SymmetricKey key, size_t outlen = 0)
+
+ This constructor takes a name for a mac, such as "HMAC(SHA-1)" or
+ "CMAC(AES-128)", along with a key to use. The optional ``outlen``
+ works the same as in ``Hash_Filter``.
+
+PK Filters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are four classes in this category, ``PK_Encryptor_Filter``,
+``PK_Decryptor_Filter``, ``PK_Signer_Filter``, and
+``PK_Verifier_Filter``. Each takes a pointer to an object of the
+appropriate type (``PK_Encryptor``, ``PK_Decryptor``, etc) that is
+deleted by the destructor. These classes are found in ``pk_filts.h``.
+
+Three of these, for encryption, decryption, and signing are much the
+same in terms of dataflow - ach of them buffers its input until the
+end of the message is marked with a call to the ``end_msg``
+function. Then they encrypt, decrypt, or sign the entire input as a
+single blob 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
+``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 ``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), see :doc:`pubkey`.
+
+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
+``Hex_Encoder`` and ``Base64_Encoder`` will convert arbitrary binary
+data into hex or base64 formats. Not surprisingly, you can use
+``Hex_Decoder`` and ``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 ``bool``
+which 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. If you want a specific value, set it. Otherwise the
+default should be fine.
+
+Lastly, ``Hex_Encoder`` takes an argument of type ``Case``, which can
+be ``Uppercase`` or ``Lowercase`` (default is ``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.
+
+You can find the declarations for these types in ``hex_filt.h`` and
+``b64_filt.h``.
+
+Compressors
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are two compression algorithms supported by Botan, zlib and
+bzip2. 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 *before* you encrypt, because encryption seeks
+to hide the redundancy that compression is supposed to try to find and remove.
+
+To test for Bzip2, check to see if ``BOTAN_HAS_COMPRESSOR_BZIP2`` is
+defined. If so, you can include ``botan/bzip2.h``, which will declare
+a pair of ``Filter`` objects: ``Bzip2_Compression`` and
+``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 ``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.
+
+Zlib compression works much like Bzip2 compression. The only
+differences in this case are that the macro is
+``BOTAN_HAS_COMPRESSOR_ZLIB``, the header you need to include is
+called ``botan/zlib.h`` (remember that you shouldn't just ``#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
+``Zlib_Compression`` and ``Zlib_Decompression``.
+
+Like Bzip2, a ``Zlib_Decompression`` object will throw an exception if
+invalid (in the sense of not being in the Zlib format) data is passed
+into it.
+
+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.
+
+Writing New Filters
+---------------------------------
+
+The system of filters and pipes was designed in an attempt to make it
+as simple as possible to write new filter types. There are four
+functions that need to be implemented by a class deriving from
+``Filter``:
+
+.. cpp:function:: void Filter::write(const byte* input, size_t length)
+
+ This function is what is called when a filter receives input for it
+ to process. The filter is not required to process the data right
+ away; many filters buffer their input before producing any output. A
+ filter will usually have ``write`` called many times during its
+ lifetime.
+
+.. cpp:function:: void Filter::send(byte* output, size_t 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 ``send``
+ with whatever it wants to send along to the next filter. There is
+ also a version of ``send`` taking a single byte argument, as a
+ convenience.
+
+.. cpp:function:: void Filter::start_msg()
+
+ Implementing this function is optional. Implement it if your filter
+ would like to do some processing or setup at the start of each
+ message, such as allocating a data structure.
+
+.. cpp:function:: void Filter::end_msg()
+
+ Implementing this function is optional. It is called when it has
+ been requested that filters finish up their computations. The filter
+ should finish up with whatever computation it is working on (for
+ example, a compressing filter would flush the compressor and
+ ``send`` the final block), and empty any buffers in preparation for
+ processing a fresh new set of input.
+
+Additionally, if necessary, filters can define a constructor that
+takes any needed arguments, and a destructor to deal with deallocating
+memory, closing files, etc.
+
diff --git a/doc/fips140.tex b/doc/fips140.tex
deleted file mode 100644
index 8b2004508..000000000
--- a/doc/fips140.tex
+++ /dev/null
@@ -1,156 +0,0 @@
-\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{[email protected]}}
-\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/doc/firststep.txt b/doc/firststep.txt
new file mode 100644
index 000000000..fb4eb583e
--- /dev/null
+++ b/doc/firststep.txt
@@ -0,0 +1,107 @@
+
+Getting Started
+========================================
+
+All declarations in the library are contained within the namespace
+``Botan``, so you need to either prefix types with ``Botan::`` or add
+a ``using`` declaration in your code. All examples will assume a
+``using`` declaration.
+
+All library headers are included like so::
+
+ #include <botan/botan.h>
+
+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
+an object of type
+
+.. cpp:class:: LibraryInitializer
+
+prior to making any other library calls. Typically this will be named
+something like ``init`` or ``botan_init``. The object lifetime must
+exceed that of all other Botan objects your application creates; for
+this reason the best place to create the ``LibraryInitializer`` is at
+the start of your ``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 (unless you are writing threaded code; see
+below), all you need is::
+
+ Botan::LibraryInitializer init;
+
+at the start of your ``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 if you wish to share a single
+object between threads.
+
+If you do not create a ``LibraryInitializer`` object, all library
+operations will fail, because it will be unable to do basic things
+like allocate memory or get random bits. You should never create more
+than one ``LibraryInitializer``.
+
+Pitfalls
+----------------------------------------
+
+There are a few things to watch out for to prevent problems when using
+the library.
+
+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 ``LibraryInitializer``. Merely making the
+``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 ``LibraryInitializer`` is
+destroyed. This implies you can't have static variables that are Botan
+objects inside functions or classes; in many C++ runtimes, these
+objects will be destroyed after main has returned.
+
+The memory object classes (``MemoryRegion``, ``MemoryVector``,
+``SecureVector``) are extremely primitive, and meant only for
+secure storage of potentially sensitive data like keys. They do not
+meet the requirements for an STL container object and you should not
+try to use them with STL algorithms. For a general-purpose container,
+use ``std::vector``.
+
+Use a ``try``/``catch`` block inside your ``main`` function, and catch
+any ``std::exception`` throws (remember to catch by reference, as
+``std::exception::what`` is polymorphic)::
+
+ int main()
+ {
+ try
+ {
+ LibraryInitializer init;
+
+ // ...
+ }
+ catch(std::exception& e)
+ {
+ std::cerr << e.what() << "\n";
+ }
+ }
+
+This is not strictly required, but if you don't, and Botan throws an
+exception, the runtime will call ``std::terminate``, which usually
+calls ``abort`` or something like it, leaving you (or worse, a user of
+your application) wondering what went wrong.
diff --git a/doc/fpe.txt b/doc/fpe.txt
new file mode 100644
index 000000000..5c035f0b7
--- /dev/null
+++ b/doc/fpe.txt
@@ -0,0 +1,58 @@
+
+Format Preserving Encryption
+========================================
+
+.. versionadded:: 1.9.17
+
+Format preserving encryption (FPE) refers to a set of techniques for
+encrypting data such that the ciphertext has the same format as the
+plaintext. For instance, you can use FPE to encrypt credit card
+numbers with valid checksums such that the ciphertext is also an
+credit card number with a valid checksum, or similiarly for bank
+account numbers, US Social Security numbers, or even more general
+mappings like English words onto other English words.
+
+The scheme currently implemented in botan is called FE1, and described
+in the paper `Format Preserving Encryption
+<http://eprint.iacr.org/2009/251>`_ by Mihir Bellare, Thomas
+Ristenpart, Phillip Rogaway, and Till Stegers. FPE is an area of
+ongoing standardization and it is likely that other schemes will be
+included in the future.
+
+To use FE1, use these functions, from ``fpe_fe1.h``:
+
+.. cpp:function:: BigInt FPE::fe1_encrypt(const BigInt& n, const BigInt& X, \
+ const SymmetricKey& key, const MemoryRegion<byte>& tweak)
+
+ Encrypts the value *X* modulo the value *n* using the *key* and
+ *tweak* specified. Returns an integer less than *n*. The *tweak* is
+ a value that does not need to be secret that parameterizes the
+ encryption function. For instance, if you were encrypting a
+ database column with a single key, you could use a per-row-unique
+ integer index value as the tweak.
+
+ To encrypt an arbitrary value using FE1, you need to use a ranking
+ method. Basically, the idea is to assign an integer to every value
+ you might encrypt. For instance, a 16 digit credit card number
+ consists of a 15 digit code plus a 1 digit checksum. So to encrypt
+ a credit card number, you first remove the checksum, encrypt the 15
+ digit value modulo 10\ :sup:`15`, and then calculate what the
+ checksum is for the new (ciphertext) number.
+
+.. cpp:function:: BigInt FPE::fe1_decrypt(const BigInt& n, const BigInt& X, \
+ const SymmetricKey& key, const MemoryRegion<byte>& tweak)
+
+ Decrypts an FE1 ciphertext produced by :cpp:func:`fe1_encrypt`; the
+ *n*, *key* and *tweak* should be the same as that provided to the
+ encryption function. Returns the plaintext.
+
+ Note that there is not any implicit authentication or checking of
+ data, so if you provide an incorrect key or tweak the result is
+ simply a random integer.
+
+This example encrypts a credit card number with a valid
+`Luhn checksum <http://en.wikipedia.org/wiki/Luhn_algorithm>`_ to
+another number with the same format, including a correct checksum.
+
+.. literalinclude:: examples/fpe.cpp
+
diff --git a/doc/indent.el b/doc/indent.el
index 9811bf848..7fa2540b0 100644
--- a/doc/indent.el
+++ b/doc/indent.el
@@ -2,19 +2,14 @@
; 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:
+; M-x c-set-style <RET> and then enter "botan".
-; (add-hook 'c++-mode-common-hook
-; (function (lambda()
-; (c-add-style "botan" botan t))))
-
-(setq botan '(
+(setq botan-style '(
(c-basic-offset . 3)
(c-comment-only-line-offset . 0)
(c-offsets-alist
@@ -55,3 +50,6 @@
(label . 0)
)
))
+
+(add-hook 'c++-mode-common-hook
+ (function (lambda () (c-add-style "botan" botan-style nil))))
diff --git a/doc/index.txt b/doc/index.txt
new file mode 100644
index 000000000..430a71f20
--- /dev/null
+++ b/doc/index.txt
@@ -0,0 +1,90 @@
+
+Welcome
+========================================
+
+Botan is a :doc:`BSD-licensed <license>` crypto library for C++. It
+provides applications with most any :doc:`cryptographic algorithm
+<algos>` you might be looking for, along with :doc:`SSL/TLS <ssl>`,
+:doc:`X.509 certificates and CRLs <x509>`, a :doc:`pipeline-style
+message processing system <filters>`, and a wide variety of other
+features. A third party open source implementation of `SSHv2
+<http://www.netsieben.com/products/ssh/>`_ that uses botan is also
+available. In addition to C++ you can use botan from Python or Perl,
+though the current bindings only wrap portions of the library.
+
+See the :doc:`faq` for a list of common questions and answers.
+
+.. only:: html and website
+
+ See :doc:`download` for information about getting the latest version.
+
+The core of botan is written in C++98 with no dependencies besides the
+STL and the rest of the ISO standard library, but the library also
+includes optional modules which make further assumptions about their
+environment, providing features such as compression (using zlib or
+bzip2), entropy gathering, and secure memory allocation. Assembly
+implementations of key algorithms like SHA-1 and multiple precision
+integer routines for x86 and x86-64 processors are also included.
+
+It runs on most common operating systems and can be used with a number
+of different commercial and open source compilers. The :doc:`build log
+<build_log>` contains information about recently tested targets. It is
+already included in most major package distributions, including
+\
+`Fedora <https://admin.fedoraproject.org/pkgdb/acls/name/botan>`_,
+`EPEL <http://download.fedora.redhat.com/pub/epel/beta/6/SRPMS/repoview/botan.html>`_ (for RHEL/CentOS),
+`Debian <http://packages.debian.org/search?keywords=libbotan>`_,
+`Ubuntu <http://packages.ubuntu.com/search?keywords=botan>`_,
+`Gentoo <http://packages.gentoo.org/package/botan>`_,
+`Arch Linux <http://www.archlinux.org/packages/extra/x86_64/botan/>`_,
+`Slackbuild <http://slackbuilds.org/result/?search=Botan>`_,
+`FreeBSD <http://www.freshports.org/security/botan>`_,
+`NetBSD <ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/security/botan/README.html>`_,
+`Cygwin <http://cygwin.com/packages/botan/>`_,
+`MacPorts <http://www.macports.org/ports.php?by=name&amp;substr=botan>`_,
+`OpenPKG <http://www.openpkg.org/product/packages/?package=botan>`_, and
+`T2 SDE <http://www.t2-project.org/packages/botan.html>`_ and has
+more than a few :doc:`known users <users>`.
+
+It was started as a personal project by `Jack Lloyd
+<http:://www.randombit.net>`_,who continues to be the maintainer and
+release manager. Since the first release in 2001, a number of
+:doc:`individuals and organizations <credits>` have contributed bug
+fixes and new features. Check out the :doc:`release notes <log>` and
+`news archive <http://botan.randombit.net/news>`_ for more project
+history.
+
+If you need help or have questions, send a mail to the `development
+mailing list
+<http://lists.randombit.net/mailman/listinfo/botan-devel/>`_.
+"Philosophical" bug reports, announcements of programs using the
+library, and related topics are also welcome. :doc:`Commercial support
+options <support>` are also available. If you find what you believe to
+be a bug, please file a ticket in `Bugzilla
+<http://bugs.randombit.net/>`_.
+
+A useful reference while reading this manual is the `Doxygen
+documentation <http://botan.randombit.net/doxygen>`_.
+
+Recommended Reading
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It's a very good idea if you have some knowledge of cryptography
+*before* trying to use the library. This is an area where it is very
+easy to make mistakes, and where things are often subtle and/or
+counterintuitive. Obviously the library tries to provide things at a
+high level precisely to minimize the number of ways things can go
+wrong, but naive use will almost certainly not result in a secure
+system.
+
+Especially recommended are:
+
+- *Cryptography Engineering*
+ Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno
+
+- *Security Engineering -- A Guide to Building Dependable Distributed Systems*
+ Ross Anderson
+
+- *Handbook of Applied Cryptography*
+ Alfred J. Menezes, Paul C. Van Oorschot, and Scott A. Vanstone
+ (`available online <http://www.cacr.math.uwaterloo.ca/hac/>`_)
diff --git a/doc/insito_manual.pdf b/doc/insito_manual.pdf
deleted file mode 100644
index b07146992..000000000
--- a/doc/insito_manual.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/internals.tex b/doc/internals.tex
deleted file mode 100644
index 5b1650f6e..000000000
--- a/doc/internals.tex
+++ /dev/null
@@ -1,179 +0,0 @@
-\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 ([email protected])}
-\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/doc/kdf.txt b/doc/kdf.txt
new file mode 100644
index 000000000..da916dcb3
--- /dev/null
+++ b/doc/kdf.txt
@@ -0,0 +1,37 @@
+
+.. _key_derivation_function:
+
+Key Derivation Functions
+========================================
+
+Key derivation functions are used to turn some amount of shared secret
+material into uniform random keys suitable for use with symmetric
+algorithms. An example of an input which is useful for a KDF is a
+shared secret created using Diffie-Hellman key agreement.
+
+.. cpp:class:: KDF
+
+ .. cpp:function:: SecureVector<byte> derive_key( \
+ size_t key_len, const MemoryRegion<byte>& secret, \
+ const std::string& salt = "") const
+
+ .. cpp:function:: SecureVector<byte> derive_key( \
+ size_t key_len, const MemoryRegion<byte>& secret, \
+ const MemoryRegion<byte>& salt) const
+
+ .. cpp:function:: SecureVector<byte> derive_key( \
+ size_t key_len, const MemoryRegion<byte>& secret, \
+ const byte* salt, size_t salt_len) const
+
+ .. cpp:function:: SecureVector<byte> derive_key( \
+ size_t key_len, const byte* secret, size_t secret_len, \
+ const std::string& salt) const
+
+ All variations on the same theme. Deterministically creates a
+ uniform random value from *secret* and *salt*. Typically *salt* is
+ a lable or identifier, such as a session id.
+
+You can create a :cpp:class:`KDF` using
+
+.. cpp:function:: KDF* get_kdf(const std::string& algo_spec)
+
diff --git a/doc/license.txt b/doc/license.txt
index f1b261eab..aefcee395 100644
--- a/doc/license.txt
+++ b/doc/license.txt
@@ -1,42 +1,49 @@
-Botan (http://botan.randombit.net/) is distributed under these terms:
-
-Copyright (C) 1999-2011 Jack Lloyd
- 2001 Peter J Jones
- 2004-2007 Justin Karneges
- 2004 Vaclav Ovsik
- 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
- 2010 Olivier de Gaalon
-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.
+
+.. _license:
+.. highlight:: none
+
+License
+========================================
+
+Botan (http://botan.randombit.net/) is distributed under these terms::
+
+ Copyright (C) 1999-2011 Jack Lloyd
+ 2001 Peter J Jones
+ 2004-2007 Justin Karneges
+ 2004 Vaclav Ovsik
+ 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
+ 2010 Olivier de Gaalon
+ 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/doc/log.txt b/doc/log.txt
index 9313ac2f6..b9c6c9230 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -1,1525 +1,2072 @@
-* 1.9.15-dev, ????-??-??
- - Pipe will delete empty output queues as soon as they are no longer
- needed, even if earlier messages still have data unread.
-
-* 1.9.14, 2011-03-01
- - Add support for bcrypt, OpenBSD's password hashing scheme
- - Add support for NIST's AES key wrapping algorithm
- - Fix an infinite loop in zlib filters introduced in 1.9.11 (PR 142)
-
-* 1.9.13, 2011-02-19
- - Update Keccak to the round 3 variant
- - Fix ordering in GOST 34.10 signatures to match DNSSEC specifications
- - Use size_t instead of u32bit for small integers in DER/BER codecs
- - Add new build option --distribution-info
- - Fix problems in the amalgamation build
- - Fix building under Clang 2.9 and Sun Studio 12
-
-* 1.9.12, 2010-12-13
- - Add the Keccak hash function
- - Fix compilation problems in Python wrappers
- - Fix compilation problem in OpenSSL engine
- - Update SQLite3 database encryption codec
-
-* 1.9.11, 2010-11-29
- - Many SSL/TLS APIs have changed. This API is still unstable.
- - The SSL interface requires TR1 (uses std::tr1::function)
- - Fix SSL handshake failures when using RC4 ciphersuites
- - Fix a number of CRL encoding and decoding bugs
- - Counter mode now always encrypts 256 blocks in parallel
- - Code where u32bit was used to represent a length now uses size_t
- - Use small tables in the first round of AES
- - Removed AES class: app must choose AES-128, AES-192, or AES-256
- - Add hex encoding/decoding functions that can be used without a Pipe
- - Add base64 encoding functions that can be used without a Pipe
- - Add to_string function to X509_Certificate
- - Add support for dynamic engine loading on Windows
- - Replace BlockCipher::BLOCK_SIZE attribute with function block_size()
- - Replace HashFunction::HASH_BLOCK_SIZE attribute with hash_block_size()
- - Changed semantics of MemoryRegion::resize and clear to match STL
- - Removed MemoryRegion::append, replaced by push_back and operator+=
- - Move PBKDF lookup to engine system
- - The IDEA key schedule has been changed to run in constant time
- - Avoid a possible timing vulnerability in Montgomery reduction
- - Add Algorithm and Key_Length_Specification classes
- - Switch default PKCS #8 encryption algorithm from AES-128 to AES-256
- - Update Skein-512 to match the v1.3 specification
- - Allow using PBKDF2 with empty passphrases
- - Add compile-time deprecation warnings for GCC, Clang, and MSVC
- - Support use of HMAC(SHA-256) and CMAC(Blowfish) in passhash9
- - Improve support for Intel Atom processors
- - Fix compilation problems under Sun Studio and Clang
-
-* 1.8.11, 2010-11-02
- - Fix a number of CRL encoding and decoding bugs
- - When building a debug library under VC++, use the debug runtime
- - Fix compilation under Sun Studio on Linux and Solaris
- - Add several functions for compatability with 1.9
- - In the examples, read most input files as binary
- - The Perl build script has been removed in this release
-
-* 1.8.10, 2010-08-31
- - Switch default PKCS #8 encryption algorithm from 3DES to AES-256
- - Increase default hash iterations from 2048 to 10000 in PBES1 and PBES2
- - Use small tables in the first round of AES
- - Add PBKDF typedef and get_pbkdf for better compatability with 1.9
- - Add version of S2K::derive_key taking salt and iteration count
- - Enable the /proc-walking entropy source on NetBSD
- - Fix the doxygen makefile target
-
-* 1.9.10, 2010-08-12
- - Add a constant time AES implementation using SSSE3
- - Add support for loading new Engines at runtime
- - Use GCC byteswap intrinsics where possible
- - Drop support for building with Python 2.4
- - Fix benchmarking of block ciphers in ECB mode
- - Consolidate the two x86 assembly engines
- - Rename S2K to PBKDF
-
-* 1.9.9, 2010-06-28
- - Add new X509::BER_encode and PKCS8::BER_encode
- - Give all Filter objects a name() function
- - Add Keyed_Filter::valid_iv_length
- - Increase default iteration counts for private key encryption
- - Fix compilation of mp_asm64 on 64-bit MIPS with GCC 4.4 and later
- - Fix compilation under Apple's GCC 4.2
- - Expand and update the Doxygen documentation
-
-* 1.8.9, 2010-06-16
- - Use constant time multiplication in IDEA
- - Avoid possible timing attack against OAEP decoding
- - Add new X509::BER_encode and PKCS8::BER_encode
- - Enable DLL builds under Windows
- - Add Win32 installer support
- - Add support for the Clang compiler
- - Fix problem in semcem.h preventing build under Clang or GCC 3.4
- - Fix bug that prevented creation of DSA groups under 1024 bits
- - Fix crash in GMP_Engine if library is shutdown and reinitialized
- - Work around problem with recent binutils in x86-64 SHA-1
- - The Perl build script is no longer supported and refuses to run by default
-
-* 1.9.8, 2010-06-14
- - Add support for wide multiplications on 64-bit Windows
- - Use constant time multiplication in IDEA
- - Avoid possible timing attack against OAEP decoding
- - Removed FORK-256; rarely used and it has been broken
- - Rename --use-boost-python to --with-boost-python
- - Skip building shared libraries on MinGW/Cygwin
- - Fix creation of 512 and 768 bit DL groups using the DSA kosherizer
- - Fix compilation on GCC versions before 4.3 (missing cpuid.h)
- - Fix compilation under the Clang compiler
-
-* 1.9.7, 2010-04-27
- - TLS: Support reading SSLv2 client hellos
- - TLS: Add support for SEED ciphersuites (RFC 4162)
- - Add Comb4P hash combiner function
- - Fix checking of EMSA_Raw signatures with leading 0 bytes
-
-* 1.9.6, 2010-04-09
- - TLS: Add support for TLS v1.1
- - TLS: Support server name indicator extension
- - TLS: Fix server handshake
- - TLS: Fix server using DSA certificates
- - TLS: Avoid timing channel between CBC padding check and MAC verification
-
-* 1.9.5, 2010-03-29
- - Numerous ECC optimizations
- - Fix GOST 34.10-2001 X.509 key loading
- - Allow PK_Signer's fault protection checks to be toggled off
- - Avoid using pool-based locking allocator if we can't mlock
- - Remove all runtime options
- - New BER_Decoder::{decode_and_check, decode_octet_string_bigint}
- - Remove SecureBuffer in favor of SecureVector length parameter
- - HMAC_RNG: Perform a poll along with user-supplied entropy
- - Fix crash in MemoryRegion if Allocator::get failed
- - Fix small compilation problem on FreeBSD
-
-* 1.9.4, 2010-03-09
- - Add the Ajisai SSLv3/TLSv1.0 implementation
- - Add GOST 34.10-2001 public key signature scheme
- - Add SIMD implementation of Noekeon
- - Add SSE2 implementation of IDEA
- - Extend Salsa20 to support longer IVs (XSalsa20)
- - Perform XTS encryption and decryption in parallel where possible
- - Perform CBC decryption in parallel where possible
- - Add SQLite3 db encryption codec, contributed by Olivier de Gaalon
- - Add a block cipher cascade construction
- - Add support for password hashing for authentication (passhash9.h)
- - Add support for Win32 high resolution system timers
- - Major refactoring and API changes in the public key code
- - Use consistency checking (anti-fault attack) for all signature schemes
- - Changed S2K interface: derive_key now takes salt, iteration count
- - Remove dependency on TR1 for ECC and CVC code
- - Renamed ECKAEG to its more usual name, ECDH
- - Fix crash in GMP_Engine if library is shutdown and reinitialized
- - Fix an invalid memory read in MD4
- - Fix Visual C++ static builds
- - Remove Timer class entirely
- - Switch default PKCS #8 encryption algorithm from 3DES to AES-128
- - New option --gen-amalgamation for creating a SQLite-style amalgamation
- - Many headers are now explicitly internal-use-only and are not installed
- - Greatly improve the Win32 installer
- - Several fixes for Visual C++ debug builds
-
-* 1.9.3, 2009-11-19
- - Add new AES implementation using Intel's AES instruction intrinsics
- - Add an implementation of format preserving encryption
- - Allow use of any hash function in X.509 certificate creation
- - Optimizations for MARS, Skipjack, and AES
- - Set macros for available SIMD instructions in build.h
- - Add support for using InnoSetup to package Windows builds
- - By default build a DLL on Windows
-
-* 1.9.2, 2009-11-03
- - Add SIMD version of XTEA
- - Support both SSE2 and AltiVec SIMD for Serpent and XTEA
- - Optimizations for SHA-1 and SHA-2
- - Add AltiVec runtime detection
- - Fix x86 CPU identification with Intel C++ and Visual C++
-
-* 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.9.1, 2009-10-23
- - Better support for Python and Perl wrappers
- - Add an implementation of Blue Midnight Wish (Round 2 tweak version)
- - Modify Skein-512 to match the tweaked 1.2 specification
- - Add threshold secret sharing (draft-mcgrew-tss-02)
- - Add runtime cpu feature detection for x86/x86-64
- - Add code for general runtime self testing for hashes, MACs, and ciphers
- - Optimize XTEA; twice as fast as before on Core2 and Opteron
- - Convert CTR_BE and OFB from filters to stream ciphers
- - New parsing code for SCAN algorithm names
- - Enable SSE2 optimizations under Visual C++
- - Remove all use of C++ exception specifications
- - Add support for GNU/Hurd and Clang/LLVM
-
-* 1.9.0, 2009-09-09
- - Add support for parallel invocation of block ciphers where possible
- - Add SSE2 implementation of Serpent
- - Add Rivest's package transform (an all or nothing transform)
- - Minor speedups to the Turing key schedule
- - Fix processing multiple messages in XTS mode
- - Add --no-autoload option to configure.py, for minimized builds
- - The previously used configure.pl script is no longer supported
-
-* 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.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.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.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.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.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.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
+.. _relnotes:
+
+Release Notes
+========================================
+
+Series 1.10
+----------------------------------------
+
+Version 1.10.0, Not Yet Released
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+Series 1.9
+----------------------------------------
+
+Version 1.9.18, 2011-06-03
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fourth release candidate for 1.10.0
+
+* The GOST 34.10 verification operation was not ensuring that s and r
+ were both greater than zero. This could potentially have meant it
+ would have accepted an invalid all-zero signature as valid for any
+ message. Due to how ECC points are internally represented it instead
+ resulted in an exception being thrown.
+
+* A simple multiexponentation algorithm is now used in ECDSA and
+ GOST-34.10 signature verification, leading to 20 to 25% improvements
+ in ECDSA and 25% to 40% improvements in GOST-34.10 verification
+ performance.
+
+* The internal representation of elliptic curve points has been
+ modified to use Montgomery representation exclusively, resulting in
+ reduced memory usage and a 10 to 20% performance improvement for
+ ECDSA and ECDH.
+
+* In OAEP decoding, scan for the delimiter bytes using a loop that is
+ written without conditionals so as to help avoid timing analysis.
+ Unfortunately GCC at least is 'smart' enough to compile it to
+ jumps anyway.
+
+* The SSE2 implementation of IDEA did not work correctly when compiled
+ by Clang, because the trick it used to emulate a 16 bit unsigned
+ compare in SSE (which doesn't contain one natively) relied on signed
+ overflow working in the 'usual' way. A different method that doesn't
+ rely on signed overflow is now used.
+
+* Add support for compiling SSL using Visual C++ 2010's TR1
+ implementation.
+
+* Fix a bug under Visual C++ 2010 which would cause ``hex_encode`` to
+ crash if given a zero-sized input to encode.
+
+* A new build option ``--via-amalgamation`` will first generate the
+ single-file amalgamation, then build the library from that single
+ file. This option requires a lot of memory and does not parallelize,
+ but the resulting library is smaller and may be faster.
+
+* On Unix, the library and header paths have been changed to allow
+ parallel installation of different versions of the library. Headers
+ are installed into ``<prefix>/include/botan-1.9/botan``, libraries
+ are named ``libbotan-1.9``, and ``botan-config`` is now namespaced
+ (so in this release ``botan-config-1.9``). All of these embedded
+ versions will be 1.10 in the upcoming stable release.
+
+* The soname system has been modified. In this release the library
+ soname is ``libbotan-1.9.so.0``, with the full library being named
+ ``libbotan-1.9.so.0.18``. The ``0`` is the ABI version, and will be
+ incremented whenever a breaking ABI change is made.
+
+* TR1 support is not longer automatically assumed under older versions
+ of GCC
+
+* Functions for base64 decoding that work standalone (without needing
+ to use a pipe) have been added to ``base64.h``
+
+* The function ``BigInt::to_u32bit`` was inadvertently removed in 1.9.11
+ and has been added back.
+
+* The function ``BigInt::get_substring`` did not work correctly with a
+ *length* argument of 32.
+
+* The implementation of ``FD_ZERO`` on Solaris uses ``memset`` and
+ assumes the caller included ``string.h`` on its behalf. Do so to
+ fix compilation in the ``dev_random`` and ``unix_procs`` entropy
+ sources. Patch from Jeremy C. Reed.
+
+* Add two different configuration targets for Atom, since some are
+ 32-bit and some are 64-bit. The 'atom' target now refers to the
+ 64-bit implementations, use 'atom32' to target the 32-bit
+ processors.
+
+* The (incomplete) support for CMS and card verifiable certificates
+ are disabled by default; add ``--enable-modules=cms`` or
+ ``--enable-modules=cvc`` during configuration to turn them back on.
+
+Version 1.9.17, 2011-04-29
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Third release candidate for 1.10.0
+
+* The format preserving encryption method currently available was
+ presented in the header ``fpe.h`` and the functions ``fpe_encrypt``
+ and ``fpe_decrypt``. These were renamed as it is likely that other
+ FPE schemes will be included in the future. The header is now
+ ``fpe_fe1.h``, and the functions are named ``fe1_encrypt`` and
+ ``fe1_decrypt``. See :doc:`fpe` for more information.
+
+* New options to ``configure.py`` control what tools are used for
+ documentation generation. The ``--with-sphinx`` option enables using
+ Sphinx to convert ReST into HTML; otherwise the ReST sources are
+ installed directly. If ``--with-doxygen`` is used, Doxygen will run
+ as well. Documentation generation can be triggered via the ``docs``
+ target in the makefile; it will also be installed by the install
+ target on Unix.
+
+* A bug in 1.9.16 effectively disabled support for runtime CPU feature
+ detection on x86 under GCC in that release.
+
+* A mostly internal change, all references to "ia32" and "amd64" have
+ been changed to the vendor neutral and probably easier to understand
+ "x86-32" and "x86-64". For instance, the "mp_amd64" module has been
+ renamed "mp_x86_64", and the macro indicating x86-32 has changed
+ from ``BOTAN_TARGET_ARCH_IS_IA32`` to
+ ``BOTAN_TARGET_ARCH_IS_X86_32``. The classes calling assembly have
+ also been renamed.
+
+* Similiarly to the above change, the AES implemenations using the
+ AES-NI instruction set have been renamed from AES_XXX_Intel to
+ AES_XXX_NI.
+
+* Systems that are identified as `sun4u` will default to compiling for
+ 32-bit SPARCv9 code rather than 64-bit. This matches the still
+ common convention for 32-bit SPARC userspaces. If you want 64-bit
+ code on such as system, use ``--cpu=sparc64``.
+
+* Some minor fixes for compiling botan under the BeOS
+ clone/continuation `Haiku <http://haiku-os.org>`_.
+
+* Further updates to the documentation
+
+Version 1.9.16, 2011-04-11
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Second release candidate for 1.10.0
+
+* The documentation, previously written in LaTeX, is now in
+ reStructuredText suitable for processing by `Sphinx
+ <http://sphinx.pocoo.org>`_, which can generate nicely formatted
+ HTML and PDFs. The documentation has also been greatly updated and
+ expanded.
+
+* The class ``EC_Domain_Params`` has been renamed ``EC_Group``, with a
+ typedef for backwards compatability.
+
+* ``EC_Group``'s string constructor didn't understand the standard
+ names like "secp160r1", forcing use of the OIDs.
+
+* Two constructors for ECDSA private keys, the one that creates a new
+ random key, and the one that provides a preset private key as a
+ ``BigInt``, have been merged. This matches the existing interface
+ for DSA and DH keys. If you previously used the version taking a
+ ``BigInt`` private key, you'll have to additionally pass in a
+ ``RandomNumberGenerator`` object starting in this release.
+
+* It is now possible to create ECDH keys with a preset ``BigInt``
+ private key; previously no method for this was available.
+
+* The overload of ``generate_passhash9`` that takes an explicit
+ algorithm identifier has been merged with the one that does not.
+ The algorithm identifier code has been moved from the second
+ parameter to the fourth. See :ref:`passhash9` for details.
+
+* Change shared library versioning to match the normal Unix
+ conventions. Instead of ``libbotan-X.Y.Z.so``, the shared lib is
+ named ``libbotan-X.Y.so.Z``; this allows the runtime linker to do
+ its runtime linky magic. It can be safely presumed that any change
+ in the major or minor version indicates ABI incompatability.
+
+* Remove the socket wrapper code; it was not actually used by anything
+ in the library, only in the examples, and you can use whatever kind
+ of (blocking) socket interface you like with the SSL/TLS code. It's
+ available as socket.h in the examples directory if you want to use
+ it.
+
+* Disable the by-default 'strong' checking of private keys that are
+ loaded from storage. You can always request key material sanity
+ checking using Private_Key::check_key.
+
+* Bring back removed functions ``min_keylength_of``,
+ ``max_keylength_of``, ``keylength_multiple_of`` in ``lookup.h`` to
+ avoid breaking applications written against 1.8
+
+Version 1.9.15, 2011-03-21
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* First release candidate for 1.10.0
+
+* Modify how message expansion is done in SHA-256 and SHA-512.
+ Instead of expanding the entire message at the start, compute them
+ in the minimum number of registers. Values are computed 15 rounds
+ before they are needed. On a Core i7-860, GCC 4.5.2, went from 143
+ to 157 MiB/s in SHA-256, and 211 to 256 MiB/s in SHA-512.
+
+* Pipe will delete empty output queues as soon as they are no longer
+ needed, even if earlier messages still have data unread. However an
+ (empty) entry in a deque of pointers will remain until all prior
+ messages are completely emptied.
+
+* Avoid reading the SPARC ``%tick`` register on OpenBSD as unlike
+ Linux the kernel will not trap and emulate it for us, causing a
+ illegal instruction crash.
+
+* Improve detection and autoconfiguration for ARM processors.
+
+Version 1.9.14, 2011-03-01
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add support for bcrypt, OpenBSD's password hashing scheme. It is
+ described in :ref:`bcrypt`.
+
+* Add support for NIST's AES key wrapping algorithm, as described in
+ :rfc:`3394`. It is available by including ``rfc3394.h``.
+
+* Fix an infinite loop in zlib filters introduced in 1.9.11 (PR 142)
+
+Version 1.9.13, 2011-02-19
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Update Keccak to the round 3 variant
+* Fix ordering in GOST 34.10 signatures to match DNSSEC specifications
+* Use ``size_t`` instead of ``u32bit`` for small integers in DER/BER codecs
+* Add new build option ``--distribution-info``
+* Fix problems in the amalgamation build
+* Fix building under Clang 2.9 and Sun Studio 12
+
+Version 1.9.12, 2010-12-13
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add the Keccak hash function
+* Fix compilation problems in Python wrappers
+* Fix compilation problem in OpenSSL engine
+* Update SQLite3 database encryption codec
+
+Version 1.9.11, 2010-11-29
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Many SSL/TLS APIs have changed. This API is still unstable.
+* The SSL interface requires TR1 (uses std::tr1::function)
+* Fix SSL handshake failures when using RC4 ciphersuites
+* Fix a number of CRL encoding and decoding bugs
+* Counter mode now always encrypts 256 blocks in parallel
+* Code where u32bit was used to represent a length now uses size_t
+* Use small tables in the first round of AES
+* Removed AES class: app must choose AES-128, AES-192, or AES-256
+* Add hex encoding/decoding functions that can be used without a Pipe
+* Add base64 encoding functions that can be used without a Pipe
+* Add to_string function to X509_Certificate
+* Add support for dynamic engine loading on Windows
+* Replace BlockCipher::BLOCK_SIZE attribute with function block_size()
+* Replace HashFunction::HASH_BLOCK_SIZE attribute with hash_block_size()
+* Changed semantics of MemoryRegion::resize and clear to match STL
+* Removed MemoryRegion::append, replaced by push_back and operator+=
+* Move PBKDF lookup to engine system
+* The IDEA key schedule has been changed to run in constant time
+* Avoid a possible timing vulnerability in Montgomery reduction
+* Add Algorithm and Key_Length_Specification classes
+* Switch default PKCS #8 encryption algorithm from AES-128 to AES-256
+* Update Skein-512 to match the v1.3 specification
+* Allow using PBKDF2 with empty passphrases
+* Add compile-time deprecation warnings for GCC, Clang, and MSVC
+* Support use of HMAC(SHA-256) and CMAC(Blowfish) in passhash9
+* Improve support for Intel Atom processors
+* Fix compilation problems under Sun Studio and Clang
+
+Version 1.9.10, 2010-08-12
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add a constant time AES implementation using SSSE3
+* Add support for loading new Engines at runtime
+* Use GCC byteswap intrinsics where possible
+* Drop support for building with Python 2.4
+* Fix benchmarking of block ciphers in ECB mode
+* Consolidate the two x86 assembly engines
+* Rename S2K to PBKDF
+
+Version 1.9.9, 2010-06-28
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add new X509::BER_encode and PKCS8::BER_encode
+* Give all Filter objects a name() function
+* Add Keyed_Filter::valid_iv_length
+* Increase default iteration counts for private key encryption
+* Fix compilation of mp_asm64 on 64-bit MIPS with GCC 4.4 and later
+* Fix compilation under Apple's GCC 4.2
+* Expand and update the Doxygen documentation
+
+Version 1.9.8, 2010-06-14
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add support for wide multiplications on 64-bit Windows
+* Use constant time multiplication in IDEA
+* Avoid possible timing attack against OAEP decoding
+* Removed FORK-256; rarely used and it has been broken
+* Rename ``--use-boost-python`` to ``--with-boost-python``
+* Skip building shared libraries on MinGW/Cygwin
+* Fix creation of 512 and 768 bit DL groups using the DSA kosherizer
+* Fix compilation on GCC versions before 4.3 (missing cpuid.h)
+* Fix compilation under the Clang compiler
+
+Version 1.9.7, 2010-04-27
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* TLS: Support reading SSLv2 client hellos
+* TLS: Add support for SEED ciphersuites (RFC 4162)
+* Add Comb4P hash combiner function
+* Fix checking of EMSA_Raw signatures with leading 0 bytes
+
+Version 1.9.6, 2010-04-09
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* TLS: Add support for TLS v1.1
+* TLS: Support server name indicator extension
+* TLS: Fix server handshake
+* TLS: Fix server using DSA certificates
+* TLS: Avoid timing channel between CBC padding check and MAC verification
+
+Version 1.9.5, 2010-03-29
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Numerous ECC optimizations
+* Fix GOST 34.10-2001 X.509 key loading
+* Allow PK_Signer's fault protection checks to be toggled off
+* Avoid using pool-based locking allocator if we can't mlock
+* Remove all runtime options
+* New BER_Decoder::{decode_and_check, decode_octet_string_bigint}
+* Remove SecureBuffer in favor of SecureVector length parameter
+* HMAC_RNG: Perform a poll along with user-supplied entropy
+* Fix crash in MemoryRegion if Allocator::get failed
+* Fix small compilation problem on FreeBSD
+
+Version 1.9.4, 2010-03-09
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add the Ajisai SSLv3/TLSv1.0 implementation
+* Add GOST 34.10-2001 public key signature scheme
+* Add SIMD implementation of Noekeon
+* Add SSE2 implementation of IDEA
+* Extend Salsa20 to support longer IVs (XSalsa20)
+* Perform XTS encryption and decryption in parallel where possible
+* Perform CBC decryption in parallel where possible
+* Add SQLite3 db encryption codec, contributed by Olivier de Gaalon
+* Add a block cipher cascade construction
+* Add support for password hashing for authentication (passhash9.h)
+* Add support for Win32 high resolution system timers
+* Major refactoring and API changes in the public key code
+* Use consistency checking (anti-fault attack) for all signature schemes
+* Changed S2K interface: derive_key now takes salt, iteration count
+* Remove dependency on TR1 for ECC and CVC code
+* Renamed ECKAEG to its more usual name, ECDH
+* Fix crash in GMP_Engine if library is shutdown and reinitialized
+* Fix an invalid memory read in MD4
+* Fix Visual C++ static builds
+* Remove Timer class entirely
+* Switch default PKCS #8 encryption algorithm from 3DES to AES-128
+* New option --gen-amalgamation for creating a SQLite-style amalgamation
+* Many headers are now explicitly internal-use-only and are not installed
+* Greatly improve the Win32 installer
+* Several fixes for Visual C++ debug builds
+
+Version 1.9.3, 2009-11-19
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add new AES implementation using Intel's AES instruction intrinsics
+* Add an implementation of format preserving encryption
+* Allow use of any hash function in X.509 certificate creation
+* Optimizations for MARS, Skipjack, and AES
+* Set macros for available SIMD instructions in build.h
+* Add support for using InnoSetup to package Windows builds
+* By default build a DLL on Windows
+
+Version 1.9.2, 2009-11-03
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add SIMD version of XTEA
+* Support both SSE2 and AltiVec SIMD for Serpent and XTEA
+* Optimizations for SHA-1 and SHA-2
+* Add AltiVec runtime detection
+* Fix x86 CPU identification with Intel C++ and Visual C++
+
+Version 1.9.1, 2009-10-23
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Better support for Python and Perl wrappers
+* Add an implementation of Blue Midnight Wish (Round 2 tweak version)
+* Modify Skein-512 to match the tweaked 1.2 specification
+* Add threshold secret sharing (draft-mcgrew-tss-02)
+* Add runtime cpu feature detection for x86/x86-64
+* Add code for general runtime self testing for hashes, MACs, and ciphers
+* Optimize XTEA; twice as fast as before on Core2 and Opteron
+* Convert CTR_BE and OFB from filters to stream ciphers
+* New parsing code for SCAN algorithm names
+* Enable SSE2 optimizations under Visual C++
+* Remove all use of C++ exception specifications
+* Add support for GNU/Hurd and Clang/LLVM
+
+Version 1.9.0, 2009-09-09
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Add support for parallel invocation of block ciphers where possible
+* Add SSE2 implementation of Serpent
+* Add Rivest's package transform (an all or nothing transform)
+* Minor speedups to the Turing key schedule
+* Fix processing multiple messages in XTS mode
+* Add --no-autoload option to configure.py, for minimized builds
+* The previously used configure.pl script is no longer supported
+
+Series 1.8
+----------------------------------------
+
+Version 1.8.11, 2010-11-02
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fix a number of CRL encoding and decoding bugs
+* When building a debug library under VC++, use the debug runtime
+* Fix compilation under Sun Studio on Linux and Solaris
+* Add several functions for compatability with 1.9
+* In the examples, read most input files as binary
+* The Perl build script has been removed in this release
+
+Version 1.8.10, 2010-08-31
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Switch default PKCS #8 encryption algorithm from 3DES to AES-256
+* Increase default hash iterations from 2048 to 10000 in PBES1 and PBES2
+* Use small tables in the first round of AES
+* Add PBKDF typedef and get_pbkdf for better compatability with 1.9
+* Add version of S2K::derive_key taking salt and iteration count
+* Enable the /proc-walking entropy source on NetBSD
+* Fix the doxygen makefile target
+
+Version 1.8.9, 2010-06-16
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Use constant time multiplication in IDEA
+* Avoid possible timing attack against OAEP decoding
+* Add new X509::BER_encode and PKCS8::BER_encode
+* Enable DLL builds under Windows
+* Add Win32 installer support
+* Add support for the Clang compiler
+* Fix problem in semcem.h preventing build under Clang or GCC 3.4
+* Fix bug that prevented creation of DSA groups under 1024 bits
+* Fix crash in GMP_Engine if library is shutdown and reinitialized
+* Work around problem with recent binutils in x86-64 SHA-1
+* The Perl build script is no longer supported and refuses to run by default
+
+Version 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
+
+Version 1.8.7, 2009-09-09
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fix processing multiple messages in XTS mode
+* Add --no-autoload option to configure.py, for minimized builds
+
+Version 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
+
+Version 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
+
+Version 1.8.4, 2009-07-12
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fix a bug in nonce generation in the Miller-Rabin test
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 1.8.0, 2008-12-08
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fix compilation on Solaris with GCC
+
+Series 1.7
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 1.6
+----------------------------------------
+
+Version 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
+
+Version 1.6.4, 2008-03-08
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fix a compilation problem with Visual Studio C++ 2003
+
+Version 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++
+
+Version 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
+
+Version 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
+
+Version 1.6.0, 2006-12-17
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Minor cleanups versus 1.5.13
+
+Series 1.5
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 1.4
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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++
+
+Series 1.3
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 1.2
+----------------------------------------
+
+Version 1.2.8, 2003-11-21
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Merged several important bug fixes from 1.3.x
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 1.1
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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)
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 1.0
+----------------------------------------
+
+Version 1.0.2, 2003-01-12
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Fixed an obscure SEGFAULT causing bug in Pipe
+* Fixed an obscure but dangerous bug in SecureVector::swap
+
+Version 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
+
+Version 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
+
+Series 0.9
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 0.8
+----------------------------------------
+
+Version 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)
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Series 0.7
+----------------------------------------
+
+Version 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
+
+Version 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
+
+Version 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)
+
+Version 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++
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 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
+
+Version 0.7.0, 2001-03-01
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* First public release
diff --git a/doc/lowlevel.txt b/doc/lowlevel.txt
new file mode 100644
index 000000000..852d7eb43
--- /dev/null
+++ b/doc/lowlevel.txt
@@ -0,0 +1,236 @@
+
+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.
+
+Basic Algorithm Abilities
+---------------------------------
+
+There are a small handful of functions implemented by most of Botan's
+algorithm objects. Among these are:
+
+.. cpp:function:: std::string Algorithm::name()
+
+Returns a human-readable string of the name of this
+algorithm. Examples of names returned are "AES-128" and
+"HMAC(SHA-512)". You can turn names back into algorithm objects using
+the functions in ``lookup.h``.
+
+.. cpp:function:: void Algorithm::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. The object will look and behave as it did when you initially
+allocated it.
+
+.. cpp:function:: T* Algorithm::clone()
+
+This function is central to Botan's name-based interface. The
+``clone`` has many different return types, such as ``BlockCipher``\*
+and ``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 ``clone`` do not affect the initial state of the new
+clone.
+
+Cloned objects can (and should) be deallocated with the C++ ``delete``
+operator.
+
+Keys and IVs
+---------------------------------
+
+Both symmetric keys and initialization values can be considered byte
+(or octet) strings. These are represented by
+
+.. cpp:class:: OctetString
+
+ Also known as ``SymmetricKey`` and ``InitializationVector``, when
+ you want to express intent.
+
+ .. cpp:function:: OctetString(RandomNumberGenerator& rng, size_t length)
+
+ This constructor creates a new random key *length* bytes long
+ using the random number generator.
+
+ .. cpp:function:: OctetString(std::string str)
+
+ The argument *str* is assumed to be a hex string; it is
+ converted to binary and stored. Whitespace is ignored.
+
+ .. cpp:function:: OctetString(const byte* input, size_t length)
+
+ This constructor copies its input.
+
+ .. cpp:function:: as_string() const
+
+ Returns the hex representation of the key or IV
+
+Symmetrically Keyed Algorithms
+---------------------------------
+
+Block ciphers, stream ciphers, and MACs are all keyed operations; to
+be useful, they have to be set to use a particular key, which is a
+randomly chosen string of bits of a specified length. The length
+required by any particular algorithm may vary, depending on both the
+algorithm specification and the implementation. You can query any
+botan object to find out what key length(s) it supports.
+
+To make this similarity in terms of keying explicit, all algorithms of
+those types are derived from the :cpp:class`SymmetricAlgorithm` base.
+This type provides functions for setting the key, and querying
+restrictions on the size of the key.
+
+.. cpp:class:: SymmetricAlgorithm
+
+ .. cpp:function:: void set_key(const byte* key, size_t length)
+
+ .. cpp:function:: void set_key(const SymmetricKey& key)
+
+ This sets the key to the value specified. Most algorithms only
+ accept keys of certain lengths. If you attempt to call
+ ``set_key`` with a key length that is not supported, the
+ exception ``Invalid_Key_Length`` will be thrown.
+
+ In all cases, ``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.
+
+ .. cpp:function:: bool valid_keylength(size_t length) const
+
+ This function returns true if and only if *length* is a valid
+ keylength for the algorithm.
+
+ .. cpp:function:: size_t minimum_keylength() const
+
+ Return the smallest key length (in bytes) that is acceptible for the
+ algorithm.
+
+ .. cpp:function:: size_t maximum_keylength() const
+
+ Return the largest key length (in bytes) that is acceptible for the
+ algorithm
+
+Block Ciphers
+---------------------------------
+
+All block ciphers classes in botan are subclasses of
+
+.. cpp:class:: BlockCipher
+
+ Which subclasses the :cpp:class:`SymmetricAlgorithm` interface.
+
+ .. cpp:function:: size_t block_size() const
+
+ Returns the block size of the cipher in bytes
+
+ .. cpp:function:: void encrypt_n(const byte* in, \
+ byte* out, size_t n) const
+
+ Encrypt *n* blocks of data, taking the input from the array *in*
+ and placing the ciphertext into *out*. The two pointers may be
+ identical, but should not overlap ranges.
+
+ .. cpp:function:: void encrypt(const byte* in, byte* out) const
+
+ Encrypt a single block, taking the input from *in* and placing
+ it in *out*. Acts like :cpp:func:`encrypt_n`\ (in, out, 1).
+
+ .. cpp:function:: void encrypt(byte* block) const
+
+ Identical to :cpp:func:`encrypt`\ (block, block)
+
+ .. cpp:function:: void decrypt_n(const byte* in, byte out, size_t n) const
+
+ Decrypt *n* blocks of data, taking the input from *in* and
+ placing the plaintext in *out*. The two pointers may be
+ identical, but should not overlap ranges.
+
+ .. cpp:function:: void decrypt(const byte* in, byte* out) const
+
+ Decrypt a single block, taking the input from *in* and placing it
+ in *out*. Acts like :cpp:func:`decrypt_n`\ (in, out, 1).
+
+ .. cpp:function:: void decrypt(byte* block) const
+
+ Identical to :cpp:func:`decrypt`\ (block, block)
+
+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).
+
+.. cpp:function:: void StreamCipher::encrypt(const byte* in, byte* out, size_t length)
+
+.. cpp:function:: void StreamCipher::encrypt(byte* data, size_t length)
+
+Stream ciphers implement the ``SymmetricAlgorithm`` interface.
+
+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 ``BufferedComputation``, which has the following
+functions.
+
+.. cpp:function:: size_t BufferedComputation::output_length()
+
+Return the size of the output of this function.
+
+.. cpp:function:: void BufferedComputation::update(const byte* input, size_t length)
+
+.. cpp:function:: void BufferedComputation::update(byte input)
+
+.. cpp:function:: void BufferedComputation::update(const std::string& input)
+
+Updates the hash/mac calculation with *input*.
+
+.. cpp:function:: void BufferedComputation::final(byte* out)
+
+.. cpp:function:: SecureVector<byte> BufferedComputation::final()
+
+Complete the hash/MAC calculation and place the result into ``out``.
+For the argument taking an array, exactly ``output_length`` bytes will
+be written. After you call ``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.
+
+There is also a pair of functions called ``process``. They are a
+combination of a single ``update``, and ``final``. Both versions
+return the final value, rather than placing it an array. Calling
+``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 a keyed hash function, so
+classes that are derived from ``MessageAuthenticationCode`` have
+``update`` and ``final`` classes just like a ``HashFunction`` (and
+like a ``HashFunction``, after ``final`` is called, it can be used to
+make a new MAC right away; the key is kept around).
+
+A MAC has the ``SymmetricAlgorithm`` interface in addition to the
+``BufferedComputation`` interface.
+
+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.
diff --git a/doc/old_tutorial.tex b/doc/old_tutorial.tex
deleted file mode 100644
index f220d765a..000000000
--- a/doc/old_tutorial.tex
+++ /dev/null
@@ -1,880 +0,0 @@
-\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{[email protected]}}
-\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 PBKDF
-(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}
- PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)");
- // hard-coded iteration count for simplicity; should be sufficient
- pbkdf->set_iterations(10000);
- // 8 octets == 64-bit salt; again, good enough
- pbkdf->new_random_salt(8);
- SecureVector<byte> the_salt = pbkdf->current_salt();
-
- // 48 octets == 32 for key + 16 for IV
- SecureVector<byte> key_and_IV = pbkdf->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{pbkdf} 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 = pbkdf->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[0], 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}
- PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)");
- // hard-coded iteration count for simplicity; should be sufficient
- pbkdf->set_iterations(10000);
- // 8 octet == 64-bit salt; again, good enough
- pbkdf->new_random_salt(8);
- // store the salt so we can write it to a file later
- SecureVector<byte> the_salt = pbkdf->current_salt();
-
- SymmetricKey master_key = pbkdf->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}
- PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)");
- pbkdf->set_iterations(10000);
- pbkdf->new_random_salt(8);
- SecureVector<byte> the_salt = pbkdf->current_salt();
-
- SymmetricKey master_key = pbkdf->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[0], the_salt.size());
-
- pipe.start_msg();
- infile >> pipe;
- pipe.end_msg();
-
- SecureVector<byte> hmac = pipe.read_all(1);
- outfile.write((const char*)&hmac[0], 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[0], 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[0], 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}
- PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)");
- pbkdf->set_iterations(10000);
- pbkdf->new_random_salt(8);
- OctetString the_salt = pbkdf->current_salt();
-
- SymmetricKey hmac_key = pbkdf->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 10000 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 != 10000; 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}
- Public_Key* key = /* loaded or generated somehow */
- 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/doc/passhash.txt b/doc/passhash.txt
new file mode 100644
index 000000000..8ce3cf805
--- /dev/null
+++ b/doc/passhash.txt
@@ -0,0 +1,117 @@
+
+Password Hashing
+========================================
+
+Storing passwords for user authentication purposes in plaintext is the
+simplest but least secure method; when an attacker compromises the
+database in which the passwords are stored, they immediately gain
+access to all of them. Often passwords are reused among multiple
+services or machines, meaning once a password to a single service is
+known an attacker has a substantial head start on attacking other
+machines.
+
+The general approach is to store, instead of the password, the output
+of a one way function of the password. Upon receiving an
+authentication request, the authenticator can recompute the one way
+function and compare the value just computed with the one that was
+stored. If they match, then the authentication request succeeds. But
+when an attacker gains access to the database, they only have the
+output of the one way function, not the original password.
+
+Common hash functions such as SHA-256 are one way, but used alone they
+have problems for this purpose. What an attacker can do, upon gaining
+access to such a stored password database, is hash common dictionary
+words and other possible passwords, storing them in a list. Then he
+can search through his list; if a stored hash and an entry in his list
+match, then he has found the password. Even worse, this can happen
+*offline*: an attacker can begin hashing common passwords days,
+months, or years before ever gaining access to the database. In
+addition, if two users choose the same password, the one way function
+output will be the same for both of them, which will be visible upon
+inspection of the database.
+
+There are two solutions to these problems: salting and
+iteration. Salting refers to including, along with the password, a
+randomly chosen value which perturbs the one way function. Salting can
+reduce the effectivness of offline dictionary generation (because for
+each potential password, an attacker would have to compute the one way
+function output for all possible salts - with a large enough salt,
+this can make the problem quite difficult). It also prevents the same
+password from producing the same output, as long as the salts do not
+collide. With a large salt (say 80 to 128 bits) this will be quite
+unlikely. Iteration refers to the general technique of forcing
+multiple one way function evaluations when computing the output, to
+slow down the operation. For instance if hashing a single password
+requires running SHA-256 100,000 times instead of just once, that will
+slow down user authentication by a factor of 100,000, but user
+authentication happens quite rarely, and usually there are more
+expensive operations that need to occur anyway (network and database
+I/O, etc). On the other hand, an attacker who is attempting to break a
+database full of stolen password hashes will be seriously
+inconvenienced by a factor of 100,000 slowdown; they will be able to
+only test at a rate of .0001% of what they would without iterations
+(or, equivalently, will require 100,000 times as many zombie botnet
+hosts).
+
+Botan provides two techniques for password hashing, bcrypt and
+passhash9.
+
+.. _bcrypt:
+
+Bcrypt Password Hashing
+----------------------------------------
+
+Bcrypt is a password hashing scheme originally designed for use in
+OpenBSD, but numerous other implementations exist. It is made
+available by including ``bcrypt.h``. Bcrypt provides outputs that
+look like this::
+
+ "$2a$12$7KIYdyv8Bp32WAvc.7YvI.wvRlyVn0HP/EhPmmOyMQA4YKxINO0p2"
+
+.. cpp:function:: std::string generate_bcrypt(const std::string& password, \
+ RandomNumberGenerator& rng, u16bit work_factor = 10)
+
+ Takes the password to hash, a rng, and a work factor. Higher values
+ increase the amount of time the algorithm runs, increasing the cost
+ of cracking attempts. The resulting hash is returned as a string.
+
+.. cpp:function:: bool check_bcrypt(const std::string& password, \
+ const std::string& hash)
+
+ Takes a password and a bcrypt output and returns true if the
+ password is the same as the one that was used to generate the
+ bcrypt hash.
+
+Here is an example of using bcrypt:
+
+.. literalinclude:: examples/bcrypt.cpp
+
+.. _passhash9:
+
+Passhash9
+----------------------------------------
+
+Botan also provides a password hashing technique called passhash9, in
+``passhash9.h``, which is based on PBKDF2. Its outputs look like::
+
+ "$9$AAAKxwMGNPSdPkOKJS07Xutm3+1Cr3ytmbnkjO6LjHzCMcMQXvcT"
+
+.. cpp:function:: std::string generate_passhash9(const std::string& password, \
+ RandomNumberGenerator& rng, u16bit work_factor = 10, byte alg_id = 0)
+
+ Functions much like ``generate_bcrypt``. The last parameter,
+ ``alg_id``, specifies which PRF to use. Currently defined values
+ are
+
+ ======= ==============
+ Value PRF algorithm
+ ======= ==============
+ 0 HMAC(SHA-1)
+ 1 HMAC(SHA-256)
+ 2 CMAC(Blowfish)
+ ======= ==============
+
+.. cpp:function:: bool check_passhash9(const std::string& password, \
+ const std::string& hash)
+
+ Functions much like ``check_bcrypt``
diff --git a/doc/pbkdf.txt b/doc/pbkdf.txt
new file mode 100644
index 000000000..f24dcd188
--- /dev/null
+++ b/doc/pbkdf.txt
@@ -0,0 +1,76 @@
+
+.. _pbkdf:
+
+PBKDF Algorithms
+========================================
+
+There are various procedures for turning a passphrase into a arbitrary
+length key for use with a symmetric cipher. A general interface for
+such algorithms is presented in ``pbkdf.h``. The main function is
+``derive_key``, which takes a passphrase, a salt, an iteration count,
+and the desired length of the output key, and returns a key of that
+length, deterministically produced from the passphrase and salt. 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).
+
+The purpose of the iteration count is to make the algorithm take
+longer to compute the final key (reducing the speed of brute-force
+attacks of various kinds). Most standards recommend an iteration count
+of at least 10000. Currently defined PBKDF algorithms are
+"PBKDF1(digest)", "PBKDF2(digest)", and "OpenPGP-S2K(digest)"; you can
+retrieve any of these using the ``get_pbkdf``, found in
+``lookup.h``. As of this writing, "PBKDF2(SHA-256)" with 10000
+iterations and a 16 byte salt is recommend for new applications.
+
+.. cpp:function:: OctetString PBKDF::derive_key( \
+ size_t output_len, const std::string& passphrase, \
+ const byte* salt, size_t salt_len, \
+ size_t iterations) const
+
+ Computes a key from *passphrase* and the *salt* (of length
+ *salt_len* bytes) using an algorithm-specific interpretation of
+ *iterations*, producing a key of length *output_len*.
+
+ Use an iteration count of at least 10000. The salt should be
+ randomly chosen by a good random number generator (see
+ :ref:`random_number_generators` for how), or at the very least
+ unique to this usage of the passphrase.
+
+ If you call this function again with the same parameters, you will
+ get the same key.
+
+::
+
+ PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)");
+ AutoSeeded_RNG rng;
+
+ SecureVector<byte> salt = rng.random_vec(16);
+ OctetString aes256_key = pbkdf->derive_key(32, "password",
+ &salt[0], salt.size(),
+ 10000);
+
+
+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 *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, 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.
+
diff --git a/doc/pgpkey.txt b/doc/pgpkey.txt
new file mode 100644
index 000000000..ef8827835
--- /dev/null
+++ b/doc/pgpkey.txt
@@ -0,0 +1,43 @@
+
+PGP Code Signing Key
+========================================
+
+.. highlight:: none
+
+The following PGP key is used to sign all releases::
+
+ pub 2048R/EFBADFBC 2004-10-30
+ Key fingerprint = 621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC
+ uid Botan Distribution Key
+
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+ Version: GnuPG v2.0.17 (GNU/Linux)
+
+ mQELBEGD1j0BCADHxPJkPcjJE+4Dlisx2hVc0Dj6JI1MSLrkM8R+2bOhVUSferxP
+ T1EMPhfrAdOHTAloyvRThJztnZsNKqfLL49GGcBLdEGAVNks1pG37Teze5Lx1XIu
+ zJFrozL2sqBy5C6nHpFgd1tcD68Rah2wp0u2cR9owXf1IqKdEfuo661+MTv7wTB1
+ 4hKV75nB7ZO6676SEZRILYM+7RJwKAKEmEPJc6hEf94VXn9ecNzaTlHgYkjhz9db
+ LOd3od9XvuUw+LMR1dwBqMxbvR90MiXjbedDEkbArcZB9YOAIvEX/lC3qaW4XJt4
+ iwHWl/YVZEfALcvQywe2CDrH5hO794wd9MpBAAYptBZCb3RhbiBEaXN0cmlidXRp
+ b24gS2V5iQEqBBMBAgAUAhsDAh4BAheABQJKfFpnBBUKCQgACgkQYhHr8e+637xk
+ PQf/aOi78XenwwvFrwXOVIVTdZIf8rK1zJksf26h09UD8uVV6z5iiTcpn86+eN9p
+ 6Ar8IH3tD+JuFnPSwZ/r9MNC2XZwenYo4Gb14jqM6/9hBe328vmeM4Y1G7bD4HrL
+ kgV5WEyokqm3zbp3FBLr3Vh68TAC5JB9aHevra+cCA2u3vBNI3YUM5z4TdO150P3
+ J00whkqImQEUni8bgxvllBLFM+uhucsX3HZWkoDEpotbg8yd0bqMkiPEyMr1OnJq
+ eDVDMrB5wnyLgLFfRAAw3mopM0C1PNOAHr/BIYiaDHX2OwnOfep8rMDoRVf2Ge0D
+ DBgsJJ6LduQHLeg403SHWL2F6YkCHAQTAQIABgUCQYPWUgAKCRBcD5boTsFta+r9
+ EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU8WIcFO1A
+ 59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18hmqqwNlKY
+ 97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8cr+C9HTs1
+ Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65MbJGlwWp
+ w/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt4XkS51yW
+ ZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2USyLI+mm9d
+ iMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5MnplTWwi
+ 40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMPoueF9mKZ
+ Cf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqMACFuTNdB
+ sjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsqoTJ8asY2
+ VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2ZohGBBARAgAGBQJMGVc1
+ AAoJEKY/LL36AvvMgsoAn2G7kXd09BF7ffk1Sfh174SVrvM9AKC7+R7x0+yV3SCd
+ JkkUOo3xR5cOxw==
+ =1QuR
+ -----END PGP PUBLIC KEY BLOCK-----
diff --git a/doc/pgpkeys.asc b/doc/pgpkeys.asc
deleted file mode 100644
index 378230f32..000000000
--- a/doc/pgpkeys.asc
+++ /dev/null
@@ -1,83 +0,0 @@
------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/doc/pubkey.txt b/doc/pubkey.txt
new file mode 100644
index 000000000..6ff016038
--- /dev/null
+++ b/doc/pubkey.txt
@@ -0,0 +1,541 @@
+
+Public Key Cryptography
+=================================
+
+Public key cryptography (also called assymmetric cryptography) is a collection
+of techniques allowing for encryption, signatures, and key agreement.
+
+Key Objects
+----------------------------------------
+
+Public and private keys are represented by classes ``Public_Key`` and it's
+subclass ``Private_Key``. The use of inheritence here means that a
+``Private_Key`` can be converted into a reference to a public key.
+
+None of the functions on ``Public_Key`` and ``Private_Key`` itself are
+particularly useful for users of the library, because 'bare' public key
+operations are *very insecure*. The only purpose of these functions is to
+provide a clean interface that higher level operations can be built on. So
+really the only thing you need to know is that when a function takes a
+reference to a ``Public_Key``, it can take any public key or private key, and
+similiarly for ``Private_Key``.
+
+Types of ``Public_Key`` include ``RSA_PublicKey``, ``DSA_PublicKey``,
+``ECDSA_PublicKey``, ``DH_PublicKey``, ``ECDH_PublicKey``, ``RW_PublicKey``,
+``NR_PublicKey``,, and ``GOST_3410_PublicKey``. There are cooresponding
+``Private_Key`` classes for each of these algorithms.
+
+.. _creating_new_private_keys:
+
+Creating New Private Keys
+----------------------------------------
+
+Creating a new private key requires two things: a source of random numbers
+(see :ref:`random_number_generators`) and some algorithm specific parameters
+that define the *security level* of the resulting key. For instance, the
+security level of an RSA key is (at least in part) defined by the length of
+the public key modulus in bits. So to create a new RSA private key, you would
+call
+
+.. cpp:function:: RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, size_t bits)
+
+ A constructor that creates a new random RSA private key with a modulus
+ of length *bits*.
+
+Algorithms based on the discrete-logarithm problem uses what is called a
+*group*; a group can safely be used with many keys, and for some operations,
+like key agreement, the two keys *must* use the same group. There are
+currently two kinds of discrete logarithm groups supported in botan: the
+integers modulo a prime, represented by :ref:`dl_group`, and elliptic curves
+in GF(p), represented by :ref:`ec_group`. A rough generalization is that the
+larger the group is, the more secure the algorithm is, but coorespondingly the
+slower the operations will be.
+
+Given a ``DL_Group``, you can create new DSA, Diffie-Hellman, and
+Nyberg-Rueppel key pairs with
+
+.. cpp:function:: DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+.. cpp:function:: ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, \
+ const DL_Group& group, const BigInt& x = 0)
+
+ The optional *x* parameter to each of these contructors is a private key
+ value. This allows you to create keys where the private key is formed by
+ some special technique; for instance you can use the hash of a password (see
+ :ref:`pbkdf` for how to do that) as a private key value. Normally, you would
+ leave the value as zero, letting the class generate a new random key.
+
+Finally, given an ``EC_Group`` object, you can create a new ECDSA,
+ECDH, or GOST 34.10-2001 private key with
+
+.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, \
+ const EC_Group& domain, const BigInt& x = 0)
+
+
+Generating RSA keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This example will 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), either encrypted or
+unencrypted depending on if a password was given.
+
+.. literalinclude:: examples/rsa_kgen.cpp
+
+Generate DSA keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This example generates a 2048 bit DSA key
+
+.. literalinclude:: examples/dsa_kgen.cpp
+
+
+.. _serializing_private_keys:
+
+Serializing Private Keys Using PKCS #8
+----------------------------------------
+
+The standard format for serializing a private key is PKCS #8, the operations
+for which are defined in ``pkcs8.h``. It supports both unencrypted and
+encrypted storage.
+
+.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key, \
+ RandomNumberGenerator& rng, const std::string& password, const std::string& pbe_algo = "")
+
+ Takes any private key object, serializes it, encrypts it using
+ *password*, and returns a binary structure representing the private
+ key.
+
+ The final (optional) argument, *pbe_algo*, specifies a particular
+ password based encryption (or PBE) algorithm. If you don't specify a
+ PBE, a sensible default will be used.
+
+.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key, \
+ RandomNumberGenerator& rng, const std::string& pass, const std::string& pbe_algo = "")
+
+ This formats the key in the same manner as ``BER_encode``, but additionally
+ encodes it into a text format with identifying headers. Using PEM encoding
+ is *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.
+
+Unencrypted serialization is also supported.
+
+.. warning::
+
+ In most situations, using unecrypted private key storage 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, described above.
+
+.. cpp:function:: SecureVector<byte> PKCS8::BER_encode(const Private_Key& key)
+
+ Serializes the private key and returns the result.
+
+.. cpp:function:: std::string PKCS8::PEM_encode(const Private_Key& key)
+
+ Serializes the private key, base64 encodes it, and returns the
+ result.
+
+Last but not least, there are some functions that will load (and
+decrypt, if necessary) a PKCS #8 private key:
+
+.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, \
+ RandomNumberGenerator& rng, const User_Interface& ui)
+
+.. cpp:function:: Private_Key* PKCS8::load_key(DataSource& in, \
+ RandomNumberGenerator& rng, std::string passphrase = "")
+
+.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, \
+ RandomNumberGenerator& rng, const User_Interface& ui)
+
+.. cpp:function:: Private_Key* PKCS8::load_key(const std::string& filename, \
+ RandomNumberGenerator& rng, const std::string& passphrase = "")
+
+These functions will return an object allocated key object based on the data
+from whatever source it is using (assuming, of course, the source is in fact
+storing a representation of a private key, and the decryption was
+sucessful). The encoding used (PEM or BER) need not be specified; the format
+will be detected automatically. The key is allocated with ``new``, and should
+be released with ``delete`` when you are done with it. The first takes a
+generic ``DataSource`` that you have to create - the other is a simple wrapper
+functions that take either a filename or a memory buffer and create the
+appropriate ``DataSource``.
+
+The versions taking a ``std::string`` attempt to decrypt using the password
+given (if the key is encrypted; if it is not, the passphase value will be
+ignored). If the passphrase does not decrypt the key, an exception will be
+thrown.
+
+The ones taking a ``User_Interface`` provide a simple callback interface which
+makes handling incorrect passphrases and such a bit simpler. A
+``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.
+
+.. note::
+
+ In a future version, it is likely that ``User_Interface`` will be
+ replaced by a simple callback using ``std::function``.
+
+To use ``User_Interface``, derive a subclass and implement:
+
+.. cpp:function:: std::string User_Interface::get_passphrase(const std::string& what, \
+ const std::string& source, UI_Result& result) const
+
+ The ``what`` argument specifies what the passphrase is needed for (for
+ example, PKCS #8 key loading passes ``what`` as "PKCS #8 private key"). This
+ lets you provide the user with some indication of *why* your application is
+ asking for a passphrase; feel free to pass the string through ``gettext(3)``
+ or moral equivalent for i18n purposes. Similarly, ``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 ``source`` will be an
+ empty string; be sure to account for this possibility.
+
+ The function returns the passphrase as the return value, and a status code
+ in ``result`` (either ``OK`` or ``CANCEL_ACTION``). If ``CANCEL_ACTION`` is
+ returned in ``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 ``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).
+
+.. _serializing_public_keys:
+
+Serializing Public Keys
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To import and export public keys, use:
+
+.. cpp:function:: MemoryVector<byte> X509::BER_encode(const Public_Key& key)
+
+.. cpp:function:: std::string X509::PEM_encode(const Public_Key& key)
+
+.. cpp:function:: Public_Key* X509::load_key(DataSource& in)
+
+.. cpp:function:: Public_Key* X509::load_key(const SecureVector<byte>& buffer)
+
+.. cpp:function:: Public_Key* X509::load_key(const std::string& filename)
+
+ These functions operate in the same way as the ones described in
+ :ref:`serializing_private_keys`, except that no encryption option is
+ availabe.
+
+.. _dl_group:
+
+DL_Group
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As described in :ref:`creating_new_private_keys`, a discrete logarithm group
+can be shared among many keys, even keys created by users who do not trust
+each other. However, it is necessary to trust the entity who created the
+group; that is why organization like NIST use algorithms which generate groups
+in a deterministic way such that creating a bogus group would require breaking
+some trusted cryptographic primitive like SHA-2.
+
+Instantiating a ``DL_Group`` simply requires calling
+
+.. cpp:function:: DL_Group::DL_Group(const std::string& name)
+
+ The *name* parameter is a specially formatted string that consists of three
+ things, the type of the group ("modp" or "dsa"), the creator of the group,
+ and the size of the group in bits, all delimited by '/' characters.
+
+ Currently all "modp" groups included in botan are ones defined by the
+ Internet Engineering Task Force, so the provider is "ietf", and the strings
+ look like "modp/ietf/N" where N can be any of 768, 1024, 1536, 2048, 3072,
+ 4096, 6144, or 8192. This group type is used for Diffie-Hellman and ElGamal
+ algorithms.
+
+ The other type, "dsa" is used for DSA and Nyberg-Rueppel keys. They can
+ also be used with Diffie-Hellman and ElGamal, but this is less common. The
+ currently available groups are "dsa/jce/N" for N in 512, 768, or 1024, and
+ "dsa/botan/N" with N being 2048 or 3072. The "jce" groups are the standard
+ DSA groups used in the Java Cryptography Extensions, while the "botan"
+ groups were randomly generated using the FIPS 186-3 algorithm by the library
+ maintainers.
+
+You can generate a new random group using
+
+.. cpp:function:: DL_Group::DL_Group(RandomNumberGenerator& rng, \
+ PrimeType type, size_t pbits, size_t qbits = 0)
+
+ The *type* can be either ``Strong``, ``Prime_Subgroup``, or
+ ``DSA_Kosherizer``. *pbits* specifies the size of the prime in
+ bits. If the *type* is ``Prime_Subgroup`` or ``DSA_Kosherizer``,
+ then *qbits* specifies the size of the subgroup.
+
+You can serialize a ``DL_Group`` using
+
+.. cpp:function:: SecureVector<byte> DL_Group::DER_Encode(Format format)
+
+or
+
+.. cpp:function:: std::string DL_Group::PEM_encode(Format format)
+
+where *format* is any of
+
+* ``ANSI_X9_42`` (or ``DH_PARAMETERS``) for modp groups
+* ``ANSI_X9_57`` (or ``DSA_PARAMETERS``) for DSA-style groups
+* ``PKCS_3`` is an older format for modp groups; it should only
+ be used for backwards compatability.
+
+You can reload a serialized group using
+
+.. cpp:function:: void DL_Group::BER_decode(DataSource& source, Format format)
+
+.. cpp:function:: void DL_Group::PEM_decode(DataSource& source)
+
+.. _ec_group:
+
+EC_Group
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An ``EC_Group`` is initialized by passing the name of the
+group to be used to the constructor. These groups have
+semi-standardized names like "secp256r1" and "brainpool512r1".
+
+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 public key type has a function
+
+.. cpp:function:: bool Public_Key::check_key(RandomNumberGenerator& rng, bool strong)
+
+ This function performs a number of algorithm-specific tests that the key
+ seems to be mathematically valid and consistent, and returns true if all of
+ the tests pass.
+
+ 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 *strong* is ``true``, then it does "strong" checking, which
+ includes expensive operations like primality checking.
+
+Encryption
+---------------------------------
+
+Safe public key encryption requires the use of a padding scheme which hides
+the underlying mathematical properties of the algorithm. Additionally, they
+will add randomness, so encrypting the same plaintext twice produces two
+different ciphertexts.
+
+The primary interface for encryption is
+
+.. cpp:class:: PK_Encryptor
+
+ .. cpp:function:: SecureVector<byte> encrypt( \
+ const byte* in, size_t length, RandomNumberGenerator& rng) const
+
+ .. cpp:function:: SecureVector<byte> encrypt( \
+ const MemoryRegion<byte>& in, RandomNumberGenerator& rng) const
+
+ These encrypt a message, returning the ciphertext.
+
+ .. cpp:function:: size_t maximum_input_size() const
+
+ Returns the maximum size of the message that can be processed, in
+ bytes. If you call :cpp:func:`PK_Encryptor::encrypt` with a value larger
+ than this the operation will fail with an exception.
+
+:cpp:class:`PK_Encryptor` is only an interface - to actually encrypt you have
+to create an implementation, of which there are currently two available in the
+library, :cpp:class:`PK_Encryptor_EME` and :cpp:class:`DLIES_Encryptor`. DLIES
+is a standard method (from IEEE 1363) that uses a key agreement technique such
+as DH or ECDH to perform message encryption. Normally, public key encryption
+is done using algorithms which support it directly, such as RSA or ElGamal;
+these use the EME class:
+
+.. cpp:class:: PK_Encryptor_EME
+
+ .. cpp:function:: PK_Encryptor_EME(const Public_Key& key, std::string eme)
+
+ With *key* being the key you want to encrypt messages to. The padding
+ method to use is specified in *eme*.
+
+ The recommended values for *eme* is "EME1(SHA-1)" or "EME1(SHA-256)". If
+ you need compatability with protocols using the PKCS #1 v1.5 standard,
+ you can also use "EME-PKCS1-v1_5".
+
+.. cpp:class:: DLIES_Encryptor
+
+ Available in the header ``dlies.h``
+
+ .. cpp:function:: DLIES_Encryptor(const PK_Key_Agreement_Key& key, \
+ KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20)
+
+ Where *kdf* is a key derivation function (see
+ :ref:`key_derivation_function`) and *mac* is a
+ MessageAuthenticationCode.
+
+The decryption classes are named ``PK_Decryptor``, ``PK_Decryptor_EME``, and
+``DLIES_Decryptor``. They are created in the exact same way, except they take
+the private key, and the processing function is named ``decrypt``.
+
+
+Signatures
+---------------------------------
+
+Signature generation is performed using
+
+.. cpp:class:: PK_Signer
+
+ .. cpp:function:: PK_Signer(const Private_Key& key, \
+ const std::string& emsa, \
+ Signature_Format format = IEEE_1363)
+
+ Constructs a new signer object for the private key *key* using the
+ signature format *emsa*. The key must support signature operations. In
+ the current version of the library, this includes RSA, DSA, ECDSA, GOST
+ 34.10-2001, Nyberg-Rueppel, and Rabin-Williams. Other signature schemes
+ may be supported in the future.
+
+ Currently available values for *emsa* 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. The Raw encoding signs the
+ input directly; if the message is too big, the signing operation will
+ fail. Raw is not useful except in very specialized applications. Examples
+ are "EMSA1(SHA-1)" and "EMSA4(SHA-256)".
+
+ For RSA, use EMSA4 (also called PSS) unless you need compatability with
+ software that uses the older PKCS #1 v1.5 standard, in which case use
+ EMSA3 (also called "EMSA-PKCS1-v1_5"). For DSA, ECDSA, GOST 34.10-2001,
+ and Nyberg-Rueppel, you should use EMSA1.
+
+ The *format* defaults to ``IEEE_1363`` which is the only available
+ format for RSA. For DSA and ECDSA, you can also use
+ ``DER_SEQUENCE``, which will format the signature as an ASN.1
+ SEQUENCE value.
+
+ .. cpp:function:: void update(const byte* in, size_t length)
+ .. cpp:function:: void update(const MemoryRegion<byte>& in)
+ .. cpp:function:: void update(byte in)
+
+ These add more data to be included in the signature
+ computation. Typically, the input will be provided directly to a
+ hash function.
+
+ .. cpp:function:: SecureVector<byte> signature(RandomNumberGenerator& rng)
+
+ Creates the signature and returns it
+
+ .. cpp:function:: SecureVector<byte> sign_message( \
+ const byte* in, size_t length, RandomNumberGenerator& rng)
+
+ .. cpp:function:: SecureVector<byte> sign_message( \
+ const MemoryRegion<byte>& in, RandomNumberGenerator& rng)
+
+ These functions are equivalent to calling
+ :cpp:func:`PK_Signer::update` and then
+ :cpp:func:`PK_Signer::signature`. Any data previously provided
+ using ``update`` will be included.
+
+Signatures are verified using
+
+.. cpp:class:: PK_Verifier
+
+ .. cpp:function:: PK_Verifier(const Public_Key& pub_key, \
+ const std::string& emsa, Signature_Format format = IEEE_1363)
+
+ Construct a new verifier for signatures assicated with public
+ key *pub_key*. The *emsa* and *format* should be the same as
+ that used by the signer.
+
+ .. cpp:function:: void update(const byte* in, size_t length)
+ .. cpp:function:: void update(const MemoryRegion<byte>& in)
+ .. cpp:function:: void update(byte in)
+
+ Add further message data that is purportedly assocated with the
+ signature that will be checked.
+
+ .. cpp:function:: bool check_signature(const byte* sig, size_t length)
+ .. cpp:function:: bool check_signature(const MemoryRegion<byte>& sig)
+
+ Check to see if *sig* is a valid signature for the message data
+ that was written in. Return true if so. This function clears the
+ internal message state, so after this call you can call
+ :cpp:func:`PK_Verifier::update` to start verifying another
+ message.
+
+ .. cpp:function:: bool verify_message(const byte* msg, size_t msg_length, \
+ const byte* sig, size_t sig_length)
+
+ .. cpp:function:: bool verify_message(const MemoryRegion<byte>& msg, \
+ const MemoryRegion<byte>& sig)
+
+ These are equivalent to calling :cpp:func:`PK_Verifier::update`
+ on *msg* and then calling :cpp:func:`PK_Verifier::check_signature`
+ on *sig*.
+
+Here is an example of DSA signature generation
+
+.. literalinclude:: examples/dsa_sign.cpp
+
+Here is an example that verifies DSA signatures
+
+.. literalinclude:: examples/dsa_ver.cpp
+
+Key Agreement
+---------------------------------
+
+You can get a hold of a ``PK_Key_Agreement_Scheme`` object by calling
+``get_pk_kas`` with a key that is of a type that supports key
+agreement (such as a Diffie-Hellman key stored in a ``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 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
+``derive_key`` with either a byte array/length pair, or a
+``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 KDF you're using, you *might not* get back a key
+of the size you requested. 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
+``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
+``public_data``, which exists for any key that is associated with a
+key agreement algorithm. It returns a ``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.
+
+An example of using Diffie-Hellman:
+
+.. literalinclude:: examples/dh.cpp
diff --git a/doc/python.tex b/doc/python.tex
deleted file mode 100644
index afdd66b6a..000000000
--- a/doc/python.tex
+++ /dev/null
@@ -1,68 +0,0 @@
-\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 Python Interface Documentation}}
-\author{Jack Lloyd \\
- \texttt{[email protected]}}
-\date{2009/10/10}
-
-\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{Ciphers}
-
-Botan's Python interface provides a generic interface to any cipher
-supported by the library. The class \type{botan.Cipher} takes three
-arguments, all strings: first, the name of the algorith, second the
-direction (which can be either ``encrypt'' or ``decrypt''), and
-lastly, the key to use. For instance
-
-\begin{verbatim}
- encryptor = botan.Cipher("AES-128/EAX", "encrypt", key)
-\end{verbatim}
-
-creates an object that will encrypt and authenticate messages using
-the EAX mode of operation using the AES cipher. To use this object,
-call the \function{cipher} function with two arguments - the input
-to encrypt, and the IV to use:
-
-\begin{verbatim}
- ciphertext = encryptor.cipher(input, salt)
-\end{verbatim}
-
-
-\subsection{Cryptobox}
-
-
-\subsection{RNGs}
-
-\section{RSA}
-
-
-
-\end{document}
diff --git a/doc/rng.txt b/doc/rng.txt
new file mode 100644
index 000000000..66679271d
--- /dev/null
+++ b/doc/rng.txt
@@ -0,0 +1,129 @@
+.. _random_number_generators:
+
+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 the same seed (ie, two
+``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 create a random number generator, instantiate a ``AutoSeeded_RNG``
+object. This object will handle choosing the right algorithms from the
+set of enabled ones and doing seeding using OS specific
+routines. The main service a RandomNumberGenerator provides is, of
+course, random numbers:
+
+.. cpp:function:: byte RandomNumberGenerator::random()
+
+ Generates a single random byte and returns it
+
+.. cpp:function:: void RandomNumberGenerator::randomize(byte* data, size_t length)
+
+ Places *length* bytes into the array pointed to by *data*
+
+To ensure good quality output, a PRNG needs to be seeded with truly
+random data. Normally this is done for you. However it may happen that
+your application has access to data that is potentially unpredictable
+to an attacker. If so, use
+
+.. cpp:function:: void RandomNumberGenerator::add_entropy(const byte* data, \
+ size_t length)
+
+which incorporates the data into the current randomness state. Don't
+worry about filtering the data or doing any kind of cryptographic
+preprocessing (such as hashing); the RNG objects in botan are designed
+such that you can feed them any arbitrary non-random or even
+maliciously chosen data - as long as at some point some of the seed
+data was good the output will be secure.
+
+
+Implementation Notes
+----------------------------------------
+
+Randpool
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``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
+``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.
+
+``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 ``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).
+
+ANSI X9.31
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``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 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.
+
+
+Entropy Sources
+---------------------------------
+
+An ``EntropySource`` is an abstract representation of some method of
+gather "real" entropy. This tends to be very system dependent. The
+*only* way you should use an ``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!
+
+``EntropySource`` has a pair of functions for getting entropy from
+some external source, called ``fast_poll`` and ``slow_poll``. These
+pass a buffer of bytes to be written; the functions then return how
+many bytes of entropy were gathered.
+
+Note for writers of ``EntropySource`` subclasses: 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 ``RandomNumberGenerator`` that asked for the
+entropy, thus any hashing you do will be wasteful of both CPU cycles
+and entropy.
+
diff --git a/doc/scripts/comba.py b/doc/scripts/comba.py
deleted file mode 100755
index ce3cfed77..000000000
--- a/doc/scripts/comba.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/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/doc/scripts/combine_bmarks.pl b/doc/scripts/combine_bmarks.pl
deleted file mode 100755
index b6436496e..000000000
--- a/doc/scripts/combine_bmarks.pl
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/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/doc/scripts/dist.sh b/doc/scripts/dist.sh
deleted file mode 100755
index 479de24d1..000000000
--- a/doc/scripts/dist.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-
-# This is probably only useful if run on my machine, which is not
-# exactly ideal
-
-SELECTOR=h:net.randombit.botan
-KEY_ID=EFBADFBC
-MTN_DB=/storage/mtn/botan.mtn
-DIST_DIR=~/Botan-dist
-
-DIST_FILES_DIR=$HOME/projects/www/files/botan/v1.9/
-WEB_DOCS_DIR=$HOME/projects/www/htdocs/botan/htdocs/
-
-# 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 python
-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
-
-botan_log_to_html log.txt > ../../log.html
-
-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* Botan-$VERSION.tbz* $DIST_FILES_DIR
-mv log.html $WEB_DOCS_DIR
-
-echo "Now edit download.html, and add a release notice to pyblosxom"
diff --git a/doc/scripts/print_deps.py b/doc/scripts/print_deps.py
deleted file mode 100755
index c68fa2617..000000000
--- a/doc/scripts/print_deps.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/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).replace('internal/', '')
-
-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/doc/scripts/update_deps.py b/doc/scripts/update_deps.py
deleted file mode 100755
index ac19885e0..000000000
--- a/doc/scripts/update_deps.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/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 len(lines) > 0 and 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/doc/secmem.txt b/doc/secmem.txt
new file mode 100644
index 000000000..eba3462de
--- /dev/null
+++ b/doc/secmem.txt
@@ -0,0 +1,81 @@
+
+Secure Memory Containers
+========================================
+
+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 ``mlock`` 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 ``setuid`` ``root``, and then drop privileges
+immediately after creating your ``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 ``root``
+all the time.
+
+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 ``std::vector``, since these objects know how to clear
+themselves when they are destroyed. You cannot, however, have a
+``std::vector`` (or any other container) of ``Pipe`` objects or
+filters, because these types have pointers to other filters, 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 ``secmem.h`` and
+``allocate.h``.
+
+``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
+``clear()``, and ``size_t`` ``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:
+``SecureBuffer<byte, 8> key;``).
+
+``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 ``SecureBuffer``, it implements
+``clear`` and ``size``.
+
+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 ``allocate.h``. Code needing to
+allocate or deallocate memory calls ``get_allocator``, which returns a
+pointer to an allocator object. This pointer should not be freed: the
+caller does not own the allocator (it is shared among multiple
+allocatore users, and uses a mutex to serialize access internally if
+necessary). It is possible to call ``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 ``Default_Allocator``,
+which just allocates memory using ``malloc``, and zeroizes it 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 ``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 ``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,
+``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.
diff --git a/doc/ssl.txt b/doc/ssl.txt
new file mode 100644
index 000000000..adca78bf8
--- /dev/null
+++ b/doc/ssl.txt
@@ -0,0 +1,58 @@
+
+.. _ssl_api:
+
+SSL and TLS
+========================================
+
+.. versionadded:: 1.9.4
+
+Botan supports both client and server implementations of the SSL/TLS
+protocols, including SSL v3, TLS v1.0, and TLS v1.1. The insecure and
+obsolete SSL v2 is not supported.
+
+The implementation uses ``std::tr1::function``, so it may not have
+been compiled into the version you are using; you can test for the
+feature macro ``BOTAN_HAS_SSL_TLS`` to check.
+
+TLS Clients
+----------------------------------------
+
+.. cpp:class:: TLS_Client
+
+ .. cpp:function:: TLS_Client( \
+ std::tr1::function<size_t (byte*, size_t)> input_fn, \
+ std::tr1::function<void (const byte*, size_t)> output_fn, \
+ const TLS_Policy& policy, RandomNumberGenerator& rng)
+
+ Creates a TLS client. It will call *input_fn* to read bytes from
+ the network and call *output_fn* when bytes need to be written to
+ the network.
+
+ .. cpp:function:: size_t read(byte* buf, size_t buf_len)
+
+ Reads up to *buf_len* bytes from the open connection into *buf*,
+ returning the number of bytes actually written.
+
+ .. cpp:function:: void write(const byte* buf, size_t buf_len)
+
+ Writes *buf_len* bytes in *buf* to the remote side
+
+ .. cpp:function:: void close()
+
+ Closes the connection
+
+ .. cpp:function:: std::vector<X509_Certificate> peer_cert_chain()
+
+ Returns the certificate chain of the server
+
+A simple TLS client example:
+
+.. literalinclude:: examples/tls_client.cpp
+
+
+TLS Servers
+----------------------------------------
+
+A simple TLS server
+
+.. literalinclude:: examples/tls_server.cpp
diff --git a/doc/support.txt b/doc/support.txt
new file mode 100644
index 000000000..288ed8aa0
--- /dev/null
+++ b/doc/support.txt
@@ -0,0 +1,19 @@
+
+Commercial Support Options
+========================================
+
+Commercial support is currently available for Botan from a couple of
+sources. If you provide services related to Botan, email the
+development list and your information can be added here.
+
+* `FlexSecure GmbH <http://www.flexsecure.de>`_ offers support for
+ both Botan and `InSiTo <http://www.flexsecure.eu/insito/>`_
+ libraries. Developers from FlexSecure have done extensive work
+ with Botan in the past, and many new features to Botan have been
+ implemented and contributed by them. More information at
+ http://www.flexsecure.eu/insito/support.html
+
+* `Jack Lloyd <http://www.randombit.net>`_ can provide services
+ relating to Botan including performance analysis of application
+ code using Botan, review of cryptographic use and designs for
+ security flaws, and implementing new features.
diff --git a/doc/thanks.txt b/doc/thanks.txt
deleted file mode 100644
index 68fd81b3b..000000000
--- a/doc/thanks.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-
-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
-via public domain code which has been repurposed into the library:
-
- Dean Gaudet wrote the SSE2 implementation of SHA-1
-
- Mike Hamburg wrote x86-64/SSSE3 assembly which was the basis for the
- constant time AES implementation
-
- 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 its 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/doc/tutorial.tex b/doc/tutorial.tex
deleted file mode 100644
index 840679d10..000000000
--- a/doc/tutorial.tex
+++ /dev/null
@@ -1,141 +0,0 @@
-\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{[email protected]}}
-\date{2010/08/07}
-
-\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.
-
-\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.
-
-\begin{verbatim}
-#include <botan/botan.h>
-
-int main()
- {
- Botan::LibraryInitializer init;
- return 0;
- }
-\end{verbatim}
-
-If your application is multi-threaded, you need to tell botan this so
-that it will use locking where necessary. This is done by passing a
-string to the constructor of \type{LibraryInitializer}:
-
-\begin{verbatim}
- Botan::LibraryInitializer init("thread_safe=yes");
-\end{verbatim}
-
-\section{Introduction to Pipe}
-
-Most operations in botan are specified in terms of transformations on
-streams. The class that handles the I/O and management for these
-streams is called \type{Pipe}. You can construct a \type{Pipe} with
-one or more \type{Filter}s, which sequentially process messages. You
-can only update a single message at a time, but you can leave the
-final output contents in a \type{Pipe} and read them out as desired.
-
-Here is how you might hex encode two messages:
-
-\begin{verbatim}
- std::string message1 = "this is the first message";
- const byte message2[] = "a second message";
- Pipe pipe(new Hex_Encoder);
-
- pipe.start_msg(); // must be called before writing to the pipe
- pipe.write(message1);
- pipe.end_msg(); // must be called to signal completion
-
- /*
- process_msg(x) is equivalent to calling
- start_msg(); write(x); end_msg();
- */
- pipe.process_msg(message2);
-
- Pipe::message_id n = pipe.message_count(); // returns 2
-
- /* you can read a message as a string, here we read message 0 */
- std::string first_result = pipe.read_all_as_string(0);
-
- /* or a piece at a time using array/length, now we'll read the
- second message (message id 1)
- */
-
- byte output[4096] = { 0 };
- u32bit got = read(output, sizeof(output), 1);
- if(got >= sizeof(output))
- // have to read again to get more of the message
-\end{verbatim}
-
-You can also read output while the message is still active (before the
-call to \function{end\_msg}), using the same interfaces. You can find
-out how much data is currently available for a particular \type{Pipe}
-by calling the member function \function{remaining}, which takes a
-message sequence number and returns the number of bytes that are
-currently available to read from that message.
-
-\section{Hashing a File}
-
-Hashing a file is done using a \type{Hash\_Filter}, which takes a string
-which specifies which hash function you want to use:
-
-\begin{verbatim}
- Pipe pipe(new Hash_Filter("SHA-256"));
-\end{verbatim}
-
-The output of a \type{Hash\_Filter} is raw binary. The filter will not
-produce any output at all until you call \function{end\_msg}.
-
-\section{Symmetric Cryptography}
-
-
-
-\subsection{Authentication}
-
-\subsection{User Authentication}
-
-\section{Public Key Cryptography}
-
-
-\end{document}
diff --git a/doc/users.txt b/doc/users.txt
new file mode 100644
index 000000000..4c743b137
--- /dev/null
+++ b/doc/users.txt
@@ -0,0 +1,111 @@
+
+Known Users
+========================================
+
+This is a list of some of the known users of botan. If you'd like to
+be added to the list, email the development list.
+
+Open Source Software
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* `SoftHSM <http://trac.opendnssec.org/wiki/SoftHSM>`_ an open sourced
+ software PKCS #11 implementation, which is used as part of the
+ `OpenDNSSEC <http://www.opendnssec.org>`_ project.
+
+* `Qt Creator <http://qt.nokia.com/products/developer-tools>`_, an
+ IDE for building Qt applications.
+
+* `NetSieben's <http://netsieben.com/products/ssh/>`_
+ SSH library provides SSHv2 client connections for C++
+ applications, using botan for the crypto. (GPL or commercial)
+
+* `InSiTo <http://www.flexsecure.eu/insito/index.html>`_ is a library
+ for ePassports based on botan which was commissioned by the German
+ Federal Office for Information Security.
+
+* `QCA <http://delta.affinix.com/qca/>`_, the Qt Cryptographic
+ Architecture (part of KDE4) uses parts of botan as an `embedded
+ crypto provider
+ <http://websvn.kde.org/trunk/kdesupport/qca/src/botantools/botan/>`_.
+
+* `Octopod <http://code.google.com/p/octopod/>`_ is a
+ file sharing system.
+
+* `Silverlock <http://www.petroules.com/products/silverlock/>`_
+ is a GPL password management tool for Windows, OS X, and Linux.</p>
+
+* `Monotone <http://monotone.ca/>`_, a free distributed
+ version control system, uses botan for RSA authentication,
+ content hashing, and message authentication.
+
+* `Publimark <http://www.gleguelv.org/soft/publimark/index.html>`_
+ is a tool for hiding messages in an audio file.
+
+* `KeySafe <http://therning.org/magnus/computer/keysafe>`_,
+ a password application for GNOME
+
+* `SuSE <http://gcc.opensuse.org>`_ uses botan as part
+ of a test suite for the GCC optimizer.
+
+* `Openbench <http://www.exactcode.de/site/open_source/openbench/>`_,
+ an open source benchmark suite, uses botan as a component.
+
+* `VNCcrack <http://www.randombit.net/code/vnccrack/>`_
+ is a password cracker for the VNC authentication/response protocol.
+
+Commercial Software
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* `Hulu Desktop <http://www.hulu.com/labs/hulu-desktop>`_ uses botan
+ on Windows `(ref)
+ <http://download.hulu.com/HuluDesktop_ThirdPartyLicenses.txt>`_.
+
+* `Hitman Pro <http://www.surfright.nl/en>`_ is a malware
+ scanner for Windows.
+
+* `Flying Lab Software <http://www.burningsea.com>`_, a Seattle based
+ game developer, uses botan as a part of their user authentication
+ process.
+
+* `CryptoTE <http://idlebox.net/2009/cryptote/>`_ is a text editor
+ with integrated strong cryptography.
+
+* `TextEgg <http://www.textegg.com/>`_ is an encrypted document editor.
+
+* `Seagate <http://www.seagate.com/www/en-us/support/downloads/>`_
+ uses botan for the drive encryption in the Maxtor OneTouch III Mini
+ Edition hard drive.
+
+* `Aegeus Technology Ltd <http://www.aegeus-technology.com>`_ used
+ botan in a research implementation of SPKI.
+
+* `E.V.E. Paradox <http://www.entropicsoftware.com/eve/eve.html>`_, a
+ suite of games for Windows.
+
+Research Projects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* `A Unified Approach to Intra-Domain Security
+ <http://www.csiir.ornl.gov/shue/research/securecom09.pdf>`_
+ describes a system by researches from Oak Ridge National Lab and
+ Indiana University that uses botan to secure ARP and DHCP.
+
+* `CLL: A Cryptographic Link Layer for Local Area Networks
+ <http://www.springerlink.com/content/c4681m76808l4621/>`_ describes
+ a network encryption system using botan. (One of the coauthors, Yves
+ Jerschow, also contributed a number of optimizations to the
+ library).
+
+* The system described in `Enabling Intrusion Detection in IPsec
+ Protected IPv6 Networks Through Secret-key Sharing
+ <http://www.stormingmedia.us/01/0151/A015134.pdf>`_
+
+* `An experimental tamper detection system
+ <http://www.cis.udel.edu/~hiper/passages/papers/jochenMILCOM03.pdf>`_
+ designed by researchers from the University of Delaware and the US
+ Army Research Laboratory.
+
+* A prototype implementation of a telephony signal security system,
+ described in `Prototyping and evaluation of TCAPsec
+ <http://www.cs.kau.se/cs/education/courses/davddiss/Uppsatser_2007/D2007-04.pdf>`_
+ by Kang Chung and Mathilda Gustafsson.
diff --git a/doc/x509.txt b/doc/x509.txt
new file mode 100644
index 000000000..d31a84498
--- /dev/null
+++ b/doc/x509.txt
@@ -0,0 +1,527 @@
+
+.. _x509_certificates:
+
+Certificate Handling
+=================================
+
+A certificate is a binding between some identifying information
+(called a *subject*) and a public key. This binding is asserted by a
+signature on the certificate, which is placed there by some authority
+(the *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
+``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 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, 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
+``x509cert.h`` and ``asn1_obj.h`` (which has the definitions of various common
+ASN.1 constructs used in X.509).
+
+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 ``subject_public_key``, which will return a
+``Public_Key``\*. As to what to do with this, read about ``load_key`` in
+:ref:`serializing_public_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, DSA, and ECDSA keys are also supported, so be careful about how
+you treat this. It is also a wise idea to examine the value returned by
+``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...) different places where you
+can stick information about the user: the *subject* field, and in an extension
+called *subjectAlternativeName*. The *subject* field is supposed to only
+included the following information: country, organization, an organizational
+sub-unit name, 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 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 *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
+... 255), an exception will get thrown. Currently the ``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 ``std::wstring`` instead of a ``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 likely never
+want to use). However, there are three very useful pieces of information that
+this extension might hold: an email address ([email protected]), a DNS name
+(somehost.example.com), or a URI (http://www.example.com).
+
+So, how to get the information? Call ``subject_info`` with the name of the
+piece of information you want, and it will return a ``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 ``std::string``.
+
+You can also get information about the issuer of the certificate in the same
+way, using ``issuer_info``.
+
+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.
+
+ - Key Usage and Extended Key Usage: No problems known.
+
+ - 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.
+
+ - Subject Alternative Names: Only the "rfc822Name", "dNSName", and
+ "uniformResourceIdentifier" fields will be stored; all others are
+ ignored.
+
+ - Issuer Alternative Names: Same restrictions as the Subject
+ Alternative Names extension. New certificates generated by Botan
+ never include the issuer alternative name.
+
+ - 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.
+
+ - Subject Key Identifier: No problems known.
+
+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). Every once in a while the CA will release a new 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 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 ``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::
+
+ X509_CRL crl1("crl1.der");
+
+ DataSource_Stream in("crl2.pem");
+ X509_CRL crl2(in);
+
+After that, pass the ``X509_CRL`` object to a ``X509_Store`` object
+with
+
+.. cpp:function:: X509_Code X509_Store::add_crl(const X509_CRL& crl)
+
+and all future verifications will take into account the certificates
+listed, assuming ``add_crl`` returns ``VERIFIED``. If it doesn't
+return ``VERIFIED``, then the return value is an error code signifying
+that the CRL could not be processed due to some problem (which could
+be something like the issuing certificate could not being found, an
+invalid signature, or the CRL having some format problem). For more
+about the ``X509_Store`` API, read :ref:`x509_store`.
+
+Reading Certificates
+---------------------------------
+
+``X509_Certificate`` has two constructors, each of which takes a source of
+data; a filename to read, and a ``DataSource&``::
+
+ 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
+
+.. _x509_store:
+
+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: ``X509_Store``.
+
+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).
+
+Adding Certificates
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can add new certificates to a certificate store using any of these
+functions:
+
+.. cpp:function:: void X509_Store::add_cert(const X509_Certificate& cert, \
+ bool trusted = false)
+
+.. cpp:function:: void X509_Store::add_cert(DataSource& source)
+
+.. cpp:function:: void X509_Store::add_trusted_certs(DataSource& source)
+
+The versions that take a ``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 are willing to trust for certification purposes. 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.
+
+Adding CRLs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. cpp:function:: X509_Code X509_Store::add_crl(const X509_CRL& 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 ``VERIFIED`` if everything completed
+successfully.
+
+Storing Certificates
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can output a set of certificates by calling ``PEM_encode``, which
+will return a ``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.
+
+Certificate Stores
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An object of 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 return an empty ``std::vector`` of
+``X509_Certificate``. This storage mechanism is *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 ``by_SKID`` (Subject Key Identifier),
+``by_name`` (the CommonName DN entry), and ``by_email`` (stored in either the
+distinguished name, or in a subjectAlternativeName extension). The name and
+email versions take a ``std::string``, while the SKID version takes a
+``SecureVector<byte>`` containing the subject key identifier in raw binary. You
+can choose not to implement ``by_name`` or ``by_email``, but ``by_SKID`` is
+mandatory to implement, and, currently, is the only version that is used by
+``X509_Store``.
+
+Finally, there is a method for finding CRLs, called ``get_crls_for``, that
+takes an ``X509_Certificate`` object, and returns a ``std::vector`` of
+``X509_CRL``. While normally 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 ``X509_CRL``.
+
+As for using such a store, you have to tell ``X509_Store`` about it
+with
+
+.. cpp:function:: void X509_Store::add_new_certstore(Certificate_Store* new_store)
+
+ The store object will be owned by (and deleted by) ``X509_Store``,
+ so make sure to allocate it with ``new``.
+
+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
+
+.. cpp:class:: X509_Store
+
+.. cpp:type:: Cert_Usage
+
+ Can be any of:
+ * ``ANY`` (any usage is OK)
+ * ``CRL_SIGNING``
+ * ``TLS_SERVER`` (for SSL/TLS server authentication)
+ * ``TLS_CLIENT`` (for SSL/TLS client authentication)
+ * ``CODE_SIGNING``
+ * ``EMAIL_PROTECTION`` (usually this means S/MIME)
+ * ``TIME_STAMPING`` (in theory any time stamp application,
+ usually IETF PKIX's Time Stamp Protocol)
+
+.. cpp:function:: X509_Code validate_cert(const X509_Certificate& cert, \
+ Cert_Usage usage = ANY)
+
+ Return ``VERIFIED`` if the certificate can safely be considered
+ valid for the usage(s) described by *usage*, and an error code if
+ it is not.
+
+First, how does :cpp:class`X509_Store::validate_cert` know if a certificate is
+valid? 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 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.
+
+The default ``ANY`` does not mean valid for any use, it means "is valid for
+some usage". This is usually what you want; 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 ``validate_cert`` (and ``add_crl``) include:
+
+* VERIFIED: The certificate is valid for the specified use.
+* INVALID_USAGE: The certificate cannot be used for the specified use.
+
+* CANNOT_ESTABLISH_TRUST: The root certificate was not marked as trusted.
+
+* CERT_CHAIN_TOO_LONG: The certificate chain exceeded the length
+ allowed by a basicConstraints extension.
+
+* SIGNATURE_ERROR: An invalid signature was found
+
+* POLICY_ERROR: Some problem with the certificate policies was found.
+
+* CERT_FORMAT_ERROR: Some format problem was found in a certificate.
+* CERT_ISSUER_NOT_FOUND: The issuer of a certificate could not be found.
+* CERT_NOT_YET_VALID: The certificate is not yet valid.
+* CERT_HAS_EXPIRED: The certificate has expired.
+* CERT_IS_REVOKED: The certificate has been revoked.
+* CRL_FORMAT_ERROR: Some format problem was found in a CRL.
+* CRL_ISSUER_NOT_FOUND: The issuer of a CRL could not be found.
+* CRL_NOT_YET_VALID: The CRL is not yet valid.
+* CRL_HAS_EXPIRED: The CRL has expired.
+* CA_CERT_CANNOT_SIGN: The CA certificate found does not have an
+ contain a public key that allows signature verification.
+* CA_CERT_NOT_FOR_CERT_ISSUER: The CA cert found is not allowed to
+ issue certificates.
+* CA_CERT_NOT_FOR_CRL_ISSUER: The CA cert found is not allowed to
+ issue CRLs.
+* UNKNOWN_X509_ERROR: Some other error occurred.
+
+Certificate Authorities
+---------------------------------
+
+Setting up a CA for X.509 certificates is perhaps the easiest thing to
+do related to X.509. A CA is represented by the type ``X509_CA``,
+which can be found in ``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:
+
+.. cpp:function:: X509_CA::X509_CA(const X509_Certificate& cert, \
+ const Private_Key& key)
+
+The private key is the private key corresponding to the public key in the
+CA's certificate.
+
+Requests for new certificates are supplied to a CA in the form on PKCS
+#10 certificate requests (called a ``PKCS10_Request`` object in
+Botan). These are decoded in a similar manner to
+certificates/CRLs/etc. A request is vetted by humans (who somehow
+verify that the name in the request corresponds to the name of the
+entity who requested it), and then signed by a CA key, generating a
+new certificate:
+
+.. cpp:function:: X509_Certificate \
+ X509_CA::sign_request(const PKCS10_Request& req) const
+
+Here's an example:
+
+.. literalinclude examples/ca.cpp
+
+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. Never fear; empty CRLs, which revoke nothing at all, can
+be issued. To generate a new, empty CRL, just call
+
+.. cpp:function:: X509_CRL X509_CA::new_crl(u32bit seconds_to_expiration = 0)
+
+ This function will return a new, empty CRL. The
+ ``seconds_to_expiration`` parameter is the number of seconds before
+ the CRL expires. If it is set to the (default) value of zero, then a
+ reasonable default (currently 7 days) will be used.
+
+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
+
+.. cpp:function:: X509_CRL X509_CA::update_crl(const X509_CRL& old_crl, \
+ std::vector<CRL_Entry> new_revoked, size_t seconds_to_expiration = 0)
+
+ Where ``X509_CRL`` is the last CRL this CA issued, and
+ ``new_revoked`` is a list of any newly revoked certificates. The
+ function returns a new ``X509_CRL`` to make available for
+ clients.
+
+The ``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
+``SecureVector<byte>`` called ``serial``. There are two additional (optional)
+values, an enumeration called ``CRL_Code`` that specifies the reason for
+revocation (``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 ``reason`` code of ``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.
+
+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. The library
+provides a utility function for this:
+
+.. cpp:function:: X509_Certificate create_self_signed_cert( \
+ const X509_Cert_Options& opts, const Private_Key& key)
+
+ Where *key* is the private key you wish to use (the public key,
+ used in the certificate itself, is extracted from the private key),
+ and *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).
+
+An example:
+
+.. literalinclude:: examples/self_sig.cpp
+
+Creating PKCS #10 Requests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Also in ``x509self.h``, there is a function for generating new PKCS #10
+certificate requests:
+
+.. cpp:function:: PKCS10_Request create_cert_req( \
+ const X509_Cert_Options& opts, const Private_Key& key)
+
+This function acts quite similarly to
+:cpp:func:`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.
+
+An example:
+
+.. literalinclude:: examples/pkcs10.cpp
+
+Certificate Options
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+What is this ``X509_Cert_Options`` thing we've been passing around? It's a
+class representing 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 ``std::string`` members, which contains
+various bits of information about the user: ``common_name``, ``serial_number``,
+``country``, ``organization``, ``org_unit``, ``locality``, ``state``,
+``email``, ``dns_name``, and ``uri``. As many of these as possible should be
+filled it (especially an email address), though the only required ones are
+``common_name`` and ``country``.
+
+There is another value that is only useful when creating a PKCS #10 request,
+which is called ``challenge``. This is a challenge password, which you can
+later use to request certificate revocation (*if* the CA supports doing
+revocations in this manner).
+
+Then there is the validity period; these are set with ``not_before`` and
+``not_after``. Both of these functions also take a ``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 ``CA_key``. This should only be used when needed.
+
+Other constraints can be set by calling the member functions
+``add_constraints`` and ``add_ex_constraints``. The first takes a
+``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):
+``DIGITAL_SIGNATURE``, ``NON_REPUDIATION``, ``KEY_ENCIPHERMENT``,
+``DATA_ENCIPHERMENT``, ``KEY_AGREEMENT``, ``KEY_CERT_SIGN``, ``CRL_SIGN``,
+``ENCIPHER_ONLY``, ``DECIPHER_ONLY``. Many of these have quite special
+semantics, so you should either consult the appropriate standards document
+(such as RFC 3280), or just not call ``add_constraints``, in which case the
+appropriate values will be chosen for you.
+
+The second 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 "add_ex_constraints" any number of times -
+each new OID will be added to the list to include in the certificate.
diff --git a/readme.txt b/readme.txt
index fde088312..ef6f2c77d 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,30 +1,15 @@
-Botan 1.9.15-dev, ????-??-??
+Botan 1.10.0, Not Yet Released
http://botan.randombit.net/
Botan is a C++ class library for performing a wide variety of
-cryptographic operations.
+cryptographic operations. It is released under the 2 clause BSD
+license; see doc/license.txt for the specifics. You can file bugs in
+Bugzilla (http://bugs.randombit.net/) or by sending a report to the
+botan-devel mailing list. More information about the mailing list is
+at http://lists.randombit.net/mailman/listinfo/botan-devel/
-Botan is released under the FreeBSD license (see doc/license.txt for
-the specifics). More information about the authors and contributors
-can be found in doc/credits.txt and doc/thanks.txt.
+You can find documentation online at http://botan.randombit.net/docs
+and http://botan.randombit.net/doxygen. A set of example programs can
+be found in the examples directory.
-You can file bugs at http://bugs.randombit.net/ 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.
-You can also find Doxygen generated documentation online at
- http://botan.randombit.net/doxygen
-
-Check the project website 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.
-
-As always, feel free to contact me with any questions or comments.
-
- - Jack Lloyd ([email protected])
+Jack Lloyd ([email protected])
diff --git a/src/alloc/alloc_mmap/mmap_mem.cpp b/src/alloc/alloc_mmap/mmap_mem.cpp
index 78177bcdd..e4b602764 100644
--- a/src/alloc/alloc_mmap/mmap_mem.cpp
+++ b/src/alloc/alloc_mmap/mmap_mem.cpp
@@ -85,20 +85,22 @@ void* MemoryMapping_Allocator::alloc_block(size_t n)
if(file.get_fd() == -1)
throw MemoryMapping_Failed("Could not create file");
- std::vector<byte> zeros(n);
+ std::vector<byte> zeros(4096);
- ssize_t remaining = n;
+ size_t remaining = n;
while(remaining)
{
- ssize_t wrote_here = ::write(file.get_fd(),
- &zeros[0],
- remaining);
+ const size_t write_try = std::min(zeros.size(), remaining);
- if(wrote_here == -1 && errno != EINTR)
+ ssize_t wrote_got = ::write(file.get_fd(),
+ &zeros[0],
+ write_try);
+
+ if(wrote_got == -1 && errno != EINTR)
throw MemoryMapping_Failed("Could not write to file");
- remaining -= wrote_here;
+ remaining -= wrote_got;
}
#ifndef MAP_NOSYNC
diff --git a/src/alloc/secmem.h b/src/alloc/secmem.h
index b06be0d55..80e8e59aa 100644
--- a/src/alloc/secmem.h
+++ b/src/alloc/secmem.h
@@ -34,7 +34,6 @@ class MemoryRegion
*/
bool empty() const { return (used == 0); }
-#if 1
/**
* Get a pointer to the first element in the buffer.
* @return pointer to the first element in the buffer
@@ -46,12 +45,6 @@ class MemoryRegion
* @return constant pointer to the first element in the buffer
*/
operator const T* () const { return buf; }
-#else
-
- T& operator[](size_t n) { return buf[n]; }
- const T& operator[](size_t n) const { return buf[n]; }
-
-#endif
/**
* Get a pointer to the first element in the buffer.
diff --git a/src/asn1/alg_id.cpp b/src/asn1/alg_id.cpp
index b48db3e50..665e42fb3 100644
--- a/src/asn1/alg_id.cpp
+++ b/src/asn1/alg_id.cpp
@@ -41,8 +41,12 @@ AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id,
const byte DER_NULL[] = { 0x05, 0x00 };
oid = alg_id;
+
if(option == USE_NULL_PARAM)
- parameters += std::make_pair(DER_NULL, sizeof(DER_NULL));
+ {
+ parameters += std::make_pair<const byte*, size_t>(
+ DER_NULL, sizeof(DER_NULL));
+ }
}
/*
@@ -54,8 +58,12 @@ AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id,
const byte DER_NULL[] = { 0x05, 0x00 };
oid = OIDS::lookup(alg_id);
+
if(option == USE_NULL_PARAM)
- parameters += std::make_pair(DER_NULL, sizeof(DER_NULL));
+ {
+ parameters += std::make_pair<const byte*, size_t>(
+ DER_NULL, sizeof(DER_NULL));
+ }
}
/*
diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp
index 9fb12cd11..5f47762a8 100644
--- a/src/block/aes/aes.cpp
+++ b/src/block/aes/aes.cpp
@@ -2,6 +2,8 @@
* AES
* (C) 1999-2010 Jack Lloyd
*
+* Based on the public domain reference implemenation
+*
* Distributed under the terms of the Botan license
*/
diff --git a/src/block/aes_intel/aes_intel.cpp b/src/block/aes_ni/aes_ni.cpp
index a2e660f2c..3ee0e608c 100644
--- a/src/block/aes_intel/aes_intel.cpp
+++ b/src/block/aes_ni/aes_ni.cpp
@@ -1,11 +1,11 @@
/*
-* AES using Intel's AES-NI instructions
+* AES using AES-NI instructions
* (C) 2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/aes_intel.h>
+#include <botan/aes_ni.h>
#include <botan/loadstor.h>
#include <wmmintrin.h>
@@ -103,7 +103,7 @@ __m128i aes_256_key_expansion(__m128i key, __m128i key2)
/*
* AES-128 Encryption
*/
-void AES_128_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_128_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -179,7 +179,7 @@ void AES_128_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-128 Decryption
*/
-void AES_128_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_128_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -255,7 +255,7 @@ void AES_128_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-128 Key Schedule
*/
-void AES_128_Intel::key_schedule(const byte key[], size_t)
+void AES_128_NI::key_schedule(const byte key[], size_t)
{
#define AES_128_key_exp(K, RCON) \
aes_128_key_expansion(K, _mm_aeskeygenassist_si128(K, RCON))
@@ -304,7 +304,7 @@ void AES_128_Intel::key_schedule(const byte key[], size_t)
/*
* Clear memory of sensitive data
*/
-void AES_128_Intel::clear()
+void AES_128_NI::clear()
{
zeroise(EK);
zeroise(DK);
@@ -313,7 +313,7 @@ void AES_128_Intel::clear()
/*
* AES-192 Encryption
*/
-void AES_192_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_192_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -395,7 +395,7 @@ void AES_192_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-192 Decryption
*/
-void AES_192_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_192_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -477,7 +477,7 @@ void AES_192_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-192 Key Schedule
*/
-void AES_192_Intel::key_schedule(const byte key[], size_t)
+void AES_192_NI::key_schedule(const byte key[], size_t)
{
__m128i K0 = _mm_loadu_si128((const __m128i*)(key));
__m128i K1 = _mm_loadu_si128((const __m128i*)(key + 8));
@@ -520,7 +520,7 @@ void AES_192_Intel::key_schedule(const byte key[], size_t)
/*
* Clear memory of sensitive data
*/
-void AES_192_Intel::clear()
+void AES_192_NI::clear()
{
zeroise(EK);
zeroise(DK);
@@ -529,7 +529,7 @@ void AES_192_Intel::clear()
/*
* AES-256 Encryption
*/
-void AES_256_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_256_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -617,7 +617,7 @@ void AES_256_Intel::encrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-256 Decryption
*/
-void AES_256_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
+void AES_256_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
const __m128i* in_mm = (const __m128i*)in;
__m128i* out_mm = (__m128i*)out;
@@ -705,7 +705,7 @@ void AES_256_Intel::decrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* AES-256 Key Schedule
*/
-void AES_256_Intel::key_schedule(const byte key[], size_t)
+void AES_256_NI::key_schedule(const byte key[], size_t)
{
__m128i K0 = _mm_loadu_si128((const __m128i*)(key));
__m128i K1 = _mm_loadu_si128((const __m128i*)(key + 16));
@@ -770,7 +770,7 @@ void AES_256_Intel::key_schedule(const byte key[], size_t)
/*
* Clear memory of sensitive data
*/
-void AES_256_Intel::clear()
+void AES_256_NI::clear()
{
zeroise(EK);
zeroise(DK);
diff --git a/src/block/aes_intel/aes_intel.h b/src/block/aes_ni/aes_ni.h
index a8e6b53e8..ae9e5b3f4 100644
--- a/src/block/aes_intel/aes_intel.h
+++ b/src/block/aes_ni/aes_ni.h
@@ -1,12 +1,12 @@
/*
-* AES using Intel's AES-NI instructions
+* AES using AES-NI instructions
* (C) 2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_AES_INTEL_H__
-#define BOTAN_AES_INTEL_H__
+#ifndef BOTAN_AES_NI_H__
+#define BOTAN_AES_NI_H__
#include <botan/block_cipher.h>
@@ -15,7 +15,7 @@ namespace Botan {
/**
* AES-128 using AES-NI
*/
-class BOTAN_DLL AES_128_Intel : public Block_Cipher_Fixed_Params<16, 16>
+class BOTAN_DLL AES_128_NI : public Block_Cipher_Fixed_Params<16, 16>
{
public:
size_t parallelism() const { return 4; }
@@ -25,9 +25,9 @@ class BOTAN_DLL AES_128_Intel : public Block_Cipher_Fixed_Params<16, 16>
void clear();
std::string name() const { return "AES-128"; }
- BlockCipher* clone() const { return new AES_128_Intel; }
+ BlockCipher* clone() const { return new AES_128_NI; }
- AES_128_Intel() : EK(44), DK(44) { }
+ AES_128_NI() : EK(44), DK(44) { }
private:
void key_schedule(const byte[], size_t);
@@ -37,7 +37,7 @@ class BOTAN_DLL AES_128_Intel : public Block_Cipher_Fixed_Params<16, 16>
/**
* AES-192 using AES-NI
*/
-class BOTAN_DLL AES_192_Intel : public Block_Cipher_Fixed_Params<16, 24>
+class BOTAN_DLL AES_192_NI : public Block_Cipher_Fixed_Params<16, 24>
{
public:
size_t parallelism() const { return 4; }
@@ -47,9 +47,9 @@ class BOTAN_DLL AES_192_Intel : public Block_Cipher_Fixed_Params<16, 24>
void clear();
std::string name() const { return "AES-192"; }
- BlockCipher* clone() const { return new AES_192_Intel; }
+ BlockCipher* clone() const { return new AES_192_NI; }
- AES_192_Intel() : EK(52), DK(52) { }
+ AES_192_NI() : EK(52), DK(52) { }
private:
void key_schedule(const byte[], size_t);
@@ -59,7 +59,7 @@ class BOTAN_DLL AES_192_Intel : public Block_Cipher_Fixed_Params<16, 24>
/**
* AES-256 using AES-NI
*/
-class BOTAN_DLL AES_256_Intel : public Block_Cipher_Fixed_Params<16, 32>
+class BOTAN_DLL AES_256_NI : public Block_Cipher_Fixed_Params<16, 32>
{
public:
size_t parallelism() const { return 4; }
@@ -69,9 +69,9 @@ class BOTAN_DLL AES_256_Intel : public Block_Cipher_Fixed_Params<16, 32>
void clear();
std::string name() const { return "AES-256"; }
- BlockCipher* clone() const { return new AES_256_Intel; }
+ BlockCipher* clone() const { return new AES_256_NI; }
- AES_256_Intel() : EK(60), DK(60) { }
+ AES_256_NI() : EK(60), DK(60) { }
private:
void key_schedule(const byte[], size_t);
diff --git a/src/block/aes_intel/info.txt b/src/block/aes_ni/info.txt
index 8bf0f07ee..597948fc3 100644
--- a/src/block/aes_intel/info.txt
+++ b/src/block/aes_ni/info.txt
@@ -1,4 +1,4 @@
-define AES_INTEL
+define AES_NI
load_on auto
diff --git a/src/block/aes_ssse3/aes_ssse3.cpp b/src/block/aes_ssse3/aes_ssse3.cpp
index c5869f899..774ccbabb 100644
--- a/src/block/aes_ssse3/aes_ssse3.cpp
+++ b/src/block/aes_ssse3/aes_ssse3.cpp
@@ -339,10 +339,10 @@ __m128i aes_ssse3_decrypt(__m128i B, const __m128i* keys, size_t rounds)
*/
void AES_128_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&EK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&EK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -356,10 +356,10 @@ void AES_128_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void AES_128_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&DK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&DK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -376,10 +376,10 @@ void AES_128_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81,
0x1F8391B9, 0xAF9DEEB6);
- __m128i key = _mm_loadu_si128((const __m128i*)keyb);
+ __m128i key = _mm_loadu_si128(reinterpret_cast<const __m128i*>(keyb));
- __m128i* EK_mm = (__m128i*)&EK[0];
- __m128i* DK_mm = (__m128i*)&DK[0];
+ __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
+ __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
_mm_storeu_si128(DK_mm + 10, _mm_shuffle_epi8(key, sr[2]));
@@ -408,10 +408,10 @@ void AES_128_SSSE3::key_schedule(const byte keyb[], size_t)
*/
void AES_192_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&EK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&EK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -425,10 +425,10 @@ void AES_192_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void AES_192_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&DK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&DK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -445,11 +445,11 @@ void AES_192_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81,
0x1F8391B9, 0xAF9DEEB6);
- __m128i* EK_mm = (__m128i*)&EK[0];
- __m128i* DK_mm = (__m128i*)&DK[0];
+ __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
+ __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
- __m128i key1 = _mm_loadu_si128((const __m128i*)keyb);
- __m128i key2 = _mm_loadu_si128((const __m128i*)(keyb + 8));
+ __m128i key1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(keyb));
+ __m128i key2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((keyb + 8)));
_mm_storeu_si128(DK_mm + 12, _mm_shuffle_epi8(key1, sr[0]));
@@ -507,10 +507,10 @@ void AES_192_SSSE3::key_schedule(const byte keyb[], size_t)
*/
void AES_256_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&EK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&EK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -524,10 +524,10 @@ void AES_256_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const
*/
void AES_256_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
- const __m128i* in_mm = (const __m128i*)in;
- __m128i* out_mm = (__m128i*)out;
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
- const __m128i* keys = (const __m128i*)&DK[0];
+ const __m128i* keys = reinterpret_cast<const __m128i*>(&DK[0]);
for(size_t i = 0; i != blocks; ++i)
{
@@ -544,11 +544,11 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t)
__m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81,
0x1F8391B9, 0xAF9DEEB6);
- __m128i* EK_mm = (__m128i*)&EK[0];
- __m128i* DK_mm = (__m128i*)&DK[0];
+ __m128i* EK_mm = reinterpret_cast<__m128i*>(&EK[0]);
+ __m128i* DK_mm = reinterpret_cast<__m128i*>(&DK[0]);
- __m128i key1 = _mm_loadu_si128((const __m128i*)keyb);
- __m128i key2 = _mm_loadu_si128((const __m128i*)(keyb + 16));
+ __m128i key1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(keyb));
+ __m128i key2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((keyb + 16)));
_mm_storeu_si128(DK_mm + 14, _mm_shuffle_epi8(key1, sr[2]));
diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp
index 739dfe87c..c500e9bab 100644
--- a/src/block/des/des.cpp
+++ b/src/block/des/des.cpp
@@ -2,6 +2,9 @@
* DES
* (C) 1999-2008 Jack Lloyd
*
+* Based on a public domain implemenation by Phil Karn (who in turn
+* credited Richard Outerbridge and Jim Gillogly)
+*
* Distributed under the terms of the Botan license
*/
diff --git a/src/block/idea_sse2/idea_sse2.cpp b/src/block/idea_sse2/idea_sse2.cpp
index f2c770103..70698560d 100644
--- a/src/block/idea_sse2/idea_sse2.cpp
+++ b/src/block/idea_sse2/idea_sse2.cpp
@@ -16,7 +16,6 @@ inline __m128i mul(__m128i X, u16bit K_16)
{
const __m128i zeros = _mm_set1_epi16(0);
const __m128i ones = _mm_set1_epi16(1);
- const __m128i high_bit = _mm_set1_epi16(-32767); // 0x8000
const __m128i K = _mm_set1_epi16(K_16);
@@ -29,10 +28,9 @@ inline __m128i mul(__m128i X, u16bit K_16)
__m128i T = _mm_sub_epi16(mul_lo, mul_hi);
// Unsigned compare; cmp = 1 if mul_lo < mul_hi else 0
- const __m128i cmp = _mm_srli_epi16(_mm_cmpgt_epi16(
- _mm_add_epi16(mul_hi, high_bit),
- _mm_add_epi16(mul_lo, high_bit)),
- 15);
+ const __m128i subs = _mm_subs_epu16(mul_hi, mul_lo);
+ const __m128i cmp = _mm_min_epu8(
+ _mm_or_si128(subs, _mm_srli_epi16(subs, 8)), ones);
T = _mm_add_epi16(T, cmp);
@@ -131,10 +129,12 @@ void transpose_out(__m128i& B0, __m128i& B1, __m128i& B2, __m128i& B3)
*/
void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52])
{
- __m128i B0 = _mm_loadu_si128((const __m128i*)in);
- __m128i B1 = _mm_loadu_si128((const __m128i*)in + 1);
- __m128i B2 = _mm_loadu_si128((const __m128i*)in + 2);
- __m128i B3 = _mm_loadu_si128((const __m128i*)in + 3);
+ const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
+
+ __m128i B0 = _mm_loadu_si128(in_mm + 0);
+ __m128i B1 = _mm_loadu_si128(in_mm + 1);
+ __m128i B2 = _mm_loadu_si128(in_mm + 2);
+ __m128i B3 = _mm_loadu_si128(in_mm + 3);
transpose_in(B0, B1, B2, B3);
@@ -183,10 +183,12 @@ void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52])
transpose_out(B0, B2, B1, B3);
- _mm_storeu_si128((__m128i*)out, B0);
- _mm_storeu_si128((__m128i*)out + 1, B2);
- _mm_storeu_si128((__m128i*)out + 2, B1);
- _mm_storeu_si128((__m128i*)out + 3, B3);
+ __m128i* out_mm = reinterpret_cast<__m128i*>(out);
+
+ _mm_storeu_si128(out_mm + 0, B0);
+ _mm_storeu_si128(out_mm + 1, B2);
+ _mm_storeu_si128(out_mm + 2, B1);
+ _mm_storeu_si128(out_mm + 3, B3);
}
}
diff --git a/src/block/noekeon_simd/info.txt b/src/block/noekeon_simd/info.txt
index b73954cff..deac80702 100644
--- a/src/block/noekeon_simd/info.txt
+++ b/src/block/noekeon_simd/info.txt
@@ -2,6 +2,6 @@ define NOEKEON_SIMD
<requires>
noekeon
-simd_32
+simd
simd_engine
</requires>
diff --git a/src/block/noekeon_simd/noekeon_simd.cpp b/src/block/noekeon_simd/noekeon_simd.cpp
index 97158593a..b2beafc82 100644
--- a/src/block/noekeon_simd/noekeon_simd.cpp
+++ b/src/block/noekeon_simd/noekeon_simd.cpp
@@ -16,7 +16,12 @@ namespace Botan {
#define NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3) \
do { \
SIMD_32 T = A0 ^ A2; \
- T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ SIMD_32 T_l8 = T; \
+ SIMD_32 T_r8 = T; \
+ T_l8.rotate_left(8); \
+ T_r8.rotate_right(8); \
+ T ^= T_l8; \
+ T ^= T_r8; \
A1 ^= T; \
A3 ^= T; \
\
@@ -26,7 +31,12 @@ namespace Botan {
A3 ^= K3; \
\
T = A1 ^ A3; \
- T ^= rotate_left(T, 8) ^ rotate_right(T, 8); \
+ T_l8 = T; \
+ T_r8 = T; \
+ T_l8.rotate_left(8); \
+ T_r8.rotate_right(8); \
+ T ^= T_l8; \
+ T ^= T_r8; \
A0 ^= T; \
A2 ^= T; \
} while(0)
diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp
index 1d940cf39..b3cf0f6c9 100644
--- a/src/block/serpent/serpent.cpp
+++ b/src/block/serpent/serpent.cpp
@@ -2,6 +2,9 @@
* Serpent
* (C) 1999-2007 Jack Lloyd
*
+* The sbox expressions used here were discovered by Dag Arne Osvik and
+* are described in his paper "Speeding Up Serpent".
+*
* Distributed under the terms of the Botan license
*/
diff --git a/src/block/serpent_simd/info.txt b/src/block/serpent_simd/info.txt
index b3bf34972..cd1a0dc7e 100644
--- a/src/block/serpent_simd/info.txt
+++ b/src/block/serpent_simd/info.txt
@@ -2,7 +2,7 @@ define SERPENT_SIMD
<requires>
serpent
-simd_32
+simd
simd_engine
</requires>
@@ -13,7 +13,3 @@ serp_simd.cpp
<header:public>
serp_simd.h
</header:public>
-
-<header:internal>
-serp_simd_sbox.h
-</header:internal>
diff --git a/src/block/serpent_simd/serp_simd.cpp b/src/block/serpent_simd/serp_simd.cpp
index babe68d40..2b5e429fc 100644
--- a/src/block/serpent_simd/serp_simd.cpp
+++ b/src/block/serpent_simd/serp_simd.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/serp_simd.h>
-#include <botan/internal/serp_simd_sbox.h>
#include <botan/internal/simd_32.h>
#include <botan/loadstor.h>
@@ -14,6 +13,420 @@ namespace Botan {
namespace {
+#define SBoxE1(B0, B1, B2, B3) \
+ do { \
+ B3 ^= B0; \
+ SIMD_32 B4 = B1; \
+ B1 &= B3; \
+ B4 ^= B2; \
+ B1 ^= B0; \
+ B0 |= B3; \
+ B0 ^= B4; \
+ B4 ^= B3; \
+ B3 ^= B2; \
+ B2 |= B1; \
+ B2 ^= B4; \
+ B4 = ~B4; \
+ B4 |= B1; \
+ B1 ^= B3; \
+ B1 ^= B4; \
+ B3 |= B0; \
+ B1 ^= B3; \
+ B4 ^= B3; \
+ B3 = B0; \
+ B0 = B1; \
+ B1 = B4; \
+ } while(0);
+
+#define SBoxE2(B0, B1, B2, B3) \
+ do { \
+ B0 = ~B0; \
+ B2 = ~B2; \
+ SIMD_32 B4 = B0; \
+ B0 &= B1; \
+ B2 ^= B0; \
+ B0 |= B3; \
+ B3 ^= B2; \
+ B1 ^= B0; \
+ B0 ^= B4; \
+ B4 |= B1; \
+ B1 ^= B3; \
+ B2 |= B0; \
+ B2 &= B4; \
+ B0 ^= B1; \
+ B1 &= B2; \
+ B1 ^= B0; \
+ B0 &= B2; \
+ B4 ^= B0; \
+ B0 = B2; \
+ B2 = B3; \
+ B3 = B1; \
+ B1 = B4; \
+ } while(0);
+
+#define SBoxE3(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B0; \
+ B0 &= B2; \
+ B0 ^= B3; \
+ B2 ^= B1; \
+ B2 ^= B0; \
+ B3 |= B4; \
+ B3 ^= B1; \
+ B4 ^= B2; \
+ B1 = B3; \
+ B3 |= B4; \
+ B3 ^= B0; \
+ B0 &= B1; \
+ B4 ^= B0; \
+ B1 ^= B3; \
+ B1 ^= B4; \
+ B0 = B2; \
+ B2 = B1; \
+ B1 = B3; \
+ B3 = ~B4; \
+ } while(0);
+
+#define SBoxE4(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B0; \
+ B0 |= B3; \
+ B3 ^= B1; \
+ B1 &= B4; \
+ B4 ^= B2; \
+ B2 ^= B3; \
+ B3 &= B0; \
+ B4 |= B1; \
+ B3 ^= B4; \
+ B0 ^= B1; \
+ B4 &= B0; \
+ B1 ^= B3; \
+ B4 ^= B2; \
+ B1 |= B0; \
+ B1 ^= B2; \
+ B0 ^= B3; \
+ B2 = B1; \
+ B1 |= B3; \
+ B0 ^= B1; \
+ B1 = B2; \
+ B2 = B3; \
+ B3 = B4; \
+ } while(0);
+
+#define SBoxE5(B0, B1, B2, B3) \
+ do { \
+ B1 ^= B3; \
+ B3 = ~B3; \
+ B2 ^= B3; \
+ B3 ^= B0; \
+ SIMD_32 B4 = B1; \
+ B1 &= B3; \
+ B1 ^= B2; \
+ B4 ^= B3; \
+ B0 ^= B4; \
+ B2 &= B4; \
+ B2 ^= B0; \
+ B0 &= B1; \
+ B3 ^= B0; \
+ B4 |= B1; \
+ B4 ^= B0; \
+ B0 |= B3; \
+ B0 ^= B2; \
+ B2 &= B3; \
+ B0 = ~B0; \
+ B4 ^= B2; \
+ B2 = B0; \
+ B0 = B1; \
+ B1 = B4; \
+ } while(0);
+
+#define SBoxE6(B0, B1, B2, B3) \
+ do { \
+ B0 ^= B1; \
+ B1 ^= B3; \
+ B3 = ~B3; \
+ SIMD_32 B4 = B1; \
+ B1 &= B0; \
+ B2 ^= B3; \
+ B1 ^= B2; \
+ B2 |= B4; \
+ B4 ^= B3; \
+ B3 &= B1; \
+ B3 ^= B0; \
+ B4 ^= B1; \
+ B4 ^= B2; \
+ B2 ^= B0; \
+ B0 &= B3; \
+ B2 = ~B2; \
+ B0 ^= B4; \
+ B4 |= B3; \
+ B4 ^= B2; \
+ B2 = B0; \
+ B0 = B1; \
+ B1 = B3; \
+ B3 = B4; \
+ } while(0);
+
+#define SBoxE7(B0, B1, B2, B3) \
+ do { \
+ B2 = ~B2; \
+ SIMD_32 B4 = B3; \
+ B3 &= B0; \
+ B0 ^= B4; \
+ B3 ^= B2; \
+ B2 |= B4; \
+ B1 ^= B3; \
+ B2 ^= B0; \
+ B0 |= B1; \
+ B2 ^= B1; \
+ B4 ^= B0; \
+ B0 |= B3; \
+ B0 ^= B2; \
+ B4 ^= B3; \
+ B4 ^= B0; \
+ B3 = ~B3; \
+ B2 &= B4; \
+ B3 ^= B2; \
+ B2 = B4; \
+ } while(0);
+
+#define SBoxE8(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B1; \
+ B1 |= B2; \
+ B1 ^= B3; \
+ B4 ^= B2; \
+ B2 ^= B1; \
+ B3 |= B4; \
+ B3 &= B0; \
+ B4 ^= B2; \
+ B3 ^= B1; \
+ B1 |= B4; \
+ B1 ^= B0; \
+ B0 |= B4; \
+ B0 ^= B2; \
+ B1 ^= B4; \
+ B2 ^= B1; \
+ B1 &= B0; \
+ B1 ^= B4; \
+ B2 = ~B2; \
+ B2 |= B0; \
+ B4 ^= B2; \
+ B2 = B1; \
+ B1 = B3; \
+ B3 = B0; \
+ B0 = B4; \
+ } while(0);
+
+#define SBoxD1(B0, B1, B2, B3) \
+ do { \
+ B2 = ~B2; \
+ SIMD_32 B4 = B1; \
+ B1 |= B0; \
+ B4 = ~B4; \
+ B1 ^= B2; \
+ B2 |= B4; \
+ B1 ^= B3; \
+ B0 ^= B4; \
+ B2 ^= B0; \
+ B0 &= B3; \
+ B4 ^= B0; \
+ B0 |= B1; \
+ B0 ^= B2; \
+ B3 ^= B4; \
+ B2 ^= B1; \
+ B3 ^= B0; \
+ B3 ^= B1; \
+ B2 &= B3; \
+ B4 ^= B2; \
+ B2 = B1; \
+ B1 = B4; \
+ } while(0);
+
+#define SBoxD2(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B1; \
+ B1 ^= B3; \
+ B3 &= B1; \
+ B4 ^= B2; \
+ B3 ^= B0; \
+ B0 |= B1; \
+ B2 ^= B3; \
+ B0 ^= B4; \
+ B0 |= B2; \
+ B1 ^= B3; \
+ B0 ^= B1; \
+ B1 |= B3; \
+ B1 ^= B0; \
+ B4 = ~B4; \
+ B4 ^= B1; \
+ B1 |= B0; \
+ B1 ^= B0; \
+ B1 |= B4; \
+ B3 ^= B1; \
+ B1 = B0; \
+ B0 = B4; \
+ B4 = B2; \
+ B2 = B3; \
+ B3 = B4; \
+ } while(0);
+
+#define SBoxD3(B0, B1, B2, B3) \
+ do { \
+ B2 ^= B3; \
+ B3 ^= B0; \
+ SIMD_32 B4 = B3; \
+ B3 &= B2; \
+ B3 ^= B1; \
+ B1 |= B2; \
+ B1 ^= B4; \
+ B4 &= B3; \
+ B2 ^= B3; \
+ B4 &= B0; \
+ B4 ^= B2; \
+ B2 &= B1; \
+ B2 |= B0; \
+ B3 = ~B3; \
+ B2 ^= B3; \
+ B0 ^= B3; \
+ B0 &= B1; \
+ B3 ^= B4; \
+ B3 ^= B0; \
+ B0 = B1; \
+ B1 = B4; \
+ } while(0);
+
+#define SBoxD4(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B2; \
+ B2 ^= B1; \
+ B0 ^= B2; \
+ B4 &= B2; \
+ B4 ^= B0; \
+ B0 &= B1; \
+ B1 ^= B3; \
+ B3 |= B4; \
+ B2 ^= B3; \
+ B0 ^= B3; \
+ B1 ^= B4; \
+ B3 &= B2; \
+ B3 ^= B1; \
+ B1 ^= B0; \
+ B1 |= B2; \
+ B0 ^= B3; \
+ B1 ^= B4; \
+ B0 ^= B1; \
+ B4 = B0; \
+ B0 = B2; \
+ B2 = B3; \
+ B3 = B4; \
+ } while(0);
+
+#define SBoxD5(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B2; \
+ B2 &= B3; \
+ B2 ^= B1; \
+ B1 |= B3; \
+ B1 &= B0; \
+ B4 ^= B2; \
+ B4 ^= B1; \
+ B1 &= B2; \
+ B0 = ~B0; \
+ B3 ^= B4; \
+ B1 ^= B3; \
+ B3 &= B0; \
+ B3 ^= B2; \
+ B0 ^= B1; \
+ B2 &= B0; \
+ B3 ^= B0; \
+ B2 ^= B4; \
+ B2 |= B3; \
+ B3 ^= B0; \
+ B2 ^= B1; \
+ B1 = B3; \
+ B3 = B4; \
+ } while(0);
+
+#define SBoxD6(B0, B1, B2, B3) \
+ do { \
+ B1 = ~B1; \
+ SIMD_32 B4 = B3; \
+ B2 ^= B1; \
+ B3 |= B0; \
+ B3 ^= B2; \
+ B2 |= B1; \
+ B2 &= B0; \
+ B4 ^= B3; \
+ B2 ^= B4; \
+ B4 |= B0; \
+ B4 ^= B1; \
+ B1 &= B2; \
+ B1 ^= B3; \
+ B4 ^= B2; \
+ B3 &= B4; \
+ B4 ^= B1; \
+ B3 ^= B4; \
+ B4 = ~B4; \
+ B3 ^= B0; \
+ B0 = B1; \
+ B1 = B4; \
+ B4 = B3; \
+ B3 = B2; \
+ B2 = B4; \
+ } while(0);
+
+#define SBoxD7(B0, B1, B2, B3) \
+ do { \
+ B0 ^= B2; \
+ SIMD_32 B4 = B2; \
+ B2 &= B0; \
+ B4 ^= B3; \
+ B2 = ~B2; \
+ B3 ^= B1; \
+ B2 ^= B3; \
+ B4 |= B0; \
+ B0 ^= B2; \
+ B3 ^= B4; \
+ B4 ^= B1; \
+ B1 &= B3; \
+ B1 ^= B0; \
+ B0 ^= B3; \
+ B0 |= B2; \
+ B3 ^= B1; \
+ B4 ^= B0; \
+ B0 = B1; \
+ B1 = B2; \
+ B2 = B4; \
+ } while(0);
+
+#define SBoxD8(B0, B1, B2, B3) \
+ do { \
+ SIMD_32 B4 = B2; \
+ B2 ^= B0; \
+ B0 &= B3; \
+ B4 |= B3; \
+ B2 = ~B2; \
+ B3 ^= B1; \
+ B1 |= B0; \
+ B0 ^= B2; \
+ B2 &= B4; \
+ B3 &= B4; \
+ B1 ^= B2; \
+ B2 ^= B0; \
+ B0 |= B2; \
+ B4 ^= B1; \
+ B0 ^= B3; \
+ B3 ^= B4; \
+ B4 |= B0; \
+ B3 ^= B2; \
+ B4 ^= B2; \
+ B2 = B1; \
+ B1 = B0; \
+ B0 = B3; \
+ B3 = B4; \
+ } while(0);
+
#define key_xor(round, B0, B1, B2, B3) \
do { \
B0 ^= SIMD_32(keys[4*round ]); \
@@ -175,6 +588,24 @@ void serpent_decrypt_4(const byte in[64],
#undef transform
#undef i_transform
+#undef SBoxE1
+#undef SBoxE2
+#undef SBoxE3
+#undef SBoxE4
+#undef SBoxE5
+#undef SBoxE6
+#undef SBoxE7
+#undef SBoxE8
+
+#undef SBoxD1
+#undef SBoxD2
+#undef SBoxD3
+#undef SBoxD4
+#undef SBoxD5
+#undef SBoxD6
+#undef SBoxD7
+#undef SBoxD8
+
/*
* Serpent Encryption
*/
diff --git a/src/block/serpent_simd/serp_simd_sbox.h b/src/block/serpent_simd/serp_simd_sbox.h
deleted file mode 100644
index 71eca19e5..000000000
--- a/src/block/serpent_simd/serp_simd_sbox.h
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
-* Serpent Sboxes in SIMD form
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_SERPENT_SIMD_SBOXES_H__
-#define BOTAN_SERPENT_SIMD_SBOXES_H__
-
-#define SBoxE1(B0, B1, B2, B3) \
- do { \
- B3 ^= B0; \
- SIMD_32 B4 = B1; \
- B1 &= B3; \
- B4 ^= B2; \
- B1 ^= B0; \
- B0 |= B3; \
- B0 ^= B4; \
- B4 ^= B3; \
- B3 ^= B2; \
- B2 |= B1; \
- B2 ^= B4; \
- B4 = ~B4; \
- B4 |= B1; \
- B1 ^= B3; \
- B1 ^= B4; \
- B3 |= B0; \
- B1 ^= B3; \
- B4 ^= B3; \
- B3 = B0; \
- B0 = B1; \
- B1 = B4; \
- } while(0);
-
-#define SBoxE2(B0, B1, B2, B3) \
- do { \
- B0 = ~B0; \
- B2 = ~B2; \
- SIMD_32 B4 = B0; \
- B0 &= B1; \
- B2 ^= B0; \
- B0 |= B3; \
- B3 ^= B2; \
- B1 ^= B0; \
- B0 ^= B4; \
- B4 |= B1; \
- B1 ^= B3; \
- B2 |= B0; \
- B2 &= B4; \
- B0 ^= B1; \
- B1 &= B2; \
- B1 ^= B0; \
- B0 &= B2; \
- B4 ^= B0; \
- B0 = B2; \
- B2 = B3; \
- B3 = B1; \
- B1 = B4; \
- } while(0);
-
-#define SBoxE3(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B0; \
- B0 &= B2; \
- B0 ^= B3; \
- B2 ^= B1; \
- B2 ^= B0; \
- B3 |= B4; \
- B3 ^= B1; \
- B4 ^= B2; \
- B1 = B3; \
- B3 |= B4; \
- B3 ^= B0; \
- B0 &= B1; \
- B4 ^= B0; \
- B1 ^= B3; \
- B1 ^= B4; \
- B0 = B2; \
- B2 = B1; \
- B1 = B3; \
- B3 = ~B4; \
- } while(0);
-
-#define SBoxE4(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B0; \
- B0 |= B3; \
- B3 ^= B1; \
- B1 &= B4; \
- B4 ^= B2; \
- B2 ^= B3; \
- B3 &= B0; \
- B4 |= B1; \
- B3 ^= B4; \
- B0 ^= B1; \
- B4 &= B0; \
- B1 ^= B3; \
- B4 ^= B2; \
- B1 |= B0; \
- B1 ^= B2; \
- B0 ^= B3; \
- B2 = B1; \
- B1 |= B3; \
- B0 ^= B1; \
- B1 = B2; \
- B2 = B3; \
- B3 = B4; \
- } while(0);
-
-#define SBoxE5(B0, B1, B2, B3) \
- do { \
- B1 ^= B3; \
- B3 = ~B3; \
- B2 ^= B3; \
- B3 ^= B0; \
- SIMD_32 B4 = B1; \
- B1 &= B3; \
- B1 ^= B2; \
- B4 ^= B3; \
- B0 ^= B4; \
- B2 &= B4; \
- B2 ^= B0; \
- B0 &= B1; \
- B3 ^= B0; \
- B4 |= B1; \
- B4 ^= B0; \
- B0 |= B3; \
- B0 ^= B2; \
- B2 &= B3; \
- B0 = ~B0; \
- B4 ^= B2; \
- B2 = B0; \
- B0 = B1; \
- B1 = B4; \
- } while(0);
-
-#define SBoxE6(B0, B1, B2, B3) \
- do { \
- B0 ^= B1; \
- B1 ^= B3; \
- B3 = ~B3; \
- SIMD_32 B4 = B1; \
- B1 &= B0; \
- B2 ^= B3; \
- B1 ^= B2; \
- B2 |= B4; \
- B4 ^= B3; \
- B3 &= B1; \
- B3 ^= B0; \
- B4 ^= B1; \
- B4 ^= B2; \
- B2 ^= B0; \
- B0 &= B3; \
- B2 = ~B2; \
- B0 ^= B4; \
- B4 |= B3; \
- B4 ^= B2; \
- B2 = B0; \
- B0 = B1; \
- B1 = B3; \
- B3 = B4; \
- } while(0);
-
-#define SBoxE7(B0, B1, B2, B3) \
- do { \
- B2 = ~B2; \
- SIMD_32 B4 = B3; \
- B3 &= B0; \
- B0 ^= B4; \
- B3 ^= B2; \
- B2 |= B4; \
- B1 ^= B3; \
- B2 ^= B0; \
- B0 |= B1; \
- B2 ^= B1; \
- B4 ^= B0; \
- B0 |= B3; \
- B0 ^= B2; \
- B4 ^= B3; \
- B4 ^= B0; \
- B3 = ~B3; \
- B2 &= B4; \
- B3 ^= B2; \
- B2 = B4; \
- } while(0);
-
-#define SBoxE8(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B1; \
- B1 |= B2; \
- B1 ^= B3; \
- B4 ^= B2; \
- B2 ^= B1; \
- B3 |= B4; \
- B3 &= B0; \
- B4 ^= B2; \
- B3 ^= B1; \
- B1 |= B4; \
- B1 ^= B0; \
- B0 |= B4; \
- B0 ^= B2; \
- B1 ^= B4; \
- B2 ^= B1; \
- B1 &= B0; \
- B1 ^= B4; \
- B2 = ~B2; \
- B2 |= B0; \
- B4 ^= B2; \
- B2 = B1; \
- B1 = B3; \
- B3 = B0; \
- B0 = B4; \
- } while(0);
-
-#define SBoxD1(B0, B1, B2, B3) \
- do { \
- B2 = ~B2; \
- SIMD_32 B4 = B1; \
- B1 |= B0; \
- B4 = ~B4; \
- B1 ^= B2; \
- B2 |= B4; \
- B1 ^= B3; \
- B0 ^= B4; \
- B2 ^= B0; \
- B0 &= B3; \
- B4 ^= B0; \
- B0 |= B1; \
- B0 ^= B2; \
- B3 ^= B4; \
- B2 ^= B1; \
- B3 ^= B0; \
- B3 ^= B1; \
- B2 &= B3; \
- B4 ^= B2; \
- B2 = B1; \
- B1 = B4; \
- } while(0);
-
-#define SBoxD2(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B1; \
- B1 ^= B3; \
- B3 &= B1; \
- B4 ^= B2; \
- B3 ^= B0; \
- B0 |= B1; \
- B2 ^= B3; \
- B0 ^= B4; \
- B0 |= B2; \
- B1 ^= B3; \
- B0 ^= B1; \
- B1 |= B3; \
- B1 ^= B0; \
- B4 = ~B4; \
- B4 ^= B1; \
- B1 |= B0; \
- B1 ^= B0; \
- B1 |= B4; \
- B3 ^= B1; \
- B1 = B0; \
- B0 = B4; \
- B4 = B2; \
- B2 = B3; \
- B3 = B4; \
- } while(0);
-
-#define SBoxD3(B0, B1, B2, B3) \
- do { \
- B2 ^= B3; \
- B3 ^= B0; \
- SIMD_32 B4 = B3; \
- B3 &= B2; \
- B3 ^= B1; \
- B1 |= B2; \
- B1 ^= B4; \
- B4 &= B3; \
- B2 ^= B3; \
- B4 &= B0; \
- B4 ^= B2; \
- B2 &= B1; \
- B2 |= B0; \
- B3 = ~B3; \
- B2 ^= B3; \
- B0 ^= B3; \
- B0 &= B1; \
- B3 ^= B4; \
- B3 ^= B0; \
- B0 = B1; \
- B1 = B4; \
- } while(0);
-
-#define SBoxD4(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B2; \
- B2 ^= B1; \
- B0 ^= B2; \
- B4 &= B2; \
- B4 ^= B0; \
- B0 &= B1; \
- B1 ^= B3; \
- B3 |= B4; \
- B2 ^= B3; \
- B0 ^= B3; \
- B1 ^= B4; \
- B3 &= B2; \
- B3 ^= B1; \
- B1 ^= B0; \
- B1 |= B2; \
- B0 ^= B3; \
- B1 ^= B4; \
- B0 ^= B1; \
- B4 = B0; \
- B0 = B2; \
- B2 = B3; \
- B3 = B4; \
- } while(0);
-
-#define SBoxD5(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B2; \
- B2 &= B3; \
- B2 ^= B1; \
- B1 |= B3; \
- B1 &= B0; \
- B4 ^= B2; \
- B4 ^= B1; \
- B1 &= B2; \
- B0 = ~B0; \
- B3 ^= B4; \
- B1 ^= B3; \
- B3 &= B0; \
- B3 ^= B2; \
- B0 ^= B1; \
- B2 &= B0; \
- B3 ^= B0; \
- B2 ^= B4; \
- B2 |= B3; \
- B3 ^= B0; \
- B2 ^= B1; \
- B1 = B3; \
- B3 = B4; \
- } while(0);
-
-#define SBoxD6(B0, B1, B2, B3) \
- do { \
- B1 = ~B1; \
- SIMD_32 B4 = B3; \
- B2 ^= B1; \
- B3 |= B0; \
- B3 ^= B2; \
- B2 |= B1; \
- B2 &= B0; \
- B4 ^= B3; \
- B2 ^= B4; \
- B4 |= B0; \
- B4 ^= B1; \
- B1 &= B2; \
- B1 ^= B3; \
- B4 ^= B2; \
- B3 &= B4; \
- B4 ^= B1; \
- B3 ^= B4; \
- B4 = ~B4; \
- B3 ^= B0; \
- B0 = B1; \
- B1 = B4; \
- B4 = B3; \
- B3 = B2; \
- B2 = B4; \
- } while(0);
-
-#define SBoxD7(B0, B1, B2, B3) \
- do { \
- B0 ^= B2; \
- SIMD_32 B4 = B2; \
- B2 &= B0; \
- B4 ^= B3; \
- B2 = ~B2; \
- B3 ^= B1; \
- B2 ^= B3; \
- B4 |= B0; \
- B0 ^= B2; \
- B3 ^= B4; \
- B4 ^= B1; \
- B1 &= B3; \
- B1 ^= B0; \
- B0 ^= B3; \
- B0 |= B2; \
- B3 ^= B1; \
- B4 ^= B0; \
- B0 = B1; \
- B1 = B2; \
- B2 = B4; \
- } while(0);
-
-#define SBoxD8(B0, B1, B2, B3) \
- do { \
- SIMD_32 B4 = B2; \
- B2 ^= B0; \
- B0 &= B3; \
- B4 |= B3; \
- B2 = ~B2; \
- B3 ^= B1; \
- B1 |= B0; \
- B0 ^= B2; \
- B2 &= B4; \
- B3 &= B4; \
- B1 ^= B2; \
- B2 ^= B0; \
- B0 |= B2; \
- B4 ^= B1; \
- B0 ^= B3; \
- B3 ^= B4; \
- B4 |= B0; \
- B3 ^= B2; \
- B4 ^= B2; \
- B2 = B1; \
- B1 = B0; \
- B0 = B3; \
- B3 = B4; \
- } while(0);
-
-#endif
diff --git a/src/block/serpent_ia32/info.txt b/src/block/serpent_x86_32/info.txt
index 3a1dd5919..b9c993546 100644
--- a/src/block/serpent_ia32/info.txt
+++ b/src/block/serpent_x86_32/info.txt
@@ -1,12 +1,12 @@
-define SERPENT_IA32
+define SERPENT_X86_32
load_on asm_ok
<arch>
-ia32
+x86_32
</arch>
<requires>
-asm_ia32
+asm_x86_32
serpent
</requires>
diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_x86_32/serp_x86_32.cpp
index d2f8adb62..4cefe1d65 100644
--- a/src/block/serpent_ia32/serp_ia32.cpp
+++ b/src/block/serpent_x86_32/serp_x86_32.cpp
@@ -1,11 +1,11 @@
/*
-* IA-32 Serpent
+* Serpent in x86-32
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/serp_ia32.h>
+#include <botan/serp_x86_32.h>
#include <botan/loadstor.h>
namespace Botan {
@@ -18,7 +18,7 @@ extern "C" {
* @param out the output block
* @param ks the key schedule
*/
-void botan_serpent_ia32_encrypt(const byte in[16],
+void botan_serpent_x86_32_encrypt(const byte in[16],
byte out[16],
const u32bit ks[132]);
@@ -28,7 +28,7 @@ void botan_serpent_ia32_encrypt(const byte in[16],
* @param out the output block
* @param ks the key schedule
*/
-void botan_serpent_ia32_decrypt(const byte in[16],
+void botan_serpent_x86_32_decrypt(const byte in[16],
byte out[16],
const u32bit ks[132]);
@@ -37,18 +37,18 @@ void botan_serpent_ia32_decrypt(const byte in[16],
* @param ks holds the initial working key (padded), and is set to the
final key schedule
*/
-void botan_serpent_ia32_key_schedule(u32bit ks[140]);
+void botan_serpent_x86_32_key_schedule(u32bit ks[140]);
}
/*
* Serpent Encryption
*/
-void Serpent_IA32::encrypt_n(const byte in[], byte out[], size_t blocks) const
+void Serpent_X86_32::encrypt_n(const byte in[], byte out[], size_t blocks) const
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_serpent_ia32_encrypt(in, out, this->get_round_keys());
+ botan_serpent_x86_32_encrypt(in, out, this->get_round_keys());
in += BLOCK_SIZE;
out += BLOCK_SIZE;
}
@@ -57,11 +57,11 @@ void Serpent_IA32::encrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* Serpent Decryption
*/
-void Serpent_IA32::decrypt_n(const byte in[], byte out[], size_t blocks) const
+void Serpent_X86_32::decrypt_n(const byte in[], byte out[], size_t blocks) const
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_serpent_ia32_decrypt(in, out, this->get_round_keys());
+ botan_serpent_x86_32_decrypt(in, out, this->get_round_keys());
in += BLOCK_SIZE;
out += BLOCK_SIZE;
}
@@ -70,14 +70,14 @@ void Serpent_IA32::decrypt_n(const byte in[], byte out[], size_t blocks) const
/*
* Serpent Key Schedule
*/
-void Serpent_IA32::key_schedule(const byte key[], size_t length)
+void Serpent_X86_32::key_schedule(const byte key[], size_t length)
{
SecureVector<u32bit> W(140);
for(size_t i = 0; i != length / 4; ++i)
W[i] = load_le<u32bit>(key, i);
W[length / 4] |= u32bit(1) << ((length%4)*8);
- botan_serpent_ia32_key_schedule(W);
+ botan_serpent_x86_32_key_schedule(W);
this->set_round_keys(W + 8);
}
diff --git a/src/block/serpent_ia32/serp_ia32.h b/src/block/serpent_x86_32/serp_x86_32.h
index d7b5bedc7..f6c4d564a 100644
--- a/src/block/serpent_ia32/serp_ia32.h
+++ b/src/block/serpent_x86_32/serp_x86_32.h
@@ -1,27 +1,27 @@
/*
-* Serpent (IA-32)
+* Serpent in x86-32 asm
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_SERPENT_IA32_H__
-#define BOTAN_SERPENT_IA32_H__
+#ifndef BOTAN_SERPENT_X86_32_H__
+#define BOTAN_SERPENT_X86_32_H__
#include <botan/serpent.h>
namespace Botan {
/**
-* Serpent implementation in x86 assembly
+* Serpent implementation in x86-32 assembly
*/
-class BOTAN_DLL Serpent_IA32 : public Serpent
+class BOTAN_DLL Serpent_X86_32 : public Serpent
{
public:
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
- BlockCipher* clone() const { return new Serpent_IA32; }
+ BlockCipher* clone() const { return new Serpent_X86_32; }
private:
void key_schedule(const byte[], size_t);
};
diff --git a/src/block/serpent_ia32/serp_ia32_imp.S b/src/block/serpent_x86_32/serp_x86_32_imp.S
index 768192061..e2549a099 100644
--- a/src/block/serpent_ia32/serp_ia32_imp.S
+++ b/src/block/serpent_x86_32/serp_x86_32_imp.S
@@ -1,13 +1,13 @@
/*
-* Serpent in IA-32 assembler
+* Serpent in x86-32 assembler
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/asm_macr_ia32.h>
+#include <botan/internal/asm_x86_32.h>
-START_LISTING(serp_ia32.S)
+START_LISTING(serp_x86_32.S)
#define SBOX_E1(A, B, C, D, T) \
XOR(D, A) ; \
@@ -441,7 +441,7 @@ START_LISTING(serp_ia32.S)
/*
* Serpent Encryption
*/
-START_FUNCTION(botan_serpent_ia32_encrypt)
+START_FUNCTION(botan_serpent_x86_32_encrypt)
SPILL_REGS()
#define PUSHED 4
@@ -507,12 +507,12 @@ START_FUNCTION(botan_serpent_ia32_encrypt)
RESTORE_REGS()
#undef PUSHED
-END_FUNCTION(botan_serpent_ia32_encrypt)
+END_FUNCTION(botan_serpent_x86_32_encrypt)
/*
* Serpent Decryption
*/
-START_FUNCTION(botan_serpent_ia32_decrypt)
+START_FUNCTION(botan_serpent_x86_32_decrypt)
SPILL_REGS()
#define PUSHED 4
@@ -578,12 +578,12 @@ START_FUNCTION(botan_serpent_ia32_decrypt)
RESTORE_REGS()
#undef PUSHED
-END_FUNCTION(botan_serpent_ia32_decrypt)
+END_FUNCTION(botan_serpent_x86_32_decrypt)
/*
* Serpent Key Schedule
*/
-START_FUNCTION(botan_serpent_ia32_key_schedule)
+START_FUNCTION(botan_serpent_x86_32_key_schedule)
SPILL_REGS()
#define PUSHED 4
@@ -591,7 +591,7 @@ START_FUNCTION(botan_serpent_ia32_key_schedule)
ASSIGN(ESI, IMM(8))
ADD_IMM(EDI, 32)
-START_LOOP(.EXPANSION)
+START_LOOP(.L_SERP_EXPANSION)
ASSIGN(EAX, ARRAY4(EDI, -1))
ASSIGN(EBX, ARRAY4(EDI, -3))
ASSIGN(ECX, ARRAY4(EDI, -5))
@@ -611,7 +611,7 @@ START_LOOP(.EXPANSION)
ADD_IMM(ESI, 1)
ADD_IMM(EDI, 4)
-LOOP_UNTIL_EQ(ESI, 140, .EXPANSION)
+LOOP_UNTIL_EQ(ESI, 140, .L_SERP_EXPANSION)
ASSIGN(EDI, ARG(1)) /* round keys */
@@ -666,4 +666,4 @@ LOOP_UNTIL_EQ(ESI, 140, .EXPANSION)
RESTORE_REGS()
#undef PUSHED
-END_FUNCTION(botan_serpent_ia32_key_schedule)
+END_FUNCTION(botan_serpent_x86_32_key_schedule)
diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp
index b1517b990..cd1865582 100644
--- a/src/block/square/square.cpp
+++ b/src/block/square/square.cpp
@@ -2,6 +2,8 @@
* Square
* (C) 1999-2007 Jack Lloyd
*
+* Based on the public domain reference implemenation
+*
* Distributed under the terms of the Botan license
*/
diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp
index 41bc7ca1c..c0735e202 100644
--- a/src/block/twofish/twofish.cpp
+++ b/src/block/twofish/twofish.cpp
@@ -2,6 +2,9 @@
* Twofish
* (C) 1999-2007 Jack Lloyd
*
+* The key schedule implemenation is based on a public domain
+* implementation by Matthew Skala
+*
* Distributed under the terms of the Botan license
*/
diff --git a/src/block/xtea_simd/info.txt b/src/block/xtea_simd/info.txt
index 5a8445b35..c16bfa2fa 100644
--- a/src/block/xtea_simd/info.txt
+++ b/src/block/xtea_simd/info.txt
@@ -2,6 +2,6 @@ define XTEA_SIMD
<requires>
xtea
-simd_32
+simd
simd_engine
</requires>
diff --git a/src/build-data/arch/arm.txt b/src/build-data/arch/arm.txt
index 77f15b1d9..b822fe130 100644
--- a/src/build-data/arch/arm.txt
+++ b/src/build-data/arch/arm.txt
@@ -1,25 +1,43 @@
+
+endian little
+family arm
+
+<aliases>
+armel # For Debian
+armhf # For Debian
+</aliases>
+
<submodels>
-arm2
-arm3
-arm6
-arm7
-arm8
-arm9
-strongarm
-strongarm110
-strongarm1100
-xscale
-cortex-a8
-cortex-a9
+armv2
+armv2a
+armv3
+armv3m
+armv4
+armv5
+armv5e
+armv5te
+armv6
+armv6j
+armv6t2
+armv6z
+armv6zk
+armv6-m
+armv7
+armv7-a
+armv7-r
+armv7-m
+iwmmxt
+iwmmxt2
+ep9312
</submodels>
<submodel_aliases>
-sa110 -> strongarm110
-sa1100 -> strongarm1100
-strongarm1110 -> strongarm1100
-armv5tel -> xscale
+strongarm -> armv4
+xscale -> armv5te
+cortex-a8 -> armv7-a
+cortex-a9 -> armv7-a
</submodel_aliases>
<isa_extn>
-neon:cortex-a8,cortex-a9
+neon:armv7-a
</isa_extn>
diff --git a/src/build-data/arch/hitachi-sh.txt b/src/build-data/arch/hitachi-sh.txt
deleted file mode 100644
index bab84b48f..000000000
--- a/src/build-data/arch/hitachi-sh.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-<submodels>
-hitachi-sh1
-hitachi-sh2
-hitachi-sh3
-hitachi-sh3e
-hitachi-sh4
-</submodels>
diff --git a/src/build-data/arch/ppc.txt b/src/build-data/arch/ppc32.txt
index dc3ea7829..e33c8ff24 100644
--- a/src/build-data/arch/ppc.txt
+++ b/src/build-data/arch/ppc32.txt
@@ -5,13 +5,9 @@ family ppc
<aliases>
powerpc
+ppc
</aliases>
-<submodel_aliases>
-g3 -> ppc740
-g4 -> ppc7450
-</submodel_aliases>
-
<submodels>
ppc601
ppc603
@@ -20,8 +16,15 @@ ppc740
ppc750
ppc7400
ppc7450
+e500v2
</submodels>
+<submodel_aliases>
+g3 -> ppc740
+g4 -> ppc7450
+powerpcspe -> e500v2 # for Debian
+</submodel_aliases>
+
<isa_extn>
altivec:ppc7400,ppc7450
</isa_extn>
diff --git a/src/build-data/arch/ppc64.txt b/src/build-data/arch/ppc64.txt
index 7a2e6b6b3..954d9181e 100644
--- a/src/build-data/arch/ppc64.txt
+++ b/src/build-data/arch/ppc64.txt
@@ -11,7 +11,6 @@ g5 -> ppc970
</submodel_aliases>
<submodels>
-rs64a
ppc970
power3
power4
diff --git a/src/build-data/arch/sparc32.txt b/src/build-data/arch/sparc32.txt
index fc015e520..69f3479aa 100644
--- a/src/build-data/arch/sparc32.txt
+++ b/src/build-data/arch/sparc32.txt
@@ -26,4 +26,6 @@ sparcv9 -> sparc32-v9
sparc-v7 -> sparc32-v7
sparc-v8 -> sparc32-v8
sparc-v9 -> sparc32-v9
+
+sun4u -> sparc32-v9
</submodel_aliases>
diff --git a/src/build-data/arch/sparc64.txt b/src/build-data/arch/sparc64.txt
index 7344fa390..3a6acd6c3 100644
--- a/src/build-data/arch/sparc64.txt
+++ b/src/build-data/arch/sparc64.txt
@@ -1,13 +1,11 @@
family sparc
-<aliases>
-sun4u
-</aliases>
-
<submodels>
ultrasparc
ultrasparc3
+niagra
+niagra2
</submodels>
<submodel_aliases>
diff --git a/src/build-data/arch/superh.txt b/src/build-data/arch/superh.txt
new file mode 100644
index 000000000..c7dc09861
--- /dev/null
+++ b/src/build-data/arch/superh.txt
@@ -0,0 +1,5 @@
+<submodels>
+sh2
+sh3
+sh4
+</submodels>
diff --git a/src/build-data/arch/ia32.txt b/src/build-data/arch/x86_32.txt
index c2d4d1769..482a53057 100644
--- a/src/build-data/arch/ia32.txt
+++ b/src/build-data/arch/x86_32.txt
@@ -4,10 +4,13 @@ unaligned ok
family x86
<aliases>
+ia32
x86
ix86
80x86
i86pc # for Solaris
+x86pc # for QNX
+bepc # for Haiku
</aliases>
<submodels>
@@ -22,7 +25,7 @@ pentium-m
prescott
k6
athlon
-atom
+atom32
</submodels>
<submodel_aliases>
@@ -59,7 +62,7 @@ intelcput2700 -> prescott
</submodel_aliases>
<isa_extn>
-sse2:pentium4,prescott,pentium-m,atom
-ssse3:atom
-movbe:atom
+sse2:pentium4,prescott,pentium-m,atom32
+ssse3:atom32
+movbe:atom32
</isa_extn>
diff --git a/src/build-data/arch/amd64.txt b/src/build-data/arch/x86_64.txt
index b3b9879d2..97b84fbde 100644
--- a/src/build-data/arch/amd64.txt
+++ b/src/build-data/arch/x86_64.txt
@@ -4,8 +4,8 @@ unaligned ok
family x86
<aliases>
+amd64
x86-64
-x86_64 # for RPM
em64t
x64
</aliases>
@@ -17,6 +17,7 @@ nocona
core2
nehalem
westmere
+atom
</submodels>
<submodel_aliases>
@@ -36,6 +37,6 @@ corei7cpu860 -> nehalem
<isa_extn>
sse2:all
-ssse3:core2,nehalem,westmere
+ssse3:core2,nehalem,westmere,atom
aes-ni:westmere
</isa_extn>
diff --git a/src/build-data/botan-config.in b/src/build-data/botan-config.in
index f3fa3db94..6780c12b8 100644
--- a/src/build-data/botan-config.in
+++ b/src/build-data/botan-config.in
@@ -2,7 +2,7 @@
# For normal builds:
guess_prefix=`dirname \`dirname $0\``
-includedir=%{includedir}
+includedir=%{includedir}/botan-%{version_major}.%{version_minor}
libdir=%{libdir}
# For workspace builds:
@@ -54,9 +54,9 @@ while test $# -gt 0; do
--libs)
if [ $prefix != "/usr" -a $prefix != "/usr/local" ]
then
- echo -L$prefix/$libdir -lbotan %{link_to}
+ echo -L$prefix/$libdir -lbotan-%{version_major}.%{version_minor} %{link_to}
else
- echo -lbotan %{link_to}
+ echo -lbotan-%{version_major}.%{version_minor} %{link_to}
fi
;;
*)
diff --git a/src/build-data/botan.doxy.in b/src/build-data/botan.doxy.in
index 2f76a756b..52021c01f 100644
--- a/src/build-data/botan.doxy.in
+++ b/src/build-data/botan.doxy.in
@@ -1,12 +1,9 @@
# Doxyfile 1.5.4
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = Botan
PROJECT_NUMBER = %{version}
-OUTPUT_DIRECTORY = doc/doxygen
+OUTPUT_DIRECTORY = %{doc_output_dir}/doxygen
+DOXYFILE_ENCODING = UTF-8
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
@@ -33,6 +30,7 @@ SIP_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -63,6 +61,7 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -73,6 +72,7 @@ WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
+
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
@@ -112,7 +112,7 @@ IGNORE_PREFIX =
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
-HTML_OUTPUT = html
+HTML_OUTPUT = .
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
@@ -129,56 +129,7 @@ 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
#---------------------------------------------------------------------------
@@ -191,6 +142,7 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
+
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
@@ -199,6 +151,7 @@ GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
+
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
@@ -226,6 +179,7 @@ DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
+
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
diff --git a/src/build-data/botan.pc.in b/src/build-data/botan.pc.in
index 70ed65d70..301f84600 100644
--- a/src/build-data/botan.pc.in
+++ b/src/build-data/botan.pc.in
@@ -1,12 +1,12 @@
prefix=%{prefix}
exec_prefix=${prefix}
libdir=${prefix}/%{libdir}
-includedir=${prefix}/include
+includedir=${prefix}/include/botan-%{version_major}.%{version_minor}
Name: Botan
Description: Multi-platform C++ crypto library
Version: %{version}
-Libs: -L${libdir} -lbotan
+Libs: -L${libdir} -lbotan-%{version_major}.%{version_minor}
Libs.private: %{link_to}
Cflags: -I${includedir}
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index 2682d2ad9..733646524 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -20,7 +20,7 @@
#define BOTAN_DISTRIBUTION_INFO "%{distribution_info}"
#ifndef BOTAN_DLL
- #define BOTAN_DLL %{dll_import_flags}
+ #define BOTAN_DLL %{visibility_attribute}
#endif
/* Chunk sizes */
@@ -35,7 +35,7 @@
/* 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_LOAD 0
#define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1
/* Should we use GCC-style inline assembler? */
diff --git a/src/build-data/cc/bcc.txt b/src/build-data/cc/bcc.txt
index 93306dde1..f2ea46ef2 100644
--- a/src/build-data/cc/bcc.txt
+++ b/src/build-data/cc/bcc.txt
@@ -15,7 +15,6 @@ lang_flags ""
warning_flags ""
shared_flags ""
-dll_import_flags ""
ar_command lib
diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt
index 14c51349c..f4db26ee8 100644
--- a/src/build-data/cc/clang.txt
+++ b/src/build-data/cc/clang.txt
@@ -17,11 +17,12 @@ makefile_style unix
lib_opt_flags "-O2"
check_opt_flags "-O2"
-shared_flags "-fPIC -fvisibility=hidden"
+shared_flags "-fPIC"
debug_flags -g
no_debug_flags "-finline-functions"
-dll_import_flags '__attribute__((visibility("default")))'
+visibility_build_flags "-fvisibility=hidden"
+visibility_attribute '__attribute__((visibility("default")))'
<so_link_flags>
# The default works for GNU ld and several other Unix linkers
@@ -29,12 +30,12 @@ default -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)"
</so_link_flags>
<mach_opt>
-amd64 -> "-march=SUBMODEL"
+x86_64 -> "-march=SUBMODEL"
nehalem -> "-march=core2 -mssse3 -msse4.1"
</mach_opt>
<mach_abi_linking>
-amd64 -> "-m64"
+x86_64 -> "-m64"
mips64 -> "-mabi=64"
s390 -> "-m31"
s390x -> "-m64"
diff --git a/src/build-data/cc/ekopath.txt b/src/build-data/cc/ekopath.txt
index ac514261e..c6e8b6550 100644
--- a/src/build-data/cc/ekopath.txt
+++ b/src/build-data/cc/ekopath.txt
@@ -28,10 +28,9 @@ default -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)"
athlon -> "-mcpu=athlon"
pentium4 -> "-mcpu=pentium4"
-opteron -> "-mcpu=opteron"
-em64t -> "-mcpu=em64t"
+k8 -> "-mcpu=opteron"
core2 -> "-mcpu=core"
-ia32 -> "-mcpu=anyx86"
-amd64 -> "-mcpu=athlon64"
+x86_32 -> "-mcpu=anyx86"
+x86_64 -> "-mcpu=athlon64"
</mach_opt>
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index 2f71c7a18..84e923764 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -1,6 +1,6 @@
macro_name GCC
-binary_name g++-4.5.2
+binary_name g++-4.6.0
compile_option "-c "
output_to_option "-o "
@@ -11,15 +11,16 @@ add_lib_option -l
lang_flags "-D_REENTRANT -std=c++0x"
warning_flags "-W -Wall"
-maintainer_warning_flags "-Werror -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual"
+maintainer_warning_flags "-Werror -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast"
lib_opt_flags "-O3"
check_opt_flags "-O2"
-shared_flags "-fPIC -fvisibility=hidden"
+shared_flags "-fPIC"
debug_flags -g
no_debug_flags "-finline-functions"
-dll_import_flags '__attribute__((visibility("default")))'
+visibility_build_flags "-fvisibility=hidden"
+visibility_attribute '__attribute__((visibility("default")))'
makefile_style unix
@@ -33,53 +34,57 @@ aix -> "$(CXX) -shared -fPIC"
darwin -> "$(CXX) -dynamiclib -fPIC -install_name $(LIBDIR)/$(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"
-ppc601 -> "-mpowerpc -mcpu=601"
+ppc601 -> "-mpowerpc -mcpu=601"
+cellppu -> "-mcpu=cell"
+e500v2 -> "-mcpu=8548"
+atom32 -> "-march=atom -momit-leaf-frame-pointer"
+
+alpha-ev68 -> "-mcpu=ev67"
+alpha-ev7 -> "-mcpu=ev67"
+
+# The patch from Debian bug 594159 has this, don't know why though...
+sh4 -> "-m4 -mieee"
+
+# This is mostly for Debian's benefit
+i486 -> "-mtune=generic -momit-leaf-frame-pointer"
# Until GCC gets -march support for these models
-nehalem -> "-march=core2 -msse4.1 -msse4.2"
-westmere -> "-march=core2 -maes -msse4.1 -msse4.2"
-atom -> "-march=i686 -msse2 -mssse3"
-cellppu -> ""
-alpha-ev68 -> "-mcpu=ev6"
-alpha-ev7 -> "-mcpu=ev6"
+nehalem -> "-march=core2 -msse4.1 -msse4.2 -momit-leaf-frame-pointer"
+westmere -> "-march=core2 -maes -msse4.1 -msse4.2 -momit-leaf-frame-pointer"
# 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"
+arm -> "-march=SUBMODEL"
+superh -> "-mSUBMODEL" sh
hppa -> "-march=SUBMODEL" hppa
+ia64 -> "-mtune=SUBMODEL"
m68k -> "-mSUBMODEL"
-hitachi-sh -> "-mSUBMODEL" hitachi-sh
-sparc32 -> "-mcpu=SUBMODEL -Wa,-xarch=v8plus" sparc32-
-sparc64 -> "-mcpu=v9 -mtune=SUBMODEL"
mips32 -> "-mips1 -mcpu=SUBMODEL" mips32-
mips64 -> "-mips3 -mcpu=SUBMODEL" mips64-
-ppc -> "-mcpu=SUBMODEL" ppc
+ppc32 -> "-mcpu=SUBMODEL" ppc
ppc64 -> "-mcpu=SUBMODEL" ppc
+sparc32 -> "-mcpu=SUBMODEL -Wa,-xarch=v8plus" sparc32-
+sparc64 -> "-mcpu=v9 -mtune=SUBMODEL"
+x86_32 -> "-march=SUBMODEL -momit-leaf-frame-pointer"
+x86_64 -> "-march=SUBMODEL -momit-leaf-frame-pointer"
</mach_opt>
-# Note that the 'linking' bit means "use this for both compiling *and* linking"
+# The 'linking' bit means "use this for both compiling *and* linking"
<mach_abi_linking>
all -> "-pthread"
-amd64 -> "-m64"
mips64 -> "-mabi=64"
s390 -> "-m31"
s390x -> "-m64"
sparc32 -> "-m32 -mno-app-regs"
sparc64 -> "-m64 -mno-app-regs"
ppc64 -> "-m64"
+x86_64 -> "-m64"
netbsd -> "-D_NETBSD_SOURCE"
qnx -> "-fexceptions -D_QNX_SOURCE"
diff --git a/src/build-data/cc/icc.txt b/src/build-data/cc/icc.txt
index 1aab4d111..e11875cb1 100644
--- a/src/build-data/cc/icc.txt
+++ b/src/build-data/cc/icc.txt
@@ -30,5 +30,5 @@ westmere -> "-march=core2"
</mach_opt>
<so_link_flags>
-default -> "$(CXX) -fPIC -shared"
+default -> "$(CXX) -fPIC -shared -Wl,-soname,$(SONAME)"
</so_link_flags>
diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt
index a854a576d..034ea7444 100644
--- a/src/build-data/cc/msvc.txt
+++ b/src/build-data/cc/msvc.txt
@@ -14,8 +14,8 @@ check_opt_flags "/O2 /D_CONSOLE"
lang_flags "/EHs /GR"
warning_flags "/W3 /wd4275 /wd4267"
-shared_flags "/DBOTAN_DLL=__declspec(dllexport)"
-dll_import_flags "__declspec(dllimport)"
+visibility_build_flags "/DBOTAN_DLL=__declspec(dllexport)"
+visibility_attribute "__declspec(dllimport)"
ar_command lib
diff --git a/src/build-data/cc/open64.txt b/src/build-data/cc/open64.txt
index 34359ef63..52f35a7e8 100644
--- a/src/build-data/cc/open64.txt
+++ b/src/build-data/cc/open64.txt
@@ -23,5 +23,5 @@ default -> "$(CXX) -shared -Wl,-soname,$(SONAME)"
</so_link_flags>
<mach_abi_linking>
-amd64 -> "-m64"
+x86_64 -> "-m64"
</mach_abi_linking>
diff --git a/src/build-data/cc/pgi.txt b/src/build-data/cc/pgi.txt
index 0e4f8baf2..985c534b9 100644
--- a/src/build-data/cc/pgi.txt
+++ b/src/build-data/cc/pgi.txt
@@ -24,5 +24,5 @@ i586 -> "-tp p5"
i686 -> "-tp p6"
athlon -> "-tp k7"
pentium4 -> "-tp p6"
-ia32 -> "-tp px"
+x86_32 -> "-tp px"
</mach_opt>
diff --git a/src/build-data/cc/sunstudio.txt b/src/build-data/cc/sunstudio.txt
index d0b25d144..43e5fcf8a 100644
--- a/src/build-data/cc/sunstudio.txt
+++ b/src/build-data/cc/sunstudio.txt
@@ -40,14 +40,18 @@ nehalem -> "-xtarget=nehalem"
sparc32-v9 -> "-xchip=ultra -xarch=v8"
+ultrasparc3 -> "-xchip=ultra3"
+niagra1 -> "-xchip=ultraT1"
+niagra2 -> "-xchip=ultraT2"
+
sparc32 -> "-xchip=ultra -xarch=SUBMODEL" sparc32-
-sparc64 -> "-xchip=SUBMODEL" sparc64-
+sparc64 -> "-xchip=generic"
</mach_opt>
<mach_abi_linking>
# Needed on some Linux distros
-#linux -> "-library=stlport4"
+linux -> "-library=stlport4"
sparc64 -> "-xarch=v9"
-amd64 -> "-m64"
+x86_64 -> "-m64"
</mach_abi_linking>
diff --git a/src/build-data/innosetup.in b/src/build-data/innosetup.in
index 0a7eeb8f6..ed618e8fb 100644
--- a/src/build-data/innosetup.in
+++ b/src/build-data/innosetup.in
@@ -41,19 +41,19 @@ name: "docs"; Description: "Developer Documentation"; Types: devel
; DLL and license file is always included
Source: "..\doc\license.txt"; DestDir: "{app}"; Components: dll; AfterInstall: ConvertLineEndings
Source: "..\botan.dll"; DestDir: "{app}"; Components: dll
-Source: "..\botan.dll.manifest"; DestDir: "{app}"; Components: dll
+Source: "..\botan.dll.manifest"; DestDir: "{app}"; Components: dll; Flags: skipifsourcedoesntexist
Source: "include\botan\*"; DestDir: "{app}\include\botan"; Components: includes; AfterInstall: ConvertLineEndings
Source: "..\readme.txt"; DestDir: "{app}\doc"; Components: docs; AfterInstall: ConvertLineEndings
-Source: "..\doc\log.txt"; DestDir: "{app}\doc"; Components: docs; AfterInstall: ConvertLineEndings
+Source: "..\doc\*.txt"; DestDir: "{app}\doc"; Excludes: "license.txt"; Components: docs; AfterInstall: ConvertLineEndings
Source: "..\doc\examples\*.cpp"; DestDir: "{app}\doc\examples"; Components: docs; AfterInstall: ConvertLineEndings
Source: "..\botan.exp"; DestDir: "{app}"; Components: implib
Source: "..\botan.lib"; DestDir: "{app}"; Components: implib
-Source: "..\doc\api.pdf"; DestDir: "{app}\doc"; Components: docs; Flags: skipifsourcedoesntexist
+Source: "..\doc\manual.pdf"; DestDir: "{app}\doc"; Components: docs; Flags: skipifsourcedoesntexist
Source: "..\doc\tutorial.pdf"; DestDir: "{app}\doc"; Components: docs; Flags: skipifsourcedoesntexist
[Code]
diff --git a/src/build-data/makefile/nmake.in b/src/build-data/makefile/nmake.in
index 9ca071da3..3e20d988a 100644
--- a/src/build-data/makefile/nmake.in
+++ b/src/build-data/makefile/nmake.in
@@ -17,6 +17,7 @@ DESTDIR = %{prefix}
### Aliases for Common Programs
AR = %{ar_command}
+COPY = copy
CD = @cd
ECHO = @echo
INSTALL = %{install_cmd_exec}
@@ -30,8 +31,6 @@ RMDIR = @rmdir
### File Lists
CHECK = check
-DOCS = %{doc_files}
-
HEADERS = %{include_files}
LIBOBJS = %{lib_objs}
@@ -67,6 +66,9 @@ $(BOTAN_LIB): $(LIBOBJS)
!Endif
### Fake Targets
+docs:
+%{build_doc_commands}
+
clean:
$(RM) %{build_dir}\lib\* %{build_dir}\checks\*
$(RM) *.manifest *.exp *.dll
diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in
index c525aa6bf..5290beda8 100644
--- a/src/build-data/makefile/unix.in
+++ b/src/build-data/makefile/unix.in
@@ -9,13 +9,14 @@ LINK_TO = %{link_to}
# Version Numbers
VERSION = %{version}
+SERIES = %{version_major}.%{version_minor}
# Installation Settings
DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
-HEADERDIR = $(DESTDIR)/%{includedir}/botan
+HEADERDIR = $(DESTDIR)/%{includedir}/botan-$(SERIES)/botan
DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
@@ -24,6 +25,8 @@ PKGCONFIG = %{botan_pkgconfig}
# Aliases for Common Programs
AR = %{ar_command}
+COPY = cp
+COPY_R = cp -r
CD = @cd
ECHO = @echo
INSTALL_CMD_EXEC = %{install_cmd_exec}
@@ -38,8 +41,6 @@ RM_R = @rm -rf
# File Lists
CHECK = %{check_prefix}check
-DOCS = %{doc_files}
-
HEADERS = %{include_files}
LIBOBJS = %{lib_objs}
@@ -52,7 +53,7 @@ CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
LIBRARIES = $(STATIC_LIB)
LIBNAME = %{lib_prefix}libbotan
-STATIC_LIB = $(LIBNAME).a
+STATIC_LIB = $(LIBNAME)-$(SERIES).a
all: $(LIBRARIES)
@@ -63,7 +64,7 @@ all: $(LIBRARIES)
# Link Commands
$(CHECK): $(LIBRARIES) $(CHECKOBJS)
- $(CXX) $(CHECKOBJS) -L. libbotan.a $(LINK_TO) -o $(CHECK)
+ $(CXX) $(CHECKOBJS) $(STATIC_LIB) $(LINK_TO) -o $(CHECK)
$(STATIC_LIB): $(LIBOBJS)
$(RM) $(STATIC_LIB)
@@ -71,12 +72,12 @@ $(STATIC_LIB): $(LIBOBJS)
$(RANLIB) $(STATIC_LIB)
# Fake Targets
-.PHONY = doxygen clean distclean install static
+.PHONY = docs clean distclean install static
static: $(STATIC_LIB)
-doxygen:
- doxygen %{build_dir}/botan.doxy
+docs:
+%{build_doc_commands}
clean:
$(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
@@ -84,22 +85,24 @@ clean:
distclean: clean
$(RM_R) %{build_dir}
- $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy
$(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG)
+ $(RM) botan_all.cpp botan_all.h
-install: $(LIBRARIES)
+install: $(LIBRARIES) docs
$(ECHO) "Installing Botan into $(DESTDIR)... "
$(MKDIR_INSTALL) $(DOCDIR)
+ $(COPY_R) %{doc_output_dir}/* $(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
+
+ $(MKDIR_INSTALL) $(LIBDIR)
$(INSTALL_CMD_DATA) $(STATIC_LIB) $(LIBDIR)
+
+ $(MKDIR_INSTALL) $(BINDIR)
$(INSTALL_CMD_EXEC) $(CONFIG_SCRIPT) $(BINDIR)
+
+ $(MKDIR_INSTALL) $(PKGCONF_DIR)
$(INSTALL_CMD_DATA) $(PKGCONFIG) $(PKGCONF_DIR)
diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in
index aaedeeaf8..31060afbb 100644
--- a/src/build-data/makefile/unix_shr.in
+++ b/src/build-data/makefile/unix_shr.in
@@ -11,14 +11,14 @@ LINK_TO = %{link_to}
# Version Numbers
VERSION = %{version}
-SO_VERSION = %{so_version}
+SERIES = %{version_major}.%{version_minor}
# Installation Settings
DESTDIR = %{prefix}
BINDIR = $(DESTDIR)/bin
LIBDIR = $(DESTDIR)/%{libdir}
-HEADERDIR = $(DESTDIR)/%{includedir}/botan
+HEADERDIR = $(DESTDIR)/%{includedir}/botan-$(SERIES)/botan
DOCDIR = $(DESTDIR)/%{docdir}/botan-$(VERSION)
PKGCONF_DIR = $(LIBDIR)/pkgconfig
@@ -27,6 +27,8 @@ PKGCONFIG = %{botan_pkgconfig}
# Aliases for Common Programs
AR = %{ar_command}
+COPY = cp
+COPY_R = cp -r
CD = @cd
ECHO = @echo
INSTALL_CMD_EXEC = %{install_cmd_exec}
@@ -41,8 +43,6 @@ RM_R = @rm -rf
# File Lists
CHECK = %{check_prefix}check
-DOCS = %{doc_files}
-
HEADERS = %{include_files}
LIBOBJS = %{lib_objs}
@@ -55,12 +55,12 @@ CHECK_FLAGS = $(CHECK_OPT) $(LANG_FLAGS) $(WARN_FLAGS)
LIBRARIES = $(STATIC_LIB) $(SHARED_LIB)
LIBNAME = %{lib_prefix}libbotan
-STATIC_LIB = $(LIBNAME).a
+STATIC_LIB = $(LIBNAME)-$(SERIES).a
-SHARED_LIB = $(LIBNAME)-$(SO_VERSION).%{so_suffix}
-SONAME = $(LIBNAME)-$(SO_VERSION).%{so_suffix}
+SONAME = $(LIBNAME)-$(SERIES).%{so_suffix}.%{so_abi_rev}
+SHARED_LIB = $(SONAME).%{version_patch}
-SYMLINK = libbotan.%{so_suffix}
+SYMLINK = $(LIBNAME)-$(SERIES).%{so_suffix}
all: $(LIBRARIES)
@@ -71,7 +71,7 @@ all: $(LIBRARIES)
# Link Commands
$(CHECK): $(LIBRARIES) $(CHECKOBJS)
- $(CXX) $(LDFLAGS) $(CHECKOBJS) -o $(CHECK) -L. -lbotan-%{so_version} $(LINK_TO)
+ $(CXX) $(LDFLAGS) $(CHECKOBJS) $(SHARED_LIB) $(LINK_TO) -o $(CHECK)
$(STATIC_LIB): $(LIBOBJS)
$(RM) $(STATIC_LIB)
@@ -80,42 +80,46 @@ $(STATIC_LIB): $(LIBOBJS)
$(SHARED_LIB): $(LIBOBJS)
$(SO_LINK_CMD) $(LDFLAGS) $(LIBOBJS) -o $(SHARED_LIB) $(LINK_TO)
+ $(LN) $(SHARED_LIB) $(SONAME)
$(LN) $(SHARED_LIB) $(SYMLINK)
# Fake Targets
-.PHONY = doxygen clean distclean install static shared
+.PHONY = docs clean distclean install static shared
static: $(STATIC_LIB)
shared: $(SHARED_LIB)
-doxygen:
- doxygen %{build_dir}/botan.doxy
+docs:
+%{build_doc_commands}
clean:
$(RM_R) %{build_dir}/lib/* %{build_dir}/checks/*
- $(RM) $(LIBRARIES) $(SYMLINK) $(CHECK)
+ $(RM) $(LIBRARIES) $(SYMLINK) $(SONAME) $(CHECK)
distclean: clean
$(RM_R) %{build_dir}
- $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy
$(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG)
+ $(RM) botan_all.cpp botan_all.h
-install: $(LIBRARIES)
+install: $(LIBRARIES) docs
$(ECHO) "Installing Botan into $(DESTDIR)... "
$(MKDIR_INSTALL) $(DOCDIR)
+ $(COPY_R) %{doc_output_dir}/* $(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
+
+ $(MKDIR_INSTALL) $(LIBDIR)
$(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)
+ $(CD) $(LIBDIR); $(LN) $(SHARED_LIB) $(SONAME)
+
+ $(MKDIR_INSTALL) $(BINDIR)
+ $(INSTALL_CMD_EXEC) $(CONFIG_SCRIPT) $(BINDIR)
+
+ $(MKDIR_INSTALL) $(PKGCONF_DIR)
+ $(INSTALL_CMD_DATA) $(PKGCONFIG) $(PKGCONF_DIR)
diff --git a/src/build-data/os/beos.txt b/src/build-data/os/beos.txt
deleted file mode 100644
index 4a16b6326..000000000
--- a/src/build-data/os/beos.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-os_type beos
-
-install_root /boot/beos
-header_dir ../develop/headers
-lib_dir system/lib
-doc_dir documentation
-
-<target_features>
-gettimeofday
-</target_features>
-
-<aliases>
-haiku
-</aliases>
diff --git a/src/build-data/os/haiku.txt b/src/build-data/os/haiku.txt
new file mode 100644
index 000000000..8e35e76eb
--- /dev/null
+++ b/src/build-data/os/haiku.txt
@@ -0,0 +1,15 @@
+os_type unix
+
+install_root /boot
+header_dir develop/headers
+lib_dir system/lib
+doc_dir system/documentation
+
+<target_features>
+gettimeofday
+gmtime_r
+</target_features>
+
+<aliases>
+beos
+</aliases>
diff --git a/src/build-data/os/mingw.txt b/src/build-data/os/mingw.txt
index 08f85b4db..5daabac90 100644
--- a/src/build-data/os/mingw.txt
+++ b/src/build-data/os/mingw.txt
@@ -14,9 +14,6 @@ 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
diff --git a/src/build-data/os/qnx.txt b/src/build-data/os/qnx.txt
index 369b720c4..4c0965764 100644
--- a/src/build-data/os/qnx.txt
+++ b/src/build-data/os/qnx.txt
@@ -1,5 +1,9 @@
os_type unix
<target_features>
+clock_gettime
gettimeofday
+posix_mlock
+gmtime_r
+dlopen
</target_features>
diff --git a/src/build-data/os/solaris.txt b/src/build-data/os/solaris.txt
index 47e7bccbc..0ed785036 100644
--- a/src/build-data/os/solaris.txt
+++ b/src/build-data/os/solaris.txt
@@ -1,5 +1,8 @@
os_type unix
+install_cmd_data '/usr/ucb/install -m 644'
+install_cmd_exec '/usr/ucb/install -m 755'
+
<target_features>
posix_mlock
gettimeofday
diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp
index 4b6c5af8c..1646adeef 100644
--- a/src/cert/cvc/cvc_self.cpp
+++ b/src/cert/cvc/cvc_self.cpp
@@ -41,7 +41,7 @@ MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key,
if(key->domain_format() == EC_DOMPAR_ENC_OID)
throw Encoding_Error("CVC encoder: cannot encode parameters by OID");
- const EC_Domain_Params& domain = key->domain();
+ const EC_Group& domain = key->domain();
// This is why we can't have nice things
diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt
index d6281802b..3cf759188 100644
--- a/src/cert/cvc/info.txt
+++ b/src/cert/cvc/info.txt
@@ -1,5 +1,5 @@
define CARD_VERIFIABLE_CERTIFICATES
-load_on auto
+load_on request
<header:public>
cvc_ado.h
diff --git a/src/cert/x509ca/x509_ca.cpp b/src/cert/x509ca/x509_ca.cpp
index b97b106f8..37b4f44b4 100644
--- a/src/cert/x509ca/x509_ca.cpp
+++ b/src/cert/x509ca/x509_ca.cpp
@@ -94,7 +94,7 @@ X509_Certificate X509_CA::make_cert(PK_Signer* signer,
const Extensions& extensions)
{
const size_t X509_CERT_VERSION = 3;
- const size_t SERIAL_BITS = 256;
+ const size_t SERIAL_BITS = 128;
BigInt serial_no(rng, SERIAL_BITS);
diff --git a/src/cert/x509cert/x509_ext.cpp b/src/cert/x509cert/x509_ext.cpp
index 462b29669..6e0befaf3 100644
--- a/src/cert/x509cert/x509_ext.cpp
+++ b/src/cert/x509cert/x509_ext.cpp
@@ -443,6 +443,9 @@ class Policy_Information : public ASN1_Object
public:
OID oid;
+ Policy_Information() {}
+ Policy_Information(const OID& oid) : oid(oid) {}
+
void encode_into(DER_Encoder& codec) const
{
codec.start_cons(SEQUENCE)
@@ -466,18 +469,16 @@ class Policy_Information : public ASN1_Object
*/
MemoryVector<byte> Certificate_Policies::encode_inner() const
{
- // FIXME
-#if 1
- throw Internal_Error("Certificate_Policies::encode_inner: Bugged");
-#else
std::vector<Policy_Information> policies;
+ for(size_t i = 0; i != oids.size(); ++i)
+ policies.push_back(oids[i]);
+
return DER_Encoder()
.start_cons(SEQUENCE)
.encode_list(policies)
.end_cons()
.get_contents();
-#endif
}
/*
@@ -491,6 +492,10 @@ void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in)
.start_cons(SEQUENCE)
.decode_list(policies)
.end_cons();
+
+ oids.clear();
+ for(size_t i = 0; i != policies.size(); ++i)
+ oids.push_back(policies[i].oid);
}
/*
diff --git a/src/cert/x509cert/x509cert.cpp b/src/cert/x509cert/x509cert.cpp
index 40b61b47d..1d7e51d08 100644
--- a/src/cert/x509cert/x509cert.cpp
+++ b/src/cert/x509cert/x509cert.cpp
@@ -390,8 +390,12 @@ std::string X509_Certificate::to_string() const
OIDS::lookup(this->signature_algorithm().oid) << "\n";
out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
- out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
- out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
+
+ if(this->authority_key_id().size())
+ out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
+
+ if(this->subject_key_id().size())
+ out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
X509_PublicKey* pubkey = this->subject_public_key();
out << "Public Key:\n" << X509::PEM_encode(*pubkey);
diff --git a/src/cms/cms_algo.cpp b/src/cms/cms_algo.cpp
index 50384d85a..3c245cc6f 100644
--- a/src/cms/cms_algo.cpp
+++ b/src/cms/cms_algo.cpp
@@ -99,7 +99,7 @@ SecureVector<byte> CMS_Encoder::wrap_key(RandomNumberGenerator& rng,
throw Encoding_Error("CMS: 128-bit KEKs must be used with " + cipher);
SecureVector<byte> lcekpad;
- lcekpad.push_back((byte)cek.length());
+ lcekpad.push_back(static_cast<byte>(cek.length()));
lcekpad += cek.bits_of();
while(lcekpad.size() % 8)
lcekpad.push_back(rng.next_byte());
diff --git a/src/cms/cms_dec.cpp b/src/cms/cms_dec.cpp
index c86e1d0ae..a9f4e69d9 100644
--- a/src/cms/cms_dec.cpp
+++ b/src/cms/cms_dec.cpp
@@ -86,7 +86,9 @@ 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[0], data.size());
+
+ return std::string(reinterpret_cast<const char*>(&data[0]),
+ data.size());
}
/*
diff --git a/src/cms/cms_enc.cpp b/src/cms/cms_enc.cpp
index cd739ef08..1a45a6a46 100644
--- a/src/cms/cms_enc.cpp
+++ b/src/cms/cms_enc.cpp
@@ -30,7 +30,7 @@ void CMS_Encoder::set_data(const byte buf[], size_t length)
*/
void CMS_Encoder::set_data(const std::string& str)
{
- set_data((const byte*)str.c_str(), str.length());
+ set_data(reinterpret_cast<const byte*>(str.c_str()), str.length());
}
/*
diff --git a/src/cms/info.txt b/src/cms/info.txt
index dc2110ae5..34e2c089c 100644
--- a/src/cms/info.txt
+++ b/src/cms/info.txt
@@ -1,5 +1,7 @@
define CMS
+load_on request
+
<requires>
asn1
bigint
diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp
index d6c5ec7c0..6a53a7a9a 100644
--- a/src/codec/base64/base64.cpp
+++ b/src/codec/base64/base64.cpp
@@ -97,5 +97,155 @@ std::string base64_encode(const MemoryRegion<byte>& input)
return base64_encode(&input[0], input.size());
}
+size_t base64_decode(byte output[],
+ const char input[],
+ size_t input_length,
+ size_t& input_consumed,
+ bool final_inputs,
+ bool ignore_ws)
+ {
+ /*
+ * Base64 Decoder Lookup Table
+ * Warning: assumes ASCII encodings
+ */
+ static const byte BASE64_TO_BIN[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
+ 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35,
+ 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
+ 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ byte* out_ptr = output;
+ byte decode_buf[4];
+ size_t decode_buf_pos = 0;
+ size_t final_truncate = 0;
+
+ clear_mem(output, input_length * 3 / 4);
+
+ for(size_t i = 0; i != input_length; ++i)
+ {
+ const byte bin = BASE64_TO_BIN[static_cast<byte>(input[i])];
+
+ if(bin <= 0x3F)
+ {
+ decode_buf[decode_buf_pos] = bin;
+ decode_buf_pos += 1;
+ }
+ else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
+ {
+ std::string bad_char(1, input[i]);
+ if(bad_char == "\t")
+ bad_char = "\\t";
+ else if(bad_char == "\n")
+ bad_char = "\\n";
+ else if(bad_char == "\r")
+ bad_char = "\\r";
+
+ throw std::invalid_argument(
+ std::string("base64_decode: invalid base64 character '") +
+ bad_char + "'");
+ }
+
+ /*
+ * If we're at the end of the input, pad with 0s and truncate
+ */
+ if(final_inputs && (i == input_length - 1))
+ {
+ if(decode_buf_pos)
+ {
+ for(size_t i = decode_buf_pos; i != 4; ++i)
+ decode_buf[i] = 0;
+ final_truncate = (4 - decode_buf_pos);
+ decode_buf_pos = 4;
+ }
+ }
+
+ if(decode_buf_pos == 4)
+ {
+ out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
+ out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
+ out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
+
+ out_ptr += 3;
+ decode_buf_pos = 0;
+ input_consumed = i+1;
+ }
+ }
+
+ while(input_consumed < input_length &&
+ BASE64_TO_BIN[static_cast<byte>(input[input_consumed])] == 0x80)
+ {
+ ++input_consumed;
+ }
+
+ size_t written = (out_ptr - output) - final_truncate;
+
+ return written;
+ }
+
+size_t base64_decode(byte output[],
+ const char input[],
+ size_t input_length,
+ bool ignore_ws)
+ {
+ size_t consumed = 0;
+ size_t written = base64_decode(output, input, input_length,
+ consumed, true, ignore_ws);
+
+ if(consumed != input_length)
+ throw std::invalid_argument("base64_decode: input did not have full bytes");
+
+ return written;
+ }
+
+size_t base64_decode(byte output[],
+ const std::string& input,
+ bool ignore_ws)
+ {
+ return base64_decode(output, &input[0], input.length(), ignore_ws);
+ }
+
+SecureVector<byte> base64_decode(const char input[],
+ size_t input_length,
+ bool ignore_ws)
+ {
+ SecureVector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4);
+
+ size_t written = base64_decode(&bin[0],
+ input,
+ input_length,
+ ignore_ws);
+
+ bin.resize(written);
+ return bin;
+ }
+
+SecureVector<byte> base64_decode(const std::string& input,
+ bool ignore_ws)
+ {
+ return base64_decode(&input[0], input.size(), ignore_ws);
+ }
+
}
diff --git a/src/codec/base64/base64.h b/src/codec/base64/base64.h
index 6daac73d8..23a2558bd 100644
--- a/src/codec/base64/base64.h
+++ b/src/codec/base64/base64.h
@@ -48,6 +48,76 @@ std::string BOTAN_DLL base64_encode(const byte input[],
*/
std::string BOTAN_DLL base64_encode(const MemoryRegion<byte>& input);
+/**
+* Perform base64 decoding
+* @param output an array of at least input_length*3/4 bytes
+* @param input some base64 input
+* @param input_length length of input in bytes
+* @param input_consumed is an output parameter which says how many
+* bytes of input were actually consumed. If less than
+* input_length, then the range input[consumed:length]
+* should be passed in later along with more input.
+* @param final_inputs true iff this is the last input, in which case
+ padding is allowed
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+size_t BOTAN_DLL base64_decode(byte output[],
+ const char input[],
+ size_t input_length,
+ size_t& input_consumed,
+ bool final_inputs,
+ bool ignore_ws = true);
+
+/**
+* Perform base64 decoding
+* @param output an array of at least input_length*3/4 bytes
+* @param input some base64 input
+* @param input_length length of input in bytes
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+size_t BOTAN_DLL base64_decode(byte output[],
+ const char input[],
+ size_t input_length,
+ bool ignore_ws = true);
+
+/**
+* Perform base64 decoding
+* @param output an array of at least input_length/3*4 bytes
+* @param input some base64 input
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+size_t BOTAN_DLL base64_decode(byte output[],
+ const std::string& input,
+ bool ignore_ws = true);
+
+/**
+* Perform base64 decoding
+* @param input some base64 input
+* @param input_length the length of input in bytes
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return decoded base64 output
+*/
+SecureVector<byte> BOTAN_DLL base64_decode(const char input[],
+ size_t input_length,
+ bool ignore_ws = true);
+
+/**
+* Perform base64 decoding
+* @param input some base64 input
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return decoded base64 output
+*/
+SecureVector<byte> BOTAN_DLL base64_decode(const std::string& input,
+ bool ignore_ws = true);
+
}
#endif
diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp
index 596e0e235..41ba1298d 100644
--- a/src/codec/hex/hex.cpp
+++ b/src/codec/hex/hex.cpp
@@ -37,9 +37,7 @@ void hex_encode(char output[],
std::string hex_encode(const MemoryRegion<byte>& input,
bool uppercase)
{
- return hex_encode(&input[0],
- input.size(),
- uppercase);
+ return hex_encode(&input[0], input.size(), uppercase);
}
std::string hex_encode(const byte input[],
@@ -47,7 +45,10 @@ std::string hex_encode(const byte input[],
bool uppercase)
{
std::string output(2 * input_length, 0);
- hex_encode(&output[0], input, input_length, uppercase);
+
+ if(input_length)
+ hex_encode(&output[0], input, input_length, uppercase);
+
return output;
}
@@ -101,7 +102,7 @@ size_t hex_decode(byte output[],
for(size_t i = 0; i != input_length; ++i)
{
- const byte bin = HEX_TO_BIN[(byte)input[i]];
+ const byte bin = HEX_TO_BIN[static_cast<byte>(input[i])];
if(bin >= 0x10)
{
diff --git a/src/constructs/fpe/fpe.cpp b/src/constructs/fpe_fe1/fpe_fe1.cpp
index 1023b067c..91d328c17 100644
--- a/src/constructs/fpe/fpe.cpp
+++ b/src/constructs/fpe_fe1/fpe_fe1.cpp
@@ -8,7 +8,7 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/fpe.h>
+#include <botan/fpe_fe1.h>
#include <botan/numthry.h>
#include <botan/hmac.h>
#include <botan/sha2_32.h>
@@ -16,6 +16,8 @@
namespace Botan {
+namespace FPE {
+
namespace {
// Normally FPE is for SSNs, CC#s, etc, nothing too big
@@ -105,10 +107,10 @@ FPE_Encryptor::FPE_Encryptor(const SymmetricKey& key,
if(n_bin.size() > MAX_N_BYTES)
throw std::runtime_error("N is too large for FPE encryption");
- mac->update_be((u32bit)n_bin.size());
+ mac->update_be(static_cast<u32bit>(n_bin.size()));
mac->update(&n_bin[0], n_bin.size());
- mac->update_be((u32bit)tweak.size());
+ mac->update_be(static_cast<u32bit>(tweak.size()));
mac->update(&tweak[0], tweak.size());
mac_n_t = mac->final();
@@ -119,9 +121,9 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R)
SecureVector<byte> r_bin = BigInt::encode(R);
mac->update(mac_n_t);
- mac->update_be((u32bit)round_no);
+ mac->update_be(static_cast<u32bit>(round_no));
- mac->update_be((u32bit)r_bin.size());
+ mac->update_be(static_cast<u32bit>(r_bin.size()));
mac->update(&r_bin[0], r_bin.size());
SecureVector<byte> X = mac->final();
@@ -133,7 +135,7 @@ BigInt FPE_Encryptor::operator()(size_t round_no, const BigInt& R)
/*
* Generic Z_n FPE encryption, FE1 scheme
*/
-BigInt fpe_encrypt(const BigInt& n, const BigInt& X0,
+BigInt fe1_encrypt(const BigInt& n, const BigInt& X0,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak)
{
@@ -161,7 +163,7 @@ BigInt fpe_encrypt(const BigInt& n, const BigInt& X0,
/*
* Generic Z_n FPE decryption, FD1 scheme
*/
-BigInt fpe_decrypt(const BigInt& n, const BigInt& X0,
+BigInt fe1_decrypt(const BigInt& n, const BigInt& X0,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak)
{
@@ -187,3 +189,5 @@ BigInt fpe_decrypt(const BigInt& n, const BigInt& X0,
}
}
+
+}
diff --git a/src/constructs/fpe/fpe.h b/src/constructs/fpe_fe1/fpe_fe1.h
index 7a4a7861a..da9a6bcb6 100644
--- a/src/constructs/fpe/fpe.h
+++ b/src/constructs/fpe_fe1/fpe_fe1.h
@@ -1,18 +1,20 @@
/*
-* Format Preserving Encryption
+* Format Preserving Encryption (FE1 scheme)
* (C) 2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_FORMAT_PRESERVING_ENCRYPTION_H__
-#define BOTAN_FORMAT_PRESERVING_ENCRYPTION_H__
+#ifndef BOTAN_FPE_FE1_H__
+#define BOTAN_FPE_FE1_H__
#include <botan/bigint.h>
#include <botan/symkey.h>
namespace Botan {
+namespace FPE {
+
/**
* Encrypt X from and onto the group Z_n using key and tweak
* @param n the modulus
@@ -20,7 +22,7 @@ namespace Botan {
* @param key a random key
* @param tweak will modify the ciphertext (think of as an IV)
*/
-BigInt BOTAN_DLL fpe_encrypt(const BigInt& n, const BigInt& X,
+BigInt BOTAN_DLL fe1_encrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak);
@@ -31,10 +33,12 @@ BigInt BOTAN_DLL fpe_encrypt(const BigInt& n, const BigInt& X,
* @param key is the key used for encryption
* @param tweak the same tweak used for encryption
*/
-BigInt BOTAN_DLL fpe_decrypt(const BigInt& n, const BigInt& X,
+BigInt BOTAN_DLL fe1_decrypt(const BigInt& n, const BigInt& X,
const SymmetricKey& key,
const MemoryRegion<byte>& tweak);
}
+}
+
#endif
diff --git a/src/constructs/fpe/info.txt b/src/constructs/fpe_fe1/info.txt
index 078eb2135..33b5a1c80 100644
--- a/src/constructs/fpe/info.txt
+++ b/src/constructs/fpe_fe1/info.txt
@@ -1,4 +1,4 @@
-define FORMAT_PRESERVING_ENCRYPTION
+define FPE_FE1
<requires>
hmac
diff --git a/src/engine/aes_isa_eng/aes_isa_engine.cpp b/src/engine/aes_isa_eng/aes_isa_engine.cpp
index 7f541d583..e56f6e9ca 100644
--- a/src/engine/aes_isa_eng/aes_isa_engine.cpp
+++ b/src/engine/aes_isa_eng/aes_isa_engine.cpp
@@ -8,8 +8,8 @@
#include <botan/internal/aes_isa_engine.h>
#include <botan/cpuid.h>
-#if defined(BOTAN_HAS_AES_INTEL)
- #include <botan/aes_intel.h>
+#if defined(BOTAN_HAS_AES_NI)
+ #include <botan/aes_ni.h>
#endif
namespace Botan {
@@ -18,15 +18,15 @@ BlockCipher*
AES_ISA_Engine::find_block_cipher(const SCAN_Name& request,
Algorithm_Factory&) const
{
-#if defined(BOTAN_HAS_AES_INTEL)
+#if defined(BOTAN_HAS_AES_NI)
if(CPUID::has_aes_ni())
{
if(request.algo_name() == "AES-128")
- return new AES_128_Intel;
+ return new AES_128_NI;
if(request.algo_name() == "AES-192")
- return new AES_192_Intel;
+ return new AES_192_NI;
if(request.algo_name() == "AES-256")
- return new AES_256_Intel;
+ return new AES_256_NI;
}
#endif
diff --git a/src/engine/asm_engine/asm_engine.cpp b/src/engine/asm_engine/asm_engine.cpp
index 747e8c00f..6d475136f 100644
--- a/src/engine/asm_engine/asm_engine.cpp
+++ b/src/engine/asm_engine/asm_engine.cpp
@@ -7,24 +7,24 @@
#include <botan/internal/asm_engine.h>
-#if defined(BOTAN_HAS_SERPENT_IA32)
- #include <botan/serp_ia32.h>
+#if defined(BOTAN_HAS_SERPENT_X86_32)
+ #include <botan/serp_x86_32.h>
#endif
-#if defined(BOTAN_HAS_MD4_IA32)
- #include <botan/md4_ia32.h>
+#if defined(BOTAN_HAS_MD4_X86_32)
+ #include <botan/md4_x86_32.h>
#endif
-#if defined(BOTAN_HAS_MD5_IA32)
- #include <botan/md5_ia32.h>
+#if defined(BOTAN_HAS_MD5_X86_32)
+ #include <botan/md5_x86_32.h>
#endif
-#if defined(BOTAN_HAS_SHA1_AMD64)
- #include <botan/sha1_amd64.h>
+#if defined(BOTAN_HAS_SHA1_X86_64)
+ #include <botan/sha1_x86_64.h>
#endif
-#if defined(BOTAN_HAS_SHA1_IA32)
- #include <botan/sha1_ia32.h>
+#if defined(BOTAN_HAS_SHA1_X86_32)
+ #include <botan/sha1_x86_32.h>
#endif
namespace Botan {
@@ -35,8 +35,8 @@ Assembler_Engine::find_block_cipher(const SCAN_Name& request,
{
if(request.algo_name() == "Serpent")
{
-#if defined(BOTAN_HAS_SERPENT_IA32)
- return new Serpent_IA32;
+#if defined(BOTAN_HAS_SERPENT_X86_32)
+ return new Serpent_X86_32;
#endif
}
@@ -47,24 +47,24 @@ HashFunction*
Assembler_Engine::find_hash(const SCAN_Name& request,
Algorithm_Factory&) const
{
-#if defined(BOTAN_HAS_MD4_IA32)
+#if defined(BOTAN_HAS_MD4_X86_32)
if(request.algo_name() == "MD4")
- return new MD4_IA32;
+ return new MD4_X86_32;
#endif
-#if defined(BOTAN_HAS_MD5_IA32)
+#if defined(BOTAN_HAS_MD5_X86_32)
if(request.algo_name() == "MD5")
- return new MD5_IA32;
+ return new MD5_X86_32;
#endif
if(request.algo_name() == "SHA-160")
- {
-#if defined(BOTAN_HAS_SHA1_AMD64)
- return new SHA_160_AMD64;
-#elif defined(BOTAN_HAS_SHA1_IA32)
- return new SHA_160_IA32;
+ {
+#if defined(BOTAN_HAS_SHA1_X86_64)
+ return new SHA_160_X86_64;
+#elif defined(BOTAN_HAS_SHA1_X86_32)
+ return new SHA_160_X86_32;
#endif
- }
+ }
return 0;
}
diff --git a/src/engine/asm_engine/asm_engine.h b/src/engine/asm_engine/asm_engine.h
index e3e9a546c..bd82566d3 100644
--- a/src/engine/asm_engine/asm_engine.h
+++ b/src/engine/asm_engine/asm_engine.h
@@ -5,8 +5,8 @@
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_IA32_ASM_ENGINE_H__
-#define BOTAN_IA32_ASM_ENGINE_H__
+#ifndef BOTAN_X86_32_ASM_ENGINE_H__
+#define BOTAN_X86_32_ASM_ENGINE_H__
#include <botan/engine.h>
diff --git a/src/engine/simd_engine/info.txt b/src/engine/simd_engine/info.txt
index cddb7524a..229b1daaf 100644
--- a/src/engine/simd_engine/info.txt
+++ b/src/engine/simd_engine/info.txt
@@ -9,3 +9,7 @@ simd_engine.cpp
<header:internal>
simd_engine.h
</header:internal>
+
+<requires>
+simd
+</requires>
diff --git a/src/entropy/beos_stats/es_beos.cpp b/src/entropy/beos_stats/es_beos.cpp
index 2b4a7a24f..e514eb121 100644
--- a/src/entropy/beos_stats/es_beos.cpp
+++ b/src/entropy/beos_stats/es_beos.cpp
@@ -26,8 +26,6 @@ void BeOS_EntropySource::poll(Entropy_Accumulator& accum)
get_key_info(&info_key);
accum.add(info_key, 0);
- accum.add(idle_time(), 0);
-
team_info info_team;
int32 cookie_team = 0;
diff --git a/src/entropy/beos_stats/info.txt b/src/entropy/beos_stats/info.txt
index 088b926f9..c7ed9fe5a 100644
--- a/src/entropy/beos_stats/info.txt
+++ b/src/entropy/beos_stats/info.txt
@@ -9,9 +9,9 @@ es_beos.h
</header:internal>
<os>
-beos
+haiku
</os>
<libs>
-beos -> root,be
+haiku -> root,be
</libs>
diff --git a/src/entropy/dev_random/dev_random.cpp b/src/entropy/dev_random/dev_random.cpp
index b15240aba..d14ae43ae 100644
--- a/src/entropy/dev_random/dev_random.cpp
+++ b/src/entropy/dev_random/dev_random.cpp
@@ -12,6 +12,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <string.h>
namespace Botan {
diff --git a/src/entropy/dev_random/info.txt b/src/entropy/dev_random/info.txt
index cabb47ea2..4c69a57f4 100644
--- a/src/entropy/dev_random/info.txt
+++ b/src/entropy/dev_random/info.txt
@@ -10,11 +10,11 @@ dev_random.h
<os>
aix
-beos
cygwin
darwin
-freebsd
dragonfly
+freebsd
+haiku
hpux
hurd
irix
diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp
index d2ce2706b..b2b629930 100644
--- a/src/entropy/egd/es_egd.cpp
+++ b/src/entropy/egd/es_egd.cpp
@@ -89,7 +89,7 @@ size_t EGD_EntropySource::EGD_Socket::read(byte outbuf[], size_t length)
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");
+ throw std::runtime_error("Bogus length field received from EGD");
ssize_t count = ::read(m_fd, outbuf, out_len);
diff --git a/src/entropy/hres_timer/hres_timer.cpp b/src/entropy/hres_timer/hres_timer.cpp
index b0f99170a..a10cdaf46 100644
--- a/src/entropy/hres_timer/hres_timer.cpp
+++ b/src/entropy/hres_timer/hres_timer.cpp
@@ -32,13 +32,13 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
if(CPUID::has_rdtsc()) // not availble on all x86 CPUs
{
- size_t rtc_low = 0, rtc_high = 0;
+ 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_CPU_IS_PPC_FAMILY)
- size_t rtc_low = 0, rtc_high = 0;
+ 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;
diff --git a/src/entropy/unix_procs/info.txt b/src/entropy/unix_procs/info.txt
index 2100584e4..d2a15f13d 100644
--- a/src/entropy/unix_procs/info.txt
+++ b/src/entropy/unix_procs/info.txt
@@ -13,10 +13,10 @@ unix_cmd.h
<os>
aix
-beos
cygwin
darwin
-#freebsd
+freebsd
+haiku
hpux
irix
linux
diff --git a/src/entropy/unix_procs/unix_cmd.cpp b/src/entropy/unix_procs/unix_cmd.cpp
index f4ae5054c..930444075 100644
--- a/src/entropy/unix_procs/unix_cmd.cpp
+++ b/src/entropy/unix_procs/unix_cmd.cpp
@@ -12,6 +12,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
diff --git a/src/filters/codec_filt/b64_filt.cpp b/src/filters/codec_filt/b64_filt.cpp
index 8a90f8b5f..9341571d4 100644
--- a/src/filters/codec_filt/b64_filt.cpp
+++ b/src/filters/codec_filt/b64_filt.cpp
@@ -14,32 +14,6 @@
namespace Botan {
/*
-* Base64 Decoder Lookup Table
-* Warning: assumes ASCII encodings
-*/
-static const byte 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 };
-
-/*
* Base64_Encoder Constructor
*/
Base64_Encoder::Base64_Encoder(bool breaks, size_t length, bool t_n) :
@@ -68,6 +42,7 @@ void Base64_Encoder::encode_and_send(const byte input[], size_t length,
do_output(&out[0], produced);
+ // FIXME: s/proc/consumed/?
input += proc;
length -= proc;
}
@@ -138,58 +113,9 @@ void Base64_Encoder::end_msg()
/*
* Base64_Decoder Constructor
*/
-Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
- {
- in.resize(48);
- out.resize(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[], size_t length)
- {
- for(size_t i = 0; i != length; i += 4)
- {
- decode(block + i, &out[0]);
- send(out, 3);
- }
- }
-
-/*
-* Handle processing an invalid character
-*/
-void Base64_Decoder::handle_bad_char(byte c)
+Base64_Decoder::Base64_Decoder(Decoder_Checking c) :
+ checking(c), in(64), out(48), position(0)
{
- 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) + "'"
- );
}
/*
@@ -197,18 +123,32 @@ void Base64_Decoder::handle_bad_char(byte c)
*/
void Base64_Decoder::write(const byte input[], size_t length)
{
- for(size_t i = 0; i != length; ++i)
+ while(length)
{
- if(is_valid(input[i]))
- in[position++] = input[i];
- else
- handle_bad_char(input[i]);
+ size_t to_copy = std::min<size_t>(length, in.size() - position);
+ copy_mem(&in[position], input, to_copy);
+ position += to_copy;
+
+ size_t consumed = 0;
+ size_t written = base64_decode(&out[0],
+ reinterpret_cast<const char*>(&in[0]),
+ position,
+ consumed,
+ false,
+ checking != FULL_CHECK);
+
+ send(out, written);
- if(position == in.size())
+ if(consumed != position)
{
- decode_and_send(&in[0], in.size());
- position = 0;
+ copy_mem(&in[0], &in[consumed], position - consumed);
+ position = position - consumed;
}
+ else
+ position = 0;
+
+ length -= to_copy;
+ input += to_copy;
}
}
@@ -217,21 +157,22 @@ void Base64_Decoder::write(const byte input[], size_t length)
*/
void Base64_Decoder::end_msg()
{
- if(position != 0)
- {
- size_t start_of_last_block = 4 * (position / 4),
- left_over = position % 4;
- decode_and_send(&in[0], start_of_last_block);
+ size_t consumed = 0;
+ size_t written = base64_decode(&out[0],
+ reinterpret_cast<const char*>(&in[0]),
+ position,
+ consumed,
+ true,
+ checking != FULL_CHECK);
+
+ send(out, written);
+
+ const bool not_full_bytes = consumed != position;
- if(left_over)
- {
- SecureVector<byte> remainder(4);
- copy_mem(&remainder[0], &in[start_of_last_block], left_over);
- decode(&remainder[0], &out[0]);
- send(out, ((left_over == 1) ? (1) : (left_over - 1)));
- }
- }
position = 0;
+
+ if(not_full_bytes)
+ throw std::invalid_argument("Base64_Decoder: Input not full bytes");
}
}
diff --git a/src/filters/codec_filt/b64_filt.h b/src/filters/codec_filt/b64_filt.h
index df3896666..afff53f30 100644
--- a/src/filters/codec_filt/b64_filt.h
+++ b/src/filters/codec_filt/b64_filt.h
@@ -47,7 +47,7 @@ class BOTAN_DLL Base64_Encoder : public Filter
const size_t line_length;
const bool trailing_newline;
- SecureVector<byte> in, out;
+ MemoryVector<byte> in, out;
size_t position, out_position;
};
@@ -78,14 +78,8 @@ class BOTAN_DLL Base64_Decoder : public Filter
*/
Base64_Decoder(Decoder_Checking checking = NONE);
private:
- static void decode(const byte input[4], byte output[3]);
- static bool is_valid(byte c);
-
- void decode_and_send(const byte[], size_t);
- void handle_bad_char(byte);
-
const Decoder_Checking checking;
- SecureVector<byte> in, out;
+ MemoryVector<byte> in, out;
size_t position;
};
diff --git a/src/filters/codec_filt/hex_filt.h b/src/filters/codec_filt/hex_filt.h
index cfbb818d3..0dc38c804 100644
--- a/src/filters/codec_filt/hex_filt.h
+++ b/src/filters/codec_filt/hex_filt.h
@@ -49,7 +49,7 @@ class BOTAN_DLL Hex_Encoder : public Filter
const Case casing;
const size_t line_length;
- SecureVector<byte> in, out;
+ MemoryVector<byte> in, out;
size_t position, counter;
};
@@ -72,7 +72,7 @@ class BOTAN_DLL Hex_Decoder : public Filter
Hex_Decoder(Decoder_Checking checking = NONE);
private:
const Decoder_Checking checking;
- SecureVector<byte> in, out;
+ MemoryVector<byte> in, out;
size_t position;
};
diff --git a/src/filters/fd_unix/info.txt b/src/filters/fd_unix/info.txt
index 9c3d0acbc..d636035f0 100644
--- a/src/filters/fd_unix/info.txt
+++ b/src/filters/fd_unix/info.txt
@@ -4,11 +4,11 @@ load_on auto
<os>
aix
-beos
cygwin
darwin
-freebsd
dragonfly
+freebsd
+haiku
hpux
irix
linux
diff --git a/src/hash/bmw/bmw_512.cpp b/src/hash/bmw_512/bmw_512.cpp
index 40338fdf0..40338fdf0 100644
--- a/src/hash/bmw/bmw_512.cpp
+++ b/src/hash/bmw_512/bmw_512.cpp
diff --git a/src/hash/bmw/bmw_512.h b/src/hash/bmw_512/bmw_512.h
index 474b607bb..474b607bb 100644
--- a/src/hash/bmw/bmw_512.h
+++ b/src/hash/bmw_512/bmw_512.h
diff --git a/src/hash/bmw/info.txt b/src/hash/bmw_512/info.txt
index 7170223d7..7170223d7 100644
--- a/src/hash/bmw/info.txt
+++ b/src/hash/bmw_512/info.txt
diff --git a/src/hash/md4_ia32/info.txt b/src/hash/md4_x86_32/info.txt
index 5d14188f2..fdc534df4 100644
--- a/src/hash/md4_ia32/info.txt
+++ b/src/hash/md4_x86_32/info.txt
@@ -1,12 +1,12 @@
-define MD4_IA32
+define MD4_X86_32
load_on asm_ok
<arch>
-ia32
+x86_32
</arch>
<requires>
-asm_ia32
+asm_x86_32
md4
</requires>
diff --git a/src/hash/md4_ia32/md4_ia32.cpp b/src/hash/md4_x86_32/md4_x86_32.cpp
index 98d3c7a19..750e65a95 100644
--- a/src/hash/md4_ia32/md4_ia32.cpp
+++ b/src/hash/md4_x86_32/md4_x86_32.cpp
@@ -1,32 +1,32 @@
/*
-* MD4 (IA-32)
+* MD4 (x86-32)
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/md4_ia32.h>
+#include <botan/md4_x86_32.h>
namespace Botan {
/**
-* MD4 compression function in IA-32 asm
+* MD4 compression function in x86-32 asm
* @param digest the current digest
* @param input the input block
* @param M the message buffer
*/
-extern "C" void botan_md4_ia32_compress(u32bit digest[4],
+extern "C" void botan_md4_x86_32_compress(u32bit digest[4],
const byte input[64],
u32bit M[16]);
/*
* MD4 Compression Function
*/
-void MD4_IA32::compress_n(const byte input[], size_t blocks)
+void MD4_X86_32::compress_n(const byte input[], size_t blocks)
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_md4_ia32_compress(digest, input, M);
+ botan_md4_x86_32_compress(digest, input, M);
input += hash_block_size();
}
}
diff --git a/src/hash/md4_ia32/md4_ia32.h b/src/hash/md4_x86_32/md4_x86_32.h
index 4bb8f1add..a9f23e94f 100644
--- a/src/hash/md4_ia32/md4_ia32.h
+++ b/src/hash/md4_x86_32/md4_x86_32.h
@@ -1,12 +1,12 @@
/*
-* MD4 (IA-32)
+* MD4 (x86-32)
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_MD4_IA32_H__
-#define BOTAN_MD4_IA32_H__
+#ifndef BOTAN_MD4_X86_32_H__
+#define BOTAN_MD4_X86_32_H__
#include <botan/md4.h>
@@ -15,10 +15,10 @@ namespace Botan {
/**
* MD4 using x86 assembly
*/
-class BOTAN_DLL MD4_IA32 : public MD4
+class BOTAN_DLL MD4_X86_32 : public MD4
{
public:
- HashFunction* clone() const { return new MD4_IA32; }
+ HashFunction* clone() const { return new MD4_X86_32; }
private:
void compress_n(const byte[], size_t blocks);
};
diff --git a/src/hash/md4_ia32/md4_ia32_imp.S b/src/hash/md4_x86_32/md4_x86_32_imp.S
index c7e108147..192751166 100644
--- a/src/hash/md4_ia32/md4_ia32_imp.S
+++ b/src/hash/md4_x86_32/md4_x86_32_imp.S
@@ -1,15 +1,15 @@
/*
-* MD4 in IA-32 assembler
+* MD4 in x86-32 assembler
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/asm_macr_ia32.h>
+#include <botan/internal/asm_x86_32.h>
-START_LISTING(md4_ia32.S)
+START_LISTING(md4_x86_32_imp.S)
-START_FUNCTION(botan_md4_ia32_compress)
+START_FUNCTION(botan_md4_x86_32_compress)
SPILL_REGS()
#define PUSHED 4
@@ -134,4 +134,4 @@ LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
ADD(ARRAY4(EBP, 3), EDX)
RESTORE_REGS()
-END_FUNCTION(botan_md4_ia32_compress)
+END_FUNCTION(botan_md4_x86_32_compress)
diff --git a/src/hash/md5_ia32/info.txt b/src/hash/md5_x86_32/info.txt
index 9be698a3f..adec65f81 100644
--- a/src/hash/md5_ia32/info.txt
+++ b/src/hash/md5_x86_32/info.txt
@@ -1,12 +1,12 @@
-define MD5_IA32
+define MD5_X86_32
load_on asm_ok
<arch>
-ia32
+x86_32
</arch>
<requires>
-asm_ia32
+asm_x86_32
md5
</requires>
diff --git a/src/hash/md5_ia32/md5_ia32.cpp b/src/hash/md5_x86_32/md5_x86_32.cpp
index 6ae235d2b..123fcff77 100644
--- a/src/hash/md5_ia32/md5_ia32.cpp
+++ b/src/hash/md5_x86_32/md5_x86_32.cpp
@@ -1,29 +1,29 @@
/*
-* MD5 (IA-32)
+* MD5 (x86-32)
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/md5_ia32.h>
+#include <botan/md5_x86_32.h>
namespace Botan {
namespace {
extern "C"
-void botan_md5_ia32_compress(u32bit[4], const byte[64], u32bit[16]);
+void botan_md5_x86_32_compress(u32bit[4], const byte[64], u32bit[16]);
}
/*
* MD5 Compression Function
*/
-void MD5_IA32::compress_n(const byte input[], size_t blocks)
+void MD5_X86_32::compress_n(const byte input[], size_t blocks)
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_md5_ia32_compress(digest, input, M);
+ botan_md5_x86_32_compress(digest, input, M);
input += hash_block_size();
}
}
diff --git a/src/hash/md5_ia32/md5_ia32.h b/src/hash/md5_x86_32/md5_x86_32.h
index bf4b4c505..0150249ae 100644
--- a/src/hash/md5_ia32/md5_ia32.h
+++ b/src/hash/md5_x86_32/md5_x86_32.h
@@ -1,12 +1,12 @@
/*
-* MD5 (IA-32)
+* MD5 (x86-32)
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_MD5_IA32_H__
-#define BOTAN_MD5_IA32_H__
+#ifndef BOTAN_MD5_X86_32_H__
+#define BOTAN_MD5_X86_32_H__
#include <botan/md5.h>
@@ -15,10 +15,10 @@ namespace Botan {
/**
* MD5 in x86 assembly
*/
-class BOTAN_DLL MD5_IA32 : public MD5
+class BOTAN_DLL MD5_X86_32 : public MD5
{
public:
- HashFunction* clone() const { return new MD5_IA32; }
+ HashFunction* clone() const { return new MD5_X86_32; }
private:
void compress_n(const byte[], size_t blocks);
};
diff --git a/src/hash/md5_ia32/md5_ia32_imp.S b/src/hash/md5_x86_32/md5_x86_32_imp.S
index e77836353..f41aaccbf 100644
--- a/src/hash/md5_ia32/md5_ia32_imp.S
+++ b/src/hash/md5_x86_32/md5_x86_32_imp.S
@@ -1,15 +1,15 @@
/*
-* MD5 in IA-32 assembler
+* MD5 in x86-32 assembler
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/asm_macr_ia32.h>
+#include <botan/internal/asm_x86_32.h>
-START_LISTING(md5_ia32.S)
+START_LISTING(md5_x86_32.S)
-START_FUNCTION(botan_md5_ia32_compress)
+START_FUNCTION(botan_md5_x86_32_compress)
SPILL_REGS()
#define PUSHED 4
@@ -163,4 +163,4 @@ LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
ADD(ARRAY4(EBP, 3), EDX)
RESTORE_REGS()
-END_FUNCTION(botan_md5_ia32_compress)
+END_FUNCTION(botan_md5_x86_32_compress)
diff --git a/src/hash/sha1/sha160.cpp b/src/hash/sha1/sha160.cpp
index 7a42ca867..f5daaadb2 100644
--- a/src/hash/sha1/sha160.cpp
+++ b/src/hash/sha1/sha160.cpp
@@ -1,6 +1,6 @@
/*
* SHA-160
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2008,2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,6 +11,8 @@
namespace Botan {
+namespace SHA1_F {
+
namespace {
/*
@@ -51,11 +53,15 @@ inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
}
+}
+
/*
* SHA-160 Compression Function
*/
void SHA_160::compress_n(const byte input[], size_t blocks)
{
+ using namespace SHA1_F;
+
u32bit A = digest[0], B = digest[1], C = digest[2],
D = digest[3], E = digest[4];
diff --git a/src/hash/sha1_ia32/sha1_ia32.h b/src/hash/sha1_ia32/sha1_ia32.h
deleted file mode 100644
index 5cff03016..000000000
--- a/src/hash/sha1_ia32/sha1_ia32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-* 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 in x86 assembly
-*/
-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[], size_t blocks);
- };
-
-}
-
-#endif
diff --git a/src/hash/sha1_sse2/sha1_sse2.cpp b/src/hash/sha1_sse2/sha1_sse2.cpp
index e890967c6..f96afd9ce 100644
--- a/src/hash/sha1_sse2/sha1_sse2.cpp
+++ b/src/hash/sha1_sse2/sha1_sse2.cpp
@@ -1,6 +1,6 @@
/*
* SHA-1 using SSE2
-* (C) 2009-2010 Jack Lloyd
+* (C) 2009-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*
@@ -14,6 +14,8 @@
namespace Botan {
+namespace SHA1_SSE2_F {
+
namespace {
/*
@@ -146,11 +148,15 @@ inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
}
+}
+
/*
* SHA-160 Compression Function using SSE for message expansion
*/
void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
{
+ using namespace SHA1_SSE2_F;
+
const __m128i K00_19 = _mm_set1_epi32(0x5A827999);
const __m128i K20_39 = _mm_set1_epi32(0x6ED9EBA1);
const __m128i K40_59 = _mm_set1_epi32(0x8F1BBCDC);
@@ -323,4 +329,7 @@ void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
#undef GET_P_32
}
+#undef prep00_15
+#undef prep
+
}
diff --git a/src/hash/sha1_ia32/info.txt b/src/hash/sha1_x86_32/info.txt
index 47d8e753e..7359a6754 100644
--- a/src/hash/sha1_ia32/info.txt
+++ b/src/hash/sha1_x86_32/info.txt
@@ -1,12 +1,12 @@
-define SHA1_IA32
+define SHA1_X86_32
load_on asm_ok
<arch>
-ia32
+x86_32
</arch>
<requires>
-asm_ia32
+asm_x86_32
sha1
</requires>
diff --git a/src/hash/sha1_ia32/sha1_ia32.cpp b/src/hash/sha1_x86_32/sha1_x86_32.cpp
index 3e9cff047..6a4dc2a1d 100644
--- a/src/hash/sha1_ia32/sha1_ia32.cpp
+++ b/src/hash/sha1_x86_32/sha1_x86_32.cpp
@@ -1,29 +1,29 @@
/*
-* SHA-160 (IA-32)
+* SHA-160 in x86-32
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/sha1_ia32.h>
+#include <botan/sha1_x86_32.h>
namespace Botan {
namespace {
extern "C"
-void botan_sha160_ia32_compress(u32bit[5], const byte[64], u32bit[81]);
+void botan_sha160_x86_32_compress(u32bit[5], const byte[64], u32bit[81]);
}
/*
* SHA-160 Compression Function
*/
-void SHA_160_IA32::compress_n(const byte input[], size_t blocks)
+void SHA_160_X86_32::compress_n(const byte input[], size_t blocks)
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_sha160_ia32_compress(&digest[0], input, &W[0]);
+ botan_sha160_x86_32_compress(&digest[0], input, &W[0]);
input += hash_block_size();
}
}
diff --git a/src/hash/sha1_x86_32/sha1_x86_32.h b/src/hash/sha1_x86_32/sha1_x86_32.h
new file mode 100644
index 000000000..b344d4ae2
--- /dev/null
+++ b/src/hash/sha1_x86_32/sha1_x86_32.h
@@ -0,0 +1,31 @@
+/*
+* SHA-160 in x86-32 asm
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SHA_160_X86_32_H__
+#define BOTAN_SHA_160_X86_32_H__
+
+#include <botan/sha160.h>
+
+namespace Botan {
+
+/**
+* SHA-160 in x86 assembly
+*/
+class BOTAN_DLL SHA_160_X86_32 : public SHA_160
+ {
+ public:
+ HashFunction* clone() const { return new SHA_160_X86_32; }
+
+ // Note 81 instead of normal 80: x86-32 asm needs an extra temp
+ SHA_160_X86_32() : SHA_160(81) {}
+ private:
+ void compress_n(const byte[], size_t blocks);
+ };
+
+}
+
+#endif
diff --git a/src/hash/sha1_ia32/sha1_ia32_imp.S b/src/hash/sha1_x86_32/sha1_x86_32_imp.S
index c2777b4b5..775ef6854 100644
--- a/src/hash/sha1_ia32/sha1_ia32_imp.S
+++ b/src/hash/sha1_x86_32/sha1_x86_32_imp.S
@@ -1,15 +1,15 @@
/*
-* SHA-1 in IA-32 assembler
+* SHA-1 in x86-32 asm
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/asm_macr_ia32.h>
+#include <botan/internal/asm_x86_32.h>
-START_LISTING(sha1_ia32.S)
+START_LISTING(sha1_x86_32_imp.S)
-START_FUNCTION(botan_sha160_ia32_compress)
+START_FUNCTION(botan_sha160_x86_32_compress)
SPILL_REGS()
#define PUSHED 4
@@ -42,7 +42,7 @@ LOOP_UNTIL_EQ(ESI, 16, .LOAD_INPUT)
ADD2_IMM(EDI, EBP, 64)
-START_LOOP(.EXPANSION)
+START_LOOP(.L_SHA_EXPANSION)
ADD_IMM(ESI, 4)
ZEROIZE(EAX)
@@ -77,7 +77,7 @@ START_LOOP(.EXPANSION)
ASSIGN(ARRAY4(EDI, 3), EAX)
ADD_IMM(EDI, 16)
-LOOP_UNTIL_EQ(ESI, 80, .EXPANSION)
+LOOP_UNTIL_EQ(ESI, 80, .L_SHA_EXPANSION)
#define MAGIC1 0x5A827999
#define MAGIC2 0x6ED9EBA1
@@ -241,4 +241,4 @@ LOOP_UNTIL_EQ(ESI, 80, .EXPANSION)
ADD(ARRAY4(EBP, 4), ECX)
RESTORE_REGS()
-END_FUNCTION(botan_sha160_ia32_compress)
+END_FUNCTION(botan_sha160_x86_32_compress)
diff --git a/src/hash/sha1_amd64/info.txt b/src/hash/sha1_x86_64/info.txt
index 78eaa23c2..3d54c0baa 100644
--- a/src/hash/sha1_amd64/info.txt
+++ b/src/hash/sha1_x86_64/info.txt
@@ -1,13 +1,13 @@
-define SHA1_AMD64
+define SHA1_X86_64
load_on asm_ok
<arch>
-amd64
+x86_64
</arch>
<requires>
asm_engine
-asm_amd64
+asm_x86_64
sha1
</requires>
diff --git a/src/hash/sha1_amd64/sha1_amd64.cpp b/src/hash/sha1_x86_64/sha1_x86_64.cpp
index d32b44901..a3e92e313 100644
--- a/src/hash/sha1_amd64/sha1_amd64.cpp
+++ b/src/hash/sha1_x86_64/sha1_x86_64.cpp
@@ -5,25 +5,25 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/sha1_amd64.h>
+#include <botan/sha1_x86_64.h>
namespace Botan {
namespace {
extern "C"
-void botan_sha160_amd64_compress(u32bit[5], const byte[64], u32bit[80]);
+void botan_sha160_x86_64_compress(u32bit[5], const byte[64], u32bit[80]);
}
/*
* SHA-160 Compression Function
*/
-void SHA_160_AMD64::compress_n(const byte input[], size_t blocks)
+void SHA_160_X86_64::compress_n(const byte input[], size_t blocks)
{
for(size_t i = 0; i != blocks; ++i)
{
- botan_sha160_amd64_compress(&digest[0], input, &W[0]);
+ botan_sha160_x86_64_compress(&digest[0], input, &W[0]);
input += hash_block_size();
}
}
diff --git a/src/hash/sha1_amd64/sha1_amd64.h b/src/hash/sha1_x86_64/sha1_x86_64.h
index 6b741184d..068a94595 100644
--- a/src/hash/sha1_amd64/sha1_amd64.h
+++ b/src/hash/sha1_x86_64/sha1_x86_64.h
@@ -5,8 +5,8 @@
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_SHA_160_AMD64_H__
-#define BOTAN_SHA_160_AMD64_H__
+#ifndef BOTAN_SHA_160_X86_64_H__
+#define BOTAN_SHA_160_X86_64_H__
#include <botan/sha160.h>
@@ -15,10 +15,10 @@ namespace Botan {
/**
* SHA-160 in x86-64 assembly
*/
-class BOTAN_DLL SHA_160_AMD64 : public SHA_160
+class BOTAN_DLL SHA_160_X86_64 : public SHA_160
{
public:
- HashFunction* clone() const { return new SHA_160_AMD64; }
+ HashFunction* clone() const { return new SHA_160_X86_64; }
private:
void compress_n(const byte[], size_t blocks);
};
diff --git a/src/hash/sha1_amd64/sha1_amd64_imp.S b/src/hash/sha1_x86_64/sha1_x86_64_imp.S
index 4eea75f11..ee35f0d85 100644
--- a/src/hash/sha1_amd64/sha1_amd64_imp.S
+++ b/src/hash/sha1_x86_64/sha1_x86_64_imp.S
@@ -5,11 +5,11 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/internal/asm_macr_amd64.h>
+#include <botan/internal/asm_x86_64.h>
-START_LISTING(sha1_amd64.S)
+START_LISTING(sha1_x86_64_imp.S)
-START_FUNCTION(botan_sha160_amd64_compress)
+START_FUNCTION(botan_sha160_x86_64_compress)
#define DIGEST_ARR %rdi
#define INPUT %rsi
@@ -263,4 +263,4 @@ ALIGN;
ADD(ARRAY4(DIGEST_ARR, 3), B)
ADD(ARRAY4(DIGEST_ARR, 4), C)
-END_FUNCTION(botan_sha160_amd64_compress)
+END_FUNCTION(botan_sha160_x86_64_compress)
diff --git a/src/hash/sha2_32/sha2_32.cpp b/src/hash/sha2_32/sha2_32.cpp
index 4e5f2b38c..6dd780e64 100644
--- a/src/hash/sha2_32/sha2_32.cpp
+++ b/src/hash/sha2_32/sha2_32.cpp
@@ -14,6 +14,8 @@ namespace Botan {
namespace {
+namespace SHA2_32 {
+
/*
* SHA-256 Rho Function
*/
@@ -33,22 +35,23 @@ inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift)
/*
* SHA-256 F1 Function
+*
+* Use a macro as many compilers won't inline a function this big,
+* even though it is much faster if inlined.
*/
-inline void F1(u32bit A, u32bit B, u32bit C, u32bit& D,
- u32bit E, u32bit F, u32bit G, u32bit& H,
- u32bit msg, u32bit magic)
- {
- H += magic + rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + msg;
- D += H;
- H += rho(A, 2, 13, 22) + ((A & B) | ((A | B) & C));
- }
+#define SHA2_32_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) \
+ do { \
+ H += magic + rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + M1; \
+ D += H; \
+ H += rho(A, 2, 13, 22) + ((A & B) | ((A | B) & C)); \
+ M1 += sigma(M2, 17, 19, 10) + M3 + sigma(M4, 7, 18, 3); \
+ } while(0);
/*
* SHA-224 / SHA-256 compression function
*/
-void sha2_32_compress(MemoryRegion<u32bit>& W,
- MemoryRegion<u32bit>& digest,
- const byte input[], size_t blocks)
+void compress(MemoryRegion<u32bit>& digest,
+ const byte input[], size_t blocks)
{
u32bit A = digest[0], B = digest[1], C = digest[2],
D = digest[3], E = digest[4], F = digest[5],
@@ -56,92 +59,87 @@ void sha2_32_compress(MemoryRegion<u32bit>& W,
for(size_t i = 0; i != blocks; ++i)
{
- load_be(&W[0], input, 16);
-
- for(size_t j = 16; j != 64; j += 8)
- {
- W[j ] = sigma(W[j- 2], 17, 19, 10) + W[j-7] +
- sigma(W[j-15], 7, 18, 3) + W[j-16];
- W[j+1] = sigma(W[j- 1], 17, 19, 10) + W[j-6] +
- sigma(W[j-14], 7, 18, 3) + W[j-15];
- W[j+2] = sigma(W[j ], 17, 19, 10) + W[j-5] +
- sigma(W[j-13], 7, 18, 3) + W[j-14];
- W[j+3] = sigma(W[j+ 1], 17, 19, 10) + W[j-4] +
- sigma(W[j-12], 7, 18, 3) + W[j-13];
- W[j+4] = sigma(W[j+ 2], 17, 19, 10) + W[j-3] +
- sigma(W[j-11], 7, 18, 3) + W[j-12];
- W[j+5] = sigma(W[j+ 3], 17, 19, 10) + W[j-2] +
- sigma(W[j-10], 7, 18, 3) + W[j-11];
- W[j+6] = sigma(W[j+ 4], 17, 19, 10) + W[j-1] +
- sigma(W[j- 9], 7, 18, 3) + W[j-10];
- W[j+7] = sigma(W[j+ 5], 17, 19, 10) + W[j ] +
- sigma(W[j- 8], 7, 18, 3) + W[j- 9];
- }
-
- 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);
+ u32bit W00 = load_be<u32bit>(input, 0);
+ u32bit W01 = load_be<u32bit>(input, 1);
+ u32bit W02 = load_be<u32bit>(input, 2);
+ u32bit W03 = load_be<u32bit>(input, 3);
+ u32bit W04 = load_be<u32bit>(input, 4);
+ u32bit W05 = load_be<u32bit>(input, 5);
+ u32bit W06 = load_be<u32bit>(input, 6);
+ u32bit W07 = load_be<u32bit>(input, 7);
+ u32bit W08 = load_be<u32bit>(input, 8);
+ u32bit W09 = load_be<u32bit>(input, 9);
+ u32bit W10 = load_be<u32bit>(input, 10);
+ u32bit W11 = load_be<u32bit>(input, 11);
+ u32bit W12 = load_be<u32bit>(input, 12);
+ u32bit W13 = load_be<u32bit>(input, 13);
+ u32bit W14 = load_be<u32bit>(input, 14);
+ u32bit W15 = load_be<u32bit>(input, 15);
+
+ SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x71374491);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCF);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA5);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25B);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B01);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A7);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C1);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC6);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DC);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C8);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF3);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x14292967);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A85);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B2138);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D13);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A7354);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C85);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A1);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664B);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A3);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD6990624);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E3585);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA070);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C08);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774C);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4A);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3);
+ SHA2_32_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE);
+ SHA2_32_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F);
+ SHA2_32_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814);
+ SHA2_32_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC70208);
+ SHA2_32_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA);
+ SHA2_32_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEB);
+ SHA2_32_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7);
+ SHA2_32_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2);
A = (digest[0] += A);
B = (digest[1] += B);
@@ -158,12 +156,14 @@ void sha2_32_compress(MemoryRegion<u32bit>& W,
}
+}
+
/*
* SHA-224 compression function
*/
void SHA_224::compress_n(const byte input[], size_t blocks)
{
- sha2_32_compress(W, digest, input, blocks);
+ SHA2_32::compress(digest, input, blocks);
}
/*
@@ -181,7 +181,6 @@ void SHA_224::copy_out(byte output[])
void SHA_224::clear()
{
MDx_HashFunction::clear();
- zeroise(W);
digest[0] = 0xC1059ED8;
digest[1] = 0x367CD507;
digest[2] = 0x3070DD17;
@@ -197,7 +196,7 @@ void SHA_224::clear()
*/
void SHA_256::compress_n(const byte input[], size_t blocks)
{
- sha2_32_compress(W, digest, input, blocks);
+ SHA2_32::compress(digest, input, blocks);
}
/*
@@ -215,7 +214,6 @@ void SHA_256::copy_out(byte output[])
void SHA_256::clear()
{
MDx_HashFunction::clear();
- zeroise(W);
digest[0] = 0x6A09E667;
digest[1] = 0xBB67AE85;
digest[2] = 0x3C6EF372;
diff --git a/src/hash/sha2_32/sha2_32.h b/src/hash/sha2_32/sha2_32.h
index ffda11772..807b979d1 100644
--- a/src/hash/sha2_32/sha2_32.h
+++ b/src/hash/sha2_32/sha2_32.h
@@ -1,6 +1,6 @@
/*
* SHA-{224,256}
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
* 2007 FlexSecure GmbH
*
* Distributed under the terms of the Botan license
@@ -25,13 +25,13 @@ class BOTAN_DLL SHA_224 : public MDx_HashFunction
void clear();
- SHA_224() : MDx_HashFunction(64, true, true), W(64), digest(8)
+ SHA_224() : MDx_HashFunction(64, true, true), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> W, digest;
+ SecureVector<u32bit> digest;
};
/**
@@ -46,13 +46,13 @@ class BOTAN_DLL SHA_256 : public MDx_HashFunction
void clear();
- SHA_256() : MDx_HashFunction(64, true, true), W(64), digest(8)
+ SHA_256() : MDx_HashFunction(64, true, true), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u32bit> W, digest;
+ SecureVector<u32bit> digest;
};
}
diff --git a/src/hash/sha2_64/sha2_64.cpp b/src/hash/sha2_64/sha2_64.cpp
index 3c1df9be6..3026c3a39 100644
--- a/src/hash/sha2_64/sha2_64.cpp
+++ b/src/hash/sha2_64/sha2_64.cpp
@@ -1,6 +1,6 @@
/*
* SHA-{384,512}
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -13,6 +13,8 @@ namespace Botan {
namespace {
+namespace SHA2_64 {
+
/*
* SHA-{384,512} Rho Function
*/
@@ -23,18 +25,6 @@ inline u64bit rho(u64bit X, u32bit rot1, u32bit rot2, u32bit 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)
@@ -43,11 +33,24 @@ inline u64bit sigma(u64bit X, u32bit rot1, u32bit rot2, u32bit shift)
}
/*
+* SHA-512 F1 Function
+*
+* Use a macro as many compilers won't inline a function this big,
+* even though it is much faster if inlined.
+*/
+#define SHA2_64_F(A, B, C, D, E, F, G, H, M1, M2, M3, M4, magic) \
+ do { \
+ H += magic + rho(E, 14, 18, 41) + ((E & F) ^ (~E & G)) + M1; \
+ D += H; \
+ H += rho(A, 28, 34, 39) + ((A & B) | ((A | B) & C)); \
+ M1 += sigma(M2, 19, 61, 6) + M3 + sigma(M4, 1, 8, 7); \
+ } while(0);
+
+/*
* SHA-{384,512} Compression Function
*/
-void sha2_64_compress(MemoryRegion<u64bit>& W,
- MemoryRegion<u64bit>& digest,
- const byte input[], size_t blocks)
+void compress(MemoryRegion<u64bit>& digest,
+ const byte input[], size_t blocks)
{
u64bit A = digest[0], B = digest[1], C = digest[2],
D = digest[3], E = digest[4], F = digest[5],
@@ -55,100 +58,103 @@ void sha2_64_compress(MemoryRegion<u64bit>& W,
for(size_t i = 0; i != blocks; ++i)
{
- load_be(&W[0], input, 16);
-
- for(size_t j = 16; j != 80; j += 8)
- {
- W[j ] = sigma(W[j-2], 19, 61, 6) + W[j-7] + sigma(W[j-15], 1, 8, 7) + W[j-16];
- W[j+1] = sigma(W[j-1], 19, 61, 6) + W[j-6] + sigma(W[j-14], 1, 8, 7) + W[j-15];
- W[j+2] = sigma(W[j ], 19, 61, 6) + W[j-5] + sigma(W[j-13], 1, 8, 7) + W[j-14];
- W[j+3] = sigma(W[j+1], 19, 61, 6) + W[j-4] + sigma(W[j-12], 1, 8, 7) + W[j-13];
- W[j+4] = sigma(W[j+2], 19, 61, 6) + W[j-3] + sigma(W[j-11], 1, 8, 7) + W[j-12];
- W[j+5] = sigma(W[j+3], 19, 61, 6) + W[j-2] + sigma(W[j-10], 1, 8, 7) + W[j-11];
- W[j+6] = sigma(W[j+4], 19, 61, 6) + W[j-1] + sigma(W[j- 9], 1, 8, 7) + W[j-10];
- W[j+7] = sigma(W[j+5], 19, 61, 6) + W[j ] + sigma(W[j- 8], 1, 8, 7) + W[j- 9];
- }
-
- F1(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98D728AE22);
- F1(H, A, B, C, D, E, F, G, W[ 1], 0x7137449123EF65CD);
- F1(G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCFEC4D3B2F);
- F1(F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA58189DBBC);
- F1(E, F, G, H, A, B, C, D, W[ 4], 0x3956C25BF348B538);
- F1(D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1B605D019);
- F1(C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4AF194F9B);
- F1(B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5DA6D8118);
- F1(A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98A3030242);
- F1(H, A, B, C, D, E, F, G, W[ 9], 0x12835B0145706FBE);
- F1(G, H, A, B, C, D, E, F, W[10], 0x243185BE4EE4B28C);
- F1(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3D5FFB4E2);
- F1(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74F27B896F);
- F1(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE3B1696B1);
- F1(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A725C71235);
- F1(B, C, D, E, F, G, H, A, W[15], 0xC19BF174CF692694);
- F1(A, B, C, D, E, F, G, H, W[16], 0xE49B69C19EF14AD2);
- F1(H, A, B, C, D, E, F, G, W[17], 0xEFBE4786384F25E3);
- F1(G, H, A, B, C, D, E, F, W[18], 0x0FC19DC68B8CD5B5);
- F1(F, G, H, A, B, C, D, E, W[19], 0x240CA1CC77AC9C65);
- F1(E, F, G, H, A, B, C, D, W[20], 0x2DE92C6F592B0275);
- F1(D, E, F, G, H, A, B, C, W[21], 0x4A7484AA6EA6E483);
- F1(C, D, E, F, G, H, A, B, W[22], 0x5CB0A9DCBD41FBD4);
- F1(B, C, D, E, F, G, H, A, W[23], 0x76F988DA831153B5);
- F1(A, B, C, D, E, F, G, H, W[24], 0x983E5152EE66DFAB);
- F1(H, A, B, C, D, E, F, G, W[25], 0xA831C66D2DB43210);
- F1(G, H, A, B, C, D, E, F, W[26], 0xB00327C898FB213F);
- F1(F, G, H, A, B, C, D, E, W[27], 0xBF597FC7BEEF0EE4);
- F1(E, F, G, H, A, B, C, D, W[28], 0xC6E00BF33DA88FC2);
- F1(D, E, F, G, H, A, B, C, W[29], 0xD5A79147930AA725);
- F1(C, D, E, F, G, H, A, B, W[30], 0x06CA6351E003826F);
- F1(B, C, D, E, F, G, H, A, W[31], 0x142929670A0E6E70);
- F1(A, B, C, D, E, F, G, H, W[32], 0x27B70A8546D22FFC);
- F1(H, A, B, C, D, E, F, G, W[33], 0x2E1B21385C26C926);
- F1(G, H, A, B, C, D, E, F, W[34], 0x4D2C6DFC5AC42AED);
- F1(F, G, H, A, B, C, D, E, W[35], 0x53380D139D95B3DF);
- F1(E, F, G, H, A, B, C, D, W[36], 0x650A73548BAF63DE);
- F1(D, E, F, G, H, A, B, C, W[37], 0x766A0ABB3C77B2A8);
- F1(C, D, E, F, G, H, A, B, W[38], 0x81C2C92E47EDAEE6);
- F1(B, C, D, E, F, G, H, A, W[39], 0x92722C851482353B);
- F1(A, B, C, D, E, F, G, H, W[40], 0xA2BFE8A14CF10364);
- F1(H, A, B, C, D, E, F, G, W[41], 0xA81A664BBC423001);
- F1(G, H, A, B, C, D, E, F, W[42], 0xC24B8B70D0F89791);
- F1(F, G, H, A, B, C, D, E, W[43], 0xC76C51A30654BE30);
- F1(E, F, G, H, A, B, C, D, W[44], 0xD192E819D6EF5218);
- F1(D, E, F, G, H, A, B, C, W[45], 0xD69906245565A910);
- F1(C, D, E, F, G, H, A, B, W[46], 0xF40E35855771202A);
- F1(B, C, D, E, F, G, H, A, W[47], 0x106AA07032BBD1B8);
- F1(A, B, C, D, E, F, G, H, W[48], 0x19A4C116B8D2D0C8);
- F1(H, A, B, C, D, E, F, G, W[49], 0x1E376C085141AB53);
- F1(G, H, A, B, C, D, E, F, W[50], 0x2748774CDF8EEB99);
- F1(F, G, H, A, B, C, D, E, W[51], 0x34B0BCB5E19B48A8);
- F1(E, F, G, H, A, B, C, D, W[52], 0x391C0CB3C5C95A63);
- F1(D, E, F, G, H, A, B, C, W[53], 0x4ED8AA4AE3418ACB);
- F1(C, D, E, F, G, H, A, B, W[54], 0x5B9CCA4F7763E373);
- F1(B, C, D, E, F, G, H, A, W[55], 0x682E6FF3D6B2B8A3);
- F1(A, B, C, D, E, F, G, H, W[56], 0x748F82EE5DEFB2FC);
- F1(H, A, B, C, D, E, F, G, W[57], 0x78A5636F43172F60);
- F1(G, H, A, B, C, D, E, F, W[58], 0x84C87814A1F0AB72);
- F1(F, G, H, A, B, C, D, E, W[59], 0x8CC702081A6439EC);
- F1(E, F, G, H, A, B, C, D, W[60], 0x90BEFFFA23631E28);
- F1(D, E, F, G, H, A, B, C, W[61], 0xA4506CEBDE82BDE9);
- F1(C, D, E, F, G, H, A, B, W[62], 0xBEF9A3F7B2C67915);
- F1(B, C, D, E, F, G, H, A, W[63], 0xC67178F2E372532B);
- F1(A, B, C, D, E, F, G, H, W[64], 0xCA273ECEEA26619C);
- F1(H, A, B, C, D, E, F, G, W[65], 0xD186B8C721C0C207);
- F1(G, H, A, B, C, D, E, F, W[66], 0xEADA7DD6CDE0EB1E);
- F1(F, G, H, A, B, C, D, E, W[67], 0xF57D4F7FEE6ED178);
- F1(E, F, G, H, A, B, C, D, W[68], 0x06F067AA72176FBA);
- F1(D, E, F, G, H, A, B, C, W[69], 0x0A637DC5A2C898A6);
- F1(C, D, E, F, G, H, A, B, W[70], 0x113F9804BEF90DAE);
- F1(B, C, D, E, F, G, H, A, W[71], 0x1B710B35131C471B);
- F1(A, B, C, D, E, F, G, H, W[72], 0x28DB77F523047D84);
- F1(H, A, B, C, D, E, F, G, W[73], 0x32CAAB7B40C72493);
- F1(G, H, A, B, C, D, E, F, W[74], 0x3C9EBE0A15C9BEBC);
- F1(F, G, H, A, B, C, D, E, W[75], 0x431D67C49C100D4C);
- F1(E, F, G, H, A, B, C, D, W[76], 0x4CC5D4BECB3E42B6);
- F1(D, E, F, G, H, A, B, C, W[77], 0x597F299CFC657E2A);
- F1(C, D, E, F, G, H, A, B, W[78], 0x5FCB6FAB3AD6FAEC);
- F1(B, C, D, E, F, G, H, A, W[79], 0x6C44198C4A475817);
+ u64bit W00 = load_be<u64bit>(input, 0);
+ u64bit W01 = load_be<u64bit>(input, 1);
+ u64bit W02 = load_be<u64bit>(input, 2);
+ u64bit W03 = load_be<u64bit>(input, 3);
+ u64bit W04 = load_be<u64bit>(input, 4);
+ u64bit W05 = load_be<u64bit>(input, 5);
+ u64bit W06 = load_be<u64bit>(input, 6);
+ u64bit W07 = load_be<u64bit>(input, 7);
+ u64bit W08 = load_be<u64bit>(input, 8);
+ u64bit W09 = load_be<u64bit>(input, 9);
+ u64bit W10 = load_be<u64bit>(input, 10);
+ u64bit W11 = load_be<u64bit>(input, 11);
+ u64bit W12 = load_be<u64bit>(input, 12);
+ u64bit W13 = load_be<u64bit>(input, 13);
+ u64bit W14 = load_be<u64bit>(input, 14);
+ u64bit W15 = load_be<u64bit>(input, 15);
+
+ SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98D728AE22);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x7137449123EF65CD);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCFEC4D3B2F);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA58189DBBC);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25BF348B538);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1B605D019);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4AF194F9B);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5DA6D8118);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98A3030242);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B0145706FBE);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE4EE4B28C);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3D5FFB4E2);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74F27B896F);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE3B1696B1);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A725C71235);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174CF692694);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C19EF14AD2);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786384F25E3);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC68B8CD5B5);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC77AC9C65);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F592B0275);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA6EA6E483);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DCBD41FBD4);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA831153B5);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152EE66DFAB);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D2DB43210);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C898FB213F);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7BEEF0EE4);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF33DA88FC2);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147930AA725);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351E003826F);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x142929670A0E6E70);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A8546D22FFC);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B21385C26C926);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC5AC42AED);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D139D95B3DF);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A73548BAF63DE);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB3C77B2A8);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E47EDAEE6);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C851482353B);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A14CF10364);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664BBC423001);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70D0F89791);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A30654BE30);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819D6EF5218);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD69906245565A910);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E35855771202A);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA07032BBD1B8);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116B8D2D0C8);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C085141AB53);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774CDF8EEB99);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5E19B48A8);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3C5C95A63);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4AE3418ACB);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F7763E373);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3D6B2B8A3);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE5DEFB2FC);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F43172F60);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814A1F0AB72);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC702081A6439EC);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA23631E28);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEBDE82BDE9);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7B2C67915);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2E372532B);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xCA273ECEEA26619C);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xD186B8C721C0C207);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xEADA7DD6CDE0EB1E);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xF57D4F7FEE6ED178);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x06F067AA72176FBA);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x0A637DC5A2C898A6);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x113F9804BEF90DAE);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x1B710B35131C471B);
+ SHA2_64_F(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x28DB77F523047D84);
+ SHA2_64_F(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x32CAAB7B40C72493);
+ SHA2_64_F(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x3C9EBE0A15C9BEBC);
+ SHA2_64_F(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x431D67C49C100D4C);
+ SHA2_64_F(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x4CC5D4BECB3E42B6);
+ SHA2_64_F(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x597F299CFC657E2A);
+ SHA2_64_F(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x5FCB6FAB3AD6FAEC);
+ SHA2_64_F(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x6C44198C4A475817);
A = (digest[0] += A);
B = (digest[1] += B);
@@ -165,12 +171,14 @@ void sha2_64_compress(MemoryRegion<u64bit>& W,
}
+}
+
/*
* SHA-384 compression function
*/
void SHA_384::compress_n(const byte input[], size_t blocks)
{
- sha2_64_compress(W, digest, input, blocks);
+ SHA2_64::compress(digest, input, blocks);
}
/*
@@ -188,7 +196,6 @@ void SHA_384::copy_out(byte output[])
void SHA_384::clear()
{
MDx_HashFunction::clear();
- zeroise(W);
digest[0] = 0xCBBB9D5DC1059ED8;
digest[1] = 0x629A292A367CD507;
digest[2] = 0x9159015A3070DD17;
@@ -204,7 +211,7 @@ void SHA_384::clear()
*/
void SHA_512::compress_n(const byte input[], size_t blocks)
{
- sha2_64_compress(W, digest, input, blocks);
+ SHA2_64::compress(digest, input, blocks);
}
/*
@@ -222,7 +229,6 @@ void SHA_512::copy_out(byte output[])
void SHA_512::clear()
{
MDx_HashFunction::clear();
- zeroise(W);
digest[0] = 0x6A09E667F3BCC908;
digest[1] = 0xBB67AE8584CAA73B;
digest[2] = 0x3C6EF372FE94F82B;
diff --git a/src/hash/sha2_64/sha2_64.h b/src/hash/sha2_64/sha2_64.h
index dcfb7224c..124d4bbfb 100644
--- a/src/hash/sha2_64/sha2_64.h
+++ b/src/hash/sha2_64/sha2_64.h
@@ -24,13 +24,13 @@ class BOTAN_DLL SHA_384 : public MDx_HashFunction
void clear();
- SHA_384() : MDx_HashFunction(128, true, true, 16), W(80), digest(8)
+ SHA_384() : MDx_HashFunction(128, true, true, 16), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u64bit> W, digest;
+ SecureVector<u64bit> digest;
};
/**
@@ -45,13 +45,13 @@ class BOTAN_DLL SHA_512 : public MDx_HashFunction
void clear();
- SHA_512() : MDx_HashFunction(128, true, true, 16), W(80), digest(8)
+ SHA_512() : MDx_HashFunction(128, true, true, 16), digest(8)
{ clear(); }
private:
void compress_n(const byte[], size_t blocks);
void copy_out(byte[]);
- SecureVector<u64bit> W, digest;
+ SecureVector<u64bit> digest;
};
}
diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp
index 92acf0814..b5f7677db 100644
--- a/src/hash/skein/skein_512.cpp
+++ b/src/hash/skein/skein_512.cpp
@@ -43,7 +43,7 @@ void ubi_512(MemoryRegion<u64bit>& H,
if(to_proc % 8)
{
for(size_t j = 0; j != to_proc % 8; ++j)
- M[to_proc/8] |= ((u64bit)msg[8*(to_proc/8)+j] << (8*j));
+ M[to_proc/8] |= static_cast<u64bit>(msg[8*(to_proc/8)+j]) << (8*j);
}
H[8] = H[0] ^ H[1] ^ H[2] ^ H[3] ^
@@ -117,7 +117,8 @@ void ubi_512(MemoryRegion<u64bit>& H,
H[6] = X6 ^ M[6];
H[7] = X7 ^ M[7];
- T[1] &= ~((u64bit)1 << 62); // clear first flag if set
+ // clear first flag if set
+ T[1] &= ~(static_cast<u64bit>(1) << 62);
msg_len -= to_proc;
msg += to_proc;
@@ -128,7 +129,10 @@ void reset_tweak(MemoryRegion<u64bit>& T,
type_code type, bool final)
{
T[0] = 0;
- T[1] = ((u64bit)type << 56) | ((u64bit)1 << 62) | ((u64bit)final << 63);
+
+ T[1] = (static_cast<u64bit>(type) << 56) |
+ (static_cast<u64bit>(1) << 62) |
+ (static_cast<u64bit>(final) << 63);
}
void initial_block(MemoryRegion<u64bit>& H,
@@ -227,7 +231,7 @@ void Skein_512::add_data(const byte input[], size_t length)
void Skein_512::final_result(byte out[])
{
- T[1] |= ((u64bit)1 << 63); // final block flag
+ T[1] |= (static_cast<u64bit>(1) << 63); // final block flag
for(size_t i = buf_pos; i != buffer.size(); ++i)
buffer[i] = 0;
diff --git a/src/kdf/ssl_prf/info.txt b/src/kdf/prf_ssl3/info.txt
index 0ef297119..0ef297119 100644
--- a/src/kdf/ssl_prf/info.txt
+++ b/src/kdf/prf_ssl3/info.txt
diff --git a/src/kdf/ssl_prf/prf_ssl3.cpp b/src/kdf/prf_ssl3/prf_ssl3.cpp
index 72cf023e2..72cf023e2 100644
--- a/src/kdf/ssl_prf/prf_ssl3.cpp
+++ b/src/kdf/prf_ssl3/prf_ssl3.cpp
diff --git a/src/kdf/ssl_prf/prf_ssl3.h b/src/kdf/prf_ssl3/prf_ssl3.h
index b07454be2..b07454be2 100644
--- a/src/kdf/ssl_prf/prf_ssl3.h
+++ b/src/kdf/prf_ssl3/prf_ssl3.h
diff --git a/src/kdf/tls_prf/info.txt b/src/kdf/prf_tls/info.txt
index 9531a6a83..9531a6a83 100644
--- a/src/kdf/tls_prf/info.txt
+++ b/src/kdf/prf_tls/info.txt
diff --git a/src/kdf/tls_prf/prf_tls.cpp b/src/kdf/prf_tls/prf_tls.cpp
index 2b57cdd25..2b57cdd25 100644
--- a/src/kdf/tls_prf/prf_tls.cpp
+++ b/src/kdf/prf_tls/prf_tls.cpp
diff --git a/src/kdf/tls_prf/prf_tls.h b/src/kdf/prf_tls/prf_tls.h
index 5237f17c0..5237f17c0 100644
--- a/src/kdf/tls_prf/prf_tls.h
+++ b/src/kdf/prf_tls/prf_tls.h
diff --git a/src/kdf/x942_prf/info.txt b/src/kdf/prf_x942/info.txt
index e51aafd08..e51aafd08 100644
--- a/src/kdf/x942_prf/info.txt
+++ b/src/kdf/prf_x942/info.txt
diff --git a/src/kdf/x942_prf/prf_x942.cpp b/src/kdf/prf_x942/prf_x942.cpp
index fc31effe4..fc31effe4 100644
--- a/src/kdf/x942_prf/prf_x942.cpp
+++ b/src/kdf/prf_x942/prf_x942.cpp
diff --git a/src/kdf/x942_prf/prf_x942.h b/src/kdf/prf_x942/prf_x942.h
index e6093eda6..e6093eda6 100644
--- a/src/kdf/x942_prf/prf_x942.h
+++ b/src/kdf/prf_x942/prf_x942.h
diff --git a/src/libstate/lookup.cpp b/src/libstate/lookup.cpp
index 24a46e3e9..0d3f33573 100644
--- a/src/libstate/lookup.cpp
+++ b/src/libstate/lookup.cpp
@@ -62,6 +62,63 @@ size_t output_length_of(const std::string& name)
}
/*
+* Query the minimum allowed key length of an algorithm implementation
+*/
+size_t min_keylength_of(const std::string& name)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
+ return bc->key_spec().minimum_keylength();
+
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
+ return sc->key_spec().minimum_keylength();
+
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
+ return mac->key_spec().minimum_keylength();
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*
+* Query the maximum allowed keylength of an algorithm implementation
+*/
+size_t max_keylength_of(const std::string& name)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
+ return bc->key_spec().maximum_keylength();
+
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
+ return sc->key_spec().maximum_keylength();
+
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
+ return mac->key_spec().maximum_keylength();
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*
+* Query the number of byte a valid key must be a multiple of
+*/
+size_t keylength_multiple_of(const std::string& name)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ if(const BlockCipher* bc = af.prototype_block_cipher(name))
+ return bc->key_spec().keylength_multiple();
+
+ if(const StreamCipher* sc = af.prototype_stream_cipher(name))
+ return sc->key_spec().keylength_multiple();
+
+ if(const MessageAuthenticationCode* mac = af.prototype_mac(name))
+ return mac->key_spec().keylength_multiple();
+
+ throw Algorithm_Not_Found(name);
+ }
+
+/*
* Get a cipher object
*/
Keyed_Filter* get_cipher(const std::string& algo_spec,
diff --git a/src/libstate/lookup.h b/src/libstate/lookup.h
index 02c1708aa..e10c195b8 100644
--- a/src/libstate/lookup.h
+++ b/src/libstate/lookup.h
@@ -299,6 +299,36 @@ BOTAN_DLL size_t block_size_of(const std::string& algo_spec);
*/
BOTAN_DLL size_t output_length_of(const std::string& algo_spec);
+/**
+* Find out the minimum key size of a certain symmetric algorithm.
+* @deprecated Call algorithm_factory() directly
+*
+* @param algo_spec the name of the algorithm
+* @return minimum key length of the specified algorithm
+*/
+BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
+BOTAN_DLL size_t min_keylength_of(const std::string& algo_spec);
+
+/**
+* Find out the maximum key size of a certain symmetric algorithm.
+* @deprecated Call algorithm_factory() directly
+*
+* @param algo_spec the name of the algorithm
+* @return maximum key length of the specified algorithm
+*/
+BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
+BOTAN_DLL size_t max_keylength_of(const std::string& algo_spec);
+
+/**
+* Find out the size any valid key is a multiple of for a certain algorithm.
+* @deprecated Call algorithm_factory() directly
+*
+* @param algo_spec the name of the algorithm
+* @return size any valid key is a multiple of
+*/
+BOTAN_DEPRECATED("Retrieve object you want and then call key_spec")
+BOTAN_DLL size_t keylength_multiple_of(const std::string& algo_spec);
+
}
#endif
diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp
index a49335e75..ae536813f 100644
--- a/src/math/bigint/bigint.cpp
+++ b/src/math/bigint/bigint.cpp
@@ -1,6 +1,6 @@
/*
* BigInt Base
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -26,8 +26,8 @@ BigInt::BigInt(u64bit n)
const size_t limbs_needed = sizeof(u64bit) / sizeof(word);
reg.resize(4*limbs_needed);
- for(size_t j = 0; j != limbs_needed; ++j)
- reg[j] = ((n >> (j*MP_WORD_BITS)) & MP_WORD_MASK);
+ for(size_t i = 0; i != limbs_needed; ++i)
+ reg[i] = ((n >> (i*MP_WORD_BITS)) & MP_WORD_MASK);
}
/*
@@ -190,16 +190,35 @@ u32bit BigInt::get_substring(size_t offset, size_t length) const
throw Invalid_Argument("BigInt::get_substring: Substring size too big");
u64bit piece = 0;
- for(size_t j = 0; j != 8; ++j)
- piece = (piece << 8) | byte_at((offset / 8) + (7-j));
+ for(size_t i = 0; i != 8; ++i)
+ {
+ const byte part = byte_at((offset / 8) + (7-i));
+ piece = (piece << 8) | part;
+ }
- u64bit mask = (1 << length) - 1;
- size_t shift = (offset % 8);
+ const u64bit mask = (static_cast<u64bit>(1) << length) - 1;
+ const size_t shift = (offset % 8);
return static_cast<u32bit>((piece >> shift) & mask);
}
/*
+* 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;
+ }
+
+/*
* Set bit number n
*/
void BigInt::set_bit(size_t n)
@@ -233,8 +252,8 @@ void BigInt::mask_bits(size_t n)
const word mask = (static_cast<word>(1) << (n % MP_WORD_BITS)) - 1;
if(top_word < size())
- for(size_t j = top_word + 1; j != size(); ++j)
- reg[j] = 0;
+ for(size_t i = top_word + 1; i != size(); ++i)
+ reg[i] = 0;
reg[top_word] &= mask;
}
@@ -340,8 +359,8 @@ BigInt BigInt::abs() const
void BigInt::binary_encode(byte output[]) const
{
const size_t sig_bytes = bytes();
- for(size_t j = 0; j != sig_bytes; ++j)
- output[sig_bytes-j-1] = byte_at(j);
+ for(size_t i = 0; i != sig_bytes; ++i)
+ output[sig_bytes-i-1] = byte_at(i);
}
/*
@@ -354,14 +373,15 @@ void BigInt::binary_decode(const byte buf[], size_t length)
clear();
reg.resize(round_up<size_t>((length / WORD_BYTES) + 1, 8));
- for(size_t j = 0; j != length / WORD_BYTES; ++j)
+ for(size_t i = 0; i != length / WORD_BYTES; ++i)
{
- size_t top = length - WORD_BYTES*j;
- for(size_t k = WORD_BYTES; k > 0; --k)
- reg[j] = (reg[j] << 8) | buf[top - k];
+ const size_t top = length - WORD_BYTES*i;
+ for(size_t j = WORD_BYTES; j > 0; --j)
+ reg[i] = (reg[i] << 8) | buf[top - j];
}
- for(size_t j = 0; j != length % WORD_BYTES; ++j)
- reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[j];
+
+ for(size_t i = 0; i != length % WORD_BYTES; ++i)
+ reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) | buf[i];
}
/*
diff --git a/src/math/bigint/bigint.h b/src/math/bigint/bigint.h
index 5b3dcc2dd..06e3ecd2f 100644
--- a/src/math/bigint/bigint.h
+++ b/src/math/bigint/bigint.h
@@ -218,6 +218,13 @@ class BOTAN_DLL BigInt
u32bit get_substring(size_t offset, size_t length) const;
/**
+ * Convert this value into a u32bit, if it is in the range
+ * [0 ... 2**32-1], or otherwise throw an exception.
+ * @result the value as a u32bit if conversion is possible
+ */
+ u32bit to_u32bit() const;
+
+ /**
* @param n the offset to get a byte from
* @result byte at offset n
*/
diff --git a/src/math/numbertheory/curve_gfp.h b/src/math/ec_gfp/curve_gfp.h
index 1ab803ec9..9867f82fe 100644
--- a/src/math/numbertheory/curve_gfp.h
+++ b/src/math/ec_gfp/curve_gfp.h
@@ -2,7 +2,7 @@
* Elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2010 Jack Lloyd
+* 2010-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -11,7 +11,6 @@
#define BOTAN_GFP_CURVE_H__
#include <botan/numthry.h>
-#include <botan/reducer.h>
namespace Botan {
@@ -34,18 +33,15 @@ class BOTAN_DLL CurveGFp
* @param b second coefficient
*/
CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) :
- p(p), a(a), b(b), reducer_p(p)
+ p(p), a(a), b(b), p_words(p.sig_words())
{
- r = 1;
- r <<= p.sig_words() * BOTAN_MP_WORD_BITS;
+ BigInt r(BigInt::Power2, p_words * BOTAN_MP_WORD_BITS);
- r_inv = inverse_mod(r, p);
+ p_dash = (((r * inverse_mod(r, p)) - 1) / p).word_at(0);
- p_dash = (((r * r_inv) - 1) / p).word_at(0);
-
- a_r = reducer_p.multiply(a, r);
-
- p_words = p.sig_words();
+ r2 = (r * r) % p;
+ a_r = (a * r) % p;
+ b_r = (b * r) % p;
}
// CurveGFp(const CurveGFp& other) = default;
@@ -68,19 +64,19 @@ class BOTAN_DLL CurveGFp
const BigInt& get_p() const { return p; }
/**
- * @return Montgomery parameter r
+ * @return Montgomery parameter r^2 % p
*/
- const BigInt& get_r() const { return r; }
+ const BigInt& get_r2() const { return r2; }
/**
- * @return Montgomery parameter r^-1
+ * @return a * r mod p
*/
- const BigInt& get_r_inv() const { return r_inv; }
+ const BigInt& get_a_r() const { return a_r; }
/**
- * @return a * r mod p
+ * @return b * r mod p
*/
- const BigInt& get_a_r() const { return a_r; }
+ const BigInt& get_b_r() const { return b_r; }
/**
* @return Montgomery parameter p-dash
@@ -93,23 +89,22 @@ class BOTAN_DLL CurveGFp
size_t get_p_words() const { return p_words; }
/**
- * @return modular reducer for p
- */
- const Modular_Reducer& mod_p() const { return reducer_p; }
-
- /**
* swaps the states of *this and other, does not throw
* @param other curve to swap values with
*/
void swap(CurveGFp& other)
{
+ std::swap(p, other.p);
+
std::swap(a, other.a);
std::swap(b, other.b);
- std::swap(p, other.p);
- std::swap(reducer_p, other.reducer_p);
- std::swap(r, other.r);
- std::swap(r_inv, other.r_inv);
+ std::swap(a_r, other.a_r);
+ std::swap(b_r, other.b_r);
+
+ std::swap(p_words, other.p_words);
+
+ std::swap(r2, other.r2);
std::swap(p_dash, other.p_dash);
}
@@ -120,7 +115,11 @@ class BOTAN_DLL CurveGFp
*/
bool operator==(const CurveGFp& other) const
{
- return (p == other.p && a == other.a && b == other.b);
+ /*
+ Relies on choice of R, but that is fixed by constructor based
+ on size of p
+ */
+ return (p == other.p && a_r == other.a_r && b_r == other.b_r);
}
private:
@@ -130,10 +129,8 @@ class BOTAN_DLL CurveGFp
size_t p_words; // cache of p.sig_words()
// Montgomery parameters
- BigInt r, r_inv, a_r;
+ BigInt r2, a_r, b_r;
word p_dash;
-
- Modular_Reducer reducer_p;
};
/**
diff --git a/src/math/ec_gfp/info.txt b/src/math/ec_gfp/info.txt
new file mode 100644
index 000000000..e6ee1d6bf
--- /dev/null
+++ b/src/math/ec_gfp/info.txt
@@ -0,0 +1,16 @@
+define EC_CURVE_GFP
+
+load_on auto
+
+<header:public>
+curve_gfp.h
+point_gfp.h
+</header:public>
+
+<source>
+point_gfp.cpp
+</source>
+
+<requires>
+numbertheory
+</requires>
diff --git a/src/math/numbertheory/point_gfp.cpp b/src/math/ec_gfp/point_gfp.cpp
index fab731d29..7ac6b4141 100644
--- a/src/math/numbertheory/point_gfp.cpp
+++ b/src/math/ec_gfp/point_gfp.cpp
@@ -1,40 +1,37 @@
/*
-* Arithmetic for point groups of elliptic curves over GF(p)
+* Point arithmetic on elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2010 Jack Lloyd
+* 2008-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/point_gfp.h>
#include <botan/numthry.h>
+#include <botan/reducer.h>
#include <botan/internal/mp_core.h>
namespace Botan {
PointGFp::PointGFp(const CurveGFp& curve) :
- curve(curve),
- coord_x(0),
- coord_y(curve.get_r()),
- coord_z(0)
+ curve(curve), ws(2 * (curve.get_p_words() + 2))
{
+ coord_x = 0;
+ coord_y = monty_mult(1, curve.get_r2());
+ coord_z = 0;
}
PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) :
- curve(curve)
+ curve(curve), ws(2 * (curve.get_p_words() + 2))
{
- const Modular_Reducer& mod_p = curve.mod_p();
-
- coord_x = mod_p.multiply(curve.get_r(), x);
- coord_y = mod_p.multiply(curve.get_r(), y);
- coord_z = mod_p.reduce(curve.get_r());
+ coord_x = monty_mult(x, curve.get_r2());
+ coord_y = monty_mult(y, curve.get_r2());
+ coord_z = monty_mult(1, curve.get_r2());
}
// Montgomery multiplication
-void PointGFp::monty_mult(BigInt& z,
- const BigInt& x, const BigInt& y,
- MemoryRegion<word>& workspace) const
+void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const
{
//assert(&z != &x && &z != &y);
@@ -52,19 +49,15 @@ void PointGFp::monty_mult(BigInt& z,
z_reg.resize(2*p_size+1);
zeroise(z_reg);
- bigint_mul(&z_reg[0], z_reg.size(),
- &workspace[0],
- x.data(), x.size(), x.sig_words(),
- y.data(), y.size(), y.sig_words());
-
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- p.data(), p_size, p_dash);
+ bigint_monty_mul(&z_reg[0], z_reg.size(),
+ x.data(), x.size(), x.sig_words(),
+ y.data(), y.size(), y.sig_words(),
+ p.data(), p_size, p_dash,
+ &ws[0]);
}
// Montgomery squaring
-void PointGFp::monty_sqr(BigInt& z, const BigInt& x,
- MemoryRegion<word>& workspace) const
+void PointGFp::monty_sqr(BigInt& z, const BigInt& x) const
{
//assert(&z != &x);
@@ -82,17 +75,14 @@ void PointGFp::monty_sqr(BigInt& z, const BigInt& x,
z_reg.resize(2*p_size+1);
zeroise(z_reg);
- bigint_sqr(&z[0], z.size(),
- &workspace[0],
- x.data(), x.size(), x.sig_words());
-
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- p.data(), p_size, p_dash);
+ bigint_monty_sqr(&z_reg[0], z_reg.size(),
+ x.data(), x.size(), x.sig_words(),
+ p.data(), p_size, p_dash,
+ &ws[0]);
}
// Point addition
-void PointGFp::add(const PointGFp& rhs, Workspace& workspace)
+void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn)
{
if(is_zero())
{
@@ -106,9 +96,6 @@ void PointGFp::add(const PointGFp& rhs, Workspace& workspace)
const BigInt& p = curve.get_p();
- MemoryRegion<word>& ws = workspace.ws_monty;
- std::vector<BigInt>& ws_bn = workspace.ws_bn;
-
BigInt& rhs_z2 = ws_bn[0];
BigInt& U1 = ws_bn[1];
BigInt& S1 = ws_bn[2];
@@ -120,17 +107,13 @@ void PointGFp::add(const PointGFp& rhs, Workspace& workspace)
BigInt& H = ws_bn[6];
BigInt& r = ws_bn[7];
- BigInt& x = ws_bn[8];
- BigInt& y = ws_bn[9];
- BigInt& z = ws_bn[10];
+ monty_sqr(rhs_z2, rhs.coord_z);
+ monty_mult(U1, coord_x, rhs_z2);
+ monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2));
- monty_sqr(rhs_z2, rhs.coord_z, ws);
- monty_mult(U1, coord_x, rhs_z2, ws);
- monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2, ws), ws);
-
- monty_sqr(lhs_z2, coord_z, ws);
- monty_mult(U2, rhs.coord_x, lhs_z2, ws);
- monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2, ws), ws);
+ monty_sqr(lhs_z2, coord_z);
+ monty_mult(U2, rhs.coord_x, lhs_z2);
+ monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2));
H = U2;
H -= U1;
@@ -146,7 +129,7 @@ void PointGFp::add(const PointGFp& rhs, Workspace& workspace)
{
if(r.is_zero())
{
- mult2(workspace);
+ mult2(ws_bn);
return;
}
@@ -154,36 +137,32 @@ void PointGFp::add(const PointGFp& rhs, Workspace& workspace)
return;
}
- monty_sqr(U2, H, ws);
+ monty_sqr(U2, H);
- monty_mult(S2, U2, H, ws);
+ monty_mult(S2, U2, H);
- U2 = monty_mult(U1, U2, ws);
+ U2 = monty_mult(U1, U2);
- monty_sqr(x, r, ws);
- x -= S2;
- x -= (U2 << 1);
- while(x.is_negative())
- x += p;
+ monty_sqr(coord_x, r);
+ coord_x -= S2;
+ coord_x -= (U2 << 1);
+ while(coord_x.is_negative())
+ coord_x += p;
- U2 -= x;
+ U2 -= coord_x;
if(U2.is_negative())
U2 += p;
- monty_mult(y, r, U2, ws);
- y -= monty_mult(S1, S2, ws);
- if(y.is_negative())
- y += p;
-
- monty_mult(z, monty_mult(coord_z, rhs.coord_z, ws), H, ws);
+ monty_mult(coord_y, r, U2);
+ coord_y -= monty_mult(S1, S2);
+ if(coord_y.is_negative())
+ coord_y += p;
- coord_x = x;
- coord_y = y;
- coord_z = z;
+ monty_mult(coord_z, monty_mult(coord_z, rhs.coord_z), H);
}
// *this *= 2
-void PointGFp::mult2(Workspace& workspace)
+void PointGFp::mult2(std::vector<BigInt>& ws_bn)
{
if(is_zero())
return;
@@ -195,9 +174,6 @@ void PointGFp::mult2(Workspace& workspace)
const BigInt& p = curve.get_p();
- MemoryRegion<word>& ws = workspace.ws_monty;
- std::vector<BigInt>& ws_bn = workspace.ws_bn;
-
BigInt& y_2 = ws_bn[0];
BigInt& S = ws_bn[1];
BigInt& z4 = ws_bn[2];
@@ -208,27 +184,27 @@ void PointGFp::mult2(Workspace& workspace)
BigInt& y = ws_bn[7];
BigInt& z = ws_bn[8];
- monty_sqr(y_2, coord_y, ws);
+ monty_sqr(y_2, coord_y);
- monty_mult(S, coord_x, y_2, ws);
+ monty_mult(S, coord_x, y_2);
S <<= 2; // * 4
while(S >= p)
S -= p;
- monty_sqr(z4, monty_sqr(coord_z, ws), ws);
- monty_mult(a_z4, curve.get_a_r(), z4, ws);
+ monty_sqr(z4, monty_sqr(coord_z));
+ monty_mult(a_z4, curve.get_a_r(), z4);
- M = 3 * monty_sqr(coord_x, ws);
+ M = 3 * monty_sqr(coord_x);
M += a_z4;
while(M >= p)
M -= p;
- monty_sqr(x, M, ws);
+ monty_sqr(x, M);
x -= (S << 1);
while(x.is_negative())
x += p;
- monty_sqr(U, y_2, ws);
+ monty_sqr(U, y_2);
U <<= 3;
while(U >= p)
U -= p;
@@ -237,12 +213,12 @@ void PointGFp::mult2(Workspace& workspace)
while(S.is_negative())
S += p;
- monty_mult(y, M, S, ws);
+ monty_mult(y, M, S);
y -= U;
if(y.is_negative())
y += p;
- monty_mult(z, coord_y, coord_z, ws);
+ monty_mult(z, coord_y, coord_z);
z <<= 1;
if(z >= p)
z -= p;
@@ -255,7 +231,7 @@ void PointGFp::mult2(Workspace& workspace)
// arithmetic operators
PointGFp& PointGFp::operator+=(const PointGFp& rhs)
{
- Workspace ws(curve.get_p_words());
+ std::vector<BigInt> ws(9);
add(rhs, ws);
return *this;
}
@@ -278,6 +254,39 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar)
return *this;
}
+PointGFp multi_exponentiate(const PointGFp& p1, const BigInt& z1,
+ const PointGFp& p2, const BigInt& z2)
+ {
+ const PointGFp p3 = p1 + p2;
+
+ PointGFp H(p1.curve); // create as zero
+ size_t bits_left = std::max(z1.bits(), z2.bits());
+
+ std::vector<BigInt> ws(9);
+
+ while(bits_left)
+ {
+ H.mult2(ws);
+
+ const bool z1_b = z1.get_bit(bits_left - 1);
+ const bool z2_b = z2.get_bit(bits_left - 1);
+
+ if(z1_b == true && z2_b == true)
+ H.add(p3, ws);
+ else if(z1_b)
+ H.add(p1, ws);
+ else if(z2_b)
+ H.add(p2, ws);
+
+ --bits_left;
+ }
+
+ if(z1.is_negative() != z2.is_negative())
+ H.negate();
+
+ return H;
+ }
+
PointGFp operator*(const BigInt& scalar, const PointGFp& point)
{
const CurveGFp& curve = point.get_curve();
@@ -285,7 +294,7 @@ PointGFp operator*(const BigInt& scalar, const PointGFp& point)
if(scalar.is_zero())
return PointGFp(curve); // zero point
- PointGFp::Workspace ws(curve.get_p_words());
+ std::vector<BigInt> ws(9);
if(scalar.abs() <= 2) // special cases for small values
{
@@ -304,6 +313,38 @@ PointGFp operator*(const BigInt& scalar, const PointGFp& point)
const size_t scalar_bits = scalar.bits();
+#if 0
+
+ PointGFp x1 = PointGFp(curve);
+ PointGFp x2 = point;
+
+ size_t bits_left = scalar_bits;
+
+ // Montgomery Ladder
+ while(bits_left)
+ {
+ const bool bit_set = scalar.get_bit(bits_left - 1);
+
+ if(bit_set)
+ {
+ x1.add(x2, ws);
+ x2.mult2(ws);
+ }
+ else
+ {
+ x2.add(x1, ws);
+ x1.mult2(ws);
+ }
+
+ --bits_left;
+ }
+
+ if(scalar.is_negative())
+ x1.negate();
+
+ return x1;
+
+#else
const size_t window_size = 4;
std::vector<PointGFp> Ps(1 << window_size);
@@ -345,6 +386,7 @@ PointGFp operator*(const BigInt& scalar, const PointGFp& point)
H.negate();
return H;
+#endif
}
BigInt PointGFp::get_affine_x() const
@@ -352,23 +394,13 @@ BigInt PointGFp::get_affine_x() const
if(is_zero())
throw Illegal_Transformation("Cannot convert zero point to affine");
- const Modular_Reducer& mod_p = curve.mod_p();
-
-#if 1
- BigInt x = mod_p.multiply(curve.get_r_inv(), coord_x);
- BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z);
-
- BigInt z2 = mod_p.square(z);
- return mod_p.multiply(x, inverse_mod(z2, curve.get_p()));
-#else
-
- SecureVector<word> ws(2 * (curve.get_p_words() + 2));
+ const BigInt& r2 = curve.get_r2();
- BigInt z2 = monty_sqr(coord_z, ws);
+ BigInt z2 = monty_sqr(coord_z);
z2 = inverse_mod(z2, curve.get_p());
- z2 = mod_p.multiply(z2, curve.get_r());
- return monty_mult(coord_x, z2, ws);
-#endif
+
+ z2 = monty_mult(z2, r2);
+ return monty_mult(coord_x, z2);
}
BigInt PointGFp::get_affine_y() const
@@ -376,23 +408,12 @@ BigInt PointGFp::get_affine_y() const
if(is_zero())
throw Illegal_Transformation("Cannot convert zero point to affine");
- const Modular_Reducer& mod_p = curve.mod_p();
+ const BigInt& r2 = curve.get_r2();
-#if 1
- BigInt y = mod_p.multiply(curve.get_r_inv(), coord_y);
- BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z);
-
- BigInt z3 = mod_p.cube(z);
- return mod_p.multiply(y, inverse_mod(z3, curve.get_p()));
-#else
-
- SecureVector<word> ws(2 * (curve.get_p_words() + 2));
-
- BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z, ws), ws);
+ BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z));
z3 = inverse_mod(z3, curve.get_p());
- z3 = mod_p.multiply(z3, curve.get_r());
- return monty_mult(coord_y, z3, ws);
-#endif
+ z3 = monty_mult(z3, r2);
+ return monty_mult(coord_y, z3);
}
bool PointGFp::on_the_curve() const
@@ -407,31 +428,28 @@ bool PointGFp::on_the_curve() const
if(is_zero())
return true;
- const Modular_Reducer& mod_p = curve.mod_p();
+ BigInt y2 = monty_mult(monty_sqr(coord_y), 1);
+ BigInt x3 = monty_mult(coord_x, monty_sqr(coord_x));
- BigInt x = mod_p.multiply(curve.get_r_inv(), coord_x);
- BigInt y = mod_p.multiply(curve.get_r_inv(), coord_y);
- BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z);
+ BigInt ax = monty_mult(coord_x, curve.get_a_r());
- BigInt y2 = mod_p.square(y);
- BigInt x3 = mod_p.cube(x);
+ const BigInt& b_r = curve.get_b_r();
- BigInt ax = mod_p.multiply(x, curve.get_a());
+ BigInt z2 = monty_sqr(coord_z);
- if(z == 1)
+ if(coord_z == z2) // Is z equal to 1 (in Montgomery form)?
{
- if(mod_p.reduce(x3 + ax + curve.get_b()) != y2)
+ if(y2 != monty_mult(x3 + ax + b_r, 1))
return false;
}
- BigInt z2 = mod_p.square(z);
- BigInt z3 = mod_p.multiply(z, z2);
+ BigInt z3 = monty_mult(coord_z, z2);
- BigInt ax_z4 = mod_p.multiply(mod_p.multiply(z3, z), ax);
+ BigInt ax_z4 = monty_mult(ax, monty_sqr(z2));
- BigInt b_z6 = mod_p.multiply(curve.get_b(), mod_p.square(z3));
+ BigInt b_z6 = monty_mult(b_r, monty_sqr(z3));
- if(y2 != mod_p.reduce(x3 + ax_z4 + b_z6))
+ if(y2 != monty_mult(x3 + ax_z4 + b_z6, 1))
return false;
return true;
@@ -444,6 +462,7 @@ void PointGFp::swap(PointGFp& other)
coord_x.swap(other.coord_x);
coord_y.swap(other.coord_y);
coord_z.swap(other.coord_z);
+ ws.swap(other.ws);
}
bool PointGFp::operator==(const PointGFp& other) const
diff --git a/src/math/numbertheory/point_gfp.h b/src/math/ec_gfp/point_gfp.h
index 35ec6d503..b2b6fe2f0 100644
--- a/src/math/numbertheory/point_gfp.h
+++ b/src/math/ec_gfp/point_gfp.h
@@ -1,8 +1,8 @@
/*
-* Arithmetic for point groups of elliptic curves over GF(p)
+* Point arithmetic on elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2010 Jack Lloyd
+* 2008-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -99,6 +99,18 @@ class BOTAN_DLL PointGFp
friend BOTAN_DLL PointGFp operator*(const BigInt& scalar, const PointGFp& point);
/**
+ * Multiexponentiation
+ * @param p1 a point
+ * @param z1 a scalar
+ * @param p2 a point
+ * @param z2 a scalar
+ * @result (p1 * z1 + p2 * z2)
+ */
+ friend BOTAN_DLL PointGFp multi_exponentiate(
+ const PointGFp& p1, const BigInt& z1,
+ const PointGFp& p2, const BigInt& z2);
+
+ /**
* Negate this point
* @return *this
*/
@@ -153,27 +165,16 @@ class BOTAN_DLL PointGFp
bool operator==(const PointGFp& other) const;
private:
- class Workspace
- {
- public:
- Workspace(size_t p_words) :
- ws_monty(2*(p_words+2)), ws_bn(12) {}
-
- SecureVector<word> ws_monty;
- std::vector<BigInt> ws_bn;
- };
-
/**
* Montgomery multiplication/reduction
* @param x first multiplicand
* @param y second multiplicand
* @param workspace temp space
*/
- BigInt monty_mult(const BigInt& x, const BigInt& y,
- MemoryRegion<word>& workspace) const
+ BigInt monty_mult(const BigInt& x, const BigInt& y) const
{
BigInt result;
- monty_mult(result, x, y, workspace);
+ monty_mult(result, x, y);
return result;
}
@@ -183,22 +184,17 @@ class BOTAN_DLL PointGFp
* @param z output
* @param x first multiplicand
* @param y second multiplicand
- * @param workspace temp space
*/
- void monty_mult(BigInt& z,
- const BigInt& x, const BigInt& y,
- MemoryRegion<word>& workspace) const;
+ void monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const;
/**
* Montgomery squaring/reduction
* @param x multiplicand
- * @param workspace temp space
*/
- BigInt monty_sqr(const BigInt& x,
- MemoryRegion<word>& workspace) const
+ BigInt monty_sqr(const BigInt& x) const
{
BigInt result;
- monty_sqr(result, x, workspace);
+ monty_sqr(result, x);
return result;
}
@@ -207,24 +203,24 @@ class BOTAN_DLL PointGFp
* @warning z cannot alias x
* @param z output
* @param x multiplicand
- * @param workspace temp space
*/
- void monty_sqr(BigInt& z, const BigInt& x,
- MemoryRegion<word>& workspace) const;
+ void monty_sqr(BigInt& z, const BigInt& x) const;
/**
* Point addition
+ * @param workspace temp space, at least 11 elements
*/
- void add(const PointGFp& other, Workspace& workspace);
+ void add(const PointGFp& other, std::vector<BigInt>& workspace);
/**
* Point doubling
- * @param workspace temp space
+ * @param workspace temp space, at least 9 elements
*/
- void mult2(Workspace& workspace);
+ void mult2(std::vector<BigInt>& workspace);
CurveGFp curve;
BigInt coord_x, coord_y, coord_z;
+ mutable SecureVector<word> ws; // workspace for Montgomery
};
// relational operators
diff --git a/src/math/mp/info.txt b/src/math/mp/info.txt
index a3c994d8b..bf7f40d3c 100644
--- a/src/math/mp/info.txt
+++ b/src/math/mp/info.txt
@@ -4,6 +4,8 @@ define BIGINT_MP
mp_asm.cpp
mp_comba.cpp
mp_karat.cpp
+mp_monty.cpp
+mp_mulop.cpp
mp_misc.cpp
mp_shift.cpp
</source>
@@ -17,7 +19,5 @@ mp_core.h
</header:internal>
<requires>
-mp_amd64|mp_msvc64|mp_asm64|mp_ia32|mp_ia32_msvc|mp_generic
-monty_generic
-mulop_generic
+mp_x86_64|mp_msvc64|mp_asm64|mp_x86_32|mp_x86_32_msvc|mp_generic
</requires>
diff --git a/src/math/mp/monty_generic/info.txt b/src/math/mp/monty_generic/info.txt
deleted file mode 100644
index cd05ccdc0..000000000
--- a/src/math/mp/monty_generic/info.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-load_on dep
-
-<source>
-mp_monty.cpp
-</source>
diff --git a/src/math/mp/monty_generic/mp_monty.cpp b/src/math/mp/monty_generic/mp_monty.cpp
deleted file mode 100644
index d7f7e0306..000000000
--- a/src/math/mp/monty_generic/mp_monty.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-* Montgomery Reduction
-* (C) 1999-2010 Jack Lloyd
-* 2006 Luca Piccarreta
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/internal/mp_core.h>
-#include <botan/internal/mp_asm.h>
-#include <botan/internal/mp_asmi.h>
-#include <botan/mem_ops.h>
-
-namespace Botan {
-
-extern "C" {
-
-/*
-* Montgomery Reduction Algorithm
-*/
-void bigint_monty_redc(word z[], size_t z_size,
- word ws[],
- const word x[], size_t x_size,
- word u)
- {
- const size_t blocks_of_8 = x_size - (x_size % 8);
-
- for(size_t i = 0; i != x_size; ++i)
- {
- word* z_i = z + i;
-
- const word y = z_i[0] * u;
-
- /*
- bigint_linmul3(ws, x, x_size, y);
- bigint_add2(z_i, z_size - i, ws, x_size+1);
- */
- word carry = 0;
-
- for(size_t j = 0; j != blocks_of_8; j += 8)
- carry = word8_madd3(z_i + j, x + j, y, carry);
-
- for(size_t 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;
-
- // Note: not constant time
- for(size_t j = x_size + 1; carry && j != z_size - i; ++j)
- {
- ++z_i[j];
- carry = !z_i[j];
- }
- }
-
- word borrow = 0;
- for(size_t i = 0; i != x_size; ++i)
- ws[i] = word_sub(z[x_size + i], x[i], &borrow);
-
- ws[x_size] = word_sub(z[x_size+x_size], 0, &borrow);
-
- copy_mem(ws + x_size + 1, z + x_size, x_size + 1);
-
- copy_mem(z, ws + borrow*(x_size+1), x_size + 1);
- clear_mem(z + x_size + 1, z_size - x_size - 1);
- }
-
-}
-
-}
diff --git a/src/math/mp/mp_asm.cpp b/src/math/mp/mp_asm.cpp
index d164c1d33..3ba52c4b1 100644
--- a/src/math/mp/mp_asm.cpp
+++ b/src/math/mp/mp_asm.cpp
@@ -67,7 +67,8 @@ word bigint_add3_nc(word z[], const word x[], size_t x_size,
*/
void bigint_add2(word x[], size_t x_size, const word y[], size_t y_size)
{
- x[x_size] += bigint_add2_nc(x, x_size, y, y_size);
+ if(bigint_add2_nc(x, x_size, y, y_size))
+ x[x_size] += 1;
}
/*
diff --git a/src/math/mp/mp_asm64/info.txt b/src/math/mp/mp_asm64/info.txt
index fd0242a7a..9af7c4ae7 100644
--- a/src/math/mp/mp_asm64/info.txt
+++ b/src/math/mp/mp_asm64/info.txt
@@ -8,7 +8,6 @@ mp_generic:mp_asmi.h
</header:internal>
<arch>
-#amd64
alpha
ia64
mips64
@@ -21,5 +20,5 @@ sparc64
# win, so it's probably worth using elsewhere.
<cc>
gcc
-sunwspro
+sunstudio
</cc>
diff --git a/src/math/mp/mp_core.h b/src/math/mp/mp_core.h
index e1692006e..40327b02b 100644
--- a/src/math/mp/mp_core.h
+++ b/src/math/mp/mp_core.h
@@ -77,19 +77,35 @@ void bigint_simple_sqr(word z[], const word x[], size_t x_size);
void bigint_linmul2(word x[], size_t x_size, word y);
void bigint_linmul3(word z[], const word x[], size_t x_size, word y);
-/*
+/**
* Montgomery Reduction
-* @param z integer to reduce (also output in first x_size+1 words)
-* @param z_size size of z (should be >= 2*x_size+1)
-* @param workspace array of at least 2*(x_size+1) words
-* @param x modulus
-* @param x_size size of x
-* @param u Montgomery value
+* @param z integer to reduce (also output in first p_size+1 words)
+* @param z_size size of z (should be >= 2*p_size+1)
+* @param p modulus
+* @param p_size size of p
+* @param p_dash Montgomery value
+* @param workspace array of at least 2*(p_size+1) words
*/
void bigint_monty_redc(word z[], size_t z_size,
- word workspace[],
- const word x[], size_t x_size,
- word u);
+ const word p[], size_t p_size, word p_dash,
+ word workspace[]);
+
+/*
+* Montgomery Multiplication
+*/
+void bigint_monty_mul(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word y[], size_t y_size, size_t y_sw,
+ const word p[], size_t p_size, word p_dash,
+ word workspace[]);
+
+/*
+* Montgomery Squaring
+*/
+void bigint_monty_sqr(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word p[], size_t p_size, word p_dash,
+ word workspace[]);
/*
* Division operation
diff --git a/src/math/mp/mp_generic/mp_asm.h b/src/math/mp/mp_generic/mp_asm.h
index ee46e1aa9..7c18343ef 100644
--- a/src/math/mp/mp_generic/mp_asm.h
+++ b/src/math/mp/mp_generic/mp_asm.h
@@ -14,7 +14,7 @@
#if (BOTAN_MP_WORD_BITS == 8)
typedef Botan::u16bit dword;
#elif (BOTAN_MP_WORD_BITS == 16)
- typedef Botan::size_t dword;
+ typedef Botan::u32bit dword;
#elif (BOTAN_MP_WORD_BITS == 32)
typedef Botan::u64bit dword;
#elif (BOTAN_MP_WORD_BITS == 64)
diff --git a/src/math/mp/mp_monty.cpp b/src/math/mp/mp_monty.cpp
new file mode 100644
index 000000000..d37fb5844
--- /dev/null
+++ b/src/math/mp/mp_monty.cpp
@@ -0,0 +1,99 @@
+/*
+* Montgomery Reduction
+* (C) 1999-2011 Jack Lloyd
+* 2006 Luca Piccarreta
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/mp_core.h>
+#include <botan/internal/mp_asm.h>
+#include <botan/internal/mp_asmi.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+extern "C" {
+
+/*
+* Montgomery Reduction Algorithm
+*/
+void bigint_monty_redc(word z[], size_t z_size,
+ const word p[], size_t p_size,
+ word p_dash, word ws[])
+ {
+ const size_t blocks_of_8 = p_size - (p_size % 8);
+
+ for(size_t i = 0; i != p_size; ++i)
+ {
+ word* z_i = z + i;
+
+ const word y = z_i[0] * p_dash;
+
+ /*
+ bigint_linmul3(ws, p, p_size, y);
+ bigint_add2(z_i, z_size - i, ws, p_size+1);
+ */
+
+ word carry = 0;
+
+ for(size_t j = 0; j != blocks_of_8; j += 8)
+ carry = word8_madd3(z_i + j, p + j, y, carry);
+
+ for(size_t j = blocks_of_8; j != p_size; ++j)
+ z_i[j] = word_madd3(p[j], y, z_i[j], &carry);
+
+ word z_sum = z_i[p_size] + carry;
+ carry = (z_sum < z_i[p_size]);
+ z_i[p_size] = z_sum;
+
+ for(size_t j = p_size + 1; carry && j != z_size - i; ++j)
+ {
+ ++z_i[j];
+ carry = !z_i[j];
+ }
+ }
+
+ word borrow = 0;
+ for(size_t i = 0; i != p_size; ++i)
+ ws[i] = word_sub(z[p_size + i], p[i], &borrow);
+
+ ws[p_size] = word_sub(z[p_size+p_size], 0, &borrow);
+
+ copy_mem(ws + p_size + 1, z + p_size, p_size + 1);
+
+ copy_mem(z, ws + borrow*(p_size+1), p_size + 1);
+ clear_mem(z + p_size + 1, z_size - p_size - 1);
+ }
+
+void bigint_monty_mul(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word y[], size_t y_size, size_t y_sw,
+ const word p[], size_t p_size, word p_dash,
+ word ws[])
+ {
+ bigint_mul(&z[0], z_size, &ws[0],
+ &x[0], x_size, x_sw,
+ &y[0], y_size, y_sw);
+
+ bigint_monty_redc(&z[0], z_size,
+ &p[0], p_size, p_dash,
+ &ws[0]);
+ }
+
+void bigint_monty_sqr(word z[], size_t z_size,
+ const word x[], size_t x_size, size_t x_sw,
+ const word p[], size_t p_size, word p_dash,
+ word ws[])
+ {
+ bigint_sqr(&z[0], z_size, &ws[0],
+ &x[0], x_size, x_sw);
+
+ bigint_monty_redc(&z[0], z_size,
+ &p[0], p_size, p_dash,
+ &ws[0]);
+ }
+
+}
+
+}
diff --git a/src/math/mp/mp_msvc64/info.txt b/src/math/mp/mp_msvc64/info.txt
index 56ae05927..fa7d90fed 100644
--- a/src/math/mp/mp_msvc64/info.txt
+++ b/src/math/mp/mp_msvc64/info.txt
@@ -8,7 +8,7 @@ mp_generic:mp_asmi.h
</header:internal>
<arch>
-amd64
+x86_64
ia64
</arch>
diff --git a/src/math/mp/mulop_generic/mp_mulop.cpp b/src/math/mp/mp_mulop.cpp
index e6a8ba891..e6a8ba891 100644
--- a/src/math/mp/mulop_generic/mp_mulop.cpp
+++ b/src/math/mp/mp_mulop.cpp
diff --git a/src/math/mp/mp_ia32/info.txt b/src/math/mp/mp_x86_32/info.txt
index 1659f74cf..432f909f8 100644
--- a/src/math/mp/mp_ia32/info.txt
+++ b/src/math/mp/mp_x86_32/info.txt
@@ -8,7 +8,7 @@ mp_asmi.h
</header:internal>
<arch>
-ia32
+x86_32
</arch>
<cc>
diff --git a/src/math/mp/mp_ia32/mp_asm.h b/src/math/mp/mp_x86_32/mp_asm.h
index 4d3afc992..9be5680f8 100644
--- a/src/math/mp/mp_ia32/mp_asm.h
+++ b/src/math/mp/mp_x86_32/mp_asm.h
@@ -12,7 +12,7 @@
#include <botan/mp_types.h>
#if (BOTAN_MP_WORD_BITS != 32)
- #error The mp_ia32 module requires that BOTAN_MP_WORD_BITS == 32
+ #error The mp_x86_32 module requires that BOTAN_MP_WORD_BITS == 32
#endif
namespace Botan {
diff --git a/src/math/mp/mp_ia32/mp_asmi.h b/src/math/mp/mp_x86_32/mp_asmi.h
index c7b679e80..c7b679e80 100644
--- a/src/math/mp/mp_ia32/mp_asmi.h
+++ b/src/math/mp/mp_x86_32/mp_asmi.h
diff --git a/src/math/mp/mp_ia32_msvc/info.txt b/src/math/mp/mp_x86_32_msvc/info.txt
index 55a42c310..8d35c02e7 100644
--- a/src/math/mp/mp_ia32_msvc/info.txt
+++ b/src/math/mp/mp_x86_32_msvc/info.txt
@@ -8,7 +8,7 @@ mp_asmi.h
</header:internal>
<arch>
-ia32
+x86_32
</arch>
<cc>
diff --git a/src/math/mp/mp_ia32_msvc/mp_asmi.h b/src/math/mp/mp_x86_32_msvc/mp_asmi.h
index aee457d65..aee457d65 100644
--- a/src/math/mp/mp_ia32_msvc/mp_asmi.h
+++ b/src/math/mp/mp_x86_32_msvc/mp_asmi.h
diff --git a/src/math/mp/mp_amd64/info.txt b/src/math/mp/mp_x86_64/info.txt
index 11cc380e2..fdcc05dd6 100644
--- a/src/math/mp/mp_amd64/info.txt
+++ b/src/math/mp/mp_x86_64/info.txt
@@ -8,7 +8,7 @@ mp_asmi.h
</header:internal>
<arch>
-amd64
+x86_64
</arch>
<cc>
diff --git a/src/math/mp/mp_amd64/mp_asm.h b/src/math/mp/mp_x86_64/mp_asm.h
index fa66d04f3..edfaf6352 100644
--- a/src/math/mp/mp_amd64/mp_asm.h
+++ b/src/math/mp/mp_x86_64/mp_asm.h
@@ -12,7 +12,7 @@
#include <botan/mp_types.h>
#if (BOTAN_MP_WORD_BITS != 64)
- #error The mp_amd64 module requires that BOTAN_MP_WORD_BITS == 64
+ #error The mp_x86_64 module requires that BOTAN_MP_WORD_BITS == 64
#endif
namespace Botan {
@@ -20,7 +20,7 @@ namespace Botan {
extern "C" {
/*
-* Helper Macros for amd64 Assembly
+* Helper Macros for x86-64 Assembly
*/
#define ASM(x) x "\n\t"
diff --git a/src/math/mp/mp_amd64/mp_asmi.h b/src/math/mp/mp_x86_64/mp_asmi.h
index adf7774ef..f14df0e89 100644
--- a/src/math/mp/mp_amd64/mp_asmi.h
+++ b/src/math/mp/mp_x86_64/mp_asmi.h
@@ -16,7 +16,7 @@ namespace Botan {
extern "C" {
/*
-* Helper Macros for amd64 Assembly
+* Helper Macros for x86-64 Assembly
*/
#ifndef ASM
#define ASM(x) x "\n\t"
diff --git a/src/math/mp/mulop_generic/info.txt b/src/math/mp/mulop_generic/info.txt
deleted file mode 100644
index 548d0f44b..000000000
--- a/src/math/mp/mulop_generic/info.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-load_on dep
-
-<source>
-mp_mulop.cpp
-</source>
diff --git a/src/math/numbertheory/info.txt b/src/math/numbertheory/info.txt
index 18349ef78..0c6a9aefc 100644
--- a/src/math/numbertheory/info.txt
+++ b/src/math/numbertheory/info.txt
@@ -1,11 +1,9 @@
-load_on auto
-
define BIGINT_MATH
+load_on auto
+
<header:public>
-curve_gfp.h
numthry.h
-point_gfp.h
pow_mod.h
reducer.h
</header:public>
@@ -20,7 +18,6 @@ jacobi.cpp
make_prm.cpp
mp_numth.cpp
numthry.cpp
-point_gfp.cpp
pow_mod.cpp
powm_fw.cpp
powm_mnt.cpp
diff --git a/src/math/numbertheory/pow_mod.cpp b/src/math/numbertheory/pow_mod.cpp
index a66a1f7df..bf6b29275 100644
--- a/src/math/numbertheory/pow_mod.cpp
+++ b/src/math/numbertheory/pow_mod.cpp
@@ -118,7 +118,12 @@ size_t Power_Mod::window_bits(size_t exp_bits, size_t,
Power_Mod::Usage_Hints hints)
{
static const size_t wsize[][2] = {
- { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 }
+ { 1434, 7 },
+ { 539, 6 },
+ { 197, 4 },
+ { 70, 3 },
+ { 25, 2 },
+ { 0, 0 }
};
size_t window_bits = 1;
diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp
index 421470364..8993f4ba9 100644
--- a/src/math/numbertheory/powm_mnt.cpp
+++ b/src/math/numbertheory/powm_mnt.cpp
@@ -33,13 +33,12 @@ void Montgomery_Exponentiator::set_base(const BigInt& base)
SecureVector<word> workspace(z.size());
g[0] = (base >= modulus) ? (base % modulus) : base;
- bigint_mul(&z[0], z.size(), &workspace[0],
- g[0].data(), g[0].size(), g[0].sig_words(),
- R2.data(), R2.size(), R2.sig_words());
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- modulus.data(), mod_words, mod_prime);
+ bigint_monty_mul(&z[0], z.size(),
+ g[0].data(), g[0].size(), g[0].sig_words(),
+ R2.data(), R2.size(), R2.sig_words(),
+ modulus.data(), mod_words, mod_prime,
+ &workspace[0]);
g[0].assign(&z[0], mod_words + 1);
@@ -52,13 +51,11 @@ void Montgomery_Exponentiator::set_base(const BigInt& base)
const size_t y_sig = y.sig_words();
zeroise(z);
- bigint_mul(&z[0], z.size(), &workspace[0],
- x.data(), x.size(), x_sig,
- y.data(), y.size(), y_sig);
-
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- modulus.data(), mod_words, mod_prime);
+ bigint_monty_mul(&z[0], z.size(),
+ x.data(), x.size(), x_sig,
+ y.data(), y.size(), y_sig,
+ modulus.data(), mod_words, mod_prime,
+ &workspace[0]);
g[i].assign(&z[0], mod_words + 1);
}
@@ -80,12 +77,11 @@ BigInt Montgomery_Exponentiator::execute() const
for(size_t k = 0; k != window_bits; ++k)
{
zeroise(z);
- bigint_sqr(&z[0], z.size(), &workspace[0],
- x.data(), x.size(), x.sig_words());
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- modulus.data(), mod_words, mod_prime);
+ bigint_monty_sqr(&z[0], z.size(),
+ x.data(), x.size(), x.sig_words(),
+ modulus.data(), mod_words, mod_prime,
+ &workspace[0]);
x.assign(&z[0], mod_words + 1);
}
@@ -95,13 +91,11 @@ BigInt Montgomery_Exponentiator::execute() const
const BigInt& y = g[nibble-1];
zeroise(z);
- bigint_mul(&z[0], z.size(), &workspace[0],
- x.data(), x.size(), x.sig_words(),
- y.data(), y.size(), y.sig_words());
-
- bigint_monty_redc(&z[0], z.size(),
- &workspace[0],
- modulus.data(), mod_words, mod_prime);
+ bigint_monty_mul(&z[0], z.size(),
+ x.data(), x.size(), x.sig_words(),
+ y.data(), y.size(), y.sig_words(),
+ modulus.data(), mod_words, mod_prime,
+ &workspace[0]);
x.assign(&z[0], mod_words + 1);
}
@@ -110,8 +104,8 @@ BigInt Montgomery_Exponentiator::execute() const
x.get_reg().resize(2*mod_words+1);
bigint_monty_redc(&x[0], x.size(),
- &workspace[0],
- modulus.data(), mod_words, mod_prime);
+ modulus.data(), mod_words, mod_prime,
+ &workspace[0]);
x.get_reg().resize(mod_words+1);
@@ -134,14 +128,12 @@ Montgomery_Exponentiator::Montgomery_Exponentiator(const BigInt& 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);
+ BigInt r(BigInt::Power2, mod_words * BOTAN_MP_WORD_BITS);
+ mod_prime = (((r * inverse_mod(r, mod)) - 1) / mod).word_at(0);
- R_mod = BigInt(BigInt::Power2, MP_WORD_BITS * mod_words);
- R_mod %= modulus;
+ R_mod = r % modulus;
- R2 = BigInt(BigInt::Power2, 2 * MP_WORD_BITS * mod_words);
- R2 %= modulus;
+ R2 = (R_mod * R_mod) % modulus;
}
}
diff --git a/src/math/numbertheory/reducer.cpp b/src/math/numbertheory/reducer.cpp
index 257ece56e..466996e99 100644
--- a/src/math/numbertheory/reducer.cpp
+++ b/src/math/numbertheory/reducer.cpp
@@ -1,6 +1,6 @@
/*
* Modular Reducer
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -22,10 +22,8 @@ Modular_Reducer::Modular_Reducer(const BigInt& 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();
}
/*
@@ -36,45 +34,49 @@ 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.cmp(modulus, false) < 0)
{
- if(x.is_negative() && t1.is_nonzero())
- return modulus - t1;
+ if(x.is_negative())
+ return x + modulus; // make positive
return x;
}
+ else if(x.cmp(modulus_2, false) < 0)
+ {
+ BigInt t1 = x;
+ t1.set_sign(BigInt::Positive);
+ t1 >>= (MP_WORD_BITS * (mod_words - 1));
+ t1 *= mu;
- if(t1 >= modulus_2)
- return (x % modulus);
+ t1 >>= (MP_WORD_BITS * (mod_words + 1));
+ t1 *= modulus;
- t1 >>= (MP_WORD_BITS * (mod_words - 1));
- t1 *= mu;
- t1 >>= (MP_WORD_BITS * (mod_words + 1));
+ t1.mask_bits(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));
- BigInt t2 = x;
- t2.set_sign(BigInt::Positive);
- t2.mask_bits(MP_WORD_BITS * (mod_words+1));
+ t2 -= t1;
- t1 = t2 - t1;
+ if(t2.is_negative())
+ {
+ BigInt b_to_k1(BigInt::Power2, MP_WORD_BITS * (mod_words + 1));
+ t2 += b_to_k1;
+ }
- if(t1.is_negative())
+ while(t2 >= modulus)
+ t2 -= modulus;
+
+ if(x.is_positive())
+ return t2;
+ else
+ return (modulus - t2);
+ }
+ else
{
- BigInt b_to_k1(BigInt::Power2, MP_WORD_BITS * (mod_words+1));
- t1 += b_to_k1;
+ // too big, fall back to normal division
+ return (x % modulus);
}
-
- while(t1 >= modulus)
- t1 -= modulus;
-
- if(x.is_negative() && t1.is_nonzero())
- t1 = modulus - t1;
-
- return t1;
}
}
diff --git a/src/math/numbertheory/reducer.h b/src/math/numbertheory/reducer.h
index 05c12a440..76712074c 100644
--- a/src/math/numbertheory/reducer.h
+++ b/src/math/numbertheory/reducer.h
@@ -13,7 +13,7 @@
namespace Botan {
/**
-* Modular Reducer
+* Modular Reducer (using Barrett's technique)
*/
class BOTAN_DLL Modular_Reducer
{
@@ -53,7 +53,7 @@ class BOTAN_DLL Modular_Reducer
Modular_Reducer(const BigInt& mod);
private:
BigInt modulus, modulus_2, mu;
- size_t mod_words, mod2_words, mu_words;
+ size_t mod_words;
};
}
diff --git a/src/passhash/bcrypt/bcrypt.cpp b/src/passhash/bcrypt/bcrypt.cpp
index 3507db879..b0d654717 100644
--- a/src/passhash/bcrypt/bcrypt.cpp
+++ b/src/passhash/bcrypt/bcrypt.cpp
@@ -11,11 +11,6 @@
#include <botan/blowfish.h>
#include <botan/base64.h>
-#include <botan/pipe.h>
-#include <botan/b64_filt.h>
-#include <iostream>
-#include <stdio.h>
-
namespace Botan {
namespace {
@@ -89,10 +84,7 @@ MemoryVector<byte> bcrypt_base64_decode(std::string input)
for(size_t i = 0; i != input.size(); ++i)
input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])];
- //return base64_decode(input);
- Pipe pipe(new Base64_Decoder);
- pipe.process_msg(input);
- return pipe.read_all();
+ return base64_decode(input);
}
std::string make_bcrypt(const std::string& pass,
diff --git a/src/passhash/passhash9/passhash9.cpp b/src/passhash/passhash9/passhash9.cpp
index 367583a0a..43bfdd36e 100644
--- a/src/passhash/passhash9/passhash9.cpp
+++ b/src/passhash/passhash9/passhash9.cpp
@@ -23,8 +23,6 @@ const size_t ALGID_BYTES = 1;
const size_t SALT_BYTES = 12; // 96 bits of salt
const size_t PASSHASH9_PBKDF_OUTPUT_LEN = 24; // 192 bits output
-const byte PASSHASH9_DEFAULT_ALGO = 0; // HMAC(SHA-1)
-
const size_t WORK_FACTOR_SCALE = 10000;
MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
@@ -49,15 +47,8 @@ MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
std::string generate_passhash9(const std::string& pass,
RandomNumberGenerator& rng,
- u16bit work_factor)
- {
- return generate_passhash9(pass, PASSHASH9_DEFAULT_ALGO, rng, work_factor);
- }
-
-std::string generate_passhash9(const std::string& pass,
- byte alg_id,
- RandomNumberGenerator& rng,
- u16bit work_factor)
+ u16bit work_factor,
+ byte alg_id)
{
MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
diff --git a/src/passhash/passhash9/passhash9.h b/src/passhash/passhash9/passhash9.h
index 92cc391dc..3c0a4be51 100644
--- a/src/passhash/passhash9/passhash9.h
+++ b/src/passhash/passhash9/passhash9.h
@@ -17,26 +17,16 @@ namespace Botan {
* @param password the password
* @param rng a random number generator
* @param work_factor how much work to do to slow down guessing attacks
-*/
-std::string BOTAN_DLL generate_passhash9(const std::string& password,
- RandomNumberGenerator& rng,
- u16bit work_factor = 10);
-
-/**
-* Create a password hash using PBKDF2
-* @param password the password
* @param alg_id specifies which PRF to use with PBKDF2
* 0 is HMAC(SHA-1)
* 1 is HMAC(SHA-256)
* 2 is CMAC(Blowfish)
* all other values are currently undefined
-* @param rng a random number generator
-* @param work_factor how much work to do to slow down guessing attacks
*/
std::string BOTAN_DLL generate_passhash9(const std::string& password,
- byte alg_id,
RandomNumberGenerator& rng,
- u16bit work_factor = 10);
+ u16bit work_factor = 10,
+ byte alg_id = 0);
/**
* Check a previously created password hash
diff --git a/src/pk_pad/eme1/eme1.cpp b/src/pk_pad/eme1/eme1.cpp
index b49fb9af0..1cc0c332d 100644
--- a/src/pk_pad/eme1/eme1.cpp
+++ b/src/pk_pad/eme1/eme1.cpp
@@ -65,38 +65,47 @@ SecureVector<byte> EME1::unpad(const byte in[], size_t in_length,
if(in_length > key_length)
in_length = 0;
- SecureVector<byte> tmp(key_length);
- tmp.copy(key_length - in_length, in, in_length);
+ SecureVector<byte> input(key_length);
+ input.copy(key_length - in_length, in, in_length);
- mgf->mask(&tmp[Phash.size()], tmp.size() - Phash.size(),
- &tmp[0], Phash.size());
- mgf->mask(&tmp[0], Phash.size(),
- &tmp[Phash.size()], tmp.size() - Phash.size());
+ mgf->mask(&input[Phash.size()], input.size() - Phash.size(),
+ &input[0], Phash.size());
+ mgf->mask(&input[0], Phash.size(),
+ &input[Phash.size()], input.size() - Phash.size());
- const bool phash_ok = same_mem(&tmp[Phash.size()], &Phash[0], Phash.size());
+ bool waiting_for_delim = true;
+ bool bad_input = false;
+ size_t delim_idx = 2 * Phash.size();
- bool delim_ok = true;
- size_t delim_idx = 0;
-
- // Is this vulnerable to timing attacks?
- for(size_t i = Phash.size() + Phash.size(); i != tmp.size(); ++i)
+ /*
+ * GCC 4.5 on x86-64 compiles this in a way that is still vunerable
+ * to timing analysis. Other compilers, or GCC on other platforms,
+ * may or may not.
+ */
+ for(size_t i = delim_idx; i != input.size(); ++i)
{
- if(tmp[i] && !delim_idx)
- {
- if(tmp[i] == 0x01)
- delim_idx = i;
- else
- delim_ok = false;
- }
- }
+ const bool zero_p = !input[i];
+ const bool one_p = input[i] == 0x01;
- if(delim_idx && delim_ok && phash_ok)
- {
- return SecureVector<byte>(&tmp[delim_idx + 1],
- tmp.size() - delim_idx - 1);
+ const bool add_1 = waiting_for_delim && zero_p;
+
+ bad_input |= waiting_for_delim && !(zero_p || one_p);
+
+ delim_idx += add_1;
+
+ waiting_for_delim &= zero_p;
}
- throw Decoding_Error("Invalid EME1 encoding");
+ // If we never saw any non-zero byte, then it's not valid input
+ bad_input |= waiting_for_delim;
+
+ bad_input |= !same_mem(&input[Phash.size()], &Phash[0], Phash.size());
+
+ if(bad_input)
+ throw Decoding_Error("Invalid EME1 encoding");
+
+ return SecureVector<byte>(input + delim_idx + 1,
+ input.size() - delim_idx - 1);
}
/*
diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_group/ec_group.cpp
index deb512518..fe4fae885 100644
--- a/src/pubkey/ec_dompar/ec_dompar.cpp
+++ b/src/pubkey/ec_group/ec_group.cpp
@@ -7,7 +7,7 @@
* Distributed under the terms of the Botan license
*/
-#include <botan/ec_dompar.h>
+#include <botan/ec_group.h>
#include <botan/ber_dec.h>
#include <botan/der_enc.h>
#include <botan/libstate.h>
@@ -16,7 +16,7 @@
namespace Botan {
-EC_Domain_Params::EC_Domain_Params(const OID& domain_oid)
+EC_Group::EC_Group(const OID& domain_oid)
{
std::string pem =
global_state().get("ec", OIDS::lookup(domain_oid));
@@ -24,31 +24,31 @@ EC_Domain_Params::EC_Domain_Params(const OID& domain_oid)
if(pem == "")
throw Lookup_Error("No ECC domain data for " + domain_oid.as_string());
- *this = EC_Domain_Params(pem);
+ *this = EC_Group(pem);
oid = domain_oid.as_string();
}
-EC_Domain_Params::EC_Domain_Params(const std::string& pem)
+EC_Group::EC_Group(const std::string& str)
{
- if(pem == "")
+ if(str == "")
return; // no initialization / uninitialized
try
{
- DataSource_Memory input(pem);
+ DataSource_Memory input(str);
SecureVector<byte> ber =
PEM_Code::decode_check_label(input, "EC PARAMETERS");
- *this = EC_Domain_Params(ber);
+ *this = EC_Group(ber);
}
catch(Decoding_Error) // hmm, not PEM?
{
- *this = EC_Domain_Params(OID(pem));
+ *this = EC_Group(OIDS::lookup(str));
}
}
-EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data)
+EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
{
BER_Decoder ber(ber_data);
BER_Object obj = ber.get_next_object();
@@ -59,7 +59,7 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data)
{
OID dom_par_oid;
BER_Decoder(ber_data).decode(dom_par_oid);
- *this = EC_Domain_Params(dom_par_oid);
+ *this = EC_Group(dom_par_oid);
}
else if(obj.type_tag == SEQUENCE)
{
@@ -92,7 +92,7 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data)
}
SecureVector<byte>
-EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const
+EC_Group::DER_encode(EC_Group_Encoding form) const
{
if(form == EC_DOMPAR_ENC_EXPLICIT)
{
@@ -125,10 +125,10 @@ EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const
else if(form == EC_DOMPAR_ENC_IMPLICITCA)
return DER_Encoder().encode_null().get_contents();
else
- throw Internal_Error("EC_Domain_Params::DER_encode: Unknown encoding");
+ throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
}
-std::string EC_Domain_Params::PEM_encode() const
+std::string EC_Group::PEM_encode() const
{
SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
return PEM_Code::encode(der, "EC PARAMETERS");
diff --git a/src/pubkey/ec_dompar/ec_dompar.h b/src/pubkey/ec_group/ec_group.h
index 2508d5a2d..b7b09985e 100644
--- a/src/pubkey/ec_dompar/ec_dompar.h
+++ b/src/pubkey/ec_group/ec_group.h
@@ -19,7 +19,7 @@ namespace Botan {
/**
* This class represents elliptic curce domain parameters
*/
-enum EC_Domain_Params_Encoding {
+enum EC_Group_Encoding {
EC_DOMPAR_ENC_EXPLICIT = 0,
EC_DOMPAR_ENC_IMPLICITCA = 1,
EC_DOMPAR_ENC_OID = 2
@@ -28,7 +28,7 @@ enum EC_Domain_Params_Encoding {
/**
* Class representing an elliptic curve
*/
-class BOTAN_DLL EC_Domain_Params
+class BOTAN_DLL EC_Group
{
public:
@@ -39,7 +39,7 @@ class BOTAN_DLL EC_Domain_Params
* @param order the order of the base point
* @param cofactor the cofactor
*/
- EC_Domain_Params(const CurveGFp& curve,
+ EC_Group(const CurveGFp& curve,
const PointGFp& base_point,
const BigInt& order,
const BigInt& cofactor) :
@@ -54,27 +54,27 @@ class BOTAN_DLL EC_Domain_Params
* Decode a BER encoded ECC domain parameter set
* @param ber_encoding the bytes of the BER encoding
*/
- EC_Domain_Params(const MemoryRegion<byte>& ber_encoding);
+ EC_Group(const MemoryRegion<byte>& ber_encoding);
/**
* Create an EC domain by OID (or throw if unknown)
* @param oid the OID of the EC domain to create
*/
- EC_Domain_Params(const OID& oid);
+ EC_Group(const OID& oid);
/**
* Create an EC domain from PEM encoding (as from PEM_encode),
* or from an OID name (eg "secp16r1", or "1.3.132.0.8")
* @param pem_or_oid PEM-encoded data, or an OID
*/
- EC_Domain_Params(const std::string& pem_or_oid = "");
+ EC_Group(const std::string& pem_or_oid = "");
/**
* Create the DER encoding of this domain
* @param form of encoding to use
* @returns bytes encododed as DER
*/
- SecureVector<byte> DER_encode(EC_Domain_Params_Encoding form) const;
+ SecureVector<byte> DER_encode(EC_Group_Encoding form) const;
/**
* Return the PEM encoding (always in explicit form)
@@ -114,7 +114,7 @@ class BOTAN_DLL EC_Domain_Params
*/
std::string get_oid() const { return oid; }
- bool operator==(const EC_Domain_Params& other) const
+ bool operator==(const EC_Group& other) const
{
return ((get_curve() == other.get_curve()) &&
(get_base_point() == other.get_base_point()) &&
@@ -129,12 +129,15 @@ class BOTAN_DLL EC_Domain_Params
std::string oid;
};
-inline bool operator!=(const EC_Domain_Params& lhs,
- const EC_Domain_Params& rhs)
+inline bool operator!=(const EC_Group& lhs,
+ const EC_Group& rhs)
{
return !(lhs == rhs);
}
+// For compatability with 1.8
+typedef EC_Group EC_Domain_Params;
+
}
#endif
diff --git a/src/pubkey/ec_dompar/info.txt b/src/pubkey/ec_group/info.txt
index ae6c328e2..9a686feeb 100644
--- a/src/pubkey/ec_dompar/info.txt
+++ b/src/pubkey/ec_group/info.txt
@@ -1,9 +1,10 @@
-define ECC_DOMAIN_PARAMATERS
+define ECC_GROUP
<requires>
asn1
-numbertheory
-pem
+ec_gfp
libstate
+numbertheory
oid_lookup
+pem
</requires>
diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp
index bd04e3197..991446f07 100644
--- a/src/pubkey/ecc_key/ecc_key.cpp
+++ b/src/pubkey/ecc_key/ecc_key.cpp
@@ -18,7 +18,7 @@
namespace Botan {
-EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par,
+EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
const PointGFp& pub_point) :
domain_params(dom_par), public_key(pub_point),
domain_encoding(EC_DOMPAR_ENC_EXPLICIT)
@@ -30,7 +30,7 @@ EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par,
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits)
{
- domain_params = EC_Domain_Params(alg_id.parameters);
+ domain_params = EC_Group(alg_id.parameters);
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
public_key = OS2ECP(key_bits, domain().get_curve());
@@ -52,7 +52,7 @@ MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const
return EC2OSP(public_point(), PointGFp::COMPRESSED);
}
-void EC_PublicKey::set_parameter_encoding(EC_Domain_Params_Encoding form)
+void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
{
if(form != EC_DOMPAR_ENC_EXPLICIT &&
form != EC_DOMPAR_ENC_IMPLICITCA &&
@@ -76,32 +76,24 @@ const BigInt& EC_PrivateKey::private_value() const
}
/**
-* EC_PrivateKey generator
-*/
-EC_PrivateKey::EC_PrivateKey(const EC_Domain_Params& dom_par,
- const BigInt& priv_key)
- {
- domain_params = dom_par;
- domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
-
- public_key = domain().get_base_point() * priv_key;
- private_key = priv_key;
- }
-
-/**
-* EC_PrivateKey generator
+* EC_PrivateKey constructor
*/
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
- const EC_Domain_Params& dom_par)
+ const EC_Group& ec_group,
+ const BigInt& x)
{
- domain_params = dom_par;
+ domain_params = ec_group;
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
- private_key = BigInt::random_integer(rng, 1, domain().get_order());
+ if(x == 0)
+ private_key = BigInt::random_integer(rng, 1, domain().get_order());
+ else
+ private_key = x;
+
public_key = domain().get_base_point() * private_key;
BOTAN_ASSERT(public_key.on_the_curve(),
- "generated ECC private key was not on the curve");
+ "ECC private key was not on the curve");
}
MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
@@ -118,7 +110,7 @@ MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits)
{
- domain_params = EC_Domain_Params(alg_id.parameters);
+ domain_params = EC_Group(alg_id.parameters);
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
BER_Decoder(key_bits)
diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h
index a20516ec6..cccc8d53c 100644
--- a/src/pubkey/ecc_key/ecc_key.h
+++ b/src/pubkey/ecc_key/ecc_key.h
@@ -10,7 +10,7 @@
#ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H__
#define BOTAN_ECC_PUBLIC_KEY_BASE_H__
-#include <botan/ec_dompar.h>
+#include <botan/ec_group.h>
#include <botan/pk_keys.h>
#include <botan/x509_key.h>
#include <botan/pkcs8.h>
@@ -18,7 +18,7 @@
namespace Botan {
/**
-* This class represents abstract EC Public Keys. When encoding a key
+* This class represents abstract ECC 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
@@ -30,7 +30,7 @@ namespace Botan {
class BOTAN_DLL EC_PublicKey : public virtual Public_Key
{
public:
- EC_PublicKey(const EC_Domain_Params& dom_par,
+ EC_PublicKey(const EC_Group& dom_par,
const PointGFp& pub_point);
EC_PublicKey(const AlgorithmIdentifier& alg_id,
@@ -57,13 +57,13 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key
* domain parameters of this point are not set
* @result the domain parameters of this key
*/
- const EC_Domain_Params& domain() const { return domain_params; }
+ const EC_Group& domain() const { return domain_params; }
/**
* Set the domain parameter encoding to be used when encoding this key.
* @param enc the encoding to use
*/
- void set_parameter_encoding(EC_Domain_Params_Encoding enc);
+ void set_parameter_encoding(EC_Group_Encoding enc);
/**
* Return the DER encoding of this keys domain in whatever format
@@ -76,28 +76,26 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key
* Get the domain parameter encoding to be used when encoding this key.
* @result the encoding to use
*/
- EC_Domain_Params_Encoding domain_format() const
+ EC_Group_Encoding domain_format() const
{ return domain_encoding; }
protected:
EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {}
- EC_Domain_Params domain_params;
+ EC_Group domain_params;
PointGFp public_key;
- EC_Domain_Params_Encoding domain_encoding;
+ EC_Group_Encoding domain_encoding;
};
/**
-* This abstract class represents general EC Private Keys
+* This abstract class represents ECC private keys
*/
class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey,
public virtual Private_Key
{
public:
- EC_PrivateKey(const EC_Domain_Params& domain,
- const BigInt& private_key);
-
- EC_PrivateKey(RandomNumberGenerator& rng,
- const EC_Domain_Params& domain);
+ EC_PrivateKey(RandomNumberGenerator& rng,
+ const EC_Group& domain,
+ const BigInt& private_key);
EC_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits);
diff --git a/src/pubkey/ecc_key/info.txt b/src/pubkey/ecc_key/info.txt
index e08a4231d..ceb98a79e 100644
--- a/src/pubkey/ecc_key/info.txt
+++ b/src/pubkey/ecc_key/info.txt
@@ -4,6 +4,7 @@ define ECC_PUBLIC_KEY_CRYPTO
alloc
asn1
bigint
-ec_dompar
+ec_gfp
+ec_group
numbertheory
</requires>
diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h
index 301bb1591..2edbfe86d 100644
--- a/src/pubkey/ecdh/ecdh.h
+++ b/src/pubkey/ecdh/ecdh.h
@@ -32,7 +32,7 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey
* @param dom_par the domain parameters associated with this key
* @param public_point the public point defining this key
*/
- ECDH_PublicKey(const EC_Domain_Params& dom_par,
+ ECDH_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
@@ -77,10 +77,12 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey,
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
+ * @param x the private key; if zero, a new random key is generated
*/
ECDH_PrivateKey(RandomNumberGenerator& rng,
- const EC_Domain_Params& domain) :
- EC_PrivateKey(rng, domain) {}
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ EC_PrivateKey(rng, domain, x) {}
MemoryVector<byte> public_value() const
{ return ECDH_PublicKey::public_value(); }
diff --git a/src/pubkey/ecdh/info.txt b/src/pubkey/ecdh/info.txt
index 12826c81b..7e7d50fef 100644
--- a/src/pubkey/ecdh/info.txt
+++ b/src/pubkey/ecdh/info.txt
@@ -3,7 +3,7 @@ define ECDH
<requires>
alloc
asn1
-ec_dompar
+ec_group
ecc_key
libstate
numbertheory
diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp
index 9a3510c33..5c45c5ed3 100644
--- a/src/pubkey/ecdsa/ecdsa.cpp
+++ b/src/pubkey/ecdsa/ecdsa.cpp
@@ -80,12 +80,13 @@ bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
BigInt r(sig, sig_len / 2);
BigInt s(sig + sig_len / 2, sig_len / 2);
- if(r < 0 || r >= order || s < 0 || s >= order)
+ if(r <= 0 || r >= order || s <= 0 || s >= order)
return false;
BigInt w = inverse_mod(s, order);
- PointGFp R = w * (e * base_point + r * public_point);
+ PointGFp R = w * multi_exponentiate(base_point, e,
+ public_point, r);
if(R.is_zero())
return false;
diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h
index 6d62a168d..f0834abd8 100644
--- a/src/pubkey/ecdsa/ecdsa.h
+++ b/src/pubkey/ecdsa/ecdsa.h
@@ -28,7 +28,7 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey
* @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,
+ ECDSA_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
@@ -66,6 +66,11 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
{
public:
+ /**
+ * Load a private key
+ * @param alg_id the X.509 algorithm identifier
+ * @param key_bits PKCS #8 structure
+ */
ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
const MemoryRegion<byte>& key_bits) :
EC_PrivateKey(alg_id, key_bits) {}
@@ -74,19 +79,12 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey,
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
+ * @param x the private key (if zero, generate a ney random key)
*/
ECDSA_PrivateKey(RandomNumberGenerator& rng,
- const EC_Domain_Params& domain) :
- EC_PrivateKey(rng, domain) {}
-
- /**
- * Load a private key
- * @param domain parameters
- * @param x the private key
- */
- ECDSA_PrivateKey(const EC_Domain_Params& domain,
- const BigInt& x) :
- EC_PrivateKey(domain, x) {}
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ EC_PrivateKey(rng, domain, x) {}
bool check_key(RandomNumberGenerator& rng, bool) const;
};
diff --git a/src/pubkey/ecdsa/info.txt b/src/pubkey/ecdsa/info.txt
index ca2694ad1..7a2113a30 100644
--- a/src/pubkey/ecdsa/info.txt
+++ b/src/pubkey/ecdsa/info.txt
@@ -2,7 +2,7 @@ define ECDSA
<requires>
asn1
-ec_dompar
+ec_group
ecc_key
numbertheory
rng
diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp
index fa72d0673..f97f83aa0 100644
--- a/src/pubkey/gost_3410/gost_3410.cpp
+++ b/src/pubkey/gost_3410/gost_3410.cpp
@@ -17,8 +17,8 @@ namespace Botan {
MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
{
// Trust CryptoPro to come up with something obnoxious
- const BigInt& x = public_point().get_affine_x();
- const BigInt& y = public_point().get_affine_y();
+ const BigInt x = public_point().get_affine_x();
+ const BigInt y = public_point().get_affine_y();
size_t part_size = std::max(x.bytes(), y.bytes());
@@ -56,7 +56,7 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
// Also includes hash and cipher OIDs... brilliant design guys
BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);
- domain_params = EC_Domain_Params(ecc_param_id);
+ domain_params = EC_Group(ecc_param_id);
SecureVector<byte> bits;
BER_Decoder(key_bits).decode(bits, OCTET_STRING);
@@ -153,7 +153,7 @@ bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len,
BigInt s(sig, sig_len / 2);
BigInt r(sig + sig_len / 2, sig_len / 2);
- if(r < 0 || r >= order || s < 0 || s >= order)
+ if(r <= 0 || r >= order || s <= 0 || s >= order)
return false;
e %= order;
@@ -165,7 +165,11 @@ bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len,
BigInt z1 = (s*v) % order;
BigInt z2 = (-r*v) % order;
- PointGFp R = (z1 * base_point + z2 * public_point);
+ PointGFp R = multi_exponentiate(base_point, z1,
+ public_point, z2);
+
+ if(R.is_zero())
+ return false;
return (R.get_affine_x() == r);
}
diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h
index 4fb7b42c3..7b638d7b5 100644
--- a/src/pubkey/gost_3410/gost_3410.h
+++ b/src/pubkey/gost_3410/gost_3410.h
@@ -27,7 +27,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey
* @param dom_par the domain parameters associated with this key
* @param public_point the public point defining this key
*/
- GOST_3410_PublicKey(const EC_Domain_Params& dom_par,
+ GOST_3410_PublicKey(const EC_Group& dom_par,
const PointGFp& public_point) :
EC_PublicKey(dom_par, public_point) {}
@@ -80,18 +80,12 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey,
* Generate a new private key
* @param rng a random number generator
* @param domain parameters to used for this key
+ * @param x the private key; if zero, a new random key is generated
*/
GOST_3410_PrivateKey(RandomNumberGenerator& rng,
- const EC_Domain_Params& domain) :
- EC_PrivateKey(rng, domain) {}
-
- /**
- * Load a private key
- * @param domain parameters
- * @param x the private key
- */
- GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) :
- EC_PrivateKey(domain, x) {}
+ const EC_Group& domain,
+ const BigInt& x = 0) :
+ EC_PrivateKey(rng, domain, x) {}
AlgorithmIdentifier pkcs8_algorithm_identifier() const
{ return EC_PublicKey::algorithm_identifier(); }
diff --git a/src/pubkey/gost_3410/info.txt b/src/pubkey/gost_3410/info.txt
index 05df445ec..9fbc3099f 100644
--- a/src/pubkey/gost_3410/info.txt
+++ b/src/pubkey/gost_3410/info.txt
@@ -5,7 +5,7 @@ load_on auto
<requires>
alloc
asn1
-ec_dompar
+ec_group
ecc_key
libstate
numbertheory
diff --git a/src/utils/simd_32/info.txt b/src/simd/info.txt
index 362e90235..d0601b141 100644
--- a/src/utils/simd_32/info.txt
+++ b/src/simd/info.txt
@@ -2,7 +2,8 @@ define SIMD_32
<header:internal>
simd_32.h
-simd_sse.h
-simd_scalar.h
-simd_altivec.h
</header:internal>
+
+<requires>
+simd_sse2|simd_altivec|simd_scalar
+</requires>
diff --git a/src/simd/simd_32.h b/src/simd/simd_32.h
new file mode 100644
index 000000000..4ef0cea85
--- /dev/null
+++ b/src/simd/simd_32.h
@@ -0,0 +1,30 @@
+/*
+* Lightweight wrappers for SIMD operations
+* (C) 2009,2011 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SIMD_32_H__
+#define BOTAN_SIMD_32_H__
+
+#include <botan/types.h>
+
+#if defined(BOTAN_HAS_SIMD_SSE2)
+ #include <botan/internal/simd_sse2.h>
+ namespace Botan { typedef SIMD_SSE2 SIMD_32; }
+
+#elif defined(BOTAN_HAS_SIMD_ALTIVEC)
+ #include <botan/internal/simd_altivec.h>
+ namespace Botan { typedef SIMD_Altivec SIMD_32; }
+
+#elif defined(BOTAN_HAS_SIMD_SCALAR)
+ #include <botan/internal/simd_scalar.h>
+ namespace Botan { typedef SIMD_Scalar SIMD_32; }
+
+#else
+ #error "No SIMD module defined"
+
+#endif
+
+#endif
diff --git a/src/simd/simd_altivec/info.txt b/src/simd/simd_altivec/info.txt
new file mode 100644
index 000000000..aa2f01c2d
--- /dev/null
+++ b/src/simd/simd_altivec/info.txt
@@ -0,0 +1,9 @@
+define SIMD_ALTIVEC
+
+need_isa altivec
+
+load_on dep
+
+<header:internal>
+simd_altivec.h
+</header:internal>
diff --git a/src/utils/simd_32/simd_altivec.h b/src/simd/simd_altivec/simd_altivec.h
index 4c412ddec..4c412ddec 100644
--- a/src/utils/simd_32/simd_altivec.h
+++ b/src/simd/simd_altivec/simd_altivec.h
diff --git a/src/simd/simd_scalar/info.txt b/src/simd/simd_scalar/info.txt
new file mode 100644
index 000000000..6817eab80
--- /dev/null
+++ b/src/simd/simd_scalar/info.txt
@@ -0,0 +1,7 @@
+define SIMD_SCALAR
+
+load_on dep
+
+<header:internal>
+simd_scalar.h
+</header:internal>
diff --git a/src/utils/simd_32/simd_scalar.h b/src/simd/simd_scalar/simd_scalar.h
index 2c68622af..2c68622af 100644
--- a/src/utils/simd_32/simd_scalar.h
+++ b/src/simd/simd_scalar/simd_scalar.h
diff --git a/src/simd/simd_sse2/info.txt b/src/simd/simd_sse2/info.txt
new file mode 100644
index 000000000..e56792491
--- /dev/null
+++ b/src/simd/simd_sse2/info.txt
@@ -0,0 +1,9 @@
+define SIMD_SSE2
+
+need_isa sse2
+
+load_on dep
+
+<header:internal>
+simd_sse2.h
+</header:internal>
diff --git a/src/utils/simd_32/simd_sse.h b/src/simd/simd_sse2/simd_sse2.h
index 1cb52105c..61fce99a9 100644
--- a/src/utils/simd_32/simd_sse.h
+++ b/src/simd/simd_sse2/simd_sse2.h
@@ -22,7 +22,7 @@ class SIMD_SSE2
SIMD_SSE2(const u32bit B[4])
{
- reg = _mm_loadu_si128((const __m128i*)B);
+ reg = _mm_loadu_si128(reinterpret_cast<const __m128i*>(B));
}
SIMD_SSE2(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
@@ -37,7 +37,7 @@ class SIMD_SSE2
static SIMD_SSE2 load_le(const void* in)
{
- return _mm_loadu_si128((const __m128i*)in);
+ return _mm_loadu_si128(reinterpret_cast<const __m128i*>(in));
}
static SIMD_SSE2 load_be(const void* in)
@@ -47,7 +47,7 @@ class SIMD_SSE2
void store_le(byte out[]) const
{
- _mm_storeu_si128((__m128i*)out, reg);
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out), reg);
}
void store_be(byte out[]) const
diff --git a/src/ssl/hello.cpp b/src/ssl/hello.cpp
index bec316bb1..2c5a9d2ea 100644
--- a/src/ssl/hello.cpp
+++ b/src/ssl/hello.cpp
@@ -177,8 +177,9 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
std::vector<byte> name =
reader.get_range_vector<byte>(2, 1, 65535);
- requested_hostname.assign((const char*)&name[0],
- name.size());
+ requested_hostname.assign(
+ reinterpret_cast<const char*>(&name[0]),
+ name.size());
name_bytes -= (2 + name.size());
}
diff --git a/src/ssl/info.txt b/src/ssl/info.txt
index 1f11772cd..910ed7e97 100644
--- a/src/ssl/info.txt
+++ b/src/ssl/info.txt
@@ -1,7 +1,11 @@
define SSL_TLS
+<comment>
+The SSL/TLS code is complex, new, and not yet reviewed, there may be
+serious bugs or security issues.
+</comment>
+
<header:public>
-socket.h
tls_client.h
tls_connection.h
tls_exceptn.h
@@ -51,11 +55,11 @@ emsa3
filters
hmac
md5
+prf_ssl3
+prf_tls
rng
rsa
sha1
ssl3mac
-ssl_prf
-tls_prf
x509cert
</requires>
diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp
index 042aae0c9..4e5b69780 100644
--- a/src/ssl/rec_read.cpp
+++ b/src/ssl/rec_read.cpp
@@ -223,7 +223,7 @@ size_t Record_Reader::get_record(byte& msg_type,
throw Decoding_Error("Record_Reader: Record truncated");
const size_t mac_offset = plaintext.size() - (mac_size + pad_size);
- SecureVector<byte> recieved_mac(&plaintext[mac_offset],
+ SecureVector<byte> received_mac(&plaintext[mac_offset],
mac_size);
const u16bit plain_length = plaintext.size() - (mac_size + pad_size + iv_size);
@@ -242,7 +242,7 @@ size_t Record_Reader::get_record(byte& msg_type,
SecureVector<byte> computed_mac = mac->final();
- if(recieved_mac != computed_mac)
+ if(received_mac != computed_mac)
throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure");
msg_type = header[0];
diff --git a/src/ssl/socket.h b/src/ssl/socket.h
deleted file mode 100644
index 6d88bd48a..000000000
--- a/src/ssl/socket.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-* Socket Interface
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SOCKET_H__
-#define BOTAN_TLS_SOCKET_H__
-
-#include <botan/types.h>
-#include <string>
-
-namespace Botan {
-
-/**
-* Socket Base Class
-*/
-class BOTAN_DLL Socket
- {
- public:
- virtual size_t read(byte[], size_t) = 0;
- virtual void write(const byte[], size_t) = 0;
-
- virtual std::string peer_id() const = 0;
-
- virtual void close() = 0;
-
- virtual ~Socket() {}
- };
-
-/**
-* Server Socket Base Class
-*/
-class BOTAN_DLL Server_Socket
- {
- public:
- virtual Socket* accept() = 0;
- virtual void close() = 0;
-
- virtual ~Server_Socket() {}
- };
-
-}
-
-#endif
diff --git a/src/ssl/tls_alerts.h b/src/ssl/tls_alerts.h
index f189cf507..241599aa8 100644
--- a/src/ssl/tls_alerts.h
+++ b/src/ssl/tls_alerts.h
@@ -15,7 +15,7 @@ namespace Botan {
/**
* SSL/TLS Alert Message
*/
-class BOTAN_DLL Alert
+class Alert
{
public:
/**
diff --git a/src/ssl/tls_client.cpp b/src/ssl/tls_client.cpp
index 03c8117cc..eeb99e24d 100644
--- a/src/ssl/tls_client.cpp
+++ b/src/ssl/tls_client.cpp
@@ -294,7 +294,7 @@ void TLS_Client::state_machine()
}
}
else
- throw Unexpected_Message("Unknown message type recieved");
+ throw Unexpected_Message("Unknown message type received");
}
/**
@@ -440,7 +440,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
is_rsa = true;
else
throw TLS_Exception(UNSUPPORTED_CERTIFICATE,
- "Unknown key type recieved in server kex");
+ "Unknown key type received in server kex");
if((is_dsa && state->suite.sig_type() != TLS_ALGO_SIGNER_DSA) ||
(is_rsa && state->suite.sig_type() != TLS_ALGO_SIGNER_RSA))
@@ -469,7 +469,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
is_rsa = true;
else
throw TLS_Exception(HANDSHAKE_FAILURE,
- "Unknown key type recieved in server kex");
+ "Unknown key type received in server kex");
if((is_dh && state->suite.kex_type() != TLS_ALGO_KEYEXCH_DH) ||
(is_rsa && state->suite.kex_type() != TLS_ALGO_KEYEXCH_RSA))
@@ -560,7 +560,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
active = true;
}
else
- throw Unexpected_Message("Unknown handshake message recieved");
+ throw Unexpected_Message("Unknown handshake message received");
}
/**
diff --git a/src/ssl/tls_exceptn.h b/src/ssl/tls_exceptn.h
index a9efc718a..37b9c0d27 100644
--- a/src/ssl/tls_exceptn.h
+++ b/src/ssl/tls_exceptn.h
@@ -32,7 +32,7 @@ class BOTAN_DLL TLS_Exception : public Exception
/**
* Unexpected_Message Exception
*/
-struct Unexpected_Message : public TLS_Exception
+struct BOTAN_DLL Unexpected_Message : public TLS_Exception
{
Unexpected_Message(const std::string& err) :
TLS_Exception(UNEXPECTED_MESSAGE, err) {}
diff --git a/src/ssl/tls_handshake_hash.h b/src/ssl/tls_handshake_hash.h
index ceaa55584..cea612a71 100644
--- a/src/ssl/tls_handshake_hash.h
+++ b/src/ssl/tls_handshake_hash.h
@@ -17,7 +17,7 @@ using namespace Botan;
/**
* TLS Handshake Hash
*/
-class BOTAN_DLL HandshakeHash
+class HandshakeHash
{
public:
void update(const byte in[], size_t length)
diff --git a/src/ssl/tls_messages.h b/src/ssl/tls_messages.h
index c5d4d8cb8..0b3553ac0 100644
--- a/src/ssl/tls_messages.h
+++ b/src/ssl/tls_messages.h
@@ -21,7 +21,7 @@ namespace Botan {
/**
* TLS Handshake Message Base Class
*/
-class BOTAN_DLL HandshakeMessage
+class HandshakeMessage
{
public:
void send(Record_Writer&, HandshakeHash&) const;
@@ -38,7 +38,7 @@ class BOTAN_DLL HandshakeMessage
/**
* Client Hello Message
*/
-class BOTAN_DLL Client_Hello : public HandshakeMessage
+class Client_Hello : public HandshakeMessage
{
public:
Handshake_Type type() const { return CLIENT_HELLO; }
@@ -80,7 +80,7 @@ class BOTAN_DLL Client_Hello : public HandshakeMessage
/**
* Client Key Exchange Message
*/
-class BOTAN_DLL Client_Key_Exchange : public HandshakeMessage
+class Client_Key_Exchange : public HandshakeMessage
{
public:
Handshake_Type type() const { return CLIENT_KEX; }
@@ -112,7 +112,7 @@ class BOTAN_DLL Client_Key_Exchange : public HandshakeMessage
/**
* Certificate Message
*/
-class BOTAN_DLL Certificate : public HandshakeMessage
+class Certificate : public HandshakeMessage
{
public:
Handshake_Type type() const { return CERTIFICATE; }
@@ -130,7 +130,7 @@ class BOTAN_DLL Certificate : public HandshakeMessage
/**
* Certificate Request Message
*/
-class BOTAN_DLL Certificate_Req : public HandshakeMessage
+class Certificate_Req : public HandshakeMessage
{
public:
Handshake_Type type() const { return CERTIFICATE_REQUEST; }
@@ -157,7 +157,7 @@ class BOTAN_DLL Certificate_Req : public HandshakeMessage
/**
* Certificate Verify Message
*/
-class BOTAN_DLL Certificate_Verify : public HandshakeMessage
+class Certificate_Verify : public HandshakeMessage
{
public:
Handshake_Type type() const { return CERTIFICATE_VERIFY; }
@@ -179,7 +179,7 @@ class BOTAN_DLL Certificate_Verify : public HandshakeMessage
/**
* Finished Message
*/
-class BOTAN_DLL Finished : public HandshakeMessage
+class Finished : public HandshakeMessage
{
public:
Handshake_Type type() const { return FINISHED; }
@@ -205,7 +205,7 @@ class BOTAN_DLL Finished : public HandshakeMessage
/**
* Hello Request Message
*/
-class BOTAN_DLL Hello_Request : public HandshakeMessage
+class Hello_Request : public HandshakeMessage
{
public:
Handshake_Type type() const { return HELLO_REQUEST; }
@@ -220,7 +220,7 @@ class BOTAN_DLL Hello_Request : public HandshakeMessage
/**
* Server Hello Message
*/
-class BOTAN_DLL Server_Hello : public HandshakeMessage
+class Server_Hello : public HandshakeMessage
{
public:
Handshake_Type type() const { return SERVER_HELLO; }
@@ -250,7 +250,7 @@ class BOTAN_DLL Server_Hello : public HandshakeMessage
/**
* Server Key Exchange Message
*/
-class BOTAN_DLL Server_Key_Exchange : public HandshakeMessage
+class Server_Key_Exchange : public HandshakeMessage
{
public:
Handshake_Type type() const { return SERVER_KEX; }
@@ -277,7 +277,7 @@ class BOTAN_DLL Server_Key_Exchange : public HandshakeMessage
/**
* Server Hello Done Message
*/
-class BOTAN_DLL Server_Hello_Done : public HandshakeMessage
+class Server_Hello_Done : public HandshakeMessage
{
public:
Handshake_Type type() const { return SERVER_HELLO_DONE; }
diff --git a/src/ssl/tls_record.h b/src/ssl/tls_record.h
index b4c052a1c..7d3bc4c6a 100644
--- a/src/ssl/tls_record.h
+++ b/src/ssl/tls_record.h
@@ -1,3 +1,4 @@
+1
/*
* TLS Record Handling
* (C) 2004-2010 Jack Lloyd
diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp
index 20e98797f..1f301e6b1 100644
--- a/src/ssl/tls_server.cpp
+++ b/src/ssl/tls_server.cpp
@@ -262,7 +262,7 @@ void TLS_Server::state_machine()
}
}
else
- throw Unexpected_Message("Unknown message type recieved");
+ throw Unexpected_Message("Unknown message type received");
}
/*
@@ -471,7 +471,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
active = true;
}
else
- throw Unexpected_Message("Unknown handshake message recieved");
+ throw Unexpected_Message("Unknown handshake message received");
}
/*
diff --git a/src/ssl/unix_socket/info.txt b/src/ssl/unix_socket/info.txt
deleted file mode 100644
index 15fc50f5b..000000000
--- a/src/ssl/unix_socket/info.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-define UNIX_SOCKET
-
-<source>
-unx_sock.cpp
-</source>
-
-<header:public>
-unx_sock.h
-</header:public>
-
-<requires>
-ssl
-</requires>
-
-<os>
-linux
-freebsd
-netbsd
-solaris
-</os>
diff --git a/src/ssl/unix_socket/unx_sock.cpp b/src/ssl/unix_socket/unx_sock.cpp
deleted file mode 100644
index a7c19b70c..000000000
--- a/src/ssl/unix_socket/unx_sock.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-* Unix Socket
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/unx_sock.h>
-#include <botan/exceptn.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-namespace Botan {
-
-/**
-* Unix Socket Constructor
-*/
-Unix_Socket::Unix_Socket(const std::string& host, u16bit port) : peer(host)
- {
- sockfd = -1;
-
- hostent* host_addr = ::gethostbyname(host.c_str());
-
- if(host_addr == 0)
- throw Stream_IO_Error("Unix_Socket: gethostbyname failed for " + host);
- if(host_addr->h_addrtype != AF_INET) // FIXME
- throw Stream_IO_Error("Unix_Socket: " + host + " has IPv6 address");
-
- int fd = ::socket(PF_INET, SOCK_STREAM, 0);
- if(fd == -1)
- throw Stream_IO_Error("Unix_Socket: Unable to acquire socket");
-
- sockaddr_in socket_info;
- ::memset(&socket_info, 0, sizeof(socket_info));
- socket_info.sin_family = AF_INET;
- socket_info.sin_port = htons(port);
-
- ::memcpy(&socket_info.sin_addr,
- host_addr->h_addr,
- host_addr->h_length);
-
- socket_info.sin_addr = *(struct in_addr*)host_addr->h_addr; // FIXME
-
- if(::connect(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
- {
- ::close(fd);
- throw Stream_IO_Error("Unix_Socket: connect failed");
- }
-
- sockfd = fd;
- }
-
-/**
-* Unix Socket Constructor
-*/
-Unix_Socket::Unix_Socket(int fd, const std::string& peer_id)
- {
- sockfd = fd;
- peer = peer_id;
- }
-
-/**
-* Read from a Unix socket
-*/
-size_t Unix_Socket::read(byte buf[], size_t length)
- {
- if(sockfd == -1)
- throw Stream_IO_Error("Unix_Socket::read: Socket not connected");
-
- size_t got = 0;
-
- while(length)
- {
- ssize_t this_time = ::recv(sockfd, buf + got, length, MSG_NOSIGNAL);
-
- if(this_time == 0)
- break;
-
- if(this_time == -1)
- {
- if(errno == EINTR)
- this_time = 0;
- else
- throw Stream_IO_Error("Unix_Socket::read: Socket read failed");
- }
-
- got += this_time;
- length -= this_time;
- }
- return got;
- }
-
-/**
-* Write to a Unix socket
-*/
-void Unix_Socket::write(const byte buf[], size_t length)
- {
- if(sockfd == -1)
- throw Stream_IO_Error("Unix_Socket::write: Socket not connected");
-
- size_t offset = 0;
- while(length)
- {
- ssize_t sent = ::send(sockfd, buf + offset, length, MSG_NOSIGNAL);
-
- if(sent == -1)
- {
- if(errno == EINTR)
- sent = 0;
- else
- throw Stream_IO_Error("Unix_Socket::write: Socket write failed");
- }
-
- offset += sent;
- length -= sent;
- }
- }
-
-/**
-* Close a Unix socket
-*/
-void Unix_Socket::close()
- {
- if(sockfd != -1)
- {
- if(::close(sockfd) != 0)
- throw Stream_IO_Error("Unix_Socket::close failed");
- sockfd = -1;
- }
- }
-
-/**
-* Return the peer's name
-*/
-std::string Unix_Socket::peer_id() const
- {
- return peer;
- }
-
-/**
-* Unix Server Socket Constructor
-*/
-Unix_Server_Socket::Unix_Server_Socket(u16bit port)
- {
- sockfd = -1;
-
- int fd = ::socket(PF_INET, SOCK_STREAM, 0);
- if(fd == -1)
- throw Stream_IO_Error("Unix_Server_Socket: Unable to acquire socket");
-
- sockaddr_in socket_info;
- ::memset(&socket_info, 0, sizeof(socket_info));
- socket_info.sin_family = AF_INET;
- socket_info.sin_port = htons(port);
-
- // FIXME: support limiting listeners
- socket_info.sin_addr.s_addr = INADDR_ANY;
-
- if(::bind(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
- {
- ::close(fd);
- throw Stream_IO_Error("Unix_Server_Socket: bind failed");
- }
-
- if(listen(fd, 100) != 0) // FIXME: totally arbitrary
- {
- ::close(fd);
- throw Stream_IO_Error("Unix_Server_Socket: listen failed");
- }
-
- sockfd = fd;
- }
-
-/**
-* Close a Unix socket
-*/
-void Unix_Server_Socket::close()
- {
- if(sockfd != -1)
- {
- if(::close(sockfd) != 0)
- throw Stream_IO_Error("Unix_Server_Socket::close failed");
- sockfd = -1;
- }
- }
-
-/**
-* Accept a new connection
-*/
-Socket* Unix_Server_Socket::accept()
- {
- // FIXME: grab IP of remote side, use gethostbyaddr, store as peer_id
- int retval = ::accept(sockfd, 0, 0);
- if(retval == -1)
- throw Stream_IO_Error("Unix_Server_Socket: accept failed");
- return new Unix_Socket(retval);
- }
-
-}
diff --git a/src/ssl/unix_socket/unx_sock.h b/src/ssl/unix_socket/unx_sock.h
deleted file mode 100644
index 58c7ada69..000000000
--- a/src/ssl/unix_socket/unx_sock.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-* Unix Socket
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SOCKET_UNIX_H__
-#define BOTAN_TLS_SOCKET_UNIX_H__
-
-#include <botan/socket.h>
-
-namespace Botan {
-
-/**
- FIXME: the current socket interface is totally unusable
- It has to handle (cleanly):
- - TCP, UDP, and SCTP, where UDP is only usable with DTLS and
- TCP/SCTP is only usable with TLS.
- - Alternate socket interfaces (ACE, Netxx, whatever) with
- minimal wrapping needed.
-*/
-
-
-/**
-* Unix Socket Base Class
-*/
-class BOTAN_DLL Unix_Socket : public Socket
- {
- public:
- size_t read(byte[], size_t);
- void write(const byte[], size_t);
-
- std::string peer_id() const;
-
- void close();
- Unix_Socket(int, const std::string& = "");
- Unix_Socket(const std::string&, u16bit);
- ~Unix_Socket() { close(); }
- private:
- std::string peer;
- int sockfd;
- };
-
-/**
-* Unix Server Socket Base Class
-*/
-class BOTAN_DLL Unix_Server_Socket : public Server_Socket
- {
- public:
- Socket* accept();
- void close();
-
- Unix_Server_Socket(u16bit);
- ~Unix_Server_Socket() { close(); }
- private:
- int sockfd;
- };
-
-}
-
-#endif
diff --git a/src/stream/ctr/ctr.cpp b/src/stream/ctr/ctr.cpp
index d221dc441..3a370eca3 100644
--- a/src/stream/ctr/ctr.cpp
+++ b/src/stream/ctr/ctr.cpp
@@ -1,6 +1,6 @@
/*
* Counter mode
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -85,20 +85,21 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len)
if(!valid_iv_length(iv_len))
throw Invalid_IV_Length(name(), iv_len);
- const size_t BLOCK_SIZE = permutation->block_size();
+ const size_t bs = permutation->block_size();
zeroise(counter);
counter.copy(0, iv, iv_len);
+ /*
+ * Set counter blocks to IV, IV + 1, ... IV + 255
+ */
for(size_t i = 1; i != 256; ++i)
{
- counter.copy(i*BLOCK_SIZE,
- &counter[(i-1)*BLOCK_SIZE],
- BLOCK_SIZE);
+ counter.copy(i*bs, &counter[(i-1)*bs], bs);
- for(size_t j = 0; j != BLOCK_SIZE; ++j)
- if(++counter[i*BLOCK_SIZE + (BLOCK_SIZE-1-j)])
+ for(size_t j = 0; j != bs; ++j)
+ if(++counter[i*bs + (bs - 1 - j)])
break;
}
@@ -111,12 +112,17 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len)
*/
void CTR_BE::increment_counter()
{
- const size_t BLOCK_SIZE = permutation->block_size();
+ const size_t bs = permutation->block_size();
+ /*
+ * Each counter value always needs to be incremented by 256,
+ * so we don't touch the lowest byte and instead treat it as
+ * an increment of one starting with the next byte.
+ */
for(size_t i = 0; i != 256; ++i)
{
- for(size_t j = 1; j != BLOCK_SIZE; ++j)
- if(++counter[i*BLOCK_SIZE + (BLOCK_SIZE-1-j)])
+ for(size_t j = 1; j != bs; ++j)
+ if(++counter[i*bs + (bs - 1 - j)])
break;
}
diff --git a/src/utils/asm_ia32/asm_macr_ia32.h b/src/utils/asm_x86_32/asm_x86_32.h
index 2ea69512b..d5482c419 100644
--- a/src/utils/asm_ia32/asm_macr_ia32.h
+++ b/src/utils/asm_x86_32/asm_x86_32.h
@@ -1,12 +1,12 @@
/*
-* Assembly Macros
+* Assembly Macros for 32-bit x86
* (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__
+#ifndef BOTAN_ASM_MACROS_X86_32_H__
+#define BOTAN_ASM_MACROS_X86_32_H__
/*
* General/Global Macros
diff --git a/src/utils/asm_ia32/info.txt b/src/utils/asm_x86_32/info.txt
index 997d51b8c..21244968f 100644
--- a/src/utils/asm_ia32/info.txt
+++ b/src/utils/asm_x86_32/info.txt
@@ -1,11 +1,11 @@
load_on dep
<header:internal>
-asm_macr_ia32.h
+asm_x86_32.h
</header:internal>
<arch>
-ia32
+x86_32
</arch>
# ELF systems
@@ -19,7 +19,6 @@ solaris
</os>
<cc>
-clang
gcc
icc
</cc>
diff --git a/src/utils/asm_amd64/asm_macr_amd64.h b/src/utils/asm_x86_64/asm_x86_64.h
index 287fa3e88..7abc1f392 100644
--- a/src/utils/asm_amd64/asm_macr_amd64.h
+++ b/src/utils/asm_x86_64/asm_x86_64.h
@@ -1,12 +1,12 @@
/*
-* Assembly Macros
+* Assembly Macros for 64-bit x86
* (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__
+#ifndef BOTAN_ASM_MACROS_X86_64_H__
+#define BOTAN_ASM_MACROS_X86_64_H__
/*
* General/Global Macros
diff --git a/src/utils/asm_amd64/info.txt b/src/utils/asm_x86_64/info.txt
index 404aeca7b..3173f3b14 100644
--- a/src/utils/asm_amd64/info.txt
+++ b/src/utils/asm_x86_64/info.txt
@@ -1,11 +1,11 @@
load_on dep
<header:internal>
-asm_macr_amd64.h
+asm_x86_64.h
</header:internal>
<arch>
-amd64
+x86_64
</arch>
<cc>
diff --git a/src/utils/bswap.h b/src/utils/bswap.h
index 6dfed0ba9..9d2c9bc28 100644
--- a/src/utils/bswap.h
+++ b/src/utils/bswap.h
@@ -1,6 +1,6 @@
/*
* Byte Swapping Operations
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
* (C) 2007 Yves Jerschow
*
* Distributed under the terms of the Botan license
@@ -21,38 +21,55 @@ namespace Botan {
/**
* Swap a 16 bit integer
*/
-inline u16bit reverse_bytes(u16bit input)
+inline u16bit reverse_bytes(u16bit val)
{
- return rotate_left(input, 8);
+ return rotate_left(val, 8);
}
/**
* Swap a 32 bit integer
*/
-inline u32bit reverse_bytes(u32bit input)
+inline u32bit reverse_bytes(u32bit val)
{
-#if BOTAN_GCC_VERSION >= 430
+#if BOTAN_GCC_VERSION >= 430 && !defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+ /*
+ GCC intrinsic added in 4.3, works for a number of CPUs
- // GCC intrinsic added in 4.3, works for a number of CPUs
- return __builtin_bswap32(input);
+ However avoid under ARM, as it branches to a function in libgcc
+ instead of generating inline asm, so slower even than the generic
+ rotate version below.
+ */
+ return __builtin_bswap32(val);
#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
// GCC-style inline assembly for x86 or x86-64
- asm("bswapl %0" : "=r" (input) : "0" (input));
- return input;
+ asm("bswapl %0" : "=r" (val) : "0" (val));
+ return val;
+
+#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+
+ asm ("eor r3, %1, %1, ror #16\n\t"
+ "bic r3, r3, #0x00FF0000\n\t"
+ "mov %0, %1, ror #8\n\t"
+ "eor %0, %0, r3, lsr #8"
+ : "=r" (val)
+ : "0" (val)
+ : "r3", "cc");
+
+ return val;
-#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32)
+#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_X86_32)
// Visual C++ inline asm for 32-bit x86, by Yves Jerschow
- __asm mov eax, input;
+ __asm mov eax, val;
__asm bswap eax;
#else
// Generic implementation
- return (rotate_right(input, 8) & 0xFF00FF00) |
- (rotate_left (input, 8) & 0x00FF00FF);
+ return (rotate_right(val, 8) & 0xFF00FF00) |
+ (rotate_left (val, 8) & 0x00FF00FF);
#endif
}
@@ -60,17 +77,17 @@ inline u32bit reverse_bytes(u32bit input)
/**
* Swap a 64 bit integer
*/
-inline u64bit reverse_bytes(u64bit input)
+inline u64bit reverse_bytes(u64bit val)
{
#if BOTAN_GCC_VERSION >= 430
// GCC intrinsic added in 4.3, works for a number of CPUs
- return __builtin_bswap64(input);
+ return __builtin_bswap64(val);
-#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64)
+#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_X86_64)
// GCC-style inline assembly for x86-64
- asm("bswapq %0" : "=r" (input) : "0" (input));
- return input;
+ asm("bswapq %0" : "=r" (val) : "0" (val));
+ return val;
#else
/* Generic implementation. Defined in terms of 32-bit bswap so any
@@ -78,8 +95,8 @@ inline u64bit reverse_bytes(u64bit input)
* useful for 32-bit x86).
*/
- u32bit hi = static_cast<u32bit>(input >> 32);
- u32bit lo = static_cast<u32bit>(input);
+ u32bit hi = static_cast<u32bit>(val >> 32);
+ u32bit lo = static_cast<u32bit>(val);
hi = reverse_bytes(hi);
lo = reverse_bytes(lo);
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
index 9ea9e82ad..cb6fdaba5 100644
--- a/src/utils/cpuid.cpp
+++ b/src/utils/cpuid.cpp
@@ -30,8 +30,21 @@
// Only available starting in GCC 4.3
#include <cpuid.h>
- #define CALL_CPUID(type, out) \
- do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0);
+
+namespace {
+
+ /*
+ * Prevent inlining to work around GCC bug 44174
+ */
+ void __attribute__((__noinline__)) call_gcc_cpuid(Botan::u32bit type,
+ Botan::u32bit out[4])
+ {
+ __get_cpuid(type, out, out+1, out+2, out+3);
+ }
+
+ #define CALL_CPUID call_gcc_cpuid
+
+}
#else
#warning "No method of calling CPUID for this compiler"
@@ -149,9 +162,9 @@ void CPUID::initialize()
u32bit cpuid[4] = { 0 };
CALL_CPUID(1, cpuid);
- x86_processor_flags = ((u64bit)cpuid[2] << 32) | cpuid[3];
+ x86_processor_flags = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
-#if defined(BOTAN_TARGET_ARCH_IS_AMD64)
+#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
/*
* If we don't have access to CPUID, we can still safely assume that
* any x86-64 processor has SSE2.
diff --git a/src/utils/dyn_load/info.txt b/src/utils/dyn_load/info.txt
index 512410460..6d74acb86 100644
--- a/src/utils/dyn_load/info.txt
+++ b/src/utils/dyn_load/info.txt
@@ -1,10 +1,11 @@
define DYNAMIC_LOADER
<os>
-linux
freebsd
-openbsd
+linux
netbsd
+openbsd
+qnx
solaris
windows
</os>
diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp
index cd92860df..800425665 100644
--- a/src/utils/mlock.cpp
+++ b/src/utils/mlock.cpp
@@ -31,7 +31,7 @@ bool has_mlock()
bool lock_mem(void* ptr, size_t bytes)
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- return (::mlock((char*)ptr, bytes) == 0);
+ return (::mlock(static_cast<char*>(ptr), bytes) == 0);
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
return (::VirtualLock(ptr, bytes) != 0);
#else
@@ -45,7 +45,7 @@ bool lock_mem(void* ptr, size_t bytes)
void unlock_mem(void* ptr, size_t bytes)
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
- ::munlock((char*)ptr, bytes);
+ ::munlock(static_cast<char*>(ptr), bytes);
#elif defined(BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK)
::VirtualUnlock(ptr, bytes);
#endif
diff --git a/src/utils/simd_32/simd_32.h b/src/utils/simd_32/simd_32.h
deleted file mode 100644
index e2c483d20..000000000
--- a/src/utils/simd_32/simd_32.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-* Lightweight wrappers for SIMD operations
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_SIMD_32_H__
-#define BOTAN_SIMD_32_H__
-
-#include <botan/types.h>
-#include <botan/rotate.h>
-
-#if defined(BOTAN_TARGET_CPU_HAS_SSE2) && !defined(BOTAN_NO_SSE_INTRINSICS)
-
- #include <botan/internal/simd_sse.h>
- namespace Botan { typedef SIMD_SSE2 SIMD_32; }
-
-#elif defined(BOTAN_TARGET_CPU_HAS_ALTIVEC)
-
- #include <botan/internal/simd_altivec.h>
- namespace Botan { typedef SIMD_Altivec SIMD_32; }
-
-#else
-
- #include <botan/internal/simd_scalar.h>
- namespace Botan { typedef SIMD_Scalar SIMD_32; }
-
-#endif
-
-namespace Botan {
-
-template<>
-inline SIMD_32 rotate_left(SIMD_32 x, size_t rot)
- {
- x.rotate_left(rot);
- return x;
- }
-
-template<>
-inline SIMD_32 rotate_right(SIMD_32 x, size_t rot)
- {
- x.rotate_right(rot);
- return x;
- }
-
-}
-
-#endif
diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp
index 5e2e0ba30..dc6053503 100644
--- a/src/wrap/python/rsa.cpp
+++ b/src/wrap/python/rsa.cpp
@@ -27,6 +27,8 @@ class Py_RSA_PrivateKey
Py_RSA_PrivateKey(std::string pem_str,
Python_RandomNumberGenerator& rng,
std::string pass);
+ Py_RSA_PrivateKey(std::string pem_str,
+ Python_RandomNumberGenerator& rng);
Py_RSA_PrivateKey(u32bit bits, Python_RandomNumberGenerator& rng);
~Py_RSA_PrivateKey() { delete rsa_key; }
@@ -87,6 +89,21 @@ Py_RSA_PrivateKey::Py_RSA_PrivateKey(u32bit bits,
}
Py_RSA_PrivateKey::Py_RSA_PrivateKey(std::string pem_str,
+ Python_RandomNumberGenerator& rng)
+ {
+ DataSource_Memory in(pem_str);
+
+ Private_Key* pkcs8_key =
+ PKCS8::load_key(in,
+ rng.get_underlying_rng());
+
+ rsa_key = dynamic_cast<RSA_PrivateKey*>(pkcs8_key);
+
+ if(!rsa_key)
+ throw std::invalid_argument("Key is not an RSA key");
+ }
+
+Py_RSA_PrivateKey::Py_RSA_PrivateKey(std::string pem_str,
Python_RandomNumberGenerator& rng,
std::string passphrase)
{
@@ -195,6 +212,7 @@ void export_rsa()
python::class_<Py_RSA_PrivateKey>
("RSA_PrivateKey", python::init<std::string, Python_RandomNumberGenerator&, std::string>())
+ .def(python::init<std::string, Python_RandomNumberGenerator&>())
.def(python::init<u32bit, Python_RandomNumberGenerator&>())
.def("to_string", &Py_RSA_PrivateKey::to_string)
.def("to_ber", &Py_RSA_PrivateKey::to_ber)